Blender V2.61 - r43446

MOD_weightvgproximity.c

Go to the documentation of this file.
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 };