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>2021-03-19 07:22:45 +0300
committerCampbell Barton <ideasman42@gmail.com>2021-03-19 07:33:43 +0300
commit74609bfd510c98161b8e251cb10f6e299e44e544 (patch)
treed6d07c603040092d6d42c6f2a2cfd9e2b34249fd
parent36deb8a48ef22e8732535c48b23af3dbc260495f (diff)
Cleanup: minor changes to pose-mode apply visual transform
- Remove use of evaluated poses, instead calculate transformations into an array which is applied afterwards. - Only update ID's for poses that have been changed.
-rw-r--r--source/blender/editors/armature/pose_transform.c73
-rw-r--r--source/blender/makesdna/DNA_action_types.h5
2 files changed, 52 insertions, 26 deletions
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index bb7ec82490a..8d1c196e9c2 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -512,37 +512,60 @@ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
{
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+
+ /* Needed to ensure #bPoseChannel.pose_mat are up to date. */
+ CTX_data_ensure_evaluated_depsgraph(C);
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, OB_ARMATURE, OB_MODE_POSE, ob) {
- /* Loop over all selected pchan's.
- *
- * TODO, loop over children before parents if multiple bones
- * at once are to be predictable*/
- FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN (ob, pchan) {
- const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
- float delta_mat[4][4];
-
- /* chan_mat already contains the delta transform from rest pose to pose-mode pose
- * as that is baked into there so that B-Bones will work. Once we've set this as the
- * new raw-transform components, don't recalc the poses yet, otherwise IK result will
- * change, thus changing the result we may be trying to record.
- */
- /* XXX For some reason, we can't use pchan->chan_mat here, gives odd rotation/offset
- * (see T38251).
- * Using pchan->pose_mat and bringing it back in bone space seems to work as expected!
- */
- BKE_armature_mat_pose_to_bone(pchan_eval, pchan_eval->pose_mat, delta_mat);
+ const bArmature *arm = ob->data;
+
+ int chanbase_len = BLI_listbase_count(&ob->pose->chanbase);
+ /* Storage for the calculated matrices to prevent reading from modified values.
+ * NOTE: this could be avoided if children were always calculated before parents
+ * however ensuring this is involved and doesn't give any significant advantage. */
+ struct {
+ float matrix[4][4];
+ bool is_set;
+ } *pchan_xform_array = MEM_mallocN(sizeof(*pchan_xform_array) * chanbase_len, __func__);
+ bool changed = false;
- BKE_pchan_apply_mat4(pchan, delta_mat, true);
+ int i;
+ LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, i) {
+ if (!((pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone))) {
+ pchan_xform_array[i].is_set = false;
+ continue;
+ }
+
+ /* `chan_mat` already contains the delta transform from rest pose to pose-mode pose
+ * as that is baked into there so that B-Bones will work. Once we've set this as the
+ * new raw-transform components, don't recalculate the poses yet, otherwise IK result will
+ * change, thus changing the result we may be trying to record. */
+
+ /* NOTE: For some reason `pchan->chan_mat` can't be used here as it gives odd
+ * rotation/offset, see T38251.
+ * Using `pchan->pose_mat` and bringing it back in bone space seems to work as expected!
+ * This matches how visual key-framing works. */
+ BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, pchan_xform_array[i].matrix);
+ pchan_xform_array[i].is_set = true;
+ changed = true;
}
- FOREACH_PCHAN_SELECTED_IN_OBJECT_END;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ if (changed) {
+ /* Perform separately to prevent feedback loop. */
+ LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, i) {
+ if (!pchan_xform_array[i].is_set) {
+ continue;
+ }
+ BKE_pchan_apply_mat4(pchan, pchan_xform_array[i].matrix, true);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ /* note, notifier might evolve */
+ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ }
- /* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
+ MEM_freeN(pchan_xform_array);
}
FOREACH_OBJECT_IN_MODE_END;
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 27374c451e9..5cc525a6cff 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -287,7 +287,10 @@ typedef struct bPoseChannel {
short rotmode;
char _pad[2];
- /** Matrix result of loc/quat/size, and where we put deform in, see next line */
+ /**
+ * Matrix result of location/rotation/scale components & constraints.
+ * This is the dynamic component of `pose_mat` (without #Bone.arm_mat).
+ */
float chan_mat[4][4];
/**
* Constraints accumulate here. in the end, `pose_mat = bone->arm_mat * chan_mat`