Armature: remove remains of the object-level deformation data cache.
authorAlexander Gavrilov <angavrilov@gmail.com>
Thu, 18 Apr 2019 20:17:04 +0000 (23:17 +0300)
committerAlexander Gavrilov <angavrilov@gmail.com>
Thu, 18 Apr 2019 20:19:44 +0000 (23:19 +0300)
Now that B-Bone shape data is kept in bPoseChannel_Runtime, the
armature level cache only holds one quaternion value per bone.
It can also be moved to runtime, and the structure removed.

This has an additional effect that, as far as I can tell, now
the Armature modifier can run as soon as all of the bones it
actually needs are done, thus making T59848 a purely depsgraph
level problem.

intern/opencolorio/CMakeLists.txt
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/armature_update.c
source/blender/blenkernel/intern/object.c
source/blender/blenlib/BLI_math_rotation.h
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_vec_types.h

index da0956c..4d95c1b 100644 (file)
@@ -24,6 +24,7 @@ set(INC
   ../guardedalloc
   ../../source/blender/blenlib
   ../../source/blender/gpu
+  ../../source/blender/makesdna
 )
 
 set(INC_SYS
index 50457c5..e171eec 100644 (file)
@@ -335,17 +335,6 @@ void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph,
                                    struct Object *object,
                                    int pchan_index);
 
-/* BBOne deformation cache.
- *
- * The idea here is to pre-calculate deformation queternions, matricies and such
- * used by armature_deform_verts().
- */
-struct ObjectBBoneDeform;
-struct ObjectBBoneDeform *BKE_armature_cached_bbone_deformation_get(struct Object *object);
-void BKE_armature_cached_bbone_deformation_free_data(struct Object *object);
-void BKE_armature_cached_bbone_deformation_free(struct Object *object);
-void BKE_armature_cached_bbone_deformation_update(struct Object *object);
-
 #ifdef __cplusplus
 }
 #endif
index 91c7602..6cbc990 100644 (file)
@@ -932,17 +932,6 @@ int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
 
 /* ************ Armature Deform ******************* */
 
-typedef struct bPoseChanDeform {
-  DualQuat *dual_quat;
-} bPoseChanDeform;
-
-/* Definition of cached object bbone deformations. */
-typedef struct ObjectBBoneDeform {
-  DualQuat *dualquats;
-  bPoseChanDeform *pdef_info_array;
-  int num_pchan;
-} ObjectBBoneDeform;
-
 static void allocate_bbone_cache(bPoseChannel *pchan, int segments)
 {
   bPoseChannel_Runtime *runtime = &pchan->runtime;
@@ -1171,12 +1160,8 @@ float distfactor_to_bone(
   }
 }
 
-static float dist_bone_deform(bPoseChannel *pchan,
-                              const bPoseChanDeform *pdef_info,
-                              float vec[3],
-                              DualQuat *dq,
-                              float mat[3][3],
-                              const float co[3])
+static float dist_bone_deform(
+    bPoseChannel *pchan, float vec[3], DualQuat *dq, float mat[3][3], const float co[3])
 {
   Bone *bone = pchan->bone;
   float fac, contrib = 0.0;
@@ -1194,7 +1179,8 @@ static float dist_bone_deform(bPoseChannel *pchan,
       if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments)
         b_bone_deform(pchan, co, fac, vec, dq, mat);
       else
-        pchan_deform_accumulate(pdef_info->dual_quat, pchan->chan_mat, co, fac, vec, dq, mat);
+        pchan_deform_accumulate(
+            &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, fac, vec, dq, mat);
     }
   }
 
