Blender V2.61 - r43446

MOD_hook.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software  Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Daniel Dunbar
00022  *                 Ton Roosendaal,
00023  *                 Ben Batt,
00024  *                 Brecht Van Lommel,
00025  *                 Campbell Barton
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  *
00029  */
00030 
00036 #include "DNA_mesh_types.h"
00037 #include "DNA_meshdata_types.h"
00038 #include "DNA_object_types.h"
00039 
00040 #include "BLI_math.h"
00041 #include "BLI_utildefines.h"
00042 #include "BLI_string.h"
00043 
00044 #include "BKE_action.h"
00045 #include "BKE_cdderivedmesh.h"
00046 #include "BKE_modifier.h"
00047 #include "BKE_deform.h"
00048 
00049 
00050 #include "depsgraph_private.h"
00051 #include "MEM_guardedalloc.h"
00052 
00053 #include "MOD_util.h"
00054 
00055 static void initData(ModifierData *md) 
00056 {
00057     HookModifierData *hmd = (HookModifierData*) md;
00058 
00059     hmd->force= 1.0;
00060 }
00061 
00062 static void copyData(ModifierData *md, ModifierData *target)
00063 {
00064     HookModifierData *hmd = (HookModifierData*) md;
00065     HookModifierData *thmd = (HookModifierData*) target;
00066 
00067     copy_v3_v3(thmd->cent, hmd->cent);
00068     thmd->falloff = hmd->falloff;
00069     thmd->force = hmd->force;
00070     thmd->object = hmd->object;
00071     thmd->totindex = hmd->totindex;
00072     thmd->indexar = MEM_dupallocN(hmd->indexar);
00073     memcpy(thmd->parentinv, hmd->parentinv, sizeof(hmd->parentinv));
00074     BLI_strncpy(thmd->name, hmd->name, sizeof(thmd->name));
00075     BLI_strncpy(thmd->subtarget, hmd->subtarget, sizeof(thmd->subtarget));
00076 }
00077 
00078 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
00079 {
00080     HookModifierData *hmd = (HookModifierData *)md;
00081     CustomDataMask dataMask = 0;
00082 
00083     /* ask for vertexgroups if we need them */
00084     if(hmd->name[0]) dataMask |= CD_MASK_MDEFORMVERT;
00085     if(hmd->indexar) dataMask |= CD_MASK_ORIGINDEX;
00086 
00087     return dataMask;
00088 }
00089 
00090 static void freeData(ModifierData *md)
00091 {
00092     HookModifierData *hmd = (HookModifierData*) md;
00093 
00094     if (hmd->indexar) MEM_freeN(hmd->indexar);
00095 }
00096 
00097 static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
00098 {
00099     HookModifierData *hmd = (HookModifierData*) md;
00100 
00101     return !hmd->object;
00102 }
00103 
00104 static void foreachObjectLink(
00105                        ModifierData *md, Object *ob,
00106     void (*walk)(void *userData, Object *ob, Object **obpoin),
00107            void *userData)
00108 {
00109     HookModifierData *hmd = (HookModifierData*) md;
00110 
00111     walk(userData, ob, &hmd->object);
00112 }
00113 
00114 static void updateDepgraph(ModifierData *md, DagForest *forest,
00115                         struct Scene *UNUSED(scene),
00116                         Object *UNUSED(ob),
00117                         DagNode *obNode)
00118 {
00119     HookModifierData *hmd = (HookModifierData*) md;
00120 
00121     if (hmd->object) {
00122         DagNode *curNode = dag_get_node(forest, hmd->object);
00123         
00124         if (hmd->subtarget[0])
00125             dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA|DAG_RL_DATA_DATA, "Hook Modifier");
00126         else
00127             dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "Hook Modifier");
00128     }
00129 }
00130 
00131 static float hook_falloff(float *co_1, float *co_2, const float falloff_squared, float fac)
00132 {
00133     if(falloff_squared) {
00134         float len_squared = len_squared_v3v3(co_1, co_2);
00135         if(len_squared > falloff_squared) {
00136             return 0.0f;
00137         }
00138         else if(len_squared > 0.0f) {
00139             return fac * (1.0f - (len_squared / falloff_squared));
00140         }
00141     }
00142 
00143     return fac;
00144 }
00145 
00146 static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
00147                            float (*vertexCos)[3], int numVerts)
00148 {
00149     bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget);
00150     float vec[3], mat[4][4], dmat[4][4];
00151     int i, *index_pt;
00152     const float falloff_squared= hmd->falloff * hmd->falloff; /* for faster comparisons */
00153     
00154     MDeformVert *dvert;
00155     int defgrp_index, max_dvert;
00156     
00157     /* get world-space matrix of target, corrected for the space the verts are in */
00158     if (hmd->subtarget[0] && pchan) {
00159         /* bone target if there's a matching pose-channel */
00160         mult_m4_m4m4(dmat, hmd->object->obmat, pchan->pose_mat);
00161     }
00162     else {
00163         /* just object target */
00164         copy_m4_m4(dmat, hmd->object->obmat);
00165     }
00166     invert_m4_m4(ob->imat, ob->obmat);
00167     mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv,
00168                  NULL, NULL, NULL, NULL, NULL);
00169 
00170     modifier_get_vgroup(ob, dm, hmd->name, &dvert, &defgrp_index);
00171     max_dvert = (dvert)? numVerts: 0;
00172 
00173     /* Regarding index range checking below.
00174      *
00175      * This should always be true and I don't generally like 
00176      * "paranoid" style code like this, but old files can have
00177      * indices that are out of range because old blender did
00178      * not correct them on exit editmode. - zr
00179      */
00180     
00181     if(hmd->force == 0.0f) {
00182         /* do nothing, avoid annoying checks in the loop */
00183     }
00184     else if(hmd->indexar) { /* vertex indices? */
00185         const float fac_orig= hmd->force;
00186         float fac;
00187         const int *origindex_ar;
00188         
00189         /* if DerivedMesh is present and has original index data, use it */
00190         if(dm && (origindex_ar= dm->getVertDataArray(dm, CD_ORIGINDEX))) {
00191             for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) {
00192                 if(*index_pt < numVerts) {
00193                     int j;
00194                     
00195                     for(j = 0; j < numVerts; j++) {
00196                         if(origindex_ar[j] == *index_pt) {
00197                             float *co = vertexCos[j];
00198                             if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
00199                                 if(dvert)
00200                                     fac *= defvert_find_weight(dvert+j, defgrp_index);
00201                                 
00202                                 if(fac) {
00203                                     mul_v3_m4v3(vec, mat, co);
00204                                     interp_v3_v3v3(co, co, vec, fac);
00205                                 }
00206                             }
00207                         }
00208                     }
00209                 }
00210             }
00211         }
00212         else { /* missing dm or ORIGINDEX */
00213             for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) {
00214                 if(*index_pt < numVerts) {
00215                     float *co = vertexCos[*index_pt];
00216                     if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
00217                         if(dvert)
00218                             fac *= defvert_find_weight(dvert+(*index_pt), defgrp_index);
00219                         
00220                         if(fac) {
00221                             mul_v3_m4v3(vec, mat, co);
00222                             interp_v3_v3v3(co, co, vec, fac);
00223                         }
00224                     }
00225                 }
00226             }
00227         }
00228     }
00229     else if(dvert) {    /* vertex group hook */
00230         const float fac_orig= hmd->force;
00231         
00232         for(i = 0; i < max_dvert; i++, dvert++) {
00233             float fac;
00234             float *co = vertexCos[i];
00235             
00236             if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
00237                 fac *= defvert_find_weight(dvert, defgrp_index);
00238                 if(fac) {
00239                     mul_v3_m4v3(vec, mat, co);
00240                     interp_v3_v3v3(co, co, vec, fac);
00241                 }
00242             }
00243         }
00244     }
00245 }
00246 
00247 static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
00248                         float (*vertexCos)[3], int numVerts,
00249                         int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
00250 {
00251     HookModifierData *hmd = (HookModifierData*) md;
00252     DerivedMesh *dm = derivedData;
00253     /* We need a valid dm for meshes when a vgroup is set... */
00254     if(!dm && ob->type == OB_MESH && hmd->name[0] != '\0')
00255         dm = get_dm(ob, NULL, dm, NULL, 0);
00256 
00257     deformVerts_do(hmd, ob, dm, vertexCos, numVerts);
00258 
00259     if(derivedData != dm)
00260         dm->release(dm);
00261 }
00262 
00263 static void deformVertsEM(ModifierData *md, Object *ob, struct EditMesh *editData,
00264                           DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
00265 {
00266     HookModifierData *hmd = (HookModifierData*) md;
00267     DerivedMesh *dm = derivedData;
00268     /* We need a valid dm for meshes when a vgroup is set... */
00269     if(!dm && ob->type == OB_MESH && hmd->name[0] != '\0')
00270         dm = get_dm(ob, editData, dm, NULL, 0);
00271 
00272     deformVerts_do(hmd, ob, dm, vertexCos, numVerts);
00273 
00274     if(derivedData != dm)
00275         dm->release(dm);
00276 }
00277 
00278 
00279 ModifierTypeInfo modifierType_Hook = {
00280     /* name */              "Hook",
00281     /* structName */        "HookModifierData",
00282     /* structSize */        sizeof(HookModifierData),
00283     /* type */              eModifierTypeType_OnlyDeform,
00284     /* flags */             eModifierTypeFlag_AcceptsCVs
00285                             | eModifierTypeFlag_SupportsEditmode,
00286     /* copyData */          copyData,
00287     /* deformVerts */       deformVerts,
00288     /* deformMatrices */    NULL,
00289     /* deformVertsEM */     deformVertsEM,
00290     /* deformMatricesEM */  NULL,
00291     /* applyModifier */     NULL,
00292     /* applyModifierEM */   NULL,
00293     /* initData */          initData,
00294     /* requiredDataMask */  requiredDataMask,
00295     /* freeData */          freeData,
00296     /* isDisabled */        isDisabled,
00297     /* updateDepgraph */    updateDepgraph,
00298     /* dependsOnTime */     NULL,
00299     /* dependsOnNormals */  NULL,
00300     /* foreachObjectLink */ foreachObjectLink,
00301     /* foreachIDLink */     NULL,
00302     /* foreachTexLink */    NULL,
00303 };