[Bf-blender-cvs] [27388587e66] temp-nla-strip-alignment: - WIP rough core implementation of strip preblend xform support for animation alignment

Wayde Moss noreply at git.blender.org
Thu Dec 10 06:13:36 CET 2020


Commit: 27388587e66ab68f44fe34fe688bda6916b165f5
Author: Wayde Moss
Date:   Wed Nov 25 01:50:35 2020 -0500
Branches: temp-nla-strip-alignment
https://developer.blender.org/rB27388587e66ab68f44fe34fe688bda6916b165f5

- WIP rough core implementation of strip preblend xform support for animation alignment

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

M	source/blender/blenkernel/intern/anim_sys.c
M	source/blender/blenkernel/nla_private.h

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

diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 53c3ef66c84..a1d577259f7 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -40,7 +40,9 @@
 
 #include "BLT_translation.h"
 
+#include "DNA_action_types.h"
 #include "DNA_anim_types.h"
+#include "DNA_constraint_types.h"
 #include "DNA_light_types.h"
 #include "DNA_material_types.h"
 #include "DNA_object_types.h"
@@ -2931,7 +2933,47 @@ static void nlastrip_evaluate_meta_raw_value(PointerRNA *ptr,
   /* unlink this strip's modifiers from the parent's modifiers again */
   nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
 }