@@ -1202,7 +1188,6 @@ static float dist_bone_deform(bPoseChannel *pchan,
 }
 
 static void pchan_bone_deform(bPoseChannel *pchan,
-                              const bPoseChanDeform *pdef_info,
                               float weight,
                               float vec[3],
                               DualQuat *dq,
@@ -1218,33 +1203,12 @@ static void pchan_bone_deform(bPoseChannel *pchan,
   if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments)
     b_bone_deform(pchan, co, weight, vec, dq, mat);
   else
-    pchan_deform_accumulate(pdef_info->dual_quat, pchan->chan_mat, co, weight, vec, dq, mat);
+    pchan_deform_accumulate(
+        &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, weight, vec, dq, mat);
 
   (*contrib) += weight;
 }
 
-typedef struct ArmatureBBoneDefmatsData {
-  bPoseChanDeform *pdef_info_array;
-  DualQuat *dualquats;
-  bool use_quaternion;
-} ArmatureBBoneDefmatsData;
-
-static void armature_bbone_defmats_cb(void *userdata, Link *iter, int index)
-{
-  ArmatureBBoneDefmatsData *data = userdata;
-  bPoseChannel *pchan = (bPoseChannel *)iter;
-
-  if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
-    bPoseChanDeform *pdef_info = &data->pdef_info_array[index];
-    const bool use_quaternion = data->use_quaternion;
-
-    if (use_quaternion) {
-      pdef_info->dual_quat = &data->dualquats[index];
-      mat4_to_dquat(pdef_info->dual_quat, pchan->bone->arm_mat, pchan->chan_mat);
-    }
-  }
-}
-
 void armature_deform_verts(Object *armOb,
                            Object *target,
                            const Mesh *mesh,
@@ -1256,10 +1220,8 @@ void armature_deform_verts(Object *armOb,
                            const char *defgrp_name,
                            bGPDstroke *gps)
 {
-  const bPoseChanDeform *pdef_info = NULL;
   bArmature *arm = armOb->data;
   bPoseChannel *pchan, **defnrToPC = NULL;
-  int *defnrToPCIndex = NULL;
   MDeformVert *dverts = NULL;
   bDeformGroup *dg;
   float obinv[4][4], premat[4][4], postmat[4][4];
@@ -1288,20 +1250,6 @@ void armature_deform_verts(Object *armOb,
   mul_m4_m4m4(postmat, obinv, armOb->obmat);
   invert_m4_m4(premat, postmat);
 
-  /* Use pre-calculated bbone deformation.
-   *
-   * TODO(sergey): Make this code robust somehow when there are dependency
-   * cycles involved. */
-  ObjectBBoneDeform *bbone_deform = BKE_armature_cached_bbone_deformation_get(armOb);
-  if (bbone_deform == NULL || bbone_deform->pdef_info_array == NULL) {
-    CLOG_ERROR(&LOG,
-               "Armature does not have bbone cache %s, "
-               "usually happens due to a dependency cycle.\n",
-               armOb->id.name + 2);
-    return;
-  }
-  const bPoseChanDeform *pdef_info_array = bbone_deform->pdef_info_array;
-
   /* get the def_nr for the overall armature vertex group if present */
   armature_def_nr = defgroup_name_index(target, defgrp_name);
 
@@ -1340,19 +1288,10 @@ void armature_deform_verts(Object *armOb,
 
       if (use_dverts) {
         defnrToPC = MEM_callocN(sizeof(*defnrToPC) * defbase_tot, "defnrToBone");
-        defnrToPCIndex = MEM_callocN(sizeof(*defnrToPCIndex) * defbase_tot, "defnrToIndex");
         /* TODO(sergey): Some considerations here:
          *
-         * - Make it more generic function, maybe even keep together with chanhash.
          * - Check whether keeping this consistent across frames gives speedup.
-         * - Don't use hash for small armatures.
          */
-        GHash *idx_hash = BLI_ghash_ptr_new("pose channel index by name");
-        int pchan_index = 0;
-        for (pchan = armOb->pose->chanbase.first; pchan != NULL;
-             pchan = pchan->next, ++pchan_index) {
-          BLI_ghash_insert(idx_hash, pchan, POINTER_FROM_INT(pchan_index));
-        }
         for (i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) {
           defnrToPC[i] = BKE_pose_channel_find_name(armOb->pose, dg->name);
           /* exclude non-deforming bones */
@@ -1360,12 +1299,8 @@ void armature_deform_verts(Object *armOb,
             if (defnrToPC[i]->bone->flag & BONE_NO_DEFORM) {
               defnrToPC[i] = NULL;
             }
-            else {
-              defnrToPCIndex[i] = POINTER_AS_INT(BLI_ghash_lookup(idx_hash, defnrToPC[i]));
-            }
           }
         }
-        BLI_ghash_free(idx_hash, NULL, NULL);
       }
     }
   }
@@ -1440,7 +1375,6 @@ void armature_deform_verts(Object *armOb,
         if (index >= 0 && index < defbase_tot && (pchan = defnrToPC[index])) {
           float weight = dw->weight;
           Bone *bone = pchan->bone;
-          pdef_info = pdef_info_array + defnrToPCIndex[index];
 
           deformed = 1;
 
@@ -1457,7 +1391,7 @@ void armature_deform_verts(Object *armOb,
             acum_weight += weight;
           }
 
-          pchan_bone_deform(pchan, pdef_info, weight, vec, dq, smat, co, &contrib);
+          pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib);
 
           /* if acumulated weight limit exceed, exit loop */
           if ((target->type == OB_GPENCIL) && (acum_weight >= 1.0f)) {
@@ -1468,18 +1402,16 @@ void armature_deform_verts(Object *armOb,
       /* if there are vertexgroups but not groups with bones
        * (like for softbody groups) */
       if (deformed == 0 && use_envelope) {
-        pdef_info = pdef_info_array;
-        for (pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next, pdef_info++) {
+        for (pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
           if (!(pchan->bone->flag & BONE_NO_DEFORM))
-            contrib += dist_bone_deform(pchan, pdef_info, vec, dq, smat, co);
+            contrib += dist_bone_deform(pchan, vec, dq, smat, co);
         }
       }
     }
     else if (use_envelope) {
-      pdef_info = pdef_info_array;
-      for (pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next, pdef_info++) {
+      for (pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
         if (!(pchan->bone->flag & BONE_NO_DEFORM))
-          contrib += dist_bone_deform(pchan, pdef_info, vec, dq, smat, co);
+          contrib += dist_bone_deform(pchan, vec, dq, smat, co);
       }
     }
 
@@ -1533,8 +1465,6 @@ void armature_deform_verts(Object *armOb,
 
   if (defnrToPC)
     MEM_freeN(defnrToPC);
-  if (defnrToPCIndex)
-    MEM_freeN(defnrToPCIndex);
 }
 
 /* ************ END Armature Deform ******************* */
@@ -2724,70 +2654,3 @@ bPoseChannel *BKE_armature_splineik_solver_find_root(bPoseChannel *pchan,
   }
   return rootchan;
 }
-
-/* ****************************** BBone cache  ****************************** */
-
-ObjectBBoneDeform *BKE_armature_cached_bbone_deformation_get(Object *object)
-{
-  return object->runtime.cached_bbone_deformation;
-}
-
-void BKE_armature_cached_bbone_deformation_free_data(Object *object)
-{
-  ObjectBBoneDeform *bbone_deform = BKE_armature_cached_bbone_deformation_get(object);
-  if (bbone_deform == NULL) {
-    return;
-  }
-  /* Free arrays. */
-  MEM_SAFE_FREE(bbone_deform->pdef_info_array);
-  MEM_SAFE_FREE(bbone_deform->dualquats);
-  /* Tag that we've got no data, so we are safe for sequential calls to
-   * data free. */
-  bbone_deform->num_pchan = 0;
-}
-
-void BKE_armature_cached_bbone_deformation_free(Object *object)
-{
-  ObjectBBoneDeform *bbone_deform = BKE_armature_cached_bbone_deformation_get(object);
-  if (bbone_deform == NULL) {
-    return;
-  }
-  BKE_armature_cached_bbone_deformation_free_data(object);
-  MEM_freeN(bbone_deform);
-  object->runtime.cached_bbone_deformation = NULL;
-}
-
-void BKE_armature_cached_bbone_deformation_update(Object *object)
-{
-  BLI_assert(object->type == OB_ARMATURE);
-  BLI_assert(object->pose != NULL);
-  bPose *pose = object->pose;
-  const int totchan = BLI_listbase_count(&pose->chanbase);
-  const bool use_quaternion = true;
-  /* Make sure cache exists. */
-  ObjectBBoneDeform *bbone_deform = BKE_armature_cached_bbone_deformation_get(object);
-  if (bbone_deform == NULL) {
-    bbone_deform = MEM_callocN(sizeof(*bbone_deform), "bbone deform cache");
-    object->runtime.cached_bbone_deformation = bbone_deform;
-  }
-  /* Make sure arrays are allocateds at the proper size. */
-  BKE_armature_cached_bbone_deformation_free_data(object);
-  DualQuat *dualquats = NULL;
-  if (use_quaternion) {
-    dualquats = MEM_calloc_arrayN(sizeof(DualQuat), totchan, "dualquats");
-  }
-  bPoseChanDeform *pdef_info_array = MEM_calloc_arrayN(
-      sizeof(bPoseChanDeform), totchan, "bPoseChanDeform");
-  /* Calculate deofrmation matricies. */
-  ArmatureBBoneDefmatsData data = {
-      .pdef_info_array = pdef_info_array,
-      .dualquats = dualquats,
-      .use_quaternion = use_quaternion,
-  };
-  BLI_task_parallel_listbase(&pose->chanbase, &data, armature_bbone_defmats_cb, totchan > 1024);
-  /* Store pointers. */
-  bbone_deform->dualquats = dualquats;
-  atomic_cas_ptr(
-      (void **)&bbone_deform->pdef_info_array, bbone_deform->pdef_info_array, pdef_info_array);
-  bbone_deform->num_pchan = totchan;
-}
index bf33b1c..0f1ebc7 100644 (file)
@@ -618,8 +618,6 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph, Scene *UNUSED(scene), Objec
   }
 
   BLI_assert(pose->chan_array != NULL || BLI_listbase_is_empty(&pose->chanbase));
-
-  BKE_armature_cached_bbone_deformation_free_data(object);
 }
 
 void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, Scene *scene, Object *object)
@@ -714,6 +712,9 @@ void BKE_pose_bone_done(struct Depsgraph *depsgraph, struct Object *object, int
   if (pchan->bone) {
     invert_m4_m4(imat, pchan->bone->arm_mat);
     mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat);
+    if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
+      mat4_to_dquat(&pchan->runtime.deform_dual_quat, pchan->bone->arm_mat, pchan->chan_mat);
+    }
   }
   if (DEG_is_active(depsgraph) && armature->edbo == NULL) {
     bPoseChannel *pchan_orig = pchan->orig_pchan;
@@ -798,7 +799,6 @@ static void pose_eval_done_common(struct Depsgraph *depsgraph, Object *object)
   bPose *pose = object->pose;
   UNUSED_VARS_NDEBUG(pose);
   BLI_assert(pose != NULL);
-  BKE_armature_cached_bbone_deformation_update(object);
   BKE_object_eval_boundbox(depsgraph, object);
 }
 static void pose_eval_cleanup_common(Object *object)
@@ -838,8 +838,6 @@ void BKE_pose_eval_proxy_init(struct Depsgraph *depsgraph, Object *object)
   DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
 
   BLI_assert(object->pose->chan_array != NULL || BLI_listbase_is_empty(&object->pose->chanbase));
-
-  BKE_armature_cached_bbone_deformation_free_data(object);
 }
 
 void BKE_pose_eval_proxy_done(struct Depsgraph *depsgraph, Object *object)
