[Bf-blender-cvs] [df8e5d66e3f] master: Modifiers: support parallelism in Armature and Lattice Deform.

Alexander Gavrilov noreply at git.blender.org
Wed May 1 15:36:34 CEST 2019


Commit: df8e5d66e3f7678af70f5c007bc2b4884978b341
Author: Alexander Gavrilov
Date:   Sun Apr 28 15:05:13 2019 +0300
Branches: master
https://developer.blender.org/rBdf8e5d66e3f7678af70f5c007bc2b4884978b341

Modifiers: support parallelism in Armature and Lattice Deform.

This partially mitigates the performance drop in Spring
02_055_A.anim caused by dependency changes in D4715.

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

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

M	source/blender/blenkernel/intern/armature.c
M	source/blender/blenkernel/intern/lattice.c

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

diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 9645721d29b..60446bf60b6 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1293,6 +1293,211 @@ static void pchan_bone_deform(bPoseChannel *pchan,
   (*contrib) += weight;
 }
 
+typedef struct ArmatureUserdata {
+  Object *armOb;
+  Object *target;
+  const Mesh *mesh;
+  float (*vertexCos)[3];
+  float (*defMats)[3][3];
+  float (*prevCos)[3];
+
+  bool use_envelope;
+  bool use_quaternion;
+  bool invert_vgroup;
+  bool use_dverts;
+
+  int armature_def_nr;
+
+  int target_totvert;
+  MDeformVert *dverts;
+
+  int defbase_tot;
+  bPoseChannel **defnrToPC;
+
+  float premat[4][4];
+  float postmat[4][4];
+} ArmatureUserdata;
+
+static void armature_vert_task(void *__restrict userdata,
+                               const int i,
+                               const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+  const ArmatureUserdata *data = userdata;
+  float(*const vertexCos)[3] = data->vertexCos;
+  float(*const defMats)[3][3] = data->defMats;
+  float(*const prevCos)[3] = data->prevCos;
+  const bool use_envelope = data->use_envelope;
+  const bool use_quaternion = data->use_quaternion;
+  const bool use_dverts = data->use_dverts;
+  const int armature_def_nr = data->armature_def_nr;
+
+  MDeformVert *dvert;
+  DualQuat sumdq, *dq = NULL;
+  bPoseChannel *pchan;
+  float *co, dco[3];
+  float sumvec[3], summat[3][3];
+  float *vec = NULL, (*smat)[3] = NULL;
+  float contrib = 0.0f;
+  float armature_weight = 1.0f; /* default to 1 if no overall def group */
+  float prevco_weight = 1.0f;   /* weight for optional cached vertexcos */
+
+  if (use_quaternion) {
+    memset(&sumdq, 0, sizeof(DualQuat));
+    dq = &sumdq;
+  }
+  else {
+    sumvec[0] = sumvec[1] = sumvec[2] = 0.0f;
+    vec = sumvec;
+
+    if (defMats) {
+      zero_m3(summat);
+      smat = summat;
+    }
+  }
+
+  if (use_dverts || armature_def_nr != -1) {
+    if (data->mesh) {
+      BLI_assert(i < data->mesh->totvert);
+      dvert = data->mesh->dvert + i;
+    }
+    else if (data->dverts && i < data->target_totvert) {
+      dvert = data->dverts + i;
+    }
+    else {
+      dvert = NULL;
+    }
+  }
+  else {
+    dvert = NULL;
+  }
+
+  if (armature_def_nr != -1 && dvert) {
+    armature_weight = defvert_find_weight(dvert, armature_def_nr);
+
+    if (data->invert_vgroup) {
+      armature_weight = 1.0f - armature_weight;
+    }
+
+    /* hackish: the blending factor can be used for blending with prevCos too */
+    if (prevCos) {
+      prevco_weight = armature_weight;
+      armature_weight = 1.0f;
+    }
+  }
+
+  /* check if there's any  point in calculating for this vert */
+  if (armature_weight == 0.0f) {
+    return;
+  }
+
+  /* get the coord we work on */
+  co = prevCos ? prevCos[i] : vertexCos[i];
+
+  /* Apply the object's matrix */
+  mul_m4_v3(data->premat, co);
+
+  if (use_dverts && dvert && dvert->totweight) { /* use weight groups ? */
+    MDeformWeight *dw = dvert->dw;
+    int deformed = 0;
+    unsigned int j;
+    float acum_weight = 0;
+    for (j = dvert->totweight; j != 0; j--, dw++) {
+      const int index = dw->def_nr;
+      if (index >= 0 && index < data->defbase_tot && (pchan = data->defnrToPC[index])) {
+        float weight = dw->weight;
+        Bone *bone = pchan->bone;
+
+        deformed = 1;
+
+        if (bone && bone->flag & BONE_MULT_VG_ENV) {
+          weight *= distfactor_to_bone(
+              co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
+        }
+
+        /* check limit of weight */
+        if (data->target->type == OB_GPENCIL) {
+          if (acum_weight + weight >= 1.0f) {
+            weight = 1.0f - acum_weight;
+          }
+          acum_weight += weight;
+        }
+
+        pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib);
+
+        /* if acumulated weight limit exceed, exit loop */
+        if ((data->target->type == OB_GPENCIL) && (acum_weight >= 1.0f)) {
+          break;
+        }
+      }
+    }
+    /* if there are vertexgroups but not groups with bones
+     * (like for softbody groups) */
+    if (deformed == 0 && use_envelope) {
+      for (pchan = data->armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
+        if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
+          contrib += dist_bone_deform(pchan, vec, dq, smat, co);
+        }
+      }
+    }
+  }
+  else if (use_envelope) {
+    for (pchan = data->armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
+      if (!(pchan->bone->flag & BONE_NO_DEFORM)) {
+        contrib += dist_bone_deform(pchan, vec, dq, smat, co);
+      }
+    }
+  }
+
+  /* actually should be EPSILON? weight values and contrib can be like 10e-39 small */
+  if (contrib > 0.0001f) {
+    if (use_quaternion) {
+      normalize_dq(dq, contrib);
+
+      if (armature_weight != 1.0f) {
+        copy_v3_v3(dco, co);
+        mul_v3m3_dq(dco, (defMats) ? summat : NULL, dq);
+        sub_v3_v3(dco, co);
+        mul_v3_fl(dco, armature_weight);
+        add_v3_v3(co, dco);
+      }
+      else {
+        mul_v3m3_dq(co, (defMats) ? summat : NULL, dq);
+      }
+
+      smat = summat;
+    }
+    else {
+      mul_v3_fl(vec, armature_weight / contrib);
+      add_v3_v3v3(co, vec, co);
+    }
+
+    if (defMats) {
+      float pre[3][3], post[3][3], tmpmat[3][3];
+
+      copy_m3_m4(pre, data->premat);
+      copy_m3_m4(post, data->postmat);
+      copy_m3_m3(tmpmat, defMats[i]);
+
+      if (!use_quaternion) { /* quaternion already is scale corrected */
+        mul_m3_fl(smat, armature_weight / contrib);
+      }
+
+      mul_m3_series(defMats[i], post, smat, pre, tmpmat);
+    }
+  }
+
+  /* always, check above code */
+  mul_m4_v3(data->postmat, co);
+
+  /* interpolate with previous modifier position using weight group */
+  if (prevCos) {
+    float mw = 1.0f - prevco_weight;
+    vertexCos[i][0] = prevco_weight * vertexCos[i][0] + mw * co[0];
+    vertexCos[i][1] = prevco_weight * vertexCos[i][1] + mw * co[1];
+    vertexCos[i][2] = prevco_weight * vertexCos[i][2] + mw * co[2];
+  }
+}
+
 void armature_deform_verts(Object *armOb,
                            Object *target,
                            const Mesh *mesh,
@@ -1305,10 +1510,9 @@ void armature_deform_verts(Object *armOb,
                            bGPDstroke *gps)
 {
   bArmature *arm = armOb->data;
-  bPoseChannel *pchan, **defnrToPC = NULL;
+  bPoseChannel **defnrToPC = NULL;
   MDeformVert *dverts = NULL;
   bDeformGroup *dg;
-  float obinv[4][4], premat[4][4], postmat[4][4];
   const bool use_envelope = (deformflag & ARM_DEF_ENVELOPE) != 0;
   const bool use_quaternion = (deformflag & ARM_DEF_QUATERNION) != 0;
   const bool invert_vgroup = (deformflag & ARM_DEF_INVERT_VGROUP) != 0;
@@ -1329,11 +1533,6 @@ void armature_deform_verts(Object *armOb,
     BLI_assert(0);
   }
 
-  invert_m4_m4(obinv, target->obmat);
-  copy_m4_m4(premat, target->obmat);
-  mul_m4_m4m4(postmat, obinv, armOb->obmat);
-  invert_m4_m4(premat, postmat);
-
   /* get the def_nr for the overall armature vertex group if present */
   armature_def_nr = defgroup_name_index(target, defgrp_name);
 
@@ -1392,172 +1591,32 @@ void armature_deform_verts(Object *armOb,
     }
   }
 
-  for (i = 0; i < numVerts; i++) {
-    MDeformVert *dvert;
-    DualQuat sumdq, *dq = NULL;
-    float *co, dco[3];
-    float sumvec[3], summat[3][3];
-    float *vec = NULL, (*smat)[3] = NULL;
-    float contrib = 0.0f;
-    float armature_weight = 1.0f; /* default to 1 if no overall def group */
-    float prevco_weight = 1.0f;   /* weight for optional cached vertexcos */
-
-    if (use_quaternion) {
-      memset(&sumdq, 0, sizeof(DualQuat));
-      dq = &sumdq;
-    }
-    else {
-      sumvec[0] = sumvec[1] = sumvec[2] = 0.0f;
-      vec = sumvec;
-
-      if (defMats) {
-        zero_m3(summat);
-        smat = summat;
-      }
-    }
-
-    if (use_dverts || armature_def_nr != -1) {
-      if (mesh) {
-        BLI_assert(i < mesh->totvert);
-        dvert = mesh->dvert + i;
-      }
-      else if (dverts && i < target_totvert) {
-        dvert = dverts + i;
-      }
-      else {
-        dvert = NULL;
-      }
-    }
-    else {
-      dvert = NULL;
-    }
-
-    if (armature_def_nr != -1 && dvert) {
-      armature_weight = defvert_find_weight(dvert, armature_def_nr);
-
-      if (invert_vgroup) {
-        armature_weight = 1.0f - armature_weight;
-      }
-
-      /* hackish: the blending factor can be used for blending with prevCos too */
-      if (prevCos) {
-        prevco_weight = armature_weight;
-        armature_weight = 1.0f;
-      }
-    }
-
-    /* check if there's any  point in calculating for this vert */
-    if (armature_weight == 0.0f) {
-      continue;
-    }
-
-    /* get the coord we work on */
-    co = prevCos ? prevCos[i] : vertexCos[i];
-
-    /* Apply the object's matrix */
-    mul_m4_v3(premat, co);
-
-    if (use_dverts && dvert && dvert->totweight) { /* use weight groups ? */
-      MDeformWeight *dw = dvert->dw;
-      int deformed = 0;
-      unsigned int j;
-      float acum_weight = 0;
-      for (j = dvert->totweight; j != 0; j--, dw++) {
-        const int index = dw->def_nr;
-        if (index >= 0 && index < defbase_tot && (pchan = defnrToPC[index])) {
-          float weight = dw->weight;
-          Bone *bone = pchan->bone;
-
-          deformed = 1;
-
-          if (bone && bone->flag & BONE_MULT_VG_ENV) {
-            weight *= distfactor_to_bone(
-                co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
-          }
-
-          /* check limit of weight */
-          if (target->type == OB_GPENCIL) {
-            if (acum_weight + weight >= 1.0f) {
-              weight = 1.0f - acum_weight;
-            }
-            acum_weight += weight;
-          }
-
-          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)) {
-            break;
-          }
-        }
-      }
-      /* if there are vertexg

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list