diff options
author | Alexander Gavrilov <angavrilov@gmail.com> | 2019-09-04 10:10:27 +0300 |
---|---|---|
committer | Alexander Gavrilov <angavrilov@gmail.com> | 2019-09-04 10:34:21 +0300 |
commit | fcf2a712eca278f198e8d61845f2078088af1f9a (patch) | |
tree | 77c6c3e0f60cba4f1fb3669029487e922514d7dd /source/blender/editors/armature | |
parent | 64f8f7db7cce0c8923afcabb523f7400f744387e (diff) |
Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
The cleanup math is specifically designed to preserve the main
axis of the bone, its length and total volume, and minimally
affect roll on average. It however will not prevent reappearance
of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
This is the simplest foolproof solution that will inherit some
scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
This mode does not handle parent shear in any way, so the child
is likely to end up having both scale and shear. It is retained
for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
Diffstat (limited to 'source/blender/editors/armature')
-rw-r--r-- | source/blender/editors/armature/armature_edit.c | 6 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_utils.c | 2 | ||||
-rw-r--r-- | source/blender/editors/armature/pose_transform.c | 32 |
3 files changed, 30 insertions, 10 deletions
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index c4c10549da3..64857dd1874 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -908,8 +908,10 @@ static void bones_merge( newbone->parent = start->parent; /* TODO, copy more things to the new bone */ - newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_SCALE | - BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE); + newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_CYCLICOFFSET | + BONE_NO_LOCAL_LOCATION | BONE_DONE); + + newbone->inherit_scale_mode = start->inherit_scale_mode; /* Step 2a: reparent any side chains which may be parented to any bone in the chain * of bones to merge - potentially several tips for side chains leading to some tree exist. diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index cd299906b4c..2b18fc15f63 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -491,6 +491,7 @@ static EditBone *make_boneList_rec(ListBase *edbo, eBone->parent = parent; BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name)); eBone->flag = curBone->flag; + eBone->inherit_scale_mode = curBone->inherit_scale_mode; /* fix selection flags */ if (eBone->flag & BONE_SELECTED) { @@ -719,6 +720,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) newBone->arm_roll = eBone->roll; newBone->flag = eBone->flag; + newBone->inherit_scale_mode = eBone->inherit_scale_mode; if (eBone == arm->act_edbone) { /* don't change active selection, this messes up separate which uses diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 854fb237929..52a3f7711c4 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -241,13 +241,21 @@ static void applyarmature_process_selected_rec(bArmature *arm, /* Parent effects on the bone transform that have to be removed. */ BKE_bone_offset_matrix_get(bone, offs_bone); - BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, bone->parent->arm_mat, pchan_eval->parent->pose_mat, &old_bpt); + BKE_bone_parent_transform_calc_from_matrices(bone->flag, + bone->inherit_scale_mode, + offs_bone, + bone->parent->arm_mat, + pchan_eval->parent->pose_mat, + &old_bpt); /* Applied parent effects that have to be kept, if any. */ float(*new_parent_pose)[4] = pstate ? pstate->new_rest_mat : bone->parent->arm_mat; - BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, bone->parent->arm_mat, new_parent_pose, &new_bpt); + BKE_bone_parent_transform_calc_from_matrices(bone->flag, + bone->inherit_scale_mode, + offs_bone, + bone->parent->arm_mat, + new_parent_pose, + &new_bpt); BKE_bone_parent_transform_invert(&old_bpt); BKE_bone_parent_transform_combine(&new_bpt, &old_bpt, &invparent); @@ -283,8 +291,12 @@ static void applyarmature_process_selected_rec(bArmature *arm, /* Include applied parent effects. */ BKE_bone_offset_matrix_get(bone, offs_bone); - BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, pstate->bone->arm_mat, pstate->new_rest_mat, &bpt); + BKE_bone_parent_transform_calc_from_matrices(bone->flag, + bone->inherit_scale_mode, + offs_bone, + pstate->bone->arm_mat, + pstate->new_rest_mat, + &bpt); unit_m4(new_pstate.new_rest_mat); BKE_bone_parent_transform_apply(&bpt, new_pstate.new_rest_mat, new_pstate.new_rest_mat); @@ -306,8 +318,12 @@ static void applyarmature_process_selected_rec(bArmature *arm, /* Compute the channel coordinate space matrices for the new rest state. */ invert_m4_m4(inv_parent_arm, pstate->new_arm_mat); mul_m4_m4m4(offs_bone, inv_parent_arm, new_pstate.new_arm_mat); - BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, pstate->new_arm_mat, pstate->new_arm_mat, &bpt); + BKE_bone_parent_transform_calc_from_matrices(bone->flag, + bone->inherit_scale_mode, + offs_bone, + pstate->new_arm_mat, + pstate->new_arm_mat, + &bpt); /* Re-apply the location to keep the final effect. */ invert_m4(bpt.loc_mat); |