From 561d738eaa2f64044f5266a480d9bc822bd0296e Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sun, 28 Jan 2018 19:19:02 -0500 Subject: Fix T53459, inconsistent bevel on identical edges. The old algorithm depended on vertex order. The new one uses a global least squares solution on chains and cycles of edges where loop slide induces a dependency. See https://wiki.blender.org/index.php/Dev:Source/Modeling/Bevel in the "Consistent Widths for Even Bevels" for derivation of the new algorithm. --- source/blender/bmesh/tools/bmesh_bevel.c | 554 ++++++++++++++++++++----------- 1 file changed, 351 insertions(+), 203 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 18b2b4db2bf..35167835646 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -44,6 +44,8 @@ #include "BKE_customdata.h" #include "BKE_deform.h" +#include "eigen_capi.h" + #include "bmesh.h" #include "bmesh_bevel.h" /* own include */ @@ -58,6 +60,7 @@ #define BEVEL_SMALL_ANG DEG2RADF(10.0f) #define BEVEL_MAX_ADJUST_PCT 10.0f #define BEVEL_MAX_AUTO_ADJUST_PCT 300.0f +#define BEVEL_MATCH_SPEC_WEIGHT 0.2 /* happens far too often, uncomment for development */ // #define BEVEL_ASSERT_PROJECT @@ -139,10 +142,14 @@ typedef struct BoundVert { NewVert nv; EdgeHalf *efirst; /* first of edges attached here: in CCW order */ EdgeHalf *elast; + EdgeHalf *eon; /* the "edge between" that this is on, in offset_on_edge_between case */ EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */ int index; /* used for vmesh indexing */ + float sinratio; /* when eon set, ratio of sines of angles to eon edge */ + struct BoundVert *adjchain; /* adjustment chain or cycle link pointer */ Profile profile; /* edge profile between this and next BoundVert */ bool any_seam; /* are any of the edges attached here seams? */ + bool visited; /* used during delta adjust pass */ // int _pad; } BoundVert; @@ -192,6 +199,7 @@ typedef struct BevelParams { bool use_weights; /* bevel amount affected by weights on edges or verts */ bool loop_slide; /* should bevel prefer to slide along edges rather than keep widths spec? */ bool limit_offset; /* should offsets be limited by collisions? */ + bool offset_adjust; /* should offsets be adjusted to try to get even widths? */ const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */ int vertex_group; /* vertex group index, maybe set if vertex_only */ int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */ @@ -207,6 +215,7 @@ static int bev_debug_flags = 0; #define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2) #define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4) + /* this flag values will get set on geom we want to return in 'out' slots for edges and verts */ #define EDGE_OUT 4 #define VERT_OUT 8 @@ -260,6 +269,9 @@ static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float vm->boundstart->prev = ans; } ans->profile.super_r = PRO_LINE_R; + ans->adjchain = NULL; + ans->sinratio = 1.0f; + ans->visited = false; vm->count++; return ans; } @@ -342,52 +354,6 @@ static EdgeHalf *find_other_end_edge_half(BevelParams *bp, EdgeHalf *e, BevVert return NULL; } -static bool other_edge_half_visited(BevelParams *bp, EdgeHalf *e) -{ - BevVert *bvo; - - bvo = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2); - if (bvo) - return bvo->visited; - else - return false; -} - -static bool edge_half_offset_changed(EdgeHalf *e) -{ - return e->offset_l != e->offset_l_spec || - e->offset_r != e->offset_r_spec; -} - -static float adjusted_rel_change(float val, float spec) -{ - float relchg; - - relchg = 0.0f; - if (val != spec) { - if (spec == 0) - relchg = 1000.0f; /* arbitrary large value */ - else - relchg = fabsf((val - spec) / spec); - } - return relchg; -} - -static float max_edge_half_offset_rel_change(BevVert *bv) -{ - int i; - float max_rel_change; - EdgeHalf *e; - - max_rel_change = 0.0f; - for (i = 0; i < bv->edgecount; i++) { - e = &bv->edges[i]; - max_rel_change = max_ff(max_rel_change, adjusted_rel_change(e->offset_l, e->offset_l_spec)); - max_rel_change = max_ff(max_rel_change, adjusted_rel_change(e->offset_r, e->offset_r_spec)); - } - return max_rel_change; -} - /* Return the next EdgeHalf after from_e that is beveled. * If from_e is NULL, find the first beveled edge. */ static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e) @@ -818,10 +784,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e copy_v3_v3(off1a, v->co); d = max_ff(e1->offset_r, e2->offset_l); madd_v3_v3fl(off1a, norm_perp1, d); - if (e1->offset_r != d) - e1->offset_r = d; - else if (e2->offset_l != d) - e2->offset_l = d; copy_v3_v3(meetco, off1a); } else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG) { @@ -830,10 +792,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e * common line, at offset distance from v. */ d = max_ff(e1->offset_r, e2->offset_l); slide_dist(e2, v, d, meetco); - if (e1->offset_r != d) - e1->offset_r = d; - else if (e2->offset_l != d) - e2->offset_l = d; } else { /* Get normal to plane where meet point should be, @@ -871,7 +829,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e negate_v3(norm_v2); } - /* get vectors perp to each edge, perp to norm_v, and pointing into face */ cross_v3_v3v3(norm_perp1, dir1, norm_v1); cross_v3_v3v3(norm_perp2, dir2, norm_v2); @@ -891,9 +848,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e if (isect_kind == 0) { /* lines are collinear: we already tested for this, but this used a different epsilon */ copy_v3_v3(meetco, off1a); /* just to do something */ - d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co); - if (fabsf(d - e2->offset_l) > BEVEL_EPSILON) - e2->offset_l = d; } else { /* The lines intersect, but is it at a reasonable place? @@ -903,11 +857,9 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e * or if the offset amount is > the edge length*/ if (e1->offset_r == 0.0f && is_outside_edge(e1, meetco, &closer_v)) { copy_v3_v3(meetco, closer_v->co); - e2->offset_l = len_v3v3(meetco, v->co); } if (e2->offset_l == 0.0f && is_outside_edge(e2, meetco, &closer_v)) { copy_v3_v3(meetco, closer_v->co); - e1->offset_r = len_v3v3(meetco, v->co); } if (edges_between && e1->offset_r > 0.0f && e2->offset_l > 0.0f) { /* Try to drop meetco to a face between e1 and e2 */ @@ -926,8 +878,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e break; } } - e1->offset_r = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co); - e2->offset_l = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co); } } } @@ -994,40 +944,27 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em /* Calculate the best place for a meeting point for the offsets from edges e1 and e2 * on the in-between edge emid. Viewed from the vertex normal side, the CCW * order of these edges is e1, emid, e2. - * The offsets probably do not meet at a common point on emid, so need to pick - * one that causes the least problems. If the other end of one of e1 or e2 has been visited - * already, prefer to keep the offset the same on this end. - * Otherwise, pick a point between the two intersection points on emid that minimizes - * the sum of squares of errors from desired offset. */ -static void offset_on_edge_between( - BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, - BMVert *v, float meetco[3]) + * Return true if we placed meetco as compromise between where two edges met. + * If we did, put ration of sines of angles in *r_sinratio too */ +static bool offset_on_edge_between( + EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, + BMVert *v, float meetco[3], float *r_sinratio) { - float d, ang1, ang2, sina1, sina2, lambda; + float ang1, ang2; float meet1[3], meet2[3]; - bool visited1, visited2, ok1, ok2; + bool ok1, ok2; + bool retval = false; BLI_assert(e1->is_bev && e2->is_bev && !emid->is_bev); - visited1 = other_edge_half_visited(bp, e1); - visited2 = other_edge_half_visited(bp, e2); - ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1); ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2); if (ok1 && ok2) { - if (visited1 && !visited2) { - copy_v3_v3(meetco, meet1); - } - else if (!visited1 && visited2) { - copy_v3_v3(meetco, meet2); - } - else { - /* find best compromise meet point */ - sina1 = sinf(ang1); - sina2 = sinf(ang2); - lambda = sina2 * sina2 / (sina1 * sina1 + sina2 * sina2); - interp_v3_v3v3(meetco, meet1, meet2, lambda); - } + mid_v3_v3v3(meetco, meet1, meet2); + if (r_sinratio) + /* ang1 should not be 0, but be paranoid */ + *r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1); + retval = true; } else if (ok1 && !ok2) { copy_v3_v3(meetco, meet1); @@ -1041,13 +978,7 @@ static void offset_on_edge_between( slide_dist(emid, v, e1->offset_r, meetco); } - /* offsets may have changed now */ - d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co); - if (fabsf(d - e1->offset_r) > BEVEL_EPSILON) - e1->offset_r = d; - d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co); - if (fabsf(d - e2->offset_l) > BEVEL_EPSILON) - e2->offset_l = d; + return retval; } /* Offset by e->offset in plane with normal plane_no, on left if left==true, @@ -1806,6 +1737,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf } } +#if 0 /* Return a value that is v if v is within BEVEL_MAX_ADJUST_PCT of the spec (assumed positive), * else clamp to make it at most that far away from spec */ static float clamp_adjust(float v, float spec) @@ -1819,6 +1751,7 @@ static float clamp_adjust(float v, float spec) else return v; } +#endif /* Make a circular list of BoundVerts for bv, each of which has the coordinates * of a vertex on the boundary of the beveled vertex bv->v. @@ -1835,11 +1768,10 @@ static float clamp_adjust(float v, float spec) static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) { MemArena *mem_arena = bp->mem_arena; - EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eother; + EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eon; BoundVert *v; - BevVert *bvother; VMesh *vm; - float co[3]; + float co[3], r; int nip, nnip; /* Current bevel does nothing if only one edge into a vertex */ @@ -1853,30 +1785,9 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) vm = bv->vmesh; - /* Find a beveled edge to be efirst. Then for each edge, try matching widths to other end. */ + /* Find a beveled edge to be efirst */ e = efirst = next_bev(bv, NULL); BLI_assert(e->is_bev); - do { - eother = find_other_end_edge_half(bp, e, &bvother); - if (eother && bvother->visited && bp->offset_type != BEVEL_AMT_PERCENT) { - /* try to keep bevel even by matching other end offsets */ - /* sometimes, adjustment can accumulate errors so use the bp->limit_offset to - * let user limit the adjustment to within a reasonable range around spec */ - if (bp->limit_offset) { - e->offset_l = clamp_adjust(eother->offset_r, e->offset_l_spec); - e->offset_r = clamp_adjust(eother->offset_l, e->offset_r_spec); - } - else { - e->offset_l = eother->offset_r; - e->offset_r = eother->offset_l; - } - } - else { - /* reset to user spec */ - e->offset_l = e->offset_l_spec; - e->offset_r = e->offset_r_spec; - } - } while ((e = e->next) != efirst); if (bv->selcount == 1) { /* special case: only one beveled edge in */ @@ -1890,6 +1801,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) e = efirst; do { BLI_assert(e->is_bev); + eon = NULL; /* Make the BoundVert for the right side of e; other side will be made * when the beveled edge to the left of e is handled. * Analyze edges until next beveled edge. @@ -1913,7 +1825,8 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) } else if (nnip > 0) { if (bp->loop_slide && nnip == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) { - offset_on_edge_between(bp, e, e2, enip, bv->v, co); + if (offset_on_edge_between(e, e2, enip, bv->v, co, &r)) + eon = enip; } else { offset_meet(e, e2, bv->v, NULL, true, co); @@ -1922,7 +1835,8 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) else { /* nip > 0 and nnip == 0 */ if (bp->loop_slide && nip == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) { - offset_on_edge_between(bp, e, e2, eip, bv->v, co); + if (offset_on_edge_between(e, e2, eip, bv->v, co, &r)) + eon = eip; } else { offset_meet(e, e2, bv->v, e->fnext, true, co); @@ -1933,6 +1847,9 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) v->efirst = e; v->elast = e2; v->ebev = e2; + v->eon = eon; + if (eon) + v->sinratio = r; e->rightv = v; e2->leftv = v; for (e3 = e->next; e3 != e2; e3 = e3->next) { @@ -1962,98 +1879,328 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) } } -/* Do a global pass to try to make offsets as even as possible. - * Consider this graph: - * nodes = BevVerts - * edges = { (u,v) } where u and v are nodes such that u and v - * are connected by a mesh edge that has at least one end - * whose offset does not match the user spec. - * - * Do a breadth-first search on this graph, starting from nodes - * that have any_adjust=true, and changing all - * not-already-changed offsets on EdgeHalfs to match the - * corresponding ones that changed on the other end. - * The graph is dynamic in the sense that having an offset that - * doesn't meet the user spec can be added as the search proceeds. - * We want this search to be deterministic (not dependent - * on order of processing through hash table), so as to avoid - * flicker to to different decisions made if search is different - * while dragging the offset number in the UI. So look for the - * lower vertex number when there is a choice of where to start. +#if 0 +static void print_adjust_stats(BoundVert *vstart) +{ + BoundVert *v; + EdgeHalf *eleft, *eright; + double even_residual2, spec_residual2; + double max_even_r, max_even_r_pct; + double max_spec_r, max_spec_r_pct; + double delta, delta_pct; + + printf("\nSolution analysis\n"); + even_residual2 = 0.0; + spec_residual2 = 0.0; + max_even_r = 0.0; + max_even_r_pct = 0.0; + max_spec_r = 0.0; + max_spec_r_pct = 0.0; + printf("width matching\n"); + v = vstart; + do { + if (v->adjchain != NULL) { + eright = v->efirst; + eleft = v->adjchain->elast; + delta = fabs(eright->offset_r - eleft->offset_l); + delta_pct = 100.0 * delta / eright->offset_r_spec; + printf("e%d r(%f) vs l(%f): abs(delta)=%f, delta_pct=%f\n", + BM_elem_index_get(eright->e), eright->offset_r, eleft->offset_l, delta, delta_pct); + even_residual2 += delta * delta; + if (delta > max_even_r) + max_even_r = delta; + if (delta_pct > max_even_r_pct) + max_even_r_pct = delta_pct; + } + v = v->adjchain; + } while (v && v != vstart); + + printf("spec matching\n"); + v = vstart; + do { + if (v->adjchain != NULL) { + eright = v->efirst; + eleft = v->adjchain->elast; + delta = fabs(eright->offset_r - eright->offset_r_spec); + delta_pct = 100.0 * delta / eright->offset_r_spec; + printf("e%d r(%f) vs r spec(%f): abs(delta)=%f, delta_pct=%f\n", + BM_elem_index_get(eright->e), eright->offset_r, eright->offset_r_spec, delta, delta_pct); + spec_residual2 += delta * delta; + if (delta > max_spec_r) + max_spec_r = delta; + if (delta_pct > max_spec_r_pct) + max_spec_r_pct = delta_pct; + + delta = fabs(eleft->offset_l - eleft->offset_l_spec); + delta_pct = 100.0 * delta / eright->offset_l_spec; + printf("e%d l(%f) vs l spec(%f): abs(delta)=%f, delta_pct=%f\n", + BM_elem_index_get(eright->e), eleft->offset_l, eleft->offset_l_spec, delta, delta_pct); + spec_residual2 += delta * delta; + if (delta > max_spec_r) + max_spec_r = delta; + if (delta_pct > max_spec_r_pct) + max_spec_r_pct = delta_pct; + } + v = v->adjchain; + } while (v && v != vstart); + + printf("Analysis Result:\n"); + printf("even residual2 = %f, spec residual2 = %f\n", even_residual2, spec_residual2); + printf("max even delta = %f, max as percent of spec = %f\n", max_even_r, max_even_r_pct); + printf("max spec delta = %f, max as percent of spec = %f\n", max_spec_r, max_spec_r_pct); +} +#endif + +static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscycle) +{ + BoundVert *v; + EdgeHalf *eleft, *eright; + float *g; + float *g_prod; + float gprod, gprod_sum, spec_sum, p; + int i; + + g = MEM_mallocN(np * sizeof(float), "beveladjust"); + g_prod = MEM_mallocN(np * sizeof(float), "beveladjust"); + + v = vstart; + spec_sum = 0.0f; + i = 0; + do { + g[i] = v->sinratio; + if (iscycle || v->adjchain != NULL) { + spec_sum += v->efirst->offset_r; + } + else { + spec_sum += v->elast->offset_l; + } + i++; + v = v->adjchain; + } while (v && v != vstart); + + gprod = 1.00f; + gprod_sum = 1.0f; + for (i = np - 1; i > 0; i--) { + gprod *= g[i]; + g_prod[i] = gprod; + gprod_sum += gprod; + } + if (iscycle) { + gprod *= g[0]; + if (fabs(gprod - 1.0f) > BEVEL_EPSILON) { + /* fast cycle calc only works if total product is 1 */ + MEM_freeN(g); + MEM_freeN(g_prod); + return false; + } + else + g_prod[0] = 1.0f; + } + if (gprod_sum == 0.0f) { + MEM_freeN(g); + MEM_freeN(g_prod); + return false; + } + p = spec_sum / gprod_sum; + + /* apply the new offsets */ + v = vstart; + i = 0; + do { + if (iscycle || v->adjchain != NULL) { + eright = v->efirst; + eleft = v->elast; + eright->offset_r = g_prod[(i + 1) % np] * p; + if (iscycle || v != vstart) { + eleft->offset_l = v->sinratio * eright->offset_r; + } + } + else { + /* not a cycle, and last of chain */ + eleft = v->elast; + eleft->offset_l = p; + } + i++; + v = v->adjchain; + } while (v && v != vstart); + + MEM_freeN(g); + MEM_freeN(g_prod); + return true; +} + +/* Adjust the offsets for a single cycle or chain. + * For chains and some cycles, a fast solution exists. + * Otherwise, we set up and solve a linear least squares problem + * that tries to minimize the squared differences of lengths + * at each end of an edge, and (with smaller weight) the + * squared differences of the offsets from their specs. + */ +static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle) +{ + BoundVert *v; + EdgeHalf *eleft, *eright; + LinearSolver *solver; + double weight, val; + int i, np, nrows, row; + + np = 0; + v = vstart; + do { + np++; + v = v->adjchain; + } while (v && v != vstart); + + if (adjust_the_cycle_or_chain_fast(vstart, np, iscycle)) + return; + + nrows = iscycle ? 2 * np : 2 * np - 1; + + solver = EIG_linear_least_squares_solver_new(nrows, np, 1); + + v = vstart; + i = 0; + weight = BEVEL_MATCH_SPEC_WEIGHT; /* sqrt of factor to weight down importance of spec match */ + do { + /* except at end of chain, v's indep variable is offset_r of v->efirst */ + if (iscycle || v->adjchain != NULL) { + eright = v->efirst; + eleft = v->elast; + + /* residue i: width difference between eright and eleft of next */ + EIG_linear_solver_matrix_add(solver, i, i, 1.0); + EIG_linear_solver_right_hand_side_add(solver, 0, i, 0.0); + if (iscycle) { + EIG_linear_solver_matrix_add(solver, i > 0 ? i - 1 : np - 1, i, -v->sinratio); + } + else { + if (i > 0) + EIG_linear_solver_matrix_add(solver, i - 1, i, -v->sinratio); + } + + /* residue np + i (if cycle) else np - 1 + i: + * right offset for parm i matches its spec; weighted */ + row = iscycle ? np + i : np - 1 + i; + EIG_linear_solver_matrix_add(solver, row, i, weight); + EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eright->offset_r); + } + else { + /* not a cycle, and last of chain */ + eleft = v->elast; + /* second part of residue i for last i */ + EIG_linear_solver_matrix_add(solver, i - 1, i, -1.0); + /* residue 2 * np -2 : last spec match residue is for left offset of final parm */ + row = 2 * np - 2; + EIG_linear_solver_matrix_add(solver, row, i, weight); + EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eleft->offset_l); + } + i++; + v = v->adjchain; + } while (v && v != vstart); + EIG_linear_solver_solve(solver); + + /* Use the solution to set new widths */ + v = vstart; + i = 0; + do { + val = EIG_linear_solver_variable_get(solver, 0, i); + if (iscycle || v->adjchain != NULL) { + eright = v->efirst; + eleft = v->elast; + eright->offset_r = (float)val; + if (iscycle || v != vstart) { + eleft->offset_l = (float)(v->sinratio * val); + } + } + else { + /* not a cycle, and last of chain */ + eleft = v->elast; + eleft->offset_l = (float)val; + } + i++; + v = v->adjchain; + } while (v && v != vstart); + + EIG_linear_solver_delete(solver); +} + +/* Adjust the offsets to try to make them, as much as possible, + * have even-width bevels with offsets that match their specs. + * The problem that we can try to amelieroate is that when loop slide + * is active, the meet point will probably not be the one that makes + * both sides have their specified width. And because both ends may be + * on loop slide edges, the widths at each end could be different. * - * Note that this might not process all BevVerts, only the ones - * that need adjustment. + * It turns out that the dependent offsets either form chains or + * cycles, and we can process each of those separatey. */ static void adjust_offsets(BevelParams *bp) { - BevVert *bv, *searchbv, *bvother; - int i, searchi; + BevVert *bv, *bvcur; + BoundVert *v, *vanchor, *vchainstart, *vnext; + EdgeHalf *enext; GHashIterator giter; - EdgeHalf *e, *efirst, *eother; - GSQueue *q; - float max_rel_adj; + bool iscycle; - BLI_assert(!bp->vertex_only); + /* find and process chains and cycles of unvisited BoundVerts that have eon set */ GHASH_ITER(giter, bp->vert_hash) { - bv = BLI_ghashIterator_getValue(&giter); - bv->visited = false; - } + bv = bvcur = BLI_ghashIterator_getValue(&giter); + vanchor = bv->vmesh->boundstart; + do { + if (vanchor->visited || !vanchor->eon) + continue; - q = BLI_gsqueue_new(sizeof(BevVert *)); - /* the following loop terminates because at least one node is visited each time */ - for (;;) { - /* look for root of a connected component in search graph */ - searchbv = NULL; - searchi = -1; - GHASH_ITER(giter, bp->vert_hash) { - bv = BLI_ghashIterator_getValue(&giter); - if (!bv->visited && max_edge_half_offset_rel_change(bv) > 0.0f) { - i = BM_elem_index_get(bv->v); - if (!searchbv || i < searchi) { - searchbv = bv; - searchi = i; + /* Find one of (1) a cycle that starts and ends at v + * where each v has v->eon set and had not been visited before; + * or (2) a chain of v's where the start and end of the chain do not have + * v->eon set but all else do. + * It is OK for the first and last elements to + * have been visited before, but not any of the inner ones. + * We chain the v's together through v->adjchain, and are following + * them in left->right direction, meaning that the left side of one edge + * pairs with the right side of the next edge in the cycle or chain. */ + + /* first follow paired edges in left->right direction */ + v = vchainstart = vanchor; + iscycle = false; + while(v->eon && !v->visited && !iscycle) { + enext = find_other_end_edge_half(bp, v->efirst, &bvcur); + BLI_assert(enext != NULL); + vnext = enext->leftv; + v->adjchain = vnext; + v->visited = true; + if (vnext->visited) { + if (vnext != vchainstart) { + printf("WHOOPS, adjusting offsets, expected cycle!\n"); + break; + } + adjust_the_cycle_or_chain(vchainstart, true); + iscycle = true; } + v = vnext; } - } - if (searchbv == NULL) - break; - - BLI_gsqueue_push(q, &searchbv); - while (!BLI_gsqueue_is_empty(q)) { - BLI_gsqueue_pop(q, &bv); - /* If do this check, don't have to check for already-on-queue before push, below */ - if (bv->visited) - continue; - bv->visited = true; - build_boundary(bp, bv, false); - - e = efirst = &bv->edges[0]; - do { - eother = find_other_end_edge_half(bp, e, &bvother); - if (eother && !bvother->visited && edge_half_offset_changed(e)) { - BLI_gsqueue_push(q, &bvother); - } - } while ((e = e->next) != efirst); - } + if (!iscycle) { + /* right->left direction, changing vchainstart at each step */ + v = vchainstart; + bvcur = bv; + do { + enext = find_other_end_edge_half(bp, v->elast, &bvcur); + BLI_assert(enext != NULL); + vnext = enext->rightv; + vnext->adjchain = v; + vchainstart = vnext; + v->visited = true; + v = vnext; + } while(!v->visited && v->eon); + adjust_the_cycle_or_chain(vchainstart, false); + } + } while ((vanchor = vanchor->next) != bv->vmesh->boundstart); } - BLI_gsqueue_free(q); - /* Should we auto-limit the error accumulation? Typically, spirals can lead to 100x relative adjustments, - * and somewhat hacky mechanism of using bp->limit_offset to indicate "clamp the adjustments" is not - * obvious to users, who almost certainly want clamping in this situation. - * The reason not to clamp always is that some models work better without it (e.g., Bent_test in regression - * suite, where relative adjust maximum is about .6). */ - if (!bp->limit_offset) { - max_rel_adj = 0.0f; - GHASH_ITER(giter, bp->vert_hash) { - bv = BLI_ghashIterator_getValue(&giter); - max_rel_adj = max_ff(max_rel_adj, max_edge_half_offset_rel_change(bv)); - } - if (max_rel_adj > BEVEL_MAX_AUTO_ADJUST_PCT / 100.0f) { - bp->limit_offset = true; - adjust_offsets(bp); - bp->limit_offset = false; - } + /* Rebuild boundaries with new width specs */ + GHASH_ITER(giter, bp->vert_hash) { + bv = BLI_ghashIterator_getValue(&giter); + build_boundary(bp, bv, false); } } @@ -4983,6 +5130,7 @@ void BM_mesh_bevel( bp.use_weights = use_weights; bp.loop_slide = loop_slide; bp.limit_offset = limit_offset; + bp.offset_adjust = true; bp.dvert = dvert; bp.vertex_group = vertex_group; bp.mat_nr = mat; @@ -5019,7 +5167,7 @@ void BM_mesh_bevel( } /* Perhaps do a pass to try to even out widths */ - if (!bp.vertex_only) { + if (!bp.vertex_only && bp.offset_adjust) { adjust_offsets(&bp); } -- cgit v1.2.3 From cebc7bb1980dcc0864685036188aad4cd79f64c6 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Mon, 29 Jan 2018 10:01:19 -0500 Subject: Fix nan problem in previous bevel commit. For chains, access to g_prod[0] was undefined. And two minor style (whitespace) changes. --- source/blender/bmesh/tools/bmesh_bevel.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 35167835646..a18c4405a31 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1985,6 +1985,7 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc g_prod[i] = gprod; gprod_sum += gprod; } + g_prod[0] = 1.0f; if (iscycle) { gprod *= g[0]; if (fabs(gprod - 1.0f) > BEVEL_EPSILON) { @@ -1993,8 +1994,6 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc MEM_freeN(g_prod); return false; } - else - g_prod[0] = 1.0f; } if (gprod_sum == 0.0f) { MEM_freeN(g); @@ -2163,7 +2162,7 @@ static void adjust_offsets(BevelParams *bp) /* first follow paired edges in left->right direction */ v = vchainstart = vanchor; iscycle = false; - while(v->eon && !v->visited && !iscycle) { + while (v->eon && !v->visited && !iscycle) { enext = find_other_end_edge_half(bp, v->efirst, &bvcur); BLI_assert(enext != NULL); vnext = enext->leftv; @@ -2191,7 +2190,7 @@ static void adjust_offsets(BevelParams *bp) vchainstart = vnext; v->visited = true; v = vnext; - } while(!v->visited && v->eon); + } while (!v->visited && v->eon); adjust_the_cycle_or_chain(vchainstart, false); } } while ((vanchor = vanchor->next) != bv->vmesh->boundstart); -- cgit v1.2.3 From 078e012cd9711e3d9b88bdf437f31e39518315df Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 1 Feb 2018 12:06:57 +1100 Subject: Cleanup: rename BLI_*_empty() -> clear() Consistent with other BLI API's --- source/blender/bmesh/operators/bmo_dissolve.c | 2 +- source/blender/bmesh/operators/bmo_edgenet.c | 2 +- source/blender/bmesh/operators/bmo_hull.c | 2 +- source/blender/bmesh/operators/bmo_subdivide.c | 10 +++++----- source/blender/bmesh/tools/bmesh_bevel.c | 2 +- source/blender/bmesh/tools/bmesh_separate.c | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 2df8e73c2b8..5a2f07be70a 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -166,7 +166,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) continue; } - BLI_array_empty(faces); + BLI_array_clear(faces); faces = NULL; /* forces different allocatio */ BMW_init(®walker, bm, BMW_ISLAND_MANIFOLD, diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index 64b092da5c8..744ef866128 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -186,7 +186,7 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) BLI_array_count_set(edges2, BLI_array_count(edges)); } - BLI_array_empty(edges); + BLI_array_clear(edges); count++; } diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index 81ec2860cf7..d52cb00e172 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -521,7 +521,7 @@ static void hull_from_bullet( int j; /* Get face vertex indices */ - BLI_array_empty(fvi); + BLI_array_clear(fvi); BLI_array_grow_items(fvi, len); plConvexHullGetFaceVertices(hull, i, fvi); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 894129b4a33..7d3419b5910 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -1011,8 +1011,8 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) /* figure out which pattern to use */ - BLI_array_empty(edges); - BLI_array_empty(verts); + BLI_array_clear(edges); + BLI_array_clear(verts); BLI_array_grow_items(edges, face->len); BLI_array_grow_items(verts, face->len); @@ -1140,7 +1140,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) face = fd->face; /* figure out which pattern to use */ - BLI_array_empty(verts); + BLI_array_clear(verts); pat = fd->pat; @@ -1148,8 +1148,8 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) int vlen; /* ok, no pattern. we still may be able to do something */ - BLI_array_empty(loops); - BLI_array_empty(loops_split); + BLI_array_clear(loops); + BLI_array_clear(loops_split); /* for case of two edges, connecting them shouldn't be too hard */ BLI_array_grow_items(loops, face->len); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index a18c4405a31..51238c92505 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -3736,7 +3736,7 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i) tryj = bevel_edge_order_extend(bm, bv, j + 1); if (tryj > bestj || (tryj == bestj && edges_face_connected_at_vert(bv->edges[tryj].e, bv->edges[0].e))) { bestj = tryj; - BLI_array_empty(save_path); + BLI_array_clear(save_path); for (k = j + 1; k <= bestj; k++) { BLI_array_append(save_path, bv->edges[k].e); } diff --git a/source/blender/bmesh/tools/bmesh_separate.c b/source/blender/bmesh/tools/bmesh_separate.c index 287b4125330..b3d0c339885 100644 --- a/source/blender/bmesh/tools/bmesh_separate.c +++ b/source/blender/bmesh/tools/bmesh_separate.c @@ -122,7 +122,7 @@ void BM_mesh_separate_faces( /* Perform the split */ BM_face_loop_separate_multi(bm, loop_split.data, loop_split.count); - BLI_buffer_empty(&loop_split); + BLI_buffer_clear(&loop_split); } } while ((l_iter = l_iter->next) != l_first); } -- cgit v1.2.3 From bd9ed0228b8455167a404c11121f0d4d46e4c689 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Mon, 5 Feb 2018 14:21:43 -0500 Subject: Fix bevel profile=1 problems, see T39132, T38458, T40278, T51010, T53783. Before, profile=1 ("square outside") only worked well in a few cases (some "pipes", cube corners). This makes it work well pretty much everywhere. --- source/blender/bmesh/tools/bmesh_bevel.c | 174 ++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 2 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 51238c92505..e89f54349f7 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -2170,7 +2170,6 @@ static void adjust_offsets(BevelParams *bp) v->visited = true; if (vnext->visited) { if (vnext != vchainstart) { - printf("WHOOPS, adjusting offsets, expected cycle!\n"); break; } adjust_the_cycle_or_chain(vchainstart, true); @@ -3187,6 +3186,173 @@ static void build_square_in_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv, VMesh } } +/* copy whichever of a and b is closer to v into r */ +static void closer_v3_v3v3v3(float r[3], float a[3], float b[3], float v[3]) +{ + if (len_squared_v3v3(a, v) <= len_squared_v3v3(b, v)) + copy_v3_v3(r, a); + else + copy_v3_v3(r, b); +} + +/* Special case of VMesh when profile == 1 and there are 3 or more beveled edges. + * We want the effect of parallel offset lines (n/2 of them) on each side of the center, for even n. + * Wherever they intersect with each other between two successive beveled edges, those intersections + * are part of the vmesh rings. + * We have to move the boundary edges too -- the usual method is to make one profile plane between + * successive BoundVerts, but for the effect we want here, there will be two planes, one on each side + * of the original edge. + */ +static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv) +{ + int n, ns, ns2, odd, i, j, k, ikind, im1, clstride; + float bndco[3], dir1[3], dir2[3], co1[3], co2[3], meet1[3], meet2[3], v1co[3], v2co[3]; + float *on_edge_cur, *on_edge_prev, *p; + float ns2inv, finalfrac, ang; + BoundVert *bndv; + EdgeHalf *e1, *e2; + VMesh *vm; + float *centerline; + + n = bv->vmesh->count; + ns = bv->vmesh->seg; + ns2 = ns / 2; + odd = ns % 2; + ns2inv = 1.0f / (float) ns2; + vm = new_adj_vmesh(bp->mem_arena, n, ns, bv->vmesh->boundstart); + clstride = 3 * (ns2 + 1); + centerline = MEM_mallocN(clstride * n * sizeof(float), "bevel"); + + /* find on_edge, place on bndv[i]'s elast where offset line would meet, + * averaging with position where next sector's offset line would meet */ + bndv = vm->boundstart; + for (i = 0; i < n; i++) { + copy_v3_v3(bndco, bndv->nv.co); + e1 = bndv->efirst; + e2 = bndv->elast; + sub_v3_v3v3(dir1, e1->e->v1->co, e1->e->v2->co); + sub_v3_v3v3(dir2, e2->e->v1->co, e2->e->v2->co); + add_v3_v3v3(co1, bndco, dir1); + add_v3_v3v3(co2, bndco, dir2); + /* intersect e1 with line through bndv parallel to e2 to get v1co */ + ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, bndco, co2, meet1, meet2); + + if (ikind == 0) { + /* Placeholder: this should get eliminated by min dist test with adjacent edge */ + mid_v3_v3v3(v1co, e1->e->v1->co, e1->e->v2->co); + } + else { + /* if the lines are skew (ikind == 2), want meet1 which is on e1 */ + copy_v3_v3(v1co, meet1); + } + /* intersect e2 with line through bndv parallel to e1 to get v2co */ + ikind = isect_line_line_v3(e2->e->v1->co, e2->e->v2->co, bndco, co1, meet1, meet2); + if (ikind == 0) { + mid_v3_v3v3(v2co, e2->e->v1->co, e2->e->v2->co); + } + else { + copy_v3_v3(v2co, meet1); + } + + /* want on_edge[i] to be min dist to bv->v of v2co and the v1co of next iteration */ + on_edge_cur = centerline + clstride * i; + on_edge_prev = centerline + clstride * ((i == 0) ? n - 1 : i - 1); + if (i == 0) { + copy_v3_v3(on_edge_cur, v2co); + copy_v3_v3(on_edge_prev, v1co); + } + else if (i == n - 1) { + closer_v3_v3v3v3(on_edge_cur, on_edge_cur, v2co, bv->v->co); + closer_v3_v3v3v3(on_edge_prev, on_edge_prev, v1co, bv->v->co); + } + else { + copy_v3_v3(on_edge_cur, v2co); + closer_v3_v3v3v3(on_edge_prev, on_edge_prev, v1co, bv->v->co); + } + bndv = bndv->next; + } + + /* fill in rest of centerlines by interpolation */ + copy_v3_v3(co2, bv->v->co); + bndv = vm->boundstart; + for (i = 0; i < n; i++) { + if (odd) { + ang = 0.5f * angle_v3v3v3(bndv->nv.co, co1, bndv->next->nv.co); + if (ang > BEVEL_SMALL_ANG) { + /* finalfrac is length along arms of isoceles triangle with top angle 2*ang + * such that the base of the triangle is 1. + * This is used in interpolation along centerline in odd case. + * To avoid too big a drop from bv, cap finalfrac a 0.8 arbitrarily */ + finalfrac = 0.5f / sin(ang); + if (finalfrac > 0.8f) + finalfrac = 0.8f; + } + else { + finalfrac = 0.8f; + } + ns2inv = 1.0f / (ns2 + finalfrac); + } + + p = centerline + clstride * i; + copy_v3_v3(co1, p); + p += 3; + for (j = 1; j <= ns2; j++) { + interp_v3_v3v3(p, co1, co2, j * ns2inv); + p += 3; + } + bndv = bndv->next; + } + + /* coords of edges and mid or near-mid line */ + bndv = vm->boundstart; + for (i = 0; i < n; i++) { + copy_v3_v3(co1, bndv->nv.co); + copy_v3_v3(co2, centerline + clstride * (i == 0 ? n - 1 : i - 1)); + for (j = 0; j < ns2 + odd; j++) { + interp_v3_v3v3(mesh_vert(vm, i, j, 0)->co, co1, co2, j * ns2inv); + } + copy_v3_v3(co2, centerline + clstride * i); + for (k = 1; k <= ns2; k++) { + interp_v3_v3v3(mesh_vert(vm, i, 0, k)->co, co1, co2, k * ns2inv); + } + bndv = bndv->next; + } + if (!odd) + copy_v3_v3(mesh_vert(vm, 0, ns2, ns2)->co, bv->v->co); + vmesh_copy_equiv_verts(vm); + + /* fill in interior points by interpolation from edges to centerlines */ + bndv = vm->boundstart; + for (i = 0; i < n; i++) { + im1 = (i == 0) ? n - 1 : i - 1; + for (j = 1; j < ns2 + odd; j++) { + for (k = 1; k <= ns2; k++) { + ikind = isect_line_line_v3( + mesh_vert(vm, i, 0, k)->co, centerline + clstride * im1 + 3 * k, + mesh_vert(vm, i, j, 0)->co, centerline + clstride * i + 3 * j, + meet1, meet2); + if (ikind == 0) { + /* how can this happen? fall back on interpolation in one direction if it does */ + interp_v3_v3v3(mesh_vert(vm, i, j, k)->co, + mesh_vert(vm, i, 0, k)->co, centerline + clstride * im1 + 3 * k, j * ns2inv); + } + else if (ikind == 1) { + copy_v3_v3(mesh_vert(vm, i, j, k)->co, meet1); + } + else { + mid_v3_v3v3(mesh_vert(vm, i, j, k)->co, meet1, meet2); + } + } + } + bndv = bndv->next; + } + + vmesh_copy_equiv_verts(vm); + + MEM_freeN(centerline); + return vm; +} + /* * 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 pattern, @@ -3209,9 +3375,13 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv) odd = ns % 2; BLI_assert(n >= 3 && ns > 1); + vpipe = pipe_test(bv); - if (vpipe) { + if (bp->pro_super_r == PRO_SQUARE_R && bv->selcount >= 3 && !odd) { + vm1 = square_out_adj_vmesh(bp, bv); + } + else if (vpipe) { vm1 = pipe_adj_vmesh(bp, bv, vpipe); } else if (tri_corner_test(bp, bv)) { -- cgit v1.2.3 From 345c6298e995ea618c34282ba6d7ab5af032f191 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Feb 2018 21:14:26 +1100 Subject: Object Mode: move to workspace struct - Read-only access can often use EvaluationContext.object_mode - Write access to go to WorkSpace.object_mode. - Some TODO's remain (marked as "TODO/OBMODE") - Add-ons will need updating (context.active_object.mode -> context.workspace.object_mode) - There will be small/medium issues that still need resolving this does work on a basic level though. See D3037 --- source/blender/bmesh/intern/bmesh_mesh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 67db51446df..8533083af22 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -1019,7 +1019,8 @@ void BM_loops_calc_normal_vcos( } } -static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from, int to) +static void UNUSED_FUNCTION(bm_mdisps_space_set)( + Object *ob, BMesh *bm, int from, int to, eObjectMode object_mode) { /* switch multires data out of tangent space */ if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) { @@ -1030,7 +1031,7 @@ static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from BMIter iter; // int i = 0; // UNUSED - multires_set_space(dm, ob, from, to); + multires_set_space(dm, ob, from, to, object_mode); mdisps = CustomData_get_layer(&dm->loopData, CD_MDISPS); -- cgit v1.2.3 From f088c6b9f6d69e7f1af15a059f122589ee6a39ab Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Feb 2018 23:38:17 +1100 Subject: Mesh: concave quad support Previously quads always split along first-third vertices. This is still the default, to avoid flickering with animated deformation however concave quads that would create two opposing triangles now use second-fourth split. Reported as T53999 although this issue has been known limitation for a long time. --- source/blender/bmesh/intern/bmesh_polygon.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 66fcd739839..66d0a83eb9f 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -1426,6 +1426,17 @@ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptri (l_ptr_a[2] = l_ptr_b[1] = l = l->next); ( l_ptr_b[2] = l->next); #endif + + if (UNLIKELY(is_quad_flip_v3_first_third_fast( + l_ptr_a[0]->v->co, + l_ptr_a[1]->v->co, + l_ptr_a[2]->v->co, + l_ptr_b[2]->v->co))) + { + /* flip out of degenerate 0-2 state. */ + l_ptr_a[2] = l_ptr_b[2]; + l_ptr_b[0] = l_ptr_a[1]; + } } #endif /* USE_TESSFACE_SPEEDUP */ -- cgit v1.2.3 From d3248bb50bf9f8f6aae6292e76ae1ed27dff159d Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Thu, 8 Feb 2018 10:48:24 -0500 Subject: Disable fast adjust code. Add other end spec matching. This fixes a few caess where new width adjustment code was less than ideal. --- source/blender/bmesh/tools/bmesh_bevel.c | 99 ++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 16 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index e89f54349f7..beee9065ece 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1879,7 +1879,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) } } -#if 0 +#ifdef DEBUG_ADJUST static void print_adjust_stats(BoundVert *vstart) { BoundVert *v; @@ -1921,21 +1921,25 @@ static void print_adjust_stats(BoundVert *vstart) if (v->adjchain != NULL) { eright = v->efirst; eleft = v->adjchain->elast; - delta = fabs(eright->offset_r - eright->offset_r_spec); + delta = eright->offset_r - eright->offset_r_spec; delta_pct = 100.0 * delta / eright->offset_r_spec; - printf("e%d r(%f) vs r spec(%f): abs(delta)=%f, delta_pct=%f\n", + printf("e%d r(%f) vs r spec(%f): delta=%f, delta_pct=%f\n", BM_elem_index_get(eright->e), eright->offset_r, eright->offset_r_spec, delta, delta_pct); spec_residual2 += delta * delta; + delta = fabs(delta); + delta_pct = fabs(delta_pct); if (delta > max_spec_r) max_spec_r = delta; if (delta_pct > max_spec_r_pct) max_spec_r_pct = delta_pct; - delta = fabs(eleft->offset_l - eleft->offset_l_spec); + delta = eleft->offset_l - eleft->offset_l_spec; delta_pct = 100.0 * delta / eright->offset_l_spec; - printf("e%d l(%f) vs l spec(%f): abs(delta)=%f, delta_pct=%f\n", + printf("e%d l(%f) vs l spec(%f): delta=%f, delta_pct=%f\n", BM_elem_index_get(eright->e), eleft->offset_l, eleft->offset_l_spec, delta, delta_pct); spec_residual2 += delta * delta; + delta = fabs(delta); + delta_pct = fabs(delta_pct); if (delta > max_spec_r) max_spec_r = delta; if (delta_pct > max_spec_r_pct) @@ -1951,6 +1955,15 @@ static void print_adjust_stats(BoundVert *vstart) } #endif +#ifdef FAST_ADJUST_CODE +/* This code uses a direct solution to the adjustment problem for chains and certain cycles. + * It is a two-step approach: first solve for the exact solution of the 'match widths' constraints + * using the one degree of freedom that allows for expressing all other widths in terms of that. + * And then minimize the spec-matching constraints using the derivative of the least squares + * residual in terms of that one degree of freedom. + * Unfortunately, the results are in some cases worse than the general least squares solution + * for the combined (with weights) problem, so this code is not used. + * But keep it here for a while in case peformance issues demand that it be used sometimes. */ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscycle) { BoundVert *v; @@ -2027,6 +2040,7 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc MEM_freeN(g_prod); return true; } +#endif /* Adjust the offsets for a single cycle or chain. * For chains and some cycles, a fast solution exists. @@ -2038,22 +2052,35 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle) { BoundVert *v; - EdgeHalf *eleft, *eright; + EdgeHalf *eleft, *eright, *enextleft; LinearSolver *solver; double weight, val; int i, np, nrows, row; np = 0; +#ifdef DEBUG_ADJUST + printf("\nadjust the %s (with eigen)\n", iscycle ? "cycle" : "chain"); +#endif v = vstart; do { +#ifdef DEBUG_ADJUST + eleft = v->elast; + eright = v->efirst; + printf(" (left=e%d, right=e%d)", BM_elem_index_get(eleft->e), BM_elem_index_get(eright->e)); +#endif np++; v = v->adjchain; } while (v && v != vstart); +#ifdef DEBUG_ADJUST + printf(" -> %d parms\n", np); +#endif +#ifdef FAST_ADJUST_CODE if (adjust_the_cycle_or_chain_fast(vstart, np, iscycle)) return; +#endif - nrows = iscycle ? 2 * np : 2 * np - 1; + nrows = iscycle ? 3 * np : 3 * np - 3; solver = EIG_linear_least_squares_solver_new(nrows, np, 1); @@ -2062,9 +2089,15 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle) weight = BEVEL_MATCH_SPEC_WEIGHT; /* sqrt of factor to weight down importance of spec match */ do { /* except at end of chain, v's indep variable is offset_r of v->efirst */ - if (iscycle || v->adjchain != NULL) { + if (iscycle || i < np - 1) { eright = v->efirst; eleft = v->elast; + enextleft = v->adjchain->elast; +#ifdef DEBUG_ADJUST + printf("p%d: e%d->offset_r = %f\n", i, BM_elem_index_get(eright->e), eright->offset_r); + if (iscycle || v != vstart) + printf(" dependent: e%d->offset_l = %f * p%d\n", BM_elem_index_get(eleft->e), v->sinratio, i); +#endif /* residue i: width difference between eright and eleft of next */ EIG_linear_solver_matrix_add(solver, i, i, 1.0); @@ -2073,53 +2106,87 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle) EIG_linear_solver_matrix_add(solver, i > 0 ? i - 1 : np - 1, i, -v->sinratio); } else { - if (i > 0) + if (i > 0) { EIG_linear_solver_matrix_add(solver, i - 1, i, -v->sinratio); + } } - /* residue np + i (if cycle) else np - 1 + i: + /* residue np + 2*i (if cycle) else np - 1 + 2*i: * right offset for parm i matches its spec; weighted */ - row = iscycle ? np + i : np - 1 + i; + row = iscycle ? np + 2 * i : np - 1 + 2 * i; EIG_linear_solver_matrix_add(solver, row, i, weight); EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eright->offset_r); +#ifdef DEBUG_ADJUST + printf("b[%d]=%f * %f, for e%d->offset_r\n", row, weight, eright->offset_r, BM_elem_index_get(eright->e)); +#endif + + /* residue np + 2*i + 1 (if cycle) else np - 1 + 2*i + 1: + * left offset for parm i matches its spec; weighted */ + row = row + 1; + EIG_linear_solver_matrix_add(solver, row, (i == np - 1) ? 0 : i + 1, weight * v->adjchain->sinratio); + EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * enextleft->offset_l); +#ifdef DEBUG_ADJUST + printf("b[%d]=%f * %f, for e%d->offset_l\n", row, weight, enextleft->offset_l, + BM_elem_index_get(enextleft->e)); +#endif } else { /* not a cycle, and last of chain */ eleft = v->elast; +#ifdef DEBUG_ADJUST + printf("p%d: e%d->offset_l = %f\n", i, BM_elem_index_get(eleft->e), eleft->offset_l); +#endif /* second part of residue i for last i */ EIG_linear_solver_matrix_add(solver, i - 1, i, -1.0); - /* residue 2 * np -2 : last spec match residue is for left offset of final parm */ - row = 2 * np - 2; - EIG_linear_solver_matrix_add(solver, row, i, weight); - EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eleft->offset_l); } i++; v = v->adjchain; } while (v && v != vstart); EIG_linear_solver_solve(solver); +#ifdef DEBUG_ADJUST + /* Note: this print only works after solve, but by that time b has been cleared */ + EIG_linear_solver_print_matrix(solver); + printf("\nSolution:\n"); + for (i = 0; i < np; i++) + printf("p%d = %f\n", i, EIG_linear_solver_variable_get(solver, 0, i)); +#endif /* Use the solution to set new widths */ v = vstart; i = 0; do { val = EIG_linear_solver_variable_get(solver, 0, i); - if (iscycle || v->adjchain != NULL) { + if (iscycle || i < np - 1) { eright = v->efirst; eleft = v->elast; eright->offset_r = (float)val; +#ifdef DEBUG_ADJUST + printf("e%d->offset_r = %f\n", BM_elem_index_get(eright->e), eright->offset_r); +#endif if (iscycle || v != vstart) { eleft->offset_l = (float)(v->sinratio * val); +#ifdef DEBUG_ADJUST + printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l); +#endif } } else { /* not a cycle, and last of chain */ eleft = v->elast; eleft->offset_l = (float)val; +#ifdef DEBUG_ADJUST + printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l); +#endif } i++; v = v->adjchain; } while (v && v != vstart); +#ifdef DEBUG_ADJUST + print_adjust_stats(vstart); + EIG_linear_solver_print_matrix(solver); +#endif + EIG_linear_solver_delete(solver); } -- cgit v1.2.3 From 56fa48969e13bf54fc7f64e03cccf6ac82624b15 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 15 Feb 2018 10:48:12 +1100 Subject: Fix T54072: Crash splitting edges --- source/blender/bmesh/intern/bmesh_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 36b2f9cadf7..aba0160622f 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2423,9 +2423,10 @@ static void bmesh_kernel_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separ /* don't visit again */ n_prev->next = n_step->next; } - } while ((void) - (n_prev = n_step), - (n_step = n_step->next)); + else { + n_prev = n_step; + } + } while ((n_step = n_step->next)); } while ((n_orig = n_orig->next) && n_orig->next); } while ((edges_separate = edges_separate->next)); -- cgit v1.2.3 From ccdacf1c9b31b15e188aa9e9adb044ffd0ca0da4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 15 Feb 2018 23:36:11 +1100 Subject: Cleanup: use '_len' instead of '_size' w/ BLI API - When returning the number of items in a collection use BLI_*_len() - Keep _size() for size in bytes. - Keep _count() for data structures that don't store length (hint this isn't a simple getter). See P611 to apply instead of manually resolving conflicts. --- source/blender/bmesh/intern/bmesh_iterators.c | 4 ++-- source/blender/bmesh/intern/bmesh_log.c | 4 ++-- source/blender/bmesh/intern/bmesh_operators.c | 2 +- source/blender/bmesh/operators/bmo_connect_pair.c | 4 ++-- source/blender/bmesh/operators/bmo_rotate_edges.c | 2 +- source/blender/bmesh/operators/bmo_subdivide_edgering.c | 4 ++-- source/blender/bmesh/operators/bmo_triangulate.c | 2 +- source/blender/bmesh/tools/bmesh_beautify.c | 2 +- source/blender/bmesh/tools/bmesh_decimate_collapse.c | 4 ++-- source/blender/bmesh/tools/bmesh_edgenet.c | 4 ++-- source/blender/bmesh/tools/bmesh_intersect.c | 6 +++--- source/blender/bmesh/tools/bmesh_path.c | 6 +++--- source/blender/bmesh/tools/bmesh_region_match.c | 14 +++++++------- 13 files changed, 29 insertions(+), 29 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 96154f051f9..9fe28561b93 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -430,7 +430,7 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const void bmiter__elem_of_mesh_begin(struct BMIter__elem_of_mesh *iter) { #ifdef USE_IMMUTABLE_ASSERT - ((BMIter *)iter)->count = BLI_mempool_count(iter->pooliter.pool); + ((BMIter *)iter)->count = BLI_mempool_len(iter->pooliter.pool); #endif BLI_mempool_iternew(iter->pooliter.pool, &iter->pooliter); } @@ -438,7 +438,7 @@ void bmiter__elem_of_mesh_begin(struct BMIter__elem_of_mesh *iter) void *bmiter__elem_of_mesh_step(struct BMIter__elem_of_mesh *iter) { #ifdef USE_IMMUTABLE_ASSERT - BLI_assert(((BMIter *)iter)->count <= BLI_mempool_count(iter->pooliter.pool)); + BLI_assert(((BMIter *)iter)->count <= BLI_mempool_len(iter->pooliter.pool)); #endif return BLI_mempool_iterstep(&iter->pooliter); } diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 1d16dbc1836..5ae72851c7e 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -990,11 +990,11 @@ void BM_log_all_added(BMesh *bm, BMLog *log) BMFace *f; /* avoid unnecessary resizing on initialization */ - if (BLI_ghash_size(log->current_entry->added_verts) == 0) { + if (BLI_ghash_len(log->current_entry->added_verts) == 0) { BLI_ghash_reserve(log->current_entry->added_verts, (uint)bm->totvert); } - if (BLI_ghash_size(log->current_entry->added_faces) == 0) { + if (BLI_ghash_len(log->current_entry->added_faces) == 0) { BLI_ghash_reserve(log->current_entry->added_faces, (uint)bm->totface); } diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 0f672a9ff2a..f814767a200 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -673,7 +673,7 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); - return BLI_ghash_size(slot->data.ghash); + return BLI_ghash_len(slot->data.ghash); } /* inserts a key/value mapping into a mapping slot. note that it copies the diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c index 60fd9808fcb..b9e5cd927c3 100644 --- a/source/blender/bmesh/operators/bmo_connect_pair.c +++ b/source/blender/bmesh/operators/bmo_connect_pair.c @@ -662,11 +662,11 @@ void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op) while (!BLI_heap_is_empty(pc.states)) { #ifdef DEBUG_PRINT - printf("\n%s: stepping %u\n", __func__, BLI_heap_size(pc.states)); + printf("\n%s: stepping %u\n", __func__, BLI_heap_len(pc.states)); #endif while (!BLI_heap_is_empty(pc.states)) { - PathLinkState *state = BLI_heap_popmin(pc.states); + PathLinkState *state = BLI_heap_pop_min(pc.states); /* either we insert this into 'pc.states' or its freed */ bool continue_search; diff --git a/source/blender/bmesh/operators/bmo_rotate_edges.c b/source/blender/bmesh/operators/bmo_rotate_edges.c index 9832fdb57d3..75e31c68dae 100644 --- a/source/blender/bmesh/operators/bmo_rotate_edges.c +++ b/source/blender/bmesh/operators/bmo_rotate_edges.c @@ -180,7 +180,7 @@ static void bm_rotate_edges_shared( const int edges_len_rotate_prev = edges_len_rotate; while (!BLI_heap_is_empty(heap)) { - BMEdge *e_best = BLI_heap_popmin(heap); + BMEdge *e_best = BLI_heap_pop_min(heap); eheap_table[BM_elem_index_get(e_best)] = NULL; /* No problem if this fails, re-evaluate if faces connected to this edge are touched. */ diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c index adcc0c71629..e6881f6d8b1 100644 --- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c +++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c @@ -269,7 +269,7 @@ static GSet *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim) BLI_ghash_free(vert_eloop_gh, NULL, NULL); - if (BLI_gset_size(eloop_pair_gs) == 0) { + if (BLI_gset_len(eloop_pair_gs) == 0) { BLI_gset_free(eloop_pair_gs, NULL); eloop_pair_gs = NULL; } @@ -1193,7 +1193,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op) goto cleanup; } - lpair_arr = BLI_array_alloca(lpair_arr, BLI_gset_size(eloop_pairs_gs)); + lpair_arr = BLI_array_alloca(lpair_arr, BLI_gset_len(eloop_pairs_gs)); /* first cache pairs */ GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) { diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index 4e8bace59e0..2cdc2646649 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -106,7 +106,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) /* sf_edge = */ BLI_scanfill_edge_add(&sf_ctx, UNPACK2(sf_verts)); /* sf_edge->tmp.p = e; */ /* UNUSED */ } - nors_tot = BLI_ghash_size(sf_vert_map); + nors_tot = BLI_ghash_len(sf_vert_map); BLI_ghash_free(sf_vert_map, NULL, NULL); diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c index 6e6242fc9f9..81f0b4822a2 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.c +++ b/source/blender/bmesh/tools/bmesh_beautify.c @@ -392,7 +392,7 @@ void BM_mesh_beautify_fill( bm->elem_index_dirty |= BM_EDGE; while (BLI_heap_is_empty(eheap) == false) { - BMEdge *e = BLI_heap_popmin(eheap); + BMEdge *e = BLI_heap_pop_min(eheap); i = BM_elem_index_get(e); eheap_table[i] = NULL; diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 0a1271c2aa9..3aa9e5278bc 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -1357,7 +1357,7 @@ void BM_mesh_decimate_collapse( (BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID)) { // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); - BMEdge *e = BLI_heap_popmin(eheap); + BMEdge *e = BLI_heap_pop_min(eheap); float optimize_co[3]; BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */ @@ -1388,7 +1388,7 @@ void BM_mesh_decimate_collapse( * - edges sharing a vertex are ignored, so the pivot vertex isnt moved to one side. */ - BMEdge *e = BLI_heap_popmin(eheap); + BMEdge *e = BLI_heap_pop_min(eheap); const int e_index = BM_elem_index_get(e); const int e_index_mirr = edge_symmetry_map[e_index]; BMEdge *e_mirr = NULL; diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c index 193a032b46e..df9d07036af 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.c +++ b/source/blender/bmesh/tools/bmesh_edgenet.c @@ -335,7 +335,7 @@ static LinkNode *bm_edgenet_path_calc( BLI_linklist_free_pool(v_ls_next, NULL, path_pool); BLI_linklist_free_pool(v_ls_prev, NULL, path_pool); - // BLI_assert(BLI_mempool_count(path_pool) == 0); + // BLI_assert(BLI_mempool_len(path_pool) == 0); path_len = bm_edgenet_path_from_pass(e_found->v1, &path, vnet_info, path_pool); BLI_linklist_reverse(&path); @@ -505,7 +505,7 @@ void BM_mesh_edgenet( } BLI_linklist_free_pool(path, NULL, path_pool); - BLI_assert(BLI_mempool_count(path_pool) == 0); + BLI_assert(BLI_mempool_len(path_pool) == 0); } bm->elem_index_dirty |= BM_FACE | BM_LOOP; diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index 9d1b20cb4d2..acadb663810 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1275,8 +1275,8 @@ bool BM_mesh_intersect( } } - splice_ls = MEM_mallocN(BLI_gset_size(s.wire_edges) * sizeof(*splice_ls), __func__); - STACK_INIT(splice_ls, BLI_gset_size(s.wire_edges)); + splice_ls = MEM_mallocN(BLI_gset_len(s.wire_edges) * sizeof(*splice_ls), __func__); + STACK_INIT(splice_ls, BLI_gset_len(s.wire_edges)); for (node = s.vert_dissolve; node; node = node->next) { BMEdge *e_pair[2]; @@ -1690,7 +1690,7 @@ bool BM_mesh_intersect( } } - has_edit_isect = (BLI_ghash_size(s.face_edges) != 0); + has_edit_isect = (BLI_ghash_len(s.face_edges) != 0); /* cleanup */ BLI_ghash_free(s.edgetri_cache, NULL, NULL); diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c index 85c591b6684..cc5ac6dd8ce 100644 --- a/source/blender/bmesh/tools/bmesh_path.c +++ b/source/blender/bmesh/tools/bmesh_path.c @@ -174,7 +174,7 @@ LinkNode *BM_mesh_calc_path_vert( cost[BM_elem_index_get(v_src)] = 0.0f; while (!BLI_heap_is_empty(heap)) { - v = BLI_heap_popmin(heap); + v = BLI_heap_pop_min(heap); if (v == v_dst) break; @@ -346,7 +346,7 @@ LinkNode *BM_mesh_calc_path_edge( cost[BM_elem_index_get(e_src)] = 0.0f; while (!BLI_heap_is_empty(heap)) { - e = BLI_heap_popmin(heap); + e = BLI_heap_pop_min(heap); if (e == e_dst) break; @@ -532,7 +532,7 @@ LinkNode *BM_mesh_calc_path_face( cost[BM_elem_index_get(f_src)] = 0.0f; while (!BLI_heap_is_empty(heap)) { - f = BLI_heap_popmin(heap); + f = BLI_heap_pop_min(heap); if (f == f_dst) break; diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index 2abf8f2c46e..e83ba73ad01 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -421,8 +421,8 @@ static void bm_uuidwalk_rehash( UUID_Int *uuid_store; uint i; - uint rehash_store_len_new = MAX2(BLI_ghash_size(uuidwalk->verts_uuid), - BLI_ghash_size(uuidwalk->faces_uuid)); + uint rehash_store_len_new = MAX2(BLI_ghash_len(uuidwalk->verts_uuid), + BLI_ghash_len(uuidwalk->faces_uuid)); bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new); uuid_store = uuidwalk->cache.rehash_store; @@ -520,8 +520,8 @@ static void bm_uuidwalk_pass_add( verts_uuid_pass = uuidwalk->cache.verts_uuid; faces_step_next = uuidwalk->cache.faces_step; - BLI_assert(BLI_ghash_size(verts_uuid_pass) == 0); - BLI_assert(BLI_gset_size(faces_step_next) == 0); + BLI_assert(BLI_ghash_len(verts_uuid_pass) == 0); + BLI_assert(BLI_gset_len(faces_step_next) == 0); /* Add the face_step data from connected faces, creating new passes */ fstep = BLI_mempool_alloc(uuidwalk->step_pool); @@ -659,7 +659,7 @@ static bool bm_uuidwalk_facestep_begin( LinkNode *f_link, *f_link_next, **f_link_prev_p; bool ok = false; - BLI_assert(BLI_ghash_size(uuidwalk->cache.faces_from_uuid) == 0); + BLI_assert(BLI_ghash_len(uuidwalk->cache.faces_from_uuid) == 0); BLI_assert(BLI_listbase_is_empty(&fstep->items)); f_link_prev_p = &fstep->faces; @@ -864,7 +864,7 @@ static BMFace **bm_mesh_region_match_pair( break; } - found = (BLI_ghash_size(w_dst->faces_uuid) == faces_src_region_len); + found = (BLI_ghash_len(w_dst->faces_uuid) == faces_src_region_len); if (found) { break; } @@ -877,7 +877,7 @@ static BMFace **bm_mesh_region_match_pair( if (found) { GHashIterator gh_iter; - const uint faces_result_len = BLI_ghash_size(w_dst->faces_uuid); + const uint faces_result_len = BLI_ghash_len(w_dst->faces_uuid); uint i; faces_result = MEM_mallocN(sizeof(*faces_result) * (faces_result_len + 1), __func__); -- cgit v1.2.3 From deacb3d6b816afe9f86f51b00043821829fb550e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 18 Feb 2018 21:27:33 +1100 Subject: Cleanup: add 2d suffix to BLI files Some of these API's can have 3D versions, explicitly name them 2D. --- source/blender/bmesh/intern/bmesh_polygon.c | 4 ++-- source/blender/bmesh/operators/bmo_connect_concave.c | 4 ++-- source/blender/bmesh/tools/bmesh_beautify.c | 2 +- source/blender/bmesh/tools/bmesh_decimate_collapse.c | 4 ++-- source/blender/bmesh/tools/bmesh_triangulate.c | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 66d0a83eb9f..bcb940f8b96 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -36,8 +36,8 @@ #include "BLI_alloca.h" #include "BLI_math.h" #include "BLI_memarena.h" -#include "BLI_polyfill2d.h" -#include "BLI_polyfill2d_beautify.h" +#include "BLI_polyfill_2d.h" +#include "BLI_polyfill_2d_beautify.h" #include "BLI_linklist.h" #include "BLI_edgehash.h" #include "BLI_heap.h" diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c index 80774323d31..d1811ac6a83 100644 --- a/source/blender/bmesh/operators/bmo_connect_concave.c +++ b/source/blender/bmesh/operators/bmo_connect_concave.c @@ -39,8 +39,8 @@ #include "BLI_alloca.h" #include "BLI_memarena.h" #include "BLI_heap.h" -#include "BLI_polyfill2d.h" -#include "BLI_polyfill2d_beautify.h" +#include "BLI_polyfill_2d.h" +#include "BLI_polyfill_2d_beautify.h" #include "BLI_linklist.h" #include "bmesh.h" diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c index 81f0b4822a2..d3972363bb4 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.c +++ b/source/blender/bmesh/tools/bmesh_beautify.c @@ -37,7 +37,7 @@ #include "BLI_math.h" #include "BLI_heap.h" -#include "BLI_polyfill2d_beautify.h" +#include "BLI_polyfill_2d_beautify.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 3aa9e5278bc..c1b2bc2625b 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -38,8 +38,8 @@ #include "BLI_alloca.h" #include "BLI_memarena.h" #include "BLI_edgehash.h" -#include "BLI_polyfill2d.h" -#include "BLI_polyfill2d_beautify.h" +#include "BLI_polyfill_2d.h" +#include "BLI_polyfill_2d_beautify.h" #include "BLI_utildefines_stack.h" diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c index bd201fa89bf..a3a3355d20f 100644 --- a/source/blender/bmesh/tools/bmesh_triangulate.c +++ b/source/blender/bmesh/tools/bmesh_triangulate.c @@ -38,8 +38,8 @@ #include "BLI_linklist.h" /* only for defines */ -#include "BLI_polyfill2d.h" -#include "BLI_polyfill2d_beautify.h" +#include "BLI_polyfill_2d.h" +#include "BLI_polyfill_2d_beautify.h" #include "bmesh.h" -- cgit v1.2.3 From 05f3e245a8e1a1ad327c6dc993551cdd832d4e3c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 19 Feb 2018 17:27:01 +1100 Subject: Fix T54098: Crash existing /w dyntopo sculpt Optionally don't remap indices for objects. Checking all objects parent's would reference a freed pointer while freeing all objects. In the case of dynamic topology there is no use in keeping track of hook/vertex-parent indices. Also disable this when creating meshes for undo storage since adding an undo step shouldn't be modifying other objects. --- source/blender/bmesh/intern/bmesh_mesh_conv.c | 2 +- source/blender/bmesh/intern/bmesh_mesh_conv.h | 2 ++ source/blender/bmesh/operators/bmo_mesh_conv.c | 7 ++++++- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 7787d704b59..4b86ac03d7f 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -751,7 +751,7 @@ void BM_mesh_bm_to_me( } /* patch hook indices and vertex parents */ - if (ototvert > 0) { + if (params->calc_object_remap && (ototvert > 0)) { Object *ob; ModifierData *md; BMVert **vertMap = NULL; diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index 1974d364171..e6072f7b5f2 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -56,6 +56,8 @@ ATTR_NONNULL(1, 3); struct BMeshToMeshParams { uint calc_tessface : 1; + /** Update object hook indices & vertex parents. */ + uint calc_object_remap : 1; int64_t cd_mask_extra; }; void BM_mesh_bm_to_me( diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c index 0eb9bf90ca8..981930705b3 100644 --- a/source/blender/bmesh/operators/bmo_mesh_conv.c +++ b/source/blender/bmesh/operators/bmo_mesh_conv.c @@ -72,5 +72,10 @@ void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) /* Object *ob = BMO_slot_ptr_get(op, "object"); */ const bool dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface"); - BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){ .calc_tessface = dotess, })); + BM_mesh_bm_to_me( + bm, me, + (&(struct BMeshToMeshParams){ + .calc_tessface = dotess, + .calc_object_remap = true, + })); } -- cgit v1.2.3 From 860939ccc2c11f0503588d35e2b23326997c9768 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 19 Feb 2018 17:41:37 +1100 Subject: Cleanup: remove BMeshToMeshParams.calc_tessface This wasn't used, tessface is being phased out. Caller can run explicitly if needed. --- source/blender/bmesh/intern/bmesh_mesh_conv.c | 6 +----- source/blender/bmesh/intern/bmesh_mesh_conv.h | 1 - source/blender/bmesh/intern/bmesh_opdefines.c | 1 - source/blender/bmesh/operators/bmo_mesh_conv.c | 6 ++---- 4 files changed, 3 insertions(+), 11 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 4b86ac03d7f..474b4656a68 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -808,11 +808,7 @@ void BM_mesh_bm_to_me( if (vertMap) MEM_freeN(vertMap); } - if (params->calc_tessface) { - BKE_mesh_tessface_calc(me); - } - - BKE_mesh_update_customdata_pointers(me, params->calc_tessface); + BKE_mesh_update_customdata_pointers(me, false); { BMEditSelection *selected; diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index e6072f7b5f2..6e9d62349ea 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -55,7 +55,6 @@ void BM_mesh_bm_from_me( ATTR_NONNULL(1, 3); struct BMeshToMeshParams { - uint calc_tessface : 1; /** Update object hook indices & vertex parents. */ uint calc_object_remap : 1; int64_t cd_mask_extra; diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 8e0e905cf88..4847ae4be42 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -843,7 +843,6 @@ static BMOpDefine bmo_bmesh_to_mesh_def = { {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, /* pointer to an object structure */ {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, - {"skip_tessface", BMO_OP_SLOT_BOOL}, /* don't calculate mfaces */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c index 981930705b3..7311ed5ce64 100644 --- a/source/blender/bmesh/operators/bmo_mesh_conv.c +++ b/source/blender/bmesh/operators/bmo_mesh_conv.c @@ -62,20 +62,18 @@ void bmo_object_load_bmesh_exec(BMesh *bm, BMOperator *op) Mesh *me = ob->data; BMO_op_callf(bm, op->flag, - "bmesh_to_mesh mesh=%p object=%p skip_tessface=%b", - me, ob, true); + "bmesh_to_mesh mesh=%p object=%p", + me, ob); } void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) { Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh"); /* Object *ob = BMO_slot_ptr_get(op, "object"); */ - const bool dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface"); BM_mesh_bm_to_me( bm, me, (&(struct BMeshToMeshParams){ - .calc_tessface = dotess, .calc_object_remap = true, })); } -- cgit v1.2.3 From 4b068c4d6f960e0a4da7e252c1d69743e282362f Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 22 Feb 2018 10:35:08 +0100 Subject: Cleanup: clnor code: more 'do not use same varname for two different things'. --- source/blender/bmesh/intern/bmesh_mesh.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 67db51446df..2eb9c1c6597 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -524,7 +524,7 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (* * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normals_vnos */ static void bm_mesh_edges_sharp_tag( - BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle, + BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], const float split_angle, float (*r_lnos)[3]) { BMIter eiter; @@ -532,10 +532,7 @@ static void bm_mesh_edges_sharp_tag( int i; const bool check_angle = (split_angle < (float)M_PI); - - if (check_angle) { - split_angle = cosf(split_angle); - } + const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f; { char htype = BM_VERT | BM_LOOP; @@ -560,7 +557,7 @@ static void bm_mesh_edges_sharp_tag( if (check_angle) { const float *no_a = fnos ? fnos[BM_elem_index_get(l_a->f)] : l_a->f->no; const float *no_b = fnos ? fnos[BM_elem_index_get(l_b->f)] : l_b->f->no; - is_angle_smooth = (dot_v3v3(no_a, no_b) >= split_angle); + is_angle_smooth = (dot_v3v3(no_a, no_b) >= split_angle_cos); } /* We only tag edges that are *really* smooth: -- cgit v1.2.3 From 0eee776e454f6b78ffa33b2ed8b19c747d8193ec Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 22 Feb 2018 15:00:42 +0100 Subject: Fix (unreported) meshes changing shading when creating empty clnors data. When you were using autosmooth to generate some custom normals, and created empty custom loop normal data, you would go back to an 'all smooth' shading, cancelling some sharp edges generated by the mesh's smooth threshold. Now we will first tag such edges as sharp, such that shading remains the same. This is not crucial in current master, but it is for clnors editing gsoc branch! --- source/blender/bmesh/intern/bmesh_mesh.c | 49 +++++++++++++++++++++++--------- source/blender/bmesh/intern/bmesh_mesh.h | 2 ++ 2 files changed, 38 insertions(+), 13 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 2eb9c1c6597..8d6e7ae5b29 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -524,8 +524,9 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (* * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normals_vnos */ static void bm_mesh_edges_sharp_tag( - BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], const float split_angle, - float (*r_lnos)[3]) + BMesh *bm, + const float (*vnos)[3], const float (*fnos)[3], float (*r_lnos)[3], + const float split_angle, const bool do_sharp_edges_tag) { BMIter eiter; BMEdge *e; @@ -567,20 +568,28 @@ static void bm_mesh_edges_sharp_tag( * and both its faces have compatible (non-flipped) normals, * i.e. both loops on the same edge do not share the same vertex. */ - if (is_angle_smooth && - BM_elem_flag_test(e, BM_ELEM_SMOOTH) && + if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) && BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH) && l_a->v != l_b->v) { - const float *no; - BM_elem_flag_enable(e, BM_ELEM_TAG); - - /* linked vertices might be fully smooth, copy their normals to loop ones. */ - no = vnos ? vnos[BM_elem_index_get(l_a->v)] : l_a->v->no; - copy_v3_v3(r_lnos[BM_elem_index_get(l_a)], no); - no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no; - copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no); + if (is_angle_smooth) { + const float *no; + BM_elem_flag_enable(e, BM_ELEM_TAG); + + /* linked vertices might be fully smooth, copy their normals to loop ones. */ + if (r_lnos) { + no = vnos ? vnos[BM_elem_index_get(l_a->v)] : l_a->v->no; + copy_v3_v3(r_lnos[BM_elem_index_get(l_a)], no); + no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no; + copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no); + } + } + else if (do_sharp_edges_tag) { + /* Note that we do not care about the other sharp-edge cases (sharp poly, non-manifold edge, etc.), + * only tag edge as sharp when it is due to angle threashold. */ + BM_elem_flag_disable(e, BM_ELEM_SMOOTH); + } } } } @@ -1005,7 +1014,7 @@ void BM_loops_calc_normal_vcos( if (use_split_normals) { /* Tag smooth edges and set lnos from vnos when they might be completely smooth... * When using custom loop normals, disable the angle feature! */ - bm_mesh_edges_sharp_tag(bm, vnos, fnos, has_clnors ? (float)M_PI : split_angle, r_lnos); + bm_mesh_edges_sharp_tag(bm, vnos, fnos, r_lnos, has_clnors ? (float)M_PI : split_angle, false); /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */ bm_mesh_loops_calc_normals(bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset); @@ -1016,6 +1025,20 @@ void BM_loops_calc_normal_vcos( } } +/** Define sharp edges as needed to mimic 'autosmooth' from angle threshold. + * + * Used when defining an empty custom loop normals data layer, to keep same shading as with autosmooth! + */ +void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle) +{ + if (split_angle >= (float)M_PI) { + /* Nothing to do! */ + return; + } + + bm_mesh_edges_sharp_tag(bm, NULL, NULL, NULL, split_angle, true); +} + static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from, int to) { /* switch multires data out of tangent space */ diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 01f11f6f942..8326e82af00 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -52,6 +52,8 @@ void BM_loops_calc_normal_vcos( const bool use_split_normals, const float split_angle, float (*r_lnos)[3], struct MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset); +void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle); + void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag); void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag); -- cgit v1.2.3 From 1178518a689eba1b53b455a07612fcc77bde45df Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 1 Mar 2018 16:54:21 +0100 Subject: Refactor: Merge non-functional-change part of 'edit normals' 2017 GSoC. This merges changes in internals, runtime-only of existing custom normals code, which make sense as of themselves, and will make diff of soc branch easier/lighter to review. In the details, it mostly changes two things: * Now, smooth fans (aka MLoopNorSpaceArray) can store either loop indices, or pointers to BMLoop themselves. This makes sense since in BMesh, it's relatively easy to get index from a BMElement, but nearly impracticable to go the other way around. * First change enforces another, now we cannot rely anymore on `loops` being NULL in MLoopNorSpace to detect single-loop fans, so we instead store that info in a new flag. Again, these are expected to be totally non-functional changes. --- source/blender/bmesh/intern/bmesh_mesh.c | 16 +++++++++------- source/blender/bmesh/intern/bmesh_mesh.h | 3 +++ 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 8d6e7ae5b29..20c49d70b02 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -597,9 +597,11 @@ static void bm_mesh_edges_sharp_tag( bm->elem_index_dirty &= ~BM_EDGE; } -/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not. - * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */ -static bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr) +/** + * Check whether given loop is part of an unknown-so-far cyclic smooth fan, or not. + * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. + */ +bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr) { BMLoop *lfan_pivot_next = l_curr; BMEdge *e_next = l_curr->e; @@ -665,7 +667,7 @@ static void bm_mesh_loops_calc_normals( r_lnors_spacearr = &_lnors_spacearr; } if (r_lnors_spacearr) { - BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop); + BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR); edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); } @@ -700,7 +702,7 @@ static void bm_mesh_loops_calc_normals( * However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop() * is quite cheap in term of CPU cycles, so really think it's not worth it. */ if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && - (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !bm_mesh_loop_check_cyclic_smooth_fan(l_curr))) + (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !BM_loop_check_cyclic_smooth_fan(l_curr))) { } else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && @@ -734,7 +736,7 @@ static void bm_mesh_loops_calc_normals( BKE_lnor_space_define(lnor_space, r_lnos[l_curr_index], vec_curr, vec_prev, NULL); /* We know there is only one loop in this space, no need to create a linklist in this case... */ - BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, false); + BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, l_curr, true); if (has_clnors) { short (*clnor)[2] = clnors_data ? &clnors_data[l_curr_index] : @@ -853,7 +855,7 @@ static void bm_mesh_loops_calc_normals( if (r_lnors_spacearr) { /* Assign current lnor space to current 'vertex' loop. */ - BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, lfan_pivot_index, true); + BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, lfan_pivot_index, lfan_pivot, false); if (e_next != e_org) { /* We store here all edges-normalized vectors processed. */ BLI_stack_push(edge_vectors, vec_next); diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 8326e82af00..10f024423aa 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -52,6 +52,9 @@ void BM_loops_calc_normal_vcos( const bool use_split_normals, const float split_angle, float (*r_lnos)[3], struct MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset); +bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr); + + void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle); void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag); -- cgit v1.2.3 From bf8f5f51428dd22d06d33fa6c990f8eaccd80b5e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 14 Mar 2018 01:58:46 +1100 Subject: Cleanup: doxygen comments --- source/blender/bmesh/intern/bmesh_mesh.c | 2 +- source/blender/bmesh/intern/bmesh_polygon_edgenet.c | 2 +- source/blender/bmesh/intern/bmesh_queries.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 20c49d70b02..7f7f48e37bd 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -521,7 +521,7 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (* } /** - * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normals_vnos + * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normal_vcos */ static void bm_mesh_edges_sharp_tag( BMesh *bm, diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 41775bdf2d0..37e68f1d5ff 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -860,7 +860,7 @@ static void bvhtree_test_edges_isect_2d_ray_cb( /** * Store values for: * - #bm_face_split_edgenet_find_connection - * - #test_edges_isect_2d + * - #test_edges_isect_2d_vert * ... which don't change each call. */ struct EdgeGroup_FindConnection_Args { diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 32f726df01d..3a76f4ca271 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1526,9 +1526,9 @@ float BM_loop_calc_face_angle(const BMLoop *l) * * Calculate the normal at this loop corner or fallback to the face normal on straight lines. * - * \param l The loop to calculate the normal at - * \param epsilon: Value to avoid numeric errors (1e-5f works well). - * \param r_normal Resulting normal + * \param l: The loop to calculate the normal at. + * \param epsilon_sq: Value to avoid numeric errors (1e-5f works well). + * \param r_normal: Resulting normal. */ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3]) { -- cgit v1.2.3 From 342593f1248c739a9f30c005ae710b9b9c7d0877 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 15 Mar 2018 01:42:44 +1100 Subject: Cleanup: rename BLI_array_count -> len Match naming convention used everywhere else. Count should only be used when this isn't directly accessible. --- source/blender/bmesh/intern/bmesh_core.c | 8 +++---- source/blender/bmesh/intern/bmesh_mods.c | 12 +++++----- .../blender/bmesh/intern/bmesh_polygon_edgenet.c | 6 ++--- source/blender/bmesh/operators/bmo_dissolve.c | 6 ++--- source/blender/bmesh/operators/bmo_edgenet.c | 28 +++++++++++----------- source/blender/bmesh/operators/bmo_subdivide.c | 6 ++--- source/blender/bmesh/tools/bmesh_bevel.c | 10 ++++---- 7 files changed, 38 insertions(+), 38 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index aba0160622f..c4b29e91fb4 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1282,8 +1282,8 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) } /* create region face */ - f_new = BLI_array_count(edges) ? - BM_face_create_ngon(bm, v1, v2, edges, BLI_array_count(edges), faces[0], BM_CREATE_NOP) : NULL; + f_new = BLI_array_len(edges) ? + BM_face_create_ngon(bm, v1, v2, edges, BLI_array_len(edges), faces[0], BM_CREATE_NOP) : NULL; if (UNLIKELY(f_new == NULL)) { /* Invalid boundary region to join faces */ goto error; @@ -1347,11 +1347,11 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) /* delete old geometry */ if (do_del) { - for (i = 0; i < BLI_array_count(deledges); i++) { + for (i = 0; i < BLI_array_len(deledges); i++) { BM_edge_kill(bm, deledges[i]); } - for (i = 0; i < BLI_array_count(delverts); i++) { + for (i = 0; i < BLI_array_len(delverts); i++) { BM_vert_kill(bm, delverts[i]); } } diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 1cd51528e06..961cc458784 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -482,8 +482,8 @@ BMEdge *BM_vert_collapse_faces( BLI_array_append(faces, f); } - if (BLI_array_count(faces) >= 2) { - BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces), true); + if (BLI_array_len(faces) >= 2) { + BMFace *f2 = BM_faces_join(bm, faces, BLI_array_len(faces), true); if (f2) { BMLoop *l_a, *l_b; @@ -499,7 +499,7 @@ BMEdge *BM_vert_collapse_faces( } } - BLI_assert(BLI_array_count(faces) < 8); + BLI_assert(BLI_array_len(faces) < 8); BLI_array_free(faces); } @@ -608,7 +608,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) } while (l != e->l); /* flag existing faces so we can differentiate oldfaces from new faces */ - for (i = 0; i < BLI_array_count(oldfaces); i++) { + for (i = 0; i < BLI_array_len(oldfaces); i++) { BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP); oldfaces[i] = BM_face_copy(bm, bm, oldfaces[i], true, true); BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP); @@ -639,7 +639,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) int i, j; /* interpolate new/changed loop data from copied old faces */ - for (i = 0; i < BLI_array_count(oldfaces); i++) { + for (i = 0; i < BLI_array_len(oldfaces); i++) { float f_center_old[3]; BM_face_calc_center_mean(oldfaces[i], f_center_old); @@ -671,7 +671,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) } /* destroy the old faces */ - for (i = 0; i < BLI_array_count(oldfaces); i++) { + for (i = 0; i < BLI_array_len(oldfaces); i++) { BM_face_verts_kill(bm, oldfaces[i]); } diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 37e68f1d5ff..85dfd3f58e2 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -665,7 +665,7 @@ bool BM_face_split_edgenet( BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT); } while ((l_iter = l_iter->next) != l_first); - if (BLI_array_count(face_arr)) { + if (BLI_array_len(face_arr)) { bmesh_face_swap_data(f, face_arr[0]); BM_face_kill(bm, face_arr[0]); face_arr[0] = f; @@ -674,13 +674,13 @@ bool BM_face_split_edgenet( BM_ELEM_API_FLAG_DISABLE(f, FACE_NET); } - for (i = 0; i < BLI_array_count(face_arr); i++) { + for (i = 0; i < BLI_array_len(face_arr); i++) { BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET); } if (r_face_arr) { *r_face_arr = face_arr; - *r_face_arr_len = BLI_array_count(face_arr); + *r_face_arr_len = BLI_array_len(face_arr); } else { if (face_arr) { diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 5a2f07be70a..816d2e8d009 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -179,7 +179,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) } BMW_end(®walker); - for (i = 0; i < BLI_array_count(faces); i++) { + for (i = 0; i < BLI_array_len(faces); i++) { f_iter = faces[i]; BMO_face_flag_disable(bm, f_iter, FACE_TAG); BMO_face_flag_enable(bm, f_iter, FACE_ORIG); @@ -198,7 +198,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) /* track how many faces we should end up with */ int totface_target = bm->totface; - for (i = 0; i < BLI_array_count(regions); i++) { + for (i = 0; i < BLI_array_len(regions); i++) { BMFace *f_new; int tot = 0; @@ -259,7 +259,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) cleanup: /* free/cleanup */ - for (i = 0; i < BLI_array_count(regions); i++) { + for (i = 0; i < BLI_array_len(regions); i++) { if (regions[i]) MEM_freeN(regions[i]); } diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index 744ef866128..931ac684b07 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -179,22 +179,22 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) if (!count) { edges1 = edges; - BLI_array_count_set(edges1, BLI_array_count(edges)); + BLI_array_len_set(edges1, BLI_array_len(edges)); } else { edges2 = edges; - BLI_array_count_set(edges2, BLI_array_count(edges)); + BLI_array_len_set(edges2, BLI_array_len(edges)); } BLI_array_clear(edges); count++; } - if (edges1 && BLI_array_count(edges1) > 2 && - BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1])) + if (edges1 && BLI_array_len(edges1) > 2 && + BM_edge_share_vert_check(edges1[0], edges1[BLI_array_len(edges1) - 1])) { - if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) + if (edges2 && BLI_array_len(edges2) > 2 && + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1])) { BLI_array_free(edges1); BLI_array_free(edges2); @@ -206,8 +206,8 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) } } - if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) + if (edges2 && BLI_array_len(edges2) > 2 && + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1])) { edges2 = NULL; } @@ -218,23 +218,23 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) float dvec1[3]; float dvec2[3]; - if (BLI_array_count(edges1) == 1) { + if (BLI_array_len(edges1) == 1) { v1 = edges1[0]->v1; v2 = edges1[0]->v2; } else { v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1; - i = BLI_array_count(edges1) - 1; + i = BLI_array_len(edges1) - 1; v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1; } - if (BLI_array_count(edges2) == 1) { + if (BLI_array_len(edges2) == 1) { v3 = edges2[0]->v1; v4 = edges2[0]->v2; } else { v3 = BM_vert_in_edge(edges2[1], edges2[0]->v1) ? edges2[0]->v2 : edges2[0]->v1; - i = BLI_array_count(edges2) - 1; + i = BLI_array_len(edges2) - 1; v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1; } @@ -265,9 +265,9 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) else if (edges1) { BMVert *v1, *v2; - if (BLI_array_count(edges1) > 1) { + if (BLI_array_len(edges1) > 1) { v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1; - i = BLI_array_count(edges1) - 1; + i = BLI_array_len(edges1) - 1; v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1; e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE); BMO_edge_flag_enable(bm, e, ELE_NEW); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 7d3419b5910..8f998797a16 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -1157,7 +1157,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) loops[a] = l; } - vlen = BLI_array_count(loops); + vlen = BLI_array_len(loops); /* find the boundary of one of the split edges */ for (a = 1; a < vlen; a++) { @@ -1236,9 +1236,9 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) * - concave corner of an ngon. * - 2 edges being used in 2+ ngons. */ -// BM_face_splits_check_legal(bm, face, loops_split, BLI_array_count(loops_split)); +// BM_face_splits_check_legal(bm, face, loops_split, BLI_array_len(loops_split)); - for (j = 0; j < BLI_array_count(loops_split); j++) { + for (j = 0; j < BLI_array_len(loops_split); j++) { if (loops_split[j][0]) { BMFace *f_new; BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == NULL); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index beee9065ece..457e74ce1aa 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -3209,7 +3209,7 @@ static void build_center_ngon(BMesh *bm, BevVert *bv, int mat_nr) BLI_array_append(ve, NULL); } } while ((v = v->next) != vm->boundstart); - bev_create_ngon(bm, vv, BLI_array_count(vv), vf, frep, ve, mat_nr, true); + bev_create_ngon(bm, vv, BLI_array_len(vv), vf, frep, ve, mat_nr, true); BLI_array_free(vv); BLI_array_free(vf); @@ -3960,7 +3960,7 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i) BLI_array_append(sucs, bme2); } } - nsucs = BLI_array_count(sucs); + nsucs = BLI_array_len(sucs); bestj = j = i; for (sucindex = 0; sucindex < nsucs; sucindex++) { @@ -4500,15 +4500,15 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) } } if (do_rebuild) { - n = BLI_array_count(vv); + n = BLI_array_len(vv); f_new = bev_create_ngon(bm, vv, n, NULL, f, NULL, -1, true); - for (k = 0; k < BLI_array_count(vv_fix); k++) { + for (k = 0; k < BLI_array_len(vv_fix); k++) { bev_merge_uvs(bm, vv_fix[k]); } /* copy attributes from old edges */ - BLI_assert(n == BLI_array_count(ee)); + BLI_assert(n == BLI_array_len(ee)); bme_prev = ee[n - 1]; for (k = 0; k < n; k++) { bme_new = BM_edge_exists(vv[k], vv[(k + 1) % n]); -- cgit v1.2.3 From 91d0825b5556150c017dad767f7971bb6a731aec Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 31 Mar 2018 19:25:27 +0200 Subject: BLI_sort_utils: add pointer sorting callback Also rename Pointer -> Ptr --- source/blender/bmesh/operators/bmo_join_triangles.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 69198ff35ab..b1053e6d8c2 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -270,7 +270,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BMFace *f; BMEdge *e; /* data: edge-to-join, sort_value: error weight */ - struct SortPointerByFloat *jedges; + struct SortPtrByFloat *jedges; unsigned i, totedge; uint totedge_tag = 0; -- cgit v1.2.3 From b2c9fdfe871e2f1eaa6be30d67ad9df12c2f0d01 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 3 Apr 2018 17:06:36 +0200 Subject: Cleanup: rename BMesh count_ex -> count_at_most --- source/blender/bmesh/intern/bmesh_core.c | 4 ++-- source/blender/bmesh/intern/bmesh_mods.c | 2 +- source/blender/bmesh/intern/bmesh_private.h | 2 +- source/blender/bmesh/intern/bmesh_queries.c | 16 ++++++++-------- source/blender/bmesh/intern/bmesh_queries.h | 20 ++++++++++---------- source/blender/bmesh/intern/bmesh_structure.c | 10 +++++----- source/blender/bmesh/intern/bmesh_structure.h | 4 ++-- 7 files changed, 29 insertions(+), 29 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index c4b29e91fb4..7e35866887d 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -685,7 +685,7 @@ int bmesh_elem_check(void *element, const char htype) err |= IS_FACE_LOOP_WRONG_RADIAL_LENGTH; } - if (bmesh_disk_count_ex(l_iter->v, 2) < 2) { + if (bmesh_disk_count_at_most(l_iter->v, 2) < 2) { err |= IS_FACE_LOOP_WRONG_DISK_LENGTH; } } @@ -1785,7 +1785,7 @@ BMEdge *bmesh_kernel_join_edge_kill_vert( return NULL; } - if (bmesh_disk_count_ex(v_kill, 3) == 2) { + if (bmesh_disk_count_at_most(v_kill, 3) == 2) { #ifndef NDEBUG int valence1, valence2; BMLoop *l; diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 961cc458784..4290f94bba1 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -65,7 +65,7 @@ bool BM_vert_dissolve(BMesh *bm, BMVert *v) { /* logic for 3 or more is identical */ - const int len = BM_vert_edge_count_ex(v, 3); + const int len = BM_vert_edge_count_at_most(v, 3); if (len == 1) { BM_vert_kill(bm, v); /* will kill edges too */ diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index 4dcf97e3f35..daee22ffe76 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -55,7 +55,7 @@ int bmesh_elem_check(void *element, const char htype); #endif int bmesh_radial_length(const BMLoop *l); -int bmesh_disk_count_ex(const BMVert *v, const int count_max); +int bmesh_disk_count_at_most(const BMVert *v, const int count_max); int bmesh_disk_count(const BMVert *v); /** diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 3a76f4ca271..ab2f017d103 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -799,9 +799,9 @@ int BM_vert_edge_count(const BMVert *v) return bmesh_disk_count(v); } -int BM_vert_edge_count_ex(const BMVert *v, const int count_max) +int BM_vert_edge_count_at_most(const BMVert *v, const int count_max) { - return bmesh_disk_count_ex(v, count_max); + return bmesh_disk_count_at_most(v, count_max); } int BM_vert_edge_count_nonwire(const BMVert *v) @@ -835,7 +835,7 @@ int BM_edge_face_count(const BMEdge *e) return count; } -int BM_edge_face_count_ex(const BMEdge *e, const int count_max) +int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) { int count = 0; @@ -863,9 +863,9 @@ int BM_vert_face_count(const BMVert *v) return bmesh_disk_facevert_count(v); } -int BM_vert_face_count_ex(const BMVert *v, int count_max) +int BM_vert_face_count_at_most(const BMVert *v, int count_max) { - return bmesh_disk_facevert_count_ex(v, count_max); + return bmesh_disk_facevert_count_at_most(v, count_max); } /** @@ -1044,7 +1044,7 @@ static int bm_loop_region_count__clear(BMLoop *l) /** * The number of loops connected to this loop (not including disconnected regions). */ -int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) +int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) { const int count = bm_loop_region_count__recursive(l->e, l->v); const int count_total = bm_loop_region_count__clear(l); @@ -1059,7 +1059,7 @@ int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) int BM_loop_region_loops_count(BMLoop *l) { - return BM_loop_region_loops_count_ex(l, NULL); + return BM_loop_region_loops_count_at_most(l, NULL); } /** @@ -1071,7 +1071,7 @@ bool BM_vert_is_manifold_region(const BMVert *v) BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v); if (l_first) { int count, count_total; - count = BM_loop_region_loops_count_ex(l_first, &count_total); + count = BM_loop_region_loops_count_at_most(l_first, &count_total); return (count == count_total); } return true; diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index c9fce96c798..e602c63da94 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -70,17 +70,17 @@ BMFace *BM_edge_pair_share_face_by_len( const bool allow_adjacent) ATTR_NONNULL(); int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -#define BM_vert_edge_count_is_equal(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == n) -#define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_ex(v, (n) + 1) == (n) + 1) -int BM_vert_edge_count_ex(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +#define BM_vert_edge_count_is_equal(v, n) (BM_vert_edge_count_at_most(v, (n) + 1) == n) +#define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_at_most(v, (n) + 1) == (n) + 1) +int BM_vert_edge_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -#define BM_edge_face_count_is_equal(e, n) (BM_edge_face_count_ex(e, (n) + 1) == n) -#define BM_edge_face_count_is_over(e, n) (BM_edge_face_count_ex(e, (n) + 1) == (n) + 1) -int BM_edge_face_count_ex(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +#define BM_edge_face_count_is_equal(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == n) +#define BM_edge_face_count_is_over(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == (n) + 1) +int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -#define BM_vert_face_count_is_equal(v, n) (BM_vert_face_count_ex(v, (n) + 1) == n) -#define BM_vert_face_count_is_over(v, n) (BM_vert_face_count_ex(v, (n) + 1) == (n) + 1) -int BM_vert_face_count_ex(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +#define BM_vert_face_count_is_equal(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == n) +#define BM_vert_face_count_is_over(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == (n) + 1) +int BM_vert_face_count_at_most(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int BM_vert_face_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -103,7 +103,7 @@ bool BM_edge_is_contiguous_loop_cd( const int cd_loop_type, const int cd_loop_offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_loop_region_loops_count_ex(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index 8e484841568..8aa9502c0f7 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -244,7 +244,7 @@ int bmesh_disk_count(const BMVert *v) return count; } -int bmesh_disk_count_ex(const BMVert *v, const int count_max) +int bmesh_disk_count_at_most(const BMVert *v, const int count_max) { int count = 0; if (v->e) { @@ -267,7 +267,7 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) if (!BM_vert_in_edge(e, v)) { return false; } - if (len == 0 || bmesh_disk_count_ex(v, len + 1) != len) { + if (len == 0 || bmesh_disk_count_at_most(v, len + 1) != len) { return false; } @@ -307,7 +307,7 @@ int bmesh_disk_facevert_count(const BMVert *v) return count; } -int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max) +int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) { /* is there an edge on this vert at all */ int count = 0; @@ -318,7 +318,7 @@ int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max) e_first = e_iter = v->e; do { if (e_iter->l) { - count += bmesh_radial_facevert_count_ex(e_iter->l, v, count_max - count); + count += bmesh_radial_facevert_count_at_most(e_iter->l, v, count_max - count); if (count == count_max) { break; } @@ -560,7 +560,7 @@ int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) return count; } -int bmesh_radial_facevert_count_ex(const BMLoop *l, const BMVert *v, const int count_max) +int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const int count_max) { const BMLoop *l_iter; int count = 0; diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index 0efb25da37c..974b276f8b3 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -49,7 +49,7 @@ BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) A BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int bmesh_disk_facevert_count_ex(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -63,7 +63,7 @@ void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL(); * bmesh_radial_loop_next(BMLoop *l) / prev. * just use member access l->radial_next, l->radial_prev now */ -int bmesh_radial_facevert_count_ex(const BMLoop *l, const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -- cgit v1.2.3 From 1c24c04e6023f2d2a328dfcdc9f86cd381d029a3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 5 Apr 2018 18:20:27 +0200 Subject: Remove workspace object mode, reverts changes w/ 2.8 This caused too many problems syncing object modes with multiple objects/windows/workspaces, see: D3130 for details. --- source/blender/bmesh/intern/bmesh_mesh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/bmesh') diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index ef7b54195ff..9e03c28ba1b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -1042,7 +1042,7 @@ void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle) } static void UNUSED_FUNCTION(bm_mdisps_space_set)( - Object *ob, BMesh *bm, int from, int to, eObjectMode object_mode) + Object *ob, BMesh *bm, int from, int to) { /* switch multires data out of tangent space */ if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) { @@ -1053,7 +1053,7 @@ static void UNUSED_FUNCTION(bm_mdisps_space_set)( BMIter iter; // int i = 0; // UNUSED - multires_set_space(dm, ob, from, to, object_mode); + multires_set_space(dm, ob, from, to); mdisps = CustomData_get_layer(&dm->loopData, CD_MDISPS); -- cgit v1.2.3