diff options
Diffstat (limited to 'source/blender/blenkernel/intern/constraint.c')
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index ee7bad773fa..e4b60c12d64 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2658,7 +2658,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t if (VALID_CONS_TARGET(ct)) { float size[3], scale[3], vec[3], xx[3], zz[3], orth[3]; float totmat[3][3]; - float dist; + float dist, bulge; /* store scaling before destroying obmat */ mat4_to_size(size, cob->matrix); @@ -2676,7 +2676,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t /* vec[2] /= size[2];*/ /* dist = normalize_v3(vec);*/ - + dist = len_v3v3(cob->matrix[3], ct->matrix[3]); /* Only Y constrained object axis scale should be used, to keep same length when scaling it. */ dist /= size[1]; @@ -2684,23 +2684,60 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t /* data->orglength==0 occurs on first run, and after 'R' button is clicked */ if (data->orglength == 0) data->orglength = dist; - if (data->bulge == 0) - data->bulge = 1.0; - + scale[1] = dist / data->orglength; + + bulge = powf(data->orglength / dist, data->bulge); + + if (data->flag & STRETCHTOCON_USE_BULGE_MAX) { + const float bulge_median = ((data->flag & STRETCHTOCON_USE_BULGE_MIN) ? + 0.5f * (data->bulge_min + data->bulge_max) : 0.0f); + const float bulge_range = data->bulge_max - bulge_median; + float x, bulge_smoothed; + + x = bulge_range != 0.0f ? (bulge - bulge_median) / bulge_range : 0.0f; + CLAMP(x, -1.0f, 1.0f); + bulge_smoothed = bulge_median + bulge_range * sinf(0.5f*M_PI * x); + + if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { + CLAMP_MIN(bulge, data->bulge_min); + } + CLAMP_MAX(bulge, data->bulge_max); + + bulge = interpf(bulge_smoothed, bulge, data->bulge_smooth); + } + else if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { + /* The quadratic formula below creates a smooth asymptote + * of the clamped bulge value. By scaling x with the inverse smooth factor + * the smoothed area becomes smaller ("less smoothing"). + * For very small smoothing factor below epsilon it is replaced + * by the clamped version to avoid floating point precision issues. + */ + const float epsilon = 0.000001f; + if (data->bulge_smooth < epsilon) { + CLAMP_MIN(bulge, data->bulge_min); + } + else { + float scale = data->bulge_smooth; + float inv_scale = 1.0f / scale; + float x = (bulge - data->bulge_min) * 0.5f * inv_scale; + bulge = scale * (x + sqrtf((x * x) + 1.0f)) + data->bulge_min; + } + } + switch (data->volmode) { /* volume preserving scaling */ case VOLUME_XZ: - scale[0] = 1.0f - sqrtf(data->bulge) + sqrtf(data->bulge * (data->orglength / dist)); + scale[0] = sqrtf(bulge); scale[2] = scale[0]; break; case VOLUME_X: - scale[0] = 1.0f + data->bulge * (data->orglength / dist - 1); + scale[0] = bulge; scale[2] = 1.0; break; case VOLUME_Z: scale[0] = 1.0; - scale[2] = 1.0f + data->bulge * (data->orglength / dist - 1); + scale[2] = bulge; break; /* don't care for volume */ case NO_VOLUME: |