diff options
Diffstat (limited to 'source/blender/bmesh')
28 files changed, 335 insertions, 87 deletions
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)); 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_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); diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 6cc1f37db43..fd32119cb5f 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -708,7 +708,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; @@ -765,11 +765,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 1974d364171..6e9d62349ea 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -55,7 +55,8 @@ 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; }; void BM_mesh_bm_to_me( 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/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/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 66fcd739839..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" @@ -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 */ 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/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_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_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c index 0eb9bf90ca8..7311ed5ce64 100644 --- a/source/blender/bmesh/operators/bmo_mesh_conv.c +++ b/source/blender/bmesh/operators/bmo_mesh_conv.c @@ -62,15 +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, })); + BM_mesh_bm_to_me( + bm, me, + (&(struct BMeshToMeshParams){ + .calc_object_remap = true, + })); } 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.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/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..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" @@ -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_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 35167835646..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; @@ -1985,6 +1998,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 +2007,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); @@ -2028,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. @@ -2039,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); @@ -2063,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); @@ -2074,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); } @@ -2163,7 +2229,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; @@ -2171,7 +2237,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); @@ -2191,7 +2256,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); @@ -3188,6 +3253,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, @@ -3210,9 +3442,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)) { @@ -3737,7 +3973,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_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 0a1271c2aa9..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" @@ -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 82545a5e011..cc8511c65f1 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1265,8 +1265,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]; @@ -1669,7 +1669,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__); 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); } 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" |