[Bf-blender-cvs] [7e8c6e71b9f] arcpatch-D8867_Nla_Merge_Strips: Refactor: NLA Prep for D8296

Wayde Moss noreply at git.blender.org
Wed Oct 21 06:26:01 CEST 2020


Commit: 7e8c6e71b9febba3a8922d2f257cd2e6b1b5ff43
Author: Wayde Moss
Date:   Wed Oct 21 00:18:02 2020 -0400
Branches: arcpatch-D8867_Nla_Merge_Strips
https://developer.blender.org/rB7e8c6e71b9febba3a8922d2f257cd2e6b1b5ff43

Refactor: NLA Prep for D8296

No intended functional changes.

This is the refactor of NLA evaluation to prepare for {D8296}. I was using TortoiseGitMerge to look at the diff to try to make the diff more readable.. but it looks like arcanist(?)/this-site uses a different method.

Refactor notes

- generally, functions not shuffled around so diffs are clearer
- in //(anim_sys.c)  nlaeval_blend_value()//, the bitmap writes to// NlaEvalChannel->valid// are unused and redundant so they're removed.
- renames //NlaEvalChannel->valid// to //NlaEvalChannel->domain// for term consistency with usage
- for blending functions, more descriptive names used and float equality checks changed to use //IS_EQF()// instead of ==.
- //(anim_sys.c) animsys_evaluate_nla()// separated into //for_flush //and //for_keyframing //variants to reduce complexity by making the use clear.
  - the dummy strip creation has been refactored to two separate functions for the tweak strip and nonpushed action strip. Both are evaluated differently from other strips and eachother. There's no need to interweave them. A future patch {D8296} generally requires both strips.
- XXX //(anim_sys.c) nlatrack_find_tweaked()// is a work around and temporary. If anyone has any insight into this problem, help is appreciated.
- //(anim_sys.c) nonstrip_action_fill_strip_data()// doesn't call// nlastrips_ctime_get_strip()// due to a future patch {D8867} needs to call the latter N times but the former only needs to be called once.
- //(anim_sys.c) BKE_is_nlatrack_evaluatable() //is an API function so a future patch {D8867} can access it.
- //(anim_sys.c) BKE_animsys_nla_remap_keyframe_values()// removed full replace strip early out. Future patch {D8296} can't use it.
- add const, limited to refactored areas
- remove redundant switch-case fall throughs to default
- //nlaeval_blend_flush()// small refactor, replace branching with assertion
- return value of //nla_combine_quaternion_invert_get_fcurve_values()// implemented to handle case where influence == 0. This failure case added to other blend inversions too. The Nla remap function  // (anim_sys.c) BKE_animsys_nla_remap_keyframe_values()// does this check but future patch {D8867} will not use the remap function directly.

Differential Revision: https://developer.blender.org/D9247

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

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 03c812b3b3d..5e42ef5d100 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -979,6 +979,19 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list,
   return nes;
 }
 
+static NlaEvalStrip *nlastrips_ctime_get_strip_single(
+    ListBase *estrips,
+    NlaStrip *single_strip,
+    const AnimationEvalContext *anim_eval_context,
+    const bool flush_to_original)
+{
+  ListBase dummy_trackslist;
+  dummy_trackslist.first = dummy_trackslist.last = single_strip;
+
+  return nlastrips_ctime_get_strip(
+      estrips, &dummy_trackslist, -1, anim_eval_context, flush_to_original);
+}
+
 /* ---------------------- */
 
 /* Initialize a valid mask, allocating memory if necessary. */
