From 61fa6165dfe10f5b882fe647700a36ad76ab16a8 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Mon, 1 Apr 2019 07:58:34 -0400 Subject: Fix T63071: Bevel inconsistent results toggling harden_normals. Some iterations in bevel were over a hash table, which leads to possibly different results run-to-run, especially when loop_slide is enabled. Changed those iters to go over all verts of BMesh, which leads to consistent order run-to-run. --- source/blender/bmesh/tools/bmesh_bevel.c | 68 +++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 23 deletions(-) (limited to 'source/blender/bmesh/tools') diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 284df9f9bc9..1c77220c03c 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -2941,18 +2941,24 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle) * 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) +static void adjust_offsets(BevelParams *bp, BMesh *bm) { + BMVert *bmv; BevVert *bv, *bvcur; BoundVert *v, *vanchor, *vchainstart, *vchainend, *vnext; EdgeHalf *enext; - GHashIterator giter; + BMIter iter; bool iscycle; int chainlen; /* 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); + /* note: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts */ + BM_ITER_MESH(bmv, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(bmv, BM_ELEM_TAG)) + continue; + bv = bvcur = find_bevvert(bp, bmv); + if (!bv) + continue; vanchor = bv->vmesh->boundstart; do { if (vanchor->visited || !vanchor->eon) { @@ -3023,9 +3029,12 @@ static void adjust_offsets(BevelParams *bp) } /* Rebuild boundaries with new width specs */ - GHASH_ITER(giter, bp->vert_hash) { - bv = BLI_ghashIterator_getValue(&giter); - build_boundary(bp, bv, false); + BM_ITER_MESH(bmv, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(bmv, BM_ELEM_TAG)) { + bv = find_bevvert(bp, bmv); + if (bv) + build_boundary(bp, bv, false); + } } } @@ -6275,17 +6284,22 @@ static float vertex_collide_offset(BevelParams *bp, EdgeHalf *ea) * current edge offset specs to reflect this clamping, * and store the new offset in bp.offset. */ -static void bevel_limit_offset(BevelParams *bp) +static void bevel_limit_offset(BevelParams *bp, BMesh *bm) { BevVert *bv; EdgeHalf *eh; - GHashIterator giter; + BMIter iter; + BMVert *bmv; float limited_offset, offset_factor, collision_offset; int i; limited_offset = bp->offset; - GHASH_ITER(giter, bp->vert_hash) { - bv = BLI_ghashIterator_getValue(&giter); + BM_ITER_MESH(bmv, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(bmv, BM_ELEM_TAG)) + continue; + bv = find_bevvert(bp, bmv); + if (!bv) + continue; for (i = 0; i < bv->edgecount; i++) { eh = &bv->edges[i]; if (bp->vertex_only) { @@ -6310,8 +6324,12 @@ static void bevel_limit_offset(BevelParams *bp) * with the new limited_offset. */ offset_factor = limited_offset / bp->offset; - GHASH_ITER(giter, bp->vert_hash) { - bv = BLI_ghashIterator_getValue(&giter); + BM_ITER_MESH(bmv, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(bmv, BM_ELEM_TAG)) + continue; + bv = find_bevvert(bp, bmv); + if (!bv) + continue; for (i = 0; i < bv->edgecount; i++) { eh = &bv->edges[i]; eh->offset_l_spec *= offset_factor; @@ -6353,7 +6371,6 @@ void BM_mesh_bevel( BMLoop *l; BevVert *bv; BevelParams bp = {NULL}; - GHashIterator giter; bp.offset = offset; bp.offset_type = offset_type; @@ -6404,22 +6421,24 @@ void BM_mesh_bevel( /* Perhaps clamp offset to avoid geometry colliisions */ if (limit_offset) { - bevel_limit_offset(&bp); + bevel_limit_offset(&bp, bm); /* Assign initial new vertex positions */ - GHASH_ITER(giter, bp.vert_hash) { - bv = BLI_ghashIterator_getValue(&giter); - build_boundary(&bp, bv, true); + BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + bv = find_bevvert(&bp, v); + if (bv) + build_boundary(&bp, bv, true); + } } } /* Perhaps do a pass to try to even out widths */ if (!bp.vertex_only && bp.offset_adjust && bp.offset_type != BEVEL_AMT_PERCENT) { - adjust_offsets(&bp); + adjust_offsets(&bp, bm); } /* Build the meshes around vertices, now that positions are final */ - /* Note: could use GHASH_ITER over bp.vert_hash when backward compatibility no longer matters */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { bv = find_bevvert(&bp, v); @@ -6439,9 +6458,12 @@ void BM_mesh_bevel( } /* Extend edge data like sharp edges and precompute normals for harden */ - GHASH_ITER(giter, bp.vert_hash) { - bv = BLI_ghashIterator_getValue(&giter); - bevel_extend_edge_data(bv); + BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + bv = find_bevvert(&bp, v); + if (bv) + bevel_extend_edge_data(bv); + } } /* Rebuild face polygons around affected vertices */ -- cgit v1.2.3