[Bf-blender-cvs] [fac59931c77] ui-asset-view-template: Cleanup: minor changes to pose-mode apply visual transform

Campbell Barton noreply at git.blender.org
Sun Mar 21 16:11:59 CET 2021


Commit: fac59931c77a8dfacb34bf3416747ae66377e959
Author: Campbell Barton
Date:   Fri Mar 19 15:22:45 2021 +1100
Branches: ui-asset-view-template
https://developer.blender.org/rBfac59931c77a8dfacb34bf3416747ae66377e959

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.

===================================================================

M	source/blender/editors/armature/pose_transform.c
M	source/blender/makesdna/DNA_action_types.h

===================================================================

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`



More information about the Bf-blender-cvs mailing list