@@ -1152,7 +1165,7 @@ static void nlaeval_snapshot_free_data(NlaEvalSnapshot *snapshot)
 /* Free memory owned by this evaluation channel. */
 static void nlaevalchan_free_data(NlaEvalChannel *nec)
 {
-  nlavalidmask_free(&nec->valid);
+  nlavalidmask_free(&nec->domain);
 
   if (nec->blend_snapshot != NULL) {
     nlaevalchan_snapshot_free(nec->blend_snapshot);
@@ -1189,7 +1202,7 @@ static void nlaeval_free(NlaEvalData *nlaeval)
 
 /* ---------------------- */
 
-static int nlaevalchan_validate_index(NlaEvalChannel *nec, int index)
+static int nlaevalchan_validate_index(const NlaEvalChannel *nec, const int index)
 {
   if (nec->is_array) {
     if (index >= 0 && index < nec->base_snapshot.length) {
@@ -1201,6 +1214,28 @@ static int nlaevalchan_validate_index(NlaEvalChannel *nec, int index)
   return 0;
 }
 
+static bool nlaevalchan_validate_index_ex(const NlaEvalChannel *nec, const int array_index)
+{
+  /** Although array_index comes from fcurve, that doesn't necessarily mean the property has that
+   * many elements. */
+  const int index = nlaevalchan_validate_index(nec, array_index);
+
+  if (index < 0) {
+    if (G.debug & G_DEBUG) {
+      ID *id = nec->key.ptr.owner_id;
+      CLOG_WARN(&LOG,
+                "Animation: Invalid array index. ID = '%s',  '%s[%d]', array length is %d",
+                id ? (id->name + 2) : "<No ID>",
+                nec->rna_path,
+                array_index,
+                nec->base_snapshot.length);
+    }
+
+    return false;
+  }
+  return true;
+}
+
 /* Initialize default values for NlaEvalChannel from the property data. */
 static void nlaevalchan_get_default_values(NlaEvalChannel *nec, float *r_values)
 {
@@ -1331,7 +1366,7 @@ static NlaEvalChannel *nlaevalchan_verify_key(NlaEvalData *nlaeval,
 
   nec->mix_mode = nlaevalchan_detect_mix_mode(key, length);
 
-  nlavalidmask_init(&nec->valid, length);
+  nlavalidmask_init(&nec->domain, length);
 
   nec->base_snapshot.channel = nec;
   nec->base_snapshot.length = length;
@@ -1399,180 +1434,226 @@ static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, NlaEvalData *nlaeval,
 
 /* ---------------------- */
 
-/* accumulate the old and new values of a channel according to mode and influence */
-static float nla_blend_value(int blendmode, float old_value, float value, float inf)
+/* Accumulate the lower strip and fcurve values of a channel according to mode and influence. */
+static float nla_blend_value(const int blendmode,
+                             const float lower_value,
+                             const float fcurve_value,
+                             const float inf)
 {
   /* Optimization: no need to try applying if there is no influence. */
   if (IS_EQF(inf, 0.0f)) {
-    return old_value;
+    return lower_value;
   }
 
-  /* perform blending */
+  /* Perform blending. */
   switch (blendmode) {
     case NLASTRIP_MODE_ADD:
-      /* simply add the scaled value on to the stack */
-      return old_value + (value * inf);
+      /* Simply add the scaled value on to the stack. */
+      return lower_value + (fcurve_value * inf);
 
     case NLASTRIP_MODE_SUBTRACT:
-      /* simply subtract the scaled value from the stack */
-      return old_value - (value * inf);
+      /* Simply subtract the scaled value from the stack. */
+      return lower_value - (fcurve_value * inf);
 
     case NLASTRIP_MODE_MULTIPLY:
-      /* multiply the scaled value with the stack */
-      /* Formula Used:
-       *     result = fac * (a * b) + (1 - fac) * a
-       */
-      return inf * (old_value * value) + (1 - inf) * old_value;
+      /* Multiply the scaled value with the stack. */
+      return inf * (lower_value * fcurve_value) + (1 - inf) * lower_value;
 
     case NLASTRIP_MODE_COMBINE:
       BLI_assert(!"combine mode");
       ATTR_FALLTHROUGH;
 
-    case NLASTRIP_MODE_REPLACE:
-    default
-        : /* TODO: do we really want to blend by default? it seems more uses might prefer add... */
-      /* do linear interpolation
-       * - the influence of the accumulated data (elsewhere, that is called dstweight)
-       *   is 1 - influence, since the strip's influence is srcweight
+    default:
+      /* TODO: Do we really want to blend by default? it seems more uses might prefer add... */
+      /* Do linear interpolation. The influence of the accumulated data (elsewhere, that is called
+       * dstweight) is 1 - influence, since the strip's influence is srcweight.
        */
-      return old_value * (1.0f - inf) + (value * inf);
+      return lower_value * (1.0f - inf) + (fcurve_value * inf);
   }
 }
 
-/* accumulate the old and new values of a channel according to mode and influence */
-static float nla_combine_value(
-    int mix_mode, float base_value, float old_value, float value, float inf)
+/* Accumulate the lower and fcurve values of a channel according to mode and influence. */
+static float nla_combine_value(const int mix_mode,
+                               float base_value,
+                               const float lower_value,
+                               const float fcurve_value,
+                               const float inf)
 {
-  /* Optimization: no need to try applying if there is no influence. */
+  /* Optimization: No need to try applying if there is no influence. */
   if (IS_EQF(inf, 0.0f)) {
-    return old_value;
+    return lower_value;
   }
 
-  /* perform blending */
+  /* Perform blending */
   switch (mix_mode) {
     case NEC_MIX_ADD:
     case NEC_MIX_AXIS_ANGLE:
-      return old_value + (value - base_value) * inf;
+      return lower_value + (fcurve_value - base_value) * inf;
 
     case NEC_MIX_MULTIPLY:
-      if (base_value == 0.0f) {
+      if (IS_EQF(base_value, 0.0f)) {
         base_value = 1.0f;
       }
-      return old_value * powf(value / base_value, inf);
+      return lower_value * powf(fcurve_value / base_value, inf);
 
-    case NEC_MIX_QUATERNION:
     default:
       BLI_assert(!"invalid mix mode");
-      return old_value;
+      return lower_value;
   }
 }
 
-/* compute the value that would blend to the desired target value using nla_blend_value */
-static bool nla_invert_blend_value(
-    int blend_mode, float old_value, float target_value, float influence, float *r_value)
+/** \returns true if solution exists and output is written to. */
+static bool nla_blend_value_invert_get_fcurve_value(const int blend_mode,
+                                                    const float lower_value,
+                                                    const float blended_value,
+                                                    const float influence,
+                                                    float *r_fcurve_value)
 {
+
+  /** No solution if fcurve value had 0 influence. */
+  if (IS_EQF(0, influence)) {
+    return false;
+  }
+
   switch (blend_mode) {
     case NLASTRIP_MODE_ADD:
-      *r_value = (target_value - old_value) / influence;
+      *r_fcurve_value = (blended_value - lower_value) / influence;
       return true;
 
     case NLASTRIP_MODE_SUBTRACT:
-      *r_value = (old_value - target_value) / influence;
+      *r_fcurve_value = (lower_value - blended_value) / influence;
       return true;
 
     case NLASTRIP_MODE_MULTIPLY:
-      if (old_value == 0.0f) {
+
+      /** Division by zero. */
+      if (IS_EQF(0.0f, lower_value)) {
         /* Resolve 0/0 to 1. */
-        if (target_value == 0.0f) {
-          *r_value = 1.0f;
+        if (IS_EQF(0.0f, blended_value)) {
+          *r_fcurve_value = 1.0f;
           return true;
         }
         /* Division by zero. */
         return false;
       }
-      else {
-        *r_value = (target_value - old_value) / influence / old_value + 1.0f;
-        return true;
-      }
+
+      /** Math:
+       *
+       *  blended_value = inf * (lower_value * fcurve_value) + (1 - inf) * lower_value
+       *  blended_value - (1 - inf) * lower_value = inf * (lower_value * fcurve_value)
+       *  (blended_value - (1 - inf) * lower_value) / (inf * lower_value) =  fcurve_value
+       *  (blended_value - lower_value + inf * lower_value) / (inf * lower_value) =  fcurve_value
+       *  ((blended_value - lower_value) / (inf * lower_value)) + 1 =  fcurve_value
+       *
+       *  fcurve_value = ((blended_value - lower_value) / (inf * lower_value)) + 1
+       */
+      *r_fcurve_value = ((blended_value - lower_value) / (influence * lower_value)) + 1.0f;
+      return true;
 
     case NLASTRIP_MODE_COMBINE:
       BLI_assert(!"combine mode");
       ATTR_FALLTHROUGH;
 
-    case NLASTRIP_MODE_REPLACE:
     default:
-      *r_value = (target_value - old_value) / influence + old_value;
+
+      /** Math:
+       *
+       *  blended_value = lower_value * (1.0f - inf) + (fcurve_value * inf)
+       *  blended_value - lower_value * (1.0f - inf) = (fcurve_value * inf)
+       *  (blended_value - lower_value * (1.0f - inf)) / inf = fcurve_value
+       *
+       *  fcurve_value = (blended_value - lower_value * (1.0f - inf)) / inf
+       */
+      *r_fcurve_value = (blended_value - lower_value * (1.0f - influence)) / influence;
       return true;
   }
 }
 
-/* compute the value that would blend to the desired target value using nla_combine_value */
-static bool nla_invert_combine_value(int mix_mode,
-                                     float base_value,
-                                     float old_va

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list