2012-02-19 18:31:04 +00:00
|
|
|
/*
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* Contributor(s): Joseph Eagar.
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2012-04-06 09:21:19 +00:00
|
|
|
/** \file blender/bmesh/operators/bmo_dissolve.c
|
|
|
|
* \ingroup bmesh
|
|
|
|
*/
|
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_array.h"
|
|
|
|
#include "BLI_math.h"
|
|
|
|
|
|
|
|
#include "bmesh.h"
|
2012-03-08 03:25:53 +00:00
|
|
|
#include "intern/bmesh_private.h"
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2012-03-08 03:25:53 +00:00
|
|
|
#include "intern/bmesh_operators_private.h" /* own include */
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2012-05-06 18:37:08 +00:00
|
|
|
#define FACE_MARK 1
|
|
|
|
#define FACE_ORIG 2
|
|
|
|
#define FACE_NEW 4
|
|
|
|
#define EDGE_MARK 1
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2012-05-06 18:37:08 +00:00
|
|
|
#define VERT_MARK 1
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2013-03-08 04:00:06 +00:00
|
|
|
static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
|
|
|
BMWalker regwalker;
|
|
|
|
BMIter liter2;
|
|
|
|
BMLoop *l2, *l3;
|
|
|
|
BMFace *f2;
|
|
|
|
|
|
|
|
/* checks if there are any unmarked boundary edges in the face regio */
|
|
|
|
|
|
|
|
BMW_init(®walker, bm, BMW_ISLAND,
|
2012-03-29 13:09:07 +00:00
|
|
|
BMW_MASK_NOP, BMW_MASK_NOP, FACE_MARK,
|
2012-04-16 08:04:12 +00:00
|
|
|
BMW_FLAG_NOP,
|
2012-02-19 18:31:04 +00:00
|
|
|
BMW_NIL_LAY);
|
2012-03-29 13:09:07 +00:00
|
|
|
|
2013-01-14 09:53:56 +00:00
|
|
|
for (f2 = BMW_begin(®walker, f); f2; f2 = BMW_step(®walker)) {
|
|
|
|
BM_ITER_ELEM (l2, &liter2, f2, BM_LOOPS_OF_FACE) {
|
2012-03-01 17:13:02 +00:00
|
|
|
l3 = l2->radial_next;
|
2012-05-06 18:37:08 +00:00
|
|
|
if (BMO_elem_flag_test(bm, l3->f, FACE_MARK) !=
|
|
|
|
BMO_elem_flag_test(bm, l2->f, FACE_MARK))
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
|
|
|
if (!BMO_elem_flag_test(bm, l2->e, EDGE_MARK)) {
|
2013-01-14 16:42:43 +00:00
|
|
|
return false;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BMW_end(®walker);
|
|
|
|
|
2013-01-14 16:42:43 +00:00
|
|
|
return true;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
2012-02-28 09:48:00 +00:00
|
|
|
void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
|
|
|
BMOIter oiter;
|
2013-03-12 05:48:30 +00:00
|
|
|
BMFace *f;
|
2012-02-19 18:31:04 +00:00
|
|
|
BLI_array_declare(faces);
|
|
|
|
BLI_array_declare(regions);
|
|
|
|
BMFace ***regions = NULL;
|
|
|
|
BMFace **faces = NULL;
|
2013-03-12 05:36:43 +00:00
|
|
|
BMFace *act_face = bm->act_face;
|
2012-02-19 18:31:04 +00:00
|
|
|
BMWalker regwalker;
|
|
|
|
int i;
|
|
|
|
|
2013-01-14 16:42:43 +00:00
|
|
|
const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
if (use_verts) {
|
|
|
|
/* tag verts that start out with only 2 edges,
|
|
|
|
* don't remove these later */
|
|
|
|
BMIter viter;
|
|
|
|
BMVert *v;
|
|
|
|
|
2012-04-19 13:47:58 +00:00
|
|
|
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
|
2012-02-25 19:43:51 +00:00
|
|
|
BMO_elem_flag_set(bm, v, VERT_MARK, (BM_vert_edge_count(v) != 2));
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-19 14:58:31 +00:00
|
|
|
BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_MARK);
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
/* collect region */
|
2012-11-19 14:58:31 +00:00
|
|
|
BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
|
2013-03-12 05:48:30 +00:00
|
|
|
BMFace *f_iter;
|
2012-03-01 13:13:08 +00:00
|
|
|
if (!BMO_elem_flag_test(bm, f, FACE_MARK)) {
|
|
|
|
continue;
|
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
BLI_array_empty(faces);
|
|
|
|
faces = NULL; /* forces different allocatio */
|
|
|
|
|
|
|
|
BMW_init(®walker, bm, BMW_ISLAND,
|
2012-03-29 13:09:07 +00:00
|
|
|
BMW_MASK_NOP, BMW_MASK_NOP, FACE_MARK,
|
2012-04-16 10:29:59 +00:00
|
|
|
BMW_FLAG_NOP, /* no need to check BMW_FLAG_TEST_HIDDEN, faces are already marked by the bmo */
|
2012-02-19 18:31:04 +00:00
|
|
|
BMW_NIL_LAY);
|
|
|
|
|
2013-03-12 05:48:30 +00:00
|
|
|
for (f_iter = BMW_begin(®walker, f); f_iter; f_iter = BMW_step(®walker)) {
|
|
|
|
BLI_array_append(faces, f_iter);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
BMW_end(®walker);
|
|
|
|
|
|
|
|
for (i = 0; i < BLI_array_count(faces); i++) {
|
2013-03-12 05:48:30 +00:00
|
|
|
f_iter = faces[i];
|
|
|
|
BMO_elem_flag_disable(bm, f_iter, FACE_MARK);
|
|
|
|
BMO_elem_flag_enable(bm, f_iter, FACE_ORIG);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (BMO_error_occurred(bm)) {
|
|
|
|
BMO_error_clear(bm);
|
|
|
|
BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED, NULL);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_array_append(faces, NULL);
|
|
|
|
BLI_array_append(regions, faces);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < BLI_array_count(regions); i++) {
|
2013-03-12 05:36:43 +00:00
|
|
|
BMFace *f_new;
|
2012-02-19 18:31:04 +00:00
|
|
|
int tot = 0;
|
|
|
|
|
|
|
|
faces = regions[i];
|
|
|
|
if (!faces[0]) {
|
|
|
|
BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED,
|
|
|
|
"Could not find boundary of dissolve region");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (faces[tot])
|
|
|
|
tot++;
|
|
|
|
|
2013-03-12 05:36:43 +00:00
|
|
|
f_new = BM_faces_join(bm, faces, tot, true);
|
|
|
|
|
|
|
|
if (f_new) {
|
|
|
|
/* maintain active face */
|
|
|
|
if (act_face && bm->act_face == NULL) {
|
|
|
|
bm->act_face = f_new;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2012-02-19 18:31:04 +00:00
|
|
|
BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED,
|
|
|
|
"Could not create merged face");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if making the new face failed (e.g. overlapping test)
|
|
|
|
* unmark the original faces for deletion */
|
2013-03-12 05:36:43 +00:00
|
|
|
BMO_elem_flag_disable(bm, f_new, FACE_ORIG);
|
|
|
|
BMO_elem_flag_enable(bm, f_new, FACE_NEW);
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-07-21 00:58:02 +00:00
|
|
|
BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", FACE_ORIG, DEL_FACES);
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (use_verts) {
|
|
|
|
BMIter viter;
|
|
|
|
BMVert *v;
|
|
|
|
|
2012-04-19 13:47:58 +00:00
|
|
|
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
|
2012-02-19 18:31:04 +00:00
|
|
|
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
|
|
|
|
if (BM_vert_edge_count(v) == 2) {
|
2013-01-14 16:42:43 +00:00
|
|
|
BM_vert_collapse_edge(bm, v->e, v, true);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-01 20:09:17 +00:00
|
|
|
if (BMO_error_occurred(bm)) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2012-11-20 05:50:19 +00:00
|
|
|
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW);
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
cleanup:
|
2012-03-01 20:09:17 +00:00
|
|
|
/* free/cleanup */
|
2012-02-19 18:31:04 +00:00
|
|
|
for (i = 0; i < BLI_array_count(regions); i++) {
|
|
|
|
if (regions[i]) MEM_freeN(regions[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_array_free(regions);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* almost identical to dissolve edge, except it cleans up vertice */
|
2012-02-28 09:48:00 +00:00
|
|
|
void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
|
|
|
/* BMOperator fop; */
|
2013-03-12 05:36:43 +00:00
|
|
|
BMFace *act_face = bm->act_face;
|
2012-02-19 18:31:04 +00:00
|
|
|
BMOIter oiter;
|
|
|
|
BMIter iter;
|
|
|
|
BMVert *v, **verts = NULL;
|
|
|
|
BLI_array_declare(verts);
|
|
|
|
BMEdge *e;
|
|
|
|
int i;
|
|
|
|
|
2012-03-05 01:53:30 +00:00
|
|
|
|
2012-11-19 14:58:31 +00:00
|
|
|
BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
|
2013-03-12 05:36:43 +00:00
|
|
|
BMFace *fa, *fb;
|
|
|
|
|
2012-03-05 01:53:30 +00:00
|
|
|
if (BM_edge_face_pair(e, &fa, &fb)) {
|
2013-03-12 05:36:43 +00:00
|
|
|
BMFace *f_new;
|
2012-02-19 18:31:04 +00:00
|
|
|
BMO_elem_flag_enable(bm, e->v1, VERT_MARK);
|
|
|
|
BMO_elem_flag_enable(bm, e->v2, VERT_MARK);
|
|
|
|
|
2012-04-04 14:48:10 +00:00
|
|
|
/* BMESH_TODO - check on delaying edge removal since we may end up removing more then
|
2012-07-16 23:23:33 +00:00
|
|
|
* one edge, and later reference a removed edge */
|
2013-03-12 05:36:43 +00:00
|
|
|
f_new = BM_faces_join_pair(bm, fa, fb, e, true);
|
|
|
|
|
|
|
|
if (f_new) {
|
|
|
|
/* maintain active face */
|
|
|
|
if (act_face && bm->act_face == NULL) {
|
|
|
|
bm->act_face = f_new;
|
|
|
|
}
|
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-19 13:47:58 +00:00
|
|
|
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
2012-02-19 18:31:04 +00:00
|
|
|
if (BMO_elem_flag_test(bm, v, VERT_MARK) && BM_vert_edge_count(v) == 2) {
|
|
|
|
BLI_array_append(verts, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clean up extreneous 2-valence vertice */
|
|
|
|
for (i = 0; i < BLI_array_count(verts); i++) {
|
|
|
|
if (verts[i]->e) {
|
2013-01-14 16:42:43 +00:00
|
|
|
BM_vert_collapse_edge(bm, verts[i]->e, verts[i], true);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_array_free(verts);
|
|
|
|
|
2012-02-28 09:48:00 +00:00
|
|
|
//BMO_op_initf(bm, &fop, "dissolve_faces faces=%ff", FACE_MARK);
|
2012-02-19 18:31:04 +00:00
|
|
|
//BMO_op_exec(bm, &fop);
|
|
|
|
|
2012-11-20 05:50:19 +00:00
|
|
|
//BMO_slot_copy(op, &fop, "region.out", "region.out");
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
//BMO_op_finish(bm, &fop);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-28 09:48:00 +00:00
|
|
|
void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
|
|
|
/* might want to make this an option or mode - campbell */
|
|
|
|
|
|
|
|
/* BMOperator fop; */
|
2013-03-12 05:36:43 +00:00
|
|
|
BMFace *act_face = bm->act_face;
|
2012-02-19 18:31:04 +00:00
|
|
|
BMOIter eiter;
|
|
|
|
BMEdge *e;
|
|
|
|
BMIter viter;
|
|
|
|
BMVert *v;
|
|
|
|
|
2013-01-14 16:42:43 +00:00
|
|
|
const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
if (use_verts) {
|
2012-04-19 13:47:58 +00:00
|
|
|
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
|
2012-02-25 19:43:51 +00:00
|
|
|
BMO_elem_flag_set(bm, v, VERT_MARK, (BM_vert_edge_count(v) != 2));
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-19 14:58:31 +00:00
|
|
|
BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
|
2012-03-05 01:53:30 +00:00
|
|
|
BMFace *fa, *fb;
|
|
|
|
|
|
|
|
if (BM_edge_face_pair(e, &fa, &fb)) {
|
2013-03-12 05:36:43 +00:00
|
|
|
BMFace *f_new;
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
/* join faces */
|
2012-04-04 14:48:10 +00:00
|
|
|
|
|
|
|
/* BMESH_TODO - check on delaying edge removal since we may end up removing more then
|
2012-07-16 23:23:33 +00:00
|
|
|
* one edge, and later reference a removed edge */
|
2013-03-12 05:36:43 +00:00
|
|
|
f_new = BM_faces_join_pair(bm, fa, fb, e, true);
|
|
|
|
|
|
|
|
if (f_new) {
|
|
|
|
/* maintain active face */
|
|
|
|
if (act_face && bm->act_face == NULL) {
|
|
|
|
bm->act_face = f_new;
|
|
|
|
}
|
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_verts) {
|
2012-04-19 13:47:58 +00:00
|
|
|
BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
|
2012-02-19 18:31:04 +00:00
|
|
|
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
|
|
|
|
if (BM_vert_edge_count(v) == 2) {
|
2013-01-14 16:42:43 +00:00
|
|
|
BM_vert_collapse_edge(bm, v->e, v, true);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-14 16:42:43 +00:00
|
|
|
static bool test_extra_verts(BMesh *bm, BMVert *v)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2013-03-12 05:48:30 +00:00
|
|
|
BMIter fiter, liter, eiter, fiter_sub;
|
|
|
|
BMFace *f;
|
2012-02-19 18:31:04 +00:00
|
|
|
BMLoop *l;
|
|
|
|
BMEdge *e;
|
|
|
|
|
2012-04-21 14:14:58 +00:00
|
|
|
/* test faces around verts for verts that would be wrongly killed
|
2012-02-19 18:31:04 +00:00
|
|
|
* by dissolve faces. */
|
2013-03-12 05:48:30 +00:00
|
|
|
BM_ITER_ELEM(f, &fiter, v, BM_FACES_OF_VERT) {
|
|
|
|
BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
|
2012-02-19 18:31:04 +00:00
|
|
|
if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) {
|
|
|
|
/* if an edge around a vert is a boundary edge,
|
|
|
|
* then dissolve faces won't destroy it.
|
|
|
|
* also if it forms a boundary with one
|
|
|
|
* of the face region */
|
2013-03-12 05:48:30 +00:00
|
|
|
bool found = false;
|
|
|
|
BM_ITER_ELEM(e, &eiter, l->v, BM_EDGES_OF_VERT) {
|
|
|
|
BMFace *f_iter;
|
2012-04-18 06:44:48 +00:00
|
|
|
if (BM_edge_is_boundary(e)) {
|
2013-01-14 16:42:43 +00:00
|
|
|
found = true;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2013-03-12 05:48:30 +00:00
|
|
|
else {
|
|
|
|
BM_ITER_ELEM(f_iter, &fiter_sub, e, BM_FACES_OF_EDGE) {
|
|
|
|
if (!BMO_elem_flag_test(bm, f_iter, FACE_MARK)) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
2013-01-14 16:42:43 +00:00
|
|
|
if (found == true) {
|
2012-02-19 18:31:04 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-01-14 16:42:43 +00:00
|
|
|
if (found == false) {
|
|
|
|
return false;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-14 16:42:43 +00:00
|
|
|
return true;
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2012-02-28 09:48:00 +00:00
|
|
|
void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
|
|
|
BMIter iter, fiter;
|
|
|
|
BMVert *v;
|
|
|
|
BMFace *f;
|
|
|
|
/* int i; */
|
2012-03-02 12:44:34 +00:00
|
|
|
|
2012-11-19 14:58:31 +00:00
|
|
|
BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_MARK);
|
2012-02-19 18:31:04 +00:00
|
|
|
|
|
|
|
for (v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v = BM_iter_step(&iter)) {
|
|
|
|
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
|
|
|
|
/* check if it's a two-valence ver */
|
|
|
|
if (BM_vert_edge_count(v) == 2) {
|
|
|
|
|
|
|
|
/* collapse the ver */
|
2012-02-26 05:48:12 +00:00
|
|
|
/* previously the faces were joined, but collapsing between 2 edges
|
|
|
|
* gives some advantage/difference in using vertex-dissolve over edge-dissolve */
|
|
|
|
#if 0
|
2013-01-14 16:42:43 +00:00
|
|
|
BM_vert_collapse_faces(bm, v->e, v, 1.0f, true, true);
|
2012-02-26 05:48:12 +00:00
|
|
|
#else
|
2013-01-14 16:42:43 +00:00
|
|
|
BM_vert_collapse_edge(bm, v->e, v, true);
|
2012-02-26 05:48:12 +00:00
|
|
|
#endif
|
|
|
|
|
2012-02-19 18:31:04 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
f = BM_iter_new(&fiter, bm, BM_FACES_OF_VERT, v);
|
|
|
|
for ( ; f; f = BM_iter_step(&fiter)) {
|
|
|
|
BMO_elem_flag_enable(bm, f, FACE_ORIG);
|
|
|
|
BMO_elem_flag_enable(bm, f, FACE_MARK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if our additions to the input to face dissolve
|
|
|
|
* will destroy nonmarked vertices. */
|
|
|
|
if (!test_extra_verts(bm, v)) {
|
|
|
|
f = BM_iter_new(&fiter, bm, BM_FACES_OF_VERT, v);
|
|
|
|
for ( ; f; f = BM_iter_step(&fiter)) {
|
|
|
|
if (BMO_elem_flag_test(bm, f, FACE_ORIG)) {
|
|
|
|
BMO_elem_flag_disable(bm, f, FACE_MARK);
|
|
|
|
BMO_elem_flag_disable(bm, f, FACE_ORIG);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
f = BM_iter_new(&fiter, bm, BM_FACES_OF_VERT, v);
|
|
|
|
for ( ; f; f = BM_iter_step(&fiter)) {
|
|
|
|
BMO_elem_flag_disable(bm, f, FACE_ORIG);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-21 00:58:02 +00:00
|
|
|
BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_MARK);
|
2012-02-19 18:31:04 +00:00
|
|
|
if (BMO_error_occurred(bm)) {
|
|
|
|
const char *msg;
|
|
|
|
|
|
|
|
BMO_error_get(bm, &msg, NULL);
|
|
|
|
BMO_error_clear(bm);
|
|
|
|
BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clean up any remainin */
|
|
|
|
for (v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v = BM_iter_step(&iter)) {
|
|
|
|
if (BMO_elem_flag_test(bm, v, VERT_MARK)) {
|
|
|
|
if (!BM_vert_dissolve(bm, v)) {
|
|
|
|
BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this code is for cleaning up two-edged faces, it shall become
|
|
|
|
* it's own function one day */
|
|
|
|
#if 0
|
|
|
|
void dummy_exec(BMesh *bm, BMOperator *op)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* clean up two-edged face */
|
|
|
|
/* basic idea is to keep joining 2-edged faces until their
|
|
|
|
* gone. this however relies on joining two 2-edged faces
|
|
|
|
* together to work, which doesn't */
|
|
|
|
found3 = 1;
|
|
|
|
while (found3) {
|
|
|
|
found3 = 0;
|
|
|
|
for (f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL); f; f = BM_iter_step(&iter)) {
|
|
|
|
if (!BM_face_validate(bm, f, stderr)) {
|
|
|
|
printf("error.\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f->len == 2) {
|
|
|
|
//this design relies on join faces working
|
|
|
|
//with two-edged faces properly.
|
|
|
|
//commenting this line disables the
|
|
|
|
//outermost loop.
|
|
|
|
//found3 = 1;
|
|
|
|
found2 = 0;
|
|
|
|
l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
|
|
|
|
fe = l->e;
|
|
|
|
for ( ; l; l = BM_iter_step(&liter)) {
|
|
|
|
f2 = BM_iter_new(&fiter, bm,
|
2012-05-06 18:37:08 +00:00
|
|
|
BM_FACES_OF_EDGE, l->e);
|
|
|
|
for (; f2; f2 = BM_iter_step(&fiter)) {
|
2012-02-19 18:31:04 +00:00
|
|
|
if (f2 != f) {
|
|
|
|
BM_faces_join_pair(bm, f, f2, l->e);
|
|
|
|
found2 = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (found2) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found2) {
|
2012-02-27 13:47:53 +00:00
|
|
|
BM_face_kill(bm, f);
|
|
|
|
BM_edge_kill(bm, fe);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
2012-03-24 06:38:07 +00:00
|
|
|
}
|
2012-04-22 11:54:53 +00:00
|
|
|
#if 0
|
|
|
|
else if (f->len == 3) {
|
2012-02-19 18:31:04 +00:00
|
|
|
BMEdge *ed[3];
|
|
|
|
BMVert *vt[3];
|
|
|
|
BMLoop *lp[3];
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
//check for duplicate edges
|
|
|
|
l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
|
|
|
|
for ( ; l; l = BM_iter_step(&liter)) {
|
|
|
|
ed[i] = l->e;
|
|
|
|
lp[i] = l;
|
|
|
|
vt[i++] = l->v;
|
|
|
|
}
|
|
|
|
if (vt[0] == vt[1] || vt[0] == vt[2]) {
|
|
|
|
i += 1;
|
|
|
|
}
|
2012-04-22 11:54:53 +00:00
|
|
|
#endif
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (oldlen == len) break;
|
|
|
|
oldlen = len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2012-04-05 01:20:32 +00:00
|
|
|
/* Limited Dissolve */
|
2012-02-28 09:48:00 +00:00
|
|
|
void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
|
2012-02-19 18:31:04 +00:00
|
|
|
{
|
2012-11-19 14:58:31 +00:00
|
|
|
BMOpSlot *einput = BMO_slot_get(op->slots_in, "edges");
|
|
|
|
BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts");
|
2012-02-19 18:31:04 +00:00
|
|
|
const float angle_max = (float)M_PI / 2.0f;
|
2012-11-19 14:58:31 +00:00
|
|
|
const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit"));
|
2013-01-14 16:42:43 +00:00
|
|
|
const bool do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries");
|
2012-02-19 18:31:04 +00:00
|
|
|
|
2012-10-23 06:13:56 +00:00
|
|
|
BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries,
|
2012-11-20 03:29:12 +00:00
|
|
|
(BMVert **)BMO_SLOT_AS_BUFFER(vinput), vinput->len,
|
|
|
|
(BMEdge **)BMO_SLOT_AS_BUFFER(einput), einput->len);
|
2012-02-19 18:31:04 +00:00
|
|
|
}
|