Blender V2.61 - r43446
|
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_meshdata_types.h" 00037 #include "DNA_object_types.h" 00038 00039 #include "BLI_math.h" 00040 #include "BLI_utildefines.h" 00041 00042 00043 #include "BKE_cdderivedmesh.h" 00044 #include "BKE_global.h" 00045 #include "BKE_mesh.h" 00046 #include "BKE_modifier.h" 00047 #include "BKE_deform.h" 00048 00049 #include "depsgraph_private.h" 00050 00051 #include "MEM_guardedalloc.h" 00052 00053 #include "MOD_util.h" 00054 00055 00056 static void initData(ModifierData *md) 00057 { 00058 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; 00059 00060 mmd->gridsize= 5; 00061 } 00062 00063 static void freeData(ModifierData *md) 00064 { 00065 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; 00066 00067 if(mmd->bindinfluences) MEM_freeN(mmd->bindinfluences); 00068 if(mmd->bindoffsets) MEM_freeN(mmd->bindoffsets); 00069 if(mmd->bindcagecos) MEM_freeN(mmd->bindcagecos); 00070 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid); 00071 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences); 00072 if(mmd->dynverts) MEM_freeN(mmd->dynverts); 00073 if(mmd->bindweights) MEM_freeN(mmd->bindweights); /* deprecated */ 00074 if(mmd->bindcos) MEM_freeN(mmd->bindcos); /* deprecated */ 00075 } 00076 00077 static void copyData(ModifierData *md, ModifierData *target) 00078 { 00079 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; 00080 MeshDeformModifierData *tmmd = (MeshDeformModifierData*) target; 00081 00082 tmmd->gridsize = mmd->gridsize; 00083 tmmd->object = mmd->object; 00084 } 00085 00086 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) 00087 { 00088 MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; 00089 CustomDataMask dataMask = 0; 00090 00091 /* ask for vertexgroups if we need them */ 00092 if(mmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT; 00093 00094 return dataMask; 00095 } 00096 00097 static int isDisabled(ModifierData *md, int UNUSED(useRenderParams)) 00098 { 00099 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; 00100 00101 return !mmd->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 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; 00110 00111 walk(userData, ob, &mmd->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 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; 00120 00121 if (mmd->object) { 00122 DagNode *curNode = dag_get_node(forest, mmd->object); 00123 00124 dag_add_relation(forest, curNode, obNode, 00125 DAG_RL_DATA_DATA|DAG_RL_OB_DATA|DAG_RL_DATA_OB|DAG_RL_OB_OB, 00126 "Mesh Deform Modifier"); 00127 } 00128 } 00129 00130 static float meshdeform_dynamic_bind(MeshDeformModifierData *mmd, float (*dco)[3], float *vec) 00131 { 00132 MDefCell *cell; 00133 MDefInfluence *inf; 00134 float gridvec[3], dvec[3], ivec[3], co[3], wx, wy, wz; 00135 float weight, cageweight, totweight, *cageco; 00136 int i, j, a, x, y, z, size; 00137 00138 zero_v3(co); 00139 totweight= 0.0f; 00140 size= mmd->dyngridsize; 00141 00142 for(i=0; i<3; i++) { 00143 gridvec[i]= (vec[i] - mmd->dyncellmin[i] - mmd->dyncellwidth*0.5f)/mmd->dyncellwidth; 00144 ivec[i]= (int)gridvec[i]; 00145 dvec[i]= gridvec[i] - ivec[i]; 00146 } 00147 00148 for(i=0; i<8; i++) { 00149 if(i & 1) { x= ivec[0]+1; wx= dvec[0]; } 00150 else { x= ivec[0]; wx= 1.0f-dvec[0]; } 00151 00152 if(i & 2) { y= ivec[1]+1; wy= dvec[1]; } 00153 else { y= ivec[1]; wy= 1.0f-dvec[1]; } 00154 00155 if(i & 4) { z= ivec[2]+1; wz= dvec[2]; } 00156 else { z= ivec[2]; wz= 1.0f-dvec[2]; } 00157 00158 CLAMP(x, 0, size-1); 00159 CLAMP(y, 0, size-1); 00160 CLAMP(z, 0, size-1); 00161 00162 a= x + y*size + z*size*size; 00163 weight= wx*wy*wz; 00164 00165 cell= &mmd->dyngrid[a]; 00166 inf= mmd->dyninfluences + cell->offset; 00167 for(j=0; j<cell->totinfluence; j++, inf++) { 00168 cageco= dco[inf->vertex]; 00169 cageweight= weight*inf->weight; 00170 co[0] += cageweight*cageco[0]; 00171 co[1] += cageweight*cageco[1]; 00172 co[2] += cageweight*cageco[2]; 00173 totweight += cageweight; 00174 } 00175 } 00176 00177 copy_v3_v3(vec, co); 00178 00179 return totweight; 00180 } 00181 00182 static void meshdeformModifier_do( 00183 ModifierData *md, Object *ob, DerivedMesh *dm, 00184 float (*vertexCos)[3], int numVerts) 00185 { 00186 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; 00187 struct Mesh *me= (mmd->object)? mmd->object->data: NULL; 00188 struct EditMesh *em = (me)? BKE_mesh_get_editmesh(me): NULL; 00189 DerivedMesh *tmpdm, *cagedm; 00190 MDeformVert *dvert = NULL; 00191 MDefInfluence *influences; 00192 int *offsets; 00193 float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4]; 00194 float weight, totweight, fac, co[3], (*dco)[3], (*bindcagecos)[3]; 00195 int a, b, totvert, totcagevert, defgrp_index; 00196 float (*cagecos)[3]; 00197 00198 if(!mmd->object || (!mmd->bindcagecos && !mmd->bindfunc)) 00199 return; 00200 00201 /* get cage derivedmesh */ 00202 if(em) { 00203 tmpdm= editmesh_get_derived_cage_and_final(md->scene, ob, em, &cagedm, 0); 00204 if(tmpdm) 00205 tmpdm->release(tmpdm); 00206 BKE_mesh_end_editmesh(me, em); 00207 } 00208 else 00209 cagedm= mmd->object->derivedFinal; 00210 00211 /* if we don't have one computed, use derivedmesh from data 00212 * without any modifiers */ 00213 if(!cagedm) { 00214 cagedm= get_dm(mmd->object, NULL, NULL, NULL, 0); 00215 if(cagedm) 00216 cagedm->needsFree= 1; 00217 } 00218 00219 if(!cagedm) { 00220 modifier_setError(md, "Can't get mesh from cage object."); 00221 return; 00222 } 00223 00224 /* compute matrices to go in and out of cage object space */ 00225 invert_m4_m4(imat, mmd->object->obmat); 00226 mult_m4_m4m4(cagemat, imat, ob->obmat); 00227 mult_m4_m4m4(cmat, mmd->bindmat, cagemat); 00228 invert_m4_m4(iobmat, cmat); 00229 copy_m3_m4(icagemat, iobmat); 00230 00231 /* bind weights if needed */ 00232 if(!mmd->bindcagecos) { 00233 static int recursive = 0; 00234 00235 /* progress bar redraw can make this recursive .. */ 00236 if(!recursive) { 00237 recursive = 1; 00238 mmd->bindfunc(md->scene, mmd, (float*)vertexCos, numVerts, cagemat); 00239 recursive = 0; 00240 } 00241 } 00242 00243 /* verify we have compatible weights */ 00244 totvert= numVerts; 00245 totcagevert= cagedm->getNumVerts(cagedm); 00246 00247 if(mmd->totvert != totvert) { 00248 modifier_setError(md, "Verts changed from %d to %d.", mmd->totvert, totvert); 00249 cagedm->release(cagedm); 00250 return; 00251 } 00252 else if (mmd->totcagevert != totcagevert) { 00253 modifier_setError(md, "Cage verts changed from %d to %d.", mmd->totcagevert, totcagevert); 00254 cagedm->release(cagedm); 00255 return; 00256 } else if (mmd->bindcagecos == NULL) { 00257 modifier_setError(md, "Bind data missing."); 00258 cagedm->release(cagedm); 00259 return; 00260 } 00261 00262 cagecos= MEM_callocN(sizeof(*cagecos)*totcagevert, "meshdeformModifier vertCos"); 00263 00264 /* setup deformation data */ 00265 cagedm->getVertCos(cagedm, cagecos); 00266 influences= mmd->bindinfluences; 00267 offsets= mmd->bindoffsets; 00268 bindcagecos= (float(*)[3])mmd->bindcagecos; 00269 00270 dco= MEM_callocN(sizeof(*dco)*totcagevert, "MDefDco"); 00271 for(a=0; a<totcagevert; a++) { 00272 /* get cage vertex in world space with binding transform */ 00273 copy_v3_v3(co, cagecos[a]); 00274 00275 if(G.rt != 527) { 00276 mul_m4_v3(mmd->bindmat, co); 00277 /* compute difference with world space bind coord */ 00278 sub_v3_v3v3(dco[a], co, bindcagecos[a]); 00279 } 00280 else 00281 copy_v3_v3(dco[a], co); 00282 } 00283 00284 modifier_get_vgroup(ob, dm, mmd->defgrp_name, &dvert, &defgrp_index); 00285 00286 /* do deformation */ 00287 fac= 1.0f; 00288 00289 for(b=0; b<totvert; b++) { 00290 if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) 00291 if(!mmd->dynverts[b]) 00292 continue; 00293 00294 if(dvert) { 00295 fac= defvert_find_weight(&dvert[b], defgrp_index); 00296 00297 if (mmd->flag & MOD_MDEF_INVERT_VGROUP) { 00298 fac= 1.0f - fac; 00299 } 00300 00301 if (fac <= 0.0) { 00302 continue; 00303 } 00304 } 00305 00306 if(mmd->flag & MOD_MDEF_DYNAMIC_BIND) { 00307 /* transform coordinate into cage's local space */ 00308 mul_v3_m4v3(co, cagemat, vertexCos[b]); 00309 totweight= meshdeform_dynamic_bind(mmd, dco, co); 00310 } 00311 else { 00312 totweight= 0.0f; 00313 zero_v3(co); 00314 00315 for(a=offsets[b]; a<offsets[b+1]; a++) { 00316 weight= influences[a].weight; 00317 madd_v3_v3fl(co, dco[influences[a].vertex], weight); 00318 totweight += weight; 00319 } 00320 } 00321 00322 if(totweight > 0.0f) { 00323 mul_v3_fl(co, fac/totweight); 00324 mul_m3_v3(icagemat, co); 00325 if(G.rt != 527) 00326 add_v3_v3(vertexCos[b], co); 00327 else 00328 copy_v3_v3(vertexCos[b], co); 00329 } 00330 } 00331 00332 /* release cage derivedmesh */ 00333 MEM_freeN(dco); 00334 MEM_freeN(cagecos); 00335 cagedm->release(cagedm); 00336 } 00337 00338 static void deformVerts(ModifierData *md, Object *ob, 00339 DerivedMesh *derivedData, 00340 float (*vertexCos)[3], 00341 int numVerts, 00342 int UNUSED(useRenderParams), 00343 int UNUSED(isFinalCalc)) 00344 { 00345 DerivedMesh *dm= get_dm(ob, NULL, derivedData, NULL, 0); 00346 00347 modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ 00348 00349 meshdeformModifier_do(md, ob, dm, vertexCos, numVerts); 00350 00351 if(dm && dm != derivedData) 00352 dm->release(dm); 00353 } 00354 00355 static void deformVertsEM(ModifierData *md, Object *ob, 00356 struct EditMesh *UNUSED(editData), 00357 DerivedMesh *derivedData, 00358 float (*vertexCos)[3], 00359 int numVerts) 00360 { 00361 DerivedMesh *dm= get_dm(ob, NULL, derivedData, NULL, 0); 00362 00363 meshdeformModifier_do(md, ob, dm, vertexCos, numVerts); 00364 00365 if(dm && dm != derivedData) 00366 dm->release(dm); 00367 } 00368 00369 #define MESHDEFORM_MIN_INFLUENCE 0.00001f 00370 00371 void modifier_mdef_compact_influences(ModifierData *md) 00372 { 00373 MeshDeformModifierData *mmd= (MeshDeformModifierData*)md; 00374 float weight, *weights, totweight; 00375 int totinfluence, totvert, totcagevert, a, b; 00376 00377 weights= mmd->bindweights; 00378 if(!weights) 00379 return; 00380 00381 totvert= mmd->totvert; 00382 totcagevert= mmd->totcagevert; 00383 00384 /* count number of influences above threshold */ 00385 for(b=0; b<totvert; b++) { 00386 for(a=0; a<totcagevert; a++) { 00387 weight= weights[a + b*totcagevert]; 00388 00389 if(weight > MESHDEFORM_MIN_INFLUENCE) 00390 mmd->totinfluence++; 00391 } 00392 } 00393 00394 /* allocate bind influences */ 00395 mmd->bindinfluences= MEM_callocN(sizeof(MDefInfluence)*mmd->totinfluence, "MDefBindInfluence"); 00396 mmd->bindoffsets= MEM_callocN(sizeof(int)*(totvert+1), "MDefBindOffset"); 00397 00398 /* write influences */ 00399 totinfluence= 0; 00400 00401 for(b=0; b<totvert; b++) { 00402 mmd->bindoffsets[b]= totinfluence; 00403 totweight= 0.0f; 00404 00405 /* sum total weight */ 00406 for(a=0; a<totcagevert; a++) { 00407 weight= weights[a + b*totcagevert]; 00408 00409 if(weight > MESHDEFORM_MIN_INFLUENCE) 00410 totweight += weight; 00411 } 00412 00413 /* assign weights normalized */ 00414 for(a=0; a<totcagevert; a++) { 00415 weight= weights[a + b*totcagevert]; 00416 00417 if(weight > MESHDEFORM_MIN_INFLUENCE) { 00418 mmd->bindinfluences[totinfluence].weight= weight/totweight; 00419 mmd->bindinfluences[totinfluence].vertex= a; 00420 totinfluence++; 00421 } 00422 } 00423 } 00424 00425 mmd->bindoffsets[b]= totinfluence; 00426 00427 /* free */ 00428 MEM_freeN(mmd->bindweights); 00429 mmd->bindweights= NULL; 00430 } 00431 00432 ModifierTypeInfo modifierType_MeshDeform = { 00433 /* name */ "MeshDeform", 00434 /* structName */ "MeshDeformModifierData", 00435 /* structSize */ sizeof(MeshDeformModifierData), 00436 /* type */ eModifierTypeType_OnlyDeform, 00437 /* flags */ eModifierTypeFlag_AcceptsCVs 00438 | eModifierTypeFlag_SupportsEditmode, 00439 00440 /* copyData */ copyData, 00441 /* deformVerts */ deformVerts, 00442 /* deformMatrices */ NULL, 00443 /* deformVertsEM */ deformVertsEM, 00444 /* deformMatricesEM */ NULL, 00445 /* applyModifier */ NULL, 00446 /* applyModifierEM */ NULL, 00447 /* initData */ initData, 00448 /* requiredDataMask */ requiredDataMask, 00449 /* freeData */ freeData, 00450 /* isDisabled */ isDisabled, 00451 /* updateDepgraph */ updateDepgraph, 00452 /* dependsOnTime */ NULL, 00453 /* dependsOnNormals */ NULL, 00454 /* foreachObjectLink */ foreachObjectLink, 00455 /* foreachIDLink */ NULL, 00456 /* foreachTexLink */ NULL, 00457 };