Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2018-04-15 13:16:55 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2018-04-15 13:16:55 +0300
commit7e1832c8d546ec13e752b7bd42ce13e3fc10ae86 (patch)
tree0fff9d878db69b288f909ff9a0f8aefe31ab8d80 /source/blender/bmesh
parentc0c8df3f2cf3ab03cec1f660619b0fe2290caf2a (diff)
parent94959dba1b53640e2a36cf9b5ca46aaf49c5c74a (diff)
Merge branch 'blender2.8' into hair_guides
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c19
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c77
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h5
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c14
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c1
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c15
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c22
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h20
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h4
-rw-r--r--source/blender/bmesh/operators/bmo_connect_concave.c4
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c4
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c8
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c30
-rw-r--r--source/blender/bmesh/operators/bmo_face_island.c2
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c2
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c2
-rw-r--r--source/blender/bmesh/operators/bmo_mesh_conv.c11
-rw-r--r--source/blender/bmesh/operators/bmo_rotate_edges.c2
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c16
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c4
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c804
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_path.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c14
-rw-r--r--source/blender/bmesh/tools/bmesh_separate.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c4
38 files changed, 790 insertions, 367 deletions
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 36b2f9cadf7..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;
}
}
@@ -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]);
}
}
@@ -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;
@@ -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..9e03c28ba1b 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -521,21 +521,19 @@ 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, const float (*vnos)[3], const float (*fnos)[3], 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;
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 +558,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:
@@ -570,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);
+ }
}
}
}
@@ -591,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;
@@ -659,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__);
}
@@ -694,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) &&
@@ -728,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] :
@@ -847,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);
@@ -1008,7 +1016,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);
@@ -1019,7 +1027,22 @@ void BM_loops_calc_normal_vcos(
}
}
-static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from, int to)
+/** 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 */
if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 01f11f6f942..10f024423aa 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -52,6 +52,11 @@ 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);
void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
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_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 1cd51528e06..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 */
@@ -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_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index ddc2b26417c..37a4fb5c29c 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/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index 41775bdf2d0..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) {
@@ -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_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 32f726df01d..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;
@@ -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])
{
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();
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..816d2e8d009 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(&regwalker, bm, BMW_ISLAND_MANIFOLD,
@@ -179,7 +179,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
}
BMW_end(&regwalker);
- 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 64b092da5c8..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_empty(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_face_island.c b/source/blender/bmesh/operators/bmo_face_island.c
index 77b28f2f29c..e52052a28d3 100644
--- a/source/blender/bmesh/operators/bmo_face_island.c
+++ b/source/blender/bmesh/operators/bmo_face_island.c
@@ -99,7 +99,7 @@ void bmo_face_island_boundary_exec(BMesh *bm, BMOperator *op)
{
BMOpSlot *slot = BMO_slot_get(op->slots_out, "boundary");
- BMO_slot_buffer_from_array(op, slot, (BMHeader **)boundary, BLI_array_count(boundary));
+ BMO_slot_buffer_from_array(op, slot, (BMHeader **)boundary, BLI_array_len(boundary));
BLI_array_free(boundary);
}
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_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;
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..8f998797a16 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);
@@ -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/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 18b2b4db2bf..457e74ce1aa 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,393 @@ 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.
- *
- * Note that this might not process all BevVerts, only the ones
- * that need adjustment.
- */
-static void adjust_offsets(BevelParams *bp)
+#ifdef DEBUG_ADJUST
+static void print_adjust_stats(BoundVert *vstart)
{
- BevVert *bv, *searchbv, *bvother;
- int i, searchi;
- GHashIterator giter;
- EdgeHalf *e, *efirst, *eother;
- GSQueue *q;
- float max_rel_adj;
+ 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 = 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): 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 = 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): 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)
+ 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
- BLI_assert(!bp->vertex_only);
- GHASH_ITER(giter, bp->vert_hash) {
- bv = BLI_ghashIterator_getValue(&giter);
- bv->visited = false;
+#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;
+ 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;
+ }
+ g_prod[0] = 1.0f;
+ 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;
+ }
}
+ if (gprod_sum == 0.0f) {
+ MEM_freeN(g);
+ MEM_freeN(g_prod);
+ return false;
+ }
+ p = spec_sum / gprod_sum;
- 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;
- }
+ /* 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;
}
}
- if (searchbv == NULL)
- break;
+ else {
+ /* not a cycle, and last of chain */
+ eleft = v->elast;
+ eleft->offset_l = p;
+ }
+ i++;
+ v = v->adjchain;
+ } while (v && v != vstart);
- 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);
+ MEM_freeN(g);
+ 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.
+ * 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, *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 ? 3 * np : 3 * np - 3;
+
+ 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 || 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);
+ 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);
}
- } while ((e = e->next) != efirst);
+ }
+
+ /* residue np + 2*i (if cycle) else np - 1 + 2*i:
+ * right offset for parm i matches its spec; weighted */
+ 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
}
- }
- BLI_gsqueue_free(q);
+ 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);
+ }
+ 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
- /* 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));
+ /* Use the solution to set new widths */
+ v = vstart;
+ i = 0;
+ do {
+ val = EIG_linear_solver_variable_get(solver, 0, i);
+ 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
+ }
}
- if (max_rel_adj > BEVEL_MAX_AUTO_ADJUST_PCT / 100.0f) {
- bp->limit_offset = true;
- adjust_offsets(bp);
- bp->limit_offset = false;
+ 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);
+}
+
+/* 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.
+ *
+ * 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, *bvcur;
+ BoundVert *v, *vanchor, *vchainstart, *vnext;
+ EdgeHalf *enext;
+ GHashIterator giter;
+ bool iscycle;
+
+ /* find and process chains and cycles of unvisited BoundVerts that have eon set */
+ GHASH_ITER(giter, bp->vert_hash) {
+ bv = bvcur = BLI_ghashIterator_getValue(&giter);
+ vanchor = bv->vmesh->boundstart;
+ do {
+ if (vanchor->visited || !vanchor->eon)
+ continue;
+
+ /* 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) {
+ break;
+ }
+ adjust_the_cycle_or_chain(vchainstart, true);
+ iscycle = true;
+ }
+ v = vnext;
+ }
+ 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);
+ }
+
+ /* Rebuild boundaries with new width specs */
+ GHASH_ITER(giter, bp->vert_hash) {
+ bv = BLI_ghashIterator_getValue(&giter);
+ build_boundary(bp, bv, false);
}
}
@@ -2997,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);
@@ -3041,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,
@@ -3063,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)) {
@@ -3577,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++) {
@@ -3590,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);
}
@@ -4117,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]);
@@ -4983,6 +5366,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 +5403,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);
}
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"