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:
authorAlexander Gavrilov <angavrilov@gmail.com>2019-04-15 21:48:33 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2019-04-15 21:53:35 +0300
commite2102e991764ae5604a9680294daaf013f344ec4 (patch)
tree6cfd2542ecf259be86281c4cca27c6eddc4ed6dc
parent2f2ba04c6053540ea3a4cd6617cd6b4e38d89c93 (diff)
Spline IK: fix continuity issues with influence and curve end rolloff.
Mainly, scaling needs to be continuously faded out in these cases. Plus, in the case of end roll-off, it seems better to integrate into this general fading system, instead of ad-hoc interpolation of tail.
-rw-r--r--source/blender/blenkernel/intern/armature_update.c47
1 files changed, 27 insertions, 20 deletions
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 6bf120b8f00..c76bf663b72 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -249,8 +249,9 @@ static bool splineik_evaluate_init(tSplineIK_Tree *tree, tSplineIk_EvalState *st
static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChannel *pchan, int index, tSplineIk_EvalState *state)
{
bSplineIKConstraint *ikData = tree->ikData;
- float origHead[3], origTail[3], poseHead[3], poseTail[3], poseMat[4][4];
+ float origHead[3], origTail[3], poseHead[3], poseTail[3], basePoseMat[3][3], poseMat[3][3];
float splineVec[3], scaleFac, radius = 1.0f;
+ float tailBlendFac = 0.0f;
mul_v3_m4v3(poseHead, state->locrot_offset, pchan->pose_head);
mul_v3_m4v3(poseTail, state->locrot_offset, pchan->pose_tail);
@@ -260,25 +261,23 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChanne
/* first, adjust the point positions on the curve */
float curveLen = tree->points[index] - tree->points[index + 1];
float pointStart = state->curve_position;
- float pointEnd = pointStart + curveLen * state->curve_scale;
+ float baseScale = 1.0f;
+ float pointEnd = pointStart + curveLen * baseScale * state->curve_scale;
state->curve_position = pointEnd;
/* step 1: determine the positions for the endpoints of the bone */
- {
+ if (pointStart < 1.0f) {
float vec[4], dir[3], rad;
- float tailBlendFac = 1.0f;
/* determine if the bone should still be affected by SplineIK */
- if (pointStart >= 1.0f) {
- /* spline doesn't affect the bone anymore, so done... */
- pchan->flag |= POSE_DONE;
- return;
- }
- else if ((pointEnd >= 1.0f) && (pointStart < 1.0f)) {
+ if (pointEnd >= 1.0f) {
/* blending factor depends on the amount of the bone still left on the chain */
tailBlendFac = (1.0f - pointStart) / (pointEnd - pointStart);
}
+ else {
+ tailBlendFac = 1.0f;
+ }
/* tail endpoint */
if (where_on_path(ikData->tar, pointEnd, vec, dir, NULL, &rad, NULL)) {
@@ -290,7 +289,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChanne
/* convert the position to pose-space, then store it */
mul_m4_v3(ob->imat, vec);
- interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac);
+ copy_v3_v3(poseTail, vec);
/* set the new radius */
radius = rad;
@@ -320,18 +319,21 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChanne
sub_v3_v3v3(splineVec, poseTail, poseHead);
scaleFac = len_v3(splineVec) / pchan->bone->length;
+ /* Adjust the scale factor towards the neutral state when rolling off the curve end. */
+ scaleFac = interpf(scaleFac, baseScale, tailBlendFac);
+
/* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis
* - this uses the same method as is used for the Damped Track Constraint (see the code there for details)
*/
{
- float dmat[3][3], rmat[3][3], tmat[3][3];
+ float dmat[3][3], rmat[3][3];
float raxis[3], rangle;
/* compute the raw rotation matrix from the bone's current matrix by extracting only the
* orientation-relevant axes, and normalizing them
*/
- mul_m3_m4m4(rmat, state->locrot_offset, pchan->pose_mat);
- normalize_m3(rmat);
+ mul_m3_m4m4(basePoseMat, state->locrot_offset, pchan->pose_mat);
+ normalize_m3_m3(rmat, basePoseMat);
/* also, normalize the orientation imposed by the bone, now that we've extracted the scale factor */
normalize_v3(splineVec);
@@ -348,7 +350,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChanne
/* multiply the magnitude of the angle by the influence of the constraint to
* control the influence of the SplineIK effect
*/
- rangle *= tree->con->enforce;
+ rangle *= tree->con->enforce * tailBlendFac;
/* construct rotation matrix from the axis-angle rotation found above
* - this call takes care to make sure that the axis provided is a unit vector first
@@ -358,9 +360,10 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChanne
/* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates,
* while still maintaining roll control from the existing bone animation
*/
- mul_m3_m3m3(tmat, dmat, rmat); /* m1, m3, m2 */
- normalize_m3(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */
- copy_m4_m3(poseMat, tmat);
+ mul_m3_m3m3(poseMat, dmat, rmat);
+ normalize_m3(poseMat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */
+
+ mul_m3_m3m3(basePoseMat, dmat, basePoseMat);
/* apply rotation to the accumulated parent transform */
mul_m4_m3m4(state->locrot_offset, dmat, state->locrot_offset);
@@ -468,6 +471,10 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChanne
}
}
+ /* Blend the scaling of the matrix according to the influence. */
+ sub_m3_m3m3(poseMat, poseMat, basePoseMat);
+ madd_m3_m3m3fl(poseMat, basePoseMat, poseMat, tree->con->enforce * tailBlendFac);
+
/* step 5: set the location of the bone in the matrix */
if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) {
/* when the 'no-root' option is affected, the chain can retain
@@ -487,10 +494,10 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChanne
interp_v3_v3v3(poseHead, origHead, poseHead, tree->con->enforce);
}
}
- copy_v3_v3(poseMat[3], poseHead);
/* finally, store the new transform */
- copy_m4_m4(pchan->pose_mat, poseMat);
+ copy_m4_m3(pchan->pose_mat, poseMat);
+ copy_v3_v3(pchan->pose_mat[3], poseHead);
copy_v3_v3(pchan->pose_head, poseHead);
mul_v3_mat3_m4v3(origTail, state->locrot_offset, pchan->pose_tail);