Merge branch 'blender-v2.82-release'

This commit is contained in:
Hans Goudey 2020-01-13 12:15:29 -05:00
commit 4f7ad0050b
7 changed files with 176 additions and 153 deletions

View File

@ -994,23 +994,31 @@ static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1,
return (ang11 - ang1co > -BEVEL_EPSILON_ANG);
}
/*
/**
* 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.
* Except: if edges_between is true, there are edges between e1 and e2 in CCW order so they
* don't share a common face. We want the meeting point to be on an existing face so it
* should be dropped onto one of the intermediate faces, if possible.
* 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.
* but if the offsets are not equal (we allow for because the bevel modifier has edge weights that
* may lead to different offsets) then the meeting point can be found by intersecting offset lines.
* If making the meeting point significantly changes the left or right offset from the user spec,
* record the change in offset_l (or offset_r); later we can tell that a change has happened
* because the offset will differ from its original value in offset_l_spec (or offset_r_spec).
*
* \param edges_between If this is true, there are edges between e1 and e2 in CCW order so they
* don't share a common face. We want the meeting point to be on an existing face so it
* should be dropped onto one of the intermediate faces, if possible.
* \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, EdgeHalf *e2, BMVert *v, BMFace *f, bool edges_between, float meetco[3])
static void offset_meet(EdgeHalf *e1,
EdgeHalf *e2,
BMVert *v,
BMFace *f,
bool edges_between,
float meetco[3],
const EdgeHalf *e_in_plane)
{
float dir1[3], dir2[3], dir1n[3], dir2p[3], norm_v[3], norm_v1[3], norm_v2[3];
float norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3];
@ -1018,10 +1026,10 @@ static void offset_meet(
float ang, d;
BMVert *closer_v;
EdgeHalf *e, *e1next, *e2prev;
BMFace *ff;
BMFace *fnext;
int isect_kind;
/* get direction vectors for two offset lines */
/* Get direction vectors for two offset lines. */
sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
@ -1032,20 +1040,20 @@ static void offset_meet(
sub_v3_v3v3(dir2p, v->co, BM_edge_other_vert(e2prev->e, v)->co);
}
else {
/* shup up 'maybe unused' warnings */
/* Shut up 'maybe unused' warnings. */
zero_v3(dir1n);
zero_v3(dir2p);
}
ang = angle_v3v3(dir1, dir2);
if (ang < BEVEL_EPSILON_ANG) {
/* special case: e1 and e2 are parallel; put offset point perp to both, from v.
/* Special case: e1 and e2 are parallel; put offset point perp to both, from v.
* need to find a suitable plane.
* this code used to just use offset and dir1, but that makes for visible errors
* This code used to just use offset and dir1, but that makes for visible errors
* on a circle with > 200 sides, which trips this "nearly perp" code (see T61214).
* so use the average of the two, and the offset formula for angle bisector.
* if offsets are different, we're out of luck:
* use the max of the two (so get consistent looking results if the same situation
* If offsets are different, we're out of luck:
* Use the max of the two (so get consistent looking results if the same situation
* arises elsewhere in the object but with opposite roles for e1 and e2 */
if (f) {
copy_v3_v3(norm_v, f->no);
@ -1063,23 +1071,21 @@ static void offset_meet(
copy_v3_v3(meetco, off1a);
}
else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG) {
/* special case e1 and e2 are antiparallel, so bevel is into
* a zero-area face. Just make the offset point on the
* common line, at offset distance from v. */
/* Special case: e1 and e2 are antiparallel, so bevel is into a zero-area face.
* Just make the offset point on the common line, at offset distance from v. */
d = max_ff(e1->offset_r, e2->offset_l);
slide_dist(e2, v, d, meetco);
}
else {
/* Get normal to plane where meet point should be,
* using cross product instead of f->no in case f is non-planar.
* Except: sometimes locally there can be a small angle
* between dir1 and dir2 that leads to a normal that is actually almost
* perpendicular to the face normal; in this case it looks wrong to use
* the local (cross-product) normal, so use the face normal if the angle
* between dir1 and dir2 is smallish.
/* Get normal to plane where meet point should be, using cross product instead of f->no
* in case f is non-planar.
* Except: sometimes locally there can be a small angle between dir1 and dir2 that leads
* to a normal that is actually almost perpendicular to the face normal;
* in this case it looks wrong to use the local (cross-product) normal,
* so use the face normal if the angle between dir1 and dir2 is smallish.
* If e1-v-e2 is a reflex angle (viewed from vertex normal side), need to flip.
* Use f->no to figure out which side to look at angle from, as even if
* f is non-planar, will be more accurate than vertex normal */
* Use f->no to figure out which side to look at angle from, as even if f is non-planar,
* will be more accurate than vertex normal. */
if (f && ang < BEVEL_SMALL_ANG) {
copy_v3_v3(norm_v1, f->no);
copy_v3_v3(norm_v2, f->no);
@ -1093,7 +1099,7 @@ static void offset_meet(
copy_v3_v3(norm_v2, norm_v1);
}
else {
/* separate faces; get face norms at corners for each separately */
/* Separate faces; get face norms at corners for each separately. */
cross_v3_v3v3(norm_v1, dir1n, dir1);
normalize_v3(norm_v1);
f = e1->fnext;
@ -1108,13 +1114,13 @@ static void offset_meet(
}
}
/* get vectors perp to each edge, perp to norm_v, and pointing into face */
/* 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);
normalize_v3(norm_perp1);
normalize_v3(norm_perp2);
/* get points that are offset distances from each line, then another point on each line */
/* 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);
@ -1122,18 +1128,17 @@ static void offset_meet(
madd_v3_v3fl(off2a, norm_perp2, e2->offset_l);
add_v3_v3v3(off2b, off2a, dir2);
/* intersect the lines */
/* Intersect the offset lines. */
isect_kind = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
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 */
/* Lines are collinear: we already tested for this, but this used a different epsilon. */
copy_v3_v3(meetco, off1a); /* Just to do something. */
}
else {
/* The lines intersect, but is it at a reasonable place?
* One problem to check: if one of the offsets is 0, then don't
* want an intersection that is outside that edge itself.
* This can happen if angle between them is > 180 degrees,
* or if the offset amount is > the edge length*/
* One problem to check: if one of the offsets is 0, then don't want an intersection
* that is outside that edge itself. This can happen if angle between them is > 180 degrees,
* 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);
}
@ -1141,19 +1146,26 @@ static void offset_meet(
copy_v3_v3(meetco, closer_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 */
/* Try to drop meetco to a face between e1 and e2. */
if (isect_kind == 2) {
/* lines didn't meet in 3d: get average of meetco and isect2 */
/* Lines didn't meet in 3d: get average of meetco and isect2. */
mid_v3_v3v3(meetco, meetco, isect2);
}
for (e = e1; e != e2; e = e->next) {
ff = e->fnext;
if (!ff) {
fnext = e->fnext;
if (!fnext) {
continue;
}
plane_from_point_normal_v3(plane, v->co, ff->no);
plane_from_point_normal_v3(plane, v->co, fnext->no);
closest_to_plane_normalized_v3(dropco, plane, meetco);
if (point_between_edges(dropco, v, ff, e, e->next)) {
/* Don't drop to the faces next to the in plane edge. */
if (e_in_plane) {
ang = angle_v3v3(fnext->no, e_in_plane->fnext->no);
if ((fabsf(ang) < BEVEL_SMALL_ANG) || (fabsf(ang - (float)M_PI) < BEVEL_SMALL_ANG)) {
continue;
}
}
if (point_between_edges(dropco, v, fnext, e, e->next)) {
copy_v3_v3(meetco, dropco);
break;
}
@ -1163,8 +1175,7 @@ static void offset_meet(
}
}
/* Chosen so that 1/sin(BEVEL_GOOD_ANGLE) is about 4,
* giving that expansion factor to bevel width. */
/* Chosen so 1/sin(BEVEL_GOOD_ANGLE) is about 4, giving that expansion factor to bevel width. */
#define BEVEL_GOOD_ANGLE 0.25f
/* Calculate the meeting point between e1 and e2 (one of which should have zero offsets),
@ -1182,7 +1193,7 @@ static bool offset_meet_edge(
normalize_v3(dir1);
normalize_v3(dir2);
/* find angle from dir1 to dir2 as viewed from vertex normal side */
/* Find angle from dir1 to dir2 as viewed from vertex normal side. */
ang = angle_normalized_v3v3(dir1, dir2);
if (fabsf(ang) < BEVEL_GOOD_ANGLE) {
if (r_angle) {
@ -1192,7 +1203,7 @@ static bool offset_meet_edge(
}
cross_v3_v3v3(fno, dir1, dir2);
if (dot_v3v3(fno, v->no) < 0.0f) {
ang = 2.0f * (float)M_PI - ang; /* angle is reflex */
ang = 2.0f * (float)M_PI - ang; /* Angle is reflex. */
if (r_angle) {
*r_angle = ang;
}
@ -1219,7 +1230,7 @@ static bool offset_meet_edge(
}
/* Return true if it will look good to put the meeting point where offset_on_edge_between
* would put it. This means that neither side sees a reflex angle */
* would put it. This means that neither side sees a reflex angle. */
static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v)
{
float ang;
@ -1248,7 +1259,7 @@ static bool offset_on_edge_between(
if (ok1 && ok2) {
mid_v3_v3v3(meetco, meet1, meet2);
if (r_sinratio) {
/* ang1 should not be 0, but be paranoid */
/* ang1 should not be 0, but be paranoid. */
*r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1);
}
retval = true;
@ -1261,7 +1272,7 @@ static bool offset_on_edge_between(
}
else {
/* Neither offset line met emid.
* This should only happen if all three lines are on top of each other */
* This should only happen if all three lines are on top of each other. */
slide_dist(emid, v, e1->offset_r, meetco);
}
@ -1269,8 +1280,7 @@ static bool offset_on_edge_between(
}
/* Offset by e->offset in plane with normal plane_no, on left if left==true,
* else on right. If no is NULL, choose an arbitrary plane different
* from eh's direction. */
* else on right. If no is NULL, choose an arbitrary plane different from eh's direction. */
static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, float r[3])
{
float dir[3], no[3], fdir[3];
@ -1303,7 +1313,7 @@ static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, flo
madd_v3_v3fl(r, fdir, left ? e->offset_l : e->offset_r);
}
/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */
/* 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])
{
float otherco[3];
@ -1317,56 +1327,55 @@ static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3],
}
/* If there is a bndv->ebev edge, find the mid control point if necessary.
* It is the closest point on the beveled edge to the line segment between
* bndv and bndv->next. */
* 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 co1[3], co2[3], co3[3], d1[3], d2[3];
float start[3], end[3], co3[3], d1[3], d2[3];
bool do_linear_interp;
copy_v3_v3(co1, bndv->nv.co);
copy_v3_v3(co2, bndv->next->nv.co);
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;
/* projection direction is direction of the edge */
/* projection direction is direction of the edge. */
sub_v3_v3v3(pro->proj_dir, e->e->v1->co, e->e->v2->co);
if (e->is_rev) {
negate_v3(pro->proj_dir);
}
normalize_v3(pro->proj_dir);
project_to_edge(e->e, co1, co2, pro->middle);
project_to_edge(e->e, start, end, pro->middle);
if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
/* put arc endpoints on plane with normal proj_dir, containing middle */
add_v3_v3v3(co3, co1, pro->proj_dir);
if (!isect_line_plane_v3(pro->start, co1, co3, pro->middle, pro->proj_dir)) {
/* shouldn't happen */
copy_v3_v3(pro->start, co1);
/* Put arc endpoints on plane with normal proj_dir, containing middle. */
add_v3_v3v3(co3, start, pro->proj_dir);
if (!isect_line_plane_v3(pro->start, start, co3, pro->middle, pro->proj_dir)) {
/* Shouldn't happen. */
copy_v3_v3(pro->start, start);
}
add_v3_v3v3(co3, co2, pro->proj_dir);
if (!isect_line_plane_v3(pro->end, co2, co3, pro->middle, pro->proj_dir)) {
/* shouldn't happen */
copy_v3_v3(pro->end, co2);
add_v3_v3v3(co3, end, pro->proj_dir);
if (!isect_line_plane_v3(pro->end, end, co3, pro->middle, pro->proj_dir)) {
/* Shouldn't happen. */
copy_v3_v3(pro->end, end);
}
}
else {
copy_v3_v3(pro->start, co1);
copy_v3_v3(pro->end, co2);
copy_v3_v3(pro->start, start);
copy_v3_v3(pro->end, end);
}
/* default plane to project onto is the one with triangle co1 - middle - co2 in it */
sub_v3_v3v3(d1, pro->middle, co1);
sub_v3_v3v3(d2, pro->middle, co2);
/* Default plane to project onto is the one with triangle start - middle - end in it. */
sub_v3_v3v3(d1, pro->middle, start);
sub_v3_v3v3(d2, pro->middle, end);
normalize_v3(d1);
normalize_v3(d2);
cross_v3_v3v3(pro->plane_no, d1, d2);
normalize_v3(pro->plane_no);
if (nearly_parallel(d1, d2)) {
/* co1 - middle -co2 are collinear.
/* Start - middle - end are collinear.
* Should be case that beveled edge is coplanar with two boundary verts.
* We want to move the profile to that common plane, if possible.
* That makes the multi-segment bevels curve nicely in that plane, as users expect.
@ -1380,8 +1389,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
}
else {
if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
copy_v3_v3(pro->start, co1);
copy_v3_v3(pro->end, co2);
copy_v3_v3(pro->start, start);
copy_v3_v3(pro->end, end);
}
if (DEBUG_OLD_FLAT_MID) {
copy_v3_v3(pro->middle, bv->v->co);
@ -1389,7 +1398,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
else {
copy_v3_v3(pro->middle, bv->v->co);
if (e->prev->is_bev && e->next->is_bev && bv->selcount >= 3) {
/* want mid at the meet point of next and prev offset edges */
/* Want mid at the meet point of next and prev offset edges. */
float d3[3], d4[3], co4[3], meetco[3], isect2[3];
int isect_kind;
@ -1398,34 +1407,34 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
normalize_v3(d3);
normalize_v3(d4);
if (nearly_parallel(d3, d4)) {
/* offset lines are collinear - want linear interpolation */
mid_v3_v3v3(pro->middle, co1, co2);
/* Offset lines are collinear - want linear interpolation. */
mid_v3_v3v3(pro->middle, start, end);
do_linear_interp = true;
}
else {
add_v3_v3v3(co3, co1, d3);
add_v3_v3v3(co4, co2, d4);
isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2);
add_v3_v3v3(co3, start, d3);
add_v3_v3v3(co4, end, d4);
isect_kind = isect_line_line_v3(start, co3, end, co4, meetco, isect2);
if (isect_kind != 0) {
copy_v3_v3(pro->middle, meetco);
}
else {
/* offset lines don't intersect - want linear interpolation */
mid_v3_v3v3(pro->middle, co1, co2);
/* Offset lines don't intersect - want linear interpolation. */
mid_v3_v3v3(pro->middle, start, end);
do_linear_interp = true;
}
}
}
}
copy_v3_v3(pro->end, co2);
sub_v3_v3v3(d1, pro->middle, co1);
copy_v3_v3(pro->end, end);
sub_v3_v3v3(d1, pro->middle, start);
normalize_v3(d1);
sub_v3_v3v3(d2, pro->middle, co2);
sub_v3_v3v3(d2, pro->middle, end);
normalize_v3(d2);
cross_v3_v3v3(pro->plane_no, d1, d2);
normalize_v3(pro->plane_no);
if (nearly_parallel(d1, d2)) {
/* whole profile is collinear with edge: just interpolate */
/* Whole profile is collinear with edge: just interpolate. */
do_linear_interp = true;
}
else {
@ -1434,12 +1443,12 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
}
}
}
copy_v3_v3(pro->plane_co, co1);
copy_v3_v3(pro->plane_co, start);
}
else if (bndv->is_arc_start) {
/* assume pro->middle was alredy set */
copy_v3_v3(pro->start, co1);
copy_v3_v3(pro->end, co2);
/* Assume pro->middle was alredy set. */
copy_v3_v3(pro->start, start);
copy_v3_v3(pro->end, end);
pro->super_r = PRO_CIRCLE_R;
zero_v3(pro->plane_co);
zero_v3(pro->plane_no);
@ -1448,10 +1457,10 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
}
if (do_linear_interp) {
pro->super_r = PRO_LINE_R;
copy_v3_v3(pro->start, co1);
copy_v3_v3(pro->end, co2);
mid_v3_v3v3(pro->middle, co1, co2);
/* won't use projection for this line profile */
copy_v3_v3(pro->start, start);
copy_v3_v3(pro->end, end);
mid_v3_v3v3(pro->middle, start, end);
/* Won't use projection for this line profile. */
zero_v3(pro->plane_co);
zero_v3(pro->plane_no);
zero_v3(pro->proj_dir);
@ -2295,14 +2304,14 @@ static int count_bound_vert_seams(BevVert *bv)
return ans;
}
/* Is e between two planes where angle between is 180? */
/* Is e between two faces with a 180 degree angle between their normals? */
static bool eh_on_plane(EdgeHalf *e)
{
float dot;
if (e->fprev && e->fnext) {
dot = dot_v3v3(e->fprev->no, e->fnext->no);
if (fabsf(dot) <= BEVEL_EPSILON_BIG || fabsf(dot - 1.0f) <= BEVEL_EPSILON_BIG) {
if (fabsf(dot + 1.0f) <= BEVEL_EPSILON_BIG || fabsf(dot - 1.0f) <= BEVEL_EPSILON_BIG) {
return true;
}
}
@ -2422,7 +2431,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
* and join with the beveled 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);
offset_meet(e->prev, e, bv->v, e->fprev, false, co, NULL);
if (construct) {
bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = e->prev;
@ -2434,7 +2443,7 @@ 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);
offset_meet(e->prev, e, bv->v, e->fprev, false, co, NULL);
if (construct) {
bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = e->prev;
@ -2592,18 +2601,20 @@ static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *em
} while (v != vstart);
}
/* 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.
* This may adjust some EdgeHalf widths, and there might have to be
* a subsequent pass to make the widths as consistent as possible.
* The first time through, construct will be true and we are making the BoundVerts
* and setting up the BoundVert and EdgeHalf pointers appropriately.
* For a width consistency path, we just recalculate the coordinates of the
* BoundVerts. If the other ends have been (re)built already, then we
* copy the offsets from there to match, else we use the ideal (user-specified)
* widths.
* Also, if construct, decide on the mesh pattern that will be used inside the boundary.
* Doesn't make the actual BMVerts */
/**
* 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. This may adjust some EdgeHalf widths, and there might have
* to be a subsequent pass to make the widths as consistent as possible.
* Doesn't make the actual BMVerts.
*
* For a width consistency pass, we just recalculate the coordinates of the BoundVerts. If the
* other ends have been (re)built already, then we copy the offsets from there to match, else we
* use the ideal (user-specified) widths.
*
* \param construct The first time through, construct will be true and we are making the BoundVerts
* and setting up the BoundVert and EdgeHalf pointers appropriately. Also, if construct, decide on
* the mesh pattern that will be used inside the boundary.
*/
static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
{
MemArena *mem_arena = bp->mem_arena;
@ -2614,7 +2625,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
int in_plane, not_in_plane, miter_outer, miter_inner;
int ang_kind;
/* Current bevel does nothing if only one edge into a vertex */
/* Current bevel does nothing if only one edge into a vertex. */
if (bv->edgecount <= 1) {
return;
}
@ -2626,21 +2637,21 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
vm = bv->vmesh;
/* Find a beveled edge to be efirst */
/* Find a beveled edge to be efirst. */
e = efirst = next_bev(bv, NULL);
BLI_assert(e->is_bev);
if (bv->selcount == 1) {
/* Special case: only one beveled edge in */
/* Special case: only one beveled edge in. */
build_boundary_terminal_edge(bp, bv, efirst, construct);
return;
}
/* Special miters outside only for 3 or more beveled edges */
/* Special miters outside only for 3 or more beveled edges. */
miter_outer = (bv->selcount >= 3) ? bp->miter_outer : BEVEL_MITER_SHARP;
miter_inner = bp->miter_inner;
/* keep track of the first beveled edge of an outside miter (there can be at most 1 per bv */
/* Keep track of the first beveled edge of an outside miter (there can be at most 1 per bv). */
emiter = NULL;
/* There is more than one beveled edge.
@ -2650,14 +2661,13 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
do {
BLI_assert(e->is_bev);
eon = NULL;
/* Make the BoundVert for the right side of e; other side will be made
* when the beveled edge to the left of e is handled.
* Analyze edges until next beveled edge.
* They are either "in plane" (preceding and subsequent faces are coplanar) or not.
* The "non-in-plane" edges affect the silhouette and we prefer to slide along one of those if
* possible. */
in_plane = not_in_plane = 0; /* Counts of in-plane / not-in-plane */
enip = eip = NULL; /* representatives of each */
/* Make the BoundVert for the right side of e; the other side will be made when the beveled
* edge to the left of e is handled.
* Analyze edges until next beveled edge: They are either "in plane" (preceding and subsequent
* faces are coplanar) or not. The "non-in-plane" edges affect the silhouette and we prefer to
* slide along one of those if possible. */
in_plane = not_in_plane = 0; /* Counts of in-plane / not-in-plane. */
enip = eip = NULL; /* Representatives of each type. */
for (e2 = e->next; !e2->is_bev; e2 = e2->next) {
if (eh_on_plane(e2)) {
in_plane++;
@ -2668,8 +2678,9 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
enip = e2;
}
}
if (in_plane == 0 && not_in_plane == 0) {
offset_meet(e, e2, bv->v, e->fnext, false, co);
offset_meet(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)) {
@ -2678,7 +2689,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
else {
offset_meet(e, e2, bv->v, NULL, true, co);
offset_meet(e, e2, bv->v, NULL, true, co, eip);
}
}
else {
@ -2689,9 +2700,10 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
else {
offset_meet(e, e2, bv->v, e->fnext, true, co);
offset_meet(e, e2, bv->v, e->fnext, true, co, eip);
}
}
if (construct) {
v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = e;

View File

@ -204,6 +204,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
DRW_shgroup_uniform_bool_copy(grp, "selectEdges", pd->edit_mesh.do_edges || select_edge);
/* Verts */
state |= DRW_STATE_WRITE_DEPTH;
DRW_PASS_CREATE(psl->edit_mesh_verts_ps[i], state | pd->clipping_state);
if (select_vert) {

View File

@ -412,6 +412,11 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_motion_path_draw(vedata);
OVERLAY_extra_centers_draw(vedata);
if (DRW_state_is_select()) {
/* Edit modes have their own selection code. */
return;
}
/* Functions after this point can change FBO freely. */
switch (pd->ctx_mode) {

View File

@ -1055,6 +1055,7 @@ void DRW_mesh_batch_cache_create_requested(
ts = scene->toolsettings;
}
MeshBatchCache *cache = mesh_batch_cache_get(me);
bool cd_uv_update = false;
/* Early out */
if (cache->batch_requested == 0) {
@ -1138,6 +1139,7 @@ void DRW_mesh_batch_cache_create_requested(
{
if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv) {
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.uv);
cd_uv_update = true;
}
if ((cache->cd_used.tan & cache->cd_needed.tan) != cache->cd_needed.tan ||
cache->cd_used.tan_orco != cache->cd_needed.tan_orco) {
@ -1177,29 +1179,27 @@ void DRW_mesh_batch_cache_create_requested(
if (batch_requested & MBC_EDITUV) {
/* Discard UV batches if sync_selection changes */
if (ts != NULL) {
const bool is_uvsyncsel = (ts->uv_flag & UV_SYNC_SELECTION);
if (cache->is_uvsyncsel != is_uvsyncsel) {
cache->is_uvsyncsel = is_uvsyncsel;
FOREACH_MESH_BUFFER_CACHE(cache, mbuffercache)
{
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.edituv_data);
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_uv);
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_tris);
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_lines);
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_points);
}
/* We only clear the batches as they may already have been
* referenced. */
GPU_BATCH_CLEAR_SAFE(cache->batch.wire_loops_uvs);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_area);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_angle);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_fdots);
cache->batch_ready &= ~MBC_EDITUV;
const bool is_uvsyncsel = ts && (ts->uv_flag & UV_SYNC_SELECTION);
if (cd_uv_update || (cache->is_uvsyncsel != is_uvsyncsel)) {
cache->is_uvsyncsel = is_uvsyncsel;
FOREACH_MESH_BUFFER_CACHE(cache, mbuffercache)
{
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.edituv_data);
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_uv);
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_tris);
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_lines);
GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_points);
}
/* We only clear the batches as they may already have been
* referenced. */
GPU_BATCH_CLEAR_SAFE(cache->batch.wire_loops_uvs);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_area);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_angle);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts);
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_fdots);
cache->batch_ready &= ~MBC_EDITUV;
}
}

View File

@ -210,6 +210,10 @@ static void drw_debug_draw_spheres(void)
GPU_batch_instbuf_set(draw_batch, inst_vbo, true);
GPU_batch_program_set_builtin(draw_batch, GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE);
float persmat[4][4];
DRW_view_persmat_get(NULL, persmat, false);
GPU_batch_uniform_mat4(draw_batch, "ViewProjectionMatrix", persmat);
GPU_batch_draw(draw_batch);
GPU_batch_discard(draw_batch);
}

View File

@ -1606,6 +1606,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
drw_draw_background_alpha_under();
}
drw_debug_draw();
/* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */
GPU_flush();
@ -1630,8 +1632,6 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
DRW_state_reset();
}
drw_debug_draw();
GPU_depth_test(false);
drw_engines_draw_text();
GPU_depth_test(true);

View File

@ -129,6 +129,7 @@ void drw_state_set(DRWState state)
}
else {
glStencilMask(0x00);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
}
}
}