[#14437] Modifier Stack Refactor
authorCampbell Barton <ideasman42@gmail.com>
Sun, 11 Apr 2010 22:12:30 +0000 (22:12 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 11 Apr 2010 22:12:30 +0000 (22:12 +0000)
patch by Ben Batt (artificer)

Updated patch for 6 or so modifiers added since the patch was written.

- tested with CMake and SCons
- fixed one error were flags were being added to the fluids type.
- remove BKE_simple_deform.h, simple_deform.c, move functions into MOD_simpledeform.c since there were problems with circular deps.
- moved some fluid and boolean functions used by modifiers too.

57 files changed:
source/blender/CMakeLists.txt
source/blender/Makefile
source/blender/SConscript
source/blender/blenkernel/BKE_booleanops.h
source/blender/blenkernel/BKE_fluidsim.h
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/booleanops.c
source/blender/blenkernel/intern/fluidsim.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/simple_deform.c [deleted file]
source/blender/modifiers/CMakeLists.txt [new file with mode: 0644]
source/blender/modifiers/MOD_modifiertypes.h [new file with mode: 0644]
source/blender/modifiers/Makefile [new file with mode: 0644]
source/blender/modifiers/SConscript [new file with mode: 0644]
source/blender/modifiers/intern/MOD_armature.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_array.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_bevel.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_boolean.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_boolean_util.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_boolean_util.h [new file with mode: 0644]
source/blender/modifiers/intern/MOD_build.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_cast.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_cloth.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_collision.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_curve.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_decimate.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_displace.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_edgesplit.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_explode.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_fluidsim.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_fluidsim_util.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_fluidsim_util.h [moved from source/blender/blenkernel/BKE_simple_deform.h with 63% similarity]
source/blender/modifiers/intern/MOD_hook.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_lattice.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_mask.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_meshdeform.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_mirror.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_multires.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_none.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_particleinstance.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_particlesystem.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_screw.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_shapekey.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_shrinkwrap.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_simpledeform.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_smoke.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_smooth.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_softbody.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_solidify.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_subsurf.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_surface.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_util.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_util.h [new file with mode: 0644]
source/blender/modifiers/intern/MOD_uvproject.c [new file with mode: 0644]
source/blender/modifiers/intern/MOD_wave.c [new file with mode: 0644]
source/creator/CMakeLists.txt

index 6263261ae1c413b871dc5dda90bade38d8aae809..164377373027a6d4ce6692f2379fa126be910150 100644 (file)
@@ -29,6 +29,7 @@ ADD_SUBDIRECTORY(editors)
 ADD_SUBDIRECTORY(avi)
 ADD_SUBDIRECTORY(nodes)
 ADD_SUBDIRECTORY(blenkernel)
+ADD_SUBDIRECTORY(modifiers)
 ADD_SUBDIRECTORY(blenlib)
 ADD_SUBDIRECTORY(blenloader)
 ADD_SUBDIRECTORY(blenpluginapi)
index 1c4ff6935b9948802f0830c812040792b941732c..1149e1c4be254239c976ca1e06f1ac8a9d7c965f 100644 (file)
@@ -33,7 +33,7 @@ include nan_definitions.mk
 DIRS = windowmanager editors blenloader readblenfile
 DIRS += avi imbuf render blenlib blenkernel blenpluginapi
 DIRS += makesdna makesrna
-DIRS += python nodes gpu
+DIRS += python nodes modifiers gpu
 DIRS += blenfont ikplugin
 
 ifeq ($(WITH_QUICKTIME), true)
index 9910db1902f0eb3934d4d58d0dc5325ef5a56b04..98e8ad73199a41ae670c432660621423386b3adb 100644 (file)
@@ -16,6 +16,7 @@ SConscript(['avi/SConscript',
             'readblenfile/SConscript',
             'render/SConscript',
             'nodes/SConscript',
+            'modifiers/SConscript',
             'ikplugin/SConscript',
             'windowmanager/SConscript',
             'blenfont/SConscript'])
index dcf71645db38e16016decfbb2cd80b263bed34e6..a213d63cc0364e08cb4534c635d1a1314d530129 100644 (file)
 #ifndef BKE_BOOLEANOPS_H
 #define BKE_BOOLEANOPS_H
 
-struct Scene;
-struct Object;
-struct Base;
-struct DerivedMesh;
-
-/* Performs a boolean between two mesh objects, it is assumed that both objects
-   are in fact a mesh object. On success returns 1 and creates a new mesh object
-   into blender data structures. On failure returns 0 and reports an error. */
-int NewBooleanMesh(struct Scene *scene, struct Base *base, struct Base *base_select, int op);
-
-
-/* Performs a boolean between two mesh objects, it is assumed that both objects
-   are in fact mesh object. On success returns a DerivedMesh. On failure
-   returns NULL and reports an error. */
-struct DerivedMesh *NewBooleanDerivedMesh(struct DerivedMesh *dm, struct Object *ob, struct DerivedMesh *dm_select, struct Object *ob_select,
-                                                                  int int_op_type);
 #endif
 
index d99e7b42cff3d3f8d5a3ad6aac487d02a259c170..da43ae7f28b4450b8136695e1bf366c00b0dd289 100644 (file)
@@ -30,6 +30,7 @@
 #ifndef BKE_FLUIDSIM_H
 #define BKE_FLUIDSIM_H
 
+
 struct Object;
 struct Scene;
 struct FluidsimModifierData;
@@ -37,25 +38,12 @@ struct DerivedMesh;
 struct MVert;
 
 /* old interface */
-struct FluidsimSettings *fluidsimSettingsNew(struct Object *srcob);
 
 void initElbeemMesh(struct Scene *scene, struct Object *ob,
        int *numVertices, float **vertices,
        int *numTriangles, int **triangles,
        int useGlobalCoords, int modifierIndex);
 
-/* new fluid-modifier interface */
-void fluidsim_init(struct FluidsimModifierData *fluidmd);
-void fluidsim_free(struct FluidsimModifierData *fluidmd);
-
-struct DerivedMesh *fluidsim_read_cache(struct Object *ob, struct DerivedMesh *orgdm,
-       struct FluidsimModifierData *fluidmd, int framenr, int useRenderParams);
-void fluidsim_read_vel_cache(struct FluidsimModifierData *fluidmd, struct DerivedMesh *dm,
-       char *filename);
-struct DerivedMesh *fluidsimModifier_do(struct FluidsimModifierData *fluidmd,
-       struct Scene *scene, struct Object *ob, struct DerivedMesh *dm,
-       int useRenderParams, int isFinalCalc);
-
 /* bounding box & memory estimate */
 void fluid_get_bb(struct MVert *mvert, int totvert, float obmat[][4],
                 float start[3], float size[3]);
index da5e73bbb45043336f2f0b10e850b1922537bc83..afb29fbcd628319ddd401156f9b81e4fb37ac216 100644 (file)
@@ -27,7 +27,7 @@
 FILE(GLOB SRC intern/*.c)
 
 SET(INC 
-       . ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna
+       . ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna ../modifiers
        ../render/extern/include ../../../intern/decimation/extern
        ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern
        ../../../intern/iksolver/extern ../blenloader ../ikplugin
@@ -38,6 +38,7 @@ SET(INC
        ${ZLIB_INC}
 )
 
+
 ADD_DEFINITIONS(-DGLEW_STATIC)
 
 IF(WITH_BULLET)
index 37a63be6389bbdc30074b5bac3d8d3750f63257e..57d7e45d986545d03a0ddf3e9ba5cf9b74bd0d00 100644 (file)
@@ -6,7 +6,7 @@ sources = env.Glob('intern/*.c')
 incs = '. #/intern/guardedalloc #/intern/memutil ../editors/include'
 incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager'
 incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna'
-incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes'
+incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers'
 incs += ' #/intern/iksolver/extern ../blenloader'
 incs += ' #/extern/bullet2/src'
 incs += ' #/intern/opennl/extern #/intern/bsp/extern'
index 3e43dfbb4d545e1d3fd9549bfd7fae41396c6132..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,595 +0,0 @@
-/**
- * $Id$
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) Blender Foundation
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- * CSG operations. 
- */
-
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_math.h"
-#include "BLI_ghash.h"
-
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
-#include "CSG_BooleanOps.h"
-
-#include "BKE_cdderivedmesh.h"
-#include "BKE_depsgraph.h"
-#include "BKE_material.h"
-#include "BKE_mesh.h"
-#include "BKE_object.h"
-
-
-
-/**
- * Here's the vertex iterator structure used to walk through
- * the blender vertex structure.
- */
-
-typedef struct {
-       DerivedMesh *dm;
-       Object *ob;
-       int pos;
-} VertexIt;
-
-/**
- * Implementations of local vertex iterator functions.
- * These describe a blender mesh to the CSG module.
- */
-
-static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator)
-{
-       if (iterator->it) {
-               // deallocate memory for iterator
-               MEM_freeN(iterator->it);
-               iterator->it = 0;
-       }
-       iterator->Done = NULL;
-       iterator->Fill = NULL;
-       iterator->Reset = NULL;
-       iterator->Step = NULL;
-       iterator->num_elements = 0;
-
-}              
-
-static int VertexIt_Done(CSG_IteratorPtr it)
-{
-       VertexIt * iterator = (VertexIt *)it;
-       return(iterator->pos >= iterator->dm->getNumVerts(iterator->dm));
-}
-
-static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert)
-{
-       VertexIt * iterator = (VertexIt *)it;
-       MVert *verts = iterator->dm->getVertArray(iterator->dm);
-
-       float global_pos[3];
-
-       /* boolean happens in global space, transform both with obmat */
-       mul_v3_m4v3(
-               global_pos,
-               iterator->ob->obmat, 
-               verts[iterator->pos].co
-       );
-
-       vert->position[0] = global_pos[0];
-       vert->position[1] = global_pos[1];
-       vert->position[2] = global_pos[2];
-}
-
-static void VertexIt_Step(CSG_IteratorPtr it)
-{
-       VertexIt * iterator = (VertexIt *)it;
-       iterator->pos ++;
-} 
-static void VertexIt_Reset(CSG_IteratorPtr it)
-{
-       VertexIt * iterator = (VertexIt *)it;
-       iterator->pos = 0;
-}
-
-static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, DerivedMesh *dm, Object *ob)
-{
-
-       VertexIt *it;
-       if (output == 0) return;
-
-       // allocate some memory for blender iterator
-       it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt),"Boolean_VIt"));
-       if (it == 0) {
-               return;
-       }
-       // assign blender specific variables
-       it->dm = dm;
-       it->ob = ob; // needed for obmat transformations 
-       
-       it->pos = 0;
-
-        // assign iterator function pointers.
-       output->Step = VertexIt_Step;
-       output->Fill = VertexIt_Fill;
-       output->Done = VertexIt_Done;
-       output->Reset = VertexIt_Reset;
-       output->num_elements = it->dm->getNumVerts(it->dm);
-       output->it = it;
-}
-
-/**
- * Blender Face iterator
- */
-
-typedef struct {
-       DerivedMesh *dm;
-       int pos;
-       int offset;
-       int flip;
-} FaceIt;
-
-static void FaceIt_Destruct(CSG_FaceIteratorDescriptor * iterator)
-{
-       MEM_freeN(iterator->it);
-       iterator->Done = NULL;
-       iterator->Fill = NULL;
-       iterator->Reset = NULL;
-       iterator->Step = NULL;
-       iterator->num_elements = 0;
-}
-
-static int FaceIt_Done(CSG_IteratorPtr it)
-{
-       // assume CSG_IteratorPtr is of the correct type.
-       FaceIt * iterator = (FaceIt *)it;
-       return(iterator->pos >= iterator->dm->getNumFaces(iterator->dm));
-}
-
-static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face)
-{
-       // assume CSG_IteratorPtr is of the correct type.
-       FaceIt *face_it = (FaceIt *)it;
-       MFace *mfaces = face_it->dm->getFaceArray(face_it->dm);
-       MFace *mface = &mfaces[face_it->pos];
-
-       /* reverse face vertices if necessary */
-       face->vertex_index[1] = mface->v2;
-       if( face_it->flip == 0 ) {
-       face->vertex_index[0] = mface->v1;
-       face->vertex_index[2] = mface->v3;
-       } else {
-               face->vertex_index[2] = mface->v1;
-               face->vertex_index[0] = mface->v3;
-       }
-       if (mface->v4) {
-               face->vertex_index[3] = mface->v4;
-               face->vertex_number = 4;
-       } else {
-               face->vertex_number = 3;
-       }
-
-       face->orig_face = face_it->offset + face_it->pos;
-}
-
-static void FaceIt_Step(CSG_IteratorPtr it)
-{
-       FaceIt * face_it = (FaceIt *)it;                
-       face_it->pos ++;
-}
-
-static void FaceIt_Reset(CSG_IteratorPtr it)
-{
-       FaceIt * face_it = (FaceIt *)it;                
-       face_it->pos = 0;
-}      
-
-static void FaceIt_Construct(
-       CSG_FaceIteratorDescriptor *output, DerivedMesh *dm, int offset, Object *ob)
-{
-       FaceIt *it;
-       if (output == 0) return;
-
-       // allocate some memory for blender iterator
-       it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt),"Boolean_FIt"));
-       if (it == 0) {
-               return ;
-       }
-       // assign blender specific variables
-       it->dm = dm;
-       it->offset = offset;
-       it->pos = 0;
-
-       /* determine if we will need to reverse order of face vertices */
-       if (ob->size[0] < 0.0f) {
-               if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) {
-                       it->flip = 1;
-               } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) {
-                       it->flip = 1;
-               } else {
-                       it->flip = 0;
-               }
-       } else {
-               if (ob->size[1] < 0.0f && ob->size[2] < 0.0f) {
-                       it->flip = 0;
-               } else if (ob->size[1] >= 0.0f && ob->size[2] >= 0.0f) {
-                       it->flip = 0;
-               } else {
-                       it->flip = 1;
-               }
-       }
-
-       // assign iterator function pointers.
-       output->Step = FaceIt_Step;
-       output->Fill = FaceIt_Fill;
-       output->Done = FaceIt_Done;
-       output->Reset = FaceIt_Reset;
-       output->num_elements = it->dm->getNumFaces(it->dm);
-       output->it = it;
-}
-
-static Object *AddNewBlenderMesh(Scene *scene, Base *base)
-{
-       // This little function adds a new mesh object to the blender object list
-       // It uses ob to duplicate data as this seems to be easier than creating
-       // a new one. This new oject contains no faces nor vertices.
-       Mesh *old_me;
-       Base *basen;
-       Object *ob_new;
-
-       // now create a new blender object.
-       // duplicating all the settings from the previous object
-       // to the new one.
-       ob_new= copy_object(base->object);
-
-       // Ok we don't want to use the actual data from the
-       // last object, the above function incremented the 
-       // number of users, so decrement it here.
-       old_me= ob_new->data;
-       old_me->id.us--;
-
-       // Now create a new base to add into the linked list of 
-       // vase objects.
-       
-       basen= MEM_mallocN(sizeof(Base), "duplibase");
-       *basen= *base;
-       BLI_addhead(&scene->base, basen);       /* addhead: anders oneindige lus */
-       basen->object= ob_new;
-       basen->flag &= ~SELECT;
-                               
-       // Initialize the mesh data associated with this object.                                                
-       ob_new->data= add_mesh("Mesh");
-
-       // Finally assign the object type.
-       ob_new->type= OB_MESH;
-
-       return ob_new;
-}
-
-static void InterpCSGFace(
-       DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr,
-       float mapmat[][4])
-{
-       float obco[3], *co[4], *orig_co[4], w[4][4];
-       MFace *mface, *orig_mface;
-       int j;
-
-       mface = CDDM_get_face(dm, index);
-       orig_mface = orig_dm->getFaceArray(orig_dm) + orig_index;
-
-       // get the vertex coordinates from the original mesh
-       orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co;
-       orig_co[1] = (orig_dm->getVertArray(orig_dm) + orig_mface->v2)->co;
-       orig_co[2] = (orig_dm->getVertArray(orig_dm) + orig_mface->v3)->co;
-       orig_co[3] = (orig_mface->v4)? (orig_dm->getVertArray(orig_dm) + orig_mface->v4)->co: NULL;
-
-       // get the vertex coordinates from the new derivedmesh
-       co[0] = CDDM_get_vert(dm, mface->v1)->co;
-       co[1] = CDDM_get_vert(dm, mface->v2)->co;
-       co[2] = CDDM_get_vert(dm, mface->v3)->co;
-       co[3] = (nr == 4)? CDDM_get_vert(dm, mface->v4)->co: NULL;
-
-       for (j = 0; j < nr; j++) {
-               // get coordinate into the space of the original mesh
-               if (mapmat)
-                       mul_v3_m4v3(obco, mapmat, co[j]);
-               else
-                       copy_v3_v3(obco, co[j]);
-
-               interp_weights_face_v3( w[j],orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco);
-       }
-
-       CustomData_interp(&orig_dm->faceData, &dm->faceData, &orig_index, NULL, (float*)w, 1, index);
-}
-
-/* Iterate over the CSG Output Descriptors and create a new DerivedMesh
-   from them */
-static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
-       CSG_FaceIteratorDescriptor *face_it,
-       CSG_VertexIteratorDescriptor *vertex_it,
-       float parinv[][4],
-       float mapmat[][4],
-       Material **mat,
-       int *totmat,
-       DerivedMesh *dm1,
-       Object *ob1,
-       DerivedMesh *dm2,
-       Object *ob2)
-{
-       DerivedMesh *result, *orig_dm;
-       GHash *material_hash = NULL;
-       Mesh *me1= (Mesh*)ob1->data;
-       Mesh *me2= (Mesh*)ob2->data;
-       int i;
-
-       // create a new DerivedMesh
-       result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
-       CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
-                                         CD_DEFAULT, face_it->num_elements); 
-       CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH,
-                                         CD_DEFAULT, face_it->num_elements); 
-
-       // step through the vertex iterators:
-       for (i = 0; !vertex_it->Done(vertex_it->it); i++) {
-               CSG_IVertex csgvert;
-               MVert *mvert = CDDM_get_vert(result, i);
-
-               // retrieve a csg vertex from the boolean module
-               vertex_it->Fill(vertex_it->it, &csgvert);
-               vertex_it->Step(vertex_it->it);
-
-               // we have to map the vertex coordinates back in the coordinate frame
-               // of the resulting object, since it was computed in world space
-               mul_v3_m4v3(mvert->co, parinv, csgvert.position);
-       }
-
-       // a hash table to remap materials to indices
-       if (mat) {
-               material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
-               *totmat = 0;
-       }
-
-       // step through the face iterators
-       for(i = 0; !face_it->Done(face_it->it); i++) {
-               Mesh *orig_me;
-               Object *orig_ob;
-               Material *orig_mat;
-               CSG_IFace csgface;
-               MFace *mface;
-               int orig_index, mat_nr;
-
-               // retrieve a csg face from the boolean module
-               face_it->Fill(face_it->it, &csgface);
-               face_it->Step(face_it->it);
-
-               // find the original mesh and data
-               orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2;
-               orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2;
-               orig_me = (orig_ob == ob1)? me1: me2;
-               orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1);
-
-               // copy all face layers, including mface
-               CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1);
-
-               // set mface
-               mface = CDDM_get_face(result, i);
-               mface->v1 = csgface.vertex_index[0];
-               mface->v2 = csgface.vertex_index[1];
-               mface->v3 = csgface.vertex_index[2];
-               mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0;
-
-               // set material, based on lookup in hash table
-               orig_mat= give_current_material(orig_ob, mface->mat_nr+1);
-
-               if (mat && orig_mat) {
-                       if (!BLI_ghash_haskey(material_hash, orig_mat)) {
-                               mat[*totmat] = orig_mat;
-                               mat_nr = mface->mat_nr = (*totmat)++;
-                               BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr));
-                       }
-                       else
-                               mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat));
-               }
-               else
-                       mface->mat_nr = 0;
-
-               InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number,
-                                         (orig_me == me2)? mapmat: NULL);
-
-               test_index_face(mface, &result->faceData, i, csgface.vertex_number);
-       }
-
-       if (material_hash)
-               BLI_ghash_free(material_hash, NULL, NULL);
-
-       CDDM_calc_edges(result);
-       CDDM_calc_normals(result);
-
-       return result;
-}
-       
-static void BuildMeshDescriptors(
-       struct DerivedMesh *dm,
-       struct Object *ob,
-       int face_offset,
-       struct CSG_FaceIteratorDescriptor * face_it,
-       struct CSG_VertexIteratorDescriptor * vertex_it)
-{
-       VertexIt_Construct(vertex_it,dm, ob);
-       FaceIt_Construct(face_it,dm,face_offset,ob);
-}
-       
-static void FreeMeshDescriptors(
-       struct CSG_FaceIteratorDescriptor *face_it,
-       struct CSG_VertexIteratorDescriptor *vertex_it)
-{
-       VertexIt_Destruct(vertex_it);
-       FaceIt_Destruct(face_it);
-}
-
-DerivedMesh *NewBooleanDerivedMesh_intern(
-       DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
-       int int_op_type, Material **mat, int *totmat)
-{
-
-       float inv_mat[4][4];
-       float map_mat[4][4];
-
-       DerivedMesh *result = NULL;
-
-       if (dm == NULL || dm_select == NULL) return 0;
-       if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) return 0;
-
-       // we map the final object back into ob's local coordinate space. For this
-       // we need to compute the inverse transform from global to ob (inv_mat),
-       // and the transform from ob to ob_select for use in interpolation (map_mat)
-       invert_m4_m4(inv_mat, ob->obmat);
-       mul_m4_m4m4(map_mat, ob_select->obmat, inv_mat);
-       invert_m4_m4(inv_mat, ob_select->obmat);
-
-       {
-               // interface with the boolean module:
-               //
-               // the idea is, we pass the boolean module verts and faces using the
-               // provided descriptors. once the boolean operation is performed, we
-               // get back output descriptors, from which we then build a DerivedMesh
-
-               CSG_VertexIteratorDescriptor vd_1, vd_2;
-               CSG_FaceIteratorDescriptor fd_1, fd_2;
-               CSG_OperationType op_type;
-               CSG_BooleanOperation *bool_op;
-
-               // work out the operation they chose and pick the appropriate 
-               // enum from the csg module.
-               switch (int_op_type) {
-                       case 1 : op_type = e_csg_intersection; break;
-                       case 2 : op_type = e_csg_union; break;
-                       case 3 : op_type = e_csg_difference; break;
-                       case 4 : op_type = e_csg_classify; break;
-                       default : op_type = e_csg_intersection;
-               }
-               
-               BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1);
-               BuildMeshDescriptors(dm, ob, dm_select->getNumFaces(dm_select) , &fd_2, &vd_2);
-
-               bool_op = CSG_NewBooleanFunction();
-
-               // perform the operation
-               if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) {
-                       CSG_VertexIteratorDescriptor vd_o;
-                       CSG_FaceIteratorDescriptor fd_o;
-
-                       CSG_OutputFaceDescriptor(bool_op, &fd_o);
-                       CSG_OutputVertexDescriptor(bool_op, &vd_o);
-
-                       // iterate through results of operation and insert
-                       // into new object
-                       result = ConvertCSGDescriptorsToDerivedMesh(
-                               &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob);
-
-                       // free up the memory
-                       CSG_FreeVertexDescriptor(&vd_o);
-                       CSG_FreeFaceDescriptor(&fd_o);
-               }
-               else
-                       printf("Unknown internal error in boolean");
-
-               CSG_FreeBooleanOperation(bool_op);
-
-               FreeMeshDescriptors(&fd_1, &vd_1);
-               FreeMeshDescriptors(&fd_2, &vd_2);
-       }
-
-       return result;
-}
-
-int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type)
-{
-       Mesh *me_new;
-       int a, maxmat, totmat= 0;
-       Object *ob_new, *ob, *ob_select;
-       Material **mat;
-       DerivedMesh *result;
-       DerivedMesh *dm_select;
-       DerivedMesh *dm;
-
-       ob= base->object;
-       ob_select= base_select->object;
-
-       dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
-       dm_select = mesh_create_derived_view(scene, ob_select, 0); // no modifiers in editmode ??
-
-       maxmat= ob->totcol + ob_select->totcol;
-       mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat");
-       
-       /* put some checks in for nice user feedback */
-       if (dm == NULL || dm_select == NULL) return 0;
-       if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select))
-       {
-               MEM_freeN(mat);
-               return -1;
-       }
-       
-       result= NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat);
-
-       if (result == NULL) {
-               MEM_freeN(mat);
-               return 0;
-       }
-
-       /* create a new blender mesh object - using 'base' as  a template */
-       ob_new= AddNewBlenderMesh(scene, base_select);
-       me_new= ob_new->data;
-
-       DM_to_mesh(result, me_new);
-       result->release(result);
-
-       dm->release(dm);
-       dm_select->release(dm_select);
-
-       /* add materials to object */
-       for (a = 0; a < totmat; a++)
-               assign_material(ob_new, mat[a], a+1);
-
-       MEM_freeN(mat);
-
-       /* update dag */
-       DAG_id_flush_update(&ob_new->id, OB_RECALC_DATA);
-
-       return 1;
-}
-
-DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select,
-                                                                  int int_op_type)
-{
-       return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL);
-}
-
index 118a44507c98361c4e409fa32f82b74475bba462..8a6f0af87d1dae5b4f9789e4fdf5d5db2b1fafa8 100644 (file)
 
 /* ************************* fluidsim bobj file handling **************************** */
 
