forked from bartvdbraak/blender
Bevel Fix for nonplanar faces / reflex angles
When beveling two adjacent edges, code used face normal instead of the face-corner normal (these can be different for nonplanar faces); the bevel may look uneven in such cases. Switched to using corner normal, and needed to fix the case where the edges meet at a reflex angle. Fixed a similar case when beveling two edges with one non-beveled in between. Also removed unnecessary argument from offset_meet.
This commit is contained in:
parent
25560a3734
commit
1158c1f7c0
@ -468,14 +468,12 @@ static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3])
|
||||
* 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
|
||||
* the bevel vertex, e1 precedes e2 in CCW order.
|
||||
* If on_right is true, offset edge is on right of both edges, where e1 enters v and
|
||||
* e2 leave it. If on_right is false, then the offset edge is on the left.
|
||||
* Offset edge is on right of both edges, where e1 enters v and e2 leave it.
|
||||
* When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2),
|
||||
* but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may
|
||||
* lead to different offsets) then meeting point can be found be intersecting offset lines.
|
||||
*/
|
||||
static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f,
|
||||
int on_right, float meetco[3])
|
||||
static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float meetco[3])
|
||||
{
|
||||
float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3],
|
||||
off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], ang;
|
||||
@ -506,16 +504,15 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f,
|
||||
slide_dist(e2, v, e2->offset_l, meetco);
|
||||
}
|
||||
else {
|
||||
/* get normal to plane where meet point should be */
|
||||
/* Get normal to plane where meet point should be,
|
||||
* using cross product instead of f->no in case f is non-planar.
|
||||
* If e1-v-e2 is a reflex angle (viewed from vertex normal side), need to flip*/
|
||||
cross_v3_v3v3(norm_v, dir2, dir1);
|
||||
normalize_v3(norm_v);
|
||||
if (!on_right)
|
||||
if (dot_v3v3(norm_v, v->no) < 0.0f)
|
||||
negate_v3(norm_v);
|
||||
|
||||
/* get vectors perp to each edge, perp to norm_v, and pointing into face */
|
||||
if (f) {
|
||||
copy_v3_v3(norm_v, f->no);
|
||||
}
|
||||
cross_v3_v3v3(norm_perp1, dir1, norm_v);
|
||||
cross_v3_v3v3(norm_perp2, dir2, norm_v);
|
||||
normalize_v3(norm_perp1);
|
||||
@ -551,12 +548,12 @@ static void offset_on_edge_between(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2,
|
||||
* Prefer the one whose other end hasn't been constructed yet.
|
||||
* Following will choose to change e2 if both have already been constructed. */
|
||||
if (find_other_end_edge_half(bp, e1)) {
|
||||
offset_meet(e1, emid, v, e1->fnext, TRUE, meetco);
|
||||
offset_meet(e1, emid, v, e1->fnext, meetco);
|
||||
/* now e2's left offset is probably different */
|
||||
e2->offset_l = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e2->e, v)->co);
|
||||
}
|
||||
else {
|
||||
offset_meet(emid, e2, v, emid->fnext, TRUE, meetco);
|
||||
offset_meet(emid, e2, v, emid->fnext, meetco);
|
||||
/* now e1's right offset is probably different */
|
||||
e1->offset_r = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co);
|
||||
}
|
||||
@ -585,6 +582,14 @@ static void offset_in_two_planes(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, Ed
|
||||
/* calculate face normals at corner in case faces are nonplanar */
|
||||
cross_v3_v3v3(f1no, dirmid, dir1);
|
||||
cross_v3_v3v3(f2no, dirmid, dir2);
|
||||
|
||||
/* if e1-v-emid or emid-v-e2 are reflex angles, need to flip corner normals */
|
||||
if (dot_v3v3(f1no, v->no) < 0.0f)
|
||||
negate_v3(f1no);
|
||||
if (dot_v3v3(f2no, v->no) < 0.0f)
|
||||
negate_v3(f2no);
|
||||
|
||||
/* get vectors perpendicular to e1 and e2, pointing into the proper faces */
|
||||
cross_v3_v3v3(norm_perp1, dir1, f1no);
|
||||
normalize_v3(norm_perp1);
|
||||
cross_v3_v3v3(norm_perp2, dir2, f2no);
|
||||
@ -874,7 +879,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv)
|
||||
/* handle only left side of beveled edge e here: next iteration should do right side */
|
||||
if (e->prev->is_bev) {
|
||||
BLI_assert(e->prev != e); /* see: wire edge special case */
|
||||
offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co);
|
||||
offset_meet(e->prev, e, bv->v, e->fprev, co);
|
||||
v = add_new_bound_vert(mem_arena, vm, co);
|
||||
v->efirst = e->prev;
|
||||
v->elast = v->ebev = e;
|
||||
@ -899,7 +904,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv)
|
||||
}
|
||||
else {
|
||||
/* neither e->prev nor e->prev->prev are beveled: make on-edge on e->prev */
|
||||
offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co);
|
||||
offset_meet(e->prev, e, bv->v, e->fprev, co);
|
||||
v = add_new_bound_vert(mem_arena, vm, co);
|
||||
v->efirst = e->prev;
|
||||
v->elast = v->ebev = e;
|
||||
@ -917,7 +922,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv)
|
||||
}
|
||||
else if (e->prev->is_bev) {
|
||||
/* on-edge meet between e->prev and e */
|
||||
offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co);
|
||||
offset_meet(e->prev, e, bv->v, e->fprev, co);
|
||||
v = add_new_bound_vert(mem_arena, vm, co);
|
||||
v->efirst = e->prev;
|
||||
v->elast = e;
|
||||
|
Loading…
Reference in New Issue
Block a user