From f9cbb908a3fbd73970920def8356993b9e016d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Mon, 13 Oct 2014 19:51:46 +0200 Subject: Integrated limits for volume preservation in stretch-to constraints. Currently the volume variation feature in stretch constraints is unlimited. This has to be compensated by riggers by adding scale limit constraints, but these are unaware of the stretch orientation and can lead to flipping. Also the stretch calculation itself is not working properly and can lead to collapsing volume. The patch fixes this with several modifications: - Interpret the volume variation factor as exponent, which works better with large values for artistic purposes. - Add integrated limits to the volume "bulge" factor, so secondary constraints for compensation become unnecessary - Add a smoothness factor to make limits less visible. Eventually a generic volume preservation constraint would be nicer, because multiple constraints currently implement volume variation of their own. This feature could actually work very nicely independent from other constraint features. Differential Revision: https://developer.blender.org/D826 --- source/blender/blenkernel/intern/constraint.c | 53 +++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 8 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') 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: -- cgit v1.2.3 From 0297763afafae7392348728580f3ae38e1208354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Tue, 14 Oct 2014 11:03:13 +0200 Subject: Tweak for smoothing limits in stretch-constraint volume preservation. Uses a arctan instead of sine function now, which has the advantage of not overestimating the bulging. --- source/blender/blenkernel/intern/constraint.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e4b60c12d64..3a9eb31f061 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2693,11 +2693,9 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t 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; + float 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); + bulge_smoothed = bulge_median + bulge_range * atanf(bulge - bulge_median) / (0.5f * M_PI); if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { CLAMP_MIN(bulge, data->bulge_min); -- cgit v1.2.3 From 20c233f3af344579fb14ea6cf1617e0c4021a31e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Tue, 14 Oct 2014 11:49:58 +0200 Subject: Yet another tweak to stretch volume variation. Make sure the 1.0 value is not affected by smoothing, and min/max limits never go above or below 1.0 respectively. This was a request by animators since not modifying the mesh in its rest pose is regarded as crucial. --- source/blender/blenkernel/intern/constraint.c | 51 ++++++++++++--------------- 1 file changed, 22 insertions(+), 29 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 3a9eb31f061..97515244422 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2613,6 +2613,8 @@ static void stretchto_new_data(void *cdata) data->plane = 0; data->orglength = 0.0; data->bulge = 1.0; + data->bulge_max = 1.0f; + data->bulge_min = 1.0f; } static void stretchto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) @@ -2689,37 +2691,28 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t 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 bulge_smoothed; - - bulge_smoothed = bulge_median + bulge_range * atanf(bulge - bulge_median) / (0.5f * M_PI); - - if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { - CLAMP_MIN(bulge, data->bulge_min); + if (bulge > 1.0f) { + if (data->flag & STRETCHTOCON_USE_BULGE_MAX) { + float bulge_max = max_ff(data->bulge_max, 1.0f); + float hard = min_ff(bulge, bulge_max); + + float range = bulge_max - 1.0f; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (0.5f * M_PI); + + bulge = interpf(soft, hard, data->bulge_smooth); } - 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; + if (bulge < 1.0f) { + if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { + float bulge_min = CLAMPIS(data->bulge_max, 0.0f, 1.0f); + float hard = max_ff(bulge, bulge_min); + + float range = 1.0f - bulge_min; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (0.5f * M_PI); + + bulge = interpf(soft, hard, data->bulge_smooth); } } -- cgit v1.2.3 From 61d14774150662a8cbcf439c7e93959fd3c74834 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 16 Oct 2014 15:42:46 +0200 Subject: Fix T42256: Translation operator moves Child-Of constrained objects in wrong space when only using parent's rotation and parent is rotated. Just do not use crazyspace correction with childof constraints in this case. Note this is only a very partial fix (partial use of parent loc on some axes is still broken in transform), a real fix would probably require a full rewrite of constraints handling in transform code (a mere static correction matrix just cannot work in all possible cases, we'd need a full dynamic correction system here). Anyway, transform code as a whole is horrible. :/ --- source/blender/blenkernel/intern/constraint.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 97515244422..8a5d313e3fb 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -185,6 +185,10 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob) /* calculate delta of constraints evaluation */ invert_m4_m4(imat, cob->startmat); + /* XXX This would seem to be in wrong order. However, it does not work in 'right' order - would be nice to + * understand why premul is needed here instead of usual postmul? + * In any case, we **do not get a delta** here (e.g. startmat & matrix having same location, still gives + * a 'delta' with non-null translation component :/ ).*/ mul_m4_m4m4(delta, cob->matrix, imat); /* copy matrices back to source */ -- cgit v1.2.3 From b154aa8c060a60d476970bb8b8fab3912a2afc22 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 31 Oct 2014 11:07:52 +0100 Subject: Fix T42447: Shrinkwrap constraint: mismatch in handling sclaing in projection case. Constraint space conversion ignores object scale, which is OK in most cases. But here, we are converting a normal from world to local space, and when later converting it into target space to actually do the BVH raycast, we use TransformSpace which does applies objects' scaling to normals, as expected. Best solution here is to also take object's scale into account when converting from local to world space. --- source/blender/blenkernel/intern/constraint.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 8a5d313e3fb..574001e2f80 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3461,10 +3461,16 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra } /* transform normal into requested space */ - unit_m4(mat); - BKE_constraint_mat_convertspace(cob->ob, cob->pchan, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace); - invert_m4(mat); - mul_mat3_m4_v3(mat, no); + /* We cannot use BKE_constraint_mat_convertspace here, it does not take into account scaling... + * In theory we would not need it, but in this case we'd have to tweak SpaceTransform to also + * optionally ignore scaling when handling normals - simpler to directly call BKE_object_to_mat4 + * if needed! See T42447. */ + if (scon->projAxisSpace == CONSTRAINT_SPACE_WORLD) { + BKE_object_to_mat4(cob->ob, mat); + invert_m4(mat); + mul_mat3_m4_v3(mat, no); + } + /* Else, we remain in local space, nothing to do. */ if (normalize_v3(no) < FLT_EPSILON) { fail = true; -- cgit v1.2.3 From 08fd38cf52e4d540e6a7d3ceeaedf4a4c3858f55 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 24 Nov 2014 12:01:51 +0100 Subject: BLI_utildefines: add UNUSED_VARS() macro --- source/blender/blenkernel/intern/constraint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 574001e2f80..10eb8b730ec 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1971,7 +1971,7 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa static void pycon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets) { #ifndef WITH_PYTHON - (void)con; (void)cob; (void)targets; /* unused */ + UNUSED_VARS(con, cob, targets); return; #else bPythonConstraint *data = con->data; -- cgit v1.2.3 From 20a177814815e7e3a1a4a4d37e91880ef98aa68a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 1 Dec 2014 17:11:18 +0100 Subject: Cleanup: more int->bool. --- source/blender/blenkernel/intern/constraint.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 10eb8b730ec..8fedf37fb95 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4395,10 +4395,10 @@ bool BKE_constraint_remove(ListBase *list, bConstraint *con) if (con) { BKE_constraint_free_data(con); BLI_freelinkN(list, con); - return 1; + return true; } else - return 0; + return false; } /* ......... */ @@ -4662,15 +4662,15 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan) /* On bone-level, check if bone is on proxy-protected layer */ if ((pchan->bone) && (pchan->bone->layer & arm->layer_protected)) - return 1; + return true; } else { /* FIXME: constraints on object-level are not handled well yet */ - return 1; + return true; } } - return 0; + return false; } /* -------- Target-Matrix Stuff ------- */ -- cgit v1.2.3 From 599c8a2c8e4cf1f904c5422916ebfd8d12eebe69 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 11 Jan 2015 14:59:11 +0100 Subject: Fix T43204: Shrinkwrap constraint, project mode: Space ignored in bone case. Own fault in rBb154aa8c060a60d to fix T42447... Reverted that commit, and added kind of not-so-nice hack instead. Note root of the issue comes from the special case we are doing here re 'Local' space of parent-less objects. In that case, local space should be the same as world one, but instead we apply the object rotation to it... This is inconsistent with all other cases and could very well lead to other issues as T42447, but afraid fixing that properly would be rather hairy - not to mention it would likely break all existing riggings etc. :( Should be safe for a 2.73a, shall we need it. --- source/blender/blenkernel/intern/constraint.c | 54 ++++++++++++++++----------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 8fedf37fb95..9072acd8b02 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -229,7 +229,8 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob) * of a matrix from one space to another for constraint evaluation. * For now, this is only implemented for Objects and PoseChannels. */ -void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to) +void BKE_constraint_mat_convertspace( + Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale) { float diff_mat[4][4]; float imat[4][4]; @@ -252,7 +253,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[ /* use pose-space as stepping stone for other spaces... */ if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ - BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); } break; } @@ -288,7 +289,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[ /* use pose-space as stepping stone for other spaces */ if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ - BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); } break; } @@ -303,7 +304,7 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[ /* use pose-space as stepping stone for other spaces */ if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { /* call self with slightly different values */ - BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); } break; } @@ -323,8 +324,17 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[ /* Local space in this case will have to be defined as local to the owner's * transform-property-rotated axes. So subtract this rotation component. */ + /* XXX This is actually an ugly hack, local space of a parent-less object *is* the same as + * global space! + * Think what we want actually here is some kind of 'Final Space', i.e. once transformations + * are applied - users are often confused about this too, this is not consistent with bones + * local space either... Meh :| + * --mont29 + */ BKE_object_to_mat4(ob, diff_mat); - normalize_m4(diff_mat); + if (!keep_scale) { + normalize_m4(diff_mat); + } zero_v3(diff_mat[3]); invert_m4_m4_safe(imat, diff_mat); @@ -342,8 +352,11 @@ void BKE_constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[ /* Local space in this case will have to be defined as local to the owner's * transform-property-rotated axes. So add back this rotation component. */ + /* XXX See comment above for world->local case... */ BKE_object_to_mat4(ob, diff_mat); - normalize_m4(diff_mat); + if (!keep_scale) { + normalize_m4(diff_mat); + } zero_v3(diff_mat[3]); mul_m4_m4m4(mat, diff_mat, mat); @@ -511,7 +524,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m /* Case OBJECT */ if (!strlen(substring)) { copy_m4_m4(mat, ob->obmat); - BKE_constraint_mat_convertspace(ob, NULL, mat, from, to); + BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); } /* Case VERTEXGROUP */ /* Current method just takes the average location of all the points in the @@ -524,11 +537,11 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m */ else if (ob->type == OB_MESH) { contarget_get_mesh_mat(ob, substring, mat); - BKE_constraint_mat_convertspace(ob, NULL, mat, from, to); + BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); } else if (ob->type == OB_LATTICE) { contarget_get_lattice_mat(ob, substring, mat); - BKE_constraint_mat_convertspace(ob, NULL, mat, from, to); + BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); } /* Case BONE */ else { @@ -561,7 +574,7 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m copy_m4_m4(mat, ob->obmat); /* convert matrix space as required */ - BKE_constraint_mat_convertspace(ob, pchan, mat, from, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, from, to, false); } } @@ -3461,16 +3474,13 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra } /* transform normal into requested space */ - /* We cannot use BKE_constraint_mat_convertspace here, it does not take into account scaling... - * In theory we would not need it, but in this case we'd have to tweak SpaceTransform to also - * optionally ignore scaling when handling normals - simpler to directly call BKE_object_to_mat4 - * if needed! See T42447. */ - if (scon->projAxisSpace == CONSTRAINT_SPACE_WORLD) { - BKE_object_to_mat4(cob->ob, mat); - invert_m4(mat); - mul_mat3_m4_v3(mat, no); - } - /* Else, we remain in local space, nothing to do. */ + /* Note that in this specific case, we need to keep scaling in non-parented 'local2world' object + * case, because SpaceTransform also takes it into account when handling normals. See T42447. */ + unit_m4(mat); + BKE_constraint_mat_convertspace(cob->ob, cob->pchan, mat, + CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace, true); + invert_m4(mat); + mul_mat3_m4_v3(mat, no); if (normalize_v3(no) < FLT_EPSILON) { fail = true; @@ -4816,7 +4826,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime) copy_m4_m4(oldmat, cob->matrix); /* move owner matrix into right space */ - BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace); + BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false); /* prepare targets for constraint solving */ BKE_constraint_targets_for_solving_get(con, cob, &targets, ctime); @@ -4834,7 +4844,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime) /* move owner back into worldspace for next constraint/other business */ if ((con->flag & CONSTRAINT_SPACEONCE) == 0) - BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD); + BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD, false); /* Interpolate the enforcement, to blend result of constraint into final owner transform * - all this happens in worldspace to prevent any weirdness creeping in ([#26014] and [#25725]), -- cgit v1.2.3 From 8787532184e648e38b4ecee0709dcf87b95862b1 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 13 Jan 2015 18:13:57 +1300 Subject: Bugfix: The "bulge_min" setting for the Stretch To constraint prevented bones from shrinking below 1.0 scale From the looks of things, this was a typo. The result was that if you had a bone with the minimum volume restriction in place, the bone would not get any thinner when it was stretched out. --- source/blender/blenkernel/intern/constraint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 9072acd8b02..5f97abbaac1 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2722,7 +2722,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t } if (bulge < 1.0f) { if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { - float bulge_min = CLAMPIS(data->bulge_max, 0.0f, 1.0f); + float bulge_min = CLAMPIS(data->bulge_min, 0.0f, 1.0f); float hard = max_ff(bulge, bulge_min); float range = 1.0f - bulge_min; -- cgit v1.2.3 From 00ef77c1a241aaf3d7c6307411e97938b87c3096 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 13 Jan 2015 19:30:31 +1300 Subject: Fixes for SplineIK: * Ensure that when new constraints are created, the new settings have sensible default values. TODO: we need to version-patch old files * Fix problem with variable shadowing (which wasn't causing problems AFAIK) --- source/blender/blenkernel/intern/constraint.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 5f97abbaac1..f591fe857f8 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3698,6 +3698,9 @@ static void splineik_new_data(void *cdata) bSplineIKConstraint *data = (bSplineIKConstraint *)cdata; data->chainlen = 1; + data->bulge = 1.0; + data->bulge_max = 1.0f; + data->bulge_min = 1.0f; } static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) -- cgit v1.2.3 From 9e9cd77b8de68015a98659671272cc9d78710e69 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 31 Jan 2015 17:23:30 +1100 Subject: Compiler warning: double-promotion --- source/blender/blenkernel/intern/constraint.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index f591fe857f8..668b78a08d4 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2715,7 +2715,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t float range = bulge_max - 1.0f; float scale = (range > 0.0f) ? 1.0f / range : 0.0f; - float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (0.5f * M_PI); + float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (float)M_PI_2; bulge = interpf(soft, hard, data->bulge_smooth); } @@ -2727,7 +2727,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t float range = 1.0f - bulge_min; float scale = (range > 0.0f) ? 1.0f / range : 0.0f; - float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (0.5f * M_PI); + float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (float)M_PI_2; bulge = interpf(soft, hard, data->bulge_smooth); } -- cgit v1.2.3 From 23214ecad03bfef75c78b6a812970959da363344 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 12 Feb 2015 07:25:36 +1100 Subject: Outliner: ContextMenus for constraints/modifiers Context menu to toggle render, visibility & delete D996 by @lichtwerk --- source/blender/blenkernel/intern/constraint.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 668b78a08d4..71b2e7df4b2 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -79,6 +79,8 @@ #include "BKE_tracking.h" #include "BKE_movieclip.h" +#include "BIK_api.h" + #ifdef WITH_PYTHON # include "BPY_extern.h" #endif @@ -4410,8 +4412,23 @@ bool BKE_constraint_remove(ListBase *list, bConstraint *con) BLI_freelinkN(list, con); return true; } - else + else { return false; + } +} + +bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool clear_dep) +{ + if (BKE_constraint_remove(list, con)) { + /* ITASC needs to be rebuilt once a constraint is removed [#26920] */ + if (clear_dep && ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) { + BIK_clear_data(ob->pose); + } + return true; + } + else { + return false; + } } /* ......... */ -- cgit v1.2.3 From 1fa98b374f620b3357fb26bf959c38cff9f8cc7e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 18 Feb 2015 10:38:21 +1100 Subject: Fix free'd memory use removing constraint --- source/blender/blenkernel/intern/constraint.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 71b2e7df4b2..93f524a5439 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4419,9 +4419,10 @@ bool BKE_constraint_remove(ListBase *list, bConstraint *con) bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool clear_dep) { + const short type = con->type; if (BKE_constraint_remove(list, con)) { /* ITASC needs to be rebuilt once a constraint is removed [#26920] */ - if (clear_dep && ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) { + if (clear_dep && ELEM(type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) { BIK_clear_data(ob->pose); } return true; -- cgit v1.2.3 From 6405aa4e9c73a2d51234b4e855bd5e8c1e4ba30f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 6 Mar 2015 15:21:01 +0500 Subject: Fix access freed memory when doing constraints ID counter on main free Basically just made constraints free function aware of possible do_id_users argument, same as we've got for objects, object data and so on. --- source/blender/blenkernel/intern/constraint.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 93f524a5439..c38a1239f12 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4370,7 +4370,7 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, bool is_re * be sure to run BIK_clear_data() when freeing an IK constraint, * unless DAG_relations_tag_update is called. */ -void BKE_constraint_free_data(bConstraint *con) +void BKE_constraint_free_data_ex(bConstraint *con, bool do_id_user) { if (con->data) { bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); @@ -4381,7 +4381,7 @@ void BKE_constraint_free_data(bConstraint *con) cti->free_data(con); /* unlink the referenced resources it uses */ - if (cti->id_looper) + if (do_id_user && cti->id_looper) cti->id_looper(con, con_unlink_refs_cb, NULL); } @@ -4390,19 +4390,28 @@ void BKE_constraint_free_data(bConstraint *con) } } +void BKE_constraint_free_data(bConstraint *con) +{ + BKE_constraint_free_data_ex(con, true); +} + /* Free all constraints from a constraint-stack */ -void BKE_constraints_free(ListBase *list) +void BKE_constraints_free_ex(ListBase *list, bool do_id_user) { bConstraint *con; /* Free constraint data and also any extra data */ for (con = list->first; con; con = con->next) - BKE_constraint_free_data(con); + BKE_constraint_free_data_ex(con, do_id_user); /* Free the whole list */ BLI_freelistN(list); } +void BKE_constraints_free(ListBase *list) +{ + BKE_constraints_free_ex(list, true); +} /* Remove the specified constraint from the given constraint stack */ bool BKE_constraint_remove(ListBase *list, bConstraint *con) -- cgit v1.2.3 From 268524c0257fe313c3c25b4c3e93913690435bea Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 30 Mar 2015 21:17:07 +1100 Subject: Cleanup: use const for typeinfo --- source/blender/blenkernel/intern/constraint.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index c38a1239f12..fa8ab14de06 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4318,7 +4318,7 @@ static void constraints_init_typeinfo(void) /* This function should be used for getting the appropriate type-info when only * a constraint type is known */ -bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type) +const bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type) { /* initialize the type-info list? */ if (CTI_INIT) { @@ -4343,7 +4343,7 @@ bConstraintTypeInfo *BKE_constraint_typeinfo_from_type(int type) /* This function should always be used to get the appropriate type-info, as it * has checks which prevent segfaults in some weird cases. */ -bConstraintTypeInfo *BKE_constraint_typeinfo_get(bConstraint *con) +const bConstraintTypeInfo *BKE_constraint_typeinfo_get(bConstraint *con) { /* only return typeinfo for valid constraints */ if (con) @@ -4373,7 +4373,7 @@ static void con_unlink_refs_cb(bConstraint *UNUSED(con), ID **idpoin, bool is_re void BKE_constraint_free_data_ex(bConstraint *con, bool do_id_user) { if (con->data) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti) { /* perform any special freeing constraint may have */ @@ -4447,7 +4447,7 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool static bConstraint *add_new_constraint_internal(const char *name, short type) { bConstraint *con = MEM_callocN(sizeof(bConstraint), "Constraint"); - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(type); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(type); const char *newName; /* Set up a generic constraint datablock */ @@ -4574,7 +4574,7 @@ void BKE_constraints_id_loop(ListBase *conlist, ConstraintIDFunc func, void *use bConstraint *con; for (con = conlist->first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti) { if (cti->id_looper) @@ -4609,7 +4609,7 @@ void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern) BLI_duplicatelist(dst, src); for (con = dst->first, srccon = src->first; con && srccon; srccon = srccon->next, con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); /* make a new copy of the constraint's data */ con->data = MEM_dupallocN(con->data); @@ -4724,7 +4724,7 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan) */ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintOb *cob; bConstraintTarget *ct; @@ -4791,7 +4791,7 @@ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, /* Get the list of targets required for solving a constraint */ void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); if (cti && cti->get_constraint_targets) { bConstraintTarget *ct; @@ -4836,7 +4836,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime) /* loop over available constraints, solving and blending them */ for (con = conlist->first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; /* these we can skip completely (invalid constraints...) */ -- cgit v1.2.3 From 6f7926c61c94ea9bd2969ebfcc7e09994ffe901d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 13 Jul 2015 18:17:07 +0200 Subject: Fix T45394: Motion tracking constraints did not work with Cycles motion blur --- source/blender/blenkernel/intern/constraint.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index fa8ab14de06..4f086437c50 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -76,6 +76,7 @@ #include "BKE_idprop.h" #include "BKE_shrinkwrap.h" #include "BKE_editmesh.h" +#include "BKE_scene.h" #include "BKE_tracking.h" #include "BKE_movieclip.h" @@ -3923,7 +3924,8 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase MovieTrackingTrack *track; MovieTrackingObject *tracking_object; Object *camob = data->camera ? data->camera : scene->camera; - int framenr; + float ctime = BKE_scene_frame_get(scene); + float framenr; if (data->flag & FOLLOWTRACK_ACTIVECLIP) clip = scene->clip; @@ -3946,7 +3948,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (!track) return; - framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra); + framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); if (data->flag & FOLLOWTRACK_USE_3D_POSITION) { if (track->flag & TRACK_HAS_BUNDLE) { @@ -3974,7 +3976,6 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase } } else { - MovieTrackingMarker *marker; float vec[3], disp[3], axis[3], mat[4][4]; float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); float len, d; @@ -4000,10 +4001,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase float pos[2], rmat[4][4]; BKE_movieclip_get_size(clip, NULL, &width, &height); - - marker = BKE_tracking_marker_get(track, framenr); - - add_v2_v2v2(pos, marker->pos, track->offset); + BKE_tracking_marker_get_subframe_position(track, framenr, pos); if (data->flag & FOLLOWTRACK_USE_UNDISTORTION) { /* Undistortion need to happen in pixel space. */ @@ -4173,7 +4171,8 @@ static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase float mat[4][4], obmat[4][4]; MovieTracking *tracking = &clip->tracking; MovieTrackingObject *object = BKE_tracking_object_get_camera(tracking); - int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra); + float ctime = BKE_scene_frame_get(scene); + float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat); @@ -4238,7 +4237,8 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (object) { float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4]; - int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, scene->r.cfra); + float ctime = BKE_scene_frame_get(scene); + float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); BKE_object_where_is_calc_mat4(scene, camob, cammat); -- cgit v1.2.3 From 60822ec183a514f38f478ec3f3a167f59865f027 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Jul 2015 13:20:34 +1000 Subject: Use looptri for BVH raycast (simple cases) --- source/blender/blenkernel/intern/constraint.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 4f086437c50..be466c29a12 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3438,7 +3438,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra if (scon->shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6); else - bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6); + bvhtree_from_mesh_looptri(&treeData, target, 0.0, 2, 6); if (treeData.tree == NULL) { fail = true; @@ -3490,7 +3490,7 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra break; } - bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6); + bvhtree_from_mesh_looptri(&treeData, target, scon->dist, 4, 6); if (treeData.tree == NULL) { fail = true; break; @@ -4107,7 +4107,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase sub_v3_v3v3(ray_nor, ray_end, ray_start); - bvhtree_from_mesh_faces(&treeData, target, 0.0f, 4, 6); + bvhtree_from_mesh_looptri(&treeData, target, 0.0f, 4, 6); hit.dist = FLT_MAX; hit.index = -1; -- cgit v1.2.3 From 2e2dc9b9e32d104a0f7c3241ea0c11b57a37fd5b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 16 Aug 2015 17:32:01 +1000 Subject: Refactor translation code out of blenfont - Add blentranslation `BLT_*` module. - moved & split `BLF_translation.h` into (`BLT_translation.h`, `BLT_lang.h`). - moved `BLF_*_unifont` functions from `blf_translation.c` to new source file `blf_font_i18n.c`. --- source/blender/blenkernel/intern/constraint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index be466c29a12..e7f6210fef4 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -43,7 +43,7 @@ #include "BLI_kdopbvh.h" #include "BLI_utildefines.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" -- cgit v1.2.3 From c727fc59abe2b7e525bdc6594bbd7ec3285936e0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 21 Aug 2015 17:05:48 +1000 Subject: BVH-raycast: ensure input direction is unit-length This was already the case for most users of ray-cast. Doing this avoids 2x normalize calls per ray-cast in many places. --- source/blender/blenkernel/intern/constraint.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e7f6210fef4..2aba4fcde27 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4106,6 +4106,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase mul_v3_m4v3(ray_end, imat, cob->matrix[3]); sub_v3_v3v3(ray_nor, ray_end, ray_start); + normalize_v3(ray_nor); bvhtree_from_mesh_looptri(&treeData, target, 0.0f, 4, 6); -- cgit v1.2.3 From f1422c40af7527141ab348ad2522d7d2435ccb1c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 7 Sep 2015 00:48:26 +1000 Subject: Use squared length where possible --- source/blender/blenkernel/intern/constraint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/blenkernel/intern/constraint.c') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 2aba4fcde27..ed2e609ae53 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -447,7 +447,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ copy_v3_v3(plane, tmat[1]); cross_v3_v3v3(mat[0], normal, plane); - if (len_v3(mat[0]) < 1e-3f) { + if (len_squared_v3(mat[0]) < SQUARE(1e-3f)) { copy_v3_v3(plane, tmat[0]); cross_v3_v3v3(mat[0], normal, plane); } -- cgit v1.2.3