Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gavrilov <angavrilov@gmail.com>2019-04-28 15:05:13 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2019-05-01 16:34:54 +0300
commitdf8e5d66e3f7678af70f5c007bc2b4884978b341 (patch)
treefd4136e34051b138f0b870d8b01e231d6f12ee95
parent4d043b5c17fbdf9c68600f15745f687d6d6b57ef (diff)
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
-rw-r--r--source/blender/blenkernel/intern/armature.c401
-rw-r--r--source/blender/blenkernel/intern/lattice.c53
2 files changed, 268 insertions, 186 deletions
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 vertexgroups but not groups with bones
- * (like for softbody groups) */
- if (deformed == 0 && use_envelope) {
- for (pchan = 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 = 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, premat);
- copy_m3_m4(post, 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);
- }
- }
+ ArmatureUserdata data = {.armOb = armOb,
+ .target = target,
+ .mesh = mesh,
+ .vertexCos = vertexCos,
+ .defMats = defMats,
+ .prevCos = prevCos,
+ .use_envelope = use_envelope,
+ .use_quaternion = use_quaternion,
+ .invert_vgroup = invert_vgroup,
+ .use_dverts = use_dverts,
+ .armature_def_nr = armature_def_nr,
+ .target_totvert = target_totvert,
+ .dverts = dverts,
+ .defbase_tot = defbase_tot,
+ .defnrToPC = defnrToPC};
+
+ float obinv[4][4];
+ invert_m4_m4(obinv, target->obmat);
- /* always, check above code */
- mul_m4_v3(postmat, co);
+ mul_m4_m4m4(data.postmat, obinv, armOb->obmat);
+ invert_m4_m4(data.premat, data.postmat);
- /* 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];
- }
- }
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 32;
+ BLI_task_parallel_range(0, numVerts, &data, armature_vert_task, &settings);
if (defnrToPC) {
MEM_freeN(defnrToPC);
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index c9a0cf50e65..b8178bec52f 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -32,6 +32,7 @@
#include "BLI_listbase.h"
#include "BLI_bitmap.h"
#include "BLI_math.h"
+#include "BLI_task.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -878,6 +879,31 @@ void curve_deform_vector(
mul_m4_v3(cd.objectspace, vec);
}
+typedef struct LatticeDeformUserdata {
+ LatticeDeformData *lattice_deform_data;
+ float (*vertexCos)[3];
+ MDeformVert *dvert;
+ int defgrp_index;
+ float fac;
+} LatticeDeformUserdata;
+
+static void lattice_deform_vert_task(void *__restrict userdata,
+ const int index,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ const LatticeDeformUserdata *data = userdata;
+
+ if (data->dvert != NULL) {
+ const float weight = defvert_find_weight(data->dvert + index, data->defgrp_index);
+ if (weight > 0.0f) {
+ calc_latt_deform(data->lattice_deform_data, data->vertexCos[index], weight * data->fac);
+ }
+ }
+ else {
+ calc_latt_deform(data->lattice_deform_data, data->vertexCos[index], data->fac);
+ }
+}
+
void lattice_deform_verts(Object *laOb,
Object *target,
Mesh *mesh,
@@ -889,7 +915,6 @@ void lattice_deform_verts(Object *laOb,
LatticeDeformData *lattice_deform_data;
MDeformVert *dvert = NULL;
int defgrp_index = -1;
- int a;
if (laOb->type != OB_LATTICE) {
return;
@@ -916,20 +941,18 @@ void lattice_deform_verts(Object *laOb,
}
}
}
- if (dvert) {
- MDeformVert *dvert_iter;
- for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
- const float weight = defvert_find_weight(dvert_iter, defgrp_index);
- if (weight > 0.0f) {
- calc_latt_deform(lattice_deform_data, vertexCos[a], weight * fac);
- }
- }
- }
- else {
- for (a = 0; a < numVerts; a++) {
- calc_latt_deform(lattice_deform_data, vertexCos[a], fac);
- }
- }
+
+ LatticeDeformUserdata data = {.lattice_deform_data = lattice_deform_data,
+ .vertexCos = vertexCos,
+ .dvert = dvert,
+ .defgrp_index = defgrp_index,
+ .fac = fac};
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 32;
+ BLI_task_parallel_range(0, numVerts, &data, lattice_deform_vert_task, &settings);
+
end_latt_deform(lattice_deform_data);
}