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:
Diffstat (limited to 'source/blender/bmesh/tools/bmesh_bevel.c')
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c303
1 files changed, 244 insertions, 59 deletions
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index b9c9aa3aec8..9497466723a 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -59,6 +59,8 @@
#define BEVEL_SMALL_ANG DEG2RADF(10.0f)
/** Difference in dot products that corresponds to 10 degree difference between vectors. */
#define BEVEL_SMALL_ANG_DOT 1 - cosf(BEVEL_SMALL_ANG)
+/** Difference in dot products that corresponds to 2.0 degree difference between vectors. */
+#define BEVEL_EPSILON_ANG_DOT 1 - cosf(BEVEL_EPSILON_ANG)
#define BEVEL_MAX_ADJUST_PCT 10.0f
#define BEVEL_MAX_AUTO_ADJUST_PCT 300.0f
#define BEVEL_MATCH_SPEC_WEIGHT 0.2
@@ -301,14 +303,14 @@ typedef enum {
} FKind;
/** Helper for keeping track of angle kind. */
-enum {
+typedef enum AngleKind {
/** Angle less than 180 degrees. */
ANGLE_SMALLER = -1,
/** 180 degree angle. */
ANGLE_STRAIGHT = 0,
/** Angle greater than 180 degrees. */
ANGLE_LARGER = 1,
-};
+} AngleKind;
/** Bevel parameters and state. */
typedef struct BevelParams {
@@ -432,6 +434,18 @@ static bool nearly_parallel(const float d1[3], const float d2[3])
return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG);
}
+/**
+ * \return True if d1 and d2 are parallel or nearly parallel.
+ */
+static bool nearly_parallel_normalized(const float d1[3], const float d2[3])
+{
+ BLI_ASSERT_UNIT_V3(d1);
+ BLI_ASSERT_UNIT_V3(d2);
+
+ const float direction_dot = dot_v3v3(d1, d2);
+ return compare_ff(fabsf(direction_dot), 1.0f, BEVEL_EPSILON_ANG_DOT);
+}
+
/* Make a new BoundVert of the given kind, inserting it at the end of the circular linked
* list with entry point bv->boundstart, and return it. */
static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3])
@@ -1087,7 +1101,7 @@ static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_
}
/* Return whether the angle is less than, equal to, or larger than 180 degrees. */
-static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
+static AngleKind edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
{
BMVert *v1 = BM_edge_other_vert(e1->e, v);
BMVert *v2 = BM_edge_other_vert(e2->e, v);
@@ -1096,6 +1110,12 @@ static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
sub_v3_v3v3(dir2, v->co, v2->co);
normalize_v3(dir1);
normalize_v3(dir2);
+
+ /* First check for in-line edges using a simpler test. */
+ if (nearly_parallel_normalized(dir1, dir2)) {
+ return ANGLE_STRAIGHT;
+ }
+
/* Angles are in [0,pi]. Need to compare cross product with normal to see if they are reflex. */
float cross[3];
cross_v3_v3v3(cross, dir1, dir2);
@@ -1110,11 +1130,8 @@ static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
else {
no = v->no;
}
- float dot = dot_v3v3(cross, no);
- if (fabsf(dot) < BEVEL_EPSILON_BIG) {
- return ANGLE_STRAIGHT;
- }
- if (dot < 0.0f) {
+
+ if (dot_v3v3(cross, no) < 0.0f) {
return ANGLE_LARGER;
}
return ANGLE_SMALLER;
@@ -1149,6 +1166,113 @@ static bool point_between_edges(
return (ang11 - ang1co > -BEVEL_EPSILON_ANG);
}
+/* Is the angle swept from e1 to e2, CCW when viewed from the normal side of f,
+ * not a reflex angle or a straight angle? Assume e1 and e2 share a vert. */
+static bool edge_edge_angle_less_than_180(const BMEdge *e1, const BMEdge *e2, const BMFace *f)
+{
+ float dir1[3], dir2[3], cross[3];
+ BLI_assert(f != NULL);
+ BMVert *v, *v1, *v2;
+ if (e1->v1 == e2->v1) {
+ v = e1->v1;
+ v1 = e1->v2;
+ v2 = e2->v2;
+ }
+ else if (e1->v1 == e2->v2) {
+ v = e1->v1;
+ v1 = e1->v2;
+ v2 = e2->v1;
+ }
+ else if (e1->v2 == e2->v1) {
+ v = e1->v2;
+ v1 = e1->v1;
+ v2 = e2->v2;
+ }
+ else if (e1->v2 == e2->v2) {
+ v = e1->v2;
+ v1 = e1->v1;
+ v2 = e2->v1;
+ }
+ else {
+ BLI_assert(false);
+ return false;
+ }
+ sub_v3_v3v3(dir1, v1->co, v->co);
+ sub_v3_v3v3(dir2, v2->co, v->co);
+ cross_v3_v3v3(cross, dir1, dir2);
+ return dot_v3v3(cross, f->no) > 0.0f;
+}
+
+/* When the offset_type is BEVEL_AMT_PERCENT or BEVEL_AMT_ABSOLUTE, fill in the coordinates
+ * of the lines whose intersection defines the boundary point between e1 and e2 with common
+ * vert v, as defined in the parameters of offset_meet.
+ */
+static void offset_meet_lines_percent_or_absolute(BevelParams *bp,
+ EdgeHalf *e1,
+ EdgeHalf *e2,
+ BMVert *v,
+ float r_l1a[3],
+ float r_l1b[3],
+ float r_l2a[3],
+ float r_l2b[3])
+{
+ /* Get points the specified distance along each leg.
+ * Note: not all BevVerts and EdgeHalfs have been made yet, so we have
+ * to find required edges by moving around faces and use fake EdgeHalfs for
+ * some of the edges. If there aren't faces to move around, we have to give up.
+ * The legs we need are:
+ * e0 : the next edge around e1->fnext (==f1) after e1.
+ * e3 : the prev edge around e2->fprev (==f2) before e2.
+ * e4 : the previous edge around f1 before e1 (may be e2).
+ * e5 : the next edge around f2 after e2 (may be e1).
+ */
+ BMVert *v1, *v2;
+ EdgeHalf e0, e3, e4, e5;
+ BMFace *f1, *f2;
+ float d0, d3, d4, d5;
+ v1 = BM_edge_other_vert(e1->e, v);
+ v2 = BM_edge_other_vert(e2->e, v);
+ f1 = e1->fnext;
+ f2 = e2->fprev;
+ bool no_offsets = f1 == NULL || f2 == NULL;
+ if (!no_offsets) {
+ BMLoop *l = BM_face_vert_share_loop(f1, v1);
+ e0.e = l->e;
+ l = BM_face_vert_share_loop(f2, v2);
+ e3.e = l->prev->e;
+ l = BM_face_vert_share_loop(f1, v);
+ e4.e = l->prev->e;
+ l = BM_face_vert_share_loop(f2, v);
+ e5.e = l->e;
+ /* All the legs must be visible from their opposite legs. */
+ no_offsets = !edge_edge_angle_less_than_180(e0.e, e1->e, f1) ||
+ !edge_edge_angle_less_than_180(e1->e, e4.e, f1) ||
+ !edge_edge_angle_less_than_180(e2->e, e3.e, f2) ||
+ !edge_edge_angle_less_than_180(e5.e, e2->e, f1);
+ if (!no_offsets) {
+ if (bp->offset_type == BEVEL_AMT_ABSOLUTE) {
+ d0 = d3 = d4 = d5 = bp->offset;
+ }
+ else {
+ d0 = bp->offset * BM_edge_calc_length(e0.e) / 100.0f;
+ d3 = bp->offset * BM_edge_calc_length(e3.e) / 100.0f;
+ d4 = bp->offset * BM_edge_calc_length(e4.e) / 100.0f;
+ d5 = bp->offset * BM_edge_calc_length(e5.e) / 100.0f;
+ }
+ slide_dist(&e4, v, d4, r_l1a);
+ slide_dist(&e0, v1, d0, r_l1b);
+ slide_dist(&e5, v, d5, r_l2a);
+ slide_dist(&e3, v2, d3, r_l2b);
+ }
+ }
+ if (no_offsets) {
+ copy_v3_v3(r_l1a, v->co);
+ copy_v3_v3(r_l1b, v1->co);
+ copy_v3_v3(r_l2a, v->co);
+ copy_v3_v3(r_l2b, v2->co);
+ }
+}
+
/**
* Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco.
* e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of
@@ -1167,7 +1291,8 @@ static bool point_between_edges(
* \param e_in_plane: If we need to drop from the calculated offset lines to one of the faces,
* we don't want to drop onto the 'in plane' face, so if this is not null skip this edge's faces.
*/
-static void offset_meet(EdgeHalf *e1,
+static void offset_meet(BevelParams *bp,
+ EdgeHalf *e1,
EdgeHalf *e2,
BMVert *v,
BMFace *f,
@@ -1209,7 +1334,21 @@ static void offset_meet(EdgeHalf *e1,
copy_v3_v3(norm_v, f->no);
}
else {
- copy_v3_v3(norm_v, v->no);
+ /* Get average of face norms of faces between e and e2. */
+ int fcount = 0;
+ zero_v3(norm_v);
+ for (EdgeHalf *eloop = e1; eloop != e2; eloop = eloop->next) {
+ if (eloop->fnext != NULL) {
+ add_v3_v3(norm_v, eloop->fnext->no);
+ fcount++;
+ }
+ }
+ if (fcount == 0) {
+ copy_v3_v3(norm_v, v->no);
+ }
+ else {
+ mul_v3_fl(norm_v, 1.0f / fcount);
+ }
}
add_v3_v3(dir1, dir2);
cross_v3_v3v3(norm_perp1, dir1, norm_v);
@@ -1273,14 +1412,19 @@ static void offset_meet(EdgeHalf *e1,
normalize_v3(norm_perp1);
normalize_v3(norm_perp2);
- /* Get points that are offset distances from each line, then another point on each line. */
float off1a[3], off1b[3], off2a[3], off2b[3];
- copy_v3_v3(off1a, v->co);
- madd_v3_v3fl(off1a, norm_perp1, e1->offset_r);
- add_v3_v3v3(off1b, off1a, dir1);
- copy_v3_v3(off2a, v->co);
- madd_v3_v3fl(off2a, norm_perp2, e2->offset_l);
- add_v3_v3v3(off2b, off2a, dir2);
+ if (ELEM(bp->offset_type, BEVEL_AMT_PERCENT, BEVEL_AMT_ABSOLUTE)) {
+ offset_meet_lines_percent_or_absolute(bp, e1, e2, v, off1a, off1b, off2a, off2b);
+ }
+ else {
+ /* Get points that are offset distances from each line, then another point on each line. */
+ copy_v3_v3(off1a, v->co);
+ madd_v3_v3fl(off1a, norm_perp1, e1->offset_r);
+ add_v3_v3v3(off1b, off1a, dir1);
+ copy_v3_v3(off2a, v->co);
+ madd_v3_v3fl(off2a, norm_perp2, e2->offset_l);
+ add_v3_v3v3(off2b, off2a, dir2);
+ }
/* Intersect the offset lines. */
float isect2[3];
@@ -1407,9 +1551,16 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em
* in-between edge emid. Viewed from the vertex normal side, the CCW order of these edges is e1,
* emid, e2. Return true if we placed meetco as compromise between where two edges met. If we did,
* put the ratio of sines of angles in *r_sinratio too.
+ * However, if the bp->offset_type is BEVEL_AMT_PERCENT or BEVEL_AMT_ABSOLUTE, we just slide
+ * along emid by the specified amount.
*/
-static bool offset_on_edge_between(
- EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v, float meetco[3], float *r_sinratio)
+static bool offset_on_edge_between(BevelParams *bp,
+ EdgeHalf *e1,
+ EdgeHalf *e2,
+ EdgeHalf *emid,
+ BMVert *v,
+ float meetco[3],
+ float *r_sinratio)
{
bool retval = false;
@@ -1419,6 +1570,22 @@ static bool offset_on_edge_between(
float meet1[3], meet2[3];
bool ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1);
bool ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2);
+ if (ELEM(bp->offset_type, BEVEL_AMT_PERCENT, BEVEL_AMT_ABSOLUTE)) {
+ BMVert *v2 = BM_edge_other_vert(emid->e, v);
+ if (bp->offset_type == BEVEL_AMT_PERCENT) {
+ interp_v3_v3v3(meetco, v->co, v2->co, bp->offset / 100.0f);
+ }
+ else {
+ float dir[3];
+ sub_v3_v3v3(dir, v2->co, v->co);
+ normalize_v3(dir);
+ madd_v3_v3v3fl(meetco, v->co, dir, bp->offset);
+ }
+ if (r_sinratio) {
+ *r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1);
+ }
+ return true;
+ }
if (ok1 && ok2) {
mid_v3_v3v3(meetco, meet1, meet2);
if (r_sinratio) {
@@ -2005,7 +2172,7 @@ static void snap_to_superellipsoid(float co[3], const float super_r, bool midlin
float x = a;
float y = b;
float z = c;
- if (r == PRO_SQUARE_R || r == PRO_SQUARE_IN_R) {
+ if (ELEM(r, PRO_SQUARE_R, PRO_SQUARE_IN_R)) {
/* Will only be called for 2d profile. */
BLI_assert(fabsf(z) < BEVEL_EPSILON);
z = 0.0f;
@@ -2288,7 +2455,7 @@ static void bevel_harden_normals(BevelParams *bp, BMesh *bm)
BMFace *f;
BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
FKind fkind = get_face_kind(bp, f);
- if (fkind == F_ORIG || fkind == F_RECON) {
+ if (ELEM(fkind, F_ORIG, F_RECON)) {
continue;
}
BMIter liter;
@@ -2554,7 +2721,9 @@ static void build_boundary_terminal_edge(BevelParams *bp,
EdgeHalf *e = efirst;
float co[3];
if (bv->edgecount == 2) {
- /* Only 2 edges in, so terminate the edge with an artificial vertex on the unbeveled edge. */
+ /* Only 2 edges in, so terminate the edge with an artificial vertex on the unbeveled edge.
+ * If the offset type is BEVEL_AMT_PERCENT or BEVEL_AMT_ABSOLUTE, what to do is a bit
+ * undefined (there aren't two "legs"), so just let the code do what it does. */
const float *no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
offset_in_plane(e, no, true, co);
if (construct) {
@@ -2592,7 +2761,13 @@ static void build_boundary_terminal_edge(BevelParams *bp,
* edge to make a poly or adj mesh, because e->prev has offset 0, offset_meet will put co on
* that edge. */
/* TODO: should do something else if angle between e and e->prev > 180 */
- offset_meet(e->prev, e, bv->v, e->fprev, false, co, NULL);
+ bool leg_slide = bp->offset_type == BEVEL_AMT_PERCENT || bp->offset_type == BEVEL_AMT_ABSOLUTE;
+ if (leg_slide) {
+ slide_dist(e->prev, bv->v, e->offset_l, co);
+ }
+ else {
+ offset_meet(bp, e->prev, e, bv->v, e->fprev, false, co, NULL);
+ }
if (construct) {
BoundVert *bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = e->prev;
@@ -2604,7 +2779,12 @@ static void build_boundary_terminal_edge(BevelParams *bp,
adjust_bound_vert(e->leftv, co);
}
e = e->next;
- offset_meet(e->prev, e, bv->v, e->fprev, false, co, NULL);
+ if (leg_slide) {
+ slide_dist(e, bv->v, e->prev->offset_r, co);
+ }
+ else {
+ offset_meet(bp, e->prev, e, bv->v, e->fprev, false, co, NULL);
+ }
if (construct) {
BoundVert *bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = e->prev;
@@ -2823,27 +3003,27 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
float r, co[3];
if (in_plane == 0 && not_in_plane == 0) {
- offset_meet(e, e2, bv->v, e->fnext, false, co, NULL);
+ offset_meet(bp, e, e2, bv->v, e->fnext, false, co, NULL);
}
else if (not_in_plane > 0) {
if (bp->loop_slide && not_in_plane == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) {
- if (offset_on_edge_between(e, e2, enip, bv->v, co, &r)) {
+ if (offset_on_edge_between(bp, e, e2, enip, bv->v, co, &r)) {
eon = enip;
}
}
else {
- offset_meet(e, e2, bv->v, NULL, true, co, eip);
+ offset_meet(bp, e, e2, bv->v, NULL, true, co, eip);
}
}
else {
/* n_in_plane > 0 and n_not_in_plane == 0. */
if (bp->loop_slide && in_plane == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) {
- if (offset_on_edge_between(e, e2, eip, bv->v, co, &r)) {
+ if (offset_on_edge_between(bp, e, e2, eip, bv->v, co, &r)) {
eon = eip;
}
}
else {
- offset_meet(e, e2, bv->v, e->fnext, true, co, eip);
+ offset_meet(bp, e, e2, bv->v, e->fnext, true, co, eip);
}
}
@@ -2861,7 +3041,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
for (EdgeHalf *e3 = e->next; e3 != e2; e3 = e3->next) {
e3->leftv = e3->rightv = v;
}
- int ang_kind = edges_angle_kind(e, e2, bv->v);
+ AngleKind ang_kind = edges_angle_kind(e, e2, bv->v);
/* Are we doing special mitering?
* There can only be one outer reflex angle, so only one outer miter,
@@ -2939,7 +3119,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
else { /* construct == false. */
- int ang_kind = edges_angle_kind(e, e2, bv->v);
+ AngleKind ang_kind = edges_angle_kind(e, e2, bv->v);
if ((miter_outer != BEVEL_MITER_SHARP && !emiter && ang_kind == ANGLE_LARGER) ||
(miter_inner != BEVEL_MITER_SHARP && ang_kind == ANGLE_SMALLER)) {
if (ang_kind == ANGLE_LARGER) {
@@ -4402,13 +4582,13 @@ static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
sub_v3_v3v3(edir, e->e->v1->co, e->e->v2->co);
plane_from_point_normal_v3(plane, co, edir);
- float va0[3], vb0[3], vmid0[3];
- closest_to_plane_v3(va0, plane, pro->start);
- closest_to_plane_v3(vb0, plane, pro->end);
- closest_to_plane_v3(vmid0, plane, pro->middle);
+ float start_plane[3], end_plane[3], middle_plane[3];
+ closest_to_plane_v3(start_plane, plane, pro->start);
+ closest_to_plane_v3(end_plane, plane, pro->end);
+ closest_to_plane_v3(middle_plane, plane, pro->middle);
float m[4][4], minv[4][4];
- if (make_unit_square_map(va0, vmid0, vb0, m) && invert_m4_m4(minv, m)) {
+ if (make_unit_square_map(start_plane, middle_plane, end_plane, m) && invert_m4_m4(minv, m)) {
/* Transform co and project it onto superellipse. */
float p[3];
mul_v3_m4v3(p, minv, co);
@@ -4419,9 +4599,9 @@ static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
copy_v3_v3(co, snap);
}
else {
- /* Planar case: just snap to line va0--vb0. */
+ /* Planar case: just snap to line start_plane--end_plane. */
float p[3];
- closest_to_line_segment_v3(p, co, va0, vb0);
+ closest_to_line_segment_v3(p, co, start_plane, end_plane);
copy_v3_v3(co, p);
}
}
@@ -4453,7 +4633,7 @@ static VMesh *pipe_adj_vmesh(BevelParams *bp, BevVert *bv, BoundVert *vpipe)
if (bp->profile_type == BEVEL_PROFILE_CUSTOM) {
/* Find both profile vertices that correspond to this point. */
float *profile_point_pipe1, *profile_point_pipe2, f;
- if (i == ipipe1 || i == ipipe2) {
+ if (ELEM(i, ipipe1, ipipe2)) {
if (n_bndv == 3 && i == ipipe1) {
/* This part of the vmesh is the triangular corner between the two pipe profiles. */
int ring = max_ii(j, k);
@@ -4762,7 +4942,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
copy_v3_v3(bndco, bndv->nv.co);
EdgeHalf *e1 = bndv->efirst;
EdgeHalf *e2 = bndv->elast;
- int ang_kind = ANGLE_STRAIGHT;
+ AngleKind ang_kind = ANGLE_STRAIGHT;
if (e1 && e2) {
ang_kind = edges_angle_kind(e1, e2, bv->v);
}
@@ -6040,27 +6220,21 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
break;
}
case BEVEL_AMT_PERCENT: {
- /* Offset needs to meet adjacent edges at percentage of their lengths. */
- BMVert *v1 = BM_edge_other_vert(e->prev->e, v);
- BMVert *v2 = BM_edge_other_vert(e->e, v);
- float z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
- e->offset_l_spec = BM_edge_calc_length(e->prev->e) * bp->offset * z / 100.0f;
- v1 = BM_edge_other_vert(e->e, v);
- v2 = BM_edge_other_vert(e->next->e, v);
- z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
- e->offset_r_spec = BM_edge_calc_length(e->next->e) * bp->offset * z / 100.0f;
+ /* Offset needs to meet adjacent edges at percentage of their lengths.
+ * Since the width isn't constant, we don't store a width at all, but
+ * rather the distance along the adjacent edge that we need to go
+ * at this end of the edge.
+ */
+
+ e->offset_l_spec = BM_edge_calc_length(e->prev->e) * bp->offset / 100.0f;
+ e->offset_r_spec = BM_edge_calc_length(e->next->e) * bp->offset / 100.0f;
+
break;
}
case BEVEL_AMT_ABSOLUTE: {
/* Like Percent, but the amount gives the absolute distance along adjacent edges. */
- BMVert *v1 = BM_edge_other_vert(e->prev->e, v);
- BMVert *v2 = BM_edge_other_vert(e->e, v);
- float z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
- e->offset_l_spec = bp->offset * z;
- v1 = BM_edge_other_vert(e->e, v);
- v2 = BM_edge_other_vert(e->next->e, v);
- z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
- e->offset_r_spec = bp->offset * z;
+ e->offset_l_spec = bp->offset;
+ e->offset_r_spec = bp->offset;
break;
}
default: {
@@ -6069,7 +6243,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
break;
}
}
- if (bp->offset_type != BEVEL_AMT_PERCENT && bp->offset_type != BEVEL_AMT_ABSOLUTE) {
+ if (!ELEM(bp->offset_type, BEVEL_AMT_PERCENT, BEVEL_AMT_ABSOLUTE)) {
e->offset_r_spec = e->offset_l_spec;
}
if (bp->use_weights) {
@@ -6611,7 +6785,7 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
BMIter iter;
BMLoop *l;
BM_ITER_ELEM (l, &iter, r_f, BM_LOOPS_OF_FACE) {
- if (l->v == verts[0] || l->v == verts[2]) {
+ if (ELEM(l->v, verts[0], verts[2])) {
BM_elem_flag_enable(l, BM_ELEM_LONG_TAG);
}
}
@@ -7072,6 +7246,17 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
EdgeHalf *ec;
BMVert *vd;
float kc;
+ if (ELEM(bp->offset_type, BEVEL_AMT_PERCENT, BEVEL_AMT_ABSOLUTE)) {
+ if (ea->is_bev && ebother != NULL && ebother->prev->is_bev) {
+ if (bp->offset_type == BEVEL_AMT_PERCENT) {
+ return 50.0f;
+ }
+ /* This is only right sometimes. The exact answer is very hard to calculate. */
+ float blen = BM_edge_calc_length(eb->e);
+ return bp->offset > blen / 2.0f ? blen / 2.0f : blen;
+ }
+ return no_collide_offset;
+ }
if (ebother != NULL) {
ec = ebother->prev; /* Note: this is in direction c --> d. */
vc = bvc->v;