Fix T51971: IK non-uniform scale regression.
This is a different fix for the issue from D2088, preserving backwards compatibility for IK stretching. The main problem with this patch is that this new behavior has been there for a year, so it may break rigs created since then which rely on the new IK stretch behavior. Test file for various cases: https://developer.blender.org/diffusion/BL/browse/trunk/lib/tests/animation/IK.blend Reviewers: campbellbarton Subscribers: maverick, pkrime Differential Revision: https://developer.blender.org/D2743
This commit is contained in:
parent
9feeb14e91
commit
f05f2f0336
Notes:
blender-bot
2023-02-14 06:49:53 +01:00
Referenced by issue #51971, IK with non uniform scale broke the animation tools
|
@ -217,9 +217,27 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3]) // nr =
|
|||
copy_m4_m3(ikmat, ik_mat);
|
||||
|
||||
if (pchan->parent)
|
||||
mul_m4_series(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat);
|
||||
mul_m4_m4m4(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat);
|
||||
else
|
||||
mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, ikmat);
|
||||
copy_m4_m4(pchan->pose_mat, pchan->chan_mat);
|
||||
|
||||
#ifdef USE_NONUNIFORM_SCALE
|
||||
/* apply IK mat, but as if the bones have uniform scale since the IK solver
|
||||
* is not aware of non-uniform scale */
|
||||
float scale[3];
|
||||
mat4_to_size(scale, pchan->pose_mat);
|
||||
normalize_v3_length(pchan->pose_mat[0], scale[1]);
|
||||
normalize_v3_length(pchan->pose_mat[2], scale[1]);
|
||||
#endif
|
||||
|
||||
mul_m4_m4m4(pchan->pose_mat, pchan->pose_mat, ikmat);
|
||||
|
||||
#ifdef USE_NONUNIFORM_SCALE
|
||||
float ik_scale[3];
|
||||
mat3_to_size(ik_scale, ik_mat);
|
||||
normalize_v3_length(pchan->pose_mat[0], scale[0] * ik_scale[0]);
|
||||
normalize_v3_length(pchan->pose_mat[2], scale[2] * ik_scale[2]);
|
||||
#endif
|
||||
|
||||
/* calculate head */
|
||||
copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]);
|
||||
|
@ -308,6 +326,10 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
|
|||
/* change length based on bone size */
|
||||
length = bone->length * len_v3(R_bonemat[1]);
|
||||
|
||||
/* basis must be pure rotation */
|
||||
normalize_m3(R_bonemat);
|
||||
normalize_m3(R_parmat);
|
||||
|
||||
/* compute rest basis and its inverse */
|
||||
copy_m3_m3(rest_basis, bone->bone_mat);
|
||||
transpose_m3_m3(irest_basis, bone->bone_mat);
|
||||
|
@ -317,11 +339,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
|
|||
mul_m3_m3m3(full_basis, iR_parmat, R_bonemat);
|
||||
mul_m3_m3m3(basis, irest_basis, full_basis);
|
||||
|
||||
/* basis must be pure rotation */
|
||||
normalize_m3(basis);
|
||||
|
||||
/* transform offset into local bone space */
|
||||
normalize_m3(iR_parmat);
|
||||
mul_m3_v3(iR_parmat, start);
|
||||
|
||||
IK_SetTransform(seg, start, rest_basis, basis, length);
|
||||
|
@ -545,18 +563,6 @@ void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan
|
|||
tree->pchan[a]->flag |= POSE_CHAIN;
|
||||
}
|
||||
|
||||
#ifdef USE_NONUNIFORM_SCALE
|
||||
float (*pchan_scale_data)[3] = MEM_mallocN(sizeof(float[3]) * tree->totchannel, __func__);
|
||||
|
||||
for (a = 0; a < tree->totchannel; a++) {
|
||||
mat4_to_size(pchan_scale_data[a], tree->pchan[a]->pose_mat);
|
||||
|
||||
/* make uniform at y scale since this controls the length */
|
||||
normalize_v3_length(tree->pchan[a]->pose_mat[0], pchan_scale_data[a][1]);
|
||||
normalize_v3_length(tree->pchan[a]->pose_mat[2], pchan_scale_data[a][1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 5. execute the IK solver */
|
||||
execute_posetree(scene, ob, tree);
|
||||
|
||||
|
@ -571,14 +577,6 @@ void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan
|
|||
where_is_ik_bone(tree->pchan[a], tree->basis_change[a]);
|
||||
}
|
||||
|
||||
#ifdef USE_NONUNIFORM_SCALE
|
||||
for (a = 0; a < tree->totchannel; a++) {
|
||||
normalize_v3_length(tree->pchan[a]->pose_mat[0], pchan_scale_data[a][0]);
|
||||
normalize_v3_length(tree->pchan[a]->pose_mat[2], pchan_scale_data[a][2]);
|
||||
}
|
||||
MEM_freeN(pchan_scale_data);
|
||||
#endif
|
||||
|
||||
/* 7. and free */
|
||||
BLI_remlink(&pchan_root->iktree, tree);
|
||||
free_posetree(tree);
|
||||
|
|
Loading…
Reference in New Issue