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 "MEM_guardedalloc.h" 00037 00038 #include "BLI_utildefines.h" 00039 #include "BLI_listbase.h" 00040 #include "BLI_string.h" 00041 #include "BLI_ghash.h" 00042 00043 #include "DNA_armature_types.h" 00044 #include "DNA_meshdata_types.h" 00045 #include "DNA_modifier_types.h" 00046 #include "DNA_object_types.h" 00047 00048 #include "BKE_action.h" /* get_pose_channel */ 00049 #include "BKE_cdderivedmesh.h" 00050 #include "BKE_mesh.h" 00051 #include "BKE_modifier.h" 00052 #include "BKE_deform.h" 00053 00054 #include "depsgraph_private.h" 00055 00056 #include "MOD_util.h" 00057 00058 static void copyData(ModifierData *md, ModifierData *target) 00059 { 00060 MaskModifierData *mmd = (MaskModifierData*) md; 00061 MaskModifierData *tmmd = (MaskModifierData*) target; 00062 00063 BLI_strncpy(tmmd->vgroup, mmd->vgroup, sizeof(tmmd->vgroup)); 00064 tmmd->flag = mmd->flag; 00065 } 00066 00067 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md)) 00068 { 00069 return CD_MASK_MDEFORMVERT; 00070 } 00071 00072 static void foreachObjectLink( 00073 ModifierData *md, Object *ob, 00074 void (*walk)(void *userData, Object *ob, Object **obpoin), 00075 void *userData) 00076 { 00077 MaskModifierData *mmd = (MaskModifierData *)md; 00078 walk(userData, ob, &mmd->ob_arm); 00079 } 00080 00081 static void updateDepgraph(ModifierData *md, DagForest *forest, 00082 struct Scene *UNUSED(scene), 00083 Object *UNUSED(ob), 00084 DagNode *obNode) 00085 { 00086 MaskModifierData *mmd = (MaskModifierData *)md; 00087 00088 if (mmd->ob_arm) 00089 { 00090 DagNode *armNode = dag_get_node(forest, mmd->ob_arm); 00091 00092 dag_add_relation(forest, armNode, obNode, 00093 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier"); 00094 } 00095 } 00096 00097 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, 00098 DerivedMesh *derivedData, 00099 int UNUSED(useRenderParams), 00100 int UNUSED(isFinalCalc)) 00101 { 00102 MaskModifierData *mmd= (MaskModifierData *)md; 00103 DerivedMesh *dm= derivedData, *result= NULL; 00104 GHash *vertHash=NULL, *edgeHash, *faceHash; 00105 GHashIterator *hashIter; 00106 MDeformVert *dvert= NULL, *dv; 00107 int numFaces=0, numEdges=0, numVerts=0; 00108 int maxVerts, maxEdges, maxFaces; 00109 int i; 00110 00111 /* Overview of Method: 00112 * 1. Get the vertices that are in the vertexgroup of interest 00113 * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices 00114 * 3. Make a new mesh containing only the mapping data 00115 */ 00116 00117 /* get original number of verts, edges, and faces */ 00118 maxVerts= dm->getNumVerts(dm); 00119 maxEdges= dm->getNumEdges(dm); 00120 maxFaces= dm->getNumFaces(dm); 00121 00122 /* check if we can just return the original mesh 00123 * - must have verts and therefore verts assigned to vgroups to do anything useful 00124 */ 00125 if ( !(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || 00126 (maxVerts == 0) || (ob->defbase.first == NULL) ) 00127 { 00128 return derivedData; 00129 } 00130 00131 /* if mode is to use selected armature bones, aggregate the bone groups */ 00132 if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */ 00133 { 00134 GHash *vgroupHash; 00135 Object *oba= mmd->ob_arm; 00136 bPoseChannel *pchan; 00137 bDeformGroup *def; 00138 char *bone_select_array; 00139 int bone_select_tot= 0; 00140 const int defbase_tot= BLI_countlist(&ob->defbase); 00141 00142 /* check that there is armature object with bones to use, otherwise return original mesh */ 00143 if (ELEM3(NULL, mmd->ob_arm, mmd->ob_arm->pose, ob->defbase.first)) 00144 return derivedData; 00145 00146 bone_select_array= MEM_mallocN(defbase_tot * sizeof(char), "mask array"); 00147 00148 for (i = 0, def = ob->defbase.first; def; def = def->next, i++) 00149 { 00150 if (((pchan= get_pose_channel(oba->pose, def->name)) && pchan->bone && (pchan->bone->flag & BONE_SELECTED))) 00151 { 00152 bone_select_array[i]= TRUE; 00153 bone_select_tot++; 00154 } 00155 else { 00156 bone_select_array[i]= FALSE; 00157 } 00158 } 00159 00160 /* hashes for finding mapping of: 00161 * - vgroups to indices -> vgroupHash (string, int) 00162 * - bones to vgroup indices -> boneHash (index of vgroup, dummy) 00163 */ 00164 vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "mask vgroup gh"); 00165 00166 /* build mapping of names of vertex groups to indices */ 00167 for (i = 0, def = ob->defbase.first; def; def = def->next, i++) 00168 BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i)); 00169 00170 /* if no bones selected, free hashes and return original mesh */ 00171 if (bone_select_tot == 0) 00172 { 00173 BLI_ghash_free(vgroupHash, NULL, NULL); 00174 MEM_freeN(bone_select_array); 00175 00176 return derivedData; 00177 } 00178 00179 /* repeat the previous check, but for dverts */ 00180 dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT); 00181 if (dvert == NULL) 00182 { 00183 BLI_ghash_free(vgroupHash, NULL, NULL); 00184 MEM_freeN(bone_select_array); 00185 00186 return derivedData; 00187 } 00188 00189 /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ 00190 vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert gh"); 00191 00192 /* add vertices which exist in vertexgroups into vertHash for filtering */ 00193 for (i= 0, dv= dvert; i < maxVerts; i++, dv++) 00194 { 00195 MDeformWeight *dw= dv->dw; 00196 int j; 00197 00198 for (j= dv->totweight; j > 0; j--, dw++) { 00199 if (dw->def_nr < defbase_tot) { 00200 if (bone_select_array[dw->def_nr]) { 00201 if(dw->weight != 0.0f) { 00202 break; 00203 } 00204 } 00205 } 00206 } 00207 00208 /* check if include vert in vertHash */ 00209 if (mmd->flag & MOD_MASK_INV) { 00210 /* if this vert is in the vgroup, don't include it in vertHash */ 00211 if (dw) continue; 00212 } 00213 else { 00214 /* if this vert isn't in the vgroup, don't include it in vertHash */ 00215 if (!dw) continue; 00216 } 00217 00218 /* add to ghash for verts (numVerts acts as counter for mapping) */ 00219 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); 00220 numVerts++; 00221 } 00222 00223 /* free temp hashes */ 00224 BLI_ghash_free(vgroupHash, NULL, NULL); 00225 MEM_freeN(bone_select_array); 00226 } 00227 else /* --- Using Nominated VertexGroup only --- */ 00228 { 00229 int defgrp_index = defgroup_name_index(ob, mmd->vgroup); 00230 00231 /* get dverts */ 00232 if (defgrp_index >= 0) 00233 dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); 00234 00235 /* if no vgroup (i.e. dverts) found, return the initial mesh */ 00236 if ((defgrp_index < 0) || (dvert == NULL)) 00237 return dm; 00238 00239 /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ 00240 vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert2 bh"); 00241 00242 /* add vertices which exist in vertexgroup into ghash for filtering */ 00243 for (i= 0, dv= dvert; i < maxVerts; i++, dv++) 00244 { 00245 const int weight_set= defvert_find_weight(dv, defgrp_index) != 0.0f; 00246 00247 /* check if include vert in vertHash */ 00248 if (mmd->flag & MOD_MASK_INV) { 00249 /* if this vert is in the vgroup, don't include it in vertHash */ 00250 if (weight_set) continue; 00251 } 00252 else { 00253 /* if this vert isn't in the vgroup, don't include it in vertHash */ 00254 if (!weight_set) continue; 00255 } 00256 00257 /* add to ghash for verts (numVerts acts as counter for mapping) */ 00258 BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); 00259 numVerts++; 00260 } 00261 } 00262 00263 /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ 00264 edgeHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask ed2 gh"); 00265 faceHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask fa2 gh"); 00266 00267 /* loop over edges and faces, and do the same thing to 00268 * ensure that they only reference existing verts 00269 */ 00270 for (i = 0; i < maxEdges; i++) 00271 { 00272 MEdge me; 00273 dm->getEdge(dm, i, &me); 00274 00275 /* only add if both verts will be in new mesh */ 00276 if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) && 00277 BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)) ) 00278 { 00279 BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges)); 00280 numEdges++; 00281 } 00282 } 00283 for (i = 0; i < maxFaces; i++) 00284 { 00285 MFace mf; 00286 dm->getFace(dm, i, &mf); 00287 00288 /* all verts must be available */ 00289 if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) && 00290 BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)) && 00291 BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)) && 00292 (mf.v4==0 || BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) ) 00293 { 00294 BLI_ghash_insert(faceHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numFaces)); 00295 numFaces++; 00296 } 00297 } 00298 00299 00300 /* now we know the number of verts, edges and faces, 00301 * we can create the new (reduced) mesh 00302 */ 00303 result = CDDM_from_template(dm, numVerts, numEdges, numFaces); 00304 00305 00306 /* using ghash-iterators, map data into new mesh */ 00307 /* vertices */ 00308 for ( hashIter = BLI_ghashIterator_new(vertHash); 00309 !BLI_ghashIterator_isDone(hashIter); 00310 BLI_ghashIterator_step(hashIter) ) 00311 { 00312 MVert source; 00313 MVert *dest; 00314 int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); 00315 int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); 00316 00317 dm->getVert(dm, oldIndex, &source); 00318 dest = CDDM_get_vert(result, newIndex); 00319 00320 DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); 00321 *dest = source; 00322 } 00323 BLI_ghashIterator_free(hashIter); 00324 00325 /* edges */ 00326 for ( hashIter = BLI_ghashIterator_new(edgeHash); 00327 !BLI_ghashIterator_isDone(hashIter); 00328 BLI_ghashIterator_step(hashIter) ) 00329 { 00330 MEdge source; 00331 MEdge *dest; 00332 int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); 00333 int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); 00334 00335 dm->getEdge(dm, oldIndex, &source); 00336 dest = CDDM_get_edge(result, newIndex); 00337 00338 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); 00339 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); 00340 00341 DM_copy_edge_data(dm, result, oldIndex, newIndex, 1); 00342 *dest = source; 00343 } 00344 BLI_ghashIterator_free(hashIter); 00345 00346 /* faces */ 00347 for ( hashIter = BLI_ghashIterator_new(faceHash); 00348 !BLI_ghashIterator_isDone(hashIter); 00349 BLI_ghashIterator_step(hashIter) ) 00350 { 00351 MFace source; 00352 MFace *dest; 00353 int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); 00354 int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); 00355 int orig_v4; 00356 00357 dm->getFace(dm, oldIndex, &source); 00358 dest = CDDM_get_face(result, newIndex); 00359 00360 orig_v4 = source.v4; 00361 00362 source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); 00363 source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); 00364 source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3))); 00365 if (source.v4) 00366 source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4))); 00367 00368 DM_copy_face_data(dm, result, oldIndex, newIndex, 1); 00369 *dest = source; 00370 00371 test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3)); 00372 } 00373 BLI_ghashIterator_free(hashIter); 00374 00375 /* recalculate normals */ 00376 CDDM_calc_normals(result); 00377 00378 /* free hashes */ 00379 BLI_ghash_free(vertHash, NULL, NULL); 00380 BLI_ghash_free(edgeHash, NULL, NULL); 00381 BLI_ghash_free(faceHash, NULL, NULL); 00382 00383 /* return the new mesh */ 00384 return result; 00385 } 00386 00387 00388 ModifierTypeInfo modifierType_Mask = { 00389 /* name */ "Mask", 00390 /* structName */ "MaskModifierData", 00391 /* structSize */ sizeof(MaskModifierData), 00392 /* type */ eModifierTypeType_Nonconstructive, 00393 /* flags */ eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_SupportsMapping|eModifierTypeFlag_SupportsEditmode, 00394 00395 /* copyData */ copyData, 00396 /* deformVerts */ NULL, 00397 /* deformMatrices */ NULL, 00398 /* deformVertsEM */ NULL, 00399 /* deformMatricesEM */ NULL, 00400 /* applyModifier */ applyModifier, 00401 /* applyModifierEM */ NULL, 00402 /* initData */ NULL, 00403 /* requiredDataMask */ requiredDataMask, 00404 /* freeData */ NULL, 00405 /* isDisabled */ NULL, 00406 /* updateDepgraph */ updateDepgraph, 00407 /* dependsOnTime */ NULL, 00408 /* dependsOnNormals */ NULL, 00409 /* foreachObjectLink */ foreachObjectLink, 00410 /* foreachIDLink */ NULL, 00411 /* foreachTexLink */ NULL, 00412 };