Hook Modifier: add falloff & radius options
authorCampbell Barton <ideasman42@gmail.com>
Tue, 3 Feb 2015 20:04:21 +0000 (07:04 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 3 Feb 2015 20:16:20 +0000 (07:16 +1100)
- Add falloff types & curves (matching warp-modifier)
- Add uniform scale option,
  important when adding hooks to non-uniform scaled objects,
  especially for use with lattice objects which can't avoid uneven scaling.

  This uses relative transformation set when the hook is assigned,
  when measuring the distances.

release/scripts/startup/bl_ui/properties_data_modifier.py
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_270.c
source/blender/blenloader/intern/writefile.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesrna/intern/rna_modifier.c
source/blender/modifiers/intern/MOD_hook.c

index 4c967079137cdcb65fdb00f157d85e9bacf126ce..92e9e02ffca6e72e16588ab1b45e5793bc83959b 100644 (file)
@@ -352,6 +352,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
         layout.label(text="Settings are inside the Physics tab")
 
     def HOOK(self, layout, ob, md):
+        use_falloff = (md.falloff_type != 'NONE')
         split = layout.split()
 
         col = split.column()
@@ -366,19 +367,28 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
 
         layout.separator()
 
-        split = layout.split()
+        row = layout.row(align=True)
+        if use_falloff:
+            row.prop(md, "falloff_radius")
+        row.prop(md, "strength", slider=True)
+        layout.prop(md, "falloff_type")
 
-        col = split.column()
-        col.prop(md, "falloff")
-        col.prop(md, "force", slider=True)
+        col = layout.column()
+        if use_falloff:
+            if md.falloff_type == 'CURVE':
+                col.template_curve_mapping(md, "falloff_curve")
+
+        split = layout.split()
 
         col = split.column()
-        col.operator("object.hook_reset", text="Reset")
-        col.operator("object.hook_recenter", text="Recenter")
+        col.prop(md, "use_falloff_uniform")
 
         if ob.mode == 'EDIT':
-            layout.separator()
-            row = layout.row()
+            row = col.row(align=True)
+            row.operator("object.hook_reset", text="Reset")
+            row.operator("object.hook_recenter", text="Recenter")
+
+            row = layout.row(align=True)
             row.operator("object.hook_select", text="Select")
             row.operator("object.hook_assign", text="Assign")
 
index 9daa6931282159268ca4ed3de41350c04e0702ee..7bfe6f0397bb9d106e98e6d14bc5ba2ca6cb1769 100644 (file)
@@ -4840,6 +4840,11 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                        if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
                                BLI_endian_switch_int32_array(hmd->indexar, hmd->totindex);
                        }
+
+                       hmd->curfalloff = newdataadr(fd, hmd->curfalloff);
+                       if (hmd->curfalloff) {
+                               direct_link_curvemapping(fd, hmd->curfalloff);
+                       }
                }
                else if (md->type == eModifierType_ParticleSystem) {
                        ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
index 6f33cab203e58fbf4c7fa1af954ada4045c3589b..a6320ed597bf6a095d96c70d619bc658550dd25a 100644 (file)
@@ -519,6 +519,20 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                }
        }
 
