diff options
Diffstat (limited to 'source/blender/modifiers/intern/MOD_hook.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_hook.c | 196 |
1 files changed, 108 insertions, 88 deletions
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index f2ffd486aa5..c26d3ff0967 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -40,6 +40,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_modifier.h" #include "BKE_deform.h" +#include "BKE_utildefines.h" #include "depsgraph_private.h" #include "MEM_guardedalloc.h" @@ -68,13 +69,14 @@ static void copyData(ModifierData *md, ModifierData *target) strncpy(thmd->subtarget, hmd->subtarget, 32); } -static CustomDataMask requiredDataMask(Object *ob, ModifierData *md) +static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) { HookModifierData *hmd = (HookModifierData *)md; CustomDataMask dataMask = 0; /* ask for vertexgroups if we need them */ - if(!hmd->indexar && hmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT); + if(hmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT); + // if(hmd->indexar) dataMask |= CD_MASK_ORIGINDEX; return dataMask; } @@ -86,7 +88,7 @@ static void freeData(ModifierData *md) if (hmd->indexar) MEM_freeN(hmd->indexar); } -static int isDisabled(ModifierData *md, int useRenderParams) +static int isDisabled(ModifierData *md, int UNUSED(useRenderParams)) { HookModifierData *hmd = (HookModifierData*) md; @@ -103,8 +105,10 @@ static void foreachObjectLink( walk(userData, ob, &hmd->object); } -static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *scene, - Object *ob, DagNode *obNode) +static void updateDepgraph(ModifierData *md, DagForest *forest, + struct Scene *UNUSED(scene), + Object *UNUSED(ob), + DagNode *obNode) { HookModifierData *hmd = (HookModifierData*) md; @@ -118,15 +122,38 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *sc } } -static void deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) +static float hook_falloff(float *co_1, float *co_2, const float falloff_squared, float fac) +{ + if(falloff_squared) { + float len_squared = len_squared_v3v3(co_1, co_2); + if(len_squared > falloff_squared) { + return 0.0f; + } + else if(len_squared > 0.0) { + return fac * (1.0 - (len_squared / falloff_squared)); + } + } + + return fac; +} + +static void deformVerts(ModifierData *md, Object *ob, + DerivedMesh *derivedData, + float (*vertexCos)[3], + int numVerts, + int UNUSED(useRenderParams), + int UNUSED(isFinalCalc)) { HookModifierData *hmd = (HookModifierData*) md; bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget); float vec[3], mat[4][4], dmat[4][4]; - int i; + int i, *index_pt; DerivedMesh *dm = derivedData; + const float falloff_squared= hmd->falloff * hmd->falloff; /* for faster comparisons */ + + int max_dvert= 0; + MDeformVert *dvert= NULL; + int defgrp_index = -1; /* get world-space matrix of target, corrected for the space the verts are in */ if (hmd->subtarget[0] && pchan) { @@ -141,98 +168,91 @@ static void deformVerts( mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv, NULL, NULL, NULL, NULL, NULL); - /* vertex indices? */ - if(hmd->indexar) { - for(i = 0; i < hmd->totindex; i++) { - int index = hmd->indexar[i]; - - /* This should always be true and I don't generally like - * "paranoid" style code like this, but old files can have - * indices that are out of range because old blender did - * not correct them on exit editmode. - zr - */ - if(index < numVerts) { - float *co = vertexCos[index]; - float fac = hmd->force; - - /* if DerivedMesh is present and has original index data, - * use it - */ - if(dm && dm->getVertDataArray(dm, CD_ORIGINDEX)) { + if((defgrp_index= defgroup_name_index(ob, hmd->name)) != -1) { + Mesh *me = ob->data; + if(dm) { + dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT); + if(dvert) { + max_dvert = numVerts; + } + } + else if(me->dvert) { + dvert= me->dvert; + if(dvert) { + max_dvert = me->totvert; + } + } + } + + /* Regarding index range checking below. + * + * This should always be true and I don't generally like + * "paranoid" style code like this, but old files can have + * indices that are out of range because old blender did + * not correct them on exit editmode. - zr + */ + + if(hmd->force == 0.0f) { + /* do nothing, avoid annoying checks in the loop */ + } + else if(hmd->indexar) { /* vertex indices? */ + const float fac_orig= hmd->force; + float fac; + const int *origindex_ar; + + /* if DerivedMesh is present and has original index data, + * use it + */ + if(dm && (origindex_ar= dm->getVertDataArray(dm, CD_ORIGINDEX))) { + for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) { + if(*index_pt < numVerts) { int j; - int orig_index; - for(j = 0; j < numVerts; ++j) { - fac = hmd->force; - orig_index = *(int *)dm->getVertData(dm, j, - CD_ORIGINDEX); - if(orig_index == index) { - co = vertexCos[j]; - if(hmd->falloff != 0.0) { - float len = len_v3v3(co, hmd->cent); - if(len > hmd->falloff) fac = 0.0; - else if(len > 0.0) - fac *= sqrt(1.0 - len / hmd->falloff); - } - if(fac != 0.0) { - mul_v3_m4v3(vec, mat, co); - interp_v3_v3v3(co, co, vec, fac); + for(j = 0; j < numVerts; j++) { + if(origindex_ar[j] == *index_pt) { + float *co = vertexCos[j]; + if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) { + if(dvert) + fac *= defvert_find_weight(dvert+j, defgrp_index); + + if(fac) { + mul_v3_m4v3(vec, mat, co); + interp_v3_v3v3(co, co, vec, fac); + } } } } - } else { - if(hmd->falloff != 0.0) { - float len = len_v3v3(co, hmd->cent); - if(len > hmd->falloff) fac = 0.0; - else if(len > 0.0) - fac *= sqrt(1.0 - len / hmd->falloff); - } - - if(fac != 0.0) { - mul_v3_m4v3(vec, mat, co); - interp_v3_v3v3(co, co, vec, fac); - } } } } - } - else if(hmd->name[0]) { /* vertex group hook */ - Mesh *me = ob->data; - int use_dverts = 0; - int maxVerts = 0; - int defgrp_index = defgroup_name_index(ob, hmd->name); - - if(dm) { - if(dm->getVertData(dm, 0, CD_MDEFORMVERT)) { - maxVerts = dm->getNumVerts(dm); - use_dverts = 1; + else { /* missing dm or ORIGINDEX */ + for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) { + if(*index_pt < numVerts) { + float *co = vertexCos[*index_pt]; + if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) { + if(dvert) + fac *= defvert_find_weight(dvert+(*index_pt), defgrp_index); + + if(fac) { + mul_v3_m4v3(vec, mat, co); + interp_v3_v3v3(co, co, vec, fac); + } + } + } } } - else if(me->dvert) { - maxVerts = me->totvert; - use_dverts = 1; - } + } + else if(dvert) { /* vertex group hook */ + int i; + const float fac_orig= hmd->force; - if(defgrp_index >= 0 && use_dverts) { - MDeformVert *dvert = me->dvert; - int i; + for(i = 0; i < max_dvert; i++, dvert++) { float fac; + float *co = vertexCos[i]; - for(i = 0; i < maxVerts; i++, dvert++) { - if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); - - fac= defvert_find_weight(dvert, defgrp_index); - - if(fac > 0.0f) { - float *co = vertexCos[i]; - - if(hmd->falloff != 0.0) { - float len = len_v3v3(co, hmd->cent); - if(len > hmd->falloff) fac = 0.0; - else if(len > 0.0) - fac *= sqrt(1.0 - len / hmd->falloff); - } - + if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) { + fac *= defvert_find_weight(dvert, defgrp_index); + if(fac) { mul_v3_m4v3(vec, mat, co); interp_v3_v3v3(co, co, vec, fac); } |