diff options
Diffstat (limited to 'source/blender/bmesh/tools')
-rw-r--r-- | source/blender/bmesh/tools/BME_bevel.c | 42 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.c | 644 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate.h | 8 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate_collapse.c | 84 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate_dissolve.c | 12 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c | 40 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_edgesplit.c | 14 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_edgesplit.h | 2 |
8 files changed, 534 insertions, 312 deletions
diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c index 5e1d58150fa..47b507603f4 100644 --- a/source/blender/bmesh/tools/BME_bevel.c +++ b/source/blender/bmesh/tools/BME_bevel.c @@ -90,7 +90,7 @@ static BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BM float factor, float weight, float maxfactor, float *max) { BME_TransData *vtd; - int is_new = 0; + int is_new = false; if (v == NULL) { return NULL; @@ -100,7 +100,7 @@ static BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BM vtd = BLI_memarena_alloc(td->ma, sizeof(*vtd)); BLI_ghash_insert(td->gh, v, vtd); td->len++; - is_new = 1; + is_new = true; } vtd->bm = bm; @@ -151,12 +151,12 @@ static void BME_Bevel_Dissolve_Disk(BMesh *bm, BMVert *v) { BMFace *f; BMEdge *e; - int done; + bool done; if (v->e) { - done = FALSE; + done = false; while (!done) { - done = TRUE; + done = true; e = v->e; /*loop the edge looking for a edge to dissolve*/ do { f = NULL; @@ -164,14 +164,14 @@ static void BME_Bevel_Dissolve_Disk(BMesh *bm, BMVert *v) f = bmesh_jfke(bm, e->l->f, e->l->radial_next->f, e); } if (f) { - done = FALSE; + done = false; break; } e = bmesh_disk_edge_next(e, v); } while (e != v->e); } - BM_vert_collapse_edge(bm, v->e, v, TRUE); - // bmesh_jekv(bm, v->e, v, FALSE); + BM_vert_collapse_edge(bm, v->e, v, true); + // bmesh_jekv(bm, v->e, v, false); } } @@ -539,18 +539,18 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti se = l->next->e; jf = NULL; if (kl->v == kv) { - BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, TRUE); + BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, true); ke = kl->e; /* BMESH-TODO: jfke doesn't handle customdata */ jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e); - BM_vert_collapse_edge(bm, ke, kv, FALSE); + BM_vert_collapse_edge(bm, ke, kv, false); } else { - BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, TRUE); + BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, true); ke = kl->e; /* BMESH-TODO: jfke doesn't handle customdata */ jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e); - BM_vert_collapse_edge(bm, ke, kv, FALSE); + BM_vert_collapse_edge(bm, ke, kv, false); } /* find saved loop pointer */ l = se->l; @@ -585,18 +585,18 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti se = l->e; jf = NULL; if (kl->v == kv) { - BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, TRUE); + BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, true); ke = kl->e; /* BMESH-TODO: jfke doesn't handle customdata */ jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e); - BM_vert_collapse_edge(bm, ke, kv, FALSE); + BM_vert_collapse_edge(bm, ke, kv, false); } else { - BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, TRUE); + BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, true); ke = kl->e; /* BMESH-TODO: jfke doesn't handle customdata */ jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e); - BM_vert_collapse_edge(bm, ke, kv, FALSE); + BM_vert_collapse_edge(bm, ke, kv, false); } /* find saved loop pointer */ l = se->l; @@ -607,7 +607,7 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti } if (!BMO_elem_flag_test(bm, v1, BME_BEVEL_NONMAN) || !BMO_elem_flag_test(bm, v2, BME_BEVEL_NONMAN)) { - BM_face_split(bm, f, v2, v1, &l, e, TRUE); + BM_face_split(bm, f, v2, v1, &l, e, true); BMO_elem_flag_enable(bm, l->e, BME_BEVEL_BEVEL); l = l->radial_next; } @@ -636,7 +636,7 @@ static BMLoop *BME_bevel_vert(BMesh *bm, BMLoop *l, float value, int UNUSED(opti l = l->next->next; /* "cut off" this corner */ - /* f = */ BM_face_split(bm, l->f, v2, v1, NULL, l->e, TRUE); + /* f = */ BM_face_split(bm, l->f, v2, v1, NULL, l->e, true); return l; } @@ -1069,7 +1069,7 @@ static BMesh *BME_bevel_mesh(BMesh *bm, float value, int UNUSED(res), int option /* get rid of beveled edge */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e, BME_BEVEL_BEVEL) && BMO_elem_flag_test(bm, e, BME_BEVEL_ORIG)) { - BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE); + BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, true); } } @@ -1083,9 +1083,9 @@ static BMesh *BME_bevel_mesh(BMesh *bm, float value, int UNUSED(res), int option if (l->v != v) l = l->next; if (l2->v != v) l2 = l2->next; if (l->f->len > 3) - BM_face_split(bm, l->f, l->next->v, l->prev->v, &l, l->e, TRUE); /* clip this corner off */ + BM_face_split(bm, l->f, l->next->v, l->prev->v, &l, l->e, true); /* clip this corner off */ if (l2->f->len > 3) - BM_face_split(bm, l2->f, l2->next->v, l2->prev->v, &l, l2->e, TRUE); /* clip this corner off */ + BM_face_split(bm, l2->f, l2->next->v, l2->prev->v, &l, l2->e, true); /* clip this corner off */ curedge = bmesh_disk_edge_next(curedge, v); } while (curedge != v->e); BME_Bevel_Dissolve_Disk(bm, v); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index a593e40d850..5461e5fe788 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -41,10 +41,8 @@ -/* experemental - Campbell */ -// #define USE_ALTERNATE_ADJ - -#define BEVEL_EPSILON 1e-6 +#define BEVEL_EPSILON_D 1e-6 +#define BEVEL_EPSILON 1e-6f /* for testing */ // #pragma GCC diagnostic error "-Wpadded" @@ -94,7 +92,7 @@ typedef struct VMesh { M_NONE, /* no polygon mesh needed */ M_POLY, /* a simple polygon */ M_ADJ, /* "adjacent edges" mesh pattern */ -// M_CROSS, /* "cross edges" mesh pattern */ + M_ADJ_SUBDIV, /* like M_ADJ, but using subdivision */ M_TRI_FAN, /* a simple polygon - fan filled */ M_QUAD_STRIP, /* a simple polygon - cut into paralelle strips */ } mesh_kind; @@ -124,7 +122,7 @@ typedef struct BevelParams { // #pragma GCC diagnostic ignored "-Wpadded" -//#include "bevdebug.c" +// #include "bevdebug.c" /* Make a new BoundVert of the given kind, insert it at the end of the circular linked * list with entry point bv->boundstart, and return it. */ @@ -323,7 +321,7 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); - if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) { /* special case: e1 and e2 are parallel; put offset point perp to both, from v. * need to find a suitable plane. * if offsets are different, we're out of luck: just use e1->offset */ @@ -409,7 +407,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, madd_v3_v3fl(off2a, norm_perp2, e2->offset); add_v3_v3v3(off2b, off2a, dir2); - if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) { /* lines are parallel; off1a is a good meet point */ copy_v3_v3(meetco, off1a); } @@ -421,7 +419,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, } else if (iret == 2) { /* lines are not coplanar; meetco and isect2 are nearest to first and second lines */ - if (len_v3v3(meetco, isect2) > 100.0f * (float)BEVEL_EPSILON) { + if (len_v3v3(meetco, isect2) > 100.0f * BEVEL_EPSILON) { /* offset lines don't meet: project average onto emid; this is not ideal (see TODO above) */ mid_v3_v3v3(co, meetco, isect2); closest_to_line_v3(meetco, co, v->co, BM_edge_other_vert(emid->e, v)->co); @@ -470,7 +468,7 @@ static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co); len = normalize_v3(dir); if (d > len) - d = len - (float)(50.0 * BEVEL_EPSILON); + d = len - (float)(50.0 * BEVEL_EPSILON_D); copy_v3_v3(slideco, v->co); madd_v3_v3fl(slideco, dir, -d); } @@ -501,79 +499,6 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) return lb->next == la ? 1 : -1; } -#ifdef USE_ALTERNATE_ADJ - -static void vmesh_cent(VMesh *vm, float r_cent[3]) -{ - BoundVert *v; - zero_v3(r_cent); - - v = vm->boundstart; - do { - add_v3_v3(r_cent, v->nv.co); - } while ((v = v->next) != vm->boundstart); - mul_v3_fl(r_cent, 1.0f / (float)vm->count); -} - -/** - * - * This example shows a tri fan of quads, - * but could be an NGon fan of quads too. - * <pre> - * The whole triangle X - * represents the / \ - * new bevel face. / \ - * / \ - * Split into / \ - * a quad fan. / \ - * / \ - * / \ - * / \ - * co_prev +-. .-+ - * / `-._ _.-' \ - * / co_cent`-+-' \ - * / | \ - * Quad of / | \ - * interest -- / ---> X | \ - * / | \ - * / | \ - * / co_next| \ - * co_orig +-----------------+-----------------+ - * - * For each quad, calcualte UV's based on the following: - * U = k / (vm->seg * 2) - * V = ring / (vm->seg * 2) - * quad = (co_orig, co_prev, co_cent, co_next) - * ... note that co_cent is the same for all quads in the fan. - * </pre> - * - */ - -static void get_point_uv(float uv[2], - /* all these args are int's originally - * but pass as floats to the function */ - const float seg, const float ring, const float k) -{ - uv[0] = (ring / seg) * 2.0f; - uv[1] = (k / seg) * 2.0f; -} - -/* TODO: make this a lot smarter!, - * this is the main reason USE_ALTERNATE_ADJ isn't so good right now :S */ -static float get_point_uv_factor(const float uv[2]) -{ - return sinf(1.0f - max_ff(uv[0], uv[1]) / 2.0f); -} - -static void get_point_on_round_edge(const float uv[2], - float quad[4][3], - float r_co[3]) -{ - interp_bilinear_quad_v3(quad, uv[0], uv[1], r_co); -} - -#else /* USE_ALTERNATE_ADJ */ - /* Fill matrix r_mat so that a point in the sheared parallelogram with corners * va, vmid, vb (and the 4th that is implied by it being a parallelogram) * is transformed to the unit square by multiplication with r_mat. @@ -601,7 +526,7 @@ static int make_unit_square_map(const float va[3], const float vmid[3], const fl sub_v3_v3v3(va_vmid, vmid, va); sub_v3_v3v3(vb_vmid, vmid, vb); - if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) > 100.f *(float)BEVEL_EPSILON) { + if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) > 100.0f * BEVEL_EPSILON) { sub_v3_v3v3(vo, va, vb_vmid); cross_v3_v3v3(vddir, vb_vmid, va_vmid); normalize_v3(vddir); @@ -694,8 +619,6 @@ static void snap_to_edge_profile(EdgeHalf *e, const float va[3], const float vb[ } } -#endif /* !USE_ALTERNATE_ADJ */ - /* Make a circular list of BoundVerts for bv, each of which has the coordinates * of a vertex on the the boundary of the beveled vertex bv->v. * Also decide on the mesh pattern that will be used inside the boundary. @@ -811,7 +734,10 @@ static void build_boundary(BevelParams *bp, BevVert *bv) } while ((e = e->next) != efirst); BLI_assert(vm->count >= 2); - if (vm->count == 2 && bv->edgecount == 3) { + if (bp->vertex_only) { + vm->mesh_kind = bp->seg > 1 ? M_ADJ_SUBDIV : M_POLY; + } + else if (vm->count == 2 && bv->edgecount == 3) { vm->mesh_kind = M_NONE; } else if (bv->selcount == 2) { @@ -846,19 +772,6 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) float co[3], coa[3], cob[3], midco[3]; float va_pipe[3], vb_pipe[3]; -#ifdef USE_ALTERNATE_ADJ - /* ordered as follows (orig, prev, center, next)*/ - float quad_plane[4][3]; - float quad_orig[4][3]; -#endif - - -#ifdef USE_ALTERNATE_ADJ - /* the rest are initialized inline, this remains the same for all */ - vmesh_cent(vm, quad_plane[2]); - copy_v3_v3(quad_orig[2], bv->v->co); -#endif - n = vm->count; ns = vm->seg; ns2 = ns / 2; @@ -875,7 +788,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) float dir1[3], dir2[3]; sub_v3_v3v3(dir1, bv->v->co, BM_edge_other_vert(e1->e, bv->v)->co); sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, bv->v)->co, bv->v->co); - if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) { epipe = e1; break; } @@ -918,37 +831,6 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) copy_v3_v3(nv->co, cob); nv->v = nvnext->v; -#ifdef USE_ALTERNATE_ADJ - /* plane */ - copy_v3_v3(quad_plane[0], v->nv.co); - mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co); - /* quad[2] is set */ - mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co); - - /* orig */ - copy_v3_v3(quad_orig[0], v->nv.co); /* only shared location between 2 quads */ - project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig[1]); - project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig[3]); - - //bl_debug_draw_quad_add(UNPACK4(quad_plane)); - //bl_debug_draw_quad_add(UNPACK4(quad_orig)); -#endif - -#ifdef USE_ALTERNATE_ADJ - for (k = 1; k < ns; k++) { - float uv[2]; - float fac; - float co_plane[3]; - float co_orig[3]; - - get_point_uv(uv, v->ebev->seg, ring, k); - get_point_on_round_edge(uv, quad_plane, co_plane); - get_point_on_round_edge(uv, quad_orig, co_orig); - fac = get_point_uv_factor(uv); - interp_v3_v3v3(co, co_plane, co_orig, fac); - copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co); - } -#else /* TODO: better calculation of new midarc point? */ project_to_edge(v->ebev->e, coa, cob, midco); @@ -962,7 +844,6 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) copy_v3_v3(va_pipe, mesh_vert(vm, i, 0, 0)->co); copy_v3_v3(vb_pipe, mesh_vert(vm, i, 0, ns)->co); } -#endif } } while ((v = v->next) != vm->boundstart); } @@ -990,9 +871,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) if (epipe) snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); -#ifndef USE_ALTERNATE_ADJ copy_v3_v3(nv->co, co); -#endif BLI_assert(nv->v == NULL && nvprev->v == NULL); create_mesh_bmvert(bm, vm, i, ring, k, bv->v); copy_mesh_vert(vm, vprev->index, k, ns - ring, i, ring, k); @@ -1041,9 +920,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) mid_v3_v3v3v3(co, nvprev->co, nv->co, nvnext->co); if (epipe) snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); -#ifndef USE_ALTERNATE_ADJ copy_v3_v3(nv->co, co); -#endif create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); @@ -1053,9 +930,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) mid_v3_v3v3(co, nvprev->co, nv->co); if (epipe) snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); -#ifndef USE_ALTERNATE_ADJ copy_v3_v3(nv->co, co); -#endif create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); @@ -1065,9 +940,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) mid_v3_v3v3(co, nv->co, nvnext->co); if (epipe) snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); -#ifndef USE_ALTERNATE_ADJ copy_v3_v3(nv->co, co); -#endif create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); @@ -1220,6 +1093,413 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) } } +static VMesh *new_adj_subdiv_vmesh(MemArena *mem_arena, int count, int seg, BoundVert *bounds) +{ + VMesh *vm; + + vm = (VMesh *)BLI_memarena_alloc(mem_arena, sizeof(VMesh)); + vm->count = count; + vm->seg = seg; + vm->boundstart = bounds; + vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena, count * (1 + seg / 2) * (1 + seg) * sizeof(NewVert)); + vm->mesh_kind = M_ADJ_SUBDIV; + return vm; +} + +/* VMesh verts for vertex i have data for (i, 0 <= j <= ns2, 0 <= k <= ns), where ns2 = floor(nseg / 2). + * But these overlap data from previous and next i: there are some forced equivalences. + * Let's call these indices the canonical ones: we will just calculate data for these + * 0 <= j <= ns2, 0 <= k < ns2 (for odd ns2) + * 0 <= j < ns2, 0 <= k <= ns2 (for even ns2) + * also (j=ns2, k=ns2) at i=0 (for even ns2) + * This function returns the canonical one for any i, j, k in [0,n],[0,ns],[0,ns] */ +static NewVert *mesh_vert_canon(VMesh *vm, int i, int j, int k) +{ + int n, ns, ns2, odd; + NewVert *ans; + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + odd = ns % 2; + BLI_assert(0 <= i && i <= n && 0 <= j && j <= ns && 0 <= k && k <= ns); + + if (!odd && j == ns2 && k == ns2) + ans = mesh_vert(vm, 0, j, k); + else if (j <= ns2 - 1 + odd && k <= ns2) + ans = mesh_vert(vm, i, j, k); + else if (k <= ns2) + ans = mesh_vert(vm, (i + n - 1) % n, k, ns - j); + else + ans = mesh_vert(vm, (i + 1) % n, ns - k, j); + return ans; +} + +static int is_canon(VMesh *vm, int i, int j, int k) +{ + int ns2 = vm->seg / 2; + if (vm->seg % 2 == 1) + return (j <= ns2 && k <= ns2); + else + return ((j < ns2 && k <= ns2) || (j == ns2 && k == ns2 && i == 0)); +} + +/* Copy the vertex data to all of vm verts from canonical ones */ +static void vmesh_copy_equiv_verts(VMesh *vm) +{ + int n, ns, ns2, i, j, k; + NewVert *v0, *v1; + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + for (i = 0; i < n; i++) { + for (j = 0; j <= ns2; j++) { + for (k = 0; k <= ns; k++) { + if (is_canon(vm, i, j, k)) + continue; + v1 = mesh_vert(vm, i, j, k); + v0 = mesh_vert_canon(vm, i, j, k); + copy_v3_v3(v1->co, v0->co); + v1->v = v0->v; + } + } + } +} + +/* Calculate and return in r_cent the centroid of the center poly */ +static void vmesh_center(VMesh *vm, float r_cent[3]) +{ + int n, ns2, i; + + n = vm->count; + ns2 = vm->seg / 2; + if (vm->seg % 2) { + zero_v3(r_cent); + for (i = 0; i < n; i++) { + add_v3_v3(r_cent, mesh_vert(vm, i, ns2, ns2)->co); + } + mul_v3_fl(r_cent, 1.0f / (float) n); + } + else { + copy_v3_v3(r_cent, mesh_vert(vm, 0, ns2, ns2)->co); + } +} + +/* Do one step of quadratic subdivision (Doo-Sabin), with special rules at boundaries. + * For now, this is written assuming vm0->nseg is odd. + * See Hwang-Chuang 2003 paper: "N-sided hole filling and vertex blending using subdivision surfaces" */ +static VMesh *quadratic_subdiv(MemArena *mem_arena, VMesh *vm0) +{ + int n, ns0, ns20, ns1 /*, ns21 */; + int i, j, k, j1, k1; + VMesh *vm1; + float co[3], co1[3], co2[3], co3[3], co4[3]; + float co11[3], co21[3], co31[3], co41[3]; + float denom; + const float wcorner[4] = {0.25f, 0.25f, 0.25f, 0.25f}; + const float wboundary[4] = {0.375f, 0.375f, 0.125f, 0.125f}; /* {3, 3, 1, 1}/8 */ + const float winterior[4] = {0.5625f, 0.1875f, 0.1875f, 0.0625f}; /* {9, 3, 3, 1}/16 */ + + n = vm0->count; + ns0 = vm0->seg; + ns20 = ns0 / 2; + BLI_assert(ns0 % 2 == 1); + + ns1 = 2 * ns0 - 1; + // ns21 = ns1 / 2; /* UNUSED */ + vm1 = new_adj_subdiv_vmesh(mem_arena, n, ns1, vm0->boundstart); + + for (i = 0; i < n; i ++) { + /* For handle vm0 polys with lower left corner at (i,j,k) for + * j in [0, ns20], k in [0, ns20]; then the center ngon. + * but only fill in data for canonical verts of v1. */ + for (j = 0; j <= ns20; j++) { + for (k = 0; k <= ns20; k++) { + if (j == ns20 && k == ns20) + continue; /* center ngon is special */ + copy_v3_v3(co1, mesh_vert_canon(vm0, i, j, k)->co); + copy_v3_v3(co2, mesh_vert_canon(vm0, i, j, k + 1)->co); + copy_v3_v3(co3, mesh_vert_canon(vm0, i, j + 1, k + 1)->co); + copy_v3_v3(co4, mesh_vert_canon(vm0, i, j + 1, k)->co); + if (j == 0 && k == 0) { + /* corner */ + copy_v3_v3(co11, co1); + interp_v3_v3v3(co21, co1, co2, 0.5f); + interp_v3_v3v3v3v3(co31, co1, co2, co3, co4, wcorner); + interp_v3_v3v3(co41, co1, co4, 0.5f); + } + else if (j == 0) { + /* ring 0 boundary */ + interp_v3_v3v3(co11, co1, co2, 0.25f); + interp_v3_v3v3(co21, co1, co2, 0.75f); + interp_v3_v3v3v3v3(co31, co2, co3, co1, co4, wboundary); + interp_v3_v3v3v3v3(co41, co1, co4, co2, co3, wboundary); + } + else if (k == 0) { + /* ring-starts boundary */ + interp_v3_v3v3(co11, co1, co4, 0.25f); + interp_v3_v3v3v3v3(co21, co1, co2, co3, co4, wboundary); + interp_v3_v3v3v3v3(co31, co3, co4, co1, co2, wboundary); + interp_v3_v3v3(co41, co1, co4, 0.75f); + } + else { + /* interior */ + interp_v3_v3v3v3v3(co11, co1, co2, co4, co3, winterior); + interp_v3_v3v3v3v3(co21, co2, co1, co3, co4, winterior); + interp_v3_v3v3v3v3(co31, co3, co2, co4, co1, winterior); + interp_v3_v3v3v3v3(co41, co4, co1, co3, co2, winterior); + } + j1 = 2 * j; + k1 = 2 * k; + if (is_canon(vm1, i, j1, k1)) + copy_v3_v3(mesh_vert(vm1, i, j1, k1)->co, co11); + if (is_canon(vm1, i, j1, k1 + 1)) + copy_v3_v3(mesh_vert(vm1, i, j1, k1 + 1)->co, co21); + if (is_canon(vm1, i, j1 + 1, k1 + 1)) + copy_v3_v3(mesh_vert(vm1, i, j1 + 1, k1 + 1)->co, co31); + if (is_canon(vm1, i, j1 + 1, k1)) + copy_v3_v3(mesh_vert(vm1, i, j1 + 1, k1)->co, co41); + } + } + + /* center ngon */ + denom = 8.0f * (float) n; + zero_v3(co); + for (j = 0; j < n; j++) { + copy_v3_v3(co1, mesh_vert(vm0, j, ns20, ns20)->co); + if (i == j) + madd_v3_v3fl(co, co1, (4.0f * (float) n + 2.0f) / denom); + else if ((i + 1) % n == j || (i + n - 1) % n == j) + madd_v3_v3fl(co, co1, ((float) n + 2.0f) / denom); + else + madd_v3_v3fl(co, co1, 2.0f / denom); + } + copy_v3_v3(mesh_vert(vm1, i, 2 * ns20, 2 * ns20)->co, co); + } + + vmesh_copy_equiv_verts(vm1); + return vm1; +} + +/* After a step of quadratic_subdiv, adjust the ring 1 verts to be on the planes of their respective faces, + * so that the cross-tangents will match on further subdivision. */ +static void fix_vmesh_tangents(VMesh *vm, BevVert *bv) +{ + int i, n; + NewVert *v; + BoundVert *bndv; + float co[3]; + + n = vm->count; + bndv = vm->boundstart; + do { + i = bndv->index; + + /* (i, 1, 1) snap to edge line */ + v = mesh_vert(vm, i, 1, 1); + closest_to_line_v3(co, v->co, bndv->nv.co, bv->v->co); + copy_v3_v3(v->co, co); + copy_v3_v3(mesh_vert(vm, (i + n -1) % n, 1, vm->seg - 1)->co, co); + + /* Also want (i, 1, k) snapped to plane of adjacent face for + * 1 < k < ns - 1, but current initial cage and subdiv rules + * ensure this, so nothing to do */ + } while ((bndv = bndv->next) != vm->boundstart); +} + +/* Fill frac with fractions of way along ring 0 for vertex i, for use with interp_range function */ +static void fill_vmesh_fracs(VMesh *vm, float *frac, int i) +{ + int k, ns; + float total = 0.0f; + + ns = vm->seg; + frac[0] = 0.0f; + for (k = 0; k < ns; k++) { + total += len_v3v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm, i, 0, k + 1)->co); + frac[k + 1] = total; + } + if (total > BEVEL_EPSILON) { + for (k = 1; k <= ns; k++) + frac[k] /= total; + } +} + +/* Return i such that frac[i] <= f <= frac[i + 1], where frac[n] == 1.0 + * and put fraction of rest of way between frac[i] and frac[i + 1] into r_rest */ +static int interp_range(const float *frac, int n, const float f, float *r_rest) +{ + int i; + float rest; + + /* could binary search in frac, but expect n to be reasonably small */ + for (i = 0; i < n; i++) { + if (f <= frac[i + 1]) { + rest = f - frac[i]; + if (rest == 0) + *r_rest = 0.0f; + else + *r_rest = rest / (frac[i + 1] - frac[i]); + return i; + } + } + *r_rest = 0.0f; + return n; +} + +/* Interpolate given vmesh to make one with target nseg and evenly spaced border vertices */ +static VMesh *interp_vmesh(MemArena *mem_arena, VMesh *vm0, int nseg) +{ + int n, ns0, nseg2, odd, i, j, k, j0, k0; + float *prev_frac, *frac, f, restj, restk; + float quad[4][3], co[3], center[3]; + VMesh *vm1; + + n = vm0->count; + ns0 = vm0->seg; + nseg2 = nseg / 2; + odd = nseg % 2; + vm1 = new_adj_subdiv_vmesh(mem_arena, n, nseg, vm0->boundstart); + prev_frac = (float *)BLI_memarena_alloc(mem_arena, (ns0 + 1 ) *sizeof(float)); + frac = (float *)BLI_memarena_alloc(mem_arena, (ns0 + 1 ) *sizeof(float)); + + fill_vmesh_fracs(vm0, prev_frac, n - 1); + fill_vmesh_fracs(vm0, frac, 0); + for (i = 0; i < n; i++) { + for (j = 0; j <= nseg2 -1 + odd; j++) { + for (k = 0; k <= nseg2; k++) { + f = (float) k / (float) nseg; + k0 = interp_range(frac, ns0, f, &restk); + f = 1.0f - (float) j / (float) nseg; + j0 = interp_range(prev_frac, ns0, f, &restj); + if (restj < BEVEL_EPSILON) { + j0 = ns0 - j0; + restj = 0.0f; + } + else { + j0 = ns0 - j0 - 1; + restj = 1.0f - restj; + } + /* Use bilinear interpolation within the source quad; could be smarter here */ + if (restj < BEVEL_EPSILON && restk < BEVEL_EPSILON) { + copy_v3_v3(co, mesh_vert_canon(vm0, i, j0, k0)->co); + } + else { + copy_v3_v3(quad[0], mesh_vert_canon(vm0, i, j0, k0)->co); + copy_v3_v3(quad[1], mesh_vert_canon(vm0, i, j0, k0 + 1)->co); + copy_v3_v3(quad[2], mesh_vert_canon(vm0, i, j0 + 1, k0 + 1)->co); + copy_v3_v3(quad[3], mesh_vert_canon(vm0, i, j0 + 1, k0)->co); + interp_bilinear_quad_v3(quad, restk, restj, co); + } + copy_v3_v3(mesh_vert(vm1, i, j, k)->co, co); + } + } + } + if (!odd) { + vmesh_center(vm0, center); + copy_v3_v3(mesh_vert(vm1, 0, nseg2, nseg2)->co, center); + } + vmesh_copy_equiv_verts(vm1); + return vm1; +} + +/* + * Given that the boundary is built and the boundary BMVerts have been made, + * calculate the positions of the interior mesh points for the M_ADJ_SUBDIV pattern, + * then make the BMVerts and the new faces. */ +static void bevel_build_rings_subdiv(BevelParams *bp, BMesh *bm, BevVert *bv) +{ + int n, ns, ns2, odd, i, j, k; + VMesh *vm0, *vm1, *vm; + float coa[3], cob[3], coc[3]; + BoundVert *v; + BMVert *bmv1, *bmv2, *bmv3, *bmv4; + BMFace *f; + MemArena *mem_arena = bp->mem_arena; + const float fullness = 0.5f; + + n = bv->edgecount; + ns = bv->vmesh->seg; + ns2 = ns / 2; + odd = ns % 2; + BLI_assert(n >= 3 && ns > 1); + + /* First construct an initial control mesh, with nseg==3 */ + vm0 = new_adj_subdiv_vmesh(mem_arena, n, 3, bv->vmesh->boundstart); + + for (i = 0; i < n; i++) { + /* Boundaries just divide input polygon edges into 3 even segments */ + copy_v3_v3(coa, mesh_vert(bv->vmesh, i, 0, 0)->co); + copy_v3_v3(cob, mesh_vert(bv->vmesh, (i + 1) % n, 0, 0)->co); + copy_v3_v3(coc, mesh_vert(bv->vmesh, (i + n -1) % n, 0, 0)->co); + copy_v3_v3(mesh_vert(vm0, i, 0, 0)->co, coa); + interp_v3_v3v3(mesh_vert(vm0, i, 0, 1)->co, coa, cob, 1.0f / 3.0f); + interp_v3_v3v3(mesh_vert(vm0, i, 1, 0)->co, coa, coc, 1.0f / 3.0f); + interp_v3_v3v3(mesh_vert(vm0, i, 1, 1)->co, coa, bv->v->co, fullness); + } + vmesh_copy_equiv_verts(vm0); + + vm1 = vm0; + do { + vm1 = quadratic_subdiv(mem_arena, vm1); + fix_vmesh_tangents(vm1, bv); + } while (vm1->seg <= ns); + vm1 = interp_vmesh(mem_arena, vm1, ns); + + /* copy final vmesh into bv->vmesh, make BMVerts and BMFaces */ + vm = bv->vmesh; + for (i = 0; i < n; i ++) { + for (j = 0; j <= ns2; j++) { + for (k = 0; k <= ns; k++) { + if (j == 0 && (k == 0 || k == ns)) + continue; /* boundary corners already made */ + if (!is_canon(vm, i, j, k)) + continue; + copy_v3_v3(mesh_vert(vm, i, j, k)->co, mesh_vert(vm1, i, j, k)->co); + create_mesh_bmvert(bm, vm, i, j, k, bv->v); + } + } + } + vmesh_copy_equiv_verts(vm); + /* make the polygons */ + v = vm->boundstart; + do { + i = v->index; + f = boundvert_rep_face(v); + /* For odd ns, make polys with lower left corner at (i,j,k) for + * j in [0, ns2-1], k in [0, ns2]. And then the center ngon. + * For even ns, + * j in [0, ns2-1], k in [0, ns2-1] */ + for (j = 0; j < ns2; j++) { + for (k = 0; k < ns2 + odd; k++) { + bmv1 = mesh_vert(vm, i, j, k)->v; + bmv2 = mesh_vert(vm, i, j, k + 1)->v; + bmv3 = mesh_vert(vm, i, j + 1, k + 1)->v; + bmv4 = mesh_vert(vm, i, j + 1, k)->v; + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); + } + } + } while ((v = v->next) != vm->boundstart); + + /* center ngon */ + if (odd) { + BMVert **vv = NULL; + BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); + + v = vm->boundstart; + do { + i = v->index; + BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v); + } while ((v = v->next) != vm->boundstart); + f = boundvert_rep_face(vm->boundstart); + bev_create_ngon(bm, vv, BLI_array_count(vv), f); + + BLI_array_free(vv); + } +} + static BMFace *bevel_build_poly_ex(BMesh *bm, BevVert *bv) { BMFace *f; @@ -1339,24 +1619,7 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) BoundVert *v, *weld1, *weld2; int n, ns, ns2, i, k, weld; float *va, *vb, co[3]; - -#ifdef USE_ALTERNATE_ADJ - /* ordered as follows (orig, prev, center, next)*/ - float quad_plane[4][3]; - float quad_orig_a[4][3]; - float quad_orig_b[4][3]; - const int is_odd = (vm->seg % 2); -#else float midco[3]; -#endif - -#ifdef USE_ALTERNATE_ADJ - /* the rest are initialized inline, this remains the same for all */ - /* NOTE; in this usage we only interpolate on the 'V' so cent and next points are unused (2,3)*/ - vmesh_cent(vm, quad_plane[2]); - copy_v3_v3(quad_orig_a[2], bv->v->co); - copy_v3_v3(quad_orig_b[2], bv->v->co); -#endif n = vm->count; ns = vm->seg; @@ -1389,59 +1652,6 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) i = v->index; copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0); if (v->ebev) { - -#ifdef USE_ALTERNATE_ADJ - copy_v3_v3(quad_plane[0], v->nv.co); - mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co); - /* quad[2] is set */ - mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co); - - /* orig 'A' */ - copy_v3_v3(quad_orig_a[0], v->nv.co); /* only shared location between 2 quads */ - project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_a[1]); - project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_a[3]); - - /* orig 'B' */ - copy_v3_v3(quad_orig_b[3], v->next->nv.co); /* only shared location between 2 quads */ - project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_b[1]); - project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_b[0]); - - //bl_debug_draw_quad_add(UNPACK4(quad_plane)); - //bl_debug_draw_quad_add(UNPACK4(quad_orig_a)); - //bl_debug_draw_quad_add(UNPACK4(quad_orig_b)); -#endif /* USE_ALTERNATE_ADJ */ - -#ifdef USE_ALTERNATE_ADJ - for (k = 1; k < ns; k++) { - float uv[2]; - float fac; - float co_plane[3]; - float co_orig[3]; - - /* quad_plane */ - get_point_uv(uv, v->ebev->seg, 0, k); - get_point_on_round_edge(uv, quad_plane, co_plane); - - /* quad_orig */ - /* each half has different UV's */ - if (k <= ns2) { - get_point_uv(uv, v->ebev->seg, 0, k); - get_point_on_round_edge(uv, quad_orig_a, co_orig); - } - else { - get_point_uv(uv, v->ebev->seg, 0, (k - ns2) - (is_odd ? 0.5f : 0.0f)); - get_point_on_round_edge(uv, quad_orig_b, co_orig); - uv[1] = 1.0f - uv[1]; /* so we can get the factor */ - } - fac = get_point_uv_factor(uv); - - /* done. interp */ - interp_v3_v3v3(co, co_plane, co_orig, fac); - copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); - if (!weld) - create_mesh_bmvert(bm, vm, i, 0, k, bv->v); - } -#else /* USE_ALTERNATE_ADJ */ va = mesh_vert(vm, i, 0, 0)->co; vb = mesh_vert(vm, i, 0, ns)->co; project_to_edge(v->ebev->e, va, vb, midco); @@ -1451,7 +1661,6 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) if (!weld) create_mesh_bmvert(bm, vm, i, 0, k, bv->v); } -#endif /* !USE_ALTERNATE_ADJ */ } } while ((v = v->next) != vm->boundstart); @@ -1478,6 +1687,9 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) case M_ADJ: bevel_build_rings(bm, bv); break; + case M_ADJ_SUBDIV: + bevel_build_rings_subdiv(bp, bm, bv); + break; case M_TRI_FAN: bevel_build_trifan(bm, bv); break; @@ -1687,6 +1899,14 @@ static int bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) BLI_array_append(vv, bmv); } } + else if (bp->vertex_only && vm->mesh_kind == M_ADJ_SUBDIV && vm->seg > 1) { + BLI_assert(v->prev == vend); + i = vend->index; + for (k = vm->seg - 1; k > 0; k--) { + bmv = mesh_vert(vm, i, 0, k)->v; + BLI_array_append(vv, bmv); + } + } v = v->prev; BLI_array_append(vv, v->nv.v); } diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index 4a557c20ae3..d3eaf1c6670 100644 --- a/source/blender/bmesh/tools/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -27,15 +27,15 @@ * \ingroup bmesh */ -void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate); +void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const bool do_triangulate); -void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only); +void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only); void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations); -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, +void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len); -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries); +void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries); /* these weights are accumulated so too high values may reach 'inf' too quickly */ #define BM_MESH_DECIM_WEIGHT_MAX 100000.0f diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 794afb3e0d2..e94bb9f5417 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -134,7 +134,7 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], } } -static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3]) +static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3]) { BMIter liter; BMLoop *l; @@ -175,13 +175,13 @@ static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_c * (first making it zero area, then flipping again) */ if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) { //printf("no flip\n"); - return TRUE; + return true; } } } } - return FALSE; + return false; } static void bm_decim_build_edge_cost_single(BMEdge *e, @@ -291,15 +291,15 @@ static void bm_decim_build_edge_cost(BMesh *bm, * collapsing edges so even has some advantage over decimating quads * directly. * - * \return TRUE if any faces were triangulated. + * \return true if any faces were triangulated. */ -static int bm_decim_triangulate_begin(BMesh *bm) +static bool bm_decim_triangulate_begin(BMesh *bm) { BMIter iter; BMFace *f; - // int has_quad; // could optimize this a little - int has_cut = FALSE; + // bool has_quad; // could optimize this a little + bool has_cut = false; BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); @@ -345,7 +345,7 @@ static int bm_decim_triangulate_begin(BMesh *bm) } #ifdef USE_SAFETY_CHECKS - if (BM_edge_exists(l_a->v, l_b->v) == FALSE) + if (BM_edge_exists(l_a->v, l_b->v) == false) #endif { BMFace *f_new; @@ -355,7 +355,7 @@ static int bm_decim_triangulate_begin(BMesh *bm) * - if there is a quad that has a free standing edge joining it along * where we want to split the face, there isnt a good way we can handle this. * currently that edge will get removed when joining the tris back into a quad. */ - f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, FALSE); + f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, false); if (f_new) { /* the value of this doesn't matter, only that the 2 loops match and have unique values */ @@ -370,7 +370,7 @@ static int bm_decim_triangulate_begin(BMesh *bm) BM_face_normal_update(f); BM_face_normal_update(f_new); - has_cut = TRUE; + has_cut = true; } } } @@ -410,15 +410,15 @@ static void bm_decim_triangulate_end(BMesh *bm) BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v, }; - BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == FALSE); - BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == FALSE); - BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == FALSE); - BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == FALSE); + BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == false); + BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == false); + BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == false); + BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == false); if (is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) { /* highly unlikely to fail, but prevents possible double-ups */ BMFace *f[2] = {l_a->f, l_b->f}; - BM_faces_join(bm, f, 2, TRUE); + BM_faces_join(bm, f, 2, true); } } } @@ -445,7 +445,7 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle //#define USE_SEAM /* these don't need to be updated, since they will get removed when the edge collapses */ BMLoop *l_clear, *l_other; - const int is_manifold = BM_edge_is_manifold(l->e); + const bool is_manifold = BM_edge_is_manifold(l->e); int side; /* l defines the vert to collapse into */ @@ -467,7 +467,7 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle /* now we have both corners of the face 'l->f' */ for (side = 0; side < 2; side++) { #ifdef USE_SEAM - int is_seam = FALSE; + bool is_seam = false; #endif void *src[2]; BMFace *f_exit = is_manifold ? l->radial_next->f : NULL; @@ -507,7 +507,7 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle #ifdef USE_SEAM /* break out unless we find a match */ - is_seam = TRUE; + is_seam = true; #endif /* ok. we have a loop. now be smart with it! */ @@ -517,13 +517,13 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle const int type = bm->ldata.layers[i].type; void *cd_src[2] = {(char *)src[0] + offset, (char *)src[1] + offset}; - void *cd_iter = (char *)l_iter->head.data + offset;; + void *cd_iter = (char *)l_iter->head.data + offset; /* detect seams */ if (CustomData_data_equals(type, cd_src[0], cd_iter)) { CustomData_bmesh_interp_n(&bm->ldata, cd_src, w, NULL, 2, l_iter->head.data, i); #ifdef USE_SEAM - is_seam = FALSE; + is_seam = false; #endif } } @@ -598,7 +598,7 @@ BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l) #endif } -static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) +static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) { /* simply check that there is no overlap between faces and edges of each vert, * (excluding the 2 faces attached to 'e' and 'e' its self) */ @@ -609,7 +609,7 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) e_iter = e_first; do { if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { - return TRUE; + return true; } bm_edge_tag_disable(e_iter); } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); @@ -617,7 +617,7 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) e_iter = e_first; do { if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { - return TRUE; + return true; } bm_edge_tag_disable(e_iter); } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); @@ -673,11 +673,11 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) e_iter = e_first; do { if (bm_edge_tag_test(e_iter)) { - return TRUE; + return true; } } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); - return FALSE; + return false; } /** @@ -690,13 +690,13 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) * \param e_clear_other let caller know what edges we remove besides \a e_clear * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other') */ -static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], +static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], #ifdef USE_CUSTOMDATA - const CD_UseFlag customdata_flag, - const float customdata_fac + const CD_UseFlag customdata_flag, + const float customdata_fac #else - const CD_UseFlag UNUSED(customdata_flag), - const float UNUSED(customdata_fac) + const CD_UseFlag UNUSED(customdata_flag), + const float UNUSED(customdata_fac) #endif ) { @@ -708,11 +708,11 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e if (BM_edge_is_manifold(e_clear)) { BMLoop *l_a, *l_b; BMEdge *e_a_other[2], *e_b_other[2]; - int ok; + bool ok; ok = BM_edge_loop_pair(e_clear, &l_a, &l_b); - BLI_assert(ok == TRUE); + BLI_assert(ok == true); BLI_assert(l_a->f->len == 3); BLI_assert(l_b->f->len == 3); @@ -749,7 +749,7 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) || ELEM(e_a_other[1], e_b_other[0], e_b_other[1])) { - return FALSE; + return false; } r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); @@ -782,7 +782,7 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e // BM_mesh_validate(bm); - return TRUE; + return true; } else if (BM_edge_is_boundary(e_clear)) { /* same as above but only one triangle */ @@ -829,10 +829,10 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e // BM_mesh_validate(bm); - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -869,7 +869,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, } /* use for customdata merging */ - if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { + if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == false)) { customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); #if 0 /* simple test for stupid collapse */ @@ -946,7 +946,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, else e_outer = l->prev->e; - BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); + BLI_assert(BM_vert_in_edge(e_outer, l->v) == false); bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table); } @@ -972,14 +972,14 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, * \param vweights Optional array of vertex aligned weights [0 - 1], * a vertex group is the usual source for this. */ -void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate) +void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const bool do_triangulate) { Heap *eheap; /* edge heap */ HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */ Quadric *vquadrics; /* vert index aligned quadrics */ int tot_edge_orig; int face_tot_target; - int use_triangulate; + bool use_triangulate; CD_UseFlag customdata_flag = 0; @@ -1015,7 +1015,7 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c /* iterative edge collapse and maintain the eheap */ while ((bm->totface > face_tot_target) && - (BLI_heap_is_empty(eheap) == FALSE) && + (BLI_heap_is_empty(eheap) == false) && (BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID)) { // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); @@ -1033,7 +1033,7 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c #ifdef USE_TRIANGULATE - if (do_triangulate == FALSE) { + if (do_triangulate == false) { /* its possible we only had triangles, skip this step in that case */ if (LIKELY(use_triangulate)) { /* temp convert quads to triangles */ diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index f67f01e4585..3a724769f2a 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -69,7 +69,7 @@ static int dissolve_elem_cmp(const void *a1, const void *a2) return 0; } -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, +void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len) { @@ -117,7 +117,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int BMFace *nf = BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, - FALSE); /* join faces */ + false); /* join faces */ /* there may be some errors, we don't mind, just move on */ if (nf) { @@ -148,7 +148,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int for (i = bm->totedge - 1; i != -1; i--) { e_iter = earray[i]; - if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) { + if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == false)) { /* edge has become wire */ int vidx_reverse; BMVert *v1 = e_iter->v1; @@ -179,7 +179,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int if (LIKELY(v != NULL) && BM_vert_edge_count(v) == 2) { - BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ + BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */ } } } @@ -210,7 +210,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int /* 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 */ + BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */ if (ne && ne->l) { BM_edge_normals_update(ne); @@ -223,7 +223,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int MEM_freeN(weight_elems); } -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries) +void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries) { int vinput_len; int einput_len; diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 71c1cedbd5e..9dc4b596568 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -36,7 +36,7 @@ #include "intern/bmesh_operators_private.h" /* own include */ -static int bm_vert_dissolve_fan_test(BMVert *v) +static bool bm_vert_dissolve_fan_test(BMVert *v) { /* check if we should walk over these verts */ BMIter iter; @@ -61,21 +61,21 @@ static int bm_vert_dissolve_fan_test(BMVert *v) } if ((tot_edge == 4) && (tot_edge_boundary == 0) && (tot_edge_manifold == 4)) { - return TRUE; + return true; } else if ((tot_edge == 3) && (tot_edge_boundary == 0) && (tot_edge_manifold == 3)) { - return TRUE; + return true; } else if ((tot_edge == 3) && (tot_edge_boundary == 2) && (tot_edge_manifold == 1)) { - return TRUE; + return true; } else if ((tot_edge == 2) && (tot_edge_wire == 2)) { - return TRUE; + return true; } - return FALSE; + return false; } -static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) +static bool bm_vert_dissolve_fan(BMesh *bm, BMVert *v) { /* collapse under 2 conditions. * - vert connects to 4 manifold edges (and 4 faces). @@ -110,7 +110,7 @@ static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) if (tot_edge == 2) { /* check for 2 wire verts only */ if (tot_edge_wire == 2) { - return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL); + return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL); } } else if (tot_edge == 4) { @@ -145,7 +145,7 @@ static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) if (l->f->len > 3) { BMLoop *l_new; BLI_assert(l->prev->v != l->next->v); - BM_face_split(bm, l->f, l->prev->v, l->next->v, &l_new, NULL, TRUE); + BM_face_split(bm, l->f, l->prev->v, l->next->v, &l_new, NULL, true); BM_elem_flag_merge_into(l_new->e, l->e, l->prev->e); } } @@ -153,7 +153,7 @@ static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) return BM_vert_dissolve(bm, v); } - return FALSE; + return false; } enum { @@ -170,7 +170,7 @@ enum { /** * \param tag_only so we can call this from an operator */ -void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only) +void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only) { #ifdef USE_WALKER # define ELE_VERT_TAG 1 @@ -191,14 +191,14 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int /* if tag_only is set, we assyme the caller knows what verts to tag * needed for the operator */ - if (tag_only == FALSE) { + if (tag_only == false) { BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { BM_elem_flag_enable(v, BM_ELEM_TAG); } } for (iter_step = 0; iter_step < iterations; iter_step++) { - int iter_done; + bool iter_done; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG) && bm_vert_dissolve_fan_test(v)) { @@ -215,7 +215,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int /* main loop, keep tagging until we can't tag any more islands */ - while (TRUE) { + while (true) { #ifdef USE_WALKER BMWalker walker; #else @@ -273,7 +273,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int vert_seek_b_tot = 0; vert_seek_b[vert_seek_b_tot++] = v_first; - while (TRUE) { + while (true) { BMEdge *e; if ((offset + depth) % nth) { @@ -318,14 +318,16 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int } /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */ - iter_done = FALSE; + iter_done = false; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) { - iter_done |= bm_vert_dissolve_fan(bm, v); + if (bm_vert_dissolve_fan(bm, v)) { + iter_done = true; + } } } - if (iter_done == FALSE) { + if (iter_done == false) { break; } } @@ -340,5 +342,5 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations) { - BM_mesh_decimate_unsubdivide_ex(bm, iterations, FALSE); + BM_mesh_decimate_unsubdivide_ex(bm, iterations, false); } diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index b6a8c7985d6..1d3f973dbc0 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -98,14 +98,14 @@ static void bm_edgesplit_validate_seams(BMesh *bm) MEM_freeN(vtouch); } -void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only) +void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only) { BMIter iter; BMEdge *e; - if (tag_only == FALSE) { - BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, FALSE); + if (tag_only == false) { + BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, false); } if (use_verts) { @@ -117,8 +117,8 @@ void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only) */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - if (UNLIKELY(((BM_elem_flag_test(e->v1, BM_ELEM_TAG) == FALSE) && - (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == FALSE)))) + if (UNLIKELY(((BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) && + (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false)))) { BM_elem_flag_enable(e->v1, BM_ELEM_TAG); BM_elem_flag_enable(e->v2, BM_ELEM_TAG); @@ -146,10 +146,10 @@ void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only) if (use_verts) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, BM_ELEM_TAG) == FALSE) { + if (BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) { BM_elem_flag_disable(e->v1, BM_ELEM_TAG); } - if (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == FALSE) { + if (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false) { BM_elem_flag_disable(e->v2, BM_ELEM_TAG); } } diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h index 687fdac0e00..8c1231dd794 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.h +++ b/source/blender/bmesh/tools/bmesh_edgesplit.h @@ -27,6 +27,6 @@ * \ingroup bmesh */ -void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only); +void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only); #endif /* __BMESH_EDGESPLIT_H__ */ |