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:
authorHans Goudey <h.goudey@me.com>2020-01-25 01:59:54 +0300
committerHans Goudey <h.goudey@me.com>2020-01-25 01:59:54 +0300
commitabe5fcb8d1422d9f650f73f73615532e15246834 (patch)
treeed6a3afa27cdcfaf83606c91a2a386f6dae6c29f /source/blender/bmesh
parent4aa703aa1430bc53f19e2cc7182e70db1a916f13 (diff)
Bevel: Simplify Profile Calculation Step
Profile calculation now happens in a single pass rather than being spread throughout the process. This means each profile will only be calculated a single time. Reviewed By: howardt Differential Revision: https://developer.blender.org/D6658
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c112
1 files changed, 58 insertions, 54 deletions
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 07e159b3241..57dbbcbfca4 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -155,6 +155,8 @@ typedef struct Profile {
float *prof_co;
/** Like prof_co, but for seg power of 2 >= seg */
float *prof_co_2;
+ /** Mark a special case so the these parameters aren't reset with others. */
+ bool special_params;
} Profile;
#define PRO_SQUARE_R 1e4f
#define PRO_CIRCLE_R 2.0f
@@ -359,6 +361,9 @@ typedef struct BevelParams {
// #pragma GCC diagnostic ignored "-Wpadded"
+/* Only for debugging, shouldn't be in blender repo. */
+// #include "bevdebug.c"
+
/* Some flags to re-enable old behavior for a while,
* in case fixes broke things not caught by regression tests. */
static int bev_debug_flags = 0;
@@ -1314,7 +1319,10 @@ static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, flo
}
/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco. */
-static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3], float projco[3])
+static void project_to_edge(const BMEdge *e,
+ const float co_a[3],
+ const float co_b[3],
+ float projco[3])
{
float otherco[3];
@@ -1330,16 +1338,13 @@ static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3],
* It is the closest point on the beveled edge to the line segment between bndv and bndv->next. */
static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
{
- EdgeHalf *e;
- Profile *pro;
float start[3], end[3], co3[3], d1[3], d2[3];
- bool do_linear_interp;
+ bool do_linear_interp = true;
+ EdgeHalf *e = bndv->ebev;
+ Profile *pro = &bndv->profile;
copy_v3_v3(start, bndv->nv.co);
copy_v3_v3(end, bndv->next->nv.co);
- pro = &bndv->profile;
- e = bndv->ebev;
- do_linear_interp = true;
if (e) {
do_linear_interp = false;
pro->super_r = bp->pro_super_r;
@@ -1446,7 +1451,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
copy_v3_v3(pro->plane_co, start);
}
else if (bndv->is_arc_start) {
- /* Assume pro->middle was alredy set. */
+ /* Assume pro->middle was already set. */
copy_v3_v3(pro->start, start);
copy_v3_v3(pro->end, end);
pro->super_r = PRO_CIRCLE_R;
@@ -1455,6 +1460,17 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
zero_v3(pro->proj_dir);
do_linear_interp = false;
}
+ else if (bp->vertex_only) {
+ copy_v3_v3(pro->start, start);
+ copy_v3_v3(pro->middle, bv->v->co);
+ copy_v3_v3(pro->end, end);
+ pro->super_r = bp->pro_super_r;
+ zero_v3(pro->plane_co);
+ zero_v3(pro->plane_no);
+ zero_v3(pro->proj_dir);
+ do_linear_interp = false;
+ }
+
if (do_linear_interp) {
pro->super_r = PRO_LINE_R;
copy_v3_v3(pro->start, start);
@@ -1467,11 +1483,11 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
}
}
-/* Maybe move the profile plane for bndv->ebev to the plane its profile's start, and the
+/* Maybe move the profile plane for bndv->ebev to the plane its profile's start, and the
* original beveled vert, bmv. This will usually be the plane containing its adjacent
* non-beveled edges, but sometimes the start and the end are not on those edges.
*
- * Currently just used in build boundary terminal edge */
+ * Currently just used in #build_boundary_terminal_edge */
static void move_profile_plane(BoundVert *bndv, BMVert *bmvert)
{
float d1[3], d2[3], no[3], no2[3], no3[3], dot2, dot3;
@@ -1496,6 +1512,9 @@ static void move_profile_plane(BoundVert *bndv, BMVert *bmvert)
copy_v3_v3(bndv->profile.plane_no, no);
}
}
+
+ /* We've changed the parameters from their defaults, so don't recalculate them later. */
+ pro->special_params = true;
}
/* Move the profile plane for the two BoundVerts involved in a weld.
@@ -1531,6 +1550,10 @@ static void move_weld_profile_planes(BevVert *bv, BoundVert *bndv1, BoundVert *b
copy_v3_v3(bndv2->profile.plane_no, no);
}
}
+
+ /* We've changed the parameters from their defaults, so don't recalculate them later. */
+ bndv1->profile.special_params = true;
+ bndv2->profile.special_params = true;
}
/* return 1 if a and b are in CCW order on the normal side of f,
@@ -1748,6 +1771,7 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
else {
map_ok = make_unit_square_map(pro->start, pro->middle, pro->end, map);
}
+
if (bp->vmesh_method == BEVEL_VMESH_CUTOFF && map_ok) {
/* Calculate the "height" of the profile by putting the (0,0) and (1,1) corners of the
* un-transformed profile throughout the 2D->3D map and calculating the distance between them.
@@ -1759,6 +1783,7 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
mul_v3_m4v3(top_corner, map, p);
pro->height = len_v3v3(bottom_corner, top_corner);
}
+
/* The first iteration is the nseg case, the second is the seg_2 case (if it's needed) */
for (i = 0; i < 2; i++) {
if (i == 0) {
@@ -2321,15 +2346,20 @@ static bool eh_on_plane(EdgeHalf *e)
/* Calculate the profiles for all the BoundVerts of VMesh vm */
static void calculate_vm_profiles(BevelParams *bp, BevVert *bv, VMesh *vm)
{
- BoundVert *bndv;
-
- bndv = vm->boundstart;
+ BoundVert *bndv = vm->boundstart;
do {
- set_profile_params(bp, bv, bndv);
- /* Use the miter profile spacing struct if the default is filled with the custom profile. */
- bool miter_profile = bp->use_custom_profile && (bndv->is_arc_start || bndv->is_patch_start);
- /* Don't bother reversing the profile if it's a miter profile */
- bool reverse_profile = !bndv->is_profile_start && !miter_profile;
+ /* In special cases the params will have already been set. */
+ if (!bndv->profile.special_params) {
+ set_profile_params(bp, bv, bndv);
+ }
+ bool miter_profile = false;
+ bool reverse_profile = false;
+ if (bp->use_custom_profile) {
+ /* Use the miter profile spacing struct if the default is filled with the custom profile. */
+ miter_profile = (bndv->is_arc_start || bndv->is_patch_start);
+ /* Don't bother reversing the profile if it's a miter profile */
+ reverse_profile = !bndv->is_profile_start && !miter_profile;
+ }
calculate_profile(bp, bndv, reverse_profile, miter_profile);
} while ((bndv = bndv->next) != vm->boundstart);
}
@@ -2357,8 +2387,6 @@ static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool constr
}
} while ((e = e->next) != efirst);
- calculate_vm_profiles(bp, bv, vm);
-
if (construct) {
set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
if (vm->count == 2) {
@@ -2471,15 +2499,13 @@ static void build_boundary_terminal_edge(BevelParams *bp,
}
}
}
- calculate_vm_profiles(bp, bv, vm);
if (bv->edgecount >= 3) {
/* Special case: snap profile to plane of adjacent two edges. */
bndv = vm->boundstart;
BLI_assert(bndv->ebev != NULL);
+ set_profile_params(bp, bv, bndv);
move_profile_plane(bndv, bv->v);
- /* This step happens before the profile orientation pass so don't reverse the profile. */
- calculate_profile(bp, bndv, false, false);
}
if (construct) {
@@ -2831,8 +2857,6 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
adjust_miter_coords(bp, bv, emiter);
}
- calculate_vm_profiles(bp, bv, vm);
-
if (construct) {
set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
@@ -4157,9 +4181,8 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
copy_v3_v3(bndv->profile.plane_co, bndv->profile.start);
cross_v3_v3v3(bndv->profile.plane_no, bndv->profile.start, bndv->profile.end);
copy_v3_v3(bndv->profile.proj_dir, bndv->profile.plane_no);
- /* No need to reverse the profile or use the miter profile spacing struct because this case
- * isn't used with custom profiles. */
- calculate_profile(bp, bndv, false, false);
+ /* Calculate profiles again because we started over with new boundverts. */
+ calculate_profile(bp, bndv, false, false); /* No custom profiles in this case. */
/* Just building the boundaries here, so sample the profile halfway through */
get_profile_point(bp, &bndv->profile, 1, 2, mesh_vert(vm0, i, 0, 1)->co);
@@ -4922,20 +4945,6 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv, BoundVert
odd = ns % 2;
BLI_assert(n_bndv >= 3 && ns > 1);
- /* Add support for profiles in vertex only in-plane bevels. */
- if (bp->vertex_only) {
- bndv = bv->vmesh->boundstart;
- do {
- Profile *pro = &bndv->profile;
- copy_v3_v3(pro->middle, bv->v->co);
- pro->super_r = bp->pro_super_r;
- bool miter_profile = bp->use_custom_profile && (bndv->is_arc_start || bndv->is_patch_start);
- /* Orientation doesn't matter when only beveling vertices */
- calculate_profile(bp, bndv, false, miter_profile);
- bndv = bndv->next;
- } while (bndv != bv->vmesh->boundstart);
- }
-
if (bp->pro_super_r == PRO_SQUARE_R && bv->selcount >= 3 && !odd && !bp->use_custom_profile) {
vm1 = square_out_adj_vmesh(bp, bv);
}
@@ -5428,7 +5437,6 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
* we have to make it here. */
static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
{
-
VMesh *vm = bv->vmesh;
BMVert *v1, *v2;
BMEdge *e_eg, *bme;
@@ -5455,8 +5463,6 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
zero_v3(pro->plane_co);
zero_v3(pro->plane_no);
zero_v3(pro->proj_dir);
- /* there's no orientation chain to continue so the orientation of the bevel doesn't matter. */
- calculate_profile(bp, bndv, false, false);
for (k = 1; k < ns; k++) {
get_profile_point(bp, pro, k, ns, co);
@@ -5519,15 +5525,17 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
}
else { /* Get the last of the two BoundVerts. */
weld2 = bndv;
+ set_profile_params(bp, bv, weld1);
+ set_profile_params(bp, bv, weld2);
move_weld_profile_planes(bv, weld1, weld2);
- if (!bp->use_custom_profile) { /* Else profile recalculated in next loop. */
- calculate_profile(bp, weld1, !weld1->is_profile_start, false);
- calculate_profile(bp, weld2, !weld2->is_profile_start, false);
- }
}
}
} while ((bndv = bndv->next) != vm->boundstart);
+ /* It's simpler to calculate all profiles only once at a single moment, so keep just a single
+ * profile calculation here, the last point before actual mesh verts are created. */
+ calculate_vm_profiles(bp, bv, vm);
+
/* Create new vertices and place them based on the profiles. */
/* Copy other ends to (i, 0, ns) for all i, and fill in profiles for edges. */
bndv = vm->boundstart;
@@ -5536,10 +5544,6 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
/* bndv's last vert along the boundary arc is the first of the next BoundVert's arc. */
copy_mesh_vert(vm, i, 0, ns, bndv->next->index, 0, 0);
- /* Fix the profile orientations if it's not a miter profile. */
- if (bp->use_custom_profile && !bndv->is_arc_start && !bndv->is_patch_start) {
- calculate_profile(bp, bndv, !bndv->is_profile_start, false);
- }
if (vm->mesh_kind != M_ADJ) {
for (k = 1; k < ns; k++) {
if (bndv->ebev) {
@@ -7423,7 +7427,7 @@ void BM_mesh_bevel(BMesh *bm,
adjust_offsets(&bp, bm);
}
- /* Maintain consistent orientations for the unsymmetrical custom profiles. */
+ /* Maintain consistent orientations for the asymmetrical custom profiles. */
if (bp.use_custom_profile) {
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {