[Bf-blender-cvs] [561d738eaa2] master: Fix T53459, inconsistent bevel on identical edges.
Howard Trickey
noreply at git.blender.org
Mon Jan 29 01:38:45 CET 2018
Commit: 561d738eaa2f64044f5266a480d9bc822bd0296e
Author: Howard Trickey
Date: Sun Jan 28 19:19:02 2018 -0500
Branches: master
https://developer.blender.org/rB561d738eaa2f64044f5266a480d9bc822bd0296e
Fix T53459, inconsistent bevel on identical edges.
The old algorithm depended on vertex order.
The new one uses a global least squares solution on chains
and cycles of edges where loop slide induces a dependency.
See https://wiki.blender.org/index.php/Dev:Source/Modeling/Bevel
in the "Consistent Widths for Even Bevels" for derivation of
the new algorithm.
===================================================================
M source/blender/bmesh/tools/bmesh_bevel.c
===================================================================
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 18b2b4db2bf..35167835646 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -44,6 +44,8 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
+#include "eigen_capi.h"
+
#include "bmesh.h"
#include "bmesh_bevel.h" /* own include */
@@ -58,6 +60,7 @@
#define BEVEL_SMALL_ANG DEG2RADF(10.0f)
#define BEVEL_MAX_ADJUST_PCT 10.0f
#define BEVEL_MAX_AUTO_ADJUST_PCT 300.0f
+#define BEVEL_MATCH_SPEC_WEIGHT 0.2
/* happens far too often, uncomment for development */
// #define BEVEL_ASSERT_PROJECT
@@ -139,10 +142,14 @@ typedef struct BoundVert {
NewVert nv;
EdgeHalf *efirst; /* first of edges attached here: in CCW order */
EdgeHalf *elast;
+ EdgeHalf *eon; /* the "edge between" that this is on, in offset_on_edge_between case */
EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */
int index; /* used for vmesh indexing */
+ float sinratio; /* when eon set, ratio of sines of angles to eon edge */
+ struct BoundVert *adjchain; /* adjustment chain or cycle link pointer */
Profile profile; /* edge profile between this and next BoundVert */
bool any_seam; /* are any of the edges attached here seams? */
+ bool visited; /* used during delta adjust pass */
// int _pad;
} BoundVert;
@@ -192,6 +199,7 @@ typedef struct BevelParams {
bool use_weights; /* bevel amount affected by weights on edges or verts */
bool loop_slide; /* should bevel prefer to slide along edges rather than keep widths spec? */
bool limit_offset; /* should offsets be limited by collisions? */
+ bool offset_adjust; /* should offsets be adjusted to try to get even widths? */
const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
int vertex_group; /* vertex group index, maybe set if vertex_only */
int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
@@ -207,6 +215,7 @@ static int bev_debug_flags = 0;
#define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2)
#define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4)
+
/* this flag values will get set on geom we want to return in 'out' slots for edges and verts */
#define EDGE_OUT 4
#define VERT_OUT 8
@@ -260,6 +269,9 @@ static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float
vm->boundstart->prev = ans;
}
ans->profile.super_r = PRO_LINE_R;
+ ans->adjchain = NULL;
+ ans->sinratio = 1.0f;
+ ans->visited = false;
vm->count++;
return ans;
}
@@ -342,52 +354,6 @@ static EdgeHalf *find_other_end_edge_half(BevelParams *bp, EdgeHalf *e, BevVert
return NULL;
}
-static bool other_edge_half_visited(BevelParams *bp, EdgeHalf *e)
-{
- BevVert *bvo;
-
- bvo = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2);
- if (bvo)
- return bvo->visited;
- else
- return false;
-}
-
-static bool edge_half_offset_changed(EdgeHalf *e)
-{
- return e->offset_l != e->offset_l_spec ||
- e->offset_r != e->offset_r_spec;
-}
-
-static float adjusted_rel_change(float val, float spec)
-{
- float relchg;
-
- relchg = 0.0f;
- if (val != spec) {
- if (spec == 0)
- relchg = 1000.0f; /* arbitrary large value */
- else
- relchg = fabsf((val - spec) / spec);
- }
- return relchg;
-}
-
-static float max_edge_half_offset_rel_change(BevVert *bv)
-{
- int i;
- float max_rel_change;
- EdgeHalf *e;
-
- max_rel_change = 0.0f;
- for (i = 0; i < bv->edgecount; i++) {
- e = &bv->edges[i];
- max_rel_change = max_ff(max_rel_change, adjusted_rel_change(e->offset_l, e->offset_l_spec));
- max_rel_change = max_ff(max_rel_change, adjusted_rel_change(e->offset_r, e->offset_r_spec));
- }
- return max_rel_change;
-}
-
/* Return the next EdgeHalf after from_e that is beveled.
* If from_e is NULL, find the first beveled edge. */
static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
@@ -818,10 +784,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
copy_v3_v3(off1a, v->co);
d = max_ff(e1->offset_r, e2->offset_l);
madd_v3_v3fl(off1a, norm_perp1, d);
- if (e1->offset_r != d)
- e1->offset_r = d;
- else if (e2->offset_l != d)
- e2->offset_l = d;
copy_v3_v3(meetco, off1a);
}
else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG) {
@@ -830,10 +792,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
* common line, at offset distance from v. */
d = max_ff(e1->offset_r, e2->offset_l);
slide_dist(e2, v, d, meetco);
- if (e1->offset_r != d)
- e1->offset_r = d;
- else if (e2->offset_l != d)
- e2->offset_l = d;
}
else {
/* Get normal to plane where meet point should be,
@@ -871,7 +829,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
negate_v3(norm_v2);
}
-
/* get vectors perp to each edge, perp to norm_v, and pointing into face */
cross_v3_v3v3(norm_perp1, dir1, norm_v1);
cross_v3_v3v3(norm_perp2, dir2, norm_v2);
@@ -891,9 +848,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
if (isect_kind == 0) {
/* lines are collinear: we already tested for this, but this used a different epsilon */
copy_v3_v3(meetco, off1a); /* just to do something */
- d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
- if (fabsf(d - e2->offset_l) > BEVEL_EPSILON)
- e2->offset_l = d;
}
else {
/* The lines intersect, but is it at a reasonable place?
@@ -903,11 +857,9 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
* or if the offset amount is > the edge length*/
if (e1->offset_r == 0.0f && is_outside_edge(e1, meetco, &closer_v)) {
copy_v3_v3(meetco, closer_v->co);
- e2->offset_l = len_v3v3(meetco, v->co);
}
if (e2->offset_l == 0.0f && is_outside_edge(e2, meetco, &closer_v)) {
copy_v3_v3(meetco, closer_v->co);
- e1->offset_r = len_v3v3(meetco, v->co);
}
if (edges_between && e1->offset_r > 0.0f && e2->offset_l > 0.0f) {
/* Try to drop meetco to a face between e1 and e2 */
@@ -926,8 +878,6 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
break;
}
}
- e1->offset_r = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
- e2->offset_l = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
}
}
}
@@ -994,40 +944,27 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em
/* Calculate the best place for a meeting point for the offsets from edges e1 and e2
* on the in-between edge emid. Viewed from the vertex normal side, the CCW
* order of these edges is e1, emid, e2.
- * The offsets probably do not meet at a common point on emid, so need to pick
- * one that causes the least problems. If the other end of one of e1 or e2 has been visited
- * already, prefer to keep the offset the same on this end.
- * Otherwise, pick a point between the two intersection points on emid that minimizes
- * the sum of squares of errors from desired offset. */
-static void offset_on_edge_between(
- BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
- BMVert *v, float meetco[3])
+ * Return true if we placed meetco as compromise between where two edges met.
+ * If we did, put ration of sines of angles in *r_sinratio too */
+static bool offset_on_edge_between(
+ EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
+ BMVert *v, float meetco[3], float *r_sinratio)
{
- float d, ang1, ang2, sina1, sina2, lambda;
+ float ang1, ang2;
float meet1[3], meet2[3];
- bool visited1, visited2, ok1, ok2;
+ bool ok1, ok2;
+ bool retval = false;
BLI_assert(e1->is_bev && e2->is_bev && !emid->is_bev);
- visited1 = other_edge_half_visited(bp, e1);
- visited2 = other_edge_half_visited(bp, e2);
-
ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1);
ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2);
if (ok1 && ok2) {
- if (visited1 && !visited2) {
- copy_v3_v3(meetco, meet1);
- }
- else if (!visited1 && visited2) {
- copy_v3_v3(meetco, meet2);
- }
- else {
- /* find best compromise meet point */
- sina1 = sinf(ang1);
- sina2 = sinf(ang2);
- lambda = sina2 * sina2 / (sina1 * sina1 + sina2 * sina2);
- interp_v3_v3v3(meetco, meet1, meet2, lambda);
- }
+ mid_v3_v3v3(meetco, meet1, meet2);
+ if (r_sinratio)
+ /* ang1 should not be 0, but be paranoid */
+ *r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1);
+ retval = true;
}
else if (ok1 && !ok2) {
copy_v3_v3(meetco, meet1);
@@ -1041,13 +978,7 @@ static void offset_on_edge_between(
slide_dist(emid, v, e1->offset_r, meetco);
}
- /* offsets may have changed now */
- d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
- if (fabsf(d - e1->offset_r) > BEVEL_EPSILON)
- e1->offset_r = d;
- d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
- if (fabsf(d - e2->offset_l) > BEVEL_EPSILON)
- e2->offset_l = d;
+ return retval;
}
/* Offset by e->offset in plane with normal plane_no, on left if left==true,
@@ -1806,6 +1737,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf
}
}
+#if 0
/* Return a value that is v if v is within BEVEL_MAX_ADJUST_PCT of the spec (assumed positive),
* else clamp to make it at most that far away from spec */
static float clamp_adjust(float v, float spec)
@@ -1819,6 +1751,7 @@ static float clamp_adjust(float v, float spec)
else
return v;
}
+#endif
/* Make a circular list of BoundVerts for bv, each of which has the coordinates
* of a vertex on the boundary of the beveled vertex bv->v.
@@ -1835,11 +1768,10 @@ static float clamp_adjust(float v, float spec)
static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
{
MemArena *mem_arena = bp->mem_arena;
- EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eother;
+ EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eon;
BoundVert *v;
- BevVert *bvother;
VMesh *vm;
- float co[3];
+ float co[3], r;
int nip, nnip;
/* Current bevel
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list