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