+/*
+ * lower is also output
+ */
+static void nlaeval_snapshot_blend(NlaEvalData *nlaeval,
+                                   NlaEvalSnapshot *raw_upper,
+                                   short upper_blendmode,
+                                   float upper_influence,
+                                   NlaEvalSnapshot *lower)
+{
+  nlaeval_snapshot_ensure_size(lower, nlaeval->num_channels);
+
+  for (int i = 0; i < nlaeval->num_channels; i++) {
+    NlaEvalChannelSnapshot *c_upper = nlaeval_snapshot_get(raw_upper, i);
+    if (c_upper == NULL) {
+      continue;
+    }
+
+    NlaEvalChannelSnapshot *c_lower = nlaeval_snapshot_ensure_channel(lower, nec);
 
+    NlaEvalChannel *nec = c_lower->channel;
+    int mix_mode = c_lower->channel->mix_mode;
+    if (upper_blendmode == NLASTRIP_MODE_COMBINE) {
+      if (mix_mode == NEC_MIX_QUATERNION) {
+        nla_combine_quaternion(c_lower->values, c_upper->values, upper_influence, c_lower->values);
+      }
+      else {
+        float *base_values = nec->base_snapshot.values;
+        for (int j = 0; j < c_lower->length; j++) {
+          c_lower->values[j] = nla_combine_value(
+              mix_mode, base_values[j], c_lower->values[j], c_upper->values[j], upper_influence);
+        }
+      }
+    }
+    else {
+      for (int j = 0; j < c_lower->length; j++) {
+        c_lower->values[j] = nla_blend_value(
+            upper_blendmode, c_lower->values[j], c_upper->values[j], upper_influence);
+      }
+    }
+  }
+}
 /* evaluates the given evaluation strip */
 void nlastrip_evaluate(PointerRNA *ptr,
                        NlaEvalData *channels,
@@ -2942,52 +2984,100 @@ void nlastrip_evaluate(PointerRNA *ptr,
                        const bool flush_to_original,
                        bool allow_alloc_channels)
 {
-  NlaStrip *strip = nes->strip;
 
-  /* To prevent potential infinite recursion problems
-   * (i.e. transition strip, beside meta strip containing a transition
-   * several levels deep inside it),
-   * we tag the current strip as being evaluated, and clear this when we leave.
-   */
-  /* TODO: be careful with this flag, since some edit tools may be running and have
-   * set this while animation playback was running. */
-  if (strip->flag & NLASTRIP_FLAG_EDIT_TOUCHED) {
-    return;
-  }
-  strip->flag |= NLASTRIP_FLAG_EDIT_TOUCHED;
+  NlaEvalSnapshot snapshot_raw;
+  nlaeval_snapshot_init(&snapshot_raw, channels, NULL);
 
-  /* actions to take depend on the type of strip */
-  switch (strip->type) {
-    case NLASTRIP_TYPE_CLIP: /* action-clip */
-      nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes, snapshot, allow_alloc_channels);
-      break;
-    case NLASTRIP_TYPE_TRANSITION: /* transition */
-      nlastrip_evaluate_transition(ptr,
-                                   channels,
-                                   modifiers,
-                                   nes,
-                                   snapshot,
-                                   anim_eval_context,
-                                   flush_to_original,
-                                   allow_alloc_channels);
-      break;
-    case NLASTRIP_TYPE_META: /* meta */
-      nlastrip_evaluate_meta(ptr,
-                             channels,
-                             modifiers,
-                             nes,
-                             snapshot,
-                             anim_eval_context,
-                             flush_to_original,
-                             allow_alloc_channels);
-      break;
+  short blendmode = 0;
+  float influence = 0;
+  nlastrip_evaluate_raw_value(
+      ptr, channels, NULL, nes, &snapshot_raw, anim_eval_context, &blendmode, &influence);
+
+  /* Apply preblend transforms to each bone's raw snapshot values.  */
+  Object *object = (Object *)ptr->owner_id;
+  bPose *pose = object->pose;
+  LISTBASE_FOREACH (NlaStripPreBlendTransform *, preblend, &nes->strip->preblend_transforms) {
+    float world[4][4];
+    loc_eul_size_to_mat4(world, preblend->location, preblend->rotation_euler, preblend->scale);
+
+    LISTBASE_FOREACH (NlaStripPreBlendTransform_BoneName *, bone, &preblend_xform->bones) {
+
+      char name_esc[sizeof(bone->name) * 2];
+      BLI_strescape(name_esc, bone->name, sizeof(name_esc));
+
+      /* Get preblend transform in bone's non-animated local space. */
+      float bone_preblend_matrix[4][4];
+      copy_m4_m4(bone_preblend_matrix, world);
+      bPoseChannel *pose_channel = BKE_pose_channel_find_name(pose, name_esc);
+      BKE_constraint_mat_convertspace(object,
+                                      pose_channel,
+                                      bone_preblend_matrix,
+                                      CONSTRAINT_SPACE_WORLD,
+                                      CONSTRAINT_SPACE_LOCAL,
+                                      false);
+
+      char *location_path = BLI_sprintfN("pose.bones[\"\s\"].location", name_esc);
+      NlaEvalChannel *location_channel = nlaevalchan_verify(ptr, channels, location_path);
+      float *location_values =
+          nlaeval_snapshot_ensure_channel(snapshot_raw, location_channel)->values;
+
+      char *rotation_path;
+      switch (pose_channel->rotmode) {
+        case ROT_MODE_QUAT:
+          rotation_path = BLI_sprintfN("pose.bones[\"\s\"].rotation_quaternion", name_esc);
+          break;
+        case ROT_MODE_AXISANGLE:
+          rotation_path = BLI_sprintfN("pose.bones[\"\s\"].rotation_axis_angle", name_esc);
+          break;
+        default:
+          rotation_path = BLI_sprintfN("pose.bones[\"\s\"].rotation_euler", name_esc);
+          break;
+      }
+      NlaEvalChannel *rotation_channel = nlaevalchan_verify(ptr, channels, rotation_path);
+      float *rotation_values =
+          nlaeval_snapshot_ensure_channel(snapshot_raw, rotation_channel)->values;
+
+      char *scale_path = BLI_sprintfN("pose.bones[\"\s\"].scale", name_esc);
+      NlaEvalChannel *scale_channel = nlaevalchan_verify(ptr, channels, scale_path);
+      float *scale_values = nlaeval_snapshot_ensure_channel(snapshot_raw, scale_channel)->values;
+
+      /* Apply preblend transform as a parent transform to bone's action channels.
+       * Results written directly back to raw snapshot. */
+      float raw_snapshot_matrix[4][4];
+      float decomposed_quat[4];
+      switch (pose_channel->rotmode) {
+        case ROT_MODE_QUAT:
+          loc_quat_size_to_mat4(
+              raw_snapshot_matrix, location_values, rotation_values, scale_values);
+          mul_m4_m4m4(raw_snapshot_matrix, bone_preblend_matrix, raw_snapshot_matrix);
+          mat4_decompose(location_values, rotation_values, scale_values, raw_snapshot_matrix);
 
-    default: /* do nothing */
-      break;
+          break;
+        case ROT_MODE_AXISANGLE:
+          loc_axisangle_size_to_mat4(
+              raw_snapshot_matrix, location_values, rotation_values, scale_values);
+          mul_m4_m4m4(raw_snapshot_matrix, bone_preblend_matrix, raw_snapshot_matrix);
+          mat4_decompose(location_values, decomposed_quat, scale_values, raw_snapshot_matrix);
+          quat_to_axis_angle(rotation_values, &rotation_values[3], decomposed_quat);
+          break;
+        default:
+          loc_eul_size_to_mat4(
+              raw_snapshot_matrix, location_values, rotation_values, scale_values);
+          mul_m4_m4m4(raw_snapshot_matrix, bone_preblend_matrix, raw_snapshot_matrix);
+          quat_to_eul(rotation_values, decomposed_quat);
+
+          break;
+      }
+
+      MEM_freeN(location_path);  // todo: verify correct call
+      MEM_freeN(rotation_path);  // todo: verify correct call
+      MEM_freeN(scale_path);     // todo: verify correct call
+    }
   }
 
-  /* clear temp recursion safe-check */
-  strip->flag &= ~NLASTRIP_FLAG_EDIT_TOUCHED;
+  /** Blend raw snapshot with lower snapshot. */
+  nlaeval_snapshot_blend(channels, &snapshot_raw, blendmode, influence, snapshot);
+  nlaeval_snapshot_free_data(&snapshot_raw);
 }
 
 /* Removes the effect of the evaluation strip from the snapshot value,
@@ -3037,8 +3127,8 @@ void nlastrip_evaluate_invert_get_lower_values(PointerRNA *ptr,
 }
 
 /* Evaluates strip without blending, stored within snapshot. NLAEvalChannelSnapshot
- * raw_value_sampled bits are set for channels sampled. This is only called by transition's invert
- * function. */
+ * raw_value_sampled bits are set for channels sampled. This is only called by transition's
+ * invert function. */
 void nlastrip_evaluate_raw_value(PointerRNA *ptr,
                                  NlaEvalData *upper_eval_data,
                                  ListBase *modifiers,
@@ -3070,9 +3160,9 @@ void nlastrip_evaluate_raw_value(PointerRNA *ptr,
       break;
     case NLASTRIP_TYPE_TRANSITION:
       /*
-       * If nes is eventually a transition, then nothing is written and no value bitmask is set.
-       * This matches the existing behavior that adjacent transitions evaluate to default (lower
-       * snapshot or property type default).
+       * If nes is eventually a transition, then nothing is written and no value bitmask is
+       * set. This matches the existing behavior that adjacent transitions evaluate to default
+       * (lower snapshot or property type default).
        *
        * In normal cases, this case should never happen. This is only called by
        * nlastrip_evaluate_transition_invert_get_lower_values() and transitions never reference
@@ -3114,8 +3204,8 @@ void nladata_flush_channels(PointerRNA *ptr,
   LISTBASE

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list