@@ -877,5 +875,6 @@ void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph, Object *object,
   BLI_assert(pchan != NULL);
   BLI_assert(pchan_from != NULL);
   BKE_pose_copyesult_pchan_result(pchan, pchan_from);
+  copy_dq_dq(&pchan->runtime.deform_dual_quat, &pchan_from->runtime.deform_dual_quat);
   BKE_pchan_bbone_segments_cache_copy(pchan, pchan_from);
 }
index 303d63d..77086d9 100644 (file)
@@ -444,7 +444,6 @@ void BKE_object_free_derived_caches(Object *ob)
 
   object_update_from_subsurf_ccg(ob);
   BKE_object_free_derived_mesh_caches(ob);
-  BKE_armature_cached_bbone_deformation_free(ob);
 
   if (ob->runtime.mesh_eval != NULL) {
     Mesh *mesh_eval = ob->runtime.mesh_eval;
@@ -3886,7 +3885,6 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
   runtime->mesh_deform_eval = NULL;
   runtime->curve_cache = NULL;
   runtime->gpencil_cache = NULL;
-  runtime->cached_bbone_deformation = NULL;
 }
 
 /*
index cde3f28..7a4ac14 100644 (file)
@@ -27,6 +27,8 @@
  * \ingroup bli
  */
 
