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/blenkernel/intern/constraint.c')
-rw-r--r--source/blender/blenkernel/intern/constraint.c53
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: