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) 2011 by Bastien Montagne. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): None yet. 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 * 00025 */ 00026 00031 #define DO_PROFILE 0 00032 00033 #include "BLI_editVert.h" 00034 #include "BLI_math.h" 00035 #include "BLI_string.h" 00036 #include "BLI_utildefines.h" 00037 00038 #if DO_PROFILE 00039 #include "PIL_time.h" 00040 #endif 00041 00042 #include "DNA_mesh_types.h" 00043 #include "DNA_meshdata_types.h" 00044 #include "DNA_modifier_types.h" 00045 #include "DNA_object_types.h" 00046 00047 #include "BKE_cdderivedmesh.h" 00048 #include "BKE_deform.h" 00049 #include "BKE_mesh.h" 00050 #include "BKE_modifier.h" 00051 #include "BKE_shrinkwrap.h" /* For SpaceTransform stuff. */ 00052 #include "BKE_texture.h" /* Texture masking. */ 00053 00054 #include "depsgraph_private.h" 00055 #include "MEM_guardedalloc.h" 00056 #include "MOD_util.h" 00057 #include "MOD_weightvg_util.h" 00058 00059 /************************************** 00060 * Util functions. * 00061 **************************************/ 00062 00063 /* Util macro. */ 00064 #define OUT_OF_MEMORY() ((void)printf("WeightVGProximity: Out of memory.\n")) 00065 00069 static void get_vert2geom_distance(int numVerts, float (*v_cos)[3], 00070 float *dist_v, float *dist_e, float *dist_f, 00071 DerivedMesh *target, const SpaceTransform *loc2trgt) 00072 { 00073 int i; 00074 BVHTreeFromMesh treeData_v = NULL_BVHTreeFromMesh; 00075 BVHTreeFromMesh treeData_e = NULL_BVHTreeFromMesh; 00076 BVHTreeFromMesh treeData_f = NULL_BVHTreeFromMesh; 00077 BVHTreeNearest nearest_v = NULL_BVHTreeNearest; 00078 BVHTreeNearest nearest_e = NULL_BVHTreeNearest; 00079 BVHTreeNearest nearest_f = NULL_BVHTreeNearest; 00080 00081 if (dist_v) { 00082 /* Create a bvh-tree of the given target's verts. */ 00083 bvhtree_from_mesh_verts(&treeData_v, target, 0.0, 2, 6); 00084 if(treeData_v.tree == NULL) { 00085 OUT_OF_MEMORY(); 00086 return; 00087 } 00088 } 00089 if (dist_e) { 00090 /* Create a bvh-tree of the given target's edges. */ 00091 bvhtree_from_mesh_edges(&treeData_e, target, 0.0, 2, 6); 00092 if(treeData_e.tree == NULL) { 00093 OUT_OF_MEMORY(); 00094 return; 00095 } 00096 } 00097 if (dist_f) { 00098 /* Create a bvh-tree of the given target's faces. */ 00099 bvhtree_from_mesh_faces(&treeData_f, target, 0.0, 2, 6); 00100 if(treeData_f.tree == NULL) { 00101 OUT_OF_MEMORY(); 00102 return; 00103 } 00104 } 00105 00106 /* Setup nearest. */ 00107 nearest_v.index = nearest_e.index = nearest_f.index = -1; 00108 /*nearest_v.dist = nearest_e.dist = nearest_f.dist = FLT_MAX;*/ 00109 /* Find the nearest vert/edge/face. */ 00110 #ifndef __APPLE__ 00111 #pragma omp parallel for default(none) private(i) firstprivate(nearest_v,nearest_e,nearest_f) \ 00112 shared(treeData_v,treeData_e,treeData_f,numVerts,v_cos,dist_v,dist_e, \ 00113 dist_f,loc2trgt) \ 00114 schedule(static) 00115 #endif 00116 for (i = 0; i < numVerts; ++i) { 00117 float tmp_co[3]; 00118 00119 /* Convert the vertex to tree coordinates. */ 00120 copy_v3_v3(tmp_co, v_cos[i]); 00121 space_transform_apply(loc2trgt, tmp_co); 00122 00123 /* Use local proximity heuristics (to reduce the nearest search). 00124 * 00125 * If we already had an hit before, we assume this vertex is going to have a close hit to 00126 * that other vertex, so we can initiate the "nearest.dist" with the expected value to that 00127 * last hit. 00128 * This will lead in prunning of the search tree. 00129 */ 00130 if (dist_v) { 00131 nearest_v.dist = nearest_v.index != -1 ? len_squared_v3v3(tmp_co, nearest_v.co) : FLT_MAX; 00132 /* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */ 00133 BLI_bvhtree_find_nearest(treeData_v.tree, tmp_co, &nearest_v, treeData_v.nearest_callback, &treeData_v); 00134 dist_v[i] = sqrtf(nearest_v.dist); 00135 } 00136 if (dist_e) { 00137 nearest_e.dist = nearest_e.index != -1 ? len_squared_v3v3(tmp_co, nearest_e.co) : FLT_MAX; 00138 /* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */ 00139 BLI_bvhtree_find_nearest(treeData_e.tree, tmp_co, &nearest_e, treeData_e.nearest_callback, &treeData_e); 00140 dist_e[i] = sqrtf(nearest_e.dist); 00141 } 00142 if (dist_f) { 00143 nearest_f.dist = nearest_f.index != -1 ? len_squared_v3v3(tmp_co, nearest_f.co) : FLT_MAX; 00144 /* Compute and store result. If invalid (-1 idx), keep FLT_MAX dist. */ 00145 BLI_bvhtree_find_nearest(treeData_f.tree, tmp_co, &nearest_f, treeData_f.nearest_callback, &treeData_f); 00146 dist_f[i] = sqrtf(nearest_f.dist); 00147 } 00148 } 00149 00150 if (dist_v) 00151 free_bvhtree_from_mesh(&treeData_v); 00152 if (dist_e) 00153 free_bvhtree_from_mesh(&treeData_e); 00154 if (dist_f) 00155 free_bvhtree_from_mesh(&treeData_f); 00156 } 00157 00162 static void get_vert2ob_distance(int numVerts, float (*v_cos)[3], float *dist, 00163 Object* ob, Object* obr) 00164 { 00165 /* Vertex and ref object coordinates. */ 00166 float v_wco[3]; 00167 unsigned int i= numVerts; 00168 00169 while(i-- > 0) { 00170 /* Get world-coordinates of the vertex (constraints and anim included). */ 00171 mul_v3_m4v3(v_wco, ob->obmat, v_cos[i]); 00172 /* Return distance between both coordinates. */ 00173 dist[i] = len_v3v3(v_wco, obr->obmat[3]); 00174 } 00175 } 00176 00181 static float get_ob2ob_distance(const Object* ob, const Object* obr) 00182 { 00183 return len_v3v3(ob->obmat[3], obr->obmat[3]); 00184 } 00185 00189 void do_map(float *weights, const int nidx, const float min_d, const float max_d, short mode) 00190 { 00191 const float range_inv= 1.0f / (max_d - min_d); /* invert since multiplication is faster */ 00192 unsigned int i= nidx; 00193 if(max_d == min_d) { 00194 while (i-- > 0) { 00195 weights[i] = (weights[i] >= max_d) ? 1.0f : 0.0f; /* "Step" behavior... */ 00196 } 00197 } 00198 else if(max_d > min_d) { 00199 while (i-- > 0) { 00200 if (weights[i] >= max_d) weights[i]= 1.0f; /* most likely case first */ 00201 else if(weights[i] <= min_d) weights[i]= 0.0f; 00202 else weights[i]= (weights[i] - min_d) * range_inv; 00203 } 00204 } 00205 else { 00206 while (i-- > 0) { 00207 if (weights[i] <= max_d) weights[i]= 1.0f; /* most likely case first */ 00208 else if(weights[i] >= min_d) weights[i]= 0.0f; 00209 else weights[i]= (weights[i] - min_d) * range_inv; 00210 } 00211 } 00212 00213 if(!ELEM(mode, MOD_WVG_MAPPING_NONE, MOD_WVG_MAPPING_CURVE)) { 00214 weightvg_do_map(nidx, weights, mode, NULL); 00215 } 00216 } 00217 00218 /************************************** 00219 * Modifiers functions. * 00220 **************************************/ 00221 static void initData(ModifierData *md) 00222 { 00223 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md; 00224 00225 wmd->proximity_mode = MOD_WVG_PROXIMITY_OBJECT; 00226 wmd->proximity_flags = MOD_WVG_PROXIMITY_GEOM_VERTS; 00227 00228 wmd->falloff_type = MOD_WVG_MAPPING_NONE; 00229 00230 wmd->mask_constant = 1.0f; 00231 wmd->mask_tex_use_channel = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */ 00232 wmd->mask_tex_mapping = MOD_DISP_MAP_LOCAL; 00233 wmd->max_dist = 1.0f; /* vert arbitrary distance, but don't use 0 */ 00234 } 00235 00236 static void copyData(ModifierData *md, ModifierData *target) 00237 { 00238 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md; 00239 WeightVGProximityModifierData *twmd = (WeightVGProximityModifierData*) target; 00240 00241 BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name)); 00242 twmd->proximity_mode = wmd->proximity_mode; 00243 twmd->proximity_flags = wmd->proximity_flags; 00244 twmd->proximity_ob_target = wmd->proximity_ob_target; 00245 00246 twmd->falloff_type = wmd->falloff_type; 00247 00248 twmd->mask_constant = wmd->mask_constant; 00249 BLI_strncpy(twmd->mask_defgrp_name, wmd->mask_defgrp_name, sizeof(twmd->mask_defgrp_name)); 00250 twmd->mask_texture = wmd->mask_texture; 00251 twmd->mask_tex_use_channel = wmd->mask_tex_use_channel; 00252 twmd->mask_tex_mapping = wmd->mask_tex_mapping; 00253 twmd->mask_tex_map_obj = wmd->mask_tex_map_obj; 00254 BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name, sizeof(twmd->mask_tex_uvlayer_name)); 00255 twmd->min_dist = wmd->min_dist; 00256 twmd->max_dist = wmd->max_dist; 00257 } 00258 00259 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) 00260 { 00261 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md; 00262 CustomDataMask dataMask = 0; 00263 00264 /* We need vertex groups! */ 00265 dataMask |= CD_MASK_MDEFORMVERT; 00266 00267 /* Ask for UV coordinates if we need them. */ 00268 if(wmd->mask_tex_mapping == MOD_DISP_MAP_UV) 00269 dataMask |= CD_MASK_MTFACE; 00270 00271 return dataMask; 00272 } 00273 00274 static int dependsOnTime(ModifierData *md) 00275 { 00276 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md; 00277 00278 if(wmd->mask_texture) 00279 return BKE_texture_dependsOnTime(wmd->mask_texture); 00280 return 0; 00281 } 00282 00283 static void foreachObjectLink(ModifierData *md, Object *ob, 00284 void (*walk)(void *userData, Object *ob, Object **obpoin), 00285 void *userData) 00286 { 00287 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md; 00288 walk(userData, ob, &wmd->proximity_ob_target); 00289 walk(userData, ob, &wmd->mask_tex_map_obj); 00290 } 00291 00292 static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) 00293 { 00294 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md; 00295 00296 walk(userData, ob, (ID **)&wmd->mask_texture); 00297 00298 foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); 00299 } 00300 00301 static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData) 00302 { 00303 walk(userData, ob, md, "mask_texture"); 00304 } 00305 00306 static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene), 00307 Object *UNUSED(ob), DagNode *obNode) 00308 { 00309 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md; 00310 DagNode *curNode; 00311 00312 if (wmd->proximity_ob_target) { 00313 curNode = dag_get_node(forest, wmd->proximity_ob_target); 00314 dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, 00315 "WeightVGProximity Modifier"); 00316 } 00317 00318 if(wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) { 00319 curNode = dag_get_node(forest, wmd->mask_tex_map_obj); 00320 00321 dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, 00322 "WeightVGProximity Modifier"); 00323 } 00324 00325 if(wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL) 00326 dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, 00327 "WeightVGProximity Modifier"); 00328 } 00329 00330 static int isDisabled(ModifierData *md, int UNUSED(useRenderParams)) 00331 { 00332 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md; 00333 /* If no vertex group, bypass. */ 00334 if (wmd->defgrp_name[0] == '\0') return 1; 00335 /* If no target object, bypass. */ 00336 return (wmd->proximity_ob_target == NULL); 00337 } 00338 00339 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, 00340 int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) 00341 { 00342 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData*) md; 00343 DerivedMesh *dm = derivedData; 00344 MDeformVert *dvert = NULL; 00345 MDeformWeight **dw, **tdw; 00346 int numVerts; 00347 float (*v_cos)[3] = NULL; /* The vertices coordinates. */ 00348 Object *obr = NULL; /* Our target object. */ 00349 int defgrp_idx; 00350 float *tw = NULL; 00351 float *org_w = NULL; 00352 float *new_w =NULL; 00353 int *tidx, *indices = NULL; 00354 int numIdx = 0; 00355 int i; 00356 00357 #if DO_PROFILE 00358 TIMEIT_START(perf) 00359 #endif 00360 00361 /* Get number of verts. */ 00362 numVerts = dm->getNumVerts(dm); 00363 00364 /* Check if we can just return the original mesh. 00365 * Must have verts and therefore verts assigned to vgroups to do anything useful! 00366 */ 00367 if ((numVerts == 0) || (ob->defbase.first == NULL)) 00368 return dm; 00369 00370 /* Get our target object. */ 00371 obr = wmd->proximity_ob_target; 00372 if (obr == NULL) 00373 return dm; 00374 00375 /* Get vgroup idx from its name. */ 00376 defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name); 00377 if (defgrp_idx < 0) 00378 return dm; 00379 00380 dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts); 00381 00382 /* Find out which vertices to work on (all vertices in vgroup), and get their relevant weight. 00383 */ 00384 tidx = MEM_mallocN(sizeof(int) * numVerts, "WeightVGProximity Modifier, tidx"); 00385 tw = MEM_mallocN(sizeof(float) * numVerts, "WeightVGProximity Modifier, tw"); 00386 tdw = MEM_mallocN(sizeof(MDeformWeight*) * numVerts, "WeightVGProximity Modifier, tdw"); 00387 for (i = 0; i < numVerts; i++) { 00388 MDeformWeight *_dw = defvert_find_index(&dvert[i], defgrp_idx); 00389 if(_dw) { 00390 tidx[numIdx] = i; 00391 tw[numIdx] = _dw->weight; 00392 tdw[numIdx++] = _dw; 00393 } 00394 } 00395 /* If no vertices found, return org data! */ 00396 if(numIdx == 0) { 00397 MEM_freeN(tidx); 00398 MEM_freeN(tw); 00399 MEM_freeN(tdw); 00400 return dm; 00401 } 00402 if(numIdx != numVerts) { 00403 indices = MEM_mallocN(sizeof(int) * numIdx, "WeightVGProximity Modifier, indices"); 00404 memcpy(indices, tidx, sizeof(int) * numIdx); 00405 org_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, org_w"); 00406 memcpy(org_w, tw, sizeof(float) * numIdx); 00407 dw = MEM_mallocN(sizeof(MDeformWeight*) * numIdx, "WeightVGProximity Modifier, dw"); 00408 memcpy(dw, tdw, sizeof(MDeformWeight*) * numIdx); 00409 MEM_freeN(tw); 00410 MEM_freeN(tdw); 00411 } 00412 else { 00413 org_w = tw; 00414 dw = tdw; 00415 } 00416 new_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, new_w"); 00417 MEM_freeN(tidx); 00418 00419 /* Get our vertex coordinates. */ 00420 v_cos = MEM_mallocN(sizeof(float[3]) * numIdx, "WeightVGProximity Modifier, v_cos"); 00421 if(numIdx != numVerts) { 00422 /* XXX In some situations, this code can be up to about 50 times more performant 00423 * than simply using getVertCo for each affected vertex... 00424 */ 00425 float (*tv_cos)[3] = MEM_mallocN(sizeof(float[3]) * numVerts, "WeightVGProximity Modifier, tv_cos"); 00426 dm->getVertCos(dm, tv_cos); 00427 for (i = 0; i < numIdx; i++) 00428 copy_v3_v3(v_cos[i], tv_cos[indices[i]]); 00429 MEM_freeN(tv_cos); 00430 } 00431 else 00432 dm->getVertCos(dm, v_cos); 00433 00434 /* Compute wanted distances. */ 00435 if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJECT) { 00436 const float dist = get_ob2ob_distance(ob, obr); 00437 for(i = 0; i < numIdx; i++) 00438 new_w[i] = dist; 00439 } 00440 else if (wmd->proximity_mode == MOD_WVG_PROXIMITY_GEOMETRY) { 00441 const short use_trgt_verts = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_VERTS); 00442 const short use_trgt_edges = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_EDGES); 00443 const short use_trgt_faces = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_FACES); 00444 00445 if (use_trgt_verts || use_trgt_edges || use_trgt_faces) { 00446 DerivedMesh *target_dm = obr->derivedFinal; 00447 short free_target_dm = FALSE; 00448 if (!target_dm) { 00449 if (ELEM3(obr->type, OB_CURVE, OB_SURF, OB_FONT)) 00450 target_dm = CDDM_from_curve(obr); 00451 else if (obr->type == OB_MESH) { 00452 Mesh *me = (Mesh*)obr->data; 00453 if (me->edit_mesh) 00454 target_dm = CDDM_from_editmesh((EditMesh*)me->edit_mesh, me); 00455 else 00456 target_dm = CDDM_from_mesh(me, obr); 00457 } 00458 free_target_dm = TRUE; 00459 } 00460 00461 /* We must check that we do have a valid target_dm! */ 00462 if (target_dm) { 00463 SpaceTransform loc2trgt; 00464 float *dists_v = use_trgt_verts ? MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, dists_v") : NULL; 00465 float *dists_e = use_trgt_edges ? MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, dists_e") : NULL; 00466 float *dists_f = use_trgt_faces ? MEM_mallocN(sizeof(float) * numIdx, "WeightVGProximity Modifier, dists_f") : NULL; 00467 00468 space_transform_setup(&loc2trgt, ob, obr); 00469 get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f, 00470 target_dm, &loc2trgt); 00471 for(i = 0; i < numIdx; i++) { 00472 new_w[i] = dists_v ? dists_v[i] : FLT_MAX; 00473 if(dists_e) 00474 new_w[i] = minf(dists_e[i], new_w[i]); 00475 if(dists_f) 00476 new_w[i] = minf(dists_f[i], new_w[i]); 00477 } 00478 if(free_target_dm) target_dm->release(target_dm); 00479 if(dists_v) MEM_freeN(dists_v); 00480 if(dists_e) MEM_freeN(dists_e); 00481 if(dists_f) MEM_freeN(dists_f); 00482 } 00483 /* Else, fall back to default obj2vert behavior. */ 00484 else { 00485 get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr); 00486 } 00487 } 00488 else { 00489 get_vert2ob_distance(numIdx, v_cos, new_w, ob, obr); 00490 } 00491 } 00492 00493 /* Map distances to weights. */ 00494 do_map(new_w, numIdx, wmd->min_dist, wmd->max_dist, wmd->falloff_type); 00495 00496 /* Do masking. */ 00497 weightvg_do_mask(numIdx, indices, org_w, new_w, ob, dm, wmd->mask_constant, 00498 wmd->mask_defgrp_name, wmd->mask_texture, wmd->mask_tex_use_channel, 00499 wmd->mask_tex_mapping, wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name); 00500 00501 /* Update vgroup. Note we never add nor remove vertices from vgroup here. */ 00502 weightvg_update_vg(dvert, defgrp_idx, dw, numIdx, indices, org_w, FALSE, 0.0f, FALSE, 0.0f); 00503 00504 /* Freeing stuff. */ 00505 MEM_freeN(org_w); 00506 MEM_freeN(new_w); 00507 MEM_freeN(dw); 00508 if(indices) 00509 MEM_freeN(indices); 00510 MEM_freeN(v_cos); 00511 00512 #if DO_PROFILE 00513 TIMEIT_END(perf) 00514 #endif 00515 00516 /* Return the vgroup-modified mesh. */ 00517 return dm; 00518 } 00519 00520 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, 00521 struct EditMesh *UNUSED(editData), 00522 DerivedMesh *derivedData) 00523 { 00524 return applyModifier(md, ob, derivedData, 0, 1); 00525 } 00526 00527 00528 ModifierTypeInfo modifierType_WeightVGProximity = { 00529 /* name */ "VertexWeightProximity", 00530 /* structName */ "WeightVGProximityModifierData", 00531 /* structSize */ sizeof(WeightVGProximityModifierData), 00532 /* type */ eModifierTypeType_NonGeometrical, 00533 /* flags */ eModifierTypeFlag_AcceptsMesh 00534 /* |eModifierTypeFlag_SupportsMapping*/ 00535 |eModifierTypeFlag_SupportsEditmode, 00536 00537 /* copyData */ copyData, 00538 /* deformVerts */ NULL, 00539 /* deformMatrices */ NULL, 00540 /* deformVertsEM */ NULL, 00541 /* deformMatricesEM */ NULL, 00542 /* applyModifier */ applyModifier, 00543 /* applyModifierEM */ applyModifierEM, 00544 /* initData */ initData, 00545 /* requiredDataMask */ requiredDataMask, 00546 /* freeData */ NULL, 00547 /* isDisabled */ isDisabled, 00548 /* updateDepgraph */ updateDepgraph, 00549 /* dependsOnTime */ dependsOnTime, 00550 /* dependsOnNormals */ NULL, 00551 /* foreachObjectLink */ foreachObjectLink, 00552 /* foreachIDLink */ foreachIDLink, 00553 /* foreachTexLink */ foreachTexLink, 00554 };