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