-// -----------------------------------------
-// forward decleration
-// -----------------------------------------
-
-// -----------------------------------------
-
-void fluidsim_init(FluidsimModifierData *fluidmd)
-{
-#ifndef DISABLE_ELBEEM
-       if(fluidmd)
-       {
-               FluidsimSettings *fss = MEM_callocN(sizeof(FluidsimSettings), "fluidsimsettings");
-               
-               fluidmd->fss = fss;
-               
-               if(!fss)
-                       return;
-               
-               fss->fmd = fluidmd;
-               fss->type = OB_FLUIDSIM_ENABLE;
-               fss->show_advancedoptions = 0;
-
-               fss->resolutionxyz = 65;
-               fss->previewresxyz = 45;
-               fss->realsize = 0.5;
-               fss->guiDisplayMode = 2; // preview
-               fss->renderDisplayMode = 3; // render
-
-               fss->viscosityMode = 2; // default to water
-               fss->viscosityValue = 1.0;
-               fss->viscosityExponent = 6;
-               
-               // dg TODO: change this to []
-               fss->gravx = 0.0;
-               fss->gravy = 0.0;
-               fss->gravz = -9.81;
-               fss->animStart = 0.0; 
-               fss->animEnd = 4.0;
-               fss->gstar = 0.005; // used as normgstar
-               fss->maxRefine = -1;
-               // maxRefine is set according to resolutionxyz during bake
-
-               // fluid/inflow settings
-               // fss->iniVel --> automatically set to 0
-
-               /*  elubie: changed this to default to the same dir as the render output
-               to prevent saving to C:\ on Windows */
-               BLI_strncpy(fss->surfdataPath, btempdir, FILE_MAX);
-
-               // first init of bounding box
-               // no bounding box needed
-               
-               // todo - reuse default init from elbeem!
-               fss->typeFlags = OB_FSBND_PARTSLIP;
-               fss->domainNovecgen = 0;
-               fss->volumeInitType = 1; // volume
-               fss->partSlipValue = 0.2;
-
-               fss->generateTracers = 0;
-               fss->generateParticles = 0.0;
-               fss->surfaceSmoothing = 1.0;
-               fss->surfaceSubdivs = 0.0;
-               fss->particleInfSize = 0.0;
-               fss->particleInfAlpha = 0.0;
-       
-               // init fluid control settings
-               fss->attractforceStrength = 0.2;
-               fss->attractforceRadius = 0.75;
-               fss->velocityforceStrength = 0.2;
-               fss->velocityforceRadius = 0.75;
-               fss->cpsTimeStart = fss->animStart;
-               fss->cpsTimeEnd = fss->animEnd;
-               fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
-               
-               /*
-               BAD TODO: this is done in buttons_object.c in the moment 
-               Mesh *mesh = ob->data;
-               // calculate bounding box
-               fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize); 
-               */
-               
-               // (ab)used to store velocities
-               fss->meshSurfNormals = NULL;
-               
-               fss->lastgoodframe = -1;
-               
-               fss->flag |= OB_FLUIDSIM_ACTIVE;
-
-       }
-#endif
-       return;
-}
-
-void fluidsim_free(FluidsimModifierData *fluidmd)
-{
-#ifndef DISABLE_ELBEEM
-       if(fluidmd)
-       {
-               if(fluidmd->fss->meshSurfNormals)
-               {
-                       MEM_freeN(fluidmd->fss->meshSurfNormals);
-                       fluidmd->fss->meshSurfNormals = NULL;
-               }
-               MEM_freeN(fluidmd->fss);
-       }
-#endif
-       return;
-}
-
-DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
-{
-#ifndef DISABLE_ELBEEM
-       DerivedMesh *result = NULL;
-       int framenr;
-       FluidsimSettings *fss = NULL;
-
-       framenr= (int)scene->r.cfra;
-       
-       // only handle fluidsim domains
-       if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN))
-               return dm;
-       
-       // sanity check
-       if(!fluidmd || (fluidmd && !fluidmd->fss))
-               return dm;
-       
-       fss = fluidmd->fss;
-       
-       // timescale not supported yet
-       // clmd->sim_parms->timescale= timescale;
-       
-       // support reversing of baked fluid frames here
-       if((fss->flag & OB_FLUIDSIM_REVERSE) && (fss->lastgoodframe >= 0))
-       {
-               framenr = fss->lastgoodframe - framenr + 1;
-               CLAMP(framenr, 1, fss->lastgoodframe);
-       }
-       
-       /* try to read from cache */
-       if(((fss->lastgoodframe >= framenr) || (fss->lastgoodframe < 0)) && (result = fluidsim_read_cache(ob, dm, fluidmd, framenr, useRenderParams)))
-       {
-               // fss->lastgoodframe = framenr; // set also in src/fluidsim.c
-               return result;
-       }
-       else
-       {       
-               // display last known good frame
-               if(fss->lastgoodframe >= 0)
-               {
-                       if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams))) 
-                       {
-                               return result;
-                       }
-                       
-                       // it was supposed to be a valid frame but it isn't!
-                       fss->lastgoodframe = framenr - 1;
-                       
-                       
-                       // this could be likely the case when you load an old fluidsim
-                       if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams))) 
-                       {
-                               return result;
-                       }
-               }
-               
-               result = CDDM_copy(dm);
-
-               if(result) 
-               {
-                       return result;
-               }
-       }
-       
-       return dm;
-#else
-       return NULL;
-#endif
-}
-
-#ifndef DISABLE_ELBEEM
-/* read .bobj.gz file into a fluidsimDerivedMesh struct */
-static DerivedMesh *fluidsim_read_obj(char *filename)
-{
-       int wri,i,j;
-       float wrf;
-       int gotBytes;
-       gzFile gzf;
-       int numverts = 0, numfaces = 0;
-       DerivedMesh *dm = NULL;
-       MFace *mface;
-       MVert *mvert;
-       short *normals;
-               
-       // ------------------------------------------------
-       // get numverts + numfaces first
-       // ------------------------------------------------
-       gzf = gzopen(filename, "rb");
-       if (!gzf) 
-       {
-               return NULL;
-       }
-
-       // read numverts
-       gotBytes = gzread(gzf, &wri, sizeof(wri));
-       numverts = wri;
-       
-       // skip verts
-       for(i=0; i<numverts*3; i++) 
-       {       
-               gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
-       }
-       
-       // read number of normals
-       gotBytes = gzread(gzf, &wri, sizeof(wri));
-       
-       // skip normals
-       for(i=0; i<numverts*3; i++) 
-       {       
-               gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
-       }
-       
-       /* get no. of triangles */
-       gotBytes = gzread(gzf, &wri, sizeof(wri));
-       numfaces = wri;
-       
-       gzclose( gzf );
-       // ------------------------------------------------
-       
-       if(!numfaces || !numverts)
-               return NULL;
-       
-       gzf = gzopen(filename, "rb");
-       if (!gzf) 
-       {
-               return NULL;
-       }
-       
-       dm = CDDM_new(numverts, 0, numfaces);
-       
-       if(!dm)
-       {
-               gzclose( gzf );
-               return NULL;
-       }
-       
-       // read numverts
-       gotBytes = gzread(gzf, &wri, sizeof(wri));
-
-       // read vertex position from file
-       mvert = CDDM_get_verts(dm);
-       for(i=0; i<numverts; i++) 
-       {
-               MVert *mv = &mvert[i];
-               
-               for(j=0; j<3; j++) 
-               {
-                       gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
-                       mv->co[j] = wrf;
-               }
-       }
-
-       // should be the same as numverts
-       gotBytes = gzread(gzf, &wri, sizeof(wri));
-       if(wri != numverts) 
-       {
-               if(dm)
-                       dm->release(dm);
-               gzclose( gzf );
-               return NULL;
-       }
-       
-       normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" );      
-       if(!normals)
-       {
-               if(dm)
-                       dm->release(dm);
-               gzclose( gzf );
-               return NULL;
-       }       
-       
-       // read normals from file (but don't save them yet)
-       for(i=0; i<numverts*3; i++) 
-       { 
-               gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
-               normals[i] = (short)(wrf*32767.0f);
-       }
-       
-       /* read no. of triangles */
-       gotBytes = gzread(gzf, &wri, sizeof(wri));
-       
-       if(wri!=numfaces)
-               printf("Fluidsim: error in reading data from file.\n");
-       
-       // read triangles from file
-       mface = CDDM_get_faces(dm);
-       for(i=0; i<numfaces; i++) 
-       {
-               int face[4];
-               MFace *mf = &mface[i];
-
-               gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] )); 
-               gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] )); 
-               gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] )); 
-               face[3] = 0;
-
-               // check if 3rd vertex has index 0 (not allowed in blender)
-               if(face[2])
-               {
-                       mf->v1 = face[0];
-                       mf->v2 = face[1];
-                       mf->v3 = face[2];
-               }
-               else
-               {
-                       mf->v1 = face[1];
-                       mf->v2 = face[2];
-                       mf->v3 = face[0];
-               }
-               mf->v4 = face[3];
-               
-               test_index_face(mf, NULL, 0, 3);
-       }
-       
-       gzclose( gzf );
-       
-       CDDM_calc_edges(dm);
-       
-       CDDM_apply_vert_normals(dm, (short (*)[3])normals);
-       MEM_freeN(normals);
-       
-       // CDDM_calc_normals(result);
-
-       return dm;
-}
-
-DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams)
-{
-       int displaymode = 0;
-       int curFrame = framenr - 1 /*scene->r.sfra*/; /* start with 0 at start frame */
-       char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
-       FluidsimSettings *fss = fluidmd->fss;
-       DerivedMesh *dm = NULL;
-       MFace *mface;
-       int numfaces;
-       int mat_nr, flag, i;
-       
-       if(!useRenderParams) {
-               displaymode = fss->guiDisplayMode;
-       } else {
-               displaymode = fss->renderDisplayMode;
-       }
-
-       strncpy(targetDir, fss->surfdataPath, FILE_MAXDIR);
-       
-       // use preview or final mesh?
-       if(displaymode==1) 
-       {
-               // just display original object
-               return NULL;
-       } 
-       else if(displaymode==2) 
-       {
-               strcat(targetDir,"fluidsurface_preview_####");
-       } 
-       else 
-       { // 3
-               strcat(targetDir,"fluidsurface_final_####");
-       }
-       
-       BLI_path_abs(targetDir, G.sce);
-       BLI_path_frame(targetDir, curFrame, 0); // fixed #frame-no 
-       
-       strcpy(targetFile,targetDir);
-       strcat(targetFile, ".bobj.gz");
-
-       dm = fluidsim_read_obj(targetFile);
-       
-       if(!dm) 
-       {       
-               // switch, abort background rendering when fluidsim mesh is missing
-               const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
-               
-               if(G.background==1) {
-                       if(getenv(strEnvName2)) {
-                               int elevel = atoi(getenv(strEnvName2));
-                               if(elevel>0) {
-                                       printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
-                                       exit(1);
-                               }
-                       }
-               }
-               
-               // display org. object upon failure which is in dm
-               return NULL;
-       }
-       
-       // assign material + flags to new dm
-       mface = orgdm->getFaceArray(orgdm);
-       mat_nr = mface[0].mat_nr;
-       flag = mface[0].flag;
-       
-       mface = dm->getFaceArray(dm);
-       numfaces = dm->getNumFaces(dm);
-       for(i=0; i<numfaces; i++) 
-       {
-               mface[i].mat_nr = mat_nr;
-               mface[i].flag = flag;
-       }
-
-       // load vertex velocities, if they exist...
-       // TODO? use generate flag as loading flag as well?
-       // warning, needs original .bobj.gz mesh loading filename
-       if(displaymode==3) 
-       {
-               fluidsim_read_vel_cache(fluidmd, dm, targetFile);
-       } 
-       else 
-       {
-               if(fss->meshSurfNormals)
-                       MEM_freeN(fss->meshSurfNormals); 
-                       
-               fss->meshSurfNormals = NULL;
-       }
-       
-       return dm;
-}
-
-
-/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
-void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh *dm, char *filename)
-{
-       int wri, i, j;
-       float wrf;
-       gzFile gzf;
-       FluidsimSettings *fss = fluidmd->fss;
-       int len = strlen(filename);
-       int totvert = dm->getNumVerts(dm);
-       float *velarray = NULL;
-       
-       // mesh and vverts have to be valid from loading...
-       
-       if(fss->meshSurfNormals)
-               MEM_freeN(fss->meshSurfNormals);
-               
-       if(len<7) 
-       { 
-               return; 
-       }
-       
-       if(fss->domainNovecgen>0) return;
-       
-       // abusing pointer to hold an array of 3d-velocities
-       fss->meshSurfNormals = MEM_callocN(sizeof(float)*3*dm->getNumVerts(dm), "Fluidsim_velocities");
-       // abusing pointer to hold an INT
-       fss->meshSurface = SET_INT_IN_POINTER(totvert);
-       
-       velarray = (float *)fss->meshSurfNormals;
-       
-       // .bobj.gz , correct filename
-       // 87654321
-       filename[len-6] = 'v';
-       filename[len-5] = 'e';
-       filename[len-4] = 'l';
-
-       gzf = gzopen(filename, "rb");
-       if (!gzf)
-       {
-               MEM_freeN(fss->meshSurfNormals);
-               fss->meshSurfNormals = NULL;    
-               return;
-       }
-
-       gzread(gzf, &wri, sizeof( wri ));
-       if(wri != totvert) 
-       {
-               MEM_freeN(fss->meshSurfNormals);
-               fss->meshSurfNormals = NULL;
-               return; 
-       }
-
-       for(i=0; i<totvert;i++) 
-       {
-               for(j=0; j<3; j++) 
-               {
-                       gzread(gzf, &wrf, sizeof( wrf )); 
-                       velarray[3*i + j] = wrf;
-               }
-       }
-
-       gzclose(gzf);
-}
-
-void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
-                /*RET*/ float start[3], /*RET*/ float size[3] )
-{
-       float bbsx=0.0, bbsy=0.0, bbsz=0.0;
-       float bbex=1.0, bbey=1.0, bbez=1.0;
-       int i;
-       float vec[3];
-
-       if(totvert == 0) {
-               zero_v3(start);
-               zero_v3(size);
-               return;
-       }
-
-       VECCOPY(vec, mvert[0].co); 
-       mul_m4_v3(obmat, vec);
-       bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
-       bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
-
-       for(i = 1; i < totvert; i++) {
-               VECCOPY(vec, mvert[i].co);
-               mul_m4_v3(obmat, vec);
-
-               if(vec[0] < bbsx){ bbsx= vec[0]; }
-               if(vec[1] < bbsy){ bbsy= vec[1]; }
-               if(vec[2] < bbsz){ bbsz= vec[2]; }
-               if(vec[0] > bbex){ bbex= vec[0]; }
-               if(vec[1] > bbey){ bbey= vec[1]; }
-               if(vec[2] > bbez){ bbez= vec[2]; }
-       }
-
-       // return values...
-       if(start) {
-               start[0] = bbsx;
-               start[1] = bbsy;
-               start[2] = bbsz;
-       } 
-       if(size) {
-               size[0] = bbex-bbsx;
-               size[1] = bbey-bbsy;
-               size[2] = bbez-bbsz;
-       }
-}
-
-//-------------------------------------------------------------------------------
-// old interface
-//-------------------------------------------------------------------------------
-
-
 
 //-------------------------------------------------------------------------------
 // file handling
 //-------------------------------------------------------------------------------
 
-void initElbeemMesh(struct Scene *scene, struct Object *ob, 
-                       int *numVertices, float **vertices, 
+void initElbeemMesh(struct Scene *scene, struct Object *ob,
+                       int *numVertices, float **vertices,
          int *numTriangles, int **triangles,
-         int useGlobalCoords, int modifierIndex) 
+         int useGlobalCoords, int modifierIndex)
 {
        DerivedMesh *dm = NULL;
        MVert *mvert;
@@ -650,14 +109,14 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
                face[2] = mface[i].v3;
                face[3] = mface[i].v4;
 
-               tris[countTris*3+0] = face[0]; 
-               tris[countTris*3+1] = face[1]; 
-               tris[countTris*3+2] = face[2]; 
+               tris[countTris*3+0] = face[0];
+               tris[countTris*3+1] = face[1];
+               tris[countTris*3+2] = face[2];
                countTris++;
-               if(face[3]) { 
-                       tris[countTris*3+0] = face[0]; 
-                       tris[countTris*3+1] = face[2]; 
-                       tris[countTris*3+2] = face[3]; 
+               if(face[3]) {
+                       tris[countTris*3+0] = face[0];
+                       tris[countTris*3+1] = face[2];
+                       tris[countTris*3+2] = face[3];
                        countTris++;
                }
        }
@@ -665,21 +124,3 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
 
        dm->release(dm);
 }
-
-void fluid_estimate_memory(Object *ob, FluidsimSettings *fss, char *value)
-{
-       Mesh *mesh;
-
-       value[0]= '\0';
-
-       if(ob->type == OB_MESH) {
-               /* use mesh bounding box and object scaling */
-               mesh= ob->data;
-
-               fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
-               elbeemEstimateMemreq(fss->resolutionxyz, fss->bbSize[0],fss->bbSize[1],fss->bbSize[2], fss->maxRefine, value);
-       }
-}
-
-#endif // DISABLE_ELBEEM
-
index c8f98bbac562e4376d590875125a36c07c466c11..d2d9d558b3c3b686b8c1a54818b8c2fd692e727b 100644 (file)
 #include "depsgraph_private.h"
 #include "BKE_deform.h"
 #include "BKE_shrinkwrap.h"
-#include "BKE_simple_deform.h"
-
-#include "LOD_decimation.h"
 
 #include "CCGSubSurf.h"
 
 #include "RE_shader_ext.h"
 
-/* Utility */
+#include "MOD_modifiertypes.h"
 
-static int is_last_displist(Object *ob)
+ModifierTypeInfo *modifierType_getInfo(ModifierType type)
 {
-       Curve *cu = ob->data;
-       static int curvecount=0, totcurve=0;
-
-       if(curvecount == 0){
-               DispList *dl;
-
-               totcurve = 0;
-               for(dl=cu->disp.first; dl; dl=dl->next)
-                       totcurve++;
-       }
-
-       curvecount++;
-
-       if(curvecount == totcurve){
-               curvecount = 0;
-               return 1;
-       }
-
-       return 0;
-}
+       static ModifierTypeInfo *types[NUM_MODIFIER_TYPES];
+       static int types_init = 1;
 
