diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-08-23 03:38:30 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-08-23 04:53:28 +0300 |
commit | 30582c59ccd00fc5c3221540c078947d25fc1bfd (patch) | |
tree | de3e29be891d3f165636a43cbc3ce26d3cc5880d /source/blender/blenkernel | |
parent | adfb9ec87cebafe61e8870c5dfd7593d32e9eb0a (diff) |
Armature: add BKE_armature_transform
ED_armature_transform uses edit-mode conversion which re-creates bones.
Needed for efficiently transforming object-data in object-mode.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_armature.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 84 |
2 files changed, 86 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index c1f04894880..ee6336a98db 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -78,6 +78,8 @@ struct bArmature *BKE_armature_copy(struct Main *bmain, const struct bArmature * void BKE_armature_copy_bone_transforms(struct bArmature *armature_dst, const struct bArmature *armature_src); +void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props); + /* Bounding box. */ struct BoundBox *BKE_armature_boundbox_get(struct Object *ob); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 89ba5e38c39..168422a4454 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -268,6 +268,90 @@ void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature } } +/** Helper for #ED_armature_transform */ +static void armature_transform_recurse(ListBase *bonebase, + const float mat[4][4], + const bool do_props, + /* Cached from 'mat'. */ + const float mat3[3][3], + const float scale, + /* Child bones. */ + const Bone *bone_parent, + const float arm_mat_parent_inv[4][4]) +{ + for (Bone *bone = bonebase->first; bone; bone = bone->next) { + + /* Transform the bone's roll. */ + if (bone_parent == NULL) { + + float roll_mat[3][3]; + { + float delta[3]; + sub_v3_v3v3(delta, bone->tail, bone->head); + vec_roll_to_mat3(delta, bone->roll, roll_mat); + } + + /* Transform the roll matrix. */ + mul_m3_m3m3(roll_mat, mat3, roll_mat); + + /* Apply the transformed roll back. */ + mat3_to_vec_roll(roll_mat, NULL, &bone->roll); + } + + mul_m4_v3(mat, bone->arm_head); + mul_m4_v3(mat, bone->arm_tail); + + /* Get the new head and tail */ + if (bone_parent) { + sub_v3_v3v3(bone->head, bone->arm_head, bone_parent->arm_tail); + sub_v3_v3v3(bone->tail, bone->arm_tail, bone_parent->arm_tail); + + mul_mat3_m4_v3(arm_mat_parent_inv, bone->head); + mul_mat3_m4_v3(arm_mat_parent_inv, bone->tail); + } + else { + copy_v3_v3(bone->head, bone->arm_head); + copy_v3_v3(bone->tail, bone->arm_tail); + } + + BKE_armature_where_is_bone(bone, bone_parent, false); + + { + float arm_mat3[3][3]; + copy_m3_m4(arm_mat3, bone->arm_mat); + mat3_to_vec_roll(arm_mat3, NULL, &bone->arm_roll); + } + + if (do_props) { + bone->rad_head *= scale; + bone->rad_tail *= scale; + bone->dist *= scale; + + /* we could be smarter and scale by the matrix along the x & z axis */ + bone->xwidth *= scale; + bone->zwidth *= scale; + } + + if (!BLI_listbase_is_empty(&bone->childbase)) { + float arm_mat_inv[4][4]; + invert_m4_m4(arm_mat_inv, bone->arm_mat); + armature_transform_recurse(&bone->childbase, mat, do_props, mat3, scale, bone, arm_mat_inv); + } + } +} + +void BKE_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props) +{ + /* Store the scale of the matrix here to use on envelopes. */ + float scale = mat4_to_scale(mat); + float mat3[3][3]; + + copy_m3_m4(mat3, mat); + normalize_m3(mat3); + + armature_transform_recurse(&arm->bonebase, mat, do_props, mat3, scale, NULL, NULL); +} + static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name) { Bone *curBone, *rbone; |