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:
authorCampbell Barton <ideasman42@gmail.com>2019-08-23 03:38:30 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-08-23 04:53:28 +0300
commit30582c59ccd00fc5c3221540c078947d25fc1bfd (patch)
treede3e29be891d3f165636a43cbc3ce26d3cc5880d /source/blender
parentadfb9ec87cebafe61e8870c5dfd7593d32e9eb0a (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')
-rw-r--r--source/blender/blenkernel/BKE_armature.h2
-rw-r--r--source/blender/blenkernel/intern/armature.c84
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;