diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-10-22 13:56:52 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-10-22 14:20:41 +0400 |
commit | dfc4de036e39f74aa0a3b1e1734a02f4a9530a78 (patch) | |
tree | 2df085daa2c61acada91e542bb86deaed395cb98 /source/blender/modifiers | |
parent | 74f40a5217c9c72447a80881c192de72577e869c (diff) |
Meshdeform modifier: Use threaded evaluation
This commit switches meshdeform modifier to use threads to evaluate
the vertices positions using the central task scheduler.
SO now we've got an utility function to help splitting the for loop
into tasks using BLI_task module which is pretty straightforward to
use: it gets range (which is an integer lower and higher bounds) and
the function and userdata to be invoked for each of the iterations.
The only weak point for now is the passing the data to the callback,
this isn't so trivial to improve in pure C.
Reviewers: campbellbarton
Differential Revision: https://developer.blender.org/D838
Diffstat (limited to 'source/blender/modifiers')
-rw-r--r-- | source/blender/modifiers/intern/MOD_meshdeform.c | 139 |
1 files changed, 88 insertions, 51 deletions
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 959bbdcbca9..bd6ce26103c 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -37,6 +37,7 @@ #include "DNA_scene_types.h" #include "BLI_math.h" +#include "BLI_task.h" #include "BLI_utildefines.h" #include "BLF_translation.h" @@ -181,6 +182,75 @@ static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3 return totweight; } +typedef struct MeshdeformUserdata { + /*const*/ MeshDeformModifierData *mmd; + const MDeformVert *dvert; + /*const*/ float (*dco)[3]; + int defgrp_index; + float (*vertexCos)[3]; + float (*cagemat)[4]; + float (*icagemat)[3]; + SpinLock lock; +} MeshdeformUserdata; + +static void meshdeform_vert_task(void *userdata, int iter) +{ + MeshdeformUserdata *data = userdata; + /*const*/ MeshDeformModifierData *mmd = data->mmd; + const MDeformVert *dvert = data->dvert; + const int defgrp_index = data->defgrp_index; + const int *offsets = mmd->bindoffsets; + const MDefInfluence *influences = influences = mmd->bindinfluences; + /*const*/ float (*dco)[3] = data->dco; + float (*vertexCos)[3] = data->vertexCos; + float co[3]; + float weight, totweight, fac = 1.0f; + + if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) + if (!mmd->dynverts[iter]) + return; + + if (dvert) { + fac = defvert_find_weight(&dvert[iter], defgrp_index); + + if (mmd->flag & MOD_MDEF_INVERT_VGROUP) { + fac = 1.0f - fac; + } + + if (fac <= 0.0f) { + return; + } + } + + if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) { + /* transform coordinate into cage's local space */ + mul_v3_m4v3(co, data->cagemat, vertexCos[iter]); + totweight = meshdeform_dynamic_bind(mmd, dco, co); + } + else { + int a; + totweight = 0.0f; + zero_v3(co); + + for (a = offsets[iter]; a < offsets[iter + 1]; a++) { + weight = influences[a].weight; + madd_v3_v3fl(co, dco[influences[a].vertex], weight); + totweight += weight; + } + } + + if (totweight > 0.0f) { + mul_v3_fl(co, fac / totweight); + mul_m3_v3(data->icagemat, co); + BLI_spin_lock(&data->lock); + if (G.debug_value != 527) + add_v3_v3(vertexCos[iter], co); + else + copy_v3_v3(vertexCos[iter], co); + BLI_spin_unlock(&data->lock); + } +} + static void meshdeformModifier_do( ModifierData *md, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) @@ -188,12 +258,11 @@ static void meshdeformModifier_do( MeshDeformModifierData *mmd = (MeshDeformModifierData *) md; DerivedMesh *tmpdm, *cagedm; MDeformVert *dvert = NULL; - MDefInfluence *influences; - const int *offsets; float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4]; - float weight, totweight, fac, co[3], (*dco)[3], (*bindcagecos)[3]; - int a, b, totvert, totcagevert, defgrp_index; + float co[3], (*dco)[3], (*bindcagecos)[3]; + int a, totvert, totcagevert, defgrp_index; float (*cagecos)[3]; + MeshdeformUserdata data; if (!mmd->object || (!mmd->bindcagecos && !mmd->bindfunc)) return; @@ -273,8 +342,6 @@ static void meshdeformModifier_do( /* setup deformation data */ cagedm->getVertCos(cagedm, cagecos); - influences = mmd->bindinfluences; - offsets = mmd->bindoffsets; bindcagecos = (float(*)[3])mmd->bindcagecos; dco = MEM_callocN(sizeof(*dco) * totcagevert, "MDefDco"); @@ -293,51 +360,21 @@ static void meshdeformModifier_do( modifier_get_vgroup(ob, dm, mmd->defgrp_name, &dvert, &defgrp_index); - /* do deformation */ - fac = 1.0f; - - for (b = 0; b < totvert; b++) { - if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) - if (!mmd->dynverts[b]) - continue; - - if (dvert) { - fac = defvert_find_weight(&dvert[b], defgrp_index); - - if (mmd->flag & MOD_MDEF_INVERT_VGROUP) { - fac = 1.0f - fac; - } - - if (fac <= 0.0f) { - continue; - } - } - - if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) { - /* transform coordinate into cage's local space */ - mul_v3_m4v3(co, cagemat, vertexCos[b]); - totweight = meshdeform_dynamic_bind(mmd, dco, co); - } - else { - totweight = 0.0f; - zero_v3(co); - - for (a = offsets[b]; a < offsets[b + 1]; a++) { - weight = influences[a].weight; - madd_v3_v3fl(co, dco[influences[a].vertex], weight); - totweight += weight; - } - } - - if (totweight > 0.0f) { - mul_v3_fl(co, fac / totweight); - mul_m3_v3(icagemat, co); - if (G.debug_value != 527) - add_v3_v3(vertexCos[b], co); - else - copy_v3_v3(vertexCos[b], co); - } - } + /* Initialize data to be pass to the for body function. */ + data.mmd = mmd; + data.dvert = dvert; + data.dco = dco; + data.defgrp_index = defgrp_index; + data.vertexCos = vertexCos; + data.cagemat = cagemat; + data.icagemat = icagemat; + BLI_spin_init(&data.lock); + + /* Do deformation. */ + BLI_task_parallel_range(0, totvert, &data, meshdeform_vert_task); + + /* Uninitialize user dtaa used by the task system. */ + BLI_spin_end(&data.lock); /* release cage derivedmesh */ MEM_freeN(dco); |