-/* returns a derived mesh if dm == NULL, for deforming modifiers that need it */
-static DerivedMesh *get_dm(Scene *scene, Object *ob, EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int orco)
-{
-       if(dm)
-               return dm;
+       if (types_init) {
+               memset(types, 0, sizeof(types));
 
-       if(ob->type==OB_MESH) {
-               if(em) dm= CDDM_from_editmesh(em, ob->data);
-               else dm = CDDM_from_mesh((Mesh*)(ob->data), ob);
+#define INIT_TYPE(typeName) \
+                       (types[eModifierType_##typeName] = &modifierType_##typeName)
+
+               INIT_TYPE(None);
+               INIT_TYPE(Curve);
+               INIT_TYPE(Lattice);
+               INIT_TYPE(Subsurf);
+               INIT_TYPE(Build);
+               INIT_TYPE(Array);
+               INIT_TYPE(Mirror);
+               INIT_TYPE(EdgeSplit);
+               INIT_TYPE(Bevel);
+               INIT_TYPE(Displace);
+               INIT_TYPE(UVProject);
+               INIT_TYPE(Decimate);
+               INIT_TYPE(Smooth);
+               INIT_TYPE(Cast);
+               INIT_TYPE(Wave);
+               INIT_TYPE(Armature);
+               INIT_TYPE(Hook);
+               INIT_TYPE(Softbody);
+               INIT_TYPE(Cloth);
+               INIT_TYPE(Collision);
+               INIT_TYPE(Boolean);
+               INIT_TYPE(MeshDeform);
+               INIT_TYPE(ParticleSystem);
+               INIT_TYPE(ParticleInstance);
+               INIT_TYPE(Explode);             
+               INIT_TYPE(Cloth);
+               INIT_TYPE(Collision);
+               INIT_TYPE(Bevel);
+               INIT_TYPE(Shrinkwrap);
+               INIT_TYPE(Fluidsim);
+               INIT_TYPE(Mask);
+               INIT_TYPE(SimpleDeform);
+               INIT_TYPE(Multires);
+               INIT_TYPE(Surface);
+               INIT_TYPE(Smoke);
+               INIT_TYPE(ShapeKey);
+               INIT_TYPE(Solidify);
+               INIT_TYPE(Screw);
+
+               types_init = 0;
 
-               if(vertexCos) {
-                       CDDM_apply_vert_coords(dm, vertexCos);
-                       //CDDM_calc_normals(dm);
-               }
-               
-               if(orco)
-                       DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob));
-       }
-       else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) {
-               if(is_last_displist(ob)) {
-                       dm= CDDM_from_curve(ob);
-               }
+#undef INIT_TYPE
        }
 
-       return dm;
-}
-
-/* returns a cdderivedmesh if dm == NULL or is another type of derivedmesh */
-static DerivedMesh *get_cddm(Scene *scene, Object *ob, EditMesh *em, DerivedMesh *dm, float (*vertexCos)[3])
-{
-       if(dm && dm->type == DM_TYPE_CDDM)
-               return dm;
-
-       if(!dm) {
-               dm= get_dm(scene, ob, em, dm, vertexCos, 0);
+       if(type >= 0 && type < NUM_MODIFIER_TYPES &&
+          types[type]->name[0] != '\0') {
+               return types[type];
        }
        else {
-               dm= CDDM_copy(dm);
-               CDDM_apply_vert_coords(dm, vertexCos);
-       }
-
-       if(dm)
-               CDDM_calc_normals(dm);
-       
-       return dm;
-}
-
-/***/
-
-static int noneModifier_isDisabled(ModifierData *md, int userRenderParams)
-{
-       return 1;
-}
-
-/* Curve */
-
-static void curveModifier_initData(ModifierData *md)
-{
-       CurveModifierData *cmd = (CurveModifierData*) md;
-
-       cmd->defaxis = MOD_CURVE_POSX;
-}
-
-static void curveModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       CurveModifierData *cmd = (CurveModifierData*) md;
-       CurveModifierData *tcmd = (CurveModifierData*) target;
-
-       tcmd->defaxis = cmd->defaxis;
-       tcmd->object = cmd->object;
-       strncpy(tcmd->name, cmd->name, 32);
-}
-
-static CustomDataMask curveModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       CurveModifierData *cmd = (CurveModifierData *)md;
-       CustomDataMask dataMask = 0;
-
-       /* ask for vertexgroups if we need them */
-       if(cmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
-       return dataMask;
-}
-
-static int curveModifier_isDisabled(ModifierData *md, int userRenderParams)
-{
-       CurveModifierData *cmd = (CurveModifierData*) md;
-
-       return !cmd->object;
-}
-
-static void curveModifier_foreachObjectLink(
-                                               ModifierData *md, Object *ob,
-        void (*walk)(void *userData, Object *ob, Object **obpoin),
-               void *userData)
-{
-       CurveModifierData *cmd = (CurveModifierData*) md;
-
-       walk(userData, ob, &cmd->object);
-}
-
-static void curveModifier_updateDepgraph(
-                                        ModifierData *md, DagForest *forest, Scene *scene,
-         Object *ob, DagNode *obNode)
-{
-       CurveModifierData *cmd = (CurveModifierData*) md;
-
-       if (cmd->object) {
-               DagNode *curNode = dag_get_node(forest, cmd->object);
-
-               dag_add_relation(forest, curNode, obNode,
-                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Modifier");
-       }
-}
-
-static void curveModifier_deformVerts(
-                                         ModifierData *md, Object *ob, DerivedMesh *derivedData,
-         float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
-       CurveModifierData *cmd = (CurveModifierData*) md;
-
-       curve_deform_verts(md->scene, cmd->object, ob, derivedData, vertexCos, numVerts,
-                          cmd->name, cmd->defaxis);
-}
-
-static void curveModifier_deformVertsEM(
-                                       ModifierData *md, Object *ob, EditMesh *editData,
-        DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
-       DerivedMesh *dm = derivedData;
-
-       if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
-       curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
-
-       if(!derivedData) dm->release(dm);
-}
-
-/* Lattice */
-
-static void latticeModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       LatticeModifierData *lmd = (LatticeModifierData*) md;
-       LatticeModifierData *tlmd = (LatticeModifierData*) target;
-
-       tlmd->object = lmd->object;
-       strncpy(tlmd->name, lmd->name, 32);
-}
-
-static CustomDataMask latticeModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       LatticeModifierData *lmd = (LatticeModifierData *)md;
-       CustomDataMask dataMask = 0;
-
-       /* ask for vertexgroups if we need them */
-       if(lmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
-       return dataMask;
-}
-
-static int latticeModifier_isDisabled(ModifierData *md, int userRenderParams)
-{
-       LatticeModifierData *lmd = (LatticeModifierData*) md;
-
-       return !lmd->object;
-}
-
-static void latticeModifier_foreachObjectLink(
-                                                 ModifierData *md, Object *ob,
-          void (*walk)(void *userData, Object *ob, Object **obpoin),
-                 void *userData)
-{
-       LatticeModifierData *lmd = (LatticeModifierData*) md;
-
-       walk(userData, ob, &lmd->object);
-}
-
-static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest,  Scene *scene,
-                                          Object *ob, DagNode *obNode)
-{
-       LatticeModifierData *lmd = (LatticeModifierData*) md;
-
-       if(lmd->object) {
-               DagNode *latNode = dag_get_node(forest, lmd->object);
-
-               dag_add_relation(forest, latNode, obNode,
-                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Lattice Modifier");
-       }
-}
-
-static void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3])
-{
-       while((md=md->next) && md->type==eModifierType_Armature) {
-               ArmatureModifierData *amd = (ArmatureModifierData*) md;
-               if(amd->multi && amd->prevCos==NULL)
-                       amd->prevCos= MEM_dupallocN(vertexCos);
-               else
-                       break;
-       }
-       /* lattice/mesh modifier too */
-}
-
-
-static void latticeModifier_deformVerts(
-                                       ModifierData *md, Object *ob, DerivedMesh *derivedData,
-        float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
-       LatticeModifierData *lmd = (LatticeModifierData*) md;
-
-
-       modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
-       
-       lattice_deform_verts(lmd->object, ob, derivedData,
-                                vertexCos, numVerts, lmd->name);
-}
-
-static void latticeModifier_deformVertsEM(
-                                         ModifierData *md, Object *ob, EditMesh *editData,
-          DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
-       DerivedMesh *dm = derivedData;
-
-       if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
-       latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0);
-
-       if(!derivedData) dm->release(dm);
-}
-
-/* Subsurf */
-
-static void subsurfModifier_initData(ModifierData *md)
-{
-       SubsurfModifierData *smd = (SubsurfModifierData*) md;
-
-       smd->levels = 1;
-       smd->renderLevels = 2;
-       smd->flags |= eSubsurfModifierFlag_SubsurfUv;
-}
-
-static void subsurfModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       SubsurfModifierData *smd = (SubsurfModifierData*) md;
-       SubsurfModifierData *tsmd = (SubsurfModifierData*) target;
-
-       tsmd->flags = smd->flags;
-       tsmd->levels = smd->levels;
-       tsmd->renderLevels = smd->renderLevels;
-       tsmd->subdivType = smd->subdivType;
-}
-
-static void subsurfModifier_freeData(ModifierData *md)
-{
-       SubsurfModifierData *smd = (SubsurfModifierData*) md;
-
-       if(smd->mCache) {
-               ccgSubSurf_free(smd->mCache);
-       }
-       if(smd->emCache) {
-               ccgSubSurf_free(smd->emCache);
-       }
-}
-
-static int subsurfModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
-       SubsurfModifierData *smd = (SubsurfModifierData*) md;
-       int levels= (useRenderParams)? smd->renderLevels: smd->levels;
-
-       return get_render_subsurf_level(&md->scene->r, levels) == 0;
-}
-
-static DerivedMesh *subsurfModifier_applyModifier(
-               ModifierData *md, Object *ob, DerivedMesh *derivedData,
-  int useRenderParams, int isFinalCalc)
-{
-       SubsurfModifierData *smd = (SubsurfModifierData*) md;
-       DerivedMesh *result;
-
-       result = subsurf_make_derived_from_derived(derivedData, smd,
-                       useRenderParams, NULL, isFinalCalc, 0);
-       
-       if(useRenderParams || !isFinalCalc) {
-               DerivedMesh *cddm= CDDM_copy(result);
-               result->release(result);
-               result= cddm;
-       }
-
-       return result;
-}
-
-static DerivedMesh *subsurfModifier_applyModifierEM(
-               ModifierData *md, Object *ob, EditMesh *editData,
-  DerivedMesh *derivedData)
-{
-       SubsurfModifierData *smd = (SubsurfModifierData*) md;
-       DerivedMesh *result;
-
-       result = subsurf_make_derived_from_derived(derivedData, smd, 0,
-                       NULL, 0, 1);
-
-       return result;
-}
-
-/* Build */
-
-static void buildModifier_initData(ModifierData *md)
-{
-       BuildModifierData *bmd = (BuildModifierData*) md;
-
-       bmd->start = 1.0;
-       bmd->length = 100.0;
-}
-
-static void buildModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       BuildModifierData *bmd = (BuildModifierData*) md;
-       BuildModifierData *tbmd = (BuildModifierData*) target;
-
-       tbmd->start = bmd->start;
-       tbmd->length = bmd->length;
-       tbmd->randomize = bmd->randomize;
-       tbmd->seed = bmd->seed;
-}
-
-static int buildModifier_dependsOnTime(ModifierData *md)
-{
-       return 1;
-}
-
-static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
-               DerivedMesh *derivedData,
-  int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *dm = derivedData;
-       DerivedMesh *result;
-       BuildModifierData *bmd = (BuildModifierData*) md;
-       int i;
-       int numFaces, numEdges;
-       int maxVerts, maxEdges, maxFaces;
-       int *vertMap, *edgeMap, *faceMap;
-       float frac;
-       GHashIterator *hashIter;
-       /* maps vert indices in old mesh to indices in new mesh */
-       GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
-                                       BLI_ghashutil_intcmp);
-       /* maps edge indices in new mesh to indices in old mesh */
-       GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
-                                       BLI_ghashutil_intcmp);
-
-       maxVerts = dm->getNumVerts(dm);
-       vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts,
-                                 "build modifier vertMap");
-       for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
-
-       maxEdges = dm->getNumEdges(dm);
-       edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges,
-                                 "build modifier edgeMap");
-       for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
-
-       maxFaces = dm->getNumFaces(dm);
-       faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces,
-                                 "build modifier faceMap");
-       for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
-
-       if (ob) {
-               frac = bsystem_time(md->scene, ob, md->scene->r.cfra,
-                                       bmd->start - 1.0f) / bmd->length;
-       } else {
-               frac = md->scene->r.cfra - bmd->start / bmd->length;
-       }
-       CLAMP(frac, 0.0, 1.0);
-
-       numFaces = dm->getNumFaces(dm) * frac;
-       numEdges = dm->getNumEdges(dm) * frac;
-
-       /* if there's at least one face, build based on faces */
-       if(numFaces) {
-               int maxEdges;
-
-               if(bmd->randomize)
-                       BLI_array_randomize(faceMap, sizeof(*faceMap),
-                                               maxFaces, bmd->seed);
-
-               /* get the set of all vert indices that will be in the final mesh,
-               * mapped to the new indices
-               */
-               for(i = 0; i < numFaces; ++i) {
-                       MFace mf;
-                       dm->getFace(dm, faceMap[i], &mf);
-
-                       if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)))
-                               BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v1),
-                                       SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
-                       if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)))
-                               BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v2),
-                                       SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
-                       if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)))
-                               BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v3),
-                                       SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
-                       if(mf.v4 && !BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4)))
-                               BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(mf.v4),
-                                       SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
-               }
-
-               /* get the set of edges that will be in the new mesh (i.e. all edges
-               * that have both verts in the new mesh)
-               */
-               maxEdges = dm->getNumEdges(dm);
-               for(i = 0; i < maxEdges; ++i) {
-                       MEdge me;
-                       dm->getEdge(dm, i, &me);
-
-                       if(BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1))
-                                               && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
-                               BLI_ghash_insert(edgeHash,
-                                       SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)), SET_INT_IN_POINTER(i));
-               }
-       } else if(numEdges) {
-               if(bmd->randomize)
-                       BLI_array_randomize(edgeMap, sizeof(*edgeMap),
-                                               maxEdges, bmd->seed);
-
-               /* get the set of all vert indices that will be in the final mesh,
-               * mapped to the new indices
-               */
-               for(i = 0; i < numEdges; ++i) {
-                       MEdge me;
-                       dm->getEdge(dm, edgeMap[i], &me);
-
-                       if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)))
-                               BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v1),
-                                       SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
-                       if(!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)))
-                               BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me.v2),
-                                       SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
-               }
-
-               /* get the set of edges that will be in the new mesh
-               */
-               for(i = 0; i < numEdges; ++i) {
-                       MEdge me;
-                       dm->getEdge(dm, edgeMap[i], &me);
-
-                       BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(BLI_ghash_size(edgeHash)),
-                                        SET_INT_IN_POINTER(edgeMap[i]));
-               }
-       } else {
-               int numVerts = dm->getNumVerts(dm) * frac;
-
-               if(bmd->randomize)
-                       BLI_array_randomize(vertMap, sizeof(*vertMap),
-                                               maxVerts, bmd->seed);
-
-               /* get the set of all vert indices that will be in the final mesh,
-               * mapped to the new indices
-               */
-               for(i = 0; i < numVerts; ++i)
-                       BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(vertMap[i]), SET_INT_IN_POINTER(i));
-       }
-
-       /* now we know the number of verts, edges and faces, we can create
-       * the mesh
-       */
-       result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
-                                       BLI_ghash_size(edgeHash), numFaces);
-
-       /* copy the vertices across */
-       for(hashIter = BLI_ghashIterator_new(vertHash);
-                  !BLI_ghashIterator_isDone(hashIter);
-                  BLI_ghashIterator_step(hashIter)) {
-                          MVert source;
-                          MVert *dest;
-                          int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
-                          int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
-
-                          dm->getVert(dm, oldIndex, &source);
-                          dest = CDDM_get_vert(result, newIndex);
-
-                          DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
-                          *dest = source;
-                  }
-                  BLI_ghashIterator_free(hashIter);
-
-                  /* copy the edges across, remapping indices */
-                  for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
-                          MEdge source;
-                          MEdge *dest;
-                          int oldIndex = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(i)));
-
-                          dm->getEdge(dm, oldIndex, &source);
-                          dest = CDDM_get_edge(result, i);
-
-                          source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
-                          source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
-
-                          DM_copy_edge_data(dm, result, oldIndex, i, 1);
-                          *dest = source;
-                  }
-
-                  /* copy the faces across, remapping indices */
-                  for(i = 0; i < numFaces; ++i) {
-                          MFace source;
-                          MFace *dest;
-                          int orig_v4;
-
-                          dm->getFace(dm, faceMap[i], &source);
-                          dest = CDDM_get_face(result, i);
-
-                          orig_v4 = source.v4;
-
-                          source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
-                          source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
-                          source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
-                          if(source.v4)
-                                  source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
-
-                          DM_copy_face_data(dm, result, faceMap[i], i, 1);
-                          *dest = source;
-
-                          test_index_face(dest, &result->faceData, i, (orig_v4 ? 4 : 3));
-                  }
-
-                  CDDM_calc_normals(result);
-
-                  BLI_ghash_free(vertHash, NULL, NULL);
-                  BLI_ghash_free(edgeHash, NULL, NULL);
-
-                  MEM_freeN(vertMap);
-                  MEM_freeN(edgeMap);
-                  MEM_freeN(faceMap);
-
-                  return result;
-}
-
-/* Mask */
-
-static void maskModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       MaskModifierData *mmd = (MaskModifierData*) md;
-       MaskModifierData *tmmd = (MaskModifierData*) target;
-       
-       strcpy(tmmd->vgroup, mmd->vgroup);
-}
-
-static CustomDataMask maskModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       return (1 << CD_MDEFORMVERT);
-}
-
-static void maskModifier_foreachObjectLink(
-                                                 ModifierData *md, Object *ob,
-          void (*walk)(void *userData, Object *ob, Object **obpoin),
-                 void *userData)
-{
-       MaskModifierData *mmd = (MaskModifierData *)md;
-       walk(userData, ob, &mmd->ob_arm);
-}
-
-static void maskModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
-                                          Object *ob, DagNode *obNode)
-{
-       MaskModifierData *mmd = (MaskModifierData *)md;
-
-       if (mmd->ob_arm) 
-       {
-               DagNode *armNode = dag_get_node(forest, mmd->ob_arm);
-               
-               dag_add_relation(forest, armNode, obNode,
-                               DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier");
-       }
-}
-
-static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob,
-               DerivedMesh *derivedData,
-  int useRenderParams, int isFinalCalc)
-{
-       MaskModifierData *mmd= (MaskModifierData *)md;
-       DerivedMesh *dm= derivedData, *result= NULL;
-       GHash *vertHash=NULL, *edgeHash, *faceHash;
-       GHashIterator *hashIter;
-       MDeformVert *dvert= NULL;
-       int numFaces=0, numEdges=0, numVerts=0;
-       int maxVerts, maxEdges, maxFaces;
-       int i;
-       
-       /* Overview of Method:
-        *      1. Get the vertices that are in the vertexgroup of interest 
-        *      2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices
-        *      3. Make a new mesh containing only the mapping data
-        */
-       
-       /* get original number of verts, edges, and faces */
-       maxVerts= dm->getNumVerts(dm);
-       maxEdges= dm->getNumEdges(dm);
-       maxFaces= dm->getNumFaces(dm);
-       
-       /* check if we can just return the original mesh 
-        *      - must have verts and therefore verts assigned to vgroups to do anything useful
-        */
-       if ( !(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) ||
-                (maxVerts == 0) || (ob->defbase.first == NULL) )
-       {
-               return derivedData;
-       }
-       
-       /* if mode is to use selected armature bones, aggregate the bone groups */
-       if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */
-       {
-               GHash *vgroupHash, *boneHash;
-               Object *oba= mmd->ob_arm;
-               bPoseChannel *pchan;
-               bDeformGroup *def;
-               
-               /* check that there is armature object with bones to use, otherwise return original mesh */
-               if (ELEM(NULL, mmd->ob_arm, mmd->ob_arm->pose))
-                       return derivedData;             
-               
-               /* hashes for finding mapping of:
-                *      - vgroups to indicies -> vgroupHash  (string, int)
-                *      - bones to vgroup indices -> boneHash (index of vgroup, dummy)
-                */
-               vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
-               boneHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
-               
-               /* build mapping of names of vertex groups to indices */
-               for (i = 0, def = ob->defbase.first; def; def = def->next, i++) 
-                       BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i));
-               
-               /* get selected-posechannel <-> vertexgroup index mapping */
-               for (pchan= oba->pose->chanbase.first; pchan; pchan= pchan->next) 
-               {
-                       /* check if bone is selected */
-                       // TODO: include checks for visibility too?
-                       // FIXME: the depsgraph needs extensions to make this work in realtime...
-                       if ( (pchan->bone) && (pchan->bone->flag & BONE_SELECTED) ) 
-                       {
-                               /* check if hash has group for this bone */
-                               if (BLI_ghash_haskey(vgroupHash, pchan->name)) 
-                               {
-                                       int defgrp_index= GET_INT_FROM_POINTER(BLI_ghash_lookup(vgroupHash, pchan->name));
-                                       
-                                       /* add index to hash (store under key only) */
-                                       BLI_ghash_insert(boneHash, SET_INT_IN_POINTER(defgrp_index), pchan);
-                               }
-                       }
-               }
-               
-               /* if no bones selected, free hashes and return original mesh */
-               if (BLI_ghash_size(boneHash) == 0)
-               {
-                       BLI_ghash_free(vgroupHash, NULL, NULL);
-                       BLI_ghash_free(boneHash, NULL, NULL);
-                       
-                       return derivedData;
-               }
-               
-               /* repeat the previous check, but for dverts */
-               dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT);
-               if (dvert == NULL)
-               {
-                       BLI_ghash_free(vgroupHash, NULL, NULL);
-                       BLI_ghash_free(boneHash, NULL, NULL);
-                       
-                       return derivedData;
-               }
-               
-               /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
-               vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
-               
-               /* add vertices which exist in vertexgroups into vertHash for filtering */
-               for (i = 0; i < maxVerts; i++) 
-               {
-                       MDeformWeight *def_weight = NULL;
-                       int j;
-                       
-                       for (j= 0; j < dvert[i].totweight; j++) 
-                       {
-                               if (BLI_ghash_haskey(boneHash, SET_INT_IN_POINTER(dvert[i].dw[j].def_nr))) 
-                               {
-                                       def_weight = &dvert[i].dw[j];
-                                       break;
-                               }
-                       }
-                       
-                       /* check if include vert in vertHash */
-                       if (mmd->flag & MOD_MASK_INV) {
-                               /* if this vert is in the vgroup, don't include it in vertHash */
-                               if (def_weight) continue;
-                       }
-                       else {
-                               /* if this vert isn't in the vgroup, don't include it in vertHash */
-                               if (!def_weight) continue;
-                       }
-                       
-                       /* add to ghash for verts (numVerts acts as counter for mapping) */
-                       BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
-                       numVerts++;
-               }
-               
-               /* free temp hashes */
-               BLI_ghash_free(vgroupHash, NULL, NULL);
-               BLI_ghash_free(boneHash, NULL, NULL);
-       }
-       else            /* --- Using Nominated VertexGroup only --- */ 
-       {
-               int defgrp_index = defgroup_name_index(ob, mmd->vgroup);
-               
-               /* get dverts */
-               if (defgrp_index >= 0)
-                       dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-                       
-               /* if no vgroup (i.e. dverts) found, return the initial mesh */
-               if ((defgrp_index < 0) || (dvert == NULL))
-                       return dm;
-                       
-               /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
-               vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
-               
-               /* add vertices which exist in vertexgroup into ghash for filtering */
-               for (i = 0; i < maxVerts; i++) 
-               {
-                       MDeformWeight *def_weight = NULL;
-                       int j;
-                       
-                       for (j= 0; j < dvert[i].totweight; j++) 
-                       {
-                               if (dvert[i].dw[j].def_nr == defgrp_index) 
-                               {
-                                       def_weight = &dvert[i].dw[j];
-                                       break;
-                               }
-                       }
-                       
-                       /* check if include vert in vertHash */
-                       if (mmd->flag & MOD_MASK_INV) {
-                               /* if this vert is in the vgroup, don't include it in vertHash */
-                               if (def_weight) continue;
-                       }
-                       else {
-                               /* if this vert isn't in the vgroup, don't include it in vertHash */
-                               if (!def_weight) continue;
-                       }
-                       
-                       /* add to ghash for verts (numVerts acts as counter for mapping) */
-                       BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts));
-                       numVerts++;
-               }
-       }
-       
-       /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */
-       edgeHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
-       faceHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
-       
-       /* loop over edges and faces, and do the same thing to 
-        * ensure that they only reference existing verts 
-        */
-       for (i = 0; i < maxEdges; i++) 
-       {
-               MEdge me;
-               dm->getEdge(dm, i, &me);
-               
-               /* only add if both verts will be in new mesh */
-               if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) &&
-                        BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)) )
-               {
-                       BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges));
-                       numEdges++;
-               }
-       }
-       for (i = 0; i < maxFaces; i++) 
-       {
-               MFace mf;
-               dm->getFace(dm, i, &mf);
-               
-               /* all verts must be available */
-               if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) &&
-                        BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)) &&
-                        BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)) &&
-                       (mf.v4==0 || BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) )
-               {
-                       BLI_ghash_insert(faceHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numFaces));
-                       numFaces++;
-               }
-       }
-       
-       
-       /* now we know the number of verts, edges and faces, 
-        * we can create the new (reduced) mesh
-        */
-       result = CDDM_from_template(dm, numVerts, numEdges, numFaces);
-       
-       
-       /* using ghash-iterators, map data into new mesh */
-               /* vertices */
-       for ( hashIter = BLI_ghashIterator_new(vertHash);
-                 !BLI_ghashIterator_isDone(hashIter);
-                 BLI_ghashIterator_step(hashIter) ) 
-       {
-               MVert source;
-               MVert *dest;
-               int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
-               int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
-               
-               dm->getVert(dm, oldIndex, &source);
-               dest = CDDM_get_vert(result, newIndex);
-               
-               DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
-               *dest = source;
-       }
-       BLI_ghashIterator_free(hashIter);
-               
-               /* edges */
-       for ( hashIter = BLI_ghashIterator_new(edgeHash);
-                 !BLI_ghashIterator_isDone(hashIter);
-                 BLI_ghashIterator_step(hashIter) ) 
-       {
-               MEdge source;
-               MEdge *dest;
-               int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
-               int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
-               
-               dm->getEdge(dm, oldIndex, &source);
-               dest = CDDM_get_edge(result, newIndex);
-               
-               source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
-               source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
-               
-               DM_copy_edge_data(dm, result, oldIndex, newIndex, 1);
-               *dest = source;
-       }
-       BLI_ghashIterator_free(hashIter);
-       
-               /* faces */
-       for ( hashIter = BLI_ghashIterator_new(faceHash);
-                 !BLI_ghashIterator_isDone(hashIter);
-                 BLI_ghashIterator_step(hashIter) ) 
-       {
-               MFace source;
-               MFace *dest;
-               int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter));
-               int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter));
-               int orig_v4;
-               
-               dm->getFace(dm, oldIndex, &source);
-               dest = CDDM_get_face(result, newIndex);
-               
-               orig_v4 = source.v4;
-               
-               source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1)));
-               source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2)));
-               source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3)));
-               if (source.v4)
-                  source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4)));
-               
-               DM_copy_face_data(dm, result, oldIndex, newIndex, 1);
-               *dest = source;
-               
-               test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3));
-       }
-       BLI_ghashIterator_free(hashIter);
-       
-       /* recalculate normals */
-       CDDM_calc_normals(result);
-       
-       /* free hashes */
-       BLI_ghash_free(vertHash, NULL, NULL);
-       BLI_ghash_free(edgeHash, NULL, NULL);
-       BLI_ghash_free(faceHash, NULL, NULL);
-       
-       /* return the new mesh */
-       return result;
-}
-
-/* Array */
-/* Array modifier: duplicates the object multiple times along an axis
-*/
-
-static void arrayModifier_initData(ModifierData *md)
-{
-       ArrayModifierData *amd = (ArrayModifierData*) md;
-
-       /* default to 2 duplicates distributed along the x-axis by an
-       offset of 1 object-width
-       */
-       amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL;
-       amd->count = 2;
-       amd->offset[0] = amd->offset[1] = amd->offset[2] = 0;
-       amd->scale[0] = 1;
-       amd->scale[1] = amd->scale[2] = 0;
-       amd->length = 0;
-       amd->merge_dist = 0.01;
-       amd->fit_type = MOD_ARR_FIXEDCOUNT;
-       amd->offset_type = MOD_ARR_OFF_RELATIVE;
-       amd->flags = 0;
-}
-
-static void arrayModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       ArrayModifierData *amd = (ArrayModifierData*) md;
-       ArrayModifierData *tamd = (ArrayModifierData*) target;
-
-       tamd->start_cap = amd->start_cap;
-       tamd->end_cap = amd->end_cap;
-       tamd->curve_ob = amd->curve_ob;
-       tamd->offset_ob = amd->offset_ob;
-       tamd->count = amd->count;
-       VECCOPY(tamd->offset, amd->offset);
-       VECCOPY(tamd->scale, amd->scale);
-       tamd->length = amd->length;
-       tamd->merge_dist = amd->merge_dist;
-       tamd->fit_type = amd->fit_type;
-       tamd->offset_type = amd->offset_type;
-       tamd->flags = amd->flags;
-}
-
-static void arrayModifier_foreachObjectLink(
-                                               ModifierData *md, Object *ob,
-        void (*walk)(void *userData, Object *ob, Object **obpoin),
-               void *userData)
-{
-       ArrayModifierData *amd = (ArrayModifierData*) md;
-
-       walk(userData, ob, &amd->start_cap);
-       walk(userData, ob, &amd->end_cap);
-       walk(userData, ob, &amd->curve_ob);
-       walk(userData, ob, &amd->offset_ob);
-}
-
-static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
-                                        Object *ob, DagNode *obNode)
-{
-       ArrayModifierData *amd = (ArrayModifierData*) md;
-
-       if (amd->start_cap) {
-               DagNode *curNode = dag_get_node(forest, amd->start_cap);
-
-               dag_add_relation(forest, curNode, obNode,
-                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
-       }
-       if (amd->end_cap) {
-               DagNode *curNode = dag_get_node(forest, amd->end_cap);
-
-               dag_add_relation(forest, curNode, obNode,
-                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
-       }
-       if (amd->curve_ob) {
-               DagNode *curNode = dag_get_node(forest, amd->curve_ob);
-
-               dag_add_relation(forest, curNode, obNode,
-                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
-       }
-       if (amd->offset_ob) {
-               DagNode *curNode = dag_get_node(forest, amd->offset_ob);
-
-               dag_add_relation(forest, curNode, obNode,
-                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
-       }
-}
-
-static float vertarray_size(MVert *mvert, int numVerts, int axis)
-{
-       int i;
-       float min_co, max_co;
-
-       /* if there are no vertices, width is 0 */
-       if(numVerts == 0) return 0;
-
-       /* find the minimum and maximum coordinates on the desired axis */
-       min_co = max_co = mvert->co[axis];
-       ++mvert;
-       for(i = 1; i < numVerts; ++i, ++mvert) {
-               if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
-               if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
-       }
-
-       return max_co - min_co;
-}
-
-typedef struct IndexMapEntry {
-       /* the new vert index that this old vert index maps to */
-       int new;
-       /* -1 if this vert isn't merged, otherwise the old vert index it
-       * should be replaced with
-       */
-       int merge;
-       /* 1 if this vert's first copy is merged with the last copy of its
-       * merge target, otherwise 0
-       */
-       short merge_final;
-} IndexMapEntry;
-
-/* indexMap - an array of IndexMap entries
- * oldIndex - the old index to map
- * copyNum - the copy number to map to (original = 0, first copy = 1, etc.)
- */
-static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum)
-{
-       if(indexMap[oldIndex].merge < 0) {
-               /* vert wasn't merged, so use copy of this vert */
-               return indexMap[oldIndex].new + copyNum;
-       } else if(indexMap[oldIndex].merge == oldIndex) {
-               /* vert was merged with itself */
-               return indexMap[oldIndex].new;
-       } else {
-               /* vert was merged with another vert */
-               /* follow the chain of merges to the end, or until we've passed
-               * a number of vertices equal to the copy number
-               */
-               if(copyNum <= 0)
-                       return indexMap[oldIndex].new;
-               else
-                       return calc_mapping(indexMap, indexMap[oldIndex].merge,
-                                               copyNum - 1);
-       }
-}
-
-static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
-                                         Scene *scene, Object *ob, DerivedMesh *dm,
-          int initFlags)
-{
-       int i, j;
-       /* offset matrix */
-       float offset[4][4];
-       float final_offset[4][4];
-       float tmp_mat[4][4];
-       float length = amd->length;
-       int count = amd->count;
-       int numVerts, numEdges, numFaces;
-       int maxVerts, maxEdges, maxFaces;
-       int finalVerts, finalEdges, finalFaces;
-       DerivedMesh *result, *start_cap = NULL, *end_cap = NULL;
-       MVert *mvert, *src_mvert;
-       MEdge *medge;
-       MFace *mface;
-
-       IndexMapEntry *indexMap;
-
-       EdgeHash *edges;
-
-       /* need to avoid infinite recursion here */
-       if(amd->start_cap && amd->start_cap != ob)
-               start_cap = amd->start_cap->derivedFinal;
-       if(amd->end_cap && amd->end_cap != ob)
-               end_cap = amd->end_cap->derivedFinal;
-
-       unit_m4(offset);
-
-       indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
-                                  "indexmap");
-
-       src_mvert = dm->getVertArray(dm);
-
-       maxVerts = dm->getNumVerts(dm);
-
-       if(amd->offset_type & MOD_ARR_OFF_CONST)
-               add_v3_v3v3(offset[3], offset[3], amd->offset);
-       if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
-               for(j = 0; j < 3; j++)
-                       offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
-                                       maxVerts, j);
-       }
-
-       if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
-               float obinv[4][4];
-               float result_mat[4][4];
-
-               if(ob)
-                       invert_m4_m4(obinv, ob->obmat);
-               else
-                       unit_m4(obinv);
-
-               mul_serie_m4(result_mat, offset,
-                                obinv, amd->offset_ob->obmat,
-        NULL, NULL, NULL, NULL, NULL);
-               copy_m4_m4(offset, result_mat);
-       }
-
-       if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) {
-               Curve *cu = amd->curve_ob->data;
-               if(cu) {
-                       float tmp_mat[3][3];
-                       float scale;
-                       
-                       object_to_mat3(amd->curve_ob, tmp_mat);
-                       scale = mat3_to_scale(tmp_mat);
-                               
-                       if(!cu->path) {
-                               cu->flag |= CU_PATH; // needed for path & bevlist
-                               makeDispListCurveTypes(scene, amd->curve_ob, 0);
-                       }
-                       if(cu->path)
-                               length = scale*cu->path->totdist;
-               }
-       }
-
-       /* calculate the maximum number of copies which will fit within the
-       prescribed length */
-       if(amd->fit_type == MOD_ARR_FITLENGTH
-                 || amd->fit_type == MOD_ARR_FITCURVE) {
-               float dist = sqrt(dot_v3v3(offset[3], offset[3]));
-
-               if(dist > 1e-6f)
-                       /* this gives length = first copy start to last copy end
-                       add a tiny offset for floating point rounding errors */
-                       count = (length + 1e-6f) / dist;
-               else
-                       /* if the offset has no translation, just make one copy */
-                       count = 1;
-                 }
-
-                 if(count < 1)
-                         count = 1;
-
-       /* allocate memory for count duplicates (including original) plus
-                 * start and end caps
-       */
-                 finalVerts = dm->getNumVerts(dm) * count;
-                 finalEdges = dm->getNumEdges(dm) * count;
-                 finalFaces = dm->getNumFaces(dm) * count;
-                 if(start_cap) {
-                         finalVerts += start_cap->getNumVerts(start_cap);
-                         finalEdges += start_cap->getNumEdges(start_cap);
-                         finalFaces += start_cap->getNumFaces(start_cap);
-                 }
-                 if(end_cap) {
-                         finalVerts += end_cap->getNumVerts(end_cap);
-                         finalEdges += end_cap->getNumEdges(end_cap);
-                         finalFaces += end_cap->getNumFaces(end_cap);
-                 }
-                 result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces);
-
-                 /* calculate the offset matrix of the final copy (for merging) */ 
-                 unit_m4(final_offset);
-
-                 for(j=0; j < count - 1; j++) {
-                         mul_m4_m4m4(tmp_mat, final_offset, offset);
-                         copy_m4_m4(final_offset, tmp_mat);
-                 }
-
-                 numVerts = numEdges = numFaces = 0;
-                 mvert = CDDM_get_verts(result);
-
-                 for (i = 0; i < maxVerts; i++) {
-                         indexMap[i].merge = -1; /* default to no merge */
-                         indexMap[i].merge_final = 0; /* default to no merge */
-                 }
-
-                 for (i = 0; i < maxVerts; i++) {
-                         MVert *inMV;
-                         MVert *mv = &mvert[numVerts];
-                         MVert *mv2;
-                         float co[3];
-
-                         inMV = &src_mvert[i];
-
-                         DM_copy_vert_data(dm, result, i, numVerts, 1);
-                         *mv = *inMV;
-                         numVerts++;
-
-                         indexMap[i].new = numVerts - 1;
-
-                         VECCOPY(co, mv->co);
-               
-               /* Attempts to merge verts from one duplicate with verts from the
-                         * next duplicate which are closer than amd->merge_dist.
-                         * Only the first such vert pair is merged.
-                         * If verts are merged in the first duplicate pair, they are merged
-                         * in all pairs.
-               */
-                         if((count > 1) && (amd->flags & MOD_ARR_MERGE)) {
-                                 float tmp_co[3];
-                                 VECCOPY(tmp_co, mv->co);
-                                 mul_m4_v3(offset, tmp_co);
-
-                                 for(j = 0; j < maxVerts; j++) {
-                                         /* if vertex already merged, don't use it */
-                                         if( indexMap[j].merge != -1 ) continue;
-
-                                         inMV = &src_mvert[j];
-                                         /* if this vert is within merge limit, merge */
-                                         if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist)) {
-                                                 indexMap[i].merge = j;
-
-                                                 /* test for merging with final copy of merge target */
-                                                 if(amd->flags & MOD_ARR_MERGEFINAL) {
-                                                         VECCOPY(tmp_co, inMV->co);
-                                                         inMV = &src_mvert[i];
-                                                         mul_m4_v3(final_offset, tmp_co);
-                                                         if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist))
-                                                                 indexMap[i].merge_final = 1;
-                                                 }
-                                                 break;
-                                         }
-                                 }
-                         }
-
-                         /* if no merging, generate copies of this vert */
-                         if(indexMap[i].merge < 0) {
-                                 for(j=0; j < count - 1; j++) {
-                                         mv2 = &mvert[numVerts];
-
-                                         DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
-                                         *mv2 = *mv;
-                                         numVerts++;
-
-                                         mul_m4_v3(offset, co);
-                                         VECCOPY(mv2->co, co);
-                                 }
-                         } else if(indexMap[i].merge != i && indexMap[i].merge_final) {
-                       /* if this vert is not merging with itself, and it is merging
-                                 * with the final copy of its merge target, remove the first copy
-                       */
-                                 numVerts--;
-                                 DM_free_vert_data(result, numVerts, 1);
-                         }
-                 }
-
-                 /* make a hashtable so we can avoid duplicate edges from merging */
-                 edges = BLI_edgehash_new();
-
-                 maxEdges = dm->getNumEdges(dm);
-                 medge = CDDM_get_edges(result);
-                 for(i = 0; i < maxEdges; i++) {
-                         MEdge inMED;
-                         MEdge med;
-                         MEdge *med2;
-                         int vert1, vert2;
-
-                         dm->getEdge(dm, i, &inMED);
-
-                         med = inMED;
-                         med.v1 = indexMap[inMED.v1].new;
-                         med.v2 = indexMap[inMED.v2].new;
-
-               /* if vertices are to be merged with the final copies of their
-                         * merge targets, calculate that final copy
-               */
-                         if(indexMap[inMED.v1].merge_final) {
-                                 med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge,
-                                                 count - 1);
-                         }
-                         if(indexMap[inMED.v2].merge_final) {
-                                 med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
-                                                 count - 1);
-                         }
-
-                         if(med.v1 == med.v2) continue;
-
-                         if (initFlags) {
-                                 med.flag |= ME_EDGEDRAW | ME_EDGERENDER;
-                         }
-
-                         if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) {
-                                 DM_copy_edge_data(dm, result, i, numEdges, 1);
-                                 medge[numEdges] = med;
-                                 numEdges++;
-
-                                 BLI_edgehash_insert(edges, med.v1, med.v2, NULL);
-                         }
-
-                         for(j = 1; j < count; j++)
-                         {
-                                 vert1 = calc_mapping(indexMap, inMED.v1, j);
-                                 vert2 = calc_mapping(indexMap, inMED.v2, j);
-                                 /* avoid duplicate edges */
-                                 if(!BLI_edgehash_haskey(edges, vert1, vert2)) {
-                                         med2 = &medge[numEdges];
-
-                                         DM_copy_edge_data(dm, result, i, numEdges, 1);
-                                         *med2 = med;
-                                         numEdges++;
-
-                                         med2->v1 = vert1;
-                                         med2->v2 = vert2;
-
-                                         BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL);
-                                 }
-                         }
-                 }
-
-                 maxFaces = dm->getNumFaces(dm);
-                 mface = CDDM_get_faces(result);
-                 for (i=0; i < maxFaces; i++) {
-                         MFace inMF;
-                         MFace *mf = &mface[numFaces];
-
-                         dm->getFace(dm, i, &inMF);
-
-                         DM_copy_face_data(dm, result, i, numFaces, 1);
-                         *mf = inMF;
-
-                         mf->v1 = indexMap[inMF.v1].new;
-                         mf->v2 = indexMap[inMF.v2].new;
-                         mf->v3 = indexMap[inMF.v3].new;
-                         if(inMF.v4)
-                                 mf->v4 = indexMap[inMF.v4].new;
-
-               /* if vertices are to be merged with the final copies of their
-                         * merge targets, calculate that final copy
-               */
-                         if(indexMap[inMF.v1].merge_final)
-                                 mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1);
-                         if(indexMap[inMF.v2].merge_final)
-                                 mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1);
-                         if(indexMap[inMF.v3].merge_final)
-                                 mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1);
-                         if(inMF.v4 && indexMap[inMF.v4].merge_final)
-                                 mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1);
-
-                         if(test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3) < 3)
-                                 continue;
-
-                         numFaces++;
-
-                         /* if the face has fewer than 3 vertices, don't create it */
-                         if(mf->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) {
-                                 numFaces--;
-                                 DM_free_face_data(result, numFaces, 1);
-                         }
-
-                         for(j = 1; j < count; j++)
-                         {
-                                 MFace *mf2 = &mface[numFaces];
-
-                                 DM_copy_face_data(dm, result, i, numFaces, 1);
-                                 *mf2 = *mf;
-
-                                 mf2->v1 = calc_mapping(indexMap, inMF.v1, j);
-                                 mf2->v2 = calc_mapping(indexMap, inMF.v2, j);
-                                 mf2->v3 = calc_mapping(indexMap, inMF.v3, j);
-                                 if (inMF.v4)
-                                         mf2->v4 = calc_mapping(indexMap, inMF.v4, j);
-
-                                 test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
-                                 numFaces++;
-
-                                 /* if the face has fewer than 3 vertices, don't create it */
-                                 if(mf2->v3 == 0 || (mf2->v1 && (mf2->v1 == mf2->v3 || mf2->v1 ==
-                                                                mf2->v4))) {
-                                         numFaces--;
-                                         DM_free_face_data(result, numFaces, 1);
-                                                                }
-                         }
-                 }
-
-                 /* add start and end caps */
-                 if(start_cap) {
-                         float startoffset[4][4];
-                         MVert *cap_mvert;
-                         MEdge *cap_medge;
-                         MFace *cap_mface;
-                         int *origindex;
-                         int *vert_map;
-                         int capVerts, capEdges, capFaces;
-
-                         capVerts = start_cap->getNumVerts(start_cap);
-                         capEdges = start_cap->getNumEdges(start_cap);
-                         capFaces = start_cap->getNumFaces(start_cap);
-                         cap_mvert = start_cap->getVertArray(start_cap);
-                         cap_medge = start_cap->getEdgeArray(start_cap);
-                         cap_mface = start_cap->getFaceArray(start_cap);
-
-                         invert_m4_m4(startoffset, offset);
-
-                         vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
-                                         "arrayModifier_doArray vert_map");
-
-                         origindex = result->getVertDataArray(result, CD_ORIGINDEX);
-                         for(i = 0; i < capVerts; i++) {
-                                 MVert *mv = &cap_mvert[i];
-                                 short merged = 0;
-
-                                 if(amd->flags & MOD_ARR_MERGE) {
-                                         float tmp_co[3];
-                                         MVert *in_mv;
-                                         int j;
-
-                                         VECCOPY(tmp_co, mv->co);
-                                         mul_m4_v3(startoffset, tmp_co);
-
-                                         for(j = 0; j < maxVerts; j++) {
-                                                 in_mv = &src_mvert[j];
-                                                 /* if this vert is within merge limit, merge */
-                                                 if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
-                                                         vert_map[i] = calc_mapping(indexMap, j, 0);
-                                                         merged = 1;
-                                                         break;
-                                                 }
-                                         }
-                                 }
-
-                                 if(!merged) {
-                                         DM_copy_vert_data(start_cap, result, i, numVerts, 1);
-                                         mvert[numVerts] = *mv;
-                                         mul_m4_v3(startoffset, mvert[numVerts].co);
-                                         origindex[numVerts] = ORIGINDEX_NONE;
-
-                                         vert_map[i] = numVerts;
-
-                                         numVerts++;
-                                 }
-                         }
-                         origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
-                         for(i = 0; i < capEdges; i++) {
-                                 int v1, v2;
-
-                                 v1 = vert_map[cap_medge[i].v1];
-                                 v2 = vert_map[cap_medge[i].v2];
-
-                                 if(!BLI_edgehash_haskey(edges, v1, v2)) {
-                                         DM_copy_edge_data(start_cap, result, i, numEdges, 1);
-                                         medge[numEdges] = cap_medge[i];
-                                         medge[numEdges].v1 = v1;
-                                         medge[numEdges].v2 = v2;
-                                         origindex[numEdges] = ORIGINDEX_NONE;
-
-                                         numEdges++;
-                                 }
-                         }
-                         origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
-                         for(i = 0; i < capFaces; i++) {
-                                 DM_copy_face_data(start_cap, result, i, numFaces, 1);
-                                 mface[numFaces] = cap_mface[i];
-                                 mface[numFaces].v1 = vert_map[mface[numFaces].v1];
-                                 mface[numFaces].v2 = vert_map[mface[numFaces].v2];
-                                 mface[numFaces].v3 = vert_map[mface[numFaces].v3];
-                                 if(mface[numFaces].v4) {
-                                         mface[numFaces].v4 = vert_map[mface[numFaces].v4];
-
-                                         test_index_face(&mface[numFaces], &result->faceData,
-                                                                         numFaces, 4);
-                                 }
-                                 else
-                                 {
-                                         test_index_face(&mface[numFaces], &result->faceData,
-                                                                         numFaces, 3);
-                                 }
-
-                                 origindex[numFaces] = ORIGINDEX_NONE;
-
-                                 numFaces++;
-                         }
-
-                         MEM_freeN(vert_map);
-                         start_cap->release(start_cap);
-                 }
-
-                 if(end_cap) {
-                         float endoffset[4][4];
-                         MVert *cap_mvert;
-                         MEdge *cap_medge;
-                         MFace *cap_mface;
-                         int *origindex;
-                         int *vert_map;
-                         int capVerts, capEdges, capFaces;
-
-                         capVerts = end_cap->getNumVerts(end_cap);
-                         capEdges = end_cap->getNumEdges(end_cap);
-                         capFaces = end_cap->getNumFaces(end_cap);
-                         cap_mvert = end_cap->getVertArray(end_cap);
-                         cap_medge = end_cap->getEdgeArray(end_cap);
-                         cap_mface = end_cap->getFaceArray(end_cap);
-
-                         mul_m4_m4m4(endoffset, final_offset, offset);
-
-                         vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
-                                         "arrayModifier_doArray vert_map");
-
-                         origindex = result->getVertDataArray(result, CD_ORIGINDEX);
-                         for(i = 0; i < capVerts; i++) {
-                                 MVert *mv = &cap_mvert[i];
-                                 short merged = 0;
-
-                                 if(amd->flags & MOD_ARR_MERGE) {
-                                         float tmp_co[3];
-                                         MVert *in_mv;
-                                         int j;
-
-                                         VECCOPY(tmp_co, mv->co);
-                                         mul_m4_v3(offset, tmp_co);
-
-                                         for(j = 0; j < maxVerts; j++) {
-                                                 in_mv = &src_mvert[j];
-                                                 /* if this vert is within merge limit, merge */
-                                                 if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) {
-                                                         vert_map[i] = calc_mapping(indexMap, j, count - 1);
-                                                         merged = 1;
-                                                         break;
-                                                 }
-                                         }
-                                 }
-
-                                 if(!merged) {
-                                         DM_copy_vert_data(end_cap, result, i, numVerts, 1);
-                                         mvert[numVerts] = *mv;
-                                         mul_m4_v3(endoffset, mvert[numVerts].co);
-                                         origindex[numVerts] = ORIGINDEX_NONE;
-
-                                         vert_map[i] = numVerts;
-
-                                         numVerts++;
-                                 }
-                         }
-                         origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
-                         for(i = 0; i < capEdges; i++) {
-                                 int v1, v2;
-
-                                 v1 = vert_map[cap_medge[i].v1];
-                                 v2 = vert_map[cap_medge[i].v2];
-
-                                 if(!BLI_edgehash_haskey(edges, v1, v2)) {
-                                         DM_copy_edge_data(end_cap, result, i, numEdges, 1);
-                                         medge[numEdges] = cap_medge[i];
-                                         medge[numEdges].v1 = v1;
-                                         medge[numEdges].v2 = v2;
-                                         origindex[numEdges] = ORIGINDEX_NONE;
-
-                                         numEdges++;
-                                 }
-                         }
-                         origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
-                         for(i = 0; i < capFaces; i++) {
-                                 DM_copy_face_data(end_cap, result, i, numFaces, 1);
-                                 mface[numFaces] = cap_mface[i];
-                                 mface[numFaces].v1 = vert_map[mface[numFaces].v1];
-                                 mface[numFaces].v2 = vert_map[mface[numFaces].v2];
-                                 mface[numFaces].v3 = vert_map[mface[numFaces].v3];
-                                 if(mface[numFaces].v4) {
-                                         mface[numFaces].v4 = vert_map[mface[numFaces].v4];
-
-                                         test_index_face(&mface[numFaces], &result->faceData,
-                                                                         numFaces, 4);
-                                 }
-                                 else
-                                 {
-                                         test_index_face(&mface[numFaces], &result->faceData,
-                                                                         numFaces, 3);
-                                 }
-                                 origindex[numFaces] = ORIGINDEX_NONE;
-
-                                 numFaces++;
-                         }
-
-                         MEM_freeN(vert_map);
-                         end_cap->release(end_cap);
-                 }
-
-                 BLI_edgehash_free(edges, NULL);
-                 MEM_freeN(indexMap);
-
-                 CDDM_lower_num_verts(result, numVerts);
-                 CDDM_lower_num_edges(result, numEdges);
-                 CDDM_lower_num_faces(result, numFaces);
-
-                 return result;
-}
-
-static DerivedMesh *arrayModifier_applyModifier(
-               ModifierData *md, Object *ob, DerivedMesh *derivedData,
-  int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *result;
-       ArrayModifierData *amd = (ArrayModifierData*) md;
-
-       result = arrayModifier_doArray(amd, md->scene, ob, derivedData, 0);
-
-       if(result != derivedData)
-               CDDM_calc_normals(result);
-
-       return result;
-}
-
-static DerivedMesh *arrayModifier_applyModifierEM(
-               ModifierData *md, Object *ob, EditMesh *editData,
-  DerivedMesh *derivedData)
-{
-       return arrayModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Mirror */
-
-static void mirrorModifier_initData(ModifierData *md)
-{
-       MirrorModifierData *mmd = (MirrorModifierData*) md;
-
-       mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP);
-       mmd->tolerance = 0.001;
-       mmd->mirror_ob = NULL;
-}
-
-static void mirrorModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       MirrorModifierData *mmd = (MirrorModifierData*) md;
-       MirrorModifierData *tmmd = (MirrorModifierData*) target;
-
-       tmmd->axis = mmd->axis;
-       tmmd->flag = mmd->flag;
-       tmmd->tolerance = mmd->tolerance;
-       tmmd->mirror_ob = mmd->mirror_ob;;
-}
-
-static void mirrorModifier_foreachObjectLink(
-                                                ModifierData *md, Object *ob,
-         void (*walk)(void *userData, Object *ob, Object **obpoin),
-                void *userData)
-{
-       MirrorModifierData *mmd = (MirrorModifierData*) md;
-
-       walk(userData, ob, &mmd->mirror_ob);
-}
-
-static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
-                                         Object *ob, DagNode *obNode)
-{
-       MirrorModifierData *mmd = (MirrorModifierData*) md;
-
-       if(mmd->mirror_ob) {
-               DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
-
-               dag_add_relation(forest, latNode, obNode,
-                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier");
-       }
-}
-
-static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
-               Object *ob,
-               DerivedMesh *dm,
-               int initFlags,
-               int axis)
-{
-       int i;
-       float tolerance = mmd->tolerance;
-       DerivedMesh *result;
-       int numVerts, numEdges, numFaces;
-       int maxVerts = dm->getNumVerts(dm);
-       int maxEdges = dm->getNumEdges(dm);
-       int maxFaces = dm->getNumFaces(dm);
-       int *flip_map= NULL;
-       int do_vgroup_mirr= (mmd->flag & MOD_MIR_VGROUP);
-       int (*indexMap)[2];
-       float mtx[4][4], imtx[4][4];
-
-       numVerts = numEdges = numFaces = 0;
-
-       indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
-
-       result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
-
-
-       if (do_vgroup_mirr) {
-               flip_map= defgroup_flip_map(ob, 0);
-               if(flip_map == NULL)
-                       do_vgroup_mirr= 0;
-       }
-
-       if (mmd->mirror_ob) {
-               float obinv[4][4];
-               
-               invert_m4_m4(obinv, mmd->mirror_ob->obmat);
-               mul_m4_m4m4(mtx, ob->obmat, obinv);
-               invert_m4_m4(imtx, mtx);
-       }
-
-       for(i = 0; i < maxVerts; i++) {
-               MVert inMV;
-               MVert *mv = CDDM_get_vert(result, numVerts);
-               int isShared;
-               float co[3];
-               
-               dm->getVert(dm, i, &inMV);
-               
-               copy_v3_v3(co, inMV.co);
-               
-               if (mmd->mirror_ob) {
-                       mul_v3_m4v3(co, mtx, co);
-               }
-               isShared = ABS(co[axis])<=tolerance;
-               
-               /* Because the topology result (# of vertices) must be the same if
-               * the mesh data is overridden by vertex cos, have to calc sharedness
-               * based on original coordinates. This is why we test before copy.
-               */
-               DM_copy_vert_data(dm, result, i, numVerts, 1);
-               *mv = inMV;
-               numVerts++;
-               
-               indexMap[i][0] = numVerts - 1;
-               indexMap[i][1] = !isShared;
-               
-               if(isShared) {
-                       co[axis] = 0;
-                       if (mmd->mirror_ob) {
-                               mul_v3_m4v3(co, imtx, co);
-                       }
-                       copy_v3_v3(mv->co, co);
-                       
-                       mv->flag |= ME_VERT_MERGED;
-               } else {
-                       MVert *mv2 = CDDM_get_vert(result, numVerts);
-                       
-                       DM_copy_vert_data(dm, result, i, numVerts, 1);
-                       *mv2 = *mv;
-                       
-                       co[axis] = -co[axis];
-                       if (mmd->mirror_ob) {
-                               mul_v3_m4v3(co, imtx, co);
-                       }
-                       copy_v3_v3(mv2->co, co);
-                       
-                       if (do_vgroup_mirr) {
-                               MDeformVert *dvert= DM_get_vert_data(result, numVerts, CD_MDEFORMVERT);
-                               if(dvert) {
-                                       defvert_flip(dvert, flip_map);
-                               }
-                       }
-
-                       numVerts++;
-               }
-       }
-
-       for(i = 0; i < maxEdges; i++) {
-               MEdge inMED;
-               MEdge *med = CDDM_get_edge(result, numEdges);
-               
-               dm->getEdge(dm, i, &inMED);
-               
-               DM_copy_edge_data(dm, result, i, numEdges, 1);
-               *med = inMED;
-               numEdges++;
-               
-               med->v1 = indexMap[inMED.v1][0];
-               med->v2 = indexMap[inMED.v2][0];
-               if(initFlags)
-                       med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
-               
-               if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
-                       MEdge *med2 = CDDM_get_edge(result, numEdges);
-                       
-                       DM_copy_edge_data(dm, result, i, numEdges, 1);
-                       *med2 = *med;
-                       numEdges++;
-                       
-                       med2->v1 += indexMap[inMED.v1][1];
-                       med2->v2 += indexMap[inMED.v2][1];
-               }
-       }
-
-       for(i = 0; i < maxFaces; i++) {
-               MFace inMF;
-               MFace *mf = CDDM_get_face(result, numFaces);
-               
-               dm->getFace(dm, i, &inMF);
-               
-               DM_copy_face_data(dm, result, i, numFaces, 1);
-               *mf = inMF;
-               numFaces++;
-               
-               mf->v1 = indexMap[inMF.v1][0];
-               mf->v2 = indexMap[inMF.v2][0];
-               mf->v3 = indexMap[inMF.v3][0];
-               mf->v4 = indexMap[inMF.v4][0];
-               
-               if(indexMap[inMF.v1][1]
-                                || indexMap[inMF.v2][1]
-                                || indexMap[inMF.v3][1]
-                                || (mf->v4 && indexMap[inMF.v4][1])) {
-                       MFace *mf2 = CDDM_get_face(result, numFaces);
-                       static int corner_indices[4] = {2, 1, 0, 3};
-                       
-                       DM_copy_face_data(dm, result, i, numFaces, 1);
-                       *mf2 = *mf;
-                       
-                       mf2->v1 += indexMap[inMF.v1][1];
-                       mf2->v2 += indexMap[inMF.v2][1];
-                       mf2->v3 += indexMap[inMF.v3][1];
-                       if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
-                       
-                       /* mirror UVs if enabled */
-                       if(mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V)) {
-                               MTFace *tf = result->getFaceData(result, numFaces, CD_MTFACE);
-                               if(tf) {
-                                       int j;
-                                       for(j = 0; j < 4; ++j) {
-                                               if(mmd->flag & MOD_MIR_MIRROR_U)
-                                                       tf->uv[j][0] = 1.0f - tf->uv[j][0];
-                                               if(mmd->flag & MOD_MIR_MIRROR_V)
-                                                       tf->uv[j][1] = 1.0f - tf->uv[j][1];
-                                       }
-                               }
-                       }
-                       
-                       /* Flip face normal */
-                       SWAP(int, mf2->v1, mf2->v3);
-                       DM_swap_face_data(result, numFaces, corner_indices);
-                       
-                       test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
-                       numFaces++;
-               }
-       }
-
-       if (flip_map) MEM_freeN(flip_map);
-
-       MEM_freeN(indexMap);
-
-       CDDM_lower_num_verts(result, numVerts);
-       CDDM_lower_num_edges(result, numEdges);
-       CDDM_lower_num_faces(result, numFaces);
-
-       return result;
-}
-
-static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
-                                               Object *ob, DerivedMesh *dm,
-                                               int initFlags)
-{
-       DerivedMesh *result = dm;
-
-       /* check which axes have been toggled and mirror accordingly */
-       if(mmd->flag & MOD_MIR_AXIS_X) {
-               result = doMirrorOnAxis(mmd, ob, result, initFlags, 0);
-       }
-       if(mmd->flag & MOD_MIR_AXIS_Y) {
-               DerivedMesh *tmp = result;
-               result = doMirrorOnAxis(mmd, ob, result, initFlags, 1);
-               if(tmp != dm) tmp->release(tmp); /* free intermediate results */
-       }
-       if(mmd->flag & MOD_MIR_AXIS_Z) {
-               DerivedMesh *tmp = result;
-               result = doMirrorOnAxis(mmd, ob, result, initFlags, 2);
-               if(tmp != dm) tmp->release(tmp); /* free intermediate results */
-       }
-
-       return result;
-}
-
-static DerivedMesh *mirrorModifier_applyModifier(
-               ModifierData *md, Object *ob, DerivedMesh *derivedData,
-  int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *result;
-       MirrorModifierData *mmd = (MirrorModifierData*) md;
-
-       result = mirrorModifier__doMirror(mmd, ob, derivedData, 0);
-
-       if(result != derivedData)
-               CDDM_calc_normals(result);
-       
-       return result;
-}
-
-static DerivedMesh *mirrorModifier_applyModifierEM(
-               ModifierData *md, Object *ob, EditMesh *editData,
-  DerivedMesh *derivedData)
-{
-       return mirrorModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* EdgeSplit */
-/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
- * or edge angle (can be used to achieve autosmoothing)
-*/
-#if 0
-#define EDGESPLIT_DEBUG_3
-#define EDGESPLIT_DEBUG_2
-#define EDGESPLIT_DEBUG_1
-#define EDGESPLIT_DEBUG_0
-#endif
-
-static void edgesplitModifier_initData(ModifierData *md)
-{
-       EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
-
-       /* default to 30-degree split angle, sharpness from both angle & flag
-       */
-       emd->split_angle = 30;
-       emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
-}
-
-static void edgesplitModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
-       EdgeSplitModifierData *temd = (EdgeSplitModifierData*) target;
-
-       temd->split_angle = emd->split_angle;
-       temd->flags = emd->flags;
-}
-
-/* Mesh data for edgesplit operation */
-typedef struct SmoothVert {
-       LinkNode *faces;     /* all faces which use this vert */
-       int oldIndex; /* the index of the original DerivedMesh vert */
-       int newIndex; /* the index of the new DerivedMesh vert */
-} SmoothVert;
-
-#define SMOOTHEDGE_NUM_VERTS 2
-
-typedef struct SmoothEdge {
-       SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
-       LinkNode *faces;     /* all faces which use this edge */
-       int oldIndex; /* the index of the original DerivedMesh edge */
-       int newIndex; /* the index of the new DerivedMesh edge */
-       short flag; /* the flags from the original DerivedMesh edge */
-} SmoothEdge;
-
-#define SMOOTHFACE_MAX_EDGES 4
-
-typedef struct SmoothFace {
-       SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
-       int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
-       float normal[3]; /* the normal of this face */
-       int oldIndex; /* the index of the original DerivedMesh face */
-       int newIndex; /* the index of the new DerivedMesh face */
-} SmoothFace;
-
-typedef struct SmoothMesh {
-       SmoothVert *verts;
-       SmoothEdge *edges;
-       SmoothFace *faces;
-       int num_verts, num_edges, num_faces;
-       int max_verts, max_edges, max_faces;
-       DerivedMesh *dm;
-       float threshold; /* the cosine of the smoothing angle */
-       int flags;
-       MemArena *arena;
-       ListBase propagatestack, reusestack;
-} SmoothMesh;
-
-static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
-{
-       SmoothVert *copy = &mesh->verts[mesh->num_verts];
-
-       if(mesh->num_verts >= mesh->max_verts) {
-               printf("Attempted to add a SmoothMesh vert beyond end of array\n");
-               return NULL;
-       }
-
-       *copy = *vert;
-       copy->faces = NULL;
-       copy->newIndex = mesh->num_verts;
-       ++mesh->num_verts;
-
-#ifdef EDGESPLIT_DEBUG_2
-       printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
-#endif
-       return copy;
-}
-
-static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
-{
-       SmoothEdge *copy = &mesh->edges[mesh->num_edges];
-
-       if(mesh->num_edges >= mesh->max_edges) {
-               printf("Attempted to add a SmoothMesh edge beyond end of array\n");
-               return NULL;
-       }
-
-       *copy = *edge;
-       copy->faces = NULL;
-       copy->newIndex = mesh->num_edges;
-       ++mesh->num_edges;
-
-#ifdef EDGESPLIT_DEBUG_2
-       printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
-#endif
-       return copy;
-}
-
-static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
-{
-       int i;
-       for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
-               if(edge->verts[i] == vert) return 1;
-
-       return 0;
-}
-
-static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
-                                 int max_verts, int max_edges, int max_faces)
-{
-       SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
-       mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
-                                 "SmoothMesh.verts");
-       mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
-                                 "SmoothMesh.edges");
-       mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
-                                 "SmoothMesh.faces");
-
-       mesh->num_verts = num_verts;
-       mesh->num_edges = num_edges;
-       mesh->num_faces = num_faces;
-
-       mesh->max_verts = max_verts;
-       mesh->max_edges = max_edges;
-       mesh->max_faces = max_faces;
-
-       return mesh;
-}
-
-static void smoothmesh_free(SmoothMesh *mesh)
-{
-       int i;
-
-       for(i = 0; i < mesh->num_verts; ++i)
-               BLI_linklist_free(mesh->verts[i].faces, NULL);
-
-       for(i = 0; i < mesh->num_edges; ++i)
-               BLI_linklist_free(mesh->edges[i].faces, NULL);
-       
-       if(mesh->arena)
-               BLI_memarena_free(mesh->arena);
-
-       MEM_freeN(mesh->verts);
-       MEM_freeN(mesh->edges);
-       MEM_freeN(mesh->faces);
-       MEM_freeN(mesh);
-}
-
-static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
-{
-       int i;
-       SmoothVert *tmp;
-
-       if(max_verts <= mesh->max_verts) return;
-
-       tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
-
-       memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
-
-       /* remap vert pointers in edges */
-       for(i = 0; i < mesh->num_edges; ++i) {
-               int j;
-               SmoothEdge *edge = &mesh->edges[i];
-
-               for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
-                       /* pointer arithmetic to get vert array index */
-                       edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
-       }
-
-       MEM_freeN(mesh->verts);
-       mesh->verts = tmp;
-       mesh->max_verts = max_verts;
-}
-
-static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
-{
-       int i;
-       SmoothEdge *tmp;
-
-       if(max_edges <= mesh->max_edges) return;
-
-       tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
-
-       memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
-
-       /* remap edge pointers in faces */
-       for(i = 0; i < mesh->num_faces; ++i) {
-               int j;
-               SmoothFace *face = &mesh->faces[i];
-
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
-                       if(face->edges[j])
-                               /* pointer arithmetic to get edge array index */
-                               face->edges[j] = &tmp[face->edges[j] - mesh->edges];
-       }
-
-       MEM_freeN(mesh->edges);
-       mesh->edges = tmp;
-       mesh->max_edges = max_edges;
-}
-
-#ifdef EDGESPLIT_DEBUG_0
-static void smoothmesh_print(SmoothMesh *mesh)
-{
-       int i, j;
-       DerivedMesh *dm = mesh->dm;
-
-       printf("--- SmoothMesh ---\n");
-       printf("--- Vertices ---\n");
-       for(i = 0; i < mesh->num_verts; i++) {
-               SmoothVert *vert = &mesh->verts[i];
-               LinkNode *node;
-               MVert mv;
-
-               dm->getVert(dm, vert->oldIndex, &mv);
-
-               printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
-                          i, vert->oldIndex, vert->newIndex,
-        mv.co[0], mv.co[1], mv.co[2]);
-               printf(", faces={");
-               for(node = vert->faces; node != NULL; node = node->next) {
-                       printf(" %d", ((SmoothFace *)node->link)->newIndex);
-               }
-               printf("}\n");
-       }
-
-       printf("\n--- Edges ---\n");
-       for(i = 0; i < mesh->num_edges; i++) {
-               SmoothEdge *edge = &mesh->edges[i];
-               LinkNode *node;
-
-               printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
-                          i,
-        edge->oldIndex, edge->newIndex,
-  edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-               if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
-               printf(", faces={");
-               for(node = edge->faces; node != NULL; node = node->next) {
-                       printf(" %d", ((SmoothFace *)node->link)->newIndex);
-               }
-               printf("}\n");
-       }
-
-       printf("\n--- Faces ---\n");
-       for(i = 0; i < mesh->num_faces; i++) {
-               SmoothFace *face = &mesh->faces[i];
-
-               printf("%4d: indices={%4d, %4d}, edges={", i,
-                          face->oldIndex, face->newIndex);
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       if(face->flip[j])
-                               printf(" -%-2d", face->edges[j]->newIndex);
-                       else
-                               printf("  %-2d", face->edges[j]->newIndex);
-               }
-               printf("}, verts={");
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
-               }
-               printf("}\n");
-       }
-}
-#endif
-
-static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
-{
-       SmoothMesh *mesh;
-       EdgeHash *edges = BLI_edgehash_new();
-       int i;
-       int totvert, totedge, totface;
-
-       totvert = dm->getNumVerts(dm);
-       totedge = dm->getNumEdges(dm);
-       totface = dm->getNumFaces(dm);
-
-       mesh = smoothmesh_new(totvert, totedge, totface,
-                                 totvert, totedge, totface);
-
-       mesh->dm = dm;
-
-       for(i = 0; i < totvert; i++) {
-               SmoothVert *vert = &mesh->verts[i];
-
-               vert->oldIndex = vert->newIndex = i;
-       }
-
-       for(i = 0; i < totedge; i++) {
-               SmoothEdge *edge = &mesh->edges[i];
-               MEdge med;
-
-               dm->getEdge(dm, i, &med);
-               edge->verts[0] = &mesh->verts[med.v1];
-               edge->verts[1] = &mesh->verts[med.v2];
-               edge->oldIndex = edge->newIndex = i;
-               edge->flag = med.flag;
-
-               BLI_edgehash_insert(edges, med.v1, med.v2, edge);
-       }
-
-       for(i = 0; i < totface; i++) {
-               SmoothFace *face = &mesh->faces[i];
-               MFace mf;
-               MVert v1, v2, v3;
-               int j;
-
-               dm->getFace(dm, i, &mf);
-
-               dm->getVert(dm, mf.v1, &v1);
-               dm->getVert(dm, mf.v2, &v2);
-               dm->getVert(dm, mf.v3, &v3);
-               face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
-               if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
-               face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
-               if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
-               if(mf.v4) {
-                       MVert v4;
-                       dm->getVert(dm, mf.v4, &v4);
-                       face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
-                       if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
-                       face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
-                       if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
-                       normal_quad_v3( face->normal,v1.co, v2.co, v3.co, v4.co);
-               } else {
-                       face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
-                       if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
-                       face->edges[3] = NULL;
-                       normal_tri_v3( face->normal,v1.co, v2.co, v3.co);
-               }
-
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       SmoothEdge *edge = face->edges[j];
-                       BLI_linklist_prepend(&edge->faces, face);
-                       BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
-               }
-
-               face->oldIndex = face->newIndex = i;
-       }
-
-       BLI_edgehash_free(edges, NULL);
-
-       return mesh;
-}
-
-static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
-{
-       DerivedMesh *result = CDDM_from_template(mesh->dm,
-                       mesh->num_verts,
-   mesh->num_edges,
-   mesh->num_faces);
-       MVert *new_verts = CDDM_get_verts(result);
-       MEdge *new_edges = CDDM_get_edges(result);
-       MFace *new_faces = CDDM_get_faces(result);
-       int i;
-
-       for(i = 0; i < mesh->num_verts; ++i) {
-               SmoothVert *vert = &mesh->verts[i];
-               MVert *newMV = &new_verts[vert->newIndex];
-
-               DM_copy_vert_data(mesh->dm, result,
-                                 vert->oldIndex, vert->newIndex, 1);
-               mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
-       }
-
-       for(i = 0; i < mesh->num_edges; ++i) {
-               SmoothEdge *edge = &mesh->edges[i];
-               MEdge *newME = &new_edges[edge->newIndex];
-
-               DM_copy_edge_data(mesh->dm, result,
-                                 edge->oldIndex, edge->newIndex, 1);
-               mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
-               newME->v1 = edge->verts[0]->newIndex;
-               newME->v2 = edge->verts[1]->newIndex;
-       }
-
-       for(i = 0; i < mesh->num_faces; ++i) {
-               SmoothFace *face = &mesh->faces[i];
-               MFace *newMF = &new_faces[face->newIndex];
-
-               DM_copy_face_data(mesh->dm, result,
-                                 face->oldIndex, face->newIndex, 1);
-               mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
-
-               newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
-               newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
-               newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
-
-               if(face->edges[3]) {
-                       newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
-               } else {
-                       newMF->v4 = 0;
-               }
-       }
-
-       return result;
-}
-
-/* returns the other vert in the given edge
- */
-static SmoothVert *other_vert(SmoothEdge *edge, SmoothVert *vert)
-{
-       if(edge->verts[0] == vert) return edge->verts[1];
-       else return edge->verts[0];
-}
-
-/* returns the other edge in the given face that uses the given vert
- * returns NULL if no other edge in the given face uses the given vert
- * (this should never happen)
- */
-static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
-                                 SmoothEdge *edge)
-{
-       int i,j;
-       for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
-               SmoothEdge *tmp_edge = face->edges[i];
-               if(tmp_edge == edge) continue;
-
-               for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
-                       if(tmp_edge->verts[j] == vert) return tmp_edge;
-       }
-
-       /* if we get to here, something's wrong (there should always be 2 edges
-       * which use the same vert in a face)
-       */
-       return NULL;
-}
-
-/* returns a face attached to the given edge which is not the given face.
- * returns NULL if no other faces use this edge.
- */
-static SmoothFace *other_face(SmoothEdge *edge, SmoothFace *face)
-{
-       LinkNode *node;
-
-       for(node = edge->faces; node != NULL; node = node->next)
-               if(node->link != face) return node->link;
-
-       return NULL;
-}
-
-#if 0
-/* copies source list to target, overwriting target (target is not freed)
- * nodes in the copy will be in the same order as in source
- */
-static void linklist_copy(LinkNode **target, LinkNode *source)
-{
-       LinkNode *node = NULL;
-       *target = NULL;
-
-       for(; source; source = source->next) {
-               if(node) {
-                       node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
-                                                                               node = node->next;
-} else {
-                                                                               node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
-}
-                                                                               node->link = source->link;
-                                                                               node->next = NULL;
-}
-}
-#endif
-
-                                                                               /* appends source to target if it's not already in target */
-                                                                               static void linklist_append_unique(LinkNode **target, void *source) 
-{
-       LinkNode *node;
-       LinkNode *prev = NULL;
-
-       /* check if source value is already in the list */
-       for(node = *target; node; prev = node, node = node->next)
-               if(node->link == source) return;
-
-       node = MEM_mallocN(sizeof(*node), "nlink");
-       node->next = NULL;
-       node->link = source;
-
-       if(prev) prev->next = node;
-       else *target = node;
-}
-
-/* appends elements of source which aren't already in target to target */
-static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
-{
-       for(; source; source = source->next)
-               linklist_append_unique(target, source->link);
-}
-
-#if 0 /* this is no longer used, it should possibly be removed */
-/* prepends prepend to list - doesn't copy nodes, just joins the lists */
-static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
-{
-       if(prepend) {
-               LinkNode *node = prepend;
-               while(node->next) node = node->next;
-
-               node->next = *list;
-               *list = prepend;
-}
-}
-#endif
-
-/* returns 1 if the linked list contains the given pointer, 0 otherwise
- */
-static int linklist_contains(LinkNode *list, void *ptr)
-{
-       LinkNode *node;
-
-       for(node = list; node; node = node->next)
-               if(node->link == ptr) return 1;
-
-       return 0;
-}
-
-/* returns 1 if the first linked list is a subset of the second (comparing
- * pointer values), 0 if not
- */
-static int linklist_subset(LinkNode *list1, LinkNode *list2)
-{
-       for(; list1; list1 = list1->next)
-               if(!linklist_contains(list2, list1->link))
-                       return 0;
-
-       return 1;
-}
-
-#if 0
-/* empties the linked list
- * frees pointers with freefunc if freefunc is not NULL
- */
-static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
-{
-       BLI_linklist_free(*list, freefunc);
-       *list = NULL;
-}
-#endif
-
-/* removes the first instance of value from the linked list
- * frees the pointer with freefunc if freefunc is not NULL
- */
-static void linklist_remove_first(LinkNode **list, void *value,
-                                 LinkNodeFreeFP freefunc)
-{
-       LinkNode *node = *list;
-       LinkNode *prev = NULL;
-
-       while(node && node->link != value) {
-               prev = node;
-               node = node->next;
-       }
-
-       if(node) {
-               if(prev)
-                       prev->next = node->next;
-               else
-                       *list = node->next;
-
-               if(freefunc)
-                       freefunc(node->link);
-
-               MEM_freeN(node);
-       }
-}
-
-/* removes all elements in source from target */
-static void linklist_remove_list(LinkNode **target, LinkNode *source,
-                                LinkNodeFreeFP freefunc)
-{
-       for(; source; source = source->next)
-               linklist_remove_first(target, source->link, freefunc);
-}
-
-#ifdef EDGESPLIT_DEBUG_0
-static void print_ptr(void *ptr)
-{
-       printf("%p\n", ptr);
-}
-
-static void print_edge(void *ptr)
-{
-       SmoothEdge *edge = ptr;
-       printf(" %4d", edge->newIndex);
-}
-
-static void print_face(void *ptr)
-{
-       SmoothFace *face = ptr;
-       printf(" %4d", face->newIndex);
-}
-#endif
-
-typedef struct ReplaceData {
-       void *find;
-       void *replace;
-} ReplaceData;
-
-static void edge_replace_vert(void *ptr, void *userdata)
-{
-       SmoothEdge *edge = ptr;
-       SmoothVert *find = ((ReplaceData *)userdata)->find;
-       SmoothVert *replace = ((ReplaceData *)userdata)->replace;
-       int i;
-
-#ifdef EDGESPLIT_DEBUG_3
-       printf("replacing vert %4d with %4d in edge %4d",
-                  find->newIndex, replace->newIndex, edge->newIndex);
-       printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
-
-       for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
-               if(edge->verts[i] == find) {
-                       linklist_append_list_unique(&replace->faces, edge->faces);
-                       linklist_remove_list(&find->faces, edge->faces, NULL);
-
-                       edge->verts[i] = replace;
-               }
-       }
-
-#ifdef EDGESPLIT_DEBUG_3
-       printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
-#endif
-}
-
-static void face_replace_vert(void *ptr, void *userdata)
-{
-       SmoothFace *face = ptr;
-       int i;
-
-       for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
-               edge_replace_vert(face->edges[i], userdata);
-}
-
-static void face_replace_edge(void *ptr, void *userdata)
-{
-       SmoothFace *face = ptr;
-       SmoothEdge *find = ((ReplaceData *)userdata)->find;
-       SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
-       int i;
-
-#ifdef EDGESPLIT_DEBUG_3
-       printf("replacing edge %4d with %4d in face %4d",
-                  find->newIndex, replace->newIndex, face->newIndex);
-       if(face->edges[3])
-               printf(": {%2d %2d %2d %2d}",
-                          face->edges[0]->newIndex, face->edges[1]->newIndex,
-        face->edges[2]->newIndex, face->edges[3]->newIndex);
-       else
-               printf(": {%2d %2d %2d}",
-                          face->edges[0]->newIndex, face->edges[1]->newIndex,
-        face->edges[2]->newIndex);
-#endif
-
-       for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
-               if(face->edges[i] == find) {
-                       linklist_remove_first(&face->edges[i]->faces, face, NULL);
-                       BLI_linklist_prepend(&replace->faces, face);
-                       face->edges[i] = replace;
-               }
-       }
-
-#ifdef EDGESPLIT_DEBUG_3
-       if(face->edges[3])
-               printf(" -> {%2d %2d %2d %2d}\n",
-                          face->edges[0]->newIndex, face->edges[1]->newIndex,
-        face->edges[2]->newIndex, face->edges[3]->newIndex);
-       else
-               printf(" -> {%2d %2d %2d}\n",
-                          face->edges[0]->newIndex, face->edges[1]->newIndex,
-        face->edges[2]->newIndex);
-#endif
-}
-
-static int edge_is_loose(SmoothEdge *edge)
-{
-       return !(edge->faces && edge->faces->next);
-}
-
-static int edge_is_sharp(SmoothEdge *edge, int flags,
-                        float threshold)
-{
-#ifdef EDGESPLIT_DEBUG_1
-       printf("edge %d: ", edge->newIndex);
-#endif
-       if(edge->flag & ME_SHARP) {
-               /* edge can only be sharp if it has at least 2 faces */
-               if(!edge_is_loose(edge)) {
-#ifdef EDGESPLIT_DEBUG_1
-                       printf("sharp\n");
-#endif
-                       return 1;
-               } else {
-                       /* edge is loose, so it can't be sharp */
-                       edge->flag &= ~ME_SHARP;
-               }
-       }
-
-#ifdef EDGESPLIT_DEBUG_1
-       printf("not sharp\n");
-#endif
-       return 0;
-}
-
-/* finds another sharp edge which uses vert, by traversing faces around the
- * vert until it does one of the following:
- * - hits a loose edge (the edge is returned)
- * - hits a sharp edge (the edge is returned)
- * - returns to the start edge (NULL is returned)
- */
-static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge,
-                                        LinkNode **visited_faces, float threshold, int flags)
-{
-       SmoothFace *face = NULL;
-       SmoothEdge *edge2 = NULL;
-       /* holds the edges we've seen so we can avoid looping indefinitely */
-       LinkNode *visited_edges = NULL;
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
-
-       /* get a face on which to start */
-       if(edge->faces) face = edge->faces->link;
-       else return NULL;
-
-       /* record this edge as visited */
-       BLI_linklist_prepend(&visited_edges, edge);
-
-       /* get the next edge */
-       edge2 = other_edge(face, vert, edge);
-
-       /* record this face as visited */
-       if(visited_faces)
-               BLI_linklist_prepend(visited_faces, face);
-
-       /* search until we hit a loose edge or a sharp edge or an edge we've
-       * seen before
-       */
-       while(face && !edge_is_sharp(edge2, flags, threshold)
-                        && !linklist_contains(visited_edges, edge2)) {
-#ifdef EDGESPLIT_DEBUG_3
-               printf("current face %4d; current edge %4d\n", face->newIndex,
-                          edge2->newIndex);
-#endif
-               /* get the next face */
-               face = other_face(edge2, face);
-
-               /* if face == NULL, edge2 is a loose edge */
-               if(face) {
-                       /* record this face as visited */
-                       if(visited_faces)
-                               BLI_linklist_prepend(visited_faces, face);
-
-                       /* record this edge as visited */
-                       BLI_linklist_prepend(&visited_edges, edge2);
-
-                       /* get the next edge */
-                       edge2 = other_edge(face, vert, edge2);
-#ifdef EDGESPLIT_DEBUG_3
-                       printf("next face %4d; next edge %4d\n",
-                                  face->newIndex, edge2->newIndex);
-               } else {
-                       printf("loose edge: %4d\n", edge2->newIndex);
-#endif
-               }
-                        }
-
-                        /* either we came back to the start edge or we found a sharp/loose edge */
-                        if(linklist_contains(visited_edges, edge2))
-                                /* we came back to the start edge */
-                                edge2 = NULL;
-
-                        BLI_linklist_free(visited_edges, NULL);
-
-#ifdef EDGESPLIT_DEBUG_1
-                        printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), "
-                                        "returning edge %d\n",
-        edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1);
-#endif
-                        return edge2;
-}
-
-static void split_single_vert(SmoothVert *vert, SmoothFace *face,
-                                 SmoothMesh *mesh)
-{
-       SmoothVert *copy_vert;
-       ReplaceData repdata;
-
-       copy_vert = smoothvert_copy(vert, mesh);
-
-       repdata.find = vert;
-       repdata.replace = copy_vert;
-       face_replace_vert(face, &repdata);
-}
-
-typedef struct PropagateEdge {
-       struct PropagateEdge *next, *prev;
-       SmoothEdge *edge;
-       SmoothVert *vert;
-} PropagateEdge;
-
-static void push_propagate_stack(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
-       PropagateEdge *pedge = mesh->reusestack.first;
-
-       if(pedge) {
-               BLI_remlink(&mesh->reusestack, pedge);
-       }
-       else {
-               if(!mesh->arena) {
-                       mesh->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
-                       BLI_memarena_use_calloc(mesh->arena);
-               }
-
-               pedge = BLI_memarena_alloc(mesh->arena, sizeof(PropagateEdge));
-       }
-
-       pedge->edge = edge;
-       pedge->vert = vert;
-       BLI_addhead(&mesh->propagatestack, pedge);
-}
-
-static void pop_propagate_stack(SmoothEdge **edge, SmoothVert **vert, SmoothMesh *mesh)
-{
-       PropagateEdge *pedge = mesh->propagatestack.first;
-
-       if(pedge) {
-               *edge = pedge->edge;
-               *vert = pedge->vert;
-               BLI_remlink(&mesh->propagatestack, pedge);
-               BLI_addhead(&mesh->reusestack, pedge);
-       }
-       else {
-               *edge = NULL;
-               *vert = NULL;
-       }
-}
-
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh);
-
-static void propagate_split(SmoothEdge *edge, SmoothVert *vert,
-                               SmoothMesh *mesh)
-{
-       SmoothEdge *edge2;
-       LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== START === propagate_split(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
-
-       edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
-                                         mesh->threshold, mesh->flags);
-
-       if(!edge2) {
-               /* didn't find a sharp or loose edge, so we've hit a dead end */
-       } else if(!edge_is_loose(edge2)) {
-               /* edge2 is not loose, so it must be sharp */
-               if(edge_is_loose(edge)) {
-                       /* edge is loose, so we can split edge2 at this vert */
-                       split_edge(edge2, vert, mesh);
-               } else if(edge_is_sharp(edge, mesh->flags, mesh->threshold)) {
-                       /* both edges are sharp, so we can split the pair at vert */
-                       split_edge(edge, vert, mesh);
-               } else {
-                       /* edge is not sharp, so try to split edge2 at its other vert */
-                       split_edge(edge2, other_vert(edge2, vert), mesh);
-               }
-       } else { /* edge2 is loose */
-               if(edge_is_loose(edge)) {
-                       SmoothVert *vert2;
-                       ReplaceData repdata;
-
-                       /* can't split edge, what should we do with vert? */
-                       if(linklist_subset(vert->faces, visited_faces)) {
-                               /* vert has only one fan of faces attached; don't split it */
-                       } else {
-                               /* vert has more than one fan of faces attached; split it */
-                               vert2 = smoothvert_copy(vert, mesh);
-
-                               /* replace vert with its copy in visited_faces */
-                               repdata.find = vert;
-                               repdata.replace = vert2;
-                               BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-                       }
-               } else {
-                       /* edge is not loose, so it must be sharp; split it */
-                       split_edge(edge, vert, mesh);
-               }
-       }
-
-       BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== END === propagate_split(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
-}
-
-static void split_edge(SmoothEdge *edge, SmoothVert *vert, SmoothMesh *mesh)
-{
-       SmoothEdge *edge2;
-       SmoothVert *vert2;
-       ReplaceData repdata;
-       /* the list of faces traversed while looking for a sharp edge */
-       LinkNode *visited_faces = NULL;
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== START === split_edge(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
-
-       edge2 = find_other_sharp_edge(vert, edge, &visited_faces,
-                                         mesh->threshold, mesh->flags);
-
-       if(!edge2) {
-               /* didn't find a sharp or loose edge, so try the other vert */
-               vert2 = other_vert(edge, vert);
-               push_propagate_stack(edge, vert2, mesh);
-       } else if(!edge_is_loose(edge2)) {
-               /* edge2 is not loose, so it must be sharp */
-               SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
-               SmoothEdge *copy_edge2 = smoothedge_copy(edge2, mesh);
-               SmoothVert *vert2;
-
-               /* replace edge with its copy in visited_faces */
-               repdata.find = edge;
-               repdata.replace = copy_edge;
-               BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
-               /* replace edge2 with its copy in visited_faces */
-               repdata.find = edge2;
-               repdata.replace = copy_edge2;
-               BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
-               vert2 = smoothvert_copy(vert, mesh);
-
-               /* replace vert with its copy in visited_faces (must be done after
-               * edge replacement so edges have correct vertices)
-               */
-               repdata.find = vert;
-               repdata.replace = vert2;
-               BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
-               /* all copying and replacing is done; the mesh should be consistent.
-               * now propagate the split to the vertices at either end
-               */
-               push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
-               push_propagate_stack(copy_edge2, other_vert(copy_edge2, vert2), mesh);
-
-               if(smoothedge_has_vert(edge, vert))
-                       push_propagate_stack(edge, vert, mesh);
-       } else {
-               /* edge2 is loose */
-               SmoothEdge *copy_edge = smoothedge_copy(edge, mesh);
-               SmoothVert *vert2;
-
-               /* replace edge with its copy in visited_faces */
-               repdata.find = edge;
-               repdata.replace = copy_edge;
-               BLI_linklist_apply(visited_faces, face_replace_edge, &repdata);
-
-               vert2 = smoothvert_copy(vert, mesh);
-
-               /* replace vert with its copy in visited_faces (must be done after
-               * edge replacement so edges have correct vertices)
-               */
-               repdata.find = vert;
-               repdata.replace = vert2;
-               BLI_linklist_apply(visited_faces, face_replace_vert, &repdata);
-
-               /* copying and replacing is done; the mesh should be consistent.
-               * now propagate the split to the vertex at the other end
-               */
-               push_propagate_stack(copy_edge, other_vert(copy_edge, vert2), mesh);
-
-               if(smoothedge_has_vert(edge, vert))
-                       push_propagate_stack(edge, vert, mesh);
-       }
-
-       BLI_linklist_free(visited_faces, NULL);
-#ifdef EDGESPLIT_DEBUG_1
-       printf("=== END === split_edge(edge = %4d, vert = %4d)\n",
-                  edge->newIndex, vert->newIndex);
-#endif
-}
-
-static void tag_and_count_extra_edges(SmoothMesh *mesh, float split_angle,
-                                         int flags, int *extra_edges)
-{
-       /* if normal1 dot normal2 < threshold, angle is greater, so split */
-       /* FIXME not sure if this always works */
-       /* 0.00001 added for floating-point rounding */
-       float threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
-       int i;
-
-       *extra_edges = 0;
-
-       /* loop through edges, counting potential new ones */
-       for(i = 0; i < mesh->num_edges; i++) {
-               SmoothEdge *edge = &mesh->edges[i];
-               int sharp = 0;
-
-               /* treat all non-manifold edges (3 or more faces) as sharp */
-               if(edge->faces && edge->faces->next && edge->faces->next->next) {
-                       LinkNode *node;
-
-                       /* this edge is sharp */
-                       sharp = 1;
-
-                       /* add an extra edge for every face beyond the first */
-                       *extra_edges += 2;
-                       for(node = edge->faces->next->next->next; node; node = node->next)
-                               (*extra_edges)++;
-               } else if((flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG))
-                                        && !edge_is_loose(edge)) {
-                       /* (the edge can only be sharp if we're checking angle or flag,
-                       * and it has at least 2 faces) */
-
-                                                /* if we're checking the sharp flag and it's set, good */
-                                                if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP)) {
-                                                        /* this edge is sharp */
-                                                        sharp = 1;
-
-                                                        (*extra_edges)++;
-                                                } else if(flags & MOD_EDGESPLIT_FROMANGLE) {
-                                                        /* we know the edge has 2 faces, so check the angle */
-                                                        SmoothFace *face1 = edge->faces->link;
-                                                        SmoothFace *face2 = edge->faces->next->link;
-                                                        float edge_angle_cos = dot_v3v3(face1->normal,
-                                                                        face2->normal);
-
-                                                        if(edge_angle_cos < threshold) {
-                                                                /* this edge is sharp */
-                                                                sharp = 1;
-
-                                                                (*extra_edges)++;
-                                                        }
-                                                }
-                                        }
-
-                                        /* set/clear sharp flag appropriately */
-                                        if(sharp) edge->flag |= ME_SHARP;
-                                        else edge->flag &= ~ME_SHARP;
-       }
-}
-
-static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
-{
-       SmoothVert *vert;
-       int i;
-       /* if normal1 dot normal2 < threshold, angle is greater, so split */
-       /* FIXME not sure if this always works */
-       /* 0.00001 added for floating-point rounding */
-       mesh->threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
-       mesh->flags = flags;
-
-       /* loop through edges, splitting sharp ones */
-       /* can't use an iterator here, because we'll be adding edges */
-       for(i = 0; i < mesh->num_edges; i++) {
-               SmoothEdge *edge = &mesh->edges[i];
-
-               if(edge_is_sharp(edge, flags, mesh->threshold)) {
-                       split_edge(edge, edge->verts[0], mesh);
-
-                       do {
-                               pop_propagate_stack(&edge, &vert, mesh);
-                               if(edge && smoothedge_has_vert(edge, vert))
-                                       propagate_split(edge, vert, mesh);
-                       } while(edge);
-               }
-       }
-}
-
-static int count_bridge_verts(SmoothMesh *mesh)
-{
-       int i, j, count = 0;
-
-       for(i = 0; i < mesh->num_faces; i++) {
-               SmoothFace *face = &mesh->faces[i];
-
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       SmoothEdge *edge = face->edges[j];
-                       SmoothEdge *next_edge;
-                       SmoothVert *vert = edge->verts[1 - face->flip[j]];
-                       int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
-                       /* wrap next around if at last edge */
-                       if(!face->edges[next]) next = 0;
-
-                       next_edge = face->edges[next];
-
-                       /* if there are other faces sharing this vertex but not
-                       * these edges, the vertex will be split, so count it
-                       */
-                       /* vert has to have at least one face (this one), so faces != 0 */
-                       if(!edge->faces->next && !next_edge->faces->next
-                                                && vert->faces->next) {
-                               count++;
-                                                }
-               }
-       }
-
-       /* each bridge vert will be counted once per face that uses it,
-       * so count is too high, but it's ok for now
-       */
-       return count;
-}
-
-static void split_bridge_verts(SmoothMesh *mesh)
-{
-       int i,j;
-
-       for(i = 0; i < mesh->num_faces; i++) {
-               SmoothFace *face = &mesh->faces[i];
-
-               for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
-                       SmoothEdge *edge = face->edges[j];
-                       SmoothEdge *next_edge;
-                       SmoothVert *vert = edge->verts[1 - face->flip[j]];
-                       int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
-
-                       /* wrap next around if at last edge */
-                       if(!face->edges[next]) next = 0;
-
-                       next_edge = face->edges[next];
-
-                       /* if there are other faces sharing this vertex but not
-                       * these edges, split the vertex
-                       */
-                       /* vert has to have at least one face (this one), so faces != 0 */
-                       if(!edge->faces->next && !next_edge->faces->next
-                                                && vert->faces->next)
-                               /* FIXME this needs to find all faces that share edges with
-                               * this one and split off together
-                               */
-                               split_single_vert(vert, face, mesh);
-               }
-       }
-}
-
-static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
-                                        Object *ob, DerivedMesh *dm)
-{
-       SmoothMesh *mesh;
-       DerivedMesh *result;
-       int max_verts, max_edges;
-
-       if(!(emd->flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
-               return dm;
-
-       /* 1. make smoothmesh with initial number of elements */
-       mesh = smoothmesh_from_derivedmesh(dm);
-
-       /* 2. count max number of elements to add */
-       tag_and_count_extra_edges(mesh, emd->split_angle, emd->flags, &max_edges);
-       max_verts = max_edges * 2 + mesh->max_verts;
-       max_verts += count_bridge_verts(mesh);
-       max_edges += mesh->max_edges;
-
-       /* 3. reallocate smoothmesh arrays & copy elements across */
-       /* 4. remap copied elements' pointers to point into the new arrays */
-       smoothmesh_resize_verts(mesh, max_verts);
-       smoothmesh_resize_edges(mesh, max_edges);
-
-#ifdef EDGESPLIT_DEBUG_1
-       printf("********** Pre-split **********\n");
-       smoothmesh_print(mesh);
-#endif
-
-       split_sharp_edges(mesh, emd->split_angle, emd->flags);
-#ifdef EDGESPLIT_DEBUG_1
-       printf("********** Post-edge-split **********\n");
-       smoothmesh_print(mesh);
-#endif
-
-       split_bridge_verts(mesh);
-
-#ifdef EDGESPLIT_DEBUG_1
-       printf("********** Post-vert-split **********\n");
-       smoothmesh_print(mesh);
-#endif
-
-#ifdef EDGESPLIT_DEBUG_0
-       printf("Edgesplit: Estimated %d verts & %d edges, "
-                       "found %d verts & %d edges\n", max_verts, max_edges,
-   mesh->num_verts, mesh->num_edges);
-#endif
-
-       result = CDDM_from_smoothmesh(mesh);
-       smoothmesh_free(mesh);
-
-       return result;
-}
-
-static DerivedMesh *edgesplitModifier_applyModifier(
-               ModifierData *md, Object *ob, DerivedMesh *derivedData,
-  int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *result;
-       EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
-
-       result = edgesplitModifier_do(emd, ob, derivedData);
-
-       if(result != derivedData)
-               CDDM_calc_normals(result);
-
-       return result;
-}
-
-static DerivedMesh *edgesplitModifier_applyModifierEM(
-               ModifierData *md, Object *ob, EditMesh *editData,
-  DerivedMesh *derivedData)
-{
-       return edgesplitModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Bevel */
-
-static void bevelModifier_initData(ModifierData *md)
-{
-       BevelModifierData *bmd = (BevelModifierData*) md;
-
-       bmd->value = 0.1f;
-       bmd->res = 1;
-       bmd->flags = 0;
-       bmd->val_flags = 0;
-       bmd->lim_flags = 0;
-       bmd->e_flags = 0;
-       bmd->bevel_angle = 30;
-       bmd->defgrp_name[0] = '\0';
-}
-
-static void bevelModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       BevelModifierData *bmd = (BevelModifierData*) md;
-       BevelModifierData *tbmd = (BevelModifierData*) target;
-
-       tbmd->value = bmd->value;
-       tbmd->res = bmd->res;
-       tbmd->flags = bmd->flags;
-       tbmd->val_flags = bmd->val_flags;
-       tbmd->lim_flags = bmd->lim_flags;
-       tbmd->e_flags = bmd->e_flags;
-       tbmd->bevel_angle = bmd->bevel_angle;
-       strncpy(tbmd->defgrp_name, bmd->defgrp_name, 32);
-}
-
-static CustomDataMask bevelModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       BevelModifierData *bmd = (BevelModifierData *)md;
-       CustomDataMask dataMask = 0;
-
-       /* ask for vertexgroups if we need them */
-       if(bmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
-       return dataMask;
-}
-
-static DerivedMesh *bevelModifier_applyModifier(
-               ModifierData *md, Object *ob, DerivedMesh *derivedData,
-  int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *result;
-       BME_Mesh *bm;
-
-       /*bDeformGroup *def;*/
-       int /*i,*/ options, defgrp_index = -1;
-       BevelModifierData *bmd = (BevelModifierData*) md;
-
-       options = bmd->flags|bmd->val_flags|bmd->lim_flags|bmd->e_flags;
-
-       /*if ((options & BME_BEVEL_VWEIGHT) && bmd->defgrp_name[0]) {
-               defgrp_index = defgroup_name_index(ob, bmd->defgrp_name);
-               if (defgrp_index < 0) {
-                       options &= ~BME_BEVEL_VWEIGHT;
-               }
-       }*/
-
-       bm = BME_derivedmesh_to_bmesh(derivedData);
-       BME_bevel(bm,bmd->value,bmd->res,options,defgrp_index,bmd->bevel_angle,NULL);
-       result = BME_bmesh_to_derivedmesh(bm,derivedData);
-       BME_free_mesh(bm);
-
-       CDDM_calc_normals(result);
-
-       return result;
-}
-
-static DerivedMesh *bevelModifier_applyModifierEM(
-               ModifierData *md, Object *ob, EditMesh *editData,
-  DerivedMesh *derivedData)
-{
-       return bevelModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Displace */
-
-static void displaceModifier_initData(ModifierData *md)
-{
-       DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
-       dmd->texture = NULL;
-       dmd->strength = 1;
-       dmd->direction = MOD_DISP_DIR_NOR;
-       dmd->midlevel = 0.5;
-}
-
-static void displaceModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-       DisplaceModifierData *tdmd = (DisplaceModifierData*) target;
-
-       tdmd->texture = dmd->texture;
-       tdmd->strength = dmd->strength;
-       tdmd->direction = dmd->direction;
-       strncpy(tdmd->defgrp_name, dmd->defgrp_name, 32);
-       tdmd->midlevel = dmd->midlevel;
-       tdmd->texmapping = dmd->texmapping;
-       tdmd->map_object = dmd->map_object;
-       strncpy(tdmd->uvlayer_name, dmd->uvlayer_name, 32);
-}
-
-static CustomDataMask displaceModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       DisplaceModifierData *dmd = (DisplaceModifierData *)md;
-       CustomDataMask dataMask = 0;
-
-       /* ask for vertexgroups if we need them */
-       if(dmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
-       /* ask for UV coordinates if we need them */
-       if(dmd->texmapping == MOD_DISP_MAP_UV) dataMask |= (1 << CD_MTFACE);
-
-       return dataMask;
-}
-
-static int displaceModifier_dependsOnTime(ModifierData *md)
-{
-       DisplaceModifierData *dmd = (DisplaceModifierData *)md;
-
-       if(dmd->texture)
-       {
-               return BKE_texture_dependsOnTime(dmd->texture);
-       }
-       else
-       {
-               return 0;
-       }
-}
-
-static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob,
-                                                  ObjectWalkFunc walk, void *userData)
-{
-       DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
-       walk(userData, ob, &dmd->map_object);
-}
-
-static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob,
-                                          IDWalkFunc walk, void *userData)
-{
-       DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
-       walk(userData, ob, (ID **)&dmd->texture);
-
-       displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
-}
-
-static int displaceModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
-       DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
-       return !dmd->texture;
-}
-
-static void displaceModifier_updateDepgraph(
-                                               ModifierData *md, DagForest *forest, Scene *scene,
-        Object *ob, DagNode *obNode)
-{
-       DisplaceModifierData *dmd = (DisplaceModifierData*) md;
-
-       if(dmd->map_object) {
-               DagNode *curNode = dag_get_node(forest, dmd->map_object);
-
-               dag_add_relation(forest, curNode, obNode,
-                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier");
-       }
-}
-
-static void validate_layer_name(const CustomData *data, int type, char *name, char *outname)
-{
-       int index = -1;
-
-       /* if a layer name was given, try to find that layer */
-       if(name[0])
-               index = CustomData_get_named_layer_index(data, CD_MTFACE, name);
-
-       if(index < 0) {
-               /* either no layer was specified, or the layer we want has been
-               * deleted, so assign the active layer to name
-               */
-               index = CustomData_get_active_layer_index(data, CD_MTFACE);
-               strcpy(outname, data->layers[index].name);
-       }
-       else
-               strcpy(outname, name);
-}
-
-static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
-                                  DerivedMesh *dm,
-         float (*co)[3], float (*texco)[3],
-                 int numVerts)
-{
-       int i;
-       int texmapping = dmd->texmapping;
-       float mapob_imat[4][4];
-
-       if(texmapping == MOD_DISP_MAP_OBJECT) {
-               if(dmd->map_object)
-                       invert_m4_m4(mapob_imat, dmd->map_object->obmat);
-               else /* if there is no map object, default to local */
-                       texmapping = MOD_DISP_MAP_LOCAL;
-       }
-
-       /* UVs need special handling, since they come from faces */
-       if(texmapping == MOD_DISP_MAP_UV) {
-               if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
-                       MFace *mface = dm->getFaceArray(dm);
-                       MFace *mf;
-                       char *done = MEM_callocN(sizeof(*done) * numVerts,
-                                       "get_texture_coords done");
-                       int numFaces = dm->getNumFaces(dm);
-                       char uvname[32];
-                       MTFace *tf;
-
-                       validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname);
-                       tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
-
-                       /* verts are given the UV from the first face that uses them */
-                       for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
-                               if(!done[mf->v1]) {
-                                       texco[mf->v1][0] = tf->uv[0][0];
-                                       texco[mf->v1][1] = tf->uv[0][1];
-                                       texco[mf->v1][2] = 0;
-                                       done[mf->v1] = 1;
-                               }
-                               if(!done[mf->v2]) {
-                                       texco[mf->v2][0] = tf->uv[1][0];
-                                       texco[mf->v2][1] = tf->uv[1][1];
-                                       texco[mf->v2][2] = 0;
-                                       done[mf->v2] = 1;
-                               }
-                               if(!done[mf->v3]) {
-                                       texco[mf->v3][0] = tf->uv[2][0];
-                                       texco[mf->v3][1] = tf->uv[2][1];
-                                       texco[mf->v3][2] = 0;
-                                       done[mf->v3] = 1;
-                               }
-                               if(!done[mf->v4]) {
-                                       texco[mf->v4][0] = tf->uv[3][0];
-                                       texco[mf->v4][1] = tf->uv[3][1];
-                                       texco[mf->v4][2] = 0;
-                                       done[mf->v4] = 1;
-                               }
-                       }
-
-                       /* remap UVs from [0, 1] to [-1, 1] */
-                       for(i = 0; i < numVerts; ++i) {
-                               texco[i][0] = texco[i][0] * 2 - 1;
-                               texco[i][1] = texco[i][1] * 2 - 1;
-                       }
-
-                       MEM_freeN(done);
-                       return;
-               } else /* if there are no UVs, default to local */
-                       texmapping = MOD_DISP_MAP_LOCAL;
-       }
-
-       for(i = 0; i < numVerts; ++i, ++co, ++texco) {
-               switch(texmapping) {
-                       case MOD_DISP_MAP_LOCAL:
-                               VECCOPY(*texco, *co);
-                               break;
-                       case MOD_DISP_MAP_GLOBAL:
-                               VECCOPY(*texco, *co);
-                               mul_m4_v3(ob->obmat, *texco);
-                               break;
-                       case MOD_DISP_MAP_OBJECT:
-                               VECCOPY(*texco, *co);
-                               mul_m4_v3(ob->obmat, *texco);
-                               mul_m4_v3(mapob_imat, *texco);
-                               break;
-               }
-       }
-}
-
-static void get_texture_value(Tex *texture, float *tex_co, TexResult *texres)
-{
-       int result_type;
-
-       result_type = multitex_ext(texture, tex_co, NULL, NULL, 0, texres);
-
-       /* if the texture gave an RGB value, we assume it didn't give a valid
-       * intensity, so calculate one (formula from do_material_tex).
-       * if the texture didn't give an RGB value, copy the intensity across
-       */
-       if(result_type & TEX_RGB)
-               texres->tin = (0.35f * texres->tr + 0.45f * texres->tg
-                               + 0.2f * texres->tb);
-       else
-               texres->tr = texres->tg = texres->tb = texres->tin;
-}
-
-/* dm must be a CDDerivedMesh */
-static void displaceModifier_do(
-                               DisplaceModifierData *dmd, Object *ob,
-       DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
-{
-       int i;
-       MVert *mvert;
-       MDeformVert *dvert = NULL;
-       int defgrp_index;
-       float (*tex_co)[3];
-
-       if(!dmd->texture) return;
-
-       defgrp_index = defgroup_name_index(ob, dmd->defgrp_name);
-
-       mvert = CDDM_get_verts(dm);
-       if(defgrp_index >= 0)
-               dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
-       tex_co = MEM_callocN(sizeof(*tex_co) * numVerts,
-                                "displaceModifier_do tex_co");
-       get_texture_coords(dmd, ob, dm, vertexCos, tex_co, numVerts);
-
-       for(i = 0; i < numVerts; ++i) {
-               TexResult texres;
-               float delta = 0, strength = dmd->strength;
-               MDeformWeight *def_weight = NULL;
-
-               if(dvert) {
-                       int j;
-                       for(j = 0; j < dvert[i].totweight; ++j) {
-                               if(dvert[i].dw[j].def_nr == defgrp_index) {
-                                       def_weight = &dvert[i].dw[j];
-                                       break;
-                               }
-                       }
-                       if(!def_weight) continue;
-               }
-
-               texres.nor = NULL;
-               get_texture_value(dmd->texture, tex_co[i], &texres);
-
-               delta = texres.tin - dmd->midlevel;
-
-               if(def_weight) strength *= def_weight->weight;
-
-               delta *= strength;
-
-               switch(dmd->direction) {
-                       case MOD_DISP_DIR_X:
-                               vertexCos[i][0] += delta;
-                               break;
-                       case MOD_DISP_DIR_Y:
-                               vertexCos[i][1] += delta;
-                               break;
-                       case MOD_DISP_DIR_Z:
-                               vertexCos[i][2] += delta;
-                               break;
-                       case MOD_DISP_DIR_RGB_XYZ:
-                               vertexCos[i][0] += (texres.tr - dmd->midlevel) * strength;
-                               vertexCos[i][1] += (texres.tg - dmd->midlevel) * strength;
-                               vertexCos[i][2] += (texres.tb - dmd->midlevel) * strength;
-                               break;
-                       case MOD_DISP_DIR_NOR:
-                               vertexCos[i][0] += delta * mvert[i].no[0] / 32767.0f;
-                               vertexCos[i][1] += delta * mvert[i].no[1] / 32767.0f;
-                               vertexCos[i][2] += delta * mvert[i].no[2] / 32767.0f;
-                               break;
-               }
-       }
-
-       MEM_freeN(tex_co);
-}
-
-static void displaceModifier_deformVerts(
-                                        ModifierData *md, Object *ob, DerivedMesh *derivedData,
-         float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *dm= get_cddm(md->scene, ob, NULL, derivedData, vertexCos);
-
-       displaceModifier_do((DisplaceModifierData *)md, ob, dm,
-                                vertexCos, numVerts);
-
-       if(dm != derivedData)
-               dm->release(dm);
-}
-
-static void displaceModifier_deformVertsEM(
-                                          ModifierData *md, Object *ob, EditMesh *editData,
-       DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
-       DerivedMesh *dm= get_cddm(md->scene, ob, editData, derivedData, vertexCos);
-
-       displaceModifier_do((DisplaceModifierData *)md, ob, dm,
-                                vertexCos, numVerts);
-
-       if(dm != derivedData)
-               dm->release(dm);
-}
-
-/* UVProject */
-/* UV Project modifier: Generates UVs projected from an object
-*/
-
-static void uvprojectModifier_initData(ModifierData *md)
-{
-       UVProjectModifierData *umd = (UVProjectModifierData*) md;
-       int i;
-
-       for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
-               umd->projectors[i] = NULL;
-       umd->image = NULL;
-       umd->flags = 0;
-       umd->num_projectors = 1;
-       umd->aspectx = umd->aspecty = 1.0f;
-       umd->scalex = umd->scaley = 1.0f;
-}
-
-static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       UVProjectModifierData *umd = (UVProjectModifierData*) md;
-       UVProjectModifierData *tumd = (UVProjectModifierData*) target;
-       int i;
-
-       for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
-               tumd->projectors[i] = umd->projectors[i];
-       tumd->image = umd->image;
-       tumd->flags = umd->flags;
-       tumd->num_projectors = umd->num_projectors;
-       tumd->aspectx = umd->aspectx;
-       tumd->aspecty = umd->aspecty;
-       tumd->scalex = umd->scalex;
-       tumd->scaley = umd->scaley;
-}
-
-static CustomDataMask uvprojectModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       CustomDataMask dataMask = 0;
-
-       /* ask for UV coordinates */
-       dataMask |= (1 << CD_MTFACE);
-
-       return dataMask;
-}
-
-static void uvprojectModifier_foreachObjectLink(ModifierData *md, Object *ob,
-               ObjectWalkFunc walk, void *userData)
-{
-       UVProjectModifierData *umd = (UVProjectModifierData*) md;
-       int i;
-
-       for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
-               walk(userData, ob, &umd->projectors[i]);
-}
-
-static void uvprojectModifier_foreachIDLink(ModifierData *md, Object *ob,
-                                               IDWalkFunc walk, void *userData)
-{
-       UVProjectModifierData *umd = (UVProjectModifierData*) md;
-
-       walk(userData, ob, (ID **)&umd->image);
-
-       uvprojectModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk,
-                                               userData);
-}
-
-static void uvprojectModifier_updateDepgraph(ModifierData *md,
-                                                DagForest *forest, Scene *scene, Object *ob, DagNode *obNode)
-{
-       UVProjectModifierData *umd = (UVProjectModifierData*) md;
-       int i;
-
-       for(i = 0; i < umd->num_projectors; ++i) {
-               if(umd->projectors[i]) {
-                       DagNode *curNode = dag_get_node(forest, umd->projectors[i]);
-
-                       dag_add_relation(forest, curNode, obNode,
-                                        DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "UV Project Modifier");
-               }
-       }
-}
-
-typedef struct Projector {
-       Object *ob;                             /* object this projector is derived from */
-       float projmat[4][4];    /* projection matrix */ 
-       float normal[3];                /* projector normal in world space */
-       void *uci;                              /* optional uv-project info (panorama projection) */
-} Projector;
-
-static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
-                                        Object *ob, DerivedMesh *dm)
-{
-       float (*coords)[3], (*co)[3];
-       MTFace *tface;
-       int i, numVerts, numFaces;
-       Image *image = umd->image;
-       MFace *mface, *mf;
-       int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0);
-       Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
-       int num_projectors = 0;
-       float aspect;
-       char uvname[32];
-       float aspx= umd->aspectx ? umd->aspectx : 1.0f;
-       float aspy= umd->aspecty ? umd->aspecty : 1.0f;
-       float scax= umd->scalex ? umd->scalex : 1.0f;
-       float scay= umd->scaley ? umd->scaley : 1.0f;
-       int free_uci= 0;
-       
-       aspect = aspx / aspy;
-
-       for(i = 0; i < umd->num_projectors; ++i)
-               if(umd->projectors[i])
-                       projectors[num_projectors++].ob = umd->projectors[i];
-
-       if(num_projectors == 0) return dm;
-
-       /* make sure there are UV layers available */
-
-       if(!CustomData_has_layer(&dm->faceData, CD_MTFACE)) return dm;
-
-       /* make sure we're using an existing layer */
-       validate_layer_name(&dm->faceData, CD_MTFACE, umd->uvlayer_name, uvname);
-
-       /* calculate a projection matrix and normal for each projector */
-       for(i = 0; i < num_projectors; ++i) {
-               float tmpmat[4][4];
-               float offsetmat[4][4];
-               Camera *cam = NULL;
-               /* calculate projection matrix */
-               invert_m4_m4(projectors[i].projmat, projectors[i].ob->obmat);
-
-               projectors[i].uci= NULL;
-
-               if(projectors[i].ob->type == OB_CAMERA) {
-                       cam = (Camera *)projectors[i].ob->data;
-
-                       if(cam->flag & CAM_PANORAMA) {
-                               projectors[i].uci= project_camera_info(projectors[i].ob, NULL, aspx, aspy);
-                               free_uci= 1;
-                       }
-                       else if(cam->type == CAM_PERSP) {
-                               float perspmat[4][4];
-                               float xmax; 
-                               float xmin;
-                               float ymax;
-                               float ymin;
-                               float pixsize = cam->clipsta * 32.0 / cam->lens;
-
-                               if(aspect > 1.0f) {
-                                       xmax = 0.5f * pixsize;
-                                       ymax = xmax / aspect;
-                               } else {
-                                       ymax = 0.5f * pixsize;
-                                       xmax = ymax * aspect; 
-                               }
-                               xmin = -xmax;
-                               ymin = -ymax;
-
-                               perspective_m4( perspmat,xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend);
-                               mul_m4_m4m4(tmpmat, projectors[i].projmat, perspmat);
-                       } else if(cam->type == CAM_ORTHO) {
-                               float orthomat[4][4];
-                               float xmax; 
-                               float xmin;
-                               float ymax;
-                               float ymin;
-
-                               if(aspect > 1.0f) {
-                                       xmax = 0.5f * cam->ortho_scale; 
-                                       ymax = xmax / aspect;
-                               } else {
-                                       ymax = 0.5f * cam->ortho_scale;
-                                       xmax = ymax * aspect; 
-                               }
-                               xmin = -xmax;
-                               ymin = -ymax;
-
-                               orthographic_m4( orthomat,xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend);
-                               mul_m4_m4m4(tmpmat, projectors[i].projmat, orthomat);
-                       }
-               } else {
-                       copy_m4_m4(tmpmat, projectors[i].projmat);
-               }
-
-               unit_m4(offsetmat);
-               mul_mat3_m4_fl(offsetmat, 0.5);
-               offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5;
-               
-               if (cam) {
-                       if (aspx == aspy) { 
-                               offsetmat[3][0] -= cam->shiftx;
-                               offsetmat[3][1] -= cam->shifty;
-                       } else if (aspx < aspy)  {
-                               offsetmat[3][0] -=(cam->shiftx * aspy/aspx);
-                               offsetmat[3][1] -= cam->shifty;
-                       } else {
-                               offsetmat[3][0] -= cam->shiftx;
-                               offsetmat[3][1] -=(cam->shifty * aspx/aspy);
-                       }
-               }
-               
-               mul_m4_m4m4(projectors[i].projmat, tmpmat, offsetmat);
-
-               /* calculate worldspace projector normal (for best projector test) */
-               projectors[i].normal[0] = 0;
-               projectors[i].normal[1] = 0;
-               projectors[i].normal[2] = 1;
-               mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal);
-       }
-
-       /* make sure we are not modifying the original UV layer */
-       tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
-                       CD_MTFACE, uvname);
-
-       
-       numVerts = dm->getNumVerts(dm);
-
-       coords = MEM_callocN(sizeof(*coords) * numVerts,
-                                "uvprojectModifier_do coords");
-       dm->getVertCos(dm, coords);
-
-       /* convert coords to world space */
-       for(i = 0, co = coords; i < numVerts; ++i, ++co)
-               mul_m4_v3(ob->obmat, *co);
-       
-       /* if only one projector, project coords to UVs */
-       if(num_projectors == 1 && projectors[0].uci==NULL)
-               for(i = 0, co = coords; i < numVerts; ++i, ++co)
-                       mul_project_m4_v4(projectors[0].projmat, *co);
-
-       mface = dm->getFaceArray(dm);
-       numFaces = dm->getNumFaces(dm);
-
-       /* apply coords as UVs, and apply image if tfaces are new */
-       for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) {
-               if(override_image || !image || tface->tpage == image) {
-                               if(num_projectors == 1) {
-                                       if(projectors[0].uci) {
-                                               project_from_camera(tface->uv[0], coords[mf->v1], projectors[0].uci);
-                                               project_from_camera(tface->uv[1], coords[mf->v2], projectors[0].uci);
-                                               project_from_camera(tface->uv[2], coords[mf->v3], projectors[0].uci);
-                                               if(mf->v3)
-                                                       project_from_camera(tface->uv[3], coords[mf->v4], projectors[0].uci);
-                                               
-                                               if(scax != 1.0f) {
-                                                       tface->uv[0][0] = ((tface->uv[0][0] - 0.5f) * scax) + 0.5f;
-                                                       tface->uv[1][0] = ((tface->uv[1][0] - 0.5f) * scax) + 0.5f;
-                                                       tface->uv[2][0] = ((tface->uv[2][0] - 0.5f) * scax) + 0.5f;
-                                                       if(mf->v3)
-                                                               tface->uv[3][0] = ((tface->uv[3][0] - 0.5f) * scax) + 0.5f;
-                                               }
-                                               
-                                               if(scay != 1.0f) {
-                                                       tface->uv[0][1] = ((tface->uv[0][1] - 0.5f) * scay) + 0.5f;
-                                                       tface->uv[1][1] = ((tface->uv[1][1] - 0.5f) * scay) + 0.5f;
-                                                       tface->uv[2][1] = ((tface->uv[2][1] - 0.5f) * scay) + 0.5f;
-                                                       if(mf->v3)
-                                                               tface->uv[3][1] = ((tface->uv[3][1] - 0.5f) * scay) + 0.5f;
-                                               }
-                                       }
-                                       else {
-                                               /* apply transformed coords as UVs */
-                                               tface->uv[0][0] = coords[mf->v1][0];
-                                               tface->uv[0][1] = coords[mf->v1][1];
-                                               tface->uv[1][0] = coords[mf->v2][0];
-                                               tface->uv[1][1] = coords[mf->v2][1];
-                                               tface->uv[2][0] = coords[mf->v3][0];
-                                               tface->uv[2][1] = coords[mf->v3][1];
-                                               if(mf->v4) {
-                                                       tface->uv[3][0] = coords[mf->v4][0];
-                                                       tface->uv[3][1] = coords[mf->v4][1];
-                                               }
-                               }
-                       } else {
-                               /* multiple projectors, select the closest to face normal
-                               * direction
-                               */
-                               float co1[3], co2[3], co3[3], co4[3];
-                               float face_no[3];
-                               int j;
-                               Projector *best_projector;
-                               float best_dot;
-
-                               VECCOPY(co1, coords[mf->v1]);
-                               VECCOPY(co2, coords[mf->v2]);
-                               VECCOPY(co3, coords[mf->v3]);
-
-                               /* get the untransformed face normal */
-                               if(mf->v4) {
-                                       VECCOPY(co4, coords[mf->v4]);
-                                       normal_quad_v3( face_no,co1, co2, co3, co4);
-                               } else { 
-                                       normal_tri_v3( face_no,co1, co2, co3);
-                               }
-
-                               /* find the projector which the face points at most directly
-                               * (projector normal with largest dot product is best)
-                               */
-                               best_dot = dot_v3v3(projectors[0].normal, face_no);
-                               best_projector = &projectors[0];
-
-                               for(j = 1; j < num_projectors; ++j) {
-                                       float tmp_dot = dot_v3v3(projectors[j].normal,
-                                                       face_no);
-                                       if(tmp_dot > best_dot) {
-                                               best_dot = tmp_dot;
-                                               best_projector = &projectors[j];
-                                       }
-                               }
-                               
-                               if(best_projector->uci) {
-                                       project_from_camera(tface->uv[0], coords[mf->v1], best_projector->uci);
-                                       project_from_camera(tface->uv[1], coords[mf->v2], best_projector->uci);
-                                       project_from_camera(tface->uv[2], coords[mf->v3], best_projector->uci);
-                                       if(mf->v3)
-                                               project_from_camera(tface->uv[3], coords[mf->v4], best_projector->uci);
-                               }
-                               else {
-                                       mul_project_m4_v4(best_projector->projmat, co1);
-                                       mul_project_m4_v4(best_projector->projmat, co2);
-                                       mul_project_m4_v4(best_projector->projmat, co3);
-                                       if(mf->v4)
-                                               mul_project_m4_v4(best_projector->projmat, co4);
-
-                                       /* apply transformed coords as UVs */
-                                       tface->uv[0][0] = co1[0];
-                                       tface->uv[0][1] = co1[1];
-                                       tface->uv[1][0] = co2[0];
-                                       tface->uv[1][1] = co2[1];
-                                       tface->uv[2][0] = co3[0];
-                                       tface->uv[2][1] = co3[1];
-                                       if(mf->v4) {
-                                               tface->uv[3][0] = co4[0];
-                                               tface->uv[3][1] = co4[1];
-                                       }
-                               }
-                       }
-               }
-
-               if(override_image) {
-                       tface->mode = TF_TEX;
-                       tface->tpage = image;
-               }
-       }
-
-       MEM_freeN(coords);
-       
-       if(free_uci) {
-               int j;
-               for(j = 0; j < num_projectors; ++j) {
-                       if(projectors[j].uci) {
-                               MEM_freeN(projectors[j].uci);
-                       }
-               }
-       }
-       return dm;
-}
-
-static DerivedMesh *uvprojectModifier_applyModifier(
-               ModifierData *md, Object *ob, DerivedMesh *derivedData,
-  int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *result;
-       UVProjectModifierData *umd = (UVProjectModifierData*) md;
-
-       result = uvprojectModifier_do(umd, ob, derivedData);
-
-       return result;
-}
-
-static DerivedMesh *uvprojectModifier_applyModifierEM(
-               ModifierData *md, Object *ob, EditMesh *editData,
-  DerivedMesh *derivedData)
-{
-       return uvprojectModifier_applyModifier(md, ob, derivedData, 0, 1);
-}
-
-/* Decimate */
-
-static void decimateModifier_initData(ModifierData *md)
-{
-       DecimateModifierData *dmd = (DecimateModifierData*) md;
-
-       dmd->percent = 1.0;
-}
-
-static void decimateModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       DecimateModifierData *dmd = (DecimateModifierData*) md;
-       DecimateModifierData *tdmd = (DecimateModifierData*) target;
-
-       tdmd->percent = dmd->percent;
-}
-
-static DerivedMesh *decimateModifier_applyModifier(
-               ModifierData *md, Object *ob, DerivedMesh *derivedData,
-  int useRenderParams, int isFinalCalc)
-{
-       DecimateModifierData *dmd = (DecimateModifierData*) md;
-       DerivedMesh *dm = derivedData, *result = NULL;
-       MVert *mvert;
-       MFace *mface;
-       LOD_Decimation_Info lod;
-       int totvert, totface;
-       int a, numTris;
-
-       mvert = dm->getVertArray(dm);
-       mface = dm->getFaceArray(dm);
-       totvert = dm->getNumVerts(dm);
-       totface = dm->getNumFaces(dm);
-
-       numTris = 0;
-       for (a=0; a<totface; a++) {
-               MFace *mf = &mface[a];
-               numTris++;
-               if (mf->v4) numTris++;
-       }
-
-       if(numTris<3) {
-               modifier_setError(md,
-                       "Modifier requires more than 3 input faces (triangles).");
-               goto exit;
-       }
-
-       lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*totvert, "vertices");
-       lod.vertex_normal_buffer= MEM_mallocN(3*sizeof(float)*totvert, "normals");
-       lod.triangle_index_buffer= MEM_mallocN(3*sizeof(int)*numTris, "trias");
-       lod.vertex_num= totvert;
-       lod.face_num= numTris;
-
-       for(a=0; a<totvert; a++) {
-               MVert *mv = &mvert[a];
-               float *vbCo = &lod.vertex_buffer[a*3];
-               float *vbNo = &lod.vertex_normal_buffer[a*3];
-
-               VECCOPY(vbCo, mv->co);
-
-               vbNo[0] = mv->no[0]/32767.0f;
-               vbNo[1] = mv->no[1]/32767.0f;
-               vbNo[2] = mv->no[2]/32767.0f;
-       }
-
-       numTris = 0;
-       for(a=0; a<totface; a++) {
-               MFace *mf = &mface[a];
-               int *tri = &lod.triangle_index_buffer[3*numTris++];
-               tri[0]= mf->v1;
-               tri[1]= mf->v2;
-               tri[2]= mf->v3;
-
-               if(mf->v4) {
-                       tri = &lod.triangle_index_buffer[3*numTris++];
-                       tri[0]= mf->v1;
-                       tri[1]= mf->v3;
-                       tri[2]= mf->v4;
-               }
-       }
-
-       dmd->faceCount = 0;
-       if(LOD_LoadMesh(&lod) ) {
-               if( LOD_PreprocessMesh(&lod) ) {
-                       /* we assume the decim_faces tells how much to reduce */
-
-                       while(lod.face_num > numTris*dmd->percent) {
-                               if( LOD_CollapseEdge(&lod)==0) break;
-                       }
-
-                       if(lod.vertex_num>2) {
-                               result = CDDM_new(lod.vertex_num, 0, lod.face_num);
-                               dmd->faceCount = lod.face_num;
-                       }
-                       else
-                               result = CDDM_new(lod.vertex_num, 0, 0);
-
-                       mvert = CDDM_get_verts(result);
-                       for(a=0; a<lod.vertex_num; a++) {
-                               MVert *mv = &mvert[a];
-                               float *vbCo = &lod.vertex_buffer[a*3];
-                               
-                               VECCOPY(mv->co, vbCo);
-                       }
-
-                       if(lod.vertex_num>2) {
-                               mface = CDDM_get_faces(result);
-                               for(a=0; a<lod.face_num; a++) {
-                                       MFace *mf = &mface[a];
-                                       int *tri = &lod.triangle_index_buffer[a*3];
-                                       mf->v1 = tri[0];
-                                       mf->v2 = tri[1];
-                                       mf->v3 = tri[2];
-                                       test_index_face(mf, NULL, 0, 3);
-                               }
-                       }
-
-                       CDDM_calc_edges(result);
-                       CDDM_calc_normals(result);
-               }
-               else
-                       modifier_setError(md, "Out of memory.");
-
-               LOD_FreeDecimationData(&lod);
-       }
-       else
-               modifier_setError(md, "Non-manifold mesh as input.");
-
-       MEM_freeN(lod.vertex_buffer);
-       MEM_freeN(lod.vertex_normal_buffer);
-       MEM_freeN(lod.triangle_index_buffer);
-
-exit:
-               return result;
-}
-
-/* Smooth */
-
-static void smoothModifier_initData(ModifierData *md)
-{
-       SmoothModifierData *smd = (SmoothModifierData*) md;
-
-       smd->fac = 0.5f;
-       smd->repeat = 1;
-       smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z;
-       smd->defgrp_name[0] = '\0';
-}
-
-static void smoothModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       SmoothModifierData *smd = (SmoothModifierData*) md;
-       SmoothModifierData *tsmd = (SmoothModifierData*) target;
-
-       tsmd->fac = smd->fac;
-       tsmd->repeat = smd->repeat;
-       tsmd->flag = smd->flag;
-       strncpy(tsmd->defgrp_name, smd->defgrp_name, 32);
-}
-
-static int smoothModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
-       SmoothModifierData *smd = (SmoothModifierData*) md;
-       short flag;
-
-       flag = smd->flag & (MOD_SMOOTH_X|MOD_SMOOTH_Y|MOD_SMOOTH_Z);
-
-       /* disable if modifier is off for X, Y and Z or if factor is 0 */
-       if((smd->fac == 0.0f) || flag == 0) return 1;
-
-       return 0;
-}
-
-static CustomDataMask smoothModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       SmoothModifierData *smd = (SmoothModifierData *)md;
-       CustomDataMask dataMask = 0;
-
-       /* ask for vertexgroups if we need them */
-       if(smd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
-       return dataMask;
-}
-
-static void smoothModifier_do(
-                                 SmoothModifierData *smd, Object *ob, DerivedMesh *dm,
-        float (*vertexCos)[3], int numVerts)
-{
-       MDeformVert *dvert = NULL;
-       MEdge *medges = NULL;
-
-       int i, j, numDMEdges, defgrp_index;
-       unsigned char *uctmp;
-       float *ftmp, fac, facm;
-
-       ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts,
-               "smoothmodifier_f");
-       if (!ftmp) return;
-       uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts,
-                "smoothmodifier_uc");
-       if (!uctmp) {
-               if (ftmp) MEM_freeN(ftmp);
-               return;
-       }
-
-       fac = smd->fac;
-       facm = 1 - fac;
-
-       medges = dm->getEdgeArray(dm);
-       numDMEdges = dm->getNumEdges(dm);
-
-       defgrp_index = defgroup_name_index(ob, smd->defgrp_name);
-
-       if (defgrp_index >= 0)
-               dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
-       /* NOTICE: this can be optimized a little bit by moving the
-       * if (dvert) out of the loop, if needed */
-       for (j = 0; j < smd->repeat; j++) {
-               for (i = 0; i < numDMEdges; i++) {
-                       float fvec[3];
-                       float *v1, *v2;
-                       unsigned int idx1, idx2;
-
-                       idx1 = medges[i].v1;
-                       idx2 = medges[i].v2;
-
-                       v1 = vertexCos[idx1];
-                       v2 = vertexCos[idx2];
-
-                       fvec[0] = (v1[0] + v2[0]) / 2.0;
-                       fvec[1] = (v1[1] + v2[1]) / 2.0;
-                       fvec[2] = (v1[2] + v2[2]) / 2.0;
-
-                       v1 = &ftmp[idx1*3];
-                       v2 = &ftmp[idx2*3];
-
-                       if (uctmp[idx1] < 255) {
-                               uctmp[idx1]++;
-                               add_v3_v3v3(v1, v1, fvec);
-                       }
-                       if (uctmp[idx2] < 255) {
-                               uctmp[idx2]++;
-                               add_v3_v3v3(v2, v2, fvec);
-                       }
-               }
-
-               if (dvert) {
-                       for (i = 0; i < numVerts; i++) {
-                               MDeformWeight *dw = NULL;
-                               float f, fm, facw, *fp, *v;
-                               int k;
-                               short flag = smd->flag;
-
-                               v = vertexCos[i];
-                               fp = &ftmp[i*3];
-
-                               for (k = 0; k < dvert[i].totweight; ++k) {
-                                       if(dvert[i].dw[k].def_nr == defgrp_index) {
-                                               dw = &dvert[i].dw[k];
-                                               break;
-                                       }
-                               }
-                               if (!dw) continue;
-
-                               f = fac * dw->weight;
-                               fm = 1.0f - f;
-
-                               /* fp is the sum of uctmp[i] verts, so must be averaged */
-                               facw = 0.0f;
-                               if (uctmp[i]) 
-                                       facw = f / (float)uctmp[i];
-
-                               if (flag & MOD_SMOOTH_X)
-                                       v[0] = fm * v[0] + facw * fp[0];
-                               if (flag & MOD_SMOOTH_Y)
-                                       v[1] = fm * v[1] + facw * fp[1];
-                               if (flag & MOD_SMOOTH_Z)
-                                       v[2] = fm * v[2] + facw * fp[2];
-                       }
-               }
-               else { /* no vertex group */
-                       for (i = 0; i < numVerts; i++) {
-                               float facw, *fp, *v;
-                               short flag = smd->flag;
-
-                               v = vertexCos[i];
-                               fp = &ftmp[i*3];
-
-                               /* fp is the sum of uctmp[i] verts, so must be averaged */
-                               facw = 0.0f;
-                               if (uctmp[i]) 
-                                       facw = fac / (float)uctmp[i];
-
-                               if (flag & MOD_SMOOTH_X)
-                                       v[0] = facm * v[0] + facw * fp[0];
-                               if (flag & MOD_SMOOTH_Y)
-                                       v[1] = facm * v[1] + facw * fp[1];
-                               if (flag & MOD_SMOOTH_Z)
-                                       v[2] = facm * v[2] + facw * fp[2];
-                       }
-
-               }
-
-               memset(ftmp, 0, 3*sizeof(float)*numVerts);
-               memset(uctmp, 0, sizeof(unsigned char)*numVerts);
-       }
-
-       MEM_freeN(ftmp);
-       MEM_freeN(uctmp);
-}
-
-static void smoothModifier_deformVerts(
-                                          ModifierData *md, Object *ob, DerivedMesh *derivedData,
-          float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *dm= get_dm(md->scene, ob, NULL, derivedData, NULL, 0);
-
-       smoothModifier_do((SmoothModifierData *)md, ob, dm,
-                          vertexCos, numVerts);
-
-       if(dm != derivedData)
-               dm->release(dm);
-}
-
-static void smoothModifier_deformVertsEM(
-                                        ModifierData *md, Object *ob, EditMesh *editData,
-         DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
-       DerivedMesh *dm= get_dm(md->scene, ob, editData, derivedData, NULL, 0);
-
-       smoothModifier_do((SmoothModifierData *)md, ob, dm,
-                          vertexCos, numVerts);
-
-       if(dm != derivedData)
-               dm->release(dm);
-}
-
-/* Cast */
-
-static void castModifier_initData(ModifierData *md)
-{
-       CastModifierData *cmd = (CastModifierData*) md;
-
-       cmd->fac = 0.5f;
-       cmd->radius = 0.0f;
-       cmd->size = 0.0f;
-       cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z
-                       | MOD_CAST_SIZE_FROM_RADIUS;
-       cmd->type = MOD_CAST_TYPE_SPHERE;
-       cmd->defgrp_name[0] = '\0';
-       cmd->object = NULL;
-}
-
-
-static void castModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       CastModifierData *cmd = (CastModifierData*) md;
-       CastModifierData *tcmd = (CastModifierData*) target;
-
-       tcmd->fac = cmd->fac;
-       tcmd->radius = cmd->radius;
-       tcmd->size = cmd->size;
-       tcmd->flag = cmd->flag;
-       tcmd->type = cmd->type;
-       tcmd->object = cmd->object;
-       strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32);
-}
-
-static int castModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
-       CastModifierData *cmd = (CastModifierData*) md;
-       short flag;
-       
-       flag = cmd->flag & (MOD_CAST_X|MOD_CAST_Y|MOD_CAST_Z);
-
-       if((cmd->fac == 0.0f) || flag == 0) return 1;
-
-       return 0;
-}
-
-static CustomDataMask castModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       CastModifierData *cmd = (CastModifierData *)md;
-       CustomDataMask dataMask = 0;
-
-       /* ask for vertexgroups if we need them */
-       if(cmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
-       return dataMask;
-}
-
-static void castModifier_foreachObjectLink(
-                                          ModifierData *md, Object *ob,
-       void (*walk)(void *userData, Object *ob, Object **obpoin),
-                  void *userData)
-{
-       CastModifierData *cmd = (CastModifierData*) md;
-
-       walk (userData, ob, &cmd->object);
-}
-
-static void castModifier_updateDepgraph(
-                                       ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
-        DagNode *obNode)
-{
-       CastModifierData *cmd = (CastModifierData*) md;
-
-       if (cmd->object) {
-               DagNode *curNode = dag_get_node(forest, cmd->object);
-
-               dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
-                       "Cast Modifier");
-       }
-}
-
-static void castModifier_sphere_do(
-                                  CastModifierData *cmd, Object *ob, DerivedMesh *dm,
-          float (*vertexCos)[3], int numVerts)
-{
-       MDeformVert *dvert = NULL;
-
-       Object *ctrl_ob = NULL;
-
-       int i, defgrp_index;
-       int has_radius = 0;
-       short flag, type;
-       float fac, facm, len = 0.0f;
-       float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
-       float mat[4][4], imat[4][4];
-
-       fac = cmd->fac;
-       facm = 1.0f - fac;
-
-       flag = cmd->flag;
-       type = cmd->type; /* projection type: sphere or cylinder */
-
-       if (type == MOD_CAST_TYPE_CYLINDER) 
-               flag &= ~MOD_CAST_Z;
-
-       ctrl_ob = cmd->object;
-
-       /* spherify's center is {0, 0, 0} (the ob's own center in its local
-       * space), by default, but if the user defined a control object,
-       * we use its location, transformed to ob's local space */
-       if (ctrl_ob) {
-               if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                       invert_m4_m4(ctrl_ob->imat, ctrl_ob->obmat);
-                       mul_m4_m4m4(mat, ob->obmat, ctrl_ob->imat);
-                       invert_m4_m4(imat, mat);
-               }
-
-               invert_m4_m4(ob->imat, ob->obmat);
-               VECCOPY(center, ctrl_ob->obmat[3]);
-               mul_m4_v3(ob->imat, center);
-       }
-
-       /* now we check which options the user wants */
-
-       /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
-       /* 2) cmd->radius > 0.0f: only the vertices within this radius from
-       * the center of the effect should be deformed */
-       if (cmd->radius > FLT_EPSILON) has_radius = 1;
-
-       /* 3) if we were given a vertex group name,
-       * only those vertices should be affected */
-       defgrp_index = defgroup_name_index(ob, cmd->defgrp_name);
-
-       if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
-               dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
-       if(flag & MOD_CAST_SIZE_FROM_RADIUS) {
-               len = cmd->radius;
-       }
-       else {
-               len = cmd->size;
-       }
-
-       if(len <= 0) {
-               for (i = 0; i < numVerts; i++) {
-                       len += len_v3v3(center, vertexCos[i]);
-               }
-               len /= numVerts;
-
-               if (len == 0.0f) len = 10.0f;
-       }
-
-       /* ready to apply the effect, one vertex at a time;
-       * tiny optimization: the code is separated (with parts repeated)
-        * in two possible cases:
-       * with or w/o a vgroup. With lots of if's in the code below,
-       * further optimizations are possible, if needed */
-       if (dvert) { /* with a vgroup */
-               float fac_orig = fac;
-               for (i = 0; i < numVerts; i++) {
-                       MDeformWeight *dw = NULL;
-                       int j;
-                       float tmp_co[3];
-
-                       VECCOPY(tmp_co, vertexCos[i]);
-                       if(ctrl_ob) {
-                               if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                                       mul_m4_v3(mat, tmp_co);
-                               } else {
-                                       sub_v3_v3v3(tmp_co, tmp_co, center);
-                               }
-                       }
-
-                       VECCOPY(vec, tmp_co);
-
-                       if (type == MOD_CAST_TYPE_CYLINDER)
-                               vec[2] = 0.0f;
-
-                       if (has_radius) {
-                               if (len_v3(vec) > cmd->radius) continue;
-                       }
-
-                       for (j = 0; j < dvert[i].totweight; ++j) {
-                               if(dvert[i].dw[j].def_nr == defgrp_index) {
-                                       dw = &dvert[i].dw[j];
-                                       break;
-                               }
-                       }
-                       if (!dw) continue;
-
-                       fac = fac_orig * dw->weight;
-                       facm = 1.0f - fac;
-
-                       normalize_v3(vec);
-
-                       if (flag & MOD_CAST_X)
-                               tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
-                       if (flag & MOD_CAST_Y)
-                               tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
-                       if (flag & MOD_CAST_Z)
-                               tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
-
-                       if(ctrl_ob) {
-                               if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                                       mul_m4_v3(imat, tmp_co);
-                               } else {
-                                       add_v3_v3v3(tmp_co, tmp_co, center);
-                               }
-                       }
-
-                       VECCOPY(vertexCos[i], tmp_co);
-               }
-               return;
-       }
-
-       /* no vgroup */
-       for (i = 0; i < numVerts; i++) {
-               float tmp_co[3];
-
-               VECCOPY(tmp_co, vertexCos[i]);
-               if(ctrl_ob) {
-                       if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                               mul_m4_v3(mat, tmp_co);
-                       } else {
-                               sub_v3_v3v3(tmp_co, tmp_co, center);
-                       }
-               }
-
-               VECCOPY(vec, tmp_co);
-
-               if (type == MOD_CAST_TYPE_CYLINDER)
-                       vec[2] = 0.0f;
-
-               if (has_radius) {
-                       if (len_v3(vec) > cmd->radius) continue;
-               }
-
-               normalize_v3(vec);
-
-               if (flag & MOD_CAST_X)
-                       tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
-               if (flag & MOD_CAST_Y)
-                       tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
-               if (flag & MOD_CAST_Z)
-                       tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
-
-               if(ctrl_ob) {
-                       if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                               mul_m4_v3(imat, tmp_co);
-                       } else {
-                               add_v3_v3v3(tmp_co, tmp_co, center);
-                       }
-               }
-
-               VECCOPY(vertexCos[i], tmp_co);
-       }
-}
-
-static void castModifier_cuboid_do(
-                                  CastModifierData *cmd, Object *ob, DerivedMesh *dm,
-          float (*vertexCos)[3], int numVerts)
-{
-       MDeformVert *dvert = NULL;
-       Object *ctrl_ob = NULL;
-
-       int i, defgrp_index;
-       int has_radius = 0;
-       short flag;
-       float fac, facm;
-       float min[3], max[3], bb[8][3];
-       float center[3] = {0.0f, 0.0f, 0.0f};
-       float mat[4][4], imat[4][4];
-
-       fac = cmd->fac;
-       facm = 1.0f - fac;
-
-       flag = cmd->flag;
-
-       ctrl_ob = cmd->object;
-
-       /* now we check which options the user wants */
-
-       /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
-       /* 2) cmd->radius > 0.0f: only the vertices within this radius from
-       * the center of the effect should be deformed */
-       if (cmd->radius > FLT_EPSILON) has_radius = 1;
-
-       /* 3) if we were given a vertex group name,
-       * only those vertices should be affected */
-       defgrp_index = defgroup_name_index(ob, cmd->defgrp_name);
-
-       if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
-               dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-
-       if (ctrl_ob) {
-               if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                       invert_m4_m4(ctrl_ob->imat, ctrl_ob->obmat);
-                       mul_m4_m4m4(mat, ob->obmat, ctrl_ob->imat);
-                       invert_m4_m4(imat, mat);
-               }
-
-               invert_m4_m4(ob->imat, ob->obmat);
-               VECCOPY(center, ctrl_ob->obmat[3]);
-               mul_m4_v3(ob->imat, center);
-       }
-
-       if((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
-               for(i = 0; i < 3; i++) {
-                       min[i] = -cmd->radius;
-                       max[i] = cmd->radius;
-               }
-       } else if(!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
-               for(i = 0; i < 3; i++) {
-                       min[i] = -cmd->size;
-                       max[i] = cmd->size;
-               }
-       } else {
-               /* get bound box */
-               /* We can't use the object's bound box because other modifiers
-               * may have changed the vertex data. */
-               INIT_MINMAX(min, max);
-
-               /* Cast's center is the ob's own center in its local space,
-               * by default, but if the user defined a control object, we use
-               * its location, transformed to ob's local space. */
-               if (ctrl_ob) {
-                       float vec[3];
-
-                       /* let the center of the ctrl_ob be part of the bound box: */
-                       DO_MINMAX(center, min, max);
-
-                       for (i = 0; i < numVerts; i++) {
-                               sub_v3_v3v3(vec, vertexCos[i], center);
-                               DO_MINMAX(vec, min, max);
-                       }
-               }
-               else {
-                       for (i = 0; i < numVerts; i++) {
-                               DO_MINMAX(vertexCos[i], min, max);
-                       }
-               }
-
-               /* we want a symmetric bound box around the origin */
-               if (fabs(min[0]) > fabs(max[0])) max[0] = fabs(min[0]); 
-               if (fabs(min[1]) > fabs(max[1])) max[1] = fabs(min[1]); 
-               if (fabs(min[2]) > fabs(max[2])) max[2] = fabs(min[2]);
-               min[0] = -max[0];
-               min[1] = -max[1];
-               min[2] = -max[2];
-       }
-
-       /* building our custom bounding box */
-       bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
-       bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
-       bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
-       bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
-       bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
-       bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
-
-       /* ready to apply the effect, one vertex at a time;
-       * tiny optimization: the code is separated (with parts repeated)
-        * in two possible cases:
-       * with or w/o a vgroup. With lots of if's in the code below,
-       * further optimizations are possible, if needed */
-       if (dvert) { /* with a vgroup */
-               float fac_orig = fac;
-               for (i = 0; i < numVerts; i++) {
-                       MDeformWeight *dw = NULL;
-                       int j, octant, coord;
-                       float d[3], dmax, apex[3], fbb;
-                       float tmp_co[3];
-
-                       VECCOPY(tmp_co, vertexCos[i]);
-                       if(ctrl_ob) {
-                               if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                                       mul_m4_v3(mat, tmp_co);
-                               } else {
-                                       sub_v3_v3v3(tmp_co, tmp_co, center);
-                               }
-                       }
-
-                       if (has_radius) {
-                               if (fabs(tmp_co[0]) > cmd->radius ||
-                                                               fabs(tmp_co[1]) > cmd->radius ||
-                                                               fabs(tmp_co[2]) > cmd->radius) continue;
-                       }
-
-                       for (j = 0; j < dvert[i].totweight; ++j) {
-                               if(dvert[i].dw[j].def_nr == defgrp_index) {
-                                       dw = &dvert[i].dw[j];
-                                       break;
-                               }
-                       }
-                       if (!dw) continue;
-
-                       fac = fac_orig * dw->weight;
-                       facm = 1.0f - fac;
-
-                       /* The algo used to project the vertices to their
-                        * bounding box (bb) is pretty simple:
-                        * for each vertex v:
-                       * 1) find in which octant v is in;
-                       * 2) find which outer "wall" of that octant is closer to v;
-                       * 3) calculate factor (var fbb) to project v to that wall;
-                       * 4) project. */
-
-                       /* find in which octant this vertex is in */
-                       octant = 0;
-                       if (tmp_co[0] > 0.0f) octant += 1;
-                       if (tmp_co[1] > 0.0f) octant += 2;
-                       if (tmp_co[2] > 0.0f) octant += 4;
-
-                       /* apex is the bb's vertex at the chosen octant */
-                       copy_v3_v3(apex, bb[octant]);
-
-                       /* find which bb plane is closest to this vertex ... */
-                       d[0] = tmp_co[0] / apex[0];
-                       d[1] = tmp_co[1] / apex[1];
-                       d[2] = tmp_co[2] / apex[2];
-
-                       /* ... (the closest has the higher (closer to 1) d value) */
-                       dmax = d[0];
-                       coord = 0;
-                       if (d[1] > dmax) {
-                               dmax = d[1];
-                               coord = 1;
-                       }
-                       if (d[2] > dmax) {
-                               /* dmax = d[2]; */ /* commented, we don't need it */
-                               coord = 2;
-                       }
-
-                       /* ok, now we know which coordinate of the vertex to use */
-
-                       if (fabs(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
-                               continue;
-
-                       /* finally, this is the factor we wanted, to project the vertex
-                       * to its bounding box (bb) */
-                       fbb = apex[coord] / tmp_co[coord];
-
-                       /* calculate the new vertex position */
-                       if (flag & MOD_CAST_X)
-                               tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
-                       if (flag & MOD_CAST_Y)
-                               tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
-                       if (flag & MOD_CAST_Z)
-                               tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
-
-                       if(ctrl_ob) {
-                               if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                                       mul_m4_v3(imat, tmp_co);
-                               } else {
-                                       add_v3_v3v3(tmp_co, tmp_co, center);
-                               }
-                       }
-
-                       VECCOPY(vertexCos[i], tmp_co);
-               }
-               return;
-       }
-
-       /* no vgroup (check previous case for comments about the code) */
-       for (i = 0; i < numVerts; i++) {
-               int octant, coord;
-               float d[3], dmax, fbb, apex[3];
-               float tmp_co[3];
-
-               VECCOPY(tmp_co, vertexCos[i]);
-               if(ctrl_ob) {
-                       if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                               mul_m4_v3(mat, tmp_co);
-                       } else {
-                               sub_v3_v3v3(tmp_co, tmp_co, center);
-                       }
-               }
-
-               if (has_radius) {
-                       if (fabs(tmp_co[0]) > cmd->radius ||
-                                                fabs(tmp_co[1]) > cmd->radius ||
-                                                fabs(tmp_co[2]) > cmd->radius) continue;
-               }
-
-               octant = 0;
-               if (tmp_co[0] > 0.0f) octant += 1;
-               if (tmp_co[1] > 0.0f) octant += 2;
-               if (tmp_co[2] > 0.0f) octant += 4;
-
-               copy_v3_v3(apex, bb[octant]);
-
-               d[0] = tmp_co[0] / apex[0];
-               d[1] = tmp_co[1] / apex[1];
-               d[2] = tmp_co[2] / apex[2];
-
-               dmax = d[0];
-               coord = 0;
-               if (d[1] > dmax) {
-                       dmax = d[1];
-                       coord = 1;
-               }
-               if (d[2] > dmax) {
-                       /* dmax = d[2]; */ /* commented, we don't need it */
-                       coord = 2;
-               }
-
-               if (fabs(tmp_co[coord]) < FLT_EPSILON)
-                       continue;
-
-               fbb = apex[coord] / tmp_co[coord];
-
-               if (flag & MOD_CAST_X)
-                       tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
-               if (flag & MOD_CAST_Y)
-                       tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
-               if (flag & MOD_CAST_Z)
-                       tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
-
-               if(ctrl_ob) {
-                       if(flag & MOD_CAST_USE_OB_TRANSFORM) {
-                               mul_m4_v3(imat, tmp_co);
-                       } else {
-                               add_v3_v3v3(tmp_co, tmp_co, center);
-                       }
-               }
-
-               VECCOPY(vertexCos[i], tmp_co);
-       }
-}
-
-static void castModifier_deformVerts(
-                                        ModifierData *md, Object *ob, DerivedMesh *derivedData,
-        float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *dm = NULL;
-       CastModifierData *cmd = (CastModifierData *)md;
-
-       dm = get_dm(md->scene, ob, NULL, derivedData, NULL, 0);
-
-       if (cmd->type == MOD_CAST_TYPE_CUBOID) {
-               castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
-       } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
-               castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
-       }
-
-       if(dm != derivedData)
-               dm->release(dm);
-}
-
-static void castModifier_deformVertsEM(
-                                          ModifierData *md, Object *ob, EditMesh *editData,
-          DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
-       DerivedMesh *dm = get_dm(md->scene, ob, editData, derivedData, NULL, 0);
-       CastModifierData *cmd = (CastModifierData *)md;
-
-       if (cmd->type == MOD_CAST_TYPE_CUBOID) {
-               castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
-       } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
-               castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
-       }
-
-       if(dm != derivedData)
-               dm->release(dm);
-}
-
-/* Wave */
-
-static void waveModifier_initData(ModifierData *md)
-{
-       WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
-
-       wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL
-                       | MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
-
-       wmd->objectcenter = NULL;
-       wmd->texture = NULL;
-       wmd->map_object = NULL;
-       wmd->height= 0.5f;
-       wmd->width= 1.5f;
-       wmd->speed= 0.25f;
-       wmd->narrow= 1.5f;
-       wmd->lifetime= 0.0f;
-       wmd->damp= 10.0f;
-       wmd->falloff= 0.0f;
-       wmd->texmapping = MOD_WAV_MAP_LOCAL;
-       wmd->defgrp_name[0] = 0;
-}
-
-static void waveModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       WaveModifierData *wmd = (WaveModifierData*) md;
-       WaveModifierData *twmd = (WaveModifierData*) target;
-
-       twmd->damp = wmd->damp;
-       twmd->flag = wmd->flag;
-       twmd->height = wmd->height;
-       twmd->lifetime = wmd->lifetime;
-       twmd->narrow = wmd->narrow;
-       twmd->speed = wmd->speed;
-       twmd->startx = wmd->startx;
-       twmd->starty = wmd->starty;
-       twmd->timeoffs = wmd->timeoffs;
-       twmd->width = wmd->width;
-       twmd->falloff = wmd->falloff;
-       twmd->objectcenter = wmd->objectcenter;
-       twmd->texture = wmd->texture;
-       twmd->map_object = wmd->map_object;
-       twmd->texmapping = wmd->texmapping;
-       strncpy(twmd->defgrp_name, wmd->defgrp_name, 32);
-}
-
-static int waveModifier_dependsOnTime(ModifierData *md)
-{
-       return 1;
-}
-
-static void waveModifier_foreachObjectLink(
-                                          ModifierData *md, Object *ob,
-       ObjectWalkFunc walk, void *userData)
-{
-       WaveModifierData *wmd = (WaveModifierData*) md;
-
-       walk(userData, ob, &wmd->objectcenter);
-       walk(userData, ob, &wmd->map_object);
-}
-
-static void waveModifier_foreachIDLink(ModifierData *md, Object *ob,
-                                          IDWalkFunc walk, void *userData)
-{
-       WaveModifierData *wmd = (WaveModifierData*) md;
-
-       walk(userData, ob, (ID **)&wmd->texture);
-
-       waveModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
-}
-
-static void waveModifier_updateDepgraph(
-                                       ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
-        DagNode *obNode)
-{
-       WaveModifierData *wmd = (WaveModifierData*) md;
-
-       if(wmd->objectcenter) {
-               DagNode *curNode = dag_get_node(forest, wmd->objectcenter);
-
-               dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
-                       "Wave Modifier");
-       }
-
-       if(wmd->map_object) {
-               DagNode *curNode = dag_get_node(forest, wmd->map_object);
-
-               dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
-                       "Wave Modifer");
-       }
-}
-
-static CustomDataMask waveModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       WaveModifierData *wmd = (WaveModifierData *)md;
-       CustomDataMask dataMask = 0;
-
-
-       /* ask for UV coordinates if we need them */
-       if(wmd->texture && wmd->texmapping == MOD_WAV_MAP_UV)
-               dataMask |= (1 << CD_MTFACE);
-
-       /* ask for vertexgroups if we need them */
-       if(wmd->defgrp_name[0])
-               dataMask |= (1 << CD_MDEFORMVERT);
-
-       return dataMask;
-}
-
-static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob,
-                                          DerivedMesh *dm,
-          float (*co)[3], float (*texco)[3],
-                  int numVerts)
-{
-       int i;
-       int texmapping = wmd->texmapping;
-
-       if(texmapping == MOD_WAV_MAP_OBJECT) {
-               if(wmd->map_object)
-                       invert_m4_m4(wmd->map_object->imat, wmd->map_object->obmat);
-               else /* if there is no map object, default to local */
-                       texmapping = MOD_WAV_MAP_LOCAL;
-       }
-
-       /* UVs need special handling, since they come from faces */
-       if(texmapping == MOD_WAV_MAP_UV) {
-               if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
-                       MFace *mface = dm->getFaceArray(dm);
-                       MFace *mf;
-                       char *done = MEM_callocN(sizeof(*done) * numVerts,
-                                       "get_texture_coords done");
-                       int numFaces = dm->getNumFaces(dm);
-                       char uvname[32];
-                       MTFace *tf;
-
-                       validate_layer_name(&dm->faceData, CD_MTFACE, wmd->uvlayer_name, uvname);
-                       tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);
-
-                       /* verts are given the UV from the first face that uses them */
-                       for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
-                               if(!done[mf->v1]) {
-                                       texco[mf->v1][0] = tf->uv[0][0];
-                                       texco[mf->v1][1] = tf->uv[0][1];
-                                       texco[mf->v1][2] = 0;
-                                       done[mf->v1] = 1;
-                               }
-                               if(!done[mf->v2]) {
-                                       texco[mf->v2][0] = tf->uv[1][0];
-                                       texco[mf->v2][1] = tf->uv[1][1];
-                                       texco[mf->v2][2] = 0;
-                                       done[mf->v2] = 1;
-                               }
-                               if(!done[mf->v3]) {
-                                       texco[mf->v3][0] = tf->uv[2][0];
-                                       texco[mf->v3][1] = tf->uv[2][1];
-                                       texco[mf->v3][2] = 0;
-                                       done[mf->v3] = 1;
-                               }
-                               if(!done[mf->v4]) {
-                                       texco[mf->v4][0] = tf->uv[3][0];
-                                       texco[mf->v4][1] = tf->uv[3][1];
-                                       texco[mf->v4][2] = 0;
-                                       done[mf->v4] = 1;
-                               }
-                       }
-
-                       /* remap UVs from [0, 1] to [-1, 1] */
-                       for(i = 0; i < numVerts; ++i) {
-                               texco[i][0] = texco[i][0] * 2 - 1;
-                               texco[i][1] = texco[i][1] * 2 - 1;
-                       }
-
-                       MEM_freeN(done);
-                       return;
-               } else /* if there are no UVs, default to local */
-                       texmapping = MOD_WAV_MAP_LOCAL;
-       }
-
-       for(i = 0; i < numVerts; ++i, ++co, ++texco) {
-               switch(texmapping) {
-                       case MOD_WAV_MAP_LOCAL:
-                               VECCOPY(*texco, *co);
-                               break;
-                       case MOD_WAV_MAP_GLOBAL:
-                               VECCOPY(*texco, *co);
-                               mul_m4_v3(ob->obmat, *texco);
-                               break;
-                       case MOD_WAV_MAP_OBJECT:
-                               VECCOPY(*texco, *co);
-                               mul_m4_v3(ob->obmat, *texco);
-                               mul_m4_v3(wmd->map_object->imat, *texco);
-                               break;
-               }
-       }
-}
-
-static void waveModifier_do(WaveModifierData *md, 
-               Scene *scene, Object *ob, DerivedMesh *dm,
-          float (*vertexCos)[3], int numVerts)
-{
-       WaveModifierData *wmd = (WaveModifierData*) md;
-       MVert *mvert = NULL;
-       MDeformVert *dvert = NULL;
-       int defgrp_index;
-       float ctime = bsystem_time(scene, ob, (float)scene->r.cfra, 0.0);
-       float minfac =
-                       (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
-       float lifefac = wmd->height;
-       float (*tex_co)[3] = NULL;
-
-       if(wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH)
-               mvert = dm->getVertArray(dm);
-
-       if(wmd->objectcenter){
-               float mat[4][4];
-               /* get the control object's location in local coordinates */
-               invert_m4_m4(ob->imat, ob->obmat);
-               mul_m4_m4m4(mat, wmd->objectcenter->obmat, ob->imat);
-
-               wmd->startx = mat[3][0];
-               wmd->starty = mat[3][1];
-       }
-
-       /* get the index of the deform group */
-       defgrp_index = defgroup_name_index(ob, wmd->defgrp_name);
-
-       if(defgrp_index >= 0){
-               dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-       }
-
-       if(wmd->damp == 0) wmd->damp = 10.0f;
-
-       if(wmd->lifetime != 0.0) {
-               float x = ctime - wmd->timeoffs;
-
-               if(x > wmd->lifetime) {
-                       lifefac = x - wmd->lifetime;
-
-                       if(lifefac > wmd->damp) lifefac = 0.0;
-                       else lifefac =
-                               (float)(wmd->height * (1.0 - sqrt(lifefac / wmd->damp)));
-               }
-       }
-
-       if(wmd->texture) {
-               tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts,
-                                        "waveModifier_do tex_co");
-               wavemod_get_texture_coords(wmd, ob, dm, vertexCos, tex_co, numVerts);
-       }
-
-       if(lifefac != 0.0) {
-               int i;
-
-               for(i = 0; i < numVerts; i++) {
-                       float *co = vertexCos[i];
-                       float x = co[0] - wmd->startx;
-                       float y = co[1] - wmd->starty;
-                       float amplit= 0.0f;
-                       float dist = 0.0f;
-                       float falloff_fac = 0.0f;
-                       TexResult texres;
-                       MDeformWeight *def_weight = NULL;
-
-                       /* get weights */
-                       if(dvert) {
-                               int j;
-                               for(j = 0; j < dvert[i].totweight; ++j) {
-                                       if(dvert[i].dw[j].def_nr == defgrp_index) {
-                                               def_weight = &dvert[i].dw[j];
-                                               break;
-                                       }
-                               }
-
-                               /* if this vert isn't in the vgroup, don't deform it */
-                               if(!def_weight) continue;
-                       }
-
-                       if(wmd->texture) {
-                               texres.nor = NULL;
-                               get_texture_value(wmd->texture, tex_co[i], &texres);
-                       }
-
-                       /*get dist*/
-                       if(wmd->flag & MOD_WAVE_X) {
-                               if(wmd->flag & MOD_WAVE_Y){
-                                       dist = (float)sqrt(x*x + y*y);
-                               }
-                               else{
-                                       dist = fabs(x);
-                               }
-                       }
-                       else if(wmd->flag & MOD_WAVE_Y) {
-                               dist = fabs(y);
-                       }
-
-                       falloff_fac = (1.0-(dist / wmd->falloff));
-                       CLAMP(falloff_fac,0,1);
-
-                       if(wmd->flag & MOD_WAVE_X) {
-                               if(wmd->flag & MOD_WAVE_Y) amplit = (float)sqrt(x*x + y*y);
-                               else amplit = x;
-                       }
-                       else if(wmd->flag & MOD_WAVE_Y)
-                               amplit= y;
-
-                       /* this way it makes nice circles */
-                       amplit -= (ctime - wmd->timeoffs) * wmd->speed;
-
-                       if(wmd->flag & MOD_WAVE_CYCL) {
-                               amplit = (float)fmod(amplit - wmd->width, 2.0 * wmd->width)
-                                               + wmd->width;
-                       }
-
-                       /* GAUSSIAN */
-                       if(amplit > -wmd->width && amplit < wmd->width) {
-                               amplit = amplit * wmd->narrow;
-                               amplit = (float)(1.0 / exp(amplit * amplit) - minfac);
-
-                               /*apply texture*/
-                               if(wmd->texture)
-                                       amplit = amplit * texres.tin;
-
-                               /*apply weight*/
-                               if(def_weight)
-                                       amplit = amplit * def_weight->weight;
-
-                               /*apply falloff*/
-                               if (wmd->falloff > 0)
-                                       amplit = amplit * falloff_fac;
-
-                               if(mvert) {
-                                       /* move along normals */
-                                       if(wmd->flag & MOD_WAVE_NORM_X) {
-                                               co[0] += (lifefac * amplit) * mvert[i].no[0] / 32767.0f;
-                                       }
-                                       if(wmd->flag & MOD_WAVE_NORM_Y) {
-                                               co[1] += (lifefac * amplit) * mvert[i].no[1] / 32767.0f;
-                                       }
-                                       if(wmd->flag & MOD_WAVE_NORM_Z) {
-                                               co[2] += (lifefac * amplit) * mvert[i].no[2] / 32767.0f;
-                                       }
-                               }
-                               else {
-                                       /* move along local z axis */
-                                       co[2] += lifefac * amplit;
-                               }
-                       }
-               }
-       }
-
-       if(wmd->texture) MEM_freeN(tex_co);
-}
-
-static void waveModifier_deformVerts(
-                                        ModifierData *md, Object *ob, DerivedMesh *derivedData,
-        float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
-       DerivedMesh *dm= derivedData;
-       WaveModifierData *wmd = (WaveModifierData *)md;
-
-       if(wmd->flag & MOD_WAVE_NORM)
-               dm= get_cddm(md->scene, ob, NULL, dm, vertexCos);
-       else if(wmd->texture || wmd->defgrp_name[0])
-               dm= get_dm(md->scene, ob, NULL, dm, NULL, 0);
-
-       waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
-
-       if(dm != derivedData)
-               dm->release(dm);
-}
-
-static void waveModifier_deformVertsEM(
-                                          ModifierData *md, Object *ob, EditMesh *editData,
-          DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
-       DerivedMesh *dm= derivedData;
-       WaveModifierData *wmd = (WaveModifierData *)md;
-
-       if(wmd->flag & MOD_WAVE_NORM)
-               dm= get_cddm(md->scene, ob, editData, dm, vertexCos);
-       else if(wmd->texture || wmd->defgrp_name[0])
-               dm= get_dm(md->scene, ob, editData, dm, NULL, 0);
-
-       waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts);
-
-       if(dm != derivedData)
-               dm->release(dm);
-}
-
-/* Armature */
-
-static void armatureModifier_initData(ModifierData *md)
-{
-       ArmatureModifierData *amd = (ArmatureModifierData*) md;
-       
-       amd->deformflag = ARM_DEF_ENVELOPE | ARM_DEF_VGROUP;
-}
-
-static void armatureModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       ArmatureModifierData *amd = (ArmatureModifierData*) md;
-       ArmatureModifierData *tamd = (ArmatureModifierData*) target;
-
-       tamd->object = amd->object;
-       tamd->deformflag = amd->deformflag;
-       strncpy(tamd->defgrp_name, amd->defgrp_name, 32);
-}
-
-static CustomDataMask armatureModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       CustomDataMask dataMask = 0;
-
-       /* ask for vertexgroups */
-       dataMask |= (1 << CD_MDEFORMVERT);
-
-       return dataMask;
-}
-
-static int armatureModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
-       ArmatureModifierData *amd = (ArmatureModifierData*) md;
-
-       return !amd->object;
-}
-
-static void armatureModifier_foreachObjectLink(
-                                                  ModifierData *md, Object *ob,
-               void (*walk)(void *userData, Object *ob, Object **obpoin),
-                  void *userData)
-{
-       ArmatureModifierData *amd = (ArmatureModifierData*) md;
-
-       walk(userData, ob, &amd->object);
-}
-
-static void armatureModifier_updateDepgraph(
-                                               ModifierData *md, DagForest *forest, Scene *scene, Object *ob,
-        DagNode *obNode)
-{
-       ArmatureModifierData *amd = (ArmatureModifierData*) md;
-
-       if (amd->object) {
-               DagNode *curNode = dag_get_node(forest, amd->object);
-
-               dag_add_relation(forest, curNode, obNode,
-                                DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Armature Modifier");
-       }
-}
-
-static void armatureModifier_deformVerts(
-                                        ModifierData *md, Object *ob, DerivedMesh *derivedData,
-         float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
-       ArmatureModifierData *amd = (ArmatureModifierData*) md;
-
-       modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */
-       
-       armature_deform_verts(amd->object, ob, derivedData, vertexCos, NULL,
-                                 numVerts, amd->deformflag, 
-        (float(*)[3])amd->prevCos, amd->defgrp_name);
-       /* free cache */
-       if(amd->prevCos) {
-               MEM_freeN(amd->prevCos);
-               amd->prevCos= NULL;
-       }
-}
-
-static void armatureModifier_deformVertsEM(
-                                          ModifierData *md, Object *ob, EditMesh *editData,
-       DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
-       ArmatureModifierData *amd = (ArmatureModifierData*) md;
-       DerivedMesh *dm = derivedData;
-
-       if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
-       armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts,
-                                 amd->deformflag, NULL, amd->defgrp_name);
-
-       if(!derivedData) dm->release(dm);
-}
-
-static void armatureModifier_deformMatricesEM(
-                                                 ModifierData *md, Object *ob, EditMesh *editData,
-          DerivedMesh *derivedData, float (*vertexCos)[3],
-                                                float (*defMats)[3][3], int numVerts)
-{
-       ArmatureModifierData *amd = (ArmatureModifierData*) md;
-       DerivedMesh *dm = derivedData;
-
-       if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
-       armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts,
-                                 amd->deformflag, NULL, amd->defgrp_name);
-
-       if(!derivedData) dm->release(dm);
-}
-
-/* Hook */
-
-static void hookModifier_initData(ModifierData *md) 
-{
-       HookModifierData *hmd = (HookModifierData*) md;
-
-       hmd->force= 1.0;
-}
-
-static void hookModifier_copyData(ModifierData *md, ModifierData *target)
-{
-       HookModifierData *hmd = (HookModifierData*) md;
-       HookModifierData *thmd = (HookModifierData*) target;
-
-       VECCOPY(thmd->cent, hmd->cent);
-       thmd->falloff = hmd->falloff;
-       thmd->force = hmd->force;
-       thmd->object = hmd->object;
-       thmd->totindex = hmd->totindex;
-       thmd->indexar = MEM_dupallocN(hmd->indexar);
-       memcpy(thmd->parentinv, hmd->parentinv, sizeof(hmd->parentinv));
-       strncpy(thmd->name, hmd->name, 32);
-       strncpy(thmd->subtarget, hmd->subtarget, 32);
-}
-
-static CustomDataMask hookModifier_requiredDataMask(Object *ob, ModifierData *md)
-{
-       HookModifierData *hmd = (HookModifierData *)md;
-       CustomDataMask dataMask = 0;
-
-       /* ask for vertexgroups if we need them */
-       if(!hmd->indexar && hmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
-
-       return dataMask;
-}
-
-static void hookModifier_freeData(ModifierData *md)
-{
-       HookModifierData *hmd = (HookModifierData*) md;
-
-       if (hmd->indexar) MEM_freeN(hmd->indexar);
-}
-
-static int hookModifier_isDisabled(ModifierData *md, int useRenderParams)
-{
-       HookModifierData *hmd = (HookModifierData*) md;
-
-       return !hmd->object;
-}
-
-static void hookModifier_foreachObjectLink(
-                                          ModifierData *md, Object *ob,
-       void (*walk)(void *userData, Object *ob, Object **obpoin),
-                  void *userData)
-{
-       HookModifierData *hmd = (HookModifierData*) md;
-
-       walk(userData, ob, &hmd->object);
-}
-
-static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene,
-                                       Object *ob, DagNode *obNode)
-{
-       HookModifierData *hmd = (HookModifierData*) md;
-
-       if (hmd->object) {
-               DagNode *curNode = dag_get_node(forest, hmd->object);
-               
-               if (hmd->subtarget[0])
-                       dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA|DAG_RL_DATA_DATA, "Hook Modifier");
-               else
-                       dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "Hook Modifier");
-       }
-}
-
-static void hookModifier_deformVerts(
-                                        ModifierData *md, Object *ob, DerivedMesh *derivedData,
-        float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
-       HookModifierData *hmd = (HookModifierData*) md;
-       bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget);
-       float vec[3], mat[4][4], dmat[4][4];
-       int i;
-       DerivedMesh *dm = derivedData;
-       
-       /* 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 */
-               mul_m4_m4m4(dmat, pchan->pose_mat, hmd->object->obmat);
-       }
-       else {
-               /* just object target */
-               copy_m4_m4(dmat, hmd->object->obmat);
-       }
-       invert_m4_m4(ob->imat, ob->obmat);
-       mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv,
-                        NULL, NULL, NULL, NULL, NULL);
-
-       /* vertex indices? */
-       if(hmd->indexar) {
-               for(i = 0; i < hmd->totindex; i++) {
-                       int index = hmd->indexar[i];
-
-                       /* This should always be true and I don't generally like 
-                       * "paranoid" style code like this, but old files can have
-                       * indices that are out of range because old blender did
-                       * not correct them on exit editmode. - zr
-                       */
-                       if(index < numVerts) {
-                               float *co = vertexCos[index];
-                               float fac = hmd->force;
-
-                               /* if DerivedMesh is present and has original index data,
-                               * use it
-                               */
-                               if(dm && dm->getVertDataArray(dm, CD_ORIGINDEX)) {
-                                       int j;
-                                       int orig_index;
-                                       for(j = 0; j < numVerts; ++j) {
-                                               fac = hmd->force;
-                                               orig_index = *(int *)dm->getVertData(dm, j,
-                                                               CD_ORIGINDEX);
-                                               if(orig_index == index) {
-                                                       co = vertexCos[j];
-                                                       if(hmd->falloff != 0.0) {
-                                                               float len = len_v3v3(co, hmd->cent);
-                                                               if(len > hmd->falloff) fac = 0.0;
-                                                               else if(len > 0.0)
-                                                                       fac *= sqrt(1.0 - len / hmd->falloff);
-                                                       }
-
-                                                       if(fac != 0.0) {
-                                                               mul_v3_m4v3(vec, mat, co);
-                                                               interp_v3_v3v3(co, co, vec, fac);
-                                                       }
-                                               }
-                                       }
-                               } else {
-                                       if(hmd->falloff != 0.0) {
-                                               float len = len_v3v3(co, hmd->cent);
-                                               if(len > hmd->falloff) fac = 0.0;
-                                               else if(len > 0.0)
-                                                       fac *= sqrt(1.0 - len / hmd->falloff);
-                                       }
-
-                                       if(fac != 0.0) {
-                                               mul_v3_m4v3(vec, mat, co);
-                                               interp_v3_v3v3(co, co, vec, fac);
-                                       }
-                               }
-                       }
-               }
-       } 
-       else if(hmd->name[0]) { /* vertex group hook */
-               Mesh *me = ob->data;
-               int use_dverts = 0;
-               int maxVerts = 0;
-               int defgrp_index = defgroup_name_index(ob, hmd->name);
-
-               if(dm) {
-                       if(dm->getVertData(dm, 0, CD_MDEFORMVERT)) {
-                               maxVerts = dm->getNumVerts(dm);
-                               use_dverts = 1;
-                       }
-               }
-               else if(me->dvert) {
-                       maxVerts = me->totvert;
-                       use_dverts = 1;
-               }
-
-               if(defgrp_index >= 0 && use_dverts) {
-                       MDeformVert *dvert = me->dvert;
-                       int i, j;
-
-                       for(i = 0; i < maxVerts; i++, dvert++) {
-                               if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT);
-                               for(j = 0; j < dvert->totweight; j++) {
-                                       if(dvert->dw[j].def_nr == defgrp_index) {
-                                               float fac = hmd->force*dvert->dw[j].weight;
-                                               float *co = vertexCos[i];
-
-                                               if(hmd->falloff != 0.0) {
-                                                       float len = len_v3v3(co, hmd->cent);
-                                                       if(len > hmd->falloff) fac = 0.0;
-                                                       else if(len > 0.0)
-                                                               fac *= sqrt(1.0 - len / hmd->falloff);
-                                               }
-
-                                               mul_v3_m4v3(vec, mat, co);
-                                               interp_v3_v3v3(co, co, vec, fac);
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-static void hookModifier_deformVertsEM(
-                                          ModifierData *md, Object *ob, EditMesh *editData,
-          DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
-{
-       DerivedMesh *dm = derivedData;
-
-       if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
-
-       hookModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
-
-       if(!derivedData) dm->release(dm);
-}
-
-/* Softbody */
-
-static void softbodyModifier_deformVerts(
-                                        ModifierData *md, Object *ob, DerivedMesh *derivedData,
-         float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
-{
-       sbObjectStep(md->scene, ob, (float)md->scene->r.cfra, vertexCos, numVerts);
-}
-
-static int softbodyModifier_dependsOnTime(ModifierData *md)
-{
-       return 1;
-}
-
-/* Solidify */
-
-
-typedef struct EdgeFaceRef {
-       int f1; /* init as -1 */
-       int f2;
-} EdgeFaceRef;
-
-static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
-{
-       int i, numVerts, numEdges, numFaces;
-       MFace *mface, *mf;
-       MVert *mvert, *mv;
-
-       float (*face_nors)[3];
-       float *f_no;
-       int calc_face_nors= 0;
-
-       numVerts = dm->getNumVerts(dm);
-       numEdges = dm->getNumEdges(dm);
-       numFaces = dm->getNumFaces(dm);
-       mface = dm->getFaceArray(dm);
-       mvert = dm->getVertArray(dm);
-
-       /* we don't want to overwrite any referenced layers */
-
-       /*
-       Dosnt work here!
-       mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
-       cddm->mvert = mv;
-       */
-
-       face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
-       if(!face_nors) {
-               calc_face_nors = 1;
-               face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, numFaces);
-       }
-
-       mv = mvert;
-       mf = mface;
-
-       {
-               EdgeHash *edge_hash = BLI_edgehash_new();
-               EdgeHashIterator *edge_iter;
-               int edge_ref_count = 0;
-               int ed_v1, ed_v2; /* use when getting the key */
-               EdgeFaceRef *edge_ref_array = MEM_callocN(numEdges * sizeof(EdgeFaceRef), "Edge Connectivity");
-               EdgeFaceRef *edge_ref;
-               float edge_normal[3];
-
-               /* This function adds an edge hash if its not there, and adds the face index */
-#define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \
-                               edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \
-                               if (!edge_ref) { \
-                                       edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \
-                                       edge_ref->f1=i; \
-                                       edge_ref->f2=-1; \
-                                       BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \
-                               } else { \
-                                       edge_ref->f2=i; \
-                               }
-
-               for(i = 0; i < numFaces; i++, mf++) {
-                       f_no = face_nors[i];
-
-                       if(mf->v4) {
-                               if(calc_face_nors)
-                                       normal_quad_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
-
-                               NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
-                               NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
-                               NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v4);
-                               NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v4, mf->v1);
-                       } else {
-                               if(calc_face_nors)
-                                       normal_tri_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
-
-                               NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
-                               NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
-                               NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v1);
-                       }
-               }
-
-               for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) {
-                       /* Get the edge vert indicies, and edge value (the face indicies that use it)*/
-                       BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2);
-                       edge_ref = BLI_edgehashIterator_getValue(edge_iter);
-
-                       if (edge_ref->f2 != -1) {
-                               /* We have 2 faces using this edge, calculate the edges normal
-                                * using the angle between the 2 faces as a weighting */
-                               add_v3_v3v3(edge_normal, face_nors[edge_ref->f1], face_nors[edge_ref->f2]);
-                               normalize_v3(edge_normal);
-                               mul_v3_fl(edge_normal, angle_normalized_v3v3(face_nors[edge_ref->f1], face_nors[edge_ref->f2]));
-                       } else {
-            &nbs