+       if (!DNA_struct_elem_find(fd->filesdna, "HookModifierData", "char", "flag")) {
+               Object *ob;
+
+               for (ob = main->object.first; ob; ob = ob->id.next) {
+                       ModifierData *md;
+                       for (md = ob->modifiers.first; md; md = md->next) {
+                               if (md->type == eModifierType_Hook) {
+                                       HookModifierData *hmd = (HookModifierData *)md;
+                                       hmd->falloff_type = eHook_Falloff_InvSquare;
+                               }
+                       }
+               }
+       }
+
        if (!MAIN_VERSION_ATLEAST(main, 273, 3)) {
                ParticleSettings *part;
                for (part = main->particle.first; part; part = part->id.next) {
index 1de2b6b267a22b40514d81aec2dce4966329b5da..3eeb30ac5d069cb1e29e8aba2a0946daabd02bd9 100644 (file)
@@ -1485,6 +1485,10 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                if (md->type==eModifierType_Hook) {
                        HookModifierData *hmd = (HookModifierData*) md;
                        
+                       if (hmd->curfalloff) {
+                               write_curvemapping(wd, hmd->curfalloff);
+                       }
+
                        writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar);
                }
                else if (md->type==eModifierType_Cloth) {
index 2d8c3b23da75209a9eecc3f85981a6b55f9295ac..47273d3c713af89bc217d56bd3b4a6414d93a694 100644 (file)
@@ -535,16 +535,39 @@ typedef struct ArmatureModifierData {
        char defgrp_name[64];     /* MAX_VGROUP_NAME */
 } ArmatureModifierData;
 
+enum {
+       MOD_HOOK_UNIFORM_SPACE = (1 << 0),
+};
+
+/* same as WarpModifierFalloff */
+typedef enum {
+       eHook_Falloff_None   = 0,
+       eHook_Falloff_Curve  = 1,
+       eHook_Falloff_Sharp  = 2, /* PROP_SHARP */
+       eHook_Falloff_Smooth = 3, /* PROP_SMOOTH */
+       eHook_Falloff_Root   = 4, /* PROP_ROOT */
+       eHook_Falloff_Linear = 5, /* PROP_LIN */
+       eHook_Falloff_Const  = 6, /* PROP_CONST */
+       eHook_Falloff_Sphere = 7, /* PROP_SPHERE */
+       eHook_Falloff_InvSquare = 8, /* PROP_INVSQUARE */
+       /* PROP_RANDOM not used */
+} HookModifierFalloff;
+
 typedef struct HookModifierData {
        ModifierData modifier;
 
        struct Object *object;
        char subtarget[64];     /* optional name of bone target, MAX_ID_NAME-2 */
 
+       char flag;
+       char falloff_type;      /* use enums from WarpModifier (exact same functionality) */
+       char pad[6];
        float parentinv[4][4];  /* matrix making current transform unmodified */
        float cent[3];          /* visualization of hook */
        float falloff;          /* if not zero, falloff is distance where influence zero */
 
+       struct CurveMapping *curfalloff;
+
        int *indexar;           /* if NULL, it's using vertexgroup */
        int totindex;
        float force;
index 12b6d74e4a58f82896fb219f6d7d0ab380494673..3124add78757da9a99c3fbb42632883ecc16dea1 100644 (file)
@@ -134,6 +134,22 @@ EnumPropertyItem modifier_triangulate_ngon_method_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
+#ifndef RNA_RUNTIME
+/* use eWarp_Falloff_*** & eHook_Falloff_***, they're in sync */
+static EnumPropertyItem modifier_warp_falloff_items[] = {
+       {eWarp_Falloff_None,    "NONE", 0, "No Falloff", ""},
+       {eWarp_Falloff_Curve,   "CURVE", 0, "Curve", ""},
+       {eWarp_Falloff_Smooth,  "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
+       {eWarp_Falloff_Sphere,  "SPHERE", ICON_SPHERECURVE, "Sphere", ""},
+       {eWarp_Falloff_Root,    "ROOT", ICON_ROOTCURVE, "Root", ""},
+       {eWarp_Falloff_InvSquare, "INVERSE_SQUARE", ICON_ROOTCURVE, "Inverse Square", ""},
+       {eWarp_Falloff_Sharp,   "SHARP", ICON_SHARPCURVE, "Sharp", ""},
+       {eWarp_Falloff_Linear,  "LINEAR", ICON_LINCURVE, "Linear", ""},
+       {eWarp_Falloff_Const,   "CONSTANT", ICON_NOCURVE, "Constant", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+#endif
+
 /* ***** Data Transfer ***** */
 
 EnumPropertyItem DT_method_vertex_items[] = {
@@ -1111,19 +1127,6 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
        StructRNA *srna;
        PropertyRNA *prop;
 
-       static EnumPropertyItem prop_falloff_items[] = {
-               {eWarp_Falloff_None,    "NONE", 0, "No Falloff", ""},
-               {eWarp_Falloff_Curve,   "CURVE", 0, "Curve", ""},
-               {eWarp_Falloff_Smooth,  "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
-               {eWarp_Falloff_Sphere,  "SPHERE", ICON_SPHERECURVE, "Sphere", ""},
-               {eWarp_Falloff_Root,    "ROOT", ICON_ROOTCURVE, "Root", ""},
-               {eWarp_Falloff_InvSquare, "INVERSE_SQUARE", ICON_ROOTCURVE, "Inverse Square", ""},
-               {eWarp_Falloff_Sharp,   "SHARP", ICON_SHARPCURVE, "Sharp", ""},
-               {eWarp_Falloff_Linear,  "LINEAR", ICON_LINCURVE, "Linear", ""},
-               {eWarp_Falloff_Const,   "CONSTANT", ICON_NOCURVE, "Constant", ""},
-               {0, NULL, 0, NULL, NULL}
-       };
-
        srna = RNA_def_struct(brna, "WarpModifier", "Modifier");
        RNA_def_struct_ui_text(srna, "Warp Modifier", "Warp modifier");
        RNA_def_struct_sdna(srna, "WarpModifierData");
@@ -1146,7 +1149,7 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
        prop = RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_items(prop, prop_falloff_items);
+       RNA_def_property_enum_items(prop, modifier_warp_falloff_items);
        RNA_def_property_ui_text(prop, "Falloff Type", "");
        RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
@@ -1678,15 +1681,28 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
        RNA_def_struct_sdna(srna, "HookModifierData");
        RNA_def_struct_ui_icon(srna, ICON_HOOK);
 
-       prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_DISTANCE);
+       prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "force");
+       RNA_def_property_range(prop, 0, 1);
+       RNA_def_property_ui_text(prop, "Strength",  "Relative force of the hook");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+       prop = RNA_def_property(srna, "falloff_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, modifier_warp_falloff_items);  /* share the enum */
+       RNA_def_property_ui_text(prop, "Falloff Type", "");
+       RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+       prop = RNA_def_property(srna, "falloff_radius", PROP_FLOAT, PROP_DISTANCE);
+       RNA_def_property_float_sdna(prop, NULL, "falloff");
        RNA_def_property_range(prop, 0, FLT_MAX);
        RNA_def_property_ui_range(prop, 0, 100, 100, 2);
-       RNA_def_property_ui_text(prop, "Falloff",  "If not zero, the distance from the hook where influence ends");
+       RNA_def_property_ui_text(prop, "Radius",  "If not zero, the distance from the hook where influence ends");
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
-       prop = RNA_def_property(srna, "force", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_range(prop, 0, 1);
-       RNA_def_property_ui_text(prop, "Force",  "Relative force of the hook");
+       prop = RNA_def_property(srna, "falloff_curve", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "curfalloff");
+       RNA_def_property_ui_text(prop, "Falloff Curve", "Custom Lamp Falloff Curve");
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
        prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_NONE);
@@ -1706,6 +1722,11 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
                                 "Name of Parent Bone for hook (if applicable), also recalculates and clears offset");
        RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
 
+       prop = RNA_def_property(srna, "use_falloff_uniform", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_HOOK_UNIFORM_SPACE);
+       RNA_def_property_ui_text(prop, "Uniform Falloff", "Compensate for non-uniform object scale");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
        prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
        RNA_def_property_string_sdna(prop, NULL, "name");
        RNA_def_property_ui_text(prop, "Vertex Group",
index f6d7c03df326763c2ef9a08b0d43fd31a186f994..2b512a6ba253bf76f8d212cc34ba5f932e81b35a 100644 (file)
@@ -43,6 +43,7 @@
 #include "BKE_cdderivedmesh.h"
 #include "BKE_modifier.h"
 #include "BKE_deform.h"
+#include "BKE_colortools.h"
 
 
 #include "depsgraph_private.h"
@@ -55,6 +56,9 @@ static void initData(ModifierData *md)
        HookModifierData *hmd = (HookModifierData *) md;
 
        hmd->force = 1.0;
+       hmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+       hmd->falloff_type = eHook_Falloff_Smooth;
+       hmd->flag = 0;
 }
 
 static void copyData(ModifierData *md, ModifierData *target)
@@ -64,6 +68,8 @@ static void copyData(ModifierData *md, ModifierData *target)
 
        modifier_copyData_generic(md, target);
 
+       thmd->curfalloff = curvemapping_copy(hmd->curfalloff);
+
        thmd->indexar = MEM_dupallocN(hmd->indexar);
 }
 
@@ -83,6 +89,8 @@ static void freeData(ModifierData *md)
 {
        HookModifierData *hmd = (HookModifierData *) md;
 
+       curvemapping_free(hmd->curfalloff);
+
        if (hmd->indexar) MEM_freeN(hmd->indexar);
 }
 
@@ -120,32 +128,172 @@ static void updateDepgraph(ModifierData *md, DagForest *forest,
        }
 }
 
-static float hook_falloff(const float co_1[3], const float co_2[3], const float falloff_squared, float fac)
+struct HookData_cb {
+       float (*vertexCos)[3];
+
+       MDeformVert *dvert;
+       int defgrp_index;
+
+       struct CurveMapping *curfalloff;
+
+       char  falloff_type;
+       float falloff;
+       float falloff_sq;
+       float fac_orig;
+
+       unsigned int use_falloff        : 1;
+       unsigned int use_uniform        : 1;
+
+       float cent[3];
+
+       float mat_uniform[3][3];
+       float mat[4][4];
+};
+
+static float hook_falloff(
+        const struct HookData_cb *hd,
+        const float len_sq)
+{
+       BLI_assert(hd->falloff_sq);
+       if (len_sq > hd->falloff_sq) {
+               return 0.0f;
+       }
+       else if (len_sq > 0.0f) {
+               float fac;
+
+               if (hd->falloff_type == eHook_Falloff_Const) {
+                       fac = 1.0f;
+                       goto finally;
+               }
+               else if (hd->falloff_type == eHook_Falloff_InvSquare) {
+                       /* avoid sqrt below */
+                       fac = 1.0f - (len_sq / hd->falloff_sq);
+                       goto finally;
+               }
+
+               fac = 1.0f - (sqrtf(len_sq) / hd->falloff);
+
+               /* closely match PROP_SMOOTH and similar */
+               switch (hd->falloff_type) {
+#if 0
+                       case eHook_Falloff_None:
+                               fac = 1.0f;
+                               break;
+#endif
+                       case eHook_Falloff_Curve:
+                               fac = curvemapping_evaluateF(hd->curfalloff, 0, fac);
+                               break;
+                       case eHook_Falloff_Sharp:
+                               fac = fac * fac;
+                               break;
+                       case eHook_Falloff_Smooth:
+                               fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
+                               break;
+                       case eHook_Falloff_Root:
+                               fac = sqrtf(fac);
+                               break;
+                       case eHook_Falloff_Linear:
+                               /* pass */
+                               break;
+#if 0
+                       case eHook_Falloff_Const:
+                               fac = 1.0f;
+                               break;
+#endif
+                       case eHook_Falloff_Sphere:
+                               fac = sqrtf(2 * fac - fac * fac);
+                               break;
+#if 0
+                       case eHook_Falloff_InvSquare:
+                               fac = fac * (2.0f - fac);
+                               break;
+#endif
+               }
+
+finally:
+               return fac * hd->fac_orig;
+       }
+       else {
+               return hd->fac_orig;
+       }
+}
+
+static void hook_co_apply(struct HookData_cb *hd, const int j)
 {
-       if (falloff_squared) {
-               float len_squared = len_squared_v3v3(co_1, co_2);
-               if (len_squared > falloff_squared) {
-                       return 0.0f;
+       float *co = hd->vertexCos[j];
+       float fac;
+
+       if (hd->use_falloff) {
+               float len_sq;
+
+               if (hd->use_uniform) {
+                       float co_uniform[3];
+                       mul_v3_m3v3(co_uniform, hd->mat_uniform, co);
+                       len_sq = len_squared_v3v3(hd->cent, co_uniform);
                }
-               else if (len_squared > 0.0f) {
-                       return fac * (1.0f - (len_squared / falloff_squared));
+               else {
+                       len_sq = len_squared_v3v3(hd->cent, co);
                }
+
+               fac = hook_falloff(hd, len_sq);
        }
+       else {
+               fac = hd->fac_orig;
+       }
+
+       if (fac) {
+               if (hd->dvert) {
+                       fac *= defvert_find_weight(&hd->dvert[j], hd->defgrp_index);
+               }
 
-       return fac;
+               if (fac) {
+                       float co_tmp[3];
+                       mul_v3_m4v3(co_tmp, hd->mat, co);
+                       interp_v3_v3v3(co, co, co_tmp, fac);
+               }
+       }
 }
 
 static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
                            float (*vertexCos)[3], int numVerts)
 {
        bPoseChannel *pchan = BKE_pose_channel_find_name(hmd->object->pose, hmd->subtarget);
-       float vec[3], mat[4][4], dmat[4][4];
+       float dmat[4][4];
        int i, *index_pt;
-       const float falloff_squared = hmd->falloff * hmd->falloff; /* for faster comparisons */
-       
-       MDeformVert *dvert;
-       int defgrp_index, max_dvert;
+       struct HookData_cb hd;
        
+       if (hmd->curfalloff == NULL) {
+               /* should never happen, but bad lib linking could cause it */
+               hmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+       }
+
+       if (hmd->curfalloff) {
+               curvemapping_initialize(hmd->curfalloff);
+       }
+
+       /* Generic data needed for applying per-vertex calculations (initialize all members) */
+       hd.vertexCos = vertexCos;
+       modifier_get_vgroup(ob, dm, hmd->name, &hd.dvert, &hd.defgrp_index);
+
+       hd.curfalloff = hmd->curfalloff;
+
+       hd.falloff_type = hmd->falloff_type;
+       hd.falloff = (hmd->falloff_type == eHook_Falloff_None) ? 0.0f : hmd->falloff;
+       hd.falloff_sq = SQUARE(hd.falloff);
+       hd.fac_orig = hmd->force;
+
+       hd.use_falloff = (hd.falloff_sq != 0.0f);
+       hd.use_uniform = (hmd->flag & MOD_HOOK_UNIFORM_SPACE) != 0;
+
+       if (hd.use_uniform) {
+               copy_m3_m4(hd.mat_uniform, hmd->parentinv);
+               mul_v3_m3v3(hd.cent, hd.mat_uniform, hmd->cent);
+       }
+       else {
+               unit_m3(hd.mat_uniform);  /* unused */
+               copy_v3_v3(hd.cent, hmd->cent);
+       }
+
        /* get world-space matrix of target, corrected for the space the verts are in */
        if (hmd->subtarget[0] && pchan) {
                /* bone target if there's a matching pose-channel */
@@ -156,10 +304,9 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
                copy_m4_m4(dmat, hmd->object->obmat);
        }
        invert_m4_m4(ob->imat, ob->obmat);
-       mul_m4_series(mat, ob->imat, dmat, hmd->parentinv);
+       mul_m4_series(hd.mat, ob->imat, dmat, hmd->parentinv);
+       /* --- done with 'hd' init --- */
 
-       modifier_get_vgroup(ob, dm, hmd->name, &dvert, &defgrp_index);
-       max_dvert = (dvert) ? numVerts : 0;
 
        /* Regarding index range checking below.
         *
@@ -168,13 +315,11 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
         * indices that are out of range because old blender did
         * not correct them on exit editmode. - zr
         */
-       
+
        if (hmd->force == 0.0f) {
                /* do nothing, avoid annoying checks in the loop */
        }
        else if (hmd->indexar) { /* vertex indices? */
-               const float fac_orig = hmd->force;
-               float fac;
                const int *origindex_ar;
                
                /* if DerivedMesh is present and has original index data, use it */
@@ -185,16 +330,7 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
                                        
                                        for (j = 0; j < numVerts; j++) {
                                                if (origindex_ar[j] == *index_pt) {
-                                                       float *co = vertexCos[j];
-                                                       if ((fac = hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
-                                                               if (dvert)
-                                                                       fac *= defvert_find_weight(dvert + j, defgrp_index);
-                                                               
-                                                               if (fac) {
-                                                                       mul_v3_m4v3(vec, mat, co);
-                                                                       interp_v3_v3v3(co, co, vec, fac);
-                                                               }
-                                                       }
+                                                       hook_co_apply(&hd, j);
                                                }
                                        }
                                }
@@ -203,34 +339,14 @@ static void deformVerts_do(HookModifierData *hmd, Object *ob, DerivedMesh *dm,
                else { /* missing dm or ORIGINDEX */
                        for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) {
                                if (*index_pt < numVerts) {
-                                       float *co = vertexCos[*index_pt];
-                                       if ((fac = hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
-                                               if (dvert)
-                                                       fac *= defvert_find_weight(dvert + (*index_pt), defgrp_index);
-                                               
-                                               if (fac) {
-                                                       mul_v3_m4v3(vec, mat, co);
-                                                       interp_v3_v3v3(co, co, vec, fac);
-                                               }
-                                       }
+                                       hook_co_apply(&hd, *index_pt);
                                }
                        }
                }
        }
-       else if (dvert) {  /* vertex group hook */
-               const float fac_orig = hmd->force;
-               
-               for (i = 0; i < max_dvert; i++, dvert++) {
-                       float fac;
-                       float *co = vertexCos[i];
-                       
-                       if ((fac = hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
-                               fac *= defvert_find_weight(dvert, defgrp_index);
-                               if (fac) {
-                                       mul_v3_m4v3(vec, mat, co);
-                                       interp_v3_v3v3(co, co, vec, fac);
-                               }
-                       }
+       else if (hd.dvert) {  /* vertex group hook */
+               for (i = 0; i < numVerts; i++) {
+                       hook_co_apply(&hd, i);
                }
        }
 }