Fix T39486, screwed object bevel made bevel amount go out of control.

There is an adjustment pass in bevel that tries to make the bevel
widths at either end of a beveled edge as equal as possible.
When there are hundreds of beveled edges end-to-end, these adjustments
can accumulate out of control and result looks awful.
Yet the adjustment pass is sometimes needed to avoid equally awful
appearances in other cases (see the "Bent test" in the bevel regression
tests).
This change uses the 'Clamp overlap' flag of bevel (on by default in
the modifier, not in the tool) to limit the amount of adjustment to within
10% of the desired width. When the flag is off, there is no limit to the
adjustment.
This commit is contained in:
Howard Trickey 2015-08-16 15:15:13 -04:00
parent 9b43fce3c1
commit 0c420a2e49
Notes: blender-bot 2023-02-14 10:53:15 +01:00
Referenced by issue #39486, bevel modifier behave weird with screwed object
1 changed files with 25 additions and 2 deletions

View File

@ -56,6 +56,7 @@
#define BEVEL_EPSILON_BIG_SQ 1e-8f
#define BEVEL_EPSILON_ANG DEG2RADF(2.0f)
#define BEVEL_SMALL_ANG DEG2RADF(10.0f)
#define BEVEL_MAX_ADJUST_PCT 10.0f
/* happens far too often, uncomment for development */
// #define BEVEL_ASSERT_PROJECT
@ -1692,6 +1693,20 @@ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf
}
}
/* 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)
{
float allowed_delta = spec * (BEVEL_MAX_ADJUST_PCT / 100.0f);
if (v - spec > allowed_delta)
return spec + allowed_delta;
else if (spec - v > allowed_delta)
return spec - allowed_delta;
else
return v;
}
/* 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
@ -1732,8 +1747,16 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
eother = find_other_end_edge_half(bp, e, &bvother);
if (eother && bvother->visited && bp->offset_type != BEVEL_AMT_PERCENT) {
/* try to keep bevel even by matching other end offsets */
e->offset_l = eother->offset_r;
e->offset_r = eother->offset_l;
/* sometimes, adjustment can accumulate errors so use the bp->limit_offset to
* let user limit the adjustment to within a reasonable range around spec */
if (bp->limit_offset) {
e->offset_l = clamp_adjust(eother->offset_r, e->offset_l_spec);
e->offset_r = clamp_adjust(eother->offset_l, e->offset_r_spec);
}
else {
e->offset_l = eother->offset_r;
e->offset_r = eother->offset_l;
}
}
else {
/* reset to user spec */