diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-11-04 06:22:56 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-11-04 06:22:56 +0400 |
commit | dd8e83606776d1d3c51cd8f5c89bf6d1a7e05f74 (patch) | |
tree | 710d8682910d03d019ca0f4a1cb86fcf2b268c2e /source/blender/bmesh | |
parent | 6dfa1601092b9aa4de88420ce1e60371cd6aed69 (diff) | |
parent | 2f2c0a51a5b108213004dcda3da6defda82e6e41 (diff) |
Merged changes in the trunk up to revision 51853.
Conflicts resolved:
source/blender/blenloader/intern/readfile.c
source/blender/bmesh/operators/bmo_utils.c
This commit also includes a fix of a bug identified during the merge and committed in revision 51853.
Thanks Thomas (dingto) for the timely fix!
Diffstat (limited to 'source/blender/bmesh')
19 files changed, 749 insertions, 658 deletions
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index f811dcf956e..d7858ebbc0d 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -30,7 +30,9 @@ set(INC ../blenlib ../makesdna ../../../intern/guardedalloc - ../../../extern/bullet2/src ../../../intern/opennl/extern) + ../../../extern/bullet2/src + ../../../intern/opennl/extern +) set(INC_SYS @@ -52,6 +54,7 @@ set(SRC operators/bmo_mirror.c operators/bmo_primitive.c operators/bmo_removedoubles.c + operators/bmo_similar.c operators/bmo_smooth_laplacian.c operators/bmo_symmetrize.c operators/bmo_subdivide.c diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c index fbdbe2ffe94..feeb2a926f3 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/intern/bmesh_decimate_collapse.c @@ -52,9 +52,9 @@ #define BOUNDARY_PRESERVE_WEIGHT 100.0f typedef enum CD_UseFlag { - CD_DO_VERT, - CD_DO_EDGE, - CD_DO_LOOP + CD_DO_VERT = (1 << 0), + CD_DO_EDGE = (1 << 1), + CD_DO_LOOP = (1 << 2) } CD_UseFlag; diff --git a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c b/source/blender/bmesh/intern/bmesh_decimate_dissolve.c index 91eac527047..d1371a18160 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/intern/bmesh_decimate_dissolve.c @@ -179,10 +179,10 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int /* simple version of the branch below, sincve we will dissolve _all_ verts that use 2 edges */ for (i = 0; i < vinput_len; i++) { BMVert *v = vinput_arr[i]; - if (v) { - if (BM_vert_edge_count(v) == 2) { - BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ - } + if (LIKELY(v != NULL) && + BM_vert_edge_count(v) == 2) + { + BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ } } } @@ -207,10 +207,11 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int for (i = 0; i < tot_found; i++) { BMVert *v = (BMVert *)weight_elems[i].ele; - if (/* topology changes may cause this to be un-collapsable */ - (BM_vert_edge_count(v) == 2) && - /* check twice because cumulative effect could dissolve over angle limit */ - bm_vert_edge_face_angle(v) < angle_limit) + if (LIKELY(v != NULL) && + /* topology changes may cause this to be un-collapsable */ + (BM_vert_edge_count(v) == 2) && + /* check twice because cumulative effect could dissolve over angle limit */ + bm_vert_edge_face_angle(v) < angle_limit) { BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index ffe79923730..508b3b8fcdf 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -224,10 +224,8 @@ static int compute_mdisp_quad(BMLoop *l, float v1[3], float v2[3], float v3[3], /* computer center */ BM_face_calc_center_mean(l->f, cent); - add_v3_v3v3(p, l->prev->v->co, l->v->co); - mul_v3_fl(p, 0.5); - add_v3_v3v3(n, l->next->v->co, l->v->co); - mul_v3_fl(n, 0.5); + mid_v3_v3v3(p, l->prev->v->co, l->v->co); + mid_v3_v3v3(n, l->next->v->co, l->v->co); copy_v3_v3(v1, cent); copy_v3_v3(v2, p); @@ -525,8 +523,7 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f) sides = (int)sqrt(mdp->totdisp); for (y = 0; y < sides; y++) { - add_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]); - mul_v3_fl(co1, 0.5); + mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]); copy_v3_v3(mdn->disps[y * sides], co1); copy_v3_v3(mdl->disps[y], co1); diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index e4a838fe893..9af65d7dd7e 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -584,8 +584,7 @@ void BM_editselection_center(BMEditSelection *ese, float r_center[3]) } else if (ese->htype == BM_EDGE) { BMEdge *eed = (BMEdge *)ese->ele; - add_v3_v3v3(r_center, eed->v1->co, eed->v2->co); - mul_v3_fl(r_center, 0.5); + mid_v3_v3v3(r_center, eed->v1->co, eed->v2->co); } else if (ese->htype == BM_FACE) { BMFace *efa = (BMFace *)ese->ele; diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 32879caec71..d3e3bcd3556 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -85,6 +85,11 @@ BMesh *BM_mesh_create(BMAllocTemplate *allocsize) bm->stackdepth = 1; bm->totflags = 1; + CustomData_reset(&bm->vdata); + CustomData_reset(&bm->edata); + CustomData_reset(&bm->ldata); + CustomData_reset(&bm->pdata); + return bm; } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index b0a9168ffda..62abf43829b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -536,7 +536,9 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess) oldverts = me->mvert; /* don't free this yet */ - CustomData_set_layer(&me->vdata, CD_MVERT, NULL); + if (oldverts) { + CustomData_set_layer(&me->vdata, CD_MVERT, NULL); + } /* free custom data */ CustomData_free(&me->vdata, me->totvert); diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index e12e28f8cff..31698f0abc1 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -822,10 +822,11 @@ static BMOpDefine bmo_spin_def = { */ static BMOpDefine bmo_similar_faces_def = { "similar_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ + {BMO_OP_SLOT_INT, "type"}, /* type of selection */ + {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ {0} /* null-terminating sentinel */}, bmo_similar_faces_exec, 0 @@ -838,10 +839,11 @@ static BMOpDefine bmo_similar_faces_def = { */ static BMOpDefine bmo_similar_edges_def = { "similar_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output edges */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ + {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output edges */ + {BMO_OP_SLOT_INT, "type"}, /* type of selection */ + {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ {0} /* null-terminating sentinel */}, bmo_similar_edges_exec, 0 @@ -854,10 +856,11 @@ static BMOpDefine bmo_similar_edges_def = { */ static BMOpDefine bmo_similar_verts_def = { "similar_verts", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ + {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ + {BMO_OP_SLOT_INT, "type"}, /* type of selection */ + {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ {0} /* null-terminating sentinel */}, bmo_similar_verts_exec, 0 diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 015052e685d..2413f3a7be0 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -1026,7 +1026,7 @@ static void bmo_flag_layer_alloc(BMesh *bm) int i; BMIter iter; - BLI_mempool *oldpool = bm->toolflagpool; /* old flag pool */ + BLI_mempool *oldpool = bm->toolflagpool; /* old flag pool */ BLI_mempool *newpool; void *oldflags; diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 05113576ca4..79b8c450fd9 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -46,11 +46,18 @@ enum { SUBDIV_SELECT_LOOPCUT }; +enum { + SIM_CMP_EQ = 0, + SIM_CMP_GT, + SIM_CMP_LT +}; + /* similar face selection slot values */ enum { SIMFACE_MATERIAL = 201, SIMFACE_IMAGE, SIMFACE_AREA, + SIMFACE_SIDES, SIMFACE_PERIMETER, SIMFACE_NORMAL, SIMFACE_COPLANAR, diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index bd0f93ee7aa..98edceb30a2 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -313,7 +313,7 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nvert float up[3] = {0.0f, 0.0f, 1.0f}, axis[3], q[4]; float mat[3][3]; - double angle; + float angle; int i; cross_v3_v3v3(axis, normal, up); @@ -329,7 +329,7 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nvert axis[2] = 0.0f; } - axis_angle_to_quat(q, axis, (float)angle); + axis_angle_to_quat(q, axis, angle); quat_to_mat3(mat, q); for (i = 0; i < nverts; i++) diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index fbbb9c2a825..4b07dd74eef 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -344,7 +344,7 @@ BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) BMLoop *l_other; // BLI_assert(BM_edge_is_manifold(e)); // TOO strict, just check if we have another radial face - BLI_assert(e->l && e->l->radial_next != l); + BLI_assert(e->l && e->l->radial_next != e->l); BLI_assert(BM_vert_in_edge(e, l->v)); l_other = (l->e == e) ? l : l->prev; diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index bb1e599f097..bb013e6428e 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -598,7 +598,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) } } } - else { /* WIRE EDGE */ + else { /* WIRE EDGE */ BMIter eiter; /* match trunk: mark all connected wire edges */ diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index 30561e47d20..d7b163cb760 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -365,7 +365,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) len2 = len_v3v3(vec, vec2); /* use shortest segment length divided by 3 as merge threshold */ - BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, MIN2(len, len2) / 3.0f); + BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, min_ff(len, len2) / 3.0f); } /* and now do imat */ diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index d3e98dd96c1..cd792f911a9 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -371,7 +371,7 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) BMIter iter; BMEdge *e, **edges = NULL; BLI_array_declare(edges); - float min[3], max[3]; + float min[3], max[3], center[3]; int i, tot; BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); @@ -400,13 +400,12 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) minmax_v3v3_v3(min, max, e->v2->co); } - add_v3_v3v3(min, min, max); - mul_v3_fl(min, 0.5f); + mid_v3_v3v3(center, min, max); /* snap edges to a point. for initial testing purposes anyway */ for (i = 0; i < tot; i++) { - copy_v3_v3(edges[i]->v1->co, min); - copy_v3_v3(edges[i]->v2->co, min); + copy_v3_v3(edges[i]->v1->co, center); + copy_v3_v3(edges[i]->v2->co, center); if (edges[i]->v1 != edges[0]->v1) BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", edges[i]->v1, edges[0]->v1); diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c new file mode 100644 index 00000000000..b4566f6c8a9 --- /dev/null +++ b/source/blender/bmesh/operators/bmo_similar.c @@ -0,0 +1,620 @@ +/* + * ***** 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, Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/operators/bmo_similar.c + * \ingroup bmesh + * + * bmesh operators to select based on + * comparisons with the existing selection. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_object_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_math.h" + +#include "BKE_customdata.h" +#include "BKE_deform.h" + +#include "bmesh.h" + +#include "intern/bmesh_operators_private.h" /* own include */ + +/* in fact these could all be the same */ + +/* + * extra face data (computed data) + */ +typedef struct SimSel_FaceExt { + BMFace *f; /* the face */ + float c[3]; /* center */ + union { + float area; /* area */ + float perim; /* perimeter */ + float d; /* 4th component of plane (the first three being the normal) */ + struct Image *t; /* image pointer */ + }; +} SimSel_FaceExt; + +static int bm_sel_similar_cmp_fl(const float delta, const float thresh, const int compare) +{ + switch (compare) { + case SIM_CMP_EQ: + return (fabsf(delta) <= thresh); + case SIM_CMP_GT: + return ((delta + thresh) >= 0.0f); + case SIM_CMP_LT: + return ((delta - thresh) <= 0.0f); + default: + BLI_assert(0); + return 0; + } +} + +static int bm_sel_similar_cmp_i(const int delta, const int compare) +{ + switch (compare) { + case SIM_CMP_EQ: + return (delta == 0); + case SIM_CMP_GT: + return (delta > 0); + case SIM_CMP_LT: + return (delta < 0); + default: + BLI_assert(0); + return 0; + } +} + +/* + * Select similar faces, the choices are in the enum in source/blender/bmesh/bmesh_operators.h + * We select either similar faces based on material, image, area, perimeter, normal, or the coplanar faces + */ +void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) +{ +#define FACE_MARK 1 + + BMIter fm_iter; + BMFace *fs, *fm; + BMOIter fs_iter; + int num_sels = 0, num_total = 0, i = 0, idx = 0; + float angle = 0.0f; + SimSel_FaceExt *f_ext = NULL; + int *indices = NULL; + float t_no[3]; /* temporary normal */ + const int type = BMO_slot_int_get(op, "type"); + const float thresh = BMO_slot_float_get(op, "thresh"); + const float thresh_radians = thresh * (float)M_PI; + const int compare = BMO_slot_int_get(op, "compare"); + + /* initial_elem - other_elem */ + float delta_fl; + int delta_i; + + num_total = BM_mesh_elem_count(bm, BM_FACE); + + /* + * The first thing to do is to iterate through all the the selected items and mark them since + * they will be in the selection anyway. + * This will increase performance, (especially when the number of originally selected faces is high) + * so the overall complexity will be less than $O(mn)$ where is the total number of selected faces, + * and n is the total number of faces + */ + BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + if (!BMO_elem_flag_test(bm, fs, FACE_MARK)) { /* is this really needed ? */ + BMO_elem_flag_enable(bm, fs, FACE_MARK); + num_sels++; + } + } + + /* allocate memory for the selected faces indices and for all temporary faces */ + indices = (int *)MEM_callocN(sizeof(int) * num_sels, "face indices util.c"); + f_ext = (SimSel_FaceExt *)MEM_callocN(sizeof(SimSel_FaceExt) * num_total, "f_ext util.c"); + + /* loop through all the faces and fill the faces/indices structure */ + BM_ITER_MESH (fm, &fm_iter, bm, BM_FACES_OF_MESH) { + f_ext[i].f = fm; + if (BMO_elem_flag_test(bm, fm, FACE_MARK)) { + indices[idx] = i; + idx++; + } + i++; + } + + /* + * Save us some computation burden: In case of perimeter/area/coplanar selection we compute + * only once. + */ + if (type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR || type == SIMFACE_IMAGE) { + for (i = 0; i < num_total; i++) { + switch (type) { + case SIMFACE_PERIMETER: + /* set the perimeter */ + f_ext[i].perim = BM_face_calc_perimeter(f_ext[i].f); + break; + + case SIMFACE_COPLANAR: + /* compute the center of the polygon */ + BM_face_calc_center_mean(f_ext[i].f, f_ext[i].c); + + /* normalize the polygon normal */ + copy_v3_v3(t_no, f_ext[i].f->no); + normalize_v3(t_no); + + /* compute the plane distance */ + f_ext[i].d = dot_v3v3(t_no, f_ext[i].c); + break; + + case SIMFACE_AREA: + f_ext[i].area = BM_face_calc_area(f_ext[i].f); + break; + + case SIMFACE_IMAGE: + f_ext[i].t = NULL; + if (CustomData_has_layer(&(bm->pdata), CD_MTEXPOLY)) { + MTexPoly *mtpoly = CustomData_bmesh_get(&bm->pdata, f_ext[i].f->head.data, CD_MTEXPOLY); + f_ext[i].t = mtpoly->tpage; + } + break; + } + } + } + + /* now select the rest (if any) */ + for (i = 0; i < num_total; i++) { + fm = f_ext[i].f; + if (!BMO_elem_flag_test(bm, fm, FACE_MARK) && !BM_elem_flag_test(fm, BM_ELEM_HIDDEN)) { + int cont = TRUE; + for (idx = 0; idx < num_sels && cont == TRUE; idx++) { + fs = f_ext[indices[idx]].f; + switch (type) { + case SIMFACE_MATERIAL: + if (fm->mat_nr == fs->mat_nr) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_IMAGE: + if (f_ext[i].t == f_ext[indices[idx]].t) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_NORMAL: + angle = angle_normalized_v3v3(fs->no, fm->no); /* if the angle between the normals -> 0 */ + if (angle <= thresh_radians) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_COPLANAR: + angle = angle_normalized_v3v3(fs->no, fm->no); /* angle -> 0 */ + if (angle <= thresh_radians) { /* and dot product difference -> 0 */ + delta_fl = f_ext[i].d - f_ext[indices[idx]].d; + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + } + break; + + case SIMFACE_AREA: + delta_fl = f_ext[i].area - f_ext[indices[idx]].area; + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_SIDES: + delta_i = fm->len - fs->len; + if (bm_sel_similar_cmp_i(delta_i, compare)) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_PERIMETER: + delta_fl = f_ext[i].perim - f_ext[indices[idx]].perim; + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + default: + BLI_assert(0); + } + } + } + } + + MEM_freeN(f_ext); + MEM_freeN(indices); + + /* transfer all marked faces to the output slot */ + BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_MARK); +#undef FACE_MARK +} + +/**************************************************************************** * + * Similar Edges + **************************************************************************** */ + +/* + * extra edge information + */ +typedef struct SimSel_EdgeExt { + BMEdge *e; + union { + float dir[3]; + float angle; /* angle between the face */ + }; + + union { + float length; /* edge length */ + int faces; /* faces count */ + }; +} SimSel_EdgeExt; + +/* + * select similar edges: the choices are in the enum in source/blender/bmesh/bmesh_operators.h + * choices are length, direction, face, ... + */ +void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) +{ +#define EDGE_MARK 1 + + BMOIter es_iter; /* selected edges iterator */ + BMIter e_iter; /* mesh edges iterator */ + BMEdge *es; /* selected edge */ + BMEdge *e; /* mesh edge */ + int idx = 0, i = 0 /* , f = 0 */; + int *indices = NULL; + SimSel_EdgeExt *e_ext = NULL; + // float *angles = NULL; + float angle; + + int num_sels = 0, num_total = 0; + const int type = BMO_slot_int_get(op, "type"); + const float thresh = BMO_slot_float_get(op, "thresh"); + const int compare = BMO_slot_int_get(op, "compare"); + + /* initial_elem - other_elem */ + float delta_fl; + int delta_i; + + /* sanity checks that the data we need is available */ + switch (type) { + case SIMEDGE_CREASE: + if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { + return; + } + break; + case SIMEDGE_BEVEL: + if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + return; + } + break; + } + + num_total = BM_mesh_elem_count(bm, BM_EDGE); + + /* iterate through all selected edges and mark them */ + BMO_ITER (es, &es_iter, bm, op, "edges", BM_EDGE) { + BMO_elem_flag_enable(bm, es, EDGE_MARK); + num_sels++; + } + + /* allocate memory for the selected edges indices and for all temporary edges */ + indices = (int *)MEM_callocN(sizeof(int) * num_sels, __func__); + e_ext = (SimSel_EdgeExt *)MEM_callocN(sizeof(SimSel_EdgeExt) * num_total, __func__); + + /* loop through all the edges and fill the edges/indices structure */ + BM_ITER_MESH (e, &e_iter, bm, BM_EDGES_OF_MESH) { + e_ext[i].e = e; + if (BMO_elem_flag_test(bm, e, EDGE_MARK)) { + indices[idx] = i; + idx++; + } + i++; + } + + /* save us some computation time by doing heavy computation once */ + if (type == SIMEDGE_LENGTH || type == SIMEDGE_FACE || type == SIMEDGE_DIR || type == SIMEDGE_FACE_ANGLE) { + for (i = 0; i < num_total; i++) { + switch (type) { + case SIMEDGE_LENGTH: /* compute the length of the edge */ + e_ext[i].length = len_v3v3(e_ext[i].e->v1->co, e_ext[i].e->v2->co); + break; + + case SIMEDGE_DIR: /* compute the direction */ + sub_v3_v3v3(e_ext[i].dir, e_ext[i].e->v1->co, e_ext[i].e->v2->co); + normalize_v3(e_ext[i].dir); + break; + + case SIMEDGE_FACE: /* count the faces around the edge */ + e_ext[i].faces = BM_edge_face_count(e_ext[i].e); + break; + + case SIMEDGE_FACE_ANGLE: + e_ext[i].faces = BM_edge_face_count(e_ext[i].e); + if (e_ext[i].faces == 2) + e_ext[i].angle = BM_edge_calc_face_angle(e_ext[i].e); + break; + } + } + } + + /* select the edges if any */ + for (i = 0; i < num_total; i++) { + e = e_ext[i].e; + if (!BMO_elem_flag_test(bm, e, EDGE_MARK) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + int cont = TRUE; + for (idx = 0; idx < num_sels && cont == TRUE; idx++) { + es = e_ext[indices[idx]].e; + switch (type) { + case SIMEDGE_LENGTH: + delta_fl = e_ext[i].length - e_ext[indices[idx]].length; + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + + case SIMEDGE_DIR: + /* compute the angle between the two edges */ + angle = angle_normalized_v3v3(e_ext[i].dir, e_ext[indices[idx]].dir); + + if (angle > (float)(M_PI / 2.0)) /* use the smallest angle between the edges */ + angle = fabsf(angle - (float)M_PI); + + if (angle / (float)(M_PI / 2.0) <= thresh) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + + case SIMEDGE_FACE: + delta_i = e_ext[i].faces - e_ext[indices[idx]].faces; + if (bm_sel_similar_cmp_i(delta_i, compare)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + + case SIMEDGE_FACE_ANGLE: + if (e_ext[i].faces == 2) { + if (e_ext[indices[idx]].faces == 2) { + if (fabsf(e_ext[i].angle - e_ext[indices[idx]].angle) <= thresh) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + } + } + else { + cont = FALSE; + } + break; + + case SIMEDGE_CREASE: + { + float *c1, *c2; + + c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE); + c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_CREASE); + delta_fl = *c1 - *c2; + + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + } + break; + + case SIMEDGE_BEVEL: + { + float *c1, *c2; + + c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT); + c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_BWEIGHT); + delta_fl = *c1 - *c2; + + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + } + break; + + case SIMEDGE_SEAM: + if (BM_elem_flag_test(e, BM_ELEM_SEAM) == BM_elem_flag_test(es, BM_ELEM_SEAM)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + + case SIMEDGE_SHARP: + if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == BM_elem_flag_test(es, BM_ELEM_SMOOTH)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + case SIMEDGE_FREESTYLE: + if (BM_elem_flag_test(e, BM_ELEM_FREESTYLE) == BM_elem_flag_test(es, BM_ELEM_FREESTYLE)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = 0; + } + break; + default: + BLI_assert(0); + } + } + } + } + + MEM_freeN(e_ext); + MEM_freeN(indices); + + /* transfer all marked edges to the output slot */ + BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_MARK); + +#undef EDGE_MARK +} + +/**************************************************************************** * + * Similar Vertices + **************************************************************************** */ + +typedef struct SimSel_VertExt { + BMVert *v; + union { + int num_faces; /* adjacent faces */ + int num_edges; /* adjacent edges */ + MDeformVert *dvert; /* deform vertex */ + }; +} SimSel_VertExt; + +/* + * select similar vertices: the choices are in the enum in source/blender/bmesh/bmesh_operators.h + * choices are normal, face, vertex group... + */ +void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) +{ +#define VERT_MARK 1 + + BMOIter vs_iter; /* selected verts iterator */ + BMIter v_iter; /* mesh verts iterator */ + BMVert *vs; /* selected vertex */ + BMVert *v; /* mesh vertex */ + SimSel_VertExt *v_ext = NULL; + int *indices = NULL; + int num_total = 0, num_sels = 0, i = 0, idx = 0; + const int type = BMO_slot_int_get(op, "type"); + const float thresh = BMO_slot_float_get(op, "thresh"); + const float thresh_radians = thresh * (float)M_PI; + const int compare = BMO_slot_int_get(op, "compare"); + + /* initial_elem - other_elem */ +// float delta_fl; + int delta_i; + + num_total = BM_mesh_elem_count(bm, BM_VERT); + + /* iterate through all selected edges and mark them */ + BMO_ITER (vs, &vs_iter, bm, op, "verts", BM_VERT) { + BMO_elem_flag_enable(bm, vs, VERT_MARK); + num_sels++; + } + + /* allocate memory for the selected vertices indices and for all temporary vertices */ + indices = (int *)MEM_mallocN(sizeof(int) * num_sels, "vertex indices"); + v_ext = (SimSel_VertExt *)MEM_mallocN(sizeof(SimSel_VertExt) * num_total, "vertex extra"); + + /* loop through all the vertices and fill the vertices/indices structure */ + BM_ITER_MESH (v, &v_iter, bm, BM_VERTS_OF_MESH) { + v_ext[i].v = v; + if (BMO_elem_flag_test(bm, v, VERT_MARK)) { + indices[idx] = i; + idx++; + } + + switch (type) { + case SIMVERT_FACE: + /* calling BM_vert_face_count every time is time consumming, so call it only once per vertex */ + v_ext[i].num_faces = BM_vert_face_count(v); + break; + + case SIMVERT_VGROUP: + if (CustomData_has_layer(&(bm->vdata), CD_MDEFORMVERT)) { + v_ext[i].dvert = CustomData_bmesh_get(&bm->vdata, v_ext[i].v->head.data, CD_MDEFORMVERT); + } + else { + v_ext[i].dvert = NULL; + } + break; + case SIMVERT_EDGE: + v_ext[i].num_edges = BM_vert_edge_count(v); + break; + } + + i++; + } + + /* select the vertices if any */ + for (i = 0; i < num_total; i++) { + v = v_ext[i].v; + if (!BMO_elem_flag_test(bm, v, VERT_MARK) && !BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + int cont = TRUE; + for (idx = 0; idx < num_sels && cont == TRUE; idx++) { + vs = v_ext[indices[idx]].v; + switch (type) { + case SIMVERT_NORMAL: + /* compare the angle between the normals */ + if (angle_normalized_v3v3(v->no, vs->no) <= thresh_radians) { + BMO_elem_flag_enable(bm, v, VERT_MARK); + cont = FALSE; + } + break; + case SIMVERT_FACE: + /* number of adjacent faces */ + delta_i = v_ext[i].num_faces - v_ext[indices[idx]].num_faces; + if (bm_sel_similar_cmp_i(delta_i, compare)) { + BMO_elem_flag_enable(bm, v, VERT_MARK); + cont = FALSE; + } + break; + + case SIMVERT_VGROUP: + if (v_ext[i].dvert != NULL && v_ext[indices[idx]].dvert != NULL) { + if (defvert_find_shared(v_ext[i].dvert, v_ext[indices[idx]].dvert) != -1) { + BMO_elem_flag_enable(bm, v, VERT_MARK); + cont = FALSE; + } + } + break; + case SIMVERT_EDGE: + /* number of adjacent edges */ + delta_i = v_ext[i].num_edges - v_ext[indices[idx]].num_edges; + if (bm_sel_similar_cmp_i(delta_i, compare)) { + BMO_elem_flag_enable(bm, v, VERT_MARK); + cont = FALSE; + } + break; + default: + BLI_assert(0); + } + } + } + } + + MEM_freeN(indices); + MEM_freeN(v_ext); + + BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + +#undef VERT_MARK +} diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 9a2a9c022e6..51b9adb5de3 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -45,19 +45,19 @@ #define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f #define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f -#define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8 -#define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE 0.15 +#define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8f +#define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE 0.15f struct BLaplacianSystem { - float *eweights; /* Length weights per Edge */ + float *eweights; /* Length weights per Edge */ float (*fweights)[3]; /* Cotangent weights per face */ - float *ring_areas; /* Total area per ring*/ - float *vlengths; /* Total sum of lengths(edges) per vertice*/ - float *vweights; /* Total sum of weights per vertice*/ - int numEdges; /* Number of edges*/ - int numFaces; /* Number of faces*/ - int numVerts; /* Number of verts*/ - short *zerola; /* Is zero area or length*/ + float *ring_areas; /* Total area per ring*/ + float *vlengths; /* Total sum of lengths(edges) per vertice*/ + float *vweights; /* Total sum of weights per vertice*/ + int numEdges; /* Number of edges*/ + int numFaces; /* Number of faces*/ + int numVerts; /* Number of verts*/ + short *zerola; /* Is zero area or length*/ /* Pointers to data*/ BMesh *bm; @@ -72,13 +72,13 @@ typedef struct BLaplacianSystem LaplacianSystem; static float compute_volume(BMesh *bm); static float cotan_weight(float *v1, float *v2, float *v3); static int vert_is_boundary(BMVert *v); -static LaplacianSystem * init_laplacian_system( int a_numEdges, int a_numFaces, int a_numVerts); -static void init_laplacian_matrix(LaplacianSystem * sys); -static void delete_laplacian_system(LaplacianSystem * sys); +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts); +static void init_laplacian_matrix(LaplacianSystem *sys); +static void delete_laplacian_system(LaplacianSystem *sys); static void delete_void_pointer(void *data); -static void fill_laplacian_matrix(LaplacianSystem * sys); +static void fill_laplacian_matrix(LaplacianSystem *sys); static void memset_laplacian_system(LaplacianSystem *sys, int val); -static void validate_solution(LaplacianSystem * sys, int usex, int usey, int usez, int volumepreservation); +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation); static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float vend, int usex, int usey, int usez); static void delete_void_pointer(void *data) @@ -89,7 +89,7 @@ static void delete_void_pointer(void *data) } } -static void delete_laplacian_system(LaplacianSystem * sys) +static void delete_laplacian_system(LaplacianSystem *sys) { delete_void_pointer(sys->eweights); delete_void_pointer(sys->fweights); @@ -107,17 +107,17 @@ static void delete_laplacian_system(LaplacianSystem * sys) static void memset_laplacian_system(LaplacianSystem *sys, int val) { - memset(sys->eweights , val, sizeof(float) * sys->numEdges); - memset(sys->fweights , val, sizeof(float) * sys->numFaces * 3); - memset(sys->ring_areas , val, sizeof(float) * sys->numVerts); - memset(sys->vlengths , val, sizeof(float) * sys->numVerts); - memset(sys->vweights , val, sizeof(float) * sys->numVerts); - memset(sys->zerola , val, sizeof(short) * sys->numVerts); + memset(sys->eweights, val, sizeof(float) * sys->numEdges); + memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3); + memset(sys->ring_areas, val, sizeof(float) * sys->numVerts); + memset(sys->vlengths, val, sizeof(float) * sys->numVerts); + memset(sys->vweights, val, sizeof(float) * sys->numVerts); + memset(sys->zerola, val, sizeof(short) * sys->numVerts); } -static LaplacianSystem * init_laplacian_system( int a_numEdges, int a_numFaces, int a_numVerts) +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts) { - LaplacianSystem * sys; + LaplacianSystem *sys; sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem"); sys->numEdges = a_numEdges; sys->numFaces = a_numFaces; @@ -128,19 +128,19 @@ static LaplacianSystem * init_laplacian_system( int a_numEdges, int a_numFaces, delete_laplacian_system(sys); return NULL; } - + sys->fweights = MEM_callocN(sizeof(float) * 3 * sys->numFaces, "ModLaplSmoothFWeight"); if (!sys->fweights) { delete_laplacian_system(sys); return NULL; } - + sys->ring_areas = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothRingAreas"); if (!sys->ring_areas) { delete_laplacian_system(sys); return NULL; } - + sys->vlengths = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVlengths"); if (!sys->vlengths) { delete_laplacian_system(sys); @@ -163,7 +163,7 @@ static LaplacianSystem * init_laplacian_system( int a_numEdges, int a_numFaces, } /* Compute weigth between vertice v_i and all your neighbors - * weight between v_i and v_neighbor + * weight between v_i and v_neighbor * Wij = cot(alpha) + cot(beta) / (4.0 * total area of all faces * sum all weight) * v_i * * / | \ @@ -172,15 +172,15 @@ static LaplacianSystem * init_laplacian_system( int a_numEdges, int a_numFaces, * \ | / * \ | / * * v_neighbor -*/ + */ -static void init_laplacian_matrix(LaplacianSystem * sys) +static void init_laplacian_matrix(LaplacianSystem *sys) { float areaf; float *v1, *v2, *v3, *v4; float w1, w2, w3, w4; int i, j; - int has_4_vert ; + int has_4_vert; unsigned int idv1, idv2, idv3, idv4, idv[4]; BMEdge *e; BMFace *f; @@ -196,7 +196,7 @@ static void init_laplacian_matrix(LaplacianSystem * sys) v2 = e->v2->co; idv1 = BM_elem_index_get(e->v1); idv2 = BM_elem_index_get(e->v2); - + w1 = len_v3v3(v1, v2); if (w1 > sys->min_area) { w1 = 1.0f / w1; @@ -204,7 +204,8 @@ static void init_laplacian_matrix(LaplacianSystem * sys) sys->eweights[i] = w1; sys->vlengths[idv1] += w1; sys->vlengths[idv2] += w1; - }else{ + } + else { sys->zerola[idv1] = 1; sys->zerola[idv2] = 1; } @@ -235,7 +236,7 @@ static void init_laplacian_matrix(LaplacianSystem * sys) areaf = area_tri_v3(v1, v2, v3); } - if (fabs(areaf) < sys->min_area) { + if (fabsf(areaf) < sys->min_area) { sys->zerola[idv1] = 1; sys->zerola[idv2] = 1; sys->zerola[idv3] = 1; @@ -248,7 +249,7 @@ static void init_laplacian_matrix(LaplacianSystem * sys) if (has_4_vert) sys->ring_areas[idv4] += areaf; if (has_4_vert) { - + idv[0] = idv1; idv[1] = idv2; idv[2] = idv3; @@ -268,7 +269,7 @@ static void init_laplacian_matrix(LaplacianSystem * sys) w2 = cotan_weight(v4, v1, v2) + cotan_weight(v3, v1, v2); w3 = cotan_weight(v2, v3, v1) + cotan_weight(v4, v1, v3); w4 = cotan_weight(v2, v4, v1) + cotan_weight(v3, v4, v1); - + sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f; } } @@ -282,7 +283,7 @@ static void init_laplacian_matrix(LaplacianSystem * sys) sys->fweights[i][0] += w1; sys->fweights[i][1] += w2; sys->fweights[i][2] += w3; - + sys->vweights[idv1] += w2 + w3; sys->vweights[idv2] += w1 + w3; sys->vweights[idv3] += w1 + w2; @@ -291,12 +292,12 @@ static void init_laplacian_matrix(LaplacianSystem * sys) } } -static void fill_laplacian_matrix(LaplacianSystem * sys) +static void fill_laplacian_matrix(LaplacianSystem *sys) { float *v1, *v2, *v3, *v4; float w2, w3, w4; int i, j; - int has_4_vert ; + int has_4_vert; unsigned int idv1, idv2, idv3, idv4, idv[4]; BMEdge *e; @@ -336,8 +337,8 @@ static void fill_laplacian_matrix(LaplacianSystem * sys) w2 = w2 / 4.0f; w3 = w3 / 4.0f; w4 = w4 / 4.0f; - - if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == 0) { + + if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == 0) { nlMatrixAdd(idv1, idv2, w2 * sys->vweights[idv1]); nlMatrixAdd(idv1, idv3, w3 * sys->vweights[idv1]); nlMatrixAdd(idv1, idv4, w4 * sys->vweights[idv1]); @@ -350,15 +351,15 @@ static void fill_laplacian_matrix(LaplacianSystem * sys) idv3 = BM_elem_index_get(vf[2]); /* Is ring if number of faces == number of edges around vertice*/ i = BM_elem_index_get(f); - if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) { + if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) { nlMatrixAdd(idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]); nlMatrixAdd(idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]); } - if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == 0) { + if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == 0) { nlMatrixAdd(idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]); nlMatrixAdd(idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]); } - if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == 0) { + if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == 0) { nlMatrixAdd(idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]); nlMatrixAdd(idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]); } @@ -392,7 +393,7 @@ static float cotan_weight(float *v1, float *v2, float *v3) if (clen == 0.0f) return 0.0f; - + return dot_v3v3(a, b) / clen; } @@ -402,7 +403,7 @@ static int vert_is_boundary(BMVert *v) BMFace *f; BMIter ei; BMIter fi; - BM_ITER_ELEM(ed, &ei, v, BM_EDGES_OF_VERT) { + BM_ITER_ELEM (ed, &ei, v, BM_EDGES_OF_VERT) { if (BM_edge_is_boundary(ed)) { return 1; } @@ -425,7 +426,7 @@ static float compute_volume(BMesh *bm) BMIter vi; BMVert *vn; BMVert *vf[4]; - + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) { vf[i] = vn; @@ -442,13 +443,13 @@ static float compute_volume(BMesh *bm) y3 = vf[2]->co[1]; z3 = vf[2]->co[2]; - vol += (1.0 / 6.0) * (0.0 - x3*y2*z1 + x2*y3*z1 + x3*y1*z2 - x1*y3*z2 - x2*y1*z3 + x1*y2*z3); + vol += (1.0f / 6.0f) * (0.0f - x3 * y2 * z1 + x2 * y3 * z1 + x3 * y1 * z2 - x1 * y3 * z2 - x2 * y1 * z3 + x1 * y2 * z3); if (i == 4) { x4 = vf[3]->co[0]; y4 = vf[3]->co[1]; z4 = vf[3]->co[2]; - vol += (1.0 / 6.0) * (x1*y3*z4 - x1*y4*z3 - x3*y1*z4 + x3*z1*y4 + y1*x4*z3 - x4*y3*z1); + vol += (1.0f / 6.0f) * (x1 * y3 * z4 - x1 * y4 * z3 - x3 * y1 * z4 + x3 * z1 * y4 + y1 * x4 * z3 - x4 * y3 * z1); } } return fabs(vol); @@ -460,8 +461,8 @@ static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float ven BMOIter siter; BMVert *v; - if (vend != 0.0f) { - beta = pow (vini / vend, 1.0f / 3.0f); + if (vend != 0.0f) { + beta = pow(vini / vend, 1.0f / 3.0f); BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { if (usex) { v->co[0] *= beta; @@ -472,12 +473,12 @@ static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float ven if (usez) { v->co[2] *= beta; } - + } } } -static void validate_solution(LaplacianSystem * sys, int usex, int usey, int usez, int volumepreservation) +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation) { int m_vertex_id; float leni, lene; @@ -502,7 +503,7 @@ static void validate_solution(LaplacianSystem * sys, int usex, int usey, int use ve2[2] = nlGetVariable(2, idv2); leni = len_v3v3(vi1, vi2); lene = len_v3v3(ve1, ve2); - if ( lene > leni* SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE || lene < leni*SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE) { + if (lene > leni * SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE || lene < leni * SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE) { sys->zerola[idv1] = 1; sys->zerola[idv2] = 1; } @@ -541,7 +542,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) float w; BMOIter siter; BMVert *v; - LaplacianSystem * sys; + LaplacianSystem *sys; sys = init_laplacian_system(bm->totedge, bm->totface, bm->totvert); if (!sys) return; @@ -568,16 +569,16 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) nlSolverParameteri(NL_NB_ROWS, bm->totvert); nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); - nlBegin(NL_SYSTEM); - for (i=0; i < bm->totvert; i++) { + nlBegin(NL_SYSTEM); + for (i = 0; i < bm->totvert; i++) { nlLockVariable(i); } BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); nlUnlockVariable(m_vertex_id); - nlSetVariable(0,m_vertex_id, v->co[0]); - nlSetVariable(1,m_vertex_id, v->co[1]); - nlSetVariable(2,m_vertex_id, v->co[2]); + nlSetVariable(0, m_vertex_id, v->co[0]); + nlSetVariable(1, m_vertex_id, v->co[1]); + nlSetVariable(2, m_vertex_id, v->co[2]); } nlBegin(NL_MATRIX); @@ -594,7 +595,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) w = sys->vlengths[i]; sys->vlengths[i] = (w == 0.0f) ? 0.0f : -lambda_border * 2.0f / w; - if (!vert_is_boundary(v)) { + if (!vert_is_boundary(v)) { nlMatrixAdd(i, i, 1.0f + lambda / (4.0f * sys->ring_areas[i])); } else { @@ -603,16 +604,16 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) } else { nlMatrixAdd(i, i, 1.0f); - } + } } fill_laplacian_matrix(sys); - + nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE) ) { validate_solution(sys, usex, usey, usez, volumepreservation); } - + delete_laplacian_system(sys); } diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index c6726ec6f3e..346daf830d0 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -54,7 +54,7 @@ #define ELE_SPLIT 16 /* see bug [#32665], 0.00005 means a we get face splits at a little under 1.0 degrees */ -#define FLT_FACE_SPLIT_EPSILON 0.00005 +#define FLT_FACE_SPLIT_EPSILON 0.00005f /* * NOTE: beauty has been renamed to flag! diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index b396da3b8d1..e311b383b86 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -479,554 +479,6 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) BLI_array_free(cos); } -/* - * compute the fake surface of an ngon - * This is done by decomposing the ngon into triangles who share the centroid of the ngon - * while this method is far from being exact, it should guarantee an invariance. - * - * NOTE: This should probably go to bmesh_polygon.c - */ -static float ngon_fake_area(BMFace *f) -{ - BMIter liter; - BMLoop *l; - int num_verts = 0; - float v[3], sv[3], c[3]; - float area = 0.0f; - - BM_face_calc_center_mean(f, c); - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - if (num_verts == 0) { - copy_v3_v3(v, l->v->co); - copy_v3_v3(sv, l->v->co); - num_verts++; - } - else { - area += area_tri_v3(v, c, l->v->co); - copy_v3_v3(v, l->v->co); - num_verts++; - } - } - - area += area_tri_v3(v, c, sv); - - return area; -} - -/* - * extra face data (computed data) - */ -typedef struct SimSel_FaceExt { - BMFace *f; /* the face */ - float c[3]; /* center */ - union { - float area; /* area */ - float perim; /* perimeter */ - float d; /* 4th component of plane (the first three being the normal) */ - struct Image *t; /* image pointer */ - }; -} SimSel_FaceExt; - -/* - * Select similar faces, the choices are in the enum in source/blender/bmesh/bmesh_operators.h - * We select either similar faces based on material, image, area, perimeter, normal, or the coplanar faces - */ -void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) -{ - BMIter fm_iter; - BMFace *fs, *fm; - BMOIter fs_iter; - int num_sels = 0, num_total = 0, i = 0, idx = 0; - float angle = 0.0f; - SimSel_FaceExt *f_ext = NULL; - int *indices = NULL; - float t_no[3]; /* temporary normal */ - int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); - const float thresh_radians = thresh * (float)M_PI; - - num_total = BM_mesh_elem_count(bm, BM_FACE); - - /* - * The first thing to do is to iterate through all the the selected items and mark them since - * they will be in the selection anyway. - * This will increase performance, (especially when the number of originally selected faces is high) - * so the overall complexity will be less than $O(mn)$ where is the total number of selected faces, - * and n is the total number of faces - */ - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { - if (!BMO_elem_flag_test(bm, fs, FACE_MARK)) { /* is this really needed ? */ - BMO_elem_flag_enable(bm, fs, FACE_MARK); - num_sels++; - } - } - - /* allocate memory for the selected faces indices and for all temporary faces */ - indices = (int *)MEM_callocN(sizeof(int) * num_sels, "face indices util.c"); - f_ext = (SimSel_FaceExt *)MEM_callocN(sizeof(SimSel_FaceExt) * num_total, "f_ext util.c"); - - /* loop through all the faces and fill the faces/indices structure */ - BM_ITER_MESH (fm, &fm_iter, bm, BM_FACES_OF_MESH) { - f_ext[i].f = fm; - if (BMO_elem_flag_test(bm, fm, FACE_MARK)) { - indices[idx] = i; - idx++; - } - i++; - } - - /* - * Save us some computation burden: In case of perimeter/area/coplanar selection we compute - * only once. - */ - if (type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR || type == SIMFACE_IMAGE) { - for (i = 0; i < num_total; i++) { - switch (type) { - case SIMFACE_PERIMETER: - /* set the perimeter */ - f_ext[i].perim = BM_face_calc_perimeter(f_ext[i].f); - break; - - case SIMFACE_COPLANAR: - /* compute the center of the polygon */ - BM_face_calc_center_mean(f_ext[i].f, f_ext[i].c); - - /* normalize the polygon normal */ - copy_v3_v3(t_no, f_ext[i].f->no); - normalize_v3(t_no); - - /* compute the plane distance */ - f_ext[i].d = dot_v3v3(t_no, f_ext[i].c); - break; - - case SIMFACE_AREA: - f_ext[i].area = ngon_fake_area(f_ext[i].f); - break; - - case SIMFACE_IMAGE: - f_ext[i].t = NULL; - if (CustomData_has_layer(&(bm->pdata), CD_MTEXPOLY)) { - MTexPoly *mtpoly = CustomData_bmesh_get(&bm->pdata, f_ext[i].f->head.data, CD_MTEXPOLY); - f_ext[i].t = mtpoly->tpage; - } - break; - } - } - } - - /* now select the rest (if any) */ - for (i = 0; i < num_total; i++) { - fm = f_ext[i].f; - if (!BMO_elem_flag_test(bm, fm, FACE_MARK) && !BM_elem_flag_test(fm, BM_ELEM_HIDDEN)) { - int cont = TRUE; - for (idx = 0; idx < num_sels && cont == TRUE; idx++) { - fs = f_ext[indices[idx]].f; - switch (type) { - case SIMFACE_MATERIAL: - if (fm->mat_nr == fs->mat_nr) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - - case SIMFACE_IMAGE: - if (f_ext[i].t == f_ext[indices[idx]].t) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - - case SIMFACE_NORMAL: - angle = angle_normalized_v3v3(fs->no, fm->no); /* if the angle between the normals -> 0 */ - if (angle <= thresh_radians) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - - case SIMFACE_COPLANAR: - angle = angle_normalized_v3v3(fs->no, fm->no); /* angle -> 0 */ - if (angle <= thresh_radians) { /* and dot product difference -> 0 */ - if (fabsf(f_ext[i].d - f_ext[indices[idx]].d) <= thresh) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - } - break; - - case SIMFACE_AREA: - if (fabsf(f_ext[i].area - f_ext[indices[idx]].area) <= thresh) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - - case SIMFACE_PERIMETER: - if (fabsf(f_ext[i].perim - f_ext[indices[idx]].perim) <= thresh) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - - case SIMFACE_FREESTYLE: - if (BM_elem_flag_test(fm, BM_ELEM_FREESTYLE) == BM_elem_flag_test(fs, BM_ELEM_FREESTYLE)) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = 0; - } - break; - } - } - } - } - - MEM_freeN(f_ext); - MEM_freeN(indices); - - /* transfer all marked faces to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_MARK); -} - -/**************************************************************************** * - * Similar Edges - **************************************************************************** */ -#define EDGE_MARK 1 - -/* - * extra edge information - */ -typedef struct SimSel_EdgeExt { - BMEdge *e; - union { - float dir[3]; - float angle; /* angle between the face */ - }; - - union { - float length; /* edge length */ - int faces; /* faces count */ - }; -} SimSel_EdgeExt; - -/* - * select similar edges: the choices are in the enum in source/blender/bmesh/bmesh_operators.h - * choices are length, direction, face, ... - */ -void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) -{ - BMOIter es_iter; /* selected edges iterator */ - BMIter e_iter; /* mesh edges iterator */ - BMEdge *es; /* selected edge */ - BMEdge *e; /* mesh edge */ - int idx = 0, i = 0 /* , f = 0 */; - int *indices = NULL; - SimSel_EdgeExt *e_ext = NULL; - // float *angles = NULL; - float angle; - - int num_sels = 0, num_total = 0; - int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); - - /* sanity checks that the data we need is available */ - switch (type) { - case SIMEDGE_CREASE: - if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { - return; - } - break; - case SIMEDGE_BEVEL: - if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { - return; - } - break; - } - - num_total = BM_mesh_elem_count(bm, BM_EDGE); - - /* iterate through all selected edges and mark them */ - BMO_ITER (es, &es_iter, bm, op, "edges", BM_EDGE) { - BMO_elem_flag_enable(bm, es, EDGE_MARK); - num_sels++; - } - - /* allocate memory for the selected edges indices and for all temporary edges */ - indices = (int *)MEM_callocN(sizeof(int) * num_sels, __func__); - e_ext = (SimSel_EdgeExt *)MEM_callocN(sizeof(SimSel_EdgeExt) * num_total, __func__); - - /* loop through all the edges and fill the edges/indices structure */ - BM_ITER_MESH (e, &e_iter, bm, BM_EDGES_OF_MESH) { - e_ext[i].e = e; - if (BMO_elem_flag_test(bm, e, EDGE_MARK)) { - indices[idx] = i; - idx++; - } - i++; - } - - /* save us some computation time by doing heavy computation once */ - if (type == SIMEDGE_LENGTH || type == SIMEDGE_FACE || type == SIMEDGE_DIR || type == SIMEDGE_FACE_ANGLE) { - for (i = 0; i < num_total; i++) { - switch (type) { - case SIMEDGE_LENGTH: /* compute the length of the edge */ - e_ext[i].length = len_v3v3(e_ext[i].e->v1->co, e_ext[i].e->v2->co); - break; - - case SIMEDGE_DIR: /* compute the direction */ - sub_v3_v3v3(e_ext[i].dir, e_ext[i].e->v1->co, e_ext[i].e->v2->co); - normalize_v3(e_ext[i].dir); - break; - - case SIMEDGE_FACE: /* count the faces around the edge */ - e_ext[i].faces = BM_edge_face_count(e_ext[i].e); - break; - - case SIMEDGE_FACE_ANGLE: - e_ext[i].faces = BM_edge_face_count(e_ext[i].e); - if (e_ext[i].faces == 2) - e_ext[i].angle = BM_edge_calc_face_angle(e_ext[i].e); - break; - } - } - } - - /* select the edges if any */ - for (i = 0; i < num_total; i++) { - e = e_ext[i].e; - if (!BMO_elem_flag_test(bm, e, EDGE_MARK) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - int cont = TRUE; - for (idx = 0; idx < num_sels && cont == TRUE; idx++) { - es = e_ext[indices[idx]].e; - switch (type) { - case SIMEDGE_LENGTH: - if (fabsf(e_ext[i].length - e_ext[indices[idx]].length) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - - case SIMEDGE_DIR: - /* compute the angle between the two edges */ - angle = angle_normalized_v3v3(e_ext[i].dir, e_ext[indices[idx]].dir); - - if (angle > (float)(M_PI / 2.0)) /* use the smallest angle between the edges */ - angle = fabsf(angle - (float)M_PI); - - if (angle / (float)(M_PI / 2.0) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - - case SIMEDGE_FACE: - if (e_ext[i].faces == e_ext[indices[idx]].faces) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - - case SIMEDGE_FACE_ANGLE: - if (e_ext[i].faces == 2) { - if (e_ext[indices[idx]].faces == 2) { - if (fabsf(e_ext[i].angle - e_ext[indices[idx]].angle) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - } - } - else { - cont = FALSE; - } - break; - - case SIMEDGE_CREASE: - { - float *c1, *c2; - - c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE); - c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_CREASE); - - if (fabsf(*c1 - *c2) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - } - break; - - case SIMEDGE_BEVEL: - { - float *c1, *c2; - - c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT); - c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_BWEIGHT); - - if (fabsf(*c1 - *c2) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - } - break; - - case SIMEDGE_SEAM: - if (BM_elem_flag_test(e, BM_ELEM_SEAM) == BM_elem_flag_test(es, BM_ELEM_SEAM)) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - - case SIMEDGE_SHARP: - if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == BM_elem_flag_test(es, BM_ELEM_SMOOTH)) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - - case SIMEDGE_FREESTYLE: - if (BM_elem_flag_test(e, BM_ELEM_FREESTYLE) == BM_elem_flag_test(es, BM_ELEM_FREESTYLE)) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = 0; - } - break; - } - } - } - } - - MEM_freeN(e_ext); - MEM_freeN(indices); - - /* transfer all marked edges to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_MARK); -} - -/**************************************************************************** * - * Similar Vertices - **************************************************************************** */ -#define VERT_MARK 1 - -typedef struct SimSel_VertExt { - BMVert *v; - union { - int num_faces; /* adjacent faces */ - int num_edges; /* adjacent edges */ - MDeformVert *dvert; /* deform vertex */ - }; -} SimSel_VertExt; - -/* - * select similar vertices: the choices are in the enum in source/blender/bmesh/bmesh_operators.h - * choices are normal, face, vertex group... - */ -void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) -{ - BMOIter vs_iter; /* selected verts iterator */ - BMIter v_iter; /* mesh verts iterator */ - BMVert *vs; /* selected vertex */ - BMVert *v; /* mesh vertex */ - SimSel_VertExt *v_ext = NULL; - int *indices = NULL; - int num_total = 0, num_sels = 0, i = 0, idx = 0; - int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); - const float thresh_radians = thresh * (float)M_PI; - - num_total = BM_mesh_elem_count(bm, BM_VERT); - - /* iterate through all selected edges and mark them */ - BMO_ITER (vs, &vs_iter, bm, op, "verts", BM_VERT) { - BMO_elem_flag_enable(bm, vs, VERT_MARK); - num_sels++; - } - - /* allocate memory for the selected vertices indices and for all temporary vertices */ - indices = (int *)MEM_mallocN(sizeof(int) * num_sels, "vertex indices"); - v_ext = (SimSel_VertExt *)MEM_mallocN(sizeof(SimSel_VertExt) * num_total, "vertex extra"); - - /* loop through all the vertices and fill the vertices/indices structure */ - BM_ITER_MESH (v, &v_iter, bm, BM_VERTS_OF_MESH) { - v_ext[i].v = v; - if (BMO_elem_flag_test(bm, v, VERT_MARK)) { - indices[idx] = i; - idx++; - } - - switch (type) { - case SIMVERT_FACE: - /* calling BM_vert_face_count every time is time consumming, so call it only once per vertex */ - v_ext[i].num_faces = BM_vert_face_count(v); - break; - - case SIMVERT_VGROUP: - if (CustomData_has_layer(&(bm->vdata), CD_MDEFORMVERT)) { - v_ext[i].dvert = CustomData_bmesh_get(&bm->vdata, v_ext[i].v->head.data, CD_MDEFORMVERT); - } - else { - v_ext[i].dvert = NULL; - } - break; - case SIMVERT_EDGE: - v_ext[i].num_edges = BM_vert_edge_count(v); - break; - } - - i++; - } - - /* select the vertices if any */ - for (i = 0; i < num_total; i++) { - v = v_ext[i].v; - if (!BMO_elem_flag_test(bm, v, VERT_MARK) && !BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - int cont = TRUE; - for (idx = 0; idx < num_sels && cont == TRUE; idx++) { - vs = v_ext[indices[idx]].v; - switch (type) { - case SIMVERT_NORMAL: - /* compare the angle between the normals */ - if (angle_normalized_v3v3(v->no, vs->no) <= thresh_radians) { - BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; - } - break; - case SIMVERT_FACE: - /* number of adjacent faces */ - if (v_ext[i].num_faces == v_ext[indices[idx]].num_faces) { - BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; - } - break; - - case SIMVERT_VGROUP: - if (v_ext[i].dvert != NULL && v_ext[indices[idx]].dvert != NULL) { - int v1, v2; - for (v1 = 0; v1 < v_ext[i].dvert->totweight && cont == 1; v1++) { - for (v2 = 0; v2 < v_ext[indices[idx]].dvert->totweight; v2++) { - if (v_ext[i].dvert->dw[v1].def_nr == v_ext[indices[idx]].dvert->dw[v2].def_nr) { - BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; - break; - } - } - } - } - break; - case SIMVERT_EDGE: - /* number of adjacent edges */ - if (v_ext[i].num_edges == v_ext[indices[idx]].num_edges) { - BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; - } - break; - } - } - } - } - - MEM_freeN(indices); - MEM_freeN(v_ext); - - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); -} - /**************************************************************************** * * Cycle UVs for a face **************************************************************************** */ @@ -1245,6 +697,8 @@ typedef struct ElemNode { HeapNode *hn; /* heap node */ } ElemNode; +#define VERT_MARK 1 + void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) { BMOIter vs_iter /* , vs2_iter */; /* selected verts iterator */ @@ -1256,7 +710,7 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) ElemNode *vert_list = NULL; int num_total = 0 /*, num_sels = 0 */, i = 0; - int type = BMO_slot_int_get(op, "type"); + const int type = BMO_slot_int_get(op, "type"); BMO_ITER (vs, &vs_iter, bm, op, "startv", BM_VERT) { sv = vs; |