+#include "DNA_vec_types.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -215,14 +217,6 @@ void rotate_eulO(float eul[3], const short order, char axis, float angle);
 
 /******************************* Dual Quaternions ****************************/
 
-typedef struct DualQuat {
-  float quat[4];
-  float trans[4];
-
-  float scale[4][4];
-  float scale_weight;
-} DualQuat;
-
 void copy_dq_dq(DualQuat *r, const DualQuat *dq);
 void normalize_dq(DualQuat *dq, float totw);
 void add_weighted_dq_dq(DualQuat *r, const DualQuat *dq, float weight);
index fd3409b..01f1dc4 100644 (file)
@@ -31,6 +31,7 @@
 #include "DNA_listBase.h"
 #include "DNA_ID.h"
 #include "DNA_view2d_types.h"
+#include "DNA_vec_types.h"
 #include "DNA_userdef_types.h" /* ThemeWireColor */
 
 struct Collection;
@@ -183,8 +184,11 @@ struct DualQuat;
 struct Mat4;
 
 typedef struct bPoseChannel_Runtime {
+  /* Cached dual quaternion for deformation. */
+  struct DualQuat deform_dual_quat;
+
+  /* B-Bone shape data: copy of the segment count for validation. */
   int bbone_segments;
-  char _pad[4];
 
   /* Rest and posed matrices for segments. */
   struct Mat4 *bbone_rest_mats;
index dc23a6a..781a221 100644 (file)
@@ -118,11 +118,6 @@ typedef struct LodLevel {
   int obhysteresis;
 } LodLevel;
 
-/* Forward declaration for cache bbone deformation information.
- *
- * TODO(sergey): Consider moving it to more appropriate place. */
-struct ObjectBBoneDeform;
-
 struct CustomData_MeshMasks;
 
 /* Not saved in file! */
@@ -166,10 +161,6 @@ typedef struct Object_Runtime {
 
   /** Runtime grease pencil drawing data */
   struct GpencilBatchCache *gpencil_cache;
-
-  struct ObjectBBoneDeform *cached_bbone_deformation;
-
-  void *_pad1;
 } Object_Runtime;
 
 typedef struct Object {
index 06e6d88..72a6056 100644 (file)
@@ -83,4 +83,13 @@ typedef struct rctf {
   float ymin, ymax;
 } rctf;
 
+/** dual quaternion. */
+typedef struct DualQuat {
+  float quat[4];
+  float trans[4];
+
+  float scale[4][4];
+  float scale_weight;
+} DualQuat;
+
 #endif