dont use tface hide or select anymore, since maintaining 2 sets of hide/select data...
[blender.git] / source / blender / blenkernel / intern / DerivedMesh.c
index 25ec8d6e3a49385077755d2c413f0559d229d299..fa8f76178d590d53a7e9a0a358edf00ffd2d7858 100644 (file)
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
  */
 
+#include <string.h>
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+#include <zlib.h>
+
 #include "PIL_time.h"
 
 #include "MEM_guardedalloc.h"
 
 #include "DNA_effect_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_key_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_object_force.h"
+#include "DNA_object_fluidsim.h" // N_T
+#include "DNA_scene_types.h" // N_T
+#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
 
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
 #include "BLI_editVert.h"
+#include "BLI_linklist.h"
 
 #include "BKE_utildefines.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_customdata.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_displist.h"
 #include "BKE_effect.h"
 #include "BKE_subsurf.h"
 #include "BKE_deform.h"
 #include "BKE_modifier.h"
+#include "BKE_key.h"
+
+#ifdef WITH_VERSE
+#include "BKE_verse.h"
+#endif
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "multires.h"
+
+// headers for fluidsim bobj meshes
+#include <stdlib.h>
+#include "LBM_fluidsim.h"
+#include "elbeem.h"
+
 ///////////////////////////////////
 ///////////////////////////////////
 
-typedef struct {
-       DerivedMesh dm;
+MVert *dm_getVertArray(DerivedMesh *dm)
+{
+       MVert *mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
 
-       Object *ob;
-       Mesh *me;
-       MVert *verts;
-       float *nors;
+       if (!mvert) {
+               mvert = CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL,
+                       dm->getNumVerts(dm));
+               CustomData_set_layer_flag(&dm->vertData, CD_MVERT, CD_FLAG_TEMPORARY);
+               dm->copyVertArray(dm, mvert);
+       }
 
-       int freeNors, freeVerts;
-} MeshDerivedMesh;
+       return mvert;
+}
 
-static DispListMesh *meshDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
+MEdge *dm_getEdgeArray(DerivedMesh *dm)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me = mdm->me;
-       DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "dlm");
+       MEdge *medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
+
+       if (!medge) {
+               medge = CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL,
+                       dm->getNumEdges(dm));
+               CustomData_set_layer_flag(&dm->edgeData, CD_MEDGE, CD_FLAG_TEMPORARY);
+               dm->copyEdgeArray(dm, medge);
+       }
 
-       dlm->totvert = me->totvert;
-       dlm->totedge = me->totedge;
-       dlm->totface = me->totface;
-       dlm->mvert = mdm->verts;
-       dlm->medge = me->medge;
-       dlm->mface = me->mface;
-       dlm->tface = me->tface;
-       dlm->mcol = me->mcol;
-       dlm->nors = mdm->nors;
-       dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 1;
+       return medge;
+}
 
-       if (!allowShared) {
-               dlm->mvert = MEM_dupallocN(dlm->mvert);
-               if (dlm->medge) dlm->medge = MEM_dupallocN(dlm->medge);
-               dlm->mface = MEM_dupallocN(dlm->mface);
-               if (dlm->tface) dlm->tface = MEM_dupallocN(dlm->tface);
-               if (dlm->mcol) dlm->mcol = MEM_dupallocN(dlm->mcol);
-               if (dlm->nors) dlm->nors = MEM_dupallocN(dlm->nors);
+MFace *dm_getFaceArray(DerivedMesh *dm)
+{
+       MFace *mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
 
-               dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 0;
+       if (!mface) {
+               mface = CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL,
+                       dm->getNumFaces(dm));
+               CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY);
+               dm->copyFaceArray(dm, mface);
        }
 
-       return dlm;
+       return mface;
 }
 
-static void meshDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
+MVert *dm_dupVertArray(DerivedMesh *dm)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me = mdm->me;
-       int i;
+       MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm),
+                                "dm_dupVertArray tmp");
 
-       if (me->totvert) {
-               for (i=0; i<me->totvert; i++) {
-                       DO_MINMAX(mdm->verts[i].co, min_r, max_r);
-               }
-       } else {
-               min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
-       }
+       if(tmp) dm->copyVertArray(dm, tmp);
+
+       return tmp;
 }
 
-static void meshDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
+MEdge *dm_dupEdgeArray(DerivedMesh *dm)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me = mdm->me;
-       int i;
+       MEdge *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumEdges(dm),
+                                "dm_dupEdgeArray tmp");
 
-       for (i=0; i<me->totvert; i++) {
-               cos_r[i][0] = mdm->verts[i].co[0];
-               cos_r[i][1] = mdm->verts[i].co[1];
-               cos_r[i][2] = mdm->verts[i].co[2];
-       }
+       if(tmp) dm->copyEdgeArray(dm, tmp);
+
+       return tmp;
 }
 
-static void meshDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
+MFace *dm_dupFaceArray(DerivedMesh *dm)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
+       MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumFaces(dm),
+                                "dm_dupFaceArray tmp");
+
+       if(tmp) dm->copyFaceArray(dm, tmp);
 
-       VECCOPY(co_r, mdm->verts[index].co);
+       return tmp;
 }
 
-static void meshDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
+void DM_init_funcs(DerivedMesh *dm)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       short *no = mdm->verts[index].no;
+       /* default function implementations */
+       dm->getVertArray = dm_getVertArray;
+       dm->getEdgeArray = dm_getEdgeArray;
+       dm->getFaceArray = dm_getFaceArray;
+       dm->dupVertArray = dm_dupVertArray;
+       dm->dupEdgeArray = dm_dupEdgeArray;
+       dm->dupFaceArray = dm_dupFaceArray;
 
-       no_r[0] = no[0]/32767.f;
-       no_r[1] = no[1]/32767.f;
-       no_r[2] = no[2]/32767.f;
+       dm->getVertData = DM_get_vert_data;
+       dm->getEdgeData = DM_get_edge_data;
+       dm->getFaceData = DM_get_face_data;
+       dm->getVertDataArray = DM_get_vert_data_layer;
+       dm->getEdgeDataArray = DM_get_edge_data_layer;
+       dm->getFaceDataArray = DM_get_face_data_layer;
 }
 
-static void meshDM_drawVerts(DerivedMesh *dm)
+void DM_init(DerivedMesh *dm,
+             int numVerts, int numEdges, int numFaces)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me = mdm->me;
-       int a;
+       CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
+       CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
+       CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
 
-       glBegin(GL_POINTS);
-       for(a=0; a<me->totvert; a++) {
-               glVertex3fv(mdm->verts[ a].co);
-       }
-       glEnd();
+       dm->numVertData = numVerts;
+       dm->numEdgeData = numEdges;
+       dm->numFaceData = numFaces;
+
+       DM_init_funcs(dm);
+       
+       dm->needsFree = 1;
 }
-static void meshDM_drawEdges(DerivedMesh *dm)
+
+void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
+                      int numVerts, int numEdges, int numFaces)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me= mdm->me;
-       int a;
-       MFace *mface = me->mface;
+       CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH,
+                       CD_CALLOC, numVerts);
+       CustomData_copy(&source->edgeData, &dm->edgeData, CD_MASK_DERIVEDMESH,
+                       CD_CALLOC, numEdges);
+       CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH,
+                       CD_CALLOC, numFaces);
 
-       if(me->medge) {
-               MEdge *medge= me->medge;
-               
-               glBegin(GL_LINES);
-               for(a=me->totedge; a>0; a--, medge++) {
-                       if(medge->flag & ME_EDGEDRAW) {
-                               glVertex3fv(mdm->verts[ medge->v1].co);
-                               glVertex3fv(mdm->verts[ medge->v2].co);
-                       }
-               }
-               glEnd();
+       dm->numVertData = numVerts;
+       dm->numEdgeData = numEdges;
+       dm->numFaceData = numFaces;
+
+       DM_init_funcs(dm);
+
+       dm->needsFree = 1;
+}
+
+int DM_release(DerivedMesh *dm)
+{
+       if (dm->needsFree) {
+               CustomData_free(&dm->vertData, dm->numVertData);
+               CustomData_free(&dm->edgeData, dm->numEdgeData);
+               CustomData_free(&dm->faceData, dm->numFaceData);
+
+               return 1;
        }
        else {
-               glBegin(GL_LINES);
-               for(a=0; a<me->totface; a++, mface++) {
-                       int test= mface->edcode;
-                       
-                       if(test) {
-                               if(test&ME_V1V2){
-                                       glVertex3fv(mdm->verts[mface->v1].co);
-                                       glVertex3fv(mdm->verts[mface->v2].co);
-                               }
-
-                               if(mface->v3) {
-                                       if(test&ME_V2V3){
-                                               glVertex3fv(mdm->verts[mface->v2].co);
-                                               glVertex3fv(mdm->verts[mface->v3].co);
-                                       }
+               CustomData_free_temporary(&dm->vertData, dm->numVertData);
+               CustomData_free_temporary(&dm->edgeData, dm->numEdgeData);
+               CustomData_free_temporary(&dm->faceData, dm->numFaceData);
 
-                                       if (mface->v4) {
-                                               if(test&ME_V3V4){
-                                                       glVertex3fv(mdm->verts[mface->v3].co);
-                                                       glVertex3fv(mdm->verts[mface->v4].co);
-                                               }
-                                               if(test&ME_V4V1){
-                                                       glVertex3fv(mdm->verts[mface->v4].co);
-                                                       glVertex3fv(mdm->verts[mface->v1].co);
-                                               }
-                                       } else {
-                                               if(test&ME_V3V1){
-                                                       glVertex3fv(mdm->verts[mface->v3].co);
-                                                       glVertex3fv(mdm->verts[mface->v1].co);
-                                               }
-                                       }
-                               }
-                       }
-               }
-               glEnd();
+               return 0;
        }
 }
-static void meshDM_drawLooseEdges(DerivedMesh *dm)
+
+void DM_to_mesh(DerivedMesh *dm, Mesh *me)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me = mdm->me;
-       MFace *mface= me->mface;
-       int a;
+       /* dm might depend on me, so we need to do everything with a local copy */
+       Mesh tmp = *me;
+       int totvert, totedge, totface;
 
-       glBegin(GL_LINES);
-       for(a=0; a<me->totface; a++, mface++) {
-               if(!mface->v3) {
-                       glVertex3fv(mdm->verts[mface->v3].co);
-                       glVertex3fv(mdm->verts[mface->v4].co);
-               } 
+       memset(&tmp.vdata, 0, sizeof(tmp.vdata));
+       memset(&tmp.edata, 0, sizeof(tmp.edata));
+       memset(&tmp.fdata, 0, sizeof(tmp.fdata));
+
+       totvert = tmp.totvert = dm->getNumVerts(dm);
+       totedge = tmp.totedge = dm->getNumEdges(dm);
+       totface = tmp.totface = dm->getNumFaces(dm);
+
+       CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
+       CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
+       CustomData_copy(&dm->faceData, &tmp.fdata, CD_MASK_MESH, CD_DUPLICATE, totface);
+
+       /* not all DerivedMeshes store their verts/edges/faces in CustomData, so
+          we set them here in case they are missing */
+       if(!CustomData_has_layer(&tmp.vdata, CD_MVERT))
+               CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN, dm->dupVertArray(dm), totvert);
+       if(!CustomData_has_layer(&tmp.edata, CD_MEDGE))
+               CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN, dm->dupEdgeArray(dm), totedge);
+       if(!CustomData_has_layer(&tmp.fdata, CD_MFACE))
+               CustomData_add_layer(&tmp.fdata, CD_MFACE, CD_ASSIGN, dm->dupFaceArray(dm), totface);
+
+       mesh_update_customdata_pointers(&tmp);
+
+       CustomData_free(&me->vdata, me->totvert);
+       CustomData_free(&me->edata, me->totedge);
+       CustomData_free(&me->fdata, me->totface);
+
+       /* if the number of verts has changed, remove invalid data */
+       if(tmp.totvert != me->totvert) {
+               if(me->key) me->key->id.us--;
+               me->key = NULL;
        }
-       glEnd();
+
+       *me = tmp;
 }
-static void meshDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
-{
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me = mdm->me;
-       MVert *mvert= mdm->verts;
-       MFace *mface= me->mface;
-       float *nors = mdm->nors;
-       int a;
-       int glmode=-1, shademodel=-1, matnr=-1, drawCurrentMat=1;
 
-#define PASSVERT(index) {                                              \
-       if (shademodel==GL_SMOOTH) {                            \
-               short *no = mvert[index].no;                    \
-               glNormal3sv(no);                                                \
-       }                                                                                       \
-       glVertex3fv(mvert[index].co);   \
+void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask)
+{
+       CustomData_set_only_copy(&dm->vertData, mask);
+       CustomData_set_only_copy(&dm->edgeData, mask);
+       CustomData_set_only_copy(&dm->faceData, mask);
 }
 
-       glBegin(glmode=GL_QUADS);
-       for(a=0; a<me->totface; a++, mface++, nors+=3) {
-               if(mface->v3) {
-                       int new_glmode, new_matnr, new_shademodel;
-                               
-                       new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
-                       new_matnr = mface->mat_nr+1;
-                       new_shademodel = (!(me->flag&ME_AUTOSMOOTH) && (mface->flag & ME_SMOOTH))?GL_SMOOTH:GL_FLAT;
-                       
-                       if (new_glmode!=glmode || new_matnr!=matnr || new_shademodel!=shademodel) {
-                               glEnd();
+void DM_add_vert_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+{
+       CustomData_add_layer(&dm->vertData, type, alloctype, layer, dm->numVertData);
+}
 
-                               drawCurrentMat = setMaterial(matnr=new_matnr);
+void DM_add_edge_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+{
+       CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData);
+}
 
-                               glShadeModel(shademodel=new_shademodel);
-                               glBegin(glmode=new_glmode);
-                       } 
-                       
-                       if (drawCurrentMat) {
-                               if(shademodel==GL_FLAT) 
-                                       glNormal3fv(nors);
-
-                               PASSVERT(mface->v1);
-                               PASSVERT(mface->v2);
-                               PASSVERT(mface->v3);
-                               if (mface->v4) {
-                                       PASSVERT(mface->v4);
-                               }
-                       }
-               }
-       }
-       glEnd();
+void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+{
+       CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numFaceData);
+}
 
-       glShadeModel(GL_FLAT);
-#undef PASSVERT
+void *DM_get_vert_data(DerivedMesh *dm, int index, int type)
+{
+       return CustomData_get(&dm->vertData, index, type);
 }
 
-static void meshDM_drawFacesColored(DerivedMesh *dm, int useTwoSide, unsigned char *col1, unsigned char *col2)
+void *DM_get_edge_data(DerivedMesh *dm, int index, int type)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me= mdm->me;
-       MFace *mface= me->mface;
-       int a, glmode;
-       unsigned char *cp1, *cp2;
+       return CustomData_get(&dm->edgeData, index, type);
+}
 
-       cp1= col1;
-       if(col2) {
-               cp2= col2;
-       } else {
-               cp2= NULL;
-               useTwoSide= 0;
-       }
+void *DM_get_face_data(DerivedMesh *dm, int index, int type)
+{
+       return CustomData_get(&dm->faceData, index, type);
+}
 
-       /* there's a conflict here... twosided colors versus culling...? */
-       /* defined by history, only texture faces have culling option */
-       /* we need that as mesh option builtin, next to double sided lighting */
-       if(col1 && col2)
-               glEnable(GL_CULL_FACE);
-       
-       glShadeModel(GL_SMOOTH);
-       glBegin(glmode=GL_QUADS);
-       for(a=0; a<me->totface; a++, mface++, cp1+= 16) {
-               if(mface->v3) {
-                       int new_glmode= mface->v4?GL_QUADS:GL_TRIANGLES;
+void *DM_get_vert_data_layer(DerivedMesh *dm, int type)
+{
+       return CustomData_get_layer(&dm->vertData, type);
+}
 
-                       if (new_glmode!=glmode) {
-                               glEnd();
-                               glBegin(glmode= new_glmode);
-                       }
-                               
-                       glColor3ub(cp1[3], cp1[2], cp1[1]);
-                       glVertex3fv( mdm->verts[mface->v1].co );
-                       glColor3ub(cp1[7], cp1[6], cp1[5]);
-                       glVertex3fv( mdm->verts[mface->v2].co );
-                       glColor3ub(cp1[11], cp1[10], cp1[9]);
-                       glVertex3fv( mdm->verts[mface->v3].co );
-                       if(mface->v4) {
-                               glColor3ub(cp1[15], cp1[14], cp1[13]);
-                               glVertex3fv( mdm->verts[mface->v4].co );
-                       }
-                               
-                       if(useTwoSide) {
-                               glColor3ub(cp2[11], cp2[10], cp2[9]);
-                               glVertex3fv( mdm->verts[mface->v3].co );
-                               glColor3ub(cp2[7], cp2[6], cp2[5]);
-                               glVertex3fv( mdm->verts[mface->v2].co );
-                               glColor3ub(cp2[3], cp2[2], cp2[1]);
-                               glVertex3fv( mdm->verts[mface->v1].co );
-                               if(mface->v4) {
-                                       glColor3ub(cp2[15], cp2[14], cp2[13]);
-                                       glVertex3fv( mdm->verts[mface->v4].co );
-                               }
-                       }
-               }
-               if(col2) cp2+= 16;
-       }
-       glEnd();
+void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
+{
+       return CustomData_get_layer(&dm->edgeData, type);
+}
 
-       glShadeModel(GL_FLAT);
-       glDisable(GL_CULL_FACE);
+void *DM_get_face_data_layer(DerivedMesh *dm, int type)
+{
+       return CustomData_get_layer(&dm->faceData, type);
 }
 
-static void meshDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) 
+void DM_set_vert_data(DerivedMesh *dm, int index, int type, void *data)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me = mdm->me;
-       MVert *mvert= mdm->verts;
-       MFace *mface= me->mface;
-       TFace *tface = me->tface;
-       float *nors = mdm->nors;
-       int a;
+       CustomData_set(&dm->vertData, index, type, data);
+}
 
-       for (a=0; a<me->totface; a++) {
-               MFace *mf= &mface[a];
-               TFace *tf = tface?&tface[a]:NULL;
-               unsigned char *cp= NULL;
-               
-               if(mf->v3==0) continue;
-               if(tf && ((tf->flag&TF_HIDE) || (tf->mode&TF_INVISIBLE))) continue;
-
-               if (setDrawParams(tf, mf->mat_nr)) {
-                       if (tf) {
-                               cp= (unsigned char *) tf->col;
-                       } else if (me->mcol) {
-                               cp= (unsigned char *) &me->mcol[a*4];
-                       }
-               }
+void DM_set_edge_data(DerivedMesh *dm, int index, int type, void *data)
+{
+       CustomData_set(&dm->edgeData, index, type, data);
+}
 
-               if (!(mf->flag&ME_SMOOTH)) {
-                       glNormal3fv(&nors[a*3]);
-               }
+void DM_set_face_data(DerivedMesh *dm, int index, int type, void *data)
+{
+       CustomData_set(&dm->faceData, index, type, data);
+}
 
-               glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
-               if (tf) glTexCoord2fv(tf->uv[0]);
-               if (cp) glColor3ub(cp[3], cp[2], cp[1]);
-               if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
-               glVertex3fv(mvert[mf->v1].co);
-                       
-               if (tf) glTexCoord2fv(tf->uv[1]);
-               if (cp) glColor3ub(cp[7], cp[6], cp[5]);
-               if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
-               glVertex3fv(mvert[mf->v2].co);
-
-               if (tf) glTexCoord2fv(tf->uv[2]);
-               if (cp) glColor3ub(cp[11], cp[10], cp[9]);
-               if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
-               glVertex3fv(mvert[mf->v3].co);
-
-               if(mf->v4) {
-                       if (tf) glTexCoord2fv(tf->uv[3]);
-                       if (cp) glColor3ub(cp[15], cp[14], cp[13]);
-                       if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
-                       glVertex3fv(mvert[mf->v4].co);
-               }
-               glEnd();
-       }
+void DM_copy_vert_data(DerivedMesh *source, DerivedMesh *dest,
+                       int source_index, int dest_index, int count)
+{
+       CustomData_copy_data(&source->vertData, &dest->vertData,
+                            source_index, dest_index, count);
 }
-static int meshDM_getNumVerts(DerivedMesh *dm)
+
+void DM_copy_edge_data(DerivedMesh *source, DerivedMesh *dest,
+                       int source_index, int dest_index, int count)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me = mdm->me;
+       CustomData_copy_data(&source->edgeData, &dest->edgeData,
+                            source_index, dest_index, count);
+}
 
-       return me->totvert;
+void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest,
+                       int source_index, int dest_index, int count)
+{
+       CustomData_copy_data(&source->faceData, &dest->faceData,
+                            source_index, dest_index, count);
 }
-static int meshDM_getNumFaces(DerivedMesh *dm)
+
+void DM_free_vert_data(struct DerivedMesh *dm, int index, int count)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
-       Mesh *me = mdm->me;
+       CustomData_free_elem(&dm->vertData, index, count);
+}
 
-       return me->totface;
+void DM_free_edge_data(struct DerivedMesh *dm, int index, int count)
+{
+       CustomData_free_elem(&dm->edgeData, index, count);
 }
 
-static void meshDM_release(DerivedMesh *dm)
+void DM_free_face_data(struct DerivedMesh *dm, int index, int count)
 {
-       MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
+       CustomData_free_elem(&dm->faceData, index, count);
+}
 
-       if (mdm->freeNors) MEM_freeN(mdm->nors);
-       if (mdm->freeVerts) MEM_freeN(mdm->verts);
-       MEM_freeN(mdm);
+void DM_interp_vert_data(DerivedMesh *source, DerivedMesh *dest,
+                         int *src_indices, float *weights,
+                         int count, int dest_index)
+{
+       CustomData_interp(&source->vertData, &dest->vertData, src_indices,
+                         weights, NULL, count, dest_index);
 }
 
-static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
+void DM_interp_edge_data(DerivedMesh *source, DerivedMesh *dest,
+                         int *src_indices,
+                         float *weights, EdgeVertWeight *vert_weights,
+                         int count, int dest_index)
 {
-       MeshDerivedMesh *mdm = MEM_callocN(sizeof(*mdm), "mdm");
+       CustomData_interp(&source->edgeData, &dest->edgeData, src_indices,
+                         weights, (float*)vert_weights, count, dest_index);
+}
 
-       mdm->dm.getMinMax = meshDM_getMinMax;
+void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
+                         int *src_indices,
+                         float *weights, FaceVertWeight *vert_weights,
+                         int count, int dest_index)
+{
+       CustomData_interp(&source->faceData, &dest->faceData, src_indices,
+                         weights, (float*)vert_weights, count, dest_index);
+}
 
-       mdm->dm.convertToDispListMesh = meshDM_convertToDispListMesh;
-       mdm->dm.getNumVerts = meshDM_getNumVerts;
-       mdm->dm.getNumFaces = meshDM_getNumFaces;
+void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices)
+{
+       CustomData_swap(&dm->faceData, index, corner_indices);
+}
 
-       mdm->dm.getVertCos = meshDM_getVertCos;
-       mdm->dm.getVertCo = meshDM_getVertCo;
-       mdm->dm.getVertNo = meshDM_getVertNo;
+static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
+{
+       DerivedMesh *dm = CDDM_from_mesh(me, ob);
+       int i, dofluidsim;
 
-       mdm->dm.drawVerts = meshDM_drawVerts;
+       dofluidsim = ((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+                     (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
+                     (ob->fluidsimSettings->meshSurface) &&
+                     (1) && (!give_parteff(ob)) && // doesnt work together with particle systems!
+                     (me->totvert == ((Mesh *)(ob->fluidsimSettings->meshSurface))->totvert));
 
-       mdm->dm.drawEdges = meshDM_drawEdges;
-       mdm->dm.drawMappedEdges = meshDM_drawEdges;
-       mdm->dm.drawLooseEdges = meshDM_drawLooseEdges;
+       if (vertCos && !dofluidsim)
+               CDDM_apply_vert_coords(dm, vertCos);
 
-       mdm->dm.drawFacesSolid = meshDM_drawFacesSolid;
-       mdm->dm.drawFacesColored = meshDM_drawFacesColored;
-       mdm->dm.drawFacesTex = meshDM_drawFacesTex;
+       CDDM_calc_normals(dm);
 
-       mdm->dm.release = meshDM_release;
-       
-       mdm->ob = ob;
-       mdm->me = me;
-       mdm->verts = me->mvert;
-       mdm->nors = NULL;
-       mdm->freeNors = 0;
-       mdm->freeVerts = 0;
-
-       if (vertCos) {
-               int i;
+       /* apply fluidsim normals */    
+       if (dofluidsim) {
+               // use normals from readBobjgz
+               // TODO? check for modifiers!?
+               MVert *fsvert = ob->fluidsimSettings->meshSurfNormals;
+               short (*normals)[3] = MEM_mallocN(sizeof(short)*3*me->totvert, "fluidsim nor");
 
-               mdm->verts = MEM_mallocN(sizeof(*mdm->verts)*me->totvert, "deformedVerts");
                for (i=0; i<me->totvert; i++) {
-                       VECCOPY(mdm->verts[i].co, vertCos[i]);
+                       VECCOPY(normals[i], fsvert[i].no);
+                       //mv->no[0]= 30000; mv->no[1]= mv->no[2]= 0; // DEBUG fixed test normals
                }
-               mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
-               mdm->freeNors = 1;
-               mdm->freeVerts = 1;
-       } else {
-                       // XXX this is kinda hacky because we shouldn't really be editing
-                       // the mesh here, however, we can't just call mesh_build_faceNormals(ob)
-                       // because in the case when a key is applied to a mesh the vertex normals
-                       // would never be correctly computed.
-               mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
-               mdm->freeNors = 1;
+
+               CDDM_apply_vert_normals(dm, normals);
+
+               MEM_freeN(normals);
        }
 
-       return (DerivedMesh*) mdm;
+       return dm;
 }
 
 ///
@@ -504,76 +459,62 @@ typedef struct {
        float (*faceNos)[3];
 } EditMeshDerivedMesh;
 
-static void emDM_getMappedVertCoEM(DerivedMesh *dm, void *vert, float co_r[3])
+static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditVert *eve;
+       int i;
 
-       if (emdm->vertexCos) {
-               EditVert *eve;
-               int i;
-
-               for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
-                       if (eve==vert) {
-                               VECCOPY(co_r, emdm->vertexCos[i]);
-                               break;
-                       }
+       for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
+               if (emdm->vertexCos) {
+                       func(userData, i, emdm->vertexCos[i], emdm->vertexNos[i], NULL);
+               } else {
+                       func(userData, i, eve->co, eve->no, NULL);
                }
-       } else {
-               EditVert *eve = vert;
-
-               VECCOPY(co_r, eve->co);
        }
 }
-static void emDM_drawMappedVertsEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditVert *vert), void *userData)
+static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditVert *eve;
+       EditEdge *eed;
+       int i;
 
        if (emdm->vertexCos) {
-               int i;
+               EditVert *eve;
 
-               bglBegin(GL_POINTS);
-               for(i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
-                       if(!setDrawOptions || setDrawOptions(userData, eve))
-                               bglVertex3fv(emdm->vertexCos[i]);
-               }
-               bglEnd();               
+               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
+                       eve->tmp.l = (long) i++;
+               for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
+                       func(userData, i, emdm->vertexCos[(int) eed->v1->tmp.l], emdm->vertexCos[(int) eed->v2->tmp.l]);
        } else {
-               bglBegin(GL_POINTS);
-               for(eve= emdm->em->verts.first; eve; eve= eve->next) {
-                       if(!setDrawOptions || setDrawOptions(userData, eve))
-                               bglVertex3fv(eve->co);
-               }
-               bglEnd();               
+               for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
+                       func(userData, i, eed->v1->co, eed->v2->co);
        }
 }
-static void emDM_drawMappedEdgesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void *userData) 
+static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
        EditEdge *eed;
+       int i;
 
        if (emdm->vertexCos) {
-               EditVert *eve, *preveve;
-               int i;
+               EditVert *eve;
 
                for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->prev = (EditVert*) i++;
+                       eve->tmp.l = (long) i++;
 
                glBegin(GL_LINES);
-               for(eed= emdm->em->edges.first; eed; eed= eed->next) {
-                       if(!setDrawOptions || setDrawOptions(userData, eed)) {
-                               glVertex3fv(emdm->vertexCos[(int) eed->v1->prev]);
-                               glVertex3fv(emdm->vertexCos[(int) eed->v2->prev]);
+               for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
+                       if(!setDrawOptions || setDrawOptions(userData, i)) {
+                               glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]);
+                               glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]);
                        }
                }
                glEnd();
-
-               for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
-                       eve->prev = preveve;
        } else {
                glBegin(GL_LINES);
-               for(eed= emdm->em->edges.first; eed; eed= eed->next) {
-                       if(!setDrawOptions || setDrawOptions(userData, eed)) {
+               for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
+                       if(!setDrawOptions || setDrawOptions(userData, i)) {
                                glVertex3fv(eed->v1->co);
                                glVertex3fv(eed->v2->co);
                        }
@@ -581,55 +522,84 @@ static void emDM_drawMappedEdgesEM(DerivedMesh *dm, int (*setDrawOptions)(void *
                glEnd();
        }
 }
-static void emDM_drawEdges(DerivedMesh *dm)
+static void emDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
 {
-       emDM_drawMappedEdgesEM(dm, NULL, NULL);
+       emDM_drawMappedEdges(dm, NULL, NULL);
 }
-static void emDM_drawMappedEdgesInterpEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void (*setDrawInterpOptions)(void *userData, EditEdge *edge, float t), void *userData) 
+static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) 
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
        EditEdge *eed;
+       int i;
 
        if (emdm->vertexCos) {
-               EditVert *eve, *preveve;
-               int i;
+               EditVert *eve;
 
                for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->prev = (EditVert*) i++;
+                       eve->tmp.l = (long) i++;
 
                glBegin(GL_LINES);
-               for(eed= emdm->em->edges.first; eed; eed= eed->next) {
-                       if(!setDrawOptions || setDrawOptions(userData, eed)) {
-                               setDrawInterpOptions(userData, eed, 0.0);
-                               glVertex3fv(emdm->vertexCos[(int) eed->v1->prev]);
-                               setDrawInterpOptions(userData, eed, 1.0);
-                               glVertex3fv(emdm->vertexCos[(int) eed->v2->prev]);
+               for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
+                       if(!setDrawOptions || setDrawOptions(userData, i)) {
+                               setDrawInterpOptions(userData, i, 0.0);
+                               glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]);
+                               setDrawInterpOptions(userData, i, 1.0);
+                               glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]);
                        }
                }
                glEnd();
-
-               for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
-                       eve->prev = preveve;
        } else {
                glBegin(GL_LINES);
-               for(eed= emdm->em->edges.first; eed; eed= eed->next) {
-                       if(!setDrawOptions || setDrawOptions(userData, eed)) {
-                               setDrawInterpOptions(userData, eed, 0.0);
+               for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
+                       if(!setDrawOptions || setDrawOptions(userData, i)) {
+                               setDrawInterpOptions(userData, i, 0.0);
                                glVertex3fv(eed->v1->co);
-                               setDrawInterpOptions(userData, eed, 1.0);
+                               setDrawInterpOptions(userData, i, 1.0);
                                glVertex3fv(eed->v2->co);
                        }
                }
                glEnd();
        }
 }
+
+static void emDM_drawUVEdges(DerivedMesh *dm)
+{
+       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditFace *efa;
+       MTFace *tf;
+
+       glBegin(GL_LINES);
+       for(efa= emdm->em->faces.first; efa; efa= efa->next) {
+               tf = CustomData_em_get(&emdm->em->fdata, efa->data, CD_MTFACE);
+
+               if(tf && !(efa->h)) {
+                       glVertex2fv(tf->uv[0]);
+                       glVertex2fv(tf->uv[1]);
+
+                       glVertex2fv(tf->uv[1]);
+                       glVertex2fv(tf->uv[2]);
+
+                       if (!efa->v4) {
+                               glVertex2fv(tf->uv[2]);
+                               glVertex2fv(tf->uv[0]);
+                       } else {
+                               glVertex2fv(tf->uv[2]);
+                               glVertex2fv(tf->uv[3]);
+                               glVertex2fv(tf->uv[3]);
+                               glVertex2fv(tf->uv[0]);
+                       }
+               }
+       }
+       glEnd();
+}
+
 static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3])
 {
        if (vertexCos) {
-               VECCOPY(cent, vertexCos[(int) efa->v1->prev]);
-               VecAddf(cent, cent, vertexCos[(int) efa->v2->prev]);
-               VecAddf(cent, cent, vertexCos[(int) efa->v3->prev]);
-               if (efa->v4) VecAddf(cent, cent, vertexCos[(int) efa->v4->prev]);
+               VECCOPY(cent, vertexCos[(int) efa->v1->tmp.l]);
+               VecAddf(cent, cent, vertexCos[(int) efa->v2->tmp.l]);
+               VecAddf(cent, cent, vertexCos[(int) efa->v3->tmp.l]);
+               if (efa->v4) VecAddf(cent, cent, vertexCos[(int) efa->v4->tmp.l]);
        } else {
                VECCOPY(cent, efa->v1->co);
                VecAddf(cent, cent, efa->v2->co);
@@ -643,862 +613,969 @@ static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[
                VecMulf(cent, 0.33333333333f);
        }
 }
-static void emDM_drawMappedFaceCentersEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, struct EditFace *efa), void *userData)
+static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditVert *eve, *preveve;
+       EditVert *eve;
        EditFace *efa;
        float cent[3];
        int i;
 
        if (emdm->vertexCos) {
                for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->prev = (EditVert*) i++;
-       }
-
-       bglBegin(GL_POINTS);
-       for(efa= emdm->em->faces.first; efa; efa= efa->next) {
-               if(!setDrawOptions || setDrawOptions(userData, efa)) {
-                       emDM__calcFaceCent(efa, cent, emdm->vertexCos);
-                       bglVertex3fv(cent);
-               }
+                       eve->tmp.l = (long) i++;
        }
-       bglEnd();
 
-       if (emdm->vertexCos) {
-               for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
-                       eve->prev = preveve;
+       for(i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
+               emDM__calcFaceCent(efa, cent, emdm->vertexCos);
+               func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n);
        }
 }
-static void emDM_drawMappedFaceNormalsEM(DerivedMesh *dm, float length, int (*setDrawOptions)(void *userData, struct EditFace *efa), void *userData)
+static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditVert *eve, *preveve;
        EditFace *efa;
-       float cent[3];
        int i;
 
-       glBegin(GL_LINES);
        if (emdm->vertexCos) {
-               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->prev = (EditVert*) i++;
-       }
-
+               EditVert *eve;
 
-       for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
-               if(!setDrawOptions || setDrawOptions(userData, efa)) {
-                       float *no = emdm->vertexCos?emdm->faceNos[i]:efa->n;
+               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
+                       eve->tmp.l = (long) i++;
 
-                       emDM__calcFaceCent(efa, cent, emdm->vertexCos);
+               for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
+                       int drawSmooth = (efa->flag & ME_SMOOTH);
+                       if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
+                               glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
 
-                       glVertex3fv(cent);
-                       glVertex3f(     cent[0] + length*no[0],
-                                               cent[1] + length*no[1],
-                                               cent[2] + length*no[2]);
+                               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+                               if (!drawSmooth) {
+                                       glNormal3fv(emdm->faceNos[i]);
+                                       glVertex3fv(emdm->vertexCos[(int) efa->v1->tmp.l]);
+                                       glVertex3fv(emdm->vertexCos[(int) efa->v2->tmp.l]);
+                                       glVertex3fv(emdm->vertexCos[(int) efa->v3->tmp.l]);
+                                       if(efa->v4) glVertex3fv(emdm->vertexCos[(int) efa->v4->tmp.l]);
+                               } else {
+                                       glNormal3fv(emdm->vertexNos[(int) efa->v1->tmp.l]);
+                                       glVertex3fv(emdm->vertexCos[(int) efa->v1->tmp.l]);
+                                       glNormal3fv(emdm->vertexNos[(int) efa->v2->tmp.l]);
+                                       glVertex3fv(emdm->vertexCos[(int) efa->v2->tmp.l]);
+                                       glNormal3fv(emdm->vertexNos[(int) efa->v3->tmp.l]);
+                                       glVertex3fv(emdm->vertexCos[(int) efa->v3->tmp.l]);
+                                       if(efa->v4) {
+                                               glNormal3fv(emdm->vertexNos[(int) efa->v4->tmp.l]);
+                                               glVertex3fv(emdm->vertexCos[(int) efa->v4->tmp.l]);
+                                       }
+                               }
+                               glEnd();
+                       }
                }
-       }
+       } else {
+               for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
+                       int drawSmooth = (efa->flag & ME_SMOOTH);
+                       if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
+                               glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
 
-       if (emdm->vertexCos) {
-               for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
-                       eve->prev = preveve;
+                               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+                               if (!drawSmooth) {
+                                       glNormal3fv(efa->n);
+                                       glVertex3fv(efa->v1->co);
+                                       glVertex3fv(efa->v2->co);
+                                       glVertex3fv(efa->v3->co);
+                                       if(efa->v4) glVertex3fv(efa->v4->co);
+                               } else {
+                                       glNormal3fv(efa->v1->no);
+                                       glVertex3fv(efa->v1->co);
+                                       glNormal3fv(efa->v2->no);
+                                       glVertex3fv(efa->v2->co);
+                                       glNormal3fv(efa->v3->no);
+                                       glVertex3fv(efa->v3->co);
+                                       if(efa->v4) {
+                                               glNormal3fv(efa->v4->no);
+                                               glVertex3fv(efa->v4->co);
+                                       }
+                               }
+                               glEnd();
+                       }
+               }
        }
-
-       glEnd();
 }
-static void emDM_drawMappedVertNormalsEM(DerivedMesh *dm, float length, int (*setDrawOptions)(void *userData, struct EditVert *eve), void *userData)
+
+static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
        EditVert *eve;
        int i;
 
-       glBegin(GL_LINES);
-       for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
-               if(!setDrawOptions || setDrawOptions(userData, eve)) {
+       if (emdm->em->verts.first) {
+               for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
                        if (emdm->vertexCos) {
-                               glVertex3fv(emdm->vertexCos[i]);
-                               glVertex3f(     emdm->vertexCos[i][0] + length*emdm->vertexNos[i][0],
-                                                       emdm->vertexCos[i][1] + length*emdm->vertexNos[i][1],
-                                                       emdm->vertexCos[i][2] + length*emdm->vertexNos[i][2]);
+                               DO_MINMAX(emdm->vertexCos[i], min_r, max_r);
                        } else {
-                               glVertex3fv(eve->co);
-                               glVertex3f(     eve->co[0] + length*eve->no[0],
-                                                       eve->co[1] + length*eve->no[1],
-                                                       eve->co[2] + length*eve->no[2]);
+                               DO_MINMAX(eve->co, min_r, max_r);
                        }
                }
+       } else {
+               min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
        }
-       glEnd();
 }
-static void emDM_drawMappedFacesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditFace *face), void *userData)
+static int emDM_getNumVerts(DerivedMesh *dm)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditFace *efa;
 
-       if (emdm->vertexCos) {
-               EditVert *eve, *preveve;
-               int i;
+       return BLI_countlist(&emdm->em->verts);
+}
 
-               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->prev = (EditVert*) i++;
+static int emDM_getNumEdges(DerivedMesh *dm)
+{
+       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
 
-               for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
-                       if(!setDrawOptions || setDrawOptions(userData, efa)) {
-                               glNormal3fv(emdm->faceNos[i]);
-                               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
-                               glVertex3fv(emdm->vertexCos[(int) efa->v1->prev]);
-                               glVertex3fv(emdm->vertexCos[(int) efa->v2->prev]);
-                               glVertex3fv(emdm->vertexCos[(int) efa->v3->prev]);
-                               if(efa->v4) glVertex3fv(emdm->vertexCos[(int) efa->v4->prev]);
-                               glEnd();
-                       }
-               }
+       return BLI_countlist(&emdm->em->edges);
+}
 
-               for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
-                       eve->prev = preveve;
-       } else {
-               for (efa= emdm->em->faces.first; efa; efa= efa->next) {
-                       if(!setDrawOptions || setDrawOptions(userData, efa)) {
-                               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
-                               glVertex3fv(efa->v1->co);
-                               glVertex3fv(efa->v2->co);
-                               glVertex3fv(efa->v3->co);
-                               if(efa->v4) glVertex3fv(efa->v4->co);
-                               glEnd();
-                       }
-               }
-       }
-}
-static void emDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+static int emDM_getNumFaces(DerivedMesh *dm)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditFace *efa;
 
-       if (emdm->vertexCos) {
-               EditVert *eve, *preveve;
-               int i;
+       return BLI_countlist(&emdm->em->faces);
+}
 
-               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->prev = (EditVert*) i++;
+void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+{
+       EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
+       int i;
 
-               for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
-                       if(efa->h==0) {
-                               if (setMaterial(efa->mat_nr+1)) {
-                                       glNormal3fv(emdm->faceNos[i]);
-                                       glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
-                                       glVertex3fv(emdm->vertexCos[(int) efa->v1->prev]);
-                                       glVertex3fv(emdm->vertexCos[(int) efa->v2->prev]);
-                                       glVertex3fv(emdm->vertexCos[(int) efa->v3->prev]);
-                                       if(efa->v4) glVertex3fv(emdm->vertexCos[(int) efa->v4->prev]);
-                                       glEnd();
-                               }
-                       }
-               }
+       for(i = 0; i < index; ++i) ev = ev->next;
 
-               for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
-                       eve->prev = preveve;
-       } else {
-               for (efa= emdm->em->faces.first; efa; efa= efa->next) {
-                       if(efa->h==0) {
-                               if (setMaterial(efa->mat_nr+1)) {
-                                       glNormal3fv(efa->n);
-                                       glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
-                                       glVertex3fv(efa->v1->co);
-                                       glVertex3fv(efa->v2->co);
-                                       glVertex3fv(efa->v3->co);
-                                       if(efa->v4) glVertex3fv(efa->v4->co);
-                                       glEnd();
-                               }
-                       }
+       VECCOPY(vert_r->co, ev->co);
+
+       vert_r->no[0] = ev->no[0] * 32767.0;
+       vert_r->no[1] = ev->no[1] * 32767.0;
+       vert_r->no[2] = ev->no[2] * 32767.0;
+
+       /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
+       vert_r->mat_nr = 0;
+}
+
+void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
+{
+       EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
+       EditEdge *ee = em->edges.first;
+       EditVert *ev, *v1, *v2;
+       int i;
+
+       for(i = 0; i < index; ++i) ee = ee->next;
+
+       edge_r->crease = (unsigned char) (ee->crease*255.0f);
+       /* TODO what to do with edge_r->flag? */
+       edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
+       if (ee->seam) edge_r->flag |= ME_SEAM;
+       if (ee->sharp) edge_r->flag |= ME_SHARP;
+#if 0
+       /* this needs setup of f2 field */
+       if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
+#endif
+
+       /* goddamn, we have to search all verts to find indices */
+       v1 = ee->v1;
+       v2 = ee->v2;
+       for(i = 0, ev = em->verts.first; v1 || v2; i++, ev = ev->next) {
+               if(ev == v1) {
+                       edge_r->v1 = i;
+                       v1 = NULL;
+               }
+               if(ev == v2) {
+                       edge_r->v2 = i;
+                       v2 = NULL;
                }
        }
 }
 
-static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
+void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditVert *eve;
+       EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
+       EditFace *ef = em->faces.first;
+       EditVert *ev, *v1, *v2, *v3, *v4;
        int i;
 
-       if (emdm->em->verts.first) {
-               for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
-                       if (emdm->vertexCos) {
-                               DO_MINMAX(emdm->vertexCos[i], min_r, max_r);
-                       } else {
-                               DO_MINMAX(eve->co, min_r, max_r);
-                       }
+       for(i = 0; i < index; ++i) ef = ef->next;
+
+       face_r->mat_nr = ef->mat_nr;
+       face_r->flag = ef->flag;
+
+       /* goddamn, we have to search all verts to find indices */
+       v1 = ef->v1;
+       v2 = ef->v2;
+       v3 = ef->v3;
+       v4 = ef->v4;
+       if(!v4) face_r->v4 = 0;
+
+       for(i = 0, ev = em->verts.first; v1 || v2 || v3 || v4;
+           i++, ev = ev->next) {
+               if(ev == v1) {
+                       face_r->v1 = i;
+                       v1 = NULL;
+               }
+               if(ev == v2) {
+                       face_r->v2 = i;
+                       v2 = NULL;
+               }
+               if(ev == v3) {
+                       face_r->v3 = i;
+                       v3 = NULL;
+               }
+               if(ev == v4) {
+                       face_r->v4 = i;
+                       v4 = NULL;
                }
-       } else {
-               min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
        }
+
+       test_index_face(face_r, NULL, 0, ef->v4?4:3);
 }
-static int emDM_getNumVerts(DerivedMesh *dm)
+
+void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
 
-       return BLI_countlist(&emdm->em->verts);
+       for( ; ev; ev = ev->next, ++vert_r) {
+               VECCOPY(vert_r->co, ev->co);
+
+               vert_r->no[0] = ev->no[0] * 32767.0;
+               vert_r->no[1] = ev->no[1] * 32767.0;
+               vert_r->no[2] = ev->no[2] * 32767.0;
+
+               /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
+               vert_r->mat_nr = 0;
+               vert_r->flag = 0;
+       }
 }
-static int emDM_getNumFaces(DerivedMesh *dm)
+
+void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
+       EditEdge *ee = em->edges.first;
+       EditVert *ev;
+       int i;
 
-       return BLI_countlist(&emdm->em->faces);
+       /* store vertex indices in tmp union */
+       for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
+               ev->tmp.l = (long) i++;
+
+       for( ; ee; ee = ee->next, ++edge_r) {
+               edge_r->crease = (unsigned char) (ee->crease*255.0f);
+               /* TODO what to do with edge_r->flag? */
+               edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
+               if (ee->seam) edge_r->flag |= ME_SEAM;
+               if (ee->sharp) edge_r->flag |= ME_SHARP;
+#if 0
+               /* this needs setup of f2 field */
+               if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
+#endif
+
+               edge_r->v1 = (int)ee->v1->tmp.l;
+               edge_r->v2 = (int)ee->v2->tmp.l;
+       }
+}
+
+void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
+{
+       EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
+       EditFace *ef = em->faces.first;
+       EditVert *ev;
+       int i;
+
+       /* store vertexes indices in tmp union */
+       for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
+               ev->tmp.l = (long) i;
+
+       for( ; ef; ef = ef->next, ++face_r) {
+               face_r->mat_nr = ef->mat_nr;
+               face_r->flag = ef->flag;
+
+               face_r->v1 = (int)ef->v1->tmp.l;
+               face_r->v2 = (int)ef->v2->tmp.l;
+               face_r->v3 = (int)ef->v3->tmp.l;
+               if(ef->v4) face_r->v4 = (int)ef->v4->tmp.l;
+               else face_r->v4 = 0;
+
+               test_index_face(face_r, NULL, 0, ef->v4?4:3);
+       }
 }
 
 static void emDM_release(DerivedMesh *dm)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
 
-       if (emdm->vertexCos) {
-               MEM_freeN(emdm->vertexCos);
-               MEM_freeN(emdm->vertexNos);
-               MEM_freeN(emdm->faceNos);
-       }
+       if (DM_release(dm)) {
+               if (emdm->vertexCos) {
+                       MEM_freeN(emdm->vertexCos);
+                       MEM_freeN(emdm->vertexNos);
+                       MEM_freeN(emdm->faceNos);
+               }
 
-       MEM_freeN(emdm);
+               MEM_freeN(emdm);
+       }
 }
 
-static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, float (*vertexCos)[3])
+static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
+                                           float (*vertexCos)[3])
 {
        EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
 
+       DM_init(&emdm->dm, BLI_countlist(&em->verts),
+                        BLI_countlist(&em->edges), BLI_countlist(&em->faces));
+
        emdm->dm.getMinMax = emDM_getMinMax;
 
        emdm->dm.getNumVerts = emDM_getNumVerts;
+       emdm->dm.getNumEdges = emDM_getNumEdges;
        emdm->dm.getNumFaces = emDM_getNumFaces;
-       emdm->dm.getMappedVertCoEM = emDM_getMappedVertCoEM;
 
-       emdm->dm.drawMappedVertsEM = emDM_drawMappedVertsEM;
+       emdm->dm.getVert = emDM_getVert;
+       emdm->dm.getEdge = emDM_getEdge;
+       emdm->dm.getFace = emDM_getFace;
+       emdm->dm.copyVertArray = emDM_copyVertArray;
+       emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
+       emdm->dm.copyFaceArray = emDM_copyFaceArray;
 
-       emdm->dm.drawEdges = emDM_drawEdges;
-       emdm->dm.drawMappedEdgesEM = emDM_drawMappedEdgesEM;
-       emdm->dm.drawMappedEdgesInterpEM = emDM_drawMappedEdgesInterpEM;
-       
-       emdm->dm.drawMappedVertNormalsEM = emDM_drawMappedVertNormalsEM;
-       emdm->dm.drawMappedFaceNormalsEM = emDM_drawMappedFaceNormalsEM;
-       emdm->dm.drawMappedFaceCentersEM = emDM_drawMappedFaceCentersEM;
+       emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
+       emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
+       emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
 
-       emdm->dm.drawFacesSolid = emDM_drawFacesSolid;
-       emdm->dm.drawMappedFacesEM = emDM_drawMappedFacesEM;
+       emdm->dm.drawEdges = emDM_drawEdges;
+       emdm->dm.drawMappedEdges = emDM_drawMappedEdges;
+       emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
+       emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
+       emdm->dm.drawUVEdges = emDM_drawUVEdges;
 
        emdm->dm.release = emDM_release;
        
        emdm->em = em;
        emdm->vertexCos = vertexCos;
 
-       if (vertexCos) {
-               EditVert *eve, *preveve;
+       if(CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
+               EditVert *eve;
+               int i;
+
+               DM_add_vert_layer(&emdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
+
+               for(eve = em->verts.first, i = 0; eve; eve = eve->next, ++i)
+                       DM_set_vert_data(&emdm->dm, i, CD_MDEFORMVERT,
+                                        CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT));
+       }
+
+       if(vertexCos) {
+               EditVert *eve;
                EditFace *efa;
                int totface = BLI_countlist(&em->faces);
                int i;
 
                for (i=0,eve=em->verts.first; eve; eve= eve->next)
-                       eve->prev = (EditVert*) i++;
+                       eve->tmp.l = (long) i++;
 
                emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno");
                emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno");
 
                for(i=0, efa= em->faces.first; efa; i++, efa=efa->next) {
-                       float *v1 = vertexCos[(int) efa->v1->prev];
-                       float *v2 = vertexCos[(int) efa->v2->prev];
-                       float *v3 = vertexCos[(int) efa->v3->prev];
+                       float *v1 = vertexCos[(int) efa->v1->tmp.l];
+                       float *v2 = vertexCos[(int) efa->v2->tmp.l];
+                       float *v3 = vertexCos[(int) efa->v3->tmp.l];
                        float *no = emdm->faceNos[i];
                        
                        if(efa->v4) {
-                               float *v4 = vertexCos[(int) efa->v3->prev];
+                               float *v4 = vertexCos[(int) efa->v3->tmp.l];
 
                                CalcNormFloat4(v1, v2, v3, v4, no);
-                               VecAddf(emdm->vertexNos[(int) efa->v4->prev], emdm->vertexNos[(int) efa->v4->prev], no);
+                               VecAddf(emdm->vertexNos[(int) efa->v4->tmp.l], emdm->vertexNos[(int) efa->v4->tmp.l], no);
                        }
                        else {
                                CalcNormFloat(v1, v2, v3, no);
                        }
 
-                       VecAddf(emdm->vertexNos[(int) efa->v1->prev], emdm->vertexNos[(int) efa->v1->prev], no);
-                       VecAddf(emdm->vertexNos[(int) efa->v2->prev], emdm->vertexNos[(int) efa->v2->prev], no);
-                       VecAddf(emdm->vertexNos[(int) efa->v3->prev], emdm->vertexNos[(int) efa->v3->prev], no);
+                       VecAddf(emdm->vertexNos[(int) efa->v1->tmp.l], emdm->vertexNos[(int) efa->v1->tmp.l], no);
+                       VecAddf(emdm->vertexNos[(int) efa->v2->tmp.l], emdm->vertexNos[(int) efa->v2->tmp.l], no);
+                       VecAddf(emdm->vertexNos[(int) efa->v3->tmp.l], emdm->vertexNos[(int) efa->v3->tmp.l], no);
                }
 
                for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
                        float *no = emdm->vertexNos[i];
-
-                       if (Normalise(no)==0.0) {
+                       /* following Mesh convention; we use vertex coordinate itself
+                        * for normal in this case */
+                       if (Normalize(no)==0.0) {
                                VECCOPY(no, vertexCos[i]);
-                               Normalise(no);
+                               Normalize(no);
                        }
                }
-
-               for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
-                       eve->prev = preveve;
        }
 
        return (DerivedMesh*) emdm;
 }
 
-///
+#ifdef WITH_VERSE
 
+/* verse derived mesh */
 typedef struct {
-       DerivedMesh dm;
-
-       DispListMesh *dlm;
-
-       EditVert **vertMap;
-       EditEdge **edgeMap;
-       EditFace **faceMap;
-} SSDerivedMesh;
+       struct DerivedMesh dm;
+       struct VNode *vnode;
+       struct VLayer *vertex_layer;
+       struct VLayer *polygon_layer;
+       struct ListBase *edges;
+       float (*vertexCos)[3];
+} VDerivedMesh;
 
-static void ssDM_getMappedVertCoEM(DerivedMesh *dm, void *vert, float co_r[3])
+/* this function set up border points of verse mesh bounding box */
+static void vDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert;
 
-       if (ssdm->vertMap) {
-               int i;
+       if(!vdm->vertex_layer) return;
 
-               for (i=0; i<dlm->totvert; i++) {
-                       if (ssdm->vertMap[i]==vert) {
-                               VECCOPY(co_r, dlm->mvert[i].co);
-                               break;
-                       }
+       vvert = (VerseVert*)vdm->vertex_layer->dl.lb.first;
+
+       if(vdm->vertex_layer->dl.da.count > 0) {
+               while(vvert) {
+                       DO_MINMAX(vdm->vertexCos ? vvert->cos : vvert->co, min_r, max_r);
+                       vvert = vvert->next;
                }
        }
+       else {
+               min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
+       }
 }
-static void ssDM_drawMappedVertsEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditVert *vert), void *userData)
-{
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
 
-       if (ssdm->vertMap) {
-               int i;
+/* this function return number of vertexes in vertex layer */
+static int vDM_getNumVerts(DerivedMesh *dm)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
 
-               bglBegin(GL_POINTS);
-               for (i=0; i<dlm->totvert; i++) {
-                       if(ssdm->vertMap[i] && (!setDrawOptions || setDrawOptions(userData, ssdm->vertMap[i]))) {
-                               bglVertex3fv(dlm->mvert[i].co);
-                       }
-               }
-               bglEnd();
-       }
+       if(!vdm->vertex_layer) return 0;
+       else return vdm->vertex_layer->dl.da.count;
 }
-static void ssDM_drawMappedEdgesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void *userData) 
+
+/* this function return number of 'fake' edges */
+static int vDM_getNumEdges(DerivedMesh *dm)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
-       int i;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
 
-       if (ssdm->edgeMap) {
-               glBegin(GL_LINES);
-               for(i=0; i<dlm->totedge; i++) {
-                       if(ssdm->edgeMap[i] && (!setDrawOptions || setDrawOptions(userData, ssdm->edgeMap[i]))) {
-                               MEdge *med = &dlm->medge[i];
+       return BLI_countlist(vdm->edges);
+}
 
-                               glVertex3fv(dlm->mvert[med->v1].co);
-                               glVertex3fv(dlm->mvert[med->v2].co);
-                       }
-               }
-               glEnd();
-       }
+/* this function returns number of polygons in polygon layer */
+static int vDM_getNumFaces(DerivedMesh *dm)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+
+       if(!vdm->polygon_layer) return 0;
+       else return vdm->polygon_layer->dl.da.count;
 }
 
-static void ssDM_drawMappedFaceCentersEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, struct EditFace *efa), void *userData)
+/* this function doesn't return vertex with index of access array,
+ * but it return 'indexth' vertex of dynamic list */
+void vDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert;
        int i;
 
-       if (ssdm->faceMap) {
-               bglBegin(GL_POINTS);
-               for (i=0; i<dlm->totface; i++) {
-                       if(ssdm->faceMap[i] && (!setDrawOptions || setDrawOptions(userData, ssdm->faceMap[i]))) {
-                               MFace *mf = &dlm->mface[i];
+       if(!vdm->vertex_layer) return;
 
-                               if (mf->v3) {
-                                       float cent[3];
+       for(vvert = vdm->vertex_layer->dl.lb.first, i=0 ; i<index; i++) vvert = vvert->next;
 
-                                       VECCOPY(cent, dlm->mvert[mf->v1].co);
-                                       VecAddf(cent, cent, dlm->mvert[mf->v2].co);
-                                       VecAddf(cent, cent, dlm->mvert[mf->v3].co);
+       if(vvert) {
+               VECCOPY(vert_r->co, vvert->co);
 
-                                       if (mf->v4) {
-                                               VecAddf(cent, cent, dlm->mvert[mf->v4].co);
-                                               VecMulf(cent, 0.25f);
-                                       } else {
-                                               VecMulf(cent, 0.33333333333f);
-                                       }
+               vert_r->no[0] = vvert->no[0] * 32767.0;
+               vert_r->no[1] = vvert->no[1] * 32767.0;
+               vert_r->no[2] = vvert->no[2] * 32767.0;
 
-                                       bglVertex3fv(cent);
-                               }
-                       }
-               }
-               bglEnd();
+               /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
+               vert_r->mat_nr = 0;
+               vert_r->flag = 0;
        }
 }
-static void ssDM_drawMappedFaceNormalsEM(DerivedMesh *dm, float length, int (*setDrawOptions)(void *userData, struct EditFace *efa), void *userData)
+
+/* this function returns fake verse edge */
+void vDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
-       int i;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseEdge *vedge;
+       struct VLayer *vert_vlayer = vdm->vertex_layer;
+       struct VerseVert *vvert;
+       int j;
 
-       if (ssdm->faceMap) {
-               glBegin(GL_LINES);
-               for (i=0; i<dlm->totface; i++) {
-                       if(ssdm->faceMap[i] && (!setDrawOptions || setDrawOptions(userData, ssdm->faceMap[i]))) {
-                               MFace *mf = &dlm->mface[i];
-
-                               if (mf->v3) {
-                                       float cent[3];
-                                       float no[3];
-
-                                       VECCOPY(cent, dlm->mvert[mf->v1].co);
-                                       VecAddf(cent, cent, dlm->mvert[mf->v2].co);
-                                       VecAddf(cent, cent, dlm->mvert[mf->v3].co);
-
-                                       if (mf->v4) {
-                                               CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, no);
-                                               VecAddf(cent, cent, dlm->mvert[mf->v4].co);
-                                               VecMulf(cent, 0.25f);
-                                       } else {
-                                               CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, no);
-                                               VecMulf(cent, 0.33333333333f);
-                                       }
+       if(!vdm->vertex_layer || !vdm->edges) return;
+
+       if(vdm->edges->first) {
+               struct VerseVert *vvert1, *vvert2;
 
-                                       glVertex3fv(cent);
-                                       glVertex3f(     cent[0] + length*no[0],
-                                                               cent[1] + length*no[1],
-                                                               cent[2] + length*no[2]);
+               /* store vert indices in tmp union */
+               for(vvert = vdm->vertex_layer->dl.lb.first, j = 0; vvert; vvert = vvert->next, j++)
+                       vvert->tmp.index = j;
+
+               for(vedge = vdm->edges->first; vedge; vedge = vedge->next) {
+                       if(vedge->tmp.index==index) {
+                               vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v0);
+                               vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v1);
+                               
+                               if(vvert1 && vvert2) {
+                                       edge_r->v1 = vvert1->tmp.index;
+                                       edge_r->v2 = vvert2->tmp.index;
                                }
+                               else {
+                                       edge_r->v1 = 0;
+                                       edge_r->v2 = 0;
+                               }
+                               /* not supported yet */
+                               edge_r->flag = 0;
+                               edge_r->crease = 0;
+                               break;
                        }
                }
-               glEnd();
        }
 }
-static void ssDM_drawMappedVertNormalsEM(DerivedMesh *dm, float length, int (*setDrawOptions)(void *userData, struct EditVert *eve), void *userData)
-{
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
-       int i;
 
-       if (ssdm->vertMap) {
-               glBegin(GL_LINES);
-               for (i=0; i<dlm->totvert; i++) {
-                       if(ssdm->vertMap[i] && (!setDrawOptions || setDrawOptions(userData, ssdm->vertMap[i]))) {
-                               float *co = dlm->mvert[i].co;
-                               short *no = dlm->mvert[i].no;
-
-                               glVertex3fv(co);
-                               glVertex3f(     co[0] + length*no[0]/32767.0,
-                                                       co[1] + length*no[1]/32767.0,
-                                                       co[2] + length*no[2]/32767.0);
-                       }
-               }
-               glEnd();
-       }
-}
-static void ssDM_drawMappedFacesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditFace *face), void *userData)
+/* this function doesn't return face with index of access array,
+ * but it returns 'indexth' vertex of dynamic list */
+void vDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseFace *vface;
+       struct VerseVert *vvert;
+       struct VerseVert *vvert0, *vvert1, *vvert2, *vvert3;
        int i;
 
-       if (ssdm->faceMap) {            
-               for (i=0; i<dlm->totface; i++) {
-                       if(ssdm->faceMap[i] && (!setDrawOptions || setDrawOptions(userData, ssdm->faceMap[i]))) {
-                               MFace *mf = &dlm->mface[i];
-
-                               if (mf->v3) {
-                                       glBegin(mf->v3?GL_QUADS:GL_TRIANGLES);
-                                       glVertex3fv(dlm->mvert[mf->v1].co);
-                                       glVertex3fv(dlm->mvert[mf->v2].co);
-                                       glVertex3fv(dlm->mvert[mf->v3].co);
-                                       if(mf->v4) glVertex3fv(dlm->mvert[mf->v4].co);
-                                       glEnd();
-                               }
-                       }
-               }
-       }
-}
+       if(!vdm->vertex_layer || !vdm->polygon_layer) return;
 
-static void ssDM_drawMappedEdges(DerivedMesh *dm)
-{
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
-       MEdge *medge= dlm->medge;
-       MVert *mvert= dlm->mvert;
-       int a;
-       
-       glBegin(GL_LINES);
-       for (a=0; a<dlm->totedge; a++, medge++) {
-               if (medge->flag&ME_EDGEDRAW) {
-                       glVertex3fv(mvert[medge->v1].co); 
-                       glVertex3fv(mvert[medge->v2].co);
+       for(vface = vdm->polygon_layer->dl.lb.first, i = 0; i < index; ++i) vface = vface->next;
+
+       face_r->mat_nr = 0;
+       face_r->flag = 0;
+
+       /* goddamn, we have to search all verts to find indices */
+       vvert0 = vface->vvert0;
+       vvert1 = vface->vvert1;
+       vvert2 = vface->vvert2;
+       vvert3 = vface->vvert3;
+       if(!vvert3) face_r->v4 = 0;
+
+       for(vvert = vdm->vertex_layer->dl.lb.first, i = 0; vvert0 || vvert1 || vvert2 || vvert3; i++, vvert = vvert->next) {
+               if(vvert == vvert0) {
+                       face_r->v1 = i;
+                       vvert0 = NULL;
+               }
+               if(vvert == vvert1) {
+                       face_r->v2 = i;
+                       vvert1 = NULL;
+               }
+               if(vvert == vvert2) {
+                       face_r->v3 = i;
+                       vvert2 = NULL;
+               }
+               if(vvert == vvert3) {
+                       face_r->v4 = i;
+                       vvert3 = NULL;
                }
        }
-       glEnd();
-}
 
-static void ssDM_drawLooseEdges(DerivedMesh *dm)
-{
-       /* Can't implement currently */ 
+       test_index_face(face_r, NULL, 0, vface->vvert3?4:3);
 }
 
-static void ssDM_drawVerts(DerivedMesh *dm)
+/* fill array of mvert */
+void vDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
-       MVert *mvert= dlm->mvert;
-       int i;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert;
 
-       bglBegin(GL_POINTS);
-       for (i=0; i<dlm->totvert; i++) {
-               bglVertex3fv(mvert[i].co);
+       if(!vdm->vertex_layer) return;
+
+       for(vvert = vdm->vertex_layer->dl.lb.first ; vvert; vvert = vvert->next, ++vert_r) {
+               VECCOPY(vert_r->co, vvert->co);
+
+               vert_r->no[0] = vvert->no[0] * 32767.0;
+               vert_r->no[1] = vvert->no[1] * 32767.0;
+               vert_r->no[2] = vvert->no[2] * 32767.0;
+
+               vert_r->mat_nr = 0;
+               vert_r->flag = 0;
        }
-       bglEnd();
 }
-static void ssDM_drawEdges(DerivedMesh *dm) 
-{
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
-       MVert *mvert= dlm->mvert;
-       int i;
 
-       if (dlm->medge) {
-               MEdge *medge= dlm->medge;
-       
-               glBegin(GL_LINES);
-               for (i=0; i<dlm->totedge; i++, medge++) {
-                       glVertex3fv(mvert[medge->v1].co); 
-                       glVertex3fv(mvert[medge->v2].co);
-               }
-               glEnd();
-       } else {
-               MFace *mface= dlm->mface;
+/* dummy function, edges arent supported in verse mesh */
+void vDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
 
-               glBegin(GL_LINES);
-               for (i=0; i<dlm->totface; i++, mface++) {
-                       glVertex3fv(mvert[mface->v1].co);
-                       glVertex3fv(mvert[mface->v2].co);
+       if(!vdm->vertex_layer || !vdm->edges) return;
 
-                       if (mface->v3) {
-                               glVertex3fv(mvert[mface->v2].co);
-                               glVertex3fv(mvert[mface->v3].co);
+       if(vdm->edges->first) {
+               struct VerseEdge *vedge;
+               struct VLayer *vert_vlayer = vdm->vertex_layer;
+               struct VerseVert *vvert, *vvert1, *vvert2;
+               int j;
 
-                               glVertex3fv(mvert[mface->v3].co);
-                               if (mface->v4) {
-                                       glVertex3fv(mvert[mface->v4].co);
+               /* store vert indices in tmp union */
+               for(vvert = vdm->vertex_layer->dl.lb.first, j = 0; vvert; vvert = vvert->next, ++j)
+                       vvert->tmp.index = j;
 
-                                       glVertex3fv(mvert[mface->v4].co);
-                               }
-                               glVertex3fv(mvert[mface->v1].co);
+               for(vedge = vdm->edges->first, j=0 ; vedge; vedge = vedge->next, ++edge_r, j++) {
+                       /* create temporary edge index */
+                       vedge->tmp.index = j;
+                       vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v0);
+                       vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v1);
+                       if(vvert1 && vvert2) {
+                               edge_r->v1 = vvert1->tmp.index;
+                               edge_r->v2 = vvert2->tmp.index;
                        }
+                       else {
+                               printf("error: vDM_copyEdgeArray: %d, %d\n", vedge->v0, vedge->v1);
+                               edge_r->v1 = 0;
+                               edge_r->v2 = 0;
+                       }
+                       /* not supported yet */
+                       edge_r->flag = 0;
+                       edge_r->crease = 0;
                }
-               glEnd();
        }
 }
-static void ssDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+
+/* fill array of mfaces */
+void vDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
-       float *nors = dlm->nors;
-       int glmode=-1, shademodel=-1, matnr=-1, drawCurrentMat=1;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseFace *vface;
+       struct VerseVert *vvert;
        int i;
+       
+       if(!vdm->vertex_layer || !vdm->polygon_layer) return;
+       
+       /* store vertexes indices in tmp union */
+       for(vvert = vdm->vertex_layer->dl.lb.first, i = 0; vvert; vvert = vvert->next, ++i)
+               vvert->tmp.index = i;
 
-#define PASSVERT(ind) {                                                \
-       if (shademodel==GL_SMOOTH)                              \
-               glNormal3sv(dlm->mvert[(ind)].no);      \
-       glVertex3fv(dlm->mvert[(ind)].co);              \
-}
-
-       glBegin(glmode=GL_QUADS);
-       for (i=0; i<dlm->totface; i++) {
-               MFace *mf= &dlm->mface[i];
-               
-               if (mf->v3) {
-                       int new_glmode = mf->v4?GL_QUADS:GL_TRIANGLES;
-                       int new_shademodel = (mf->flag&ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
-                       int new_matnr = mf->mat_nr+1;
-                       
-                       if(new_glmode!=glmode || new_shademodel!=shademodel || new_matnr!=matnr) {
-                               glEnd();
+       for(vface = vdm->polygon_layer->dl.lb.first; vface; vface = vface->next, ++face_r) {
+               face_r->mat_nr = 0;
+               face_r->flag = 0;
 
-                               drawCurrentMat = setMaterial(matnr=new_matnr);
+               face_r->v1 = vface->vvert0->tmp.index;
+               face_r->v2 = vface->vvert1->tmp.index;
+               face_r->v3 = vface->vvert2->tmp.index;
+               if(vface->vvert3) face_r->v4 = vface->vvert3->tmp.index;
+               else face_r->v4 = 0;
 
-                               glShadeModel(shademodel=new_shademodel);
-                               glBegin(glmode=new_glmode);
-                       }
-                       
-                       if (drawCurrentMat) {
-                               if (shademodel==GL_FLAT)
-                                       glNormal3fv(&nors[i*3]);
-                                       
-                               PASSVERT(mf->v1);
-                               PASSVERT(mf->v2);
-                               PASSVERT(mf->v3);
-                               if (mf->v4)
-                                       PASSVERT(mf->v4);
-                       }
-               }
+               test_index_face(face_r, NULL, 0, vface->vvert3?4:3);
        }
-       glEnd();
-       
-#undef PASSVERT
 }
-static void ssDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *vcols1, unsigned char *vcols2)
+
+/* return coordination of vertex with index */
+static void vDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
-       int i, lmode;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert = NULL;
+
+       if(!vdm->vertex_layer) return;
+
+       vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index);
        
-       glShadeModel(GL_SMOOTH);
-       if (vcols2) {
-               glEnable(GL_CULL_FACE);
-       else {
-               useTwoSided = 0;
+       if(vvert) {
+               VECCOPY(co_r, vdm->vertexCos ? vvert->cos : vvert->co);
+       }
+       else {
+               co_r[0] = co_r[1] = co_r[2] = 0.0;
        }
-               
-#define PASSVERT(vidx, fidx) {                                 \
-       unsigned char *col= &colbase[fidx*4];           \
-       glColor3ub(col[3], col[2], col[1]);                     \
-       glVertex3fv(dlm->mvert[(vidx)].co);                     \
 }
 
-       glBegin(lmode= GL_QUADS);
-       for (i=0; i<dlm->totface; i++) {
-               MFace *mf= &dlm->mface[i];
-               
-               if (mf->v3) {
-                       int nmode= mf->v4?GL_QUADS:GL_TRIANGLES;
-                       unsigned char *colbase= &vcols1[i*16];
-                       
-                       if (nmode!=lmode) {
-                               glEnd();
-                               glBegin(lmode= nmode);
-                       }
-                       
-                       PASSVERT(mf->v1, 0);
-                       PASSVERT(mf->v2, 1);
-                       PASSVERT(mf->v3, 2);
-                       if (mf->v4)
-                               PASSVERT(mf->v4, 3);
-                       
-                       if (useTwoSided) {
-                               unsigned char *colbase= &vcols2[i*16];
-
-                               if (mf->v4)
-                                       PASSVERT(mf->v4, 3);
-                               PASSVERT(mf->v3, 2);
-                               PASSVERT(mf->v2, 1);
-                               PASSVERT(mf->v1, 0);
-                       }
-               }
-       }
-       glEnd();
+/* return array of vertex coordiantions */
+static void vDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert;
+       int i = 0;
 
-       if (vcols2)
-               glDisable(GL_CULL_FACE);
-       
-#undef PASSVERT
+       if(!vdm->vertex_layer) return;
+
+       vvert = vdm->vertex_layer->dl.lb.first;
+       while(vvert) {
+               VECCOPY(cos_r[i], vdm->vertexCos ? vvert->cos : vvert->co);
+               i++;
+               vvert = vvert->next;
+       }
 }
-static void ssDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) 
+
+/* return normal of vertex with index */
+static void vDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       DispListMesh *dlm = ssdm->dlm;
-       MVert *mvert= dlm->mvert;
-       MFace *mface= dlm->mface;
-       TFace *tface = dlm->tface;
-       float *nors = dlm->nors;
-       int a;
-       
-       for (a=0; a<dlm->totface; a++) {
-               MFace *mf= &mface[a];
-               TFace *tf = tface?&tface[a]:NULL;
-               unsigned char *cp= NULL;
-               
-               if(mf->v3==0) continue;
-               if(tf && ((tf->flag&TF_HIDE) || (tf->mode&TF_INVISIBLE))) continue;
-
-               if (setDrawParams(tf, mf->mat_nr)) {
-                       if (tf) {
-                               cp= (unsigned char*) tf->col;
-                       } else if (dlm->mcol) {
-                               cp= (unsigned char*) &dlm->mcol[a*4];
-                       }
-               }
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert = NULL;
 
-               if (!(mf->flag&ME_SMOOTH)) {
-                       glNormal3fv(&nors[a*3]);
-               }
+       if(!vdm->vertex_layer) return;
 
-               glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
-               if (tf) glTexCoord2fv(tf->uv[0]);
-               if (cp) glColor3ub(cp[3], cp[2], cp[1]);
-               if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
-               glVertex3fv((mvert+mf->v1)->co);
-                       
-               if (tf) glTexCoord2fv(tf->uv[1]);
-               if (cp) glColor3ub(cp[7], cp[6], cp[5]);
-               if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
-               glVertex3fv((mvert+mf->v2)->co);
-
-               if (tf) glTexCoord2fv(tf->uv[2]);
-               if (cp) glColor3ub(cp[11], cp[10], cp[9]);
-               if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
-               glVertex3fv((mvert+mf->v3)->co);
-
-               if(mf->v4) {
-                       if (tf) glTexCoord2fv(tf->uv[3]);
-                       if (cp) glColor3ub(cp[15], cp[14], cp[13]);
-                       if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
-                       glVertex3fv((mvert+mf->v4)->co);
-               }
-               glEnd();
+       vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index);
+       if(vvert) {
+               VECCOPY(no_r, vvert->no);
+       }
+       else {
+               no_r[0] = no_r[1] = no_r[2] = 0.0;
        }
 }
 
-static void ssDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
+/* draw all VerseVertexes */
+static void vDM_drawVerts(DerivedMesh *dm)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       int i;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseVert *vvert;
 
-       if (ssdm->dlm->totvert) {
-               for (i=0; i<ssdm->dlm->totvert; i++) {
-                       DO_MINMAX(ssdm->dlm->mvert[i].co, min_r, max_r);
-               }
-       } else {
-               min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
+       if(!vdm->vertex_layer) return;
+
+       vvert = vdm->vertex_layer->dl.lb.first;
+
+       bglBegin(GL_POINTS);
+       while(vvert) {
+               bglVertex3fv(vdm->vertexCos ? vvert->cos : vvert->co);
+               vvert = vvert->next;
        }
+       bglEnd();
 }
 
-static void ssDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
+/* draw all edges of VerseFaces ... it isn't optimal, because verse
+ * specification doesn't support edges :-( ... bother eskil ;-)
+ * ... some edges (most of edges) are drawn twice */
+static void vDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
-       int i;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseEdge *vedge;
+       struct VLayer *vert_vlayer = vdm->vertex_layer;
+
+       if(vert_vlayer && vdm->edges && (BLI_countlist(vdm->edges) > 0)) {
+               struct VerseVert *vvert1, *vvert2;
 
-       for (i=0; i<ssdm->dlm->totvert; i++) {
-               cos_r[i][0] = ssdm->dlm->mvert[i].co[0];
-               cos_r[i][1] = ssdm->dlm->mvert[i].co[1];
-               cos_r[i][2] = ssdm->dlm->mvert[i].co[2];
+               glBegin(GL_LINES);
+               for(vedge = vdm->edges->first; vedge; vedge = vedge->next) {
+                       vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v0);
+                       vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v1);
+                       if(vvert1 && vvert2) {
+                               glVertex3fv(vdm->vertexCos ? vvert1->cos : vvert1->co);
+                               glVertex3fv(vdm->vertexCos ? vvert2->cos : vvert2->co);
+                       }
+               }
+               glEnd();
        }
 }
 
-static int ssDM_getNumVerts(DerivedMesh *dm)
+/* verse spec doesn't support edges ... loose edges can't exist */
+void vDM_drawLooseEdges(DerivedMesh *dm)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
+}
 
-       return ssdm->dlm->totvert;
+/* draw uv edges, not supported yet */
+static void vDM_drawUVEdges(DerivedMesh *dm)
+{
 }
-static int ssDM_getNumFaces(DerivedMesh *dm)
+
+/* draw all VerseFaces */
+static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseFace *vface;
+
+       if(!vdm->polygon_layer) return;
 
-       return ssdm->dlm->totface;
+       vface = vdm->polygon_layer->dl.lb.first;
+
+       glShadeModel(GL_FLAT);
+       while(vface) {
+               glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
+               glNormal3fv(vface->no);
+               glVertex3fv(vdm->vertexCos ? vface->vvert0->cos : vface->vvert0->co);
+               glVertex3fv(vdm->vertexCos ? vface->vvert1->cos : vface->vvert1->co);
+               glVertex3fv(vdm->vertexCos ? vface->vvert2->cos : vface->vvert2->co);
+               if(vface->vvert3)
+                       glVertex3fv(vdm->vertexCos ? vface->vvert3->cos : vface->vvert3->co);
+               glEnd();
+               vface = vface->next;
+       }
 }
 
-static DispListMesh *ssDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
+/* this function should draw mesh with mapped texture, but it isn't supported yet */
+static void vDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseFace *vface;
 
-       if (allowShared) {
-               return displistmesh_copyShared(ssdm->dlm);
-       } else {
-               return displistmesh_copy(ssdm->dlm);
+       if(!vdm->polygon_layer) return;
+
+       vface = vdm->polygon_layer->dl.lb.first;
+
+       while(vface) {
+               glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
+               glVertex3fv(vdm->vertexCos ? vface->vvert0->cos : vface->vvert0->co);
+               glVertex3fv(vdm->vertexCos ? vface->vvert1->cos : vface->vvert1->co);
+               glVertex3fv(vdm->vertexCos ? vface->vvert2->cos : vface->vvert2->co);
+               if(vface->vvert3)
+                       glVertex3fv(vdm->vertexCos ? vface->vvert3->cos : vface->vvert3->co);
+               glEnd();
+
+               vface = vface->next;
        }
 }
 
-static DispListMesh *ssDM_convertToDispListMeshMapped(DerivedMesh *dm, int allowShared, EditVert ***vertMap_r, EditEdge ***edgeMap_r, EditFace ***faceMap_r)
+/* this function should draw mesh with colored faces (weight paint, vertex
+ * colors, etc.), but it isn't supported yet */
+static void vDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       struct VerseFace *vface;
 
-               // We should never get here if the appropriate ssdm fields weren't given.
+       if(!vdm->polygon_layer) return;
 
-       *vertMap_r = MEM_dupallocN(ssdm->vertMap);
-       *edgeMap_r = MEM_dupallocN(ssdm->edgeMap);
-       *faceMap_r = MEM_dupallocN(ssdm->faceMap);
+       vface = vdm->polygon_layer->dl.lb.first;
 
-       if (allowShared) {
-               return displistmesh_copyShared(ssdm->dlm);
-       } else {
-               return displistmesh_copy(ssdm->dlm);
+       while(vface) {
+               glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
+               glVertex3fv(vdm->vertexCos ? vface->vvert0->cos : vface->vvert0->co);
+               glVertex3fv(vdm->vertexCos ? vface->vvert1->cos : vface->vvert1->co);
+               glVertex3fv(vdm->vertexCos ? vface->vvert2->cos : vface->vvert2->co);
+               if(vface->vvert3)
+                       glVertex3fv(vdm->vertexCos ? vface->vvert3->cos : vface->vvert3->co);
+               glEnd();
+
+               vface = vface->next;
        }
 }
 
-static void ssDM_release(DerivedMesh *dm)
+/**/
+static void vDM_foreachMappedVert(
+               DerivedMesh *dm,
+               void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
+               void *userData)
 {
-       SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
+}
 
-       displistmesh_free(ssdm->dlm);
-       if (ssdm->vertMap) {
-               MEM_freeN(ssdm->vertMap);
-               MEM_freeN(ssdm->edgeMap);
-               MEM_freeN(ssdm->faceMap);
-       }
+/**/
+static void vDM_foreachMappedEdge(
+               DerivedMesh *dm,
+               void (*func)(void *userData, int index, float *v0co, float *v1co),
+               void *userData)
+{
+}
 
-       MEM_freeN(dm);
+/**/
+static void vDM_foreachMappedFaceCenter(
+               DerivedMesh *dm,
+               void (*func)(void *userData, int index, float *cent, float *no),
+               void *userData)
+{
 }
 
-DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm, float (*vertexCos)[3], EditVert **vertMap, EditEdge **edgeMap, EditFace **faceMap)
+/**/
+static void vDM_drawMappedFacesTex(
+               DerivedMesh *dm,
+               int (*setDrawParams)(void *userData, int index),
+               void *userData)
 {
-       SSDerivedMesh *ssdm = MEM_callocN(sizeof(*ssdm), "ssdm");
+}
 
-       ssdm->dm.getMinMax = ssDM_getMinMax;
+/**/
+static void vDM_drawMappedFaces(
+               DerivedMesh *dm,
+               int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
+               void *userData,
+               int useColors)
+{
+}
 
-       ssdm->dm.getNumVerts = ssDM_getNumVerts;
-       ssdm->dm.getNumFaces = ssDM_getNumFaces;
-       ssdm->dm.convertToDispListMesh = ssDM_convertToDispListMesh;
-       ssdm->dm.convertToDispListMeshMapped = ssDM_convertToDispListMeshMapped;
+/**/
+static void vDM_drawMappedEdges(
+               DerivedMesh *dm,
+               int (*setDrawOptions)(void *userData, int index),
+               void *userData)
+{
+}
 
-       ssdm->dm.getVertCos = ssDM_getVertCos;
+/**/
+static void vDM_drawMappedEdgesInterp(
+               DerivedMesh *dm, 
+               int (*setDrawOptions)(void *userData, int index), 
+               void (*setDrawInterpOptions)(void *userData, int index, float t),
+               void *userData)
+{
+}
+
+/* free all DerivedMesh data */
+static void vDM_release(DerivedMesh *dm)
+{
+       VDerivedMesh *vdm = (VDerivedMesh*)dm;
 
-       ssdm->dm.drawVerts = ssDM_drawVerts;
+       if (DM_release(dm)) {
+               if(vdm->vertexCos) MEM_freeN(vdm->vertexCos);
+               MEM_freeN(vdm);
+       }
+}
 
-       ssdm->dm.drawEdges = ssDM_drawEdges;
-       ssdm->dm.drawMappedEdges = ssDM_drawMappedEdges;
-       ssdm->dm.drawLooseEdges = ssDM_drawLooseEdges;
+/* create derived mesh from verse mesh ... it is used in object mode, when some other client can
+ * change shared data and want to see this changes in real time too */
+DerivedMesh *derivedmesh_from_versemesh(VNode *vnode, float (*vertexCos)[3])
+{
+       VDerivedMesh *vdm = MEM_callocN(sizeof(*vdm), "vdm");
+       struct VerseVert *vvert;
 
-       ssdm->dm.drawFacesSolid = ssDM_drawFacesSolid;
-       ssdm->dm.drawFacesColored = ssDM_drawFacesColored;
-       ssdm->dm.drawFacesTex = ssDM_drawFacesTex;
+       vdm->vnode = vnode;
+       vdm->vertex_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
+       vdm->polygon_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
+       vdm->edges = &((VGeomData*)vnode->data)->edges;
 
-               /* EM functions */
+       /* vertex and polygon layer has to exist */
+       if(vdm->vertex_layer && vdm->polygon_layer)
+               DM_init(&vdm->dm, vdm->vertex_layer->dl.da.count, BLI_countlist(vdm->edges), vdm->polygon_layer->dl.da.count);
+       else
+               DM_init(&vdm->dm, 0, 0, 0);
        
-       ssdm->dm.getMappedVertCoEM = ssDM_getMappedVertCoEM;
-       ssdm->dm.drawMappedVertsEM = ssDM_drawMappedVertsEM;
-
-       ssdm->dm.drawMappedEdgesEM = ssDM_drawMappedEdgesEM;
-       ssdm->dm.drawMappedEdgesInterpEM = NULL; // no way to implement this one
+       vdm->dm.getMinMax = vDM_getMinMax;
+
+       vdm->dm.getNumVerts = vDM_getNumVerts;
+       vdm->dm.getNumEdges = vDM_getNumEdges;
+       vdm->dm.getNumFaces = vDM_getNumFaces;
+
+       vdm->dm.getVert = vDM_getVert;
+       vdm->dm.getEdge = vDM_getEdge;
+       vdm->dm.getFace = vDM_getFace;
+       vdm->dm.copyVertArray = vDM_copyVertArray;
+       vdm->dm.copyEdgeArray = vDM_copyEdgeArray;
+       vdm->dm.copyFaceArray = vDM_copyFaceArray;
        
-       ssdm->dm.drawMappedVertNormalsEM = ssDM_drawMappedVertNormalsEM;
-       ssdm->dm.drawMappedFaceNormalsEM = ssDM_drawMappedFaceNormalsEM;
-       ssdm->dm.drawMappedFaceCentersEM = ssDM_drawMappedFaceCentersEM;
+       vdm->dm.foreachMappedVert = vDM_foreachMappedVert;
+       vdm->dm.foreachMappedEdge = vDM_foreachMappedEdge;
+       vdm->dm.foreachMappedFaceCenter = vDM_foreachMappedFaceCenter;
 
-       ssdm->dm.drawMappedFacesEM = ssDM_drawMappedFacesEM;
+       vdm->dm.getVertCos = vDM_getVertCos;
+       vdm->dm.getVertCo = vDM_getVertCo;
+       vdm->dm.getVertNo = vDM_getVertNo;
 
-       ssdm->dm.release = ssDM_release;
-       
-       ssdm->dlm = dlm;
-       ssdm->vertMap = vertMap;
-       ssdm->edgeMap = edgeMap;
-       ssdm->faceMap = faceMap;
+       vdm->dm.drawVerts = vDM_drawVerts;
 
-       if (vertexCos) {
-               int i;
+       vdm->dm.drawEdges = vDM_drawEdges;
+       vdm->dm.drawLooseEdges = vDM_drawLooseEdges;
+       vdm->dm.drawUVEdges = vDM_drawUVEdges;
 
-               for (i=0; i<dlm->totvert; i++) {
-                       VECCOPY(dlm->mvert[i].co, vertexCos[i]);
-               }
+       vdm->dm.drawFacesSolid = vDM_drawFacesSolid;
+       vdm->dm.drawFacesTex = vDM_drawFacesTex;
+       vdm->dm.drawFacesColored = vDM_drawFacesColored;
 
-               if (dlm->nors && !dlm->dontFreeNors) {
-                       MEM_freeN(dlm->nors);
-                       dlm->nors = 0;
-               }
+       vdm->dm.drawMappedFacesTex = vDM_drawMappedFacesTex;
+       vdm->dm.drawMappedFaces = vDM_drawMappedFaces;
+       vdm->dm.drawMappedEdges = vDM_drawMappedEdges;
+       vdm->dm.drawMappedEdgesInterp = vDM_drawMappedEdgesInterp;
 
-               mesh_calc_normals(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface, &dlm->nors);
-       }
+       vdm->dm.release = vDM_release;
 
-       return (DerivedMesh*) ssdm;
+       vdm->vertexCos = vertexCos;
+
+       return (DerivedMesh*) vdm;
 }
 
-/***/
+#endif
 
-typedef float vec3f[3];
+/***/
 
 DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
 {
@@ -1514,81 +1591,196 @@ DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
                float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
 
                mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
-               
+#ifdef WITH_VERSE
+               if(me->vnode) dm = derivedmesh_from_versemesh(me->vnode, deformedVerts);
+               else dm = getMeshDerivedMesh(me, ob, deformedVerts);
+#else
                dm = getMeshDerivedMesh(me, ob, deformedVerts);
+#endif
+
                MEM_freeN(deformedVerts);
        } else {
-               dm = mti->applyModifier(md, ob, NULL, NULL, 0, 0);
+               DerivedMesh *tdm = getMeshDerivedMesh(me, ob, NULL);
+               dm = mti->applyModifier(md, ob, tdm, 0, 0);
+
+               if(tdm != dm) tdm->release(tdm);
        }
 
        return dm;
 }
 
-static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform)
+CustomDataMask get_viewedit_datamask()
+{
+       CustomDataMask mask = CD_MASK_BAREMESH;
+       ScrArea *sa;
+
+       /* check if we need tfaces & mcols due to face select or texture paint */
+       if(G.f & G_FACESELECT || G.f & G_TEXTUREPAINT) {
+               mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+       } else {
+               /* check if we need tfaces & mcols due to view mode */
+               for(sa = G.curscreen->areabase.first; sa; sa = sa->next) {
+                       if(sa->spacetype == SPACE_VIEW3D) {
+                               View3D *view = sa->spacedata.first;
+                               if(view->drawtype == OB_SHADED) {
+                                       /* this includes normals for mesh_create_shadedColors */
+                                       mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL;
+                               }
+                               if(view->drawtype == OB_TEXTURE) {
+                                       mask |= CD_MASK_MTFACE | CD_MASK_MCOL;
+                               }
+                       }
+               }
+       }
+
+       /* check if we need mcols due to vertex paint or weightpaint */
+       if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT)
+               mask |= CD_MASK_MCOL;
+
+       return mask;
+}
+
+static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
+                                DerivedMesh **deform_r, DerivedMesh **final_r,
+                                int useRenderParams, int useDeform,
+                                int needMapping, CustomDataMask dataMask)
 {
        Mesh *me = ob->data;
-       ModifierData *md= ob->modifiers.first;
-       float (*deformedVerts)[3];
+       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       LinkNode *datamasks, *curr;
+       float (*deformedVerts)[3] = NULL;
        DerivedMesh *dm;
        int numVerts = me->totvert;
+       int fluidsimMeshUsed = 0;
+       int required_mode;
+
+       modifiers_clearErrors(ob);
+
+       /* we always want to keep original indices */
+       dataMask |= CD_MASK_ORIGINDEX;
 
-       modifiers_clearErrors(&ob->modifiers);
+       datamasks = modifiers_calcDataMasks(md, dataMask);
+       curr = datamasks;
 
-       if (deform_r) *deform_r = NULL;
+       if(deform_r) *deform_r = NULL;
        *final_r = NULL;
 
-       if (useDeform) {
-               mesh_modifier(ob, &deformedVerts);
+       /* replace original mesh by fluidsim surface mesh for fluidsim
+        * domain objects
+        */
+       if((G.obedit!=ob) && !needMapping) {
+               if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
+                  (1) && (!give_parteff(ob)) ) { // doesnt work together with particle systems!
+                       if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
+                               loadFluidsimMesh(ob,useRenderParams);
+                               fluidsimMeshUsed = 1;
+                               /* might have changed... */
+                               me = ob->data;
+                               numVerts = me->totvert;
+                       }
+               }
+       }
+
+       if(useRenderParams) required_mode = eModifierMode_Render;
+       else required_mode = eModifierMode_Realtime;
 
-                       /* Apply all leading deforming modifiers */
-               for (; md; md=md->next) {
+       if(useDeform) {
+               if(do_ob_key(ob)) /* shape key makes deform verts */
+                       deformedVerts = mesh_getVertexCos(me, &numVerts);
+               
+               /* Apply all leading deforming modifiers */
+               for(; md; md = md->next, curr = curr->next) {
                        ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 
-                       if (!(md->mode&(1<<useRenderParams))) continue;
-                       if (mti->isDisabled && mti->isDisabled(md)) continue;
+                       if((md->mode & required_mode) != required_mode) continue;
+                       if(mti->isDisabled && mti->isDisabled(md)) continue;
+
+                       if(mti->type == eModifierTypeType_OnlyDeform) {
+                               if(!deformedVerts)
+                                       deformedVerts = mesh_getVertexCos(me, &numVerts);
 
-                       if (mti->type==eModifierTypeType_OnlyDeform) {
-                               if (!deformedVerts) deformedVerts = mesh_getVertexCos(me, &numVerts);
                                mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
                        } else {
                                break;
                        }
                }
 
-                       /* Result of all leading deforming modifiers is cached for
-                        * places that wish to use the original mesh but with deformed
-                        * coordinates (vpaint, etc.)
-                        */
-               if (deform_r) *deform_r = getMeshDerivedMesh(me, ob, deformedVerts);
+               /* Result of all leading deforming modifiers is cached for
+                * places that wish to use the original mesh but with deformed
+                * coordinates (vpaint, etc.)
+                */
+               if (deform_r) {
+#ifdef WITH_VERSE
+                       if(me->vnode) *deform_r = derivedmesh_from_versemesh(me->vnode, deformedVerts);
+                       else {
+                               *deform_r = CDDM_from_mesh(me, ob);
+                               if(deformedVerts) {
+                                       CDDM_apply_vert_coords(*deform_r, deformedVerts);
+                                       CDDM_calc_normals(*deform_r);
+                               }
+                       }
+#else
+                       *deform_r = CDDM_from_mesh(me, ob);
+                       if(deformedVerts) {
+                               CDDM_apply_vert_coords(*deform_r, deformedVerts);
+                               CDDM_calc_normals(*deform_r);
+                       }
+#endif
+               }
        } else {
-               deformedVerts = inputVertexCos;
+               if(!fluidsimMeshUsed) {
+                       /* default behaviour for meshes */
+                       deformedVerts = inputVertexCos;
+               } else {
+                       /* the fluid sim mesh might have more vertices than the original 
+                        * one, so inputVertexCos shouldnt be used
+                        */
+                       deformedVerts = mesh_getVertexCos(me, &numVerts);
+               }
        }
 
-               /* Now apply all remaining modifiers. If useDeform is off then skip
-                * OnlyDeform ones. 
-                */
+
+       /* Now apply all remaining modifiers. If useDeform is off then skip
+        * OnlyDeform ones. 
+        */
        dm = NULL;
-       for (; md; md=md->next) {
+
+#ifdef WITH_VERSE
+       /* hack to make sure modifiers don't try to use mesh data from a verse
+        * node
+        */
+       if(me->vnode) dm = derivedmesh_from_versemesh(me->vnode, deformedVerts);
+#endif
+
+       for(; md; md = md->next, curr = curr->next) {
                ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 
-               if (!(md->mode&(1<<useRenderParams))) continue;
-               if (mti->type==eModifierTypeType_OnlyDeform && !useDeform) continue;
-               if (mti->isDisabled && mti->isDisabled(md)) continue;
+               if((md->mode & required_mode) != required_mode) continue;
+               if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue;
+               if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
+                       modifier_setError(md, "Internal error, modifier requires "
+                                         "original data (bad stack position).");
+                       continue;
+               }
+               if(mti->isDisabled && mti->isDisabled(md)) continue;
+               if(needMapping && !modifier_supportsMapping(md)) continue;
 
-                       /* How to apply modifier depends on (a) what we already have as
-                        * a result of previous modifiers (could be a DerivedMesh or just
-                        * deformed vertices) and (b) what type the modifier is.
-                        */
+               /* How to apply modifier depends on (a) what we already have as
+                * a result of previous modifiers (could be a DerivedMesh or just
+                * deformed vertices) and (b) what type the modifier is.
+                */
 
-               if (mti->type==eModifierTypeType_OnlyDeform) {
-                               /* No existing verts to deform, need to build them. */
-                       if (!deformedVerts) {
-                               if (dm) {
-                                               /* Deforming a derived mesh, read the vertex locations out of the mesh and
-                                                * deform them. Once done with this run of deformers verts will be written back.
-                                                */
+               if(mti->type == eModifierTypeType_OnlyDeform) {
+                       /* No existing verts to deform, need to build them. */
+                       if(!deformedVerts) {
+                               if(dm) {
+                                       /* Deforming a derived mesh, read the vertex locations
+                                        * out of the mesh and deform them. Once done with this
+                                        * run of deformers verts will be written back.
+                                        */
                                        numVerts = dm->getNumVerts(dm);
-                                       deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
+                                       deformedVerts =
+                                           MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv");
                                        dm->getVertCos(dm, deformedVerts);
                                } else {
                                        deformedVerts = mesh_getVertexCos(me, &numVerts);
@@ -1597,49 +1789,92 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
 
                        mti->deformVerts(md, ob, dm, deformedVerts, numVerts);
                } else {
-                               /* There are 4 cases here (have deform? have dm?) but they all are handled
-                                * by the modifier apply function, which will also free the DerivedMesh if
-                                * it exists.
-                                */
-                       DerivedMesh *ndm = mti->applyModifier(md, ob, dm, deformedVerts, useRenderParams, !inputVertexCos);
+                       DerivedMesh *ndm;
 
-                       if (ndm) {
-                               if (dm) dm->release(dm);
+                       /* apply vertex coordinates or build a DerivedMesh as necessary */
+                       if(dm) {
+                               if(deformedVerts) {
+                                       DerivedMesh *tdm = CDDM_copy(dm);
+                                       dm->release(dm);
+                                       dm = tdm;
+
+                                       CDDM_apply_vert_coords(dm, deformedVerts);
+                                       CDDM_calc_normals(dm);
+                               }
+                       } else {
+                               dm = CDDM_from_mesh(me, ob);
+
+                               if(deformedVerts) {
+                                       CDDM_apply_vert_coords(dm, deformedVerts);
+                                       CDDM_calc_normals(dm);
+                               }
+                       }
+
+                       /* set the DerivedMesh to only copy needed data */
+                       DM_set_only_copy(dm, (CustomDataMask)curr->link);
+
+                       ndm = mti->applyModifier(md, ob, dm, useRenderParams,
+                                                !inputVertexCos);
+
+                       if(ndm) {
+                               /* if the modifier returned a new dm, release the old one */
+                               if(dm && dm != ndm) dm->release(dm);
 
                                dm = ndm;
 
-                               if (deformedVerts) {
-                                       if (deformedVerts!=inputVertexCos) {
+                               if(deformedVerts) {
+                                       if(deformedVerts != inputVertexCos)
                                                MEM_freeN(deformedVerts);
-                                       }
+
                                        deformedVerts = NULL;
                                }
                        } 
                }
        }
 
-               /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
-                * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
-                * one.
-                */
-       if (dm && deformedVerts) {
-               DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
+       /* Yay, we are done. If we have a DerivedMesh and deformed vertices
+        * need to apply these back onto the DerivedMesh. If we have no
+        * DerivedMesh then we need to build one.
+        */
+       if(dm && deformedVerts) {
+               *final_r = CDDM_copy(dm);
 
                dm->release(dm);
 
-               *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts, NULL, NULL, NULL);
-       } else if (dm) {
+               CDDM_apply_vert_coords(*final_r, deformedVerts);
+               CDDM_calc_normals(*final_r);
+       } else if(dm) {
                *final_r = dm;
        } else {
-               *final_r = getMeshDerivedMesh(me, ob, deformedVerts);
+#ifdef WITH_VERSE
+               if(me->vnode)
+                       *final_r = derivedmesh_from_versemesh(me->vnode, deformedVerts);
+               else {
+                       *final_r = CDDM_from_mesh(me, ob);
+                       if(deformedVerts) {
+                               CDDM_apply_vert_coords(*final_r, deformedVerts);
+                               CDDM_calc_normals(*final_r);
+                       }
+               }
+#else
+               *final_r = CDDM_from_mesh(me, ob);
+               if(deformedVerts) {
+                       CDDM_apply_vert_coords(*final_r, deformedVerts);
+                       CDDM_calc_normals(*final_r);
+               }
+#endif
        }
 
-       if (deformedVerts && deformedVerts!=inputVertexCos) {
+       if(deformedVerts && deformedVerts != inputVertexCos)
                MEM_freeN(deformedVerts);
-       }
+
+       BLI_linklist_free(datamasks, NULL);
+
+       /* restore mesh in any case */
+       if(fluidsimMeshUsed) ob->data = ob->fluidsimSettings->orgMesh;
 }
 
-static vec3f *editmesh_getVertexCos(EditMesh *em, int *numVerts_r)
+static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
 {
        int i, numVerts = *numVerts_r = BLI_countlist(&em->verts);
        float (*cos)[3];
@@ -1653,44 +1888,62 @@ static vec3f *editmesh_getVertexCos(EditMesh *em, int *numVerts_r)
        return cos;
 }
 
-static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
+static void editmesh_calc_modifiers(DerivedMesh **cage_r,
+                                    DerivedMesh **final_r,
+                                    CustomDataMask dataMask)
 {
        Object *ob = G.obedit;
        EditMesh *em = G.editMesh;
        ModifierData *md;
        float (*deformedVerts)[3] = NULL;
        DerivedMesh *dm;
-       int i, numVerts, cageIndex = modifiers_getCageIndex(&ob->modifiers, NULL);
+       int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
+       int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
+       LinkNode *datamasks, *curr;
 
-       modifiers_clearErrors(&ob->modifiers);
+       modifiers_clearErrors(ob);
 
-       if (cage_r && cageIndex==-1) {
-               *cage_r = getEditMeshDerivedMesh(em, NULL);
+       if(cage_r && cageIndex == -1) {
+               *cage_r = getEditMeshDerivedMesh(em, ob, NULL);
        }
 
        dm = NULL;
-       for (i=0,md= ob->modifiers.first; md; i++,md=md->next) {
+       md = ob->modifiers.first;
+
+       /* we always want to keep original indices */
+       dataMask |= CD_MASK_ORIGINDEX;
+
+       datamasks = modifiers_calcDataMasks(md, dataMask);
+
+       curr = datamasks;
+       for(i = 0; md; i++, md = md->next, curr = curr->next) {
                ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 
-               if (!(md->mode&eModifierMode_Realtime)) continue;
-               if (!(md->mode&eModifierMode_Editmode)) continue;
-               if (mti->isDisabled && mti->isDisabled(md)) continue;
-               if (!(mti->flags&eModifierTypeFlag_SupportsEditmode)) continue;
+               if((md->mode & required_mode) != required_mode) continue;
+               if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
+                       modifier_setError(md, "Internal error, modifier requires"
+                                         "original data (bad stack position).");
+                       continue;
+               }
+               if(mti->isDisabled && mti->isDisabled(md)) continue;
+               if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
 
-                       /* How to apply modifier depends on (a) what we already have as
-                        * a result of previous modifiers (could be a DerivedMesh or just
-                        * deformed vertices) and (b) what type the modifier is.
-                        */
+               /* How to apply modifier depends on (a) what we already have as
+                * a result of previous modifiers (could be a DerivedMesh or just
+                * deformed vertices) and (b) what type the modifier is.
+                */
 
-               if (mti->type==eModifierTypeType_OnlyDeform) {
-                               /* No existing verts to deform, need to build them. */
-                       if (!deformedVerts) {
-                               if (dm) {
-                                               /* Deforming a derived mesh, read the vertex locations out of the mesh and
-                                                * deform them. Once done with this run of deformers verts will be written back.
-                                                */
+               if(mti->type == eModifierTypeType_OnlyDeform) {
+                       /* No existing verts to deform, need to build them. */
+                       if(!deformedVerts) {
+                               if(dm) {
+                                       /* Deforming a derived mesh, read the vertex locations
+                                        * out of the mesh and deform them. Once done with this
+                                        * run of deformers verts will be written back.
+                                        */
                                        numVerts = dm->getNumVerts(dm);
-                                       deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
+                                       deformedVerts =
+                                           MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv");
                                        dm->getVertCos(dm, deformedVerts);
                                } else {
                                        deformedVerts = editmesh_getVertexCos(em, &numVerts);
@@ -1699,14 +1952,40 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
 
                        mti->deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
                } else {
-                               /* There are 4 cases here (have deform? have dm?) but they all are handled
-                                * by the modifier apply function, which will also free the DerivedMesh if
-                                * it exists.
-                                */
-                       DerivedMesh *ndm = mti->applyModifierEM(md, ob, em, dm, deformedVerts);
+                       DerivedMesh *ndm;
+
+                       /* apply vertex coordinates or build a DerivedMesh as necessary */
+                       if(dm) {
+                               if(deformedVerts) {
+                                       DerivedMesh *tdm = CDDM_copy(dm);
+                                       if(!(cage_r && dm == *cage_r)) dm->release(dm);
+                                       dm = tdm;
+
+                                       CDDM_apply_vert_coords(dm, deformedVerts);
+                                       CDDM_calc_normals(dm);
+                               } else if(cage_r && dm == *cage_r) {
+                                       /* dm may be changed by this modifier, so we need to copy it
+                                        */
+                                       dm = CDDM_copy(dm);
+                               }
+
+                       } else {
+                               dm = CDDM_from_editmesh(em, ob->data);
+
+                               if(deformedVerts) {
+                                       CDDM_apply_vert_coords(dm, deformedVerts);
+                                       CDDM_calc_normals(dm);
+                               }
+                       }
+
+                       /* set the DerivedMesh to only copy needed data */
+                       DM_set_only_copy(dm, (CustomDataMask)curr->link);
+
+                       ndm = mti->applyModifierEM(md, ob, em, dm);
 
                        if (ndm) {
-                               if (dm && (!cage_r || dm!=*cage_r)) dm->release(dm);
+                               if(dm && dm != ndm)
+                                       dm->release(dm);
 
                                dm = ndm;
 
@@ -1717,44 +1996,124 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
                        }
                }
 
-               if (cage_r && i==cageIndex) {
-                       if (dm && deformedVerts) {
-                               DispListMesh *dlm;
-                               EditVert **vertMap;
-                               EditEdge **edgeMap;
-                               EditFace **faceMap;
-
-                               dlm = dm->convertToDispListMeshMapped(dm, 0, &vertMap, &edgeMap, &faceMap);
-
-                               *cage_r = derivedmesh_from_displistmesh(dlm, deformedVerts, vertMap, edgeMap, faceMap);
-                       } else if (dm) {
+               if(cage_r && i == cageIndex) {
+                       if(dm && deformedVerts) {
+                               *cage_r = CDDM_copy(dm);
+                               CDDM_apply_vert_coords(*cage_r, deformedVerts);
+                       } else if(dm) {
                                *cage_r = dm;
                        } else {
-                               *cage_r = getEditMeshDerivedMesh(em, deformedVerts?MEM_dupallocN(deformedVerts):NULL);
+                               *cage_r =
+                                   getEditMeshDerivedMesh(em, ob,
+                                       deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
                        }
                }
        }
 
-               /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
-                * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
-                * one.
-                */
-       if (dm && deformedVerts) {
-               DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
+       BLI_linklist_free(datamasks, NULL);
 
-               if (!cage_r || dm!=*cage_r) dm->release(dm);
+       /* Yay, we are done. If we have a DerivedMesh and deformed vertices need
+        * to apply these back onto the DerivedMesh. If we have no DerivedMesh
+        * then we need to build one.
+        */
+       if(dm && deformedVerts) {
+               *final_r = CDDM_copy(dm);
 
-               *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts, NULL, NULL, NULL);
-               MEM_freeN(deformedVerts);
+               if(!(cage_r && dm == *cage_r)) dm->release(dm);
+
+               CDDM_apply_vert_coords(*final_r, deformedVerts);
+               CDDM_calc_normals(*final_r);
        } else if (dm) {
                *final_r = dm;
+       } else if (cage_r && *cage_r) {
+               *final_r = *cage_r;
        } else {
-               *final_r = getEditMeshDerivedMesh(em, deformedVerts);
+               *final_r = getEditMeshDerivedMesh(em, ob, deformedVerts);
+               deformedVerts = NULL;
        }
+
+       if(deformedVerts)
+               MEM_freeN(deformedVerts);
 }
 
 /***/
 
+
+       /* Something of a hack, at the moment deal with weightpaint
+        * by tucking into colors during modifier eval, only in
+        * wpaint mode. Works ok but need to make sure recalc
+        * happens on enter/exit wpaint.
+        */
+
+void weight_to_rgb(float input, float *fr, float *fg, float *fb)
+{
+       float blend;
+       
+       blend= ((input/2.0f)+0.5f);
+       
+       if (input<=0.25f){      // blue->cyan
+               *fr= 0.0f;
+               *fg= blend*input*4.0f;
+               *fb= blend;
+       }
+       else if (input<=0.50f){ // cyan->green
+               *fr= 0.0f;
+               *fg= blend;
+               *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
+       }
+       else if (input<=0.75){  // green->yellow
+               *fr= blend * ((input-0.50f)*4.0f);
+               *fg= blend;
+               *fb= 0.0f;
+       }
+       else if (input<=1.0){ // yellow->red
+               *fr= blend;
+               *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
+               *fb= 0.0f;
+       }
+}
+static void calc_weightpaint_vert_color(Object *ob, int vert, unsigned char *col)
+{
+       Mesh *me = ob->data;
+       float fr, fg, fb, input = 0.0f;
+       int i;
+
+       if (me->dvert) {
+               for (i=0; i<me->dvert[vert].totweight; i++)
+                       if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
+                               input+=me->dvert[vert].dw[i].weight;            
+       }
+
+       CLAMP(input, 0.0f, 1.0f);
+       
+       weight_to_rgb(input, &fr, &fg, &fb);
+       
+       col[3] = (unsigned char)(fr * 255.0f);
+       col[2] = (unsigned char)(fg * 255.0f);
+       col[1] = (unsigned char)(fb * 255.0f);
+       col[0] = 255;
+}
+static unsigned char *calc_weightpaint_colors(Object *ob) 
+{
+       Mesh *me = ob->data;
+       MFace *mf = me->mface;
+       unsigned char *wtcol;
+       int i;
+       
+       wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
+       
+       memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
+       for (i=0; i<me->totface; i++, mf++){
+               calc_weightpaint_vert_color(ob, mf->v1, &wtcol[(i*4 + 0)*4]); 
+               calc_weightpaint_vert_color(ob, mf->v2, &wtcol[(i*4 + 1)*4]); 
+               calc_weightpaint_vert_color(ob, mf->v3, &wtcol[(i*4 + 2)*4]); 
+               if (mf->v4)
+                       calc_weightpaint_vert_color(ob, mf->v4, &wtcol[(i*4 + 3)*4]); 
+       }
+       
+       return wtcol;
+}
+
 static void clear_mesh_caches(Object *ob)
 {
        Mesh *me= ob->data;
@@ -1768,33 +2127,62 @@ static void clear_mesh_caches(Object *ob)
        freedisplist(&ob->disp);
 
        if (ob->derivedFinal) {
+               ob->derivedFinal->needsFree = 1;
                ob->derivedFinal->release(ob->derivedFinal);
                ob->derivedFinal= NULL;
        }
        if (ob->derivedDeform) {
+               ob->derivedDeform->needsFree = 1;
                ob->derivedDeform->release(ob->derivedDeform);
                ob->derivedDeform= NULL;
        }
 }
 
-static void mesh_build_data(Object *ob)
+static void mesh_build_data(Object *ob, CustomDataMask dataMask)
 {
+       Mesh *me = ob->data;
        float min[3], max[3];
 
-       if(ob->flag&OB_FROMDUPLI) return;
-
        clear_mesh_caches(ob);
 
-       mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1);
+       if(ob!=G.obedit) {
+               Object *obact = G.scene->basact?G.scene->basact->object:NULL;
+               int editing = (G.f & (G_FACESELECT|G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT));
+               int needMapping = editing && (ob==obact);
 
-       INIT_MINMAX(min, max);
+               if( (G.f & G_WEIGHTPAINT) && ob==obact ) {
+                       MCol *wpcol = (MCol*)calc_weightpaint_colors(ob);
+                       int layernum = CustomData_number_of_layers(&me->fdata, CD_MCOL);
+
+                       /* ugly hack here, we temporarily add a new active mcol layer with
+                          weightpaint colors in it, that is then duplicated in CDDM_from_mesh */
+                       CustomData_add_layer(&me->fdata, CD_MCOL, CD_ASSIGN, wpcol, me->totface);
+                       CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
+
+                       mesh_calc_modifiers(ob, NULL, &ob->derivedDeform,
+                                           &ob->derivedFinal, 0, 1,
+                                           needMapping, dataMask);
 
-       ob->derivedFinal->getMinMax(ob->derivedFinal, min, max);
+                       CustomData_free_layer_active(&me->fdata, CD_MCOL, me->totface);
+               } else {
+                       mesh_calc_modifiers(ob, NULL, &ob->derivedDeform,
+                                           &ob->derivedFinal, 0, 1,
+                                           needMapping, dataMask);
+               }
+
+               INIT_MINMAX(min, max);
+
+               ob->derivedFinal->getMinMax(ob->derivedFinal, min, max);
 
-       boundbox_set_from_min_max(mesh_get_bb(ob->data), min, max);
+               boundbox_set_from_min_max(mesh_get_bb(ob->data), min, max);
+
+               ob->derivedFinal->needsFree = 0;
+               ob->derivedDeform->needsFree = 0;
+               ob->lastDataMask = dataMask;
+       }
 }
 
-static void editmesh_build_data(void)
+static void editmesh_build_data(CustomDataMask dataMask)
 {
        float min[3], max[3];
 
@@ -1804,108 +2192,851 @@ static void editmesh_build_data(void)
 
        if (em->derivedFinal) {
                if (em->derivedFinal!=em->derivedCage) {
+                       em->derivedFinal->needsFree = 1;
                        em->derivedFinal->release(em->derivedFinal);
                }
                em->derivedFinal = NULL;
        }
        if (em->derivedCage) {
+               em->derivedCage->needsFree = 1;
                em->derivedCage->release(em->derivedCage);
                em->derivedCage = NULL;
        }
 
-       editmesh_calc_modifiers(&em->derivedCage, &em->derivedFinal);
+       editmesh_calc_modifiers(&em->derivedCage, &em->derivedFinal, dataMask);
+       em->lastDataMask = dataMask;
 
        INIT_MINMAX(min, max);
 
        em->derivedFinal->getMinMax(em->derivedFinal, min, max);
 
        boundbox_set_from_min_max(mesh_get_bb(G.obedit->data), min, max);
+
+       em->derivedFinal->needsFree = 0;
+       em->derivedCage->needsFree = 0;
 }
 
-void makeDispListMesh(Object *ob)
+void makeDerivedMesh(Object *ob, CustomDataMask dataMask)
 {
        if (ob==G.obedit) {
-               editmesh_build_data();
+               editmesh_build_data(dataMask);
        } else {
-               mesh_build_data(ob);
-
-               build_particle_system(ob);
+               PartEff *paf= give_parteff(ob);
+               
+               mesh_build_data(ob, dataMask);
+               
+               if(paf) {
+                       if((paf->flag & PAF_STATIC) || (ob->recalc & OB_RECALC_TIME)==0)
+                               build_particle_system(ob);
+               }
        }
 }
 
 /***/
 
-DerivedMesh *mesh_get_derived_final(Object *ob, int *needsFree_r)
+DerivedMesh *mesh_get_derived_final(Object *ob, CustomDataMask dataMask)
 {
-       if (!ob->derivedFinal) {
-               mesh_build_data(ob);
-       }
+       /* if there's no derived mesh or the last data mask used doesn't include
+        * the data we need, rebuild the derived mesh
+        */
+       if(!ob->derivedFinal || (dataMask & ob->lastDataMask) != dataMask)
+               mesh_build_data(ob, dataMask);
 
-       *needsFree_r = 0;
        return ob->derivedFinal;
 }
 
-DerivedMesh *mesh_get_derived_deform(Object *ob, int *needsFree_r)
+DerivedMesh *mesh_get_derived_deform(Object *ob, CustomDataMask dataMask)
 {
-       if (!ob->derivedDeform) {
-               mesh_build_data(ob);
-       } 
+       /* if there's no derived mesh or the last data mask used doesn't include
+        * the data we need, rebuild the derived mesh
+        */
+       if(!ob->derivedDeform || (dataMask & ob->lastDataMask) != dataMask)
+               mesh_build_data(ob, dataMask);
 
-       *needsFree_r = 0;
        return ob->derivedDeform;
 }
 
-DerivedMesh *mesh_create_derived_render(Object *ob)
+/* Move to multires Pin level, returns a copy of the original vertex coords. */
+float *multires_render_pin(Object *ob, Mesh *me, int *orig_lvl)
 {
-       DerivedMesh *final;
+       float *vert_copy= NULL;
+
+       if(me->mr) {
+               MultiresLevel *lvl= NULL;
+               int i;
+               
+               /* Make sure all mesh edits are properly stored in the multires data*/
+               multires_update_levels(me, 1);
+       
+               /* Copy the highest level of multires verts */
+               *orig_lvl= me->mr->current;
+               lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
+               vert_copy= MEM_callocN(sizeof(float)*3*lvl->totvert, "multires vert_copy");
+               for(i=0; i<lvl->totvert; ++i)
+                       VecCopyf(&vert_copy[i*3], lvl->verts[i].co);
+       
+               /* Goto the pin level for multires */
+               me->mr->newlvl= me->mr->pinlvl;
+               multires_set_level(ob, me, 1);
+       }
+       
+       return vert_copy;
+}
+
+/* Propagate the changes to render level - fails if mesh topology changed */
+void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_copy, const int orig_lvl)
+{
+       if(me->mr) {
+               if((*dm)->getNumVerts(*dm) == me->totvert &&
+                  (*dm)->getNumFaces(*dm) == me->totface) {
+                       MultiresLevel *lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
+                       DerivedMesh *old= NULL;
+                       int i;
+
+                       (*dm)->copyVertArray(*dm, me->mvert);
+                       (*dm)->release(*dm);
+
+                       me->mr->newlvl= me->mr->renderlvl;
+                       multires_set_level(ob, me, 1);
+                       (*dm)= getMeshDerivedMesh(me, ob, NULL);
+
+                       /* Some of the data in dm is referenced externally, so make a copy */
+                       old= *dm;
+                       (*dm)= CDDM_copy(old);
+                       old->release(old);
+
+                       /* Restore the original verts */
+                       me->mr->newlvl= BLI_countlist(&me->mr->levels);
+                       multires_set_level(ob, me, 1);
+                       for(i=0; i<lvl->totvert; ++i)
+                               VecCopyf(me->mvert[i].co, &vert_copy[i*3]);
+               }
+               
+               if(vert_copy)
+                       MEM_freeN(vert_copy);
+                       
+               me->mr->newlvl= orig_lvl;
+               multires_set_level(ob, me, 1);
+       }
+}
 
-       mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1);
+/* Multires note - if mesh has multires enabled, mesh is first set to the Pin level,
+   where all modifiers are applied, then if the topology hasn't changed, the changes
+   from modifiers are propagated up to the Render level. */
+DerivedMesh *mesh_create_derived_render(Object *ob, CustomDataMask dataMask)
+{
+       DerivedMesh *final;
+       Mesh *me= get_mesh(ob);
+       float *vert_copy= NULL;
+       int orig_lvl= 0;
+       
+       vert_copy= multires_render_pin(ob, me, &orig_lvl);
+       mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask);
+       multires_render_final(ob, me, &final, vert_copy, orig_lvl);
 
        return final;
 }
 
-DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3])
+DerivedMesh *mesh_create_derived_view(Object *ob, CustomDataMask dataMask)
 {
        DerivedMesh *final;
 
-       mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0);
+       mesh_calc_modifiers(ob, NULL, NULL, &final, 0, 1, 0, dataMask);
+
+       return final;
+}
+
+DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3],
+                                           CustomDataMask dataMask)
+{
+       DerivedMesh *final;
+       
+       mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0, 0, dataMask);
 
        return final;
 }
 
-DerivedMesh *mesh_create_derived_no_deform_render(Object *ob, float (*vertCos)[3])
+DerivedMesh *mesh_create_derived_no_deform_render(Object *ob,
+                                                  float (*vertCos)[3],
+                                                  CustomDataMask dataMask)
 {
        DerivedMesh *final;
+       Mesh *me= get_mesh(ob);
+       float *vert_copy= NULL;
+       int orig_lvl= 0;
 
-       mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0);
+       vert_copy= multires_render_pin(ob, me, &orig_lvl);
+       mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0, 0, dataMask);
+       multires_render_final(ob, me, &final, vert_copy, orig_lvl);
 
        return final;
 }
 
 /***/
 
-DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r, int *cageNeedsFree_r, int *finalNeedsFree_r)
+DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r,
+                                                 CustomDataMask dataMask)
 {
-       *cageNeedsFree_r = *finalNeedsFree_r = 0;
-
-       if (!G.editMesh->derivedCage)
-               editmesh_build_data();
+       /* if there's no derived mesh or the last data mask used doesn't include
+        * the data we need, rebuild the derived mesh
+        */
+       if(!G.editMesh->derivedCage ||
+          (G.editMesh->lastDataMask & dataMask) != dataMask)
+               editmesh_build_data(dataMask);
 
        *final_r = G.editMesh->derivedFinal;
        return G.editMesh->derivedCage;
 }
 
-DerivedMesh *editmesh_get_derived_cage(int *needsFree_r)
+DerivedMesh *editmesh_get_derived_cage(CustomDataMask dataMask)
 {
-       *needsFree_r = 0;
-
-       if (!G.editMesh->derivedCage)
-               editmesh_build_data();
+       /* if there's no derived mesh or the last data mask used doesn't include
+        * the data we need, rebuild the derived mesh
+        */
+       if(!G.editMesh->derivedCage ||
+          (G.editMesh->lastDataMask & dataMask) != dataMask)
+               editmesh_build_data(dataMask);
 
        return G.editMesh->derivedCage;
 }
 
 DerivedMesh *editmesh_get_derived_base(void)
 {
-       return getEditMeshDerivedMesh(G.editMesh, NULL);
+       return getEditMeshDerivedMesh(G.editMesh, G.obedit, NULL);
+}
+
+
+/* ********* For those who don't grasp derived stuff! (ton) :) *************** */
+
+static void make_vertexcosnos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+{
+       float *vec = userData;
+       
+       vec+= 6*index;
+
+       /* check if we've been here before (normal should not be 0) */
+       if(vec[3] || vec[4] || vec[5]) return;
+
+       VECCOPY(vec, co);
+       vec+= 3;
+       if(no_f) {
+               VECCOPY(vec, no_f);
+       }
+       else {
+               VECCOPY(vec, no_s);
+       }
+}
+
+/* always returns original amount me->totvert of vertices and normals, but fully deformed and subsurfered */
+/* this is needed for all code using vertexgroups (no subsurf support) */
+/* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */
+/* in use now by vertex/weight paint and particle generating */
+
+float *mesh_get_mapped_verts_nors(Object *ob)
+{
+       Mesh *me= ob->data;
+       DerivedMesh *dm;
+       float *vertexcosnos;
+       
+       /* lets prevent crashing... */
+       if(ob->type!=OB_MESH || me->totvert==0)
+               return NULL;
+       
+       dm= mesh_get_derived_final(ob, CD_MASK_BAREMESH);
+       vertexcosnos= MEM_callocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
+       
+       if(dm->foreachMappedVert) {
+               dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
+       }
+       else {
+               float *fp= vertexcosnos;
+               int a;
+               
+               for(a=0; a< me->totvert; a++, fp+=6) {
+                       dm->getVertCo(dm, a, fp);
+                       dm->getVertNo(dm, a, fp+3);
+               }
+       }
+       
+       dm->release(dm);
+       return vertexcosnos;
+}
+
+
+/* ************************* fluidsim bobj file handling **************************** */
+
+#ifndef DISABLE_ELBEEM
+
+#ifdef WIN32
+#ifndef snprintf
+#define snprintf _snprintf
+#endif
+#endif
+
+/* write .bobj.gz file for a mesh object */
+void writeBobjgz(char *filename, struct Object *ob, int useGlobalCoords, int append, float time) 
+{
+       char debugStrBuffer[256];
+       int wri,i,j,totvert,totface;
+       float wrf;
+       gzFile gzf;
+       DerivedMesh *dm;
+       float vec[3];
+       float rotmat[3][3];
+       MVert *mvert;
+       MFace *mface;
+       //if(append)return; // DEBUG
+
+       if(!ob->data || (ob->type!=OB_MESH)) {
+               snprintf(debugStrBuffer,256,"Writing GZ_BOBJ Invalid object %s ...\n", ob->id.name); 
+               elbeemDebugOut(debugStrBuffer);
+               return;
+       }
+       if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) {
+               snprintf(debugStrBuffer,256,"\nfluidSim::writeBobjgz:: Warning object %s has negative scaling - check triangle ordering...?\n\n", ob->id.name); 
+               elbeemDebugOut(debugStrBuffer);
+       }
+
+       snprintf(debugStrBuffer,256,"Writing GZ_BOBJ '%s' ... ",filename); elbeemDebugOut(debugStrBuffer); 
+       if(append) gzf = gzopen(filename, "a+b9");
+       else       gzf = gzopen(filename, "wb9");
+       if (!gzf) {
+               snprintf(debugStrBuffer,256,"writeBobjgz::error - Unable to open file for writing '%s'\n", filename);
+               elbeemDebugOut(debugStrBuffer);
+               return;
+       }
+
+       dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
+       //dm = mesh_create_derived_no_deform(ob,NULL);
+
+       mvert = dm->getVertArray(dm);
+       mface = dm->getFaceArray(dm);
+       totvert = dm->getNumVerts(dm);
+       totface = dm->getNumFaces(dm);
+
+       // write time value for appended anim mesh
+       if(append) {
+               gzwrite(gzf, &time, sizeof(time));
+       }
+
+       // continue with verts/norms
+       if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Writing GZ_BOBJ, Invalid int size %d...\n", wri); elbeemDebugOut(debugStrBuffer); return; } // paranoia check
+       wri = dm->getNumVerts(dm);
+       mvert = dm->getVertArray(dm);
+       gzwrite(gzf, &wri, sizeof(wri));
+       for(i=0; i<wri;i++) {
+               VECCOPY(vec, mvert[i].co);
+               if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, vec); }
+               for(j=0; j<3; j++) {
+                       wrf = vec[j]; 
+                       gzwrite(gzf, &wrf, sizeof( wrf )); 
+               }
+       }
+
+       // should be the same as Vertices.size
+       wri = totvert;
+       gzwrite(gzf, &wri, sizeof(wri));
+       EulToMat3(ob->rot, rotmat);
+       for(i=0; i<wri;i++) {
+               VECCOPY(vec, mvert[i].no);
+               Normalize(vec);
+               if(useGlobalCoords) { Mat3MulVecfl(rotmat, vec); }
+               for(j=0; j<3; j++) {
+                       wrf = vec[j];
+                       gzwrite(gzf, &wrf, sizeof( wrf )); 
+               }
+       }
+
+       // append only writes verts&norms 
+       if(!append) {
+               //float side1[3],side2[3],norm1[3],norm2[3];
+               //float inpf;
+       
+               // compute no. of triangles 
+               wri = 0;
+               for(i=0; i<totface; i++) {
+                       wri++;
+                       if(mface[i].v4) { wri++; }
+               }
+               gzwrite(gzf, &wri, sizeof(wri));
+               for(i=0; i<totface; i++) {
+
+                       int face[4];
+                       face[0] = mface[i].v1;
+                       face[1] = mface[i].v2;
+                       face[2] = mface[i].v3;
+                       face[3] = mface[i].v4;
+                       //snprintf(debugStrBuffer,256,"F %s %d = %d,%d,%d,%d \n",ob->id.name, i, face[0],face[1],face[2],face[3] ); elbeemDebugOut(debugStrBuffer);
+                       //VecSubf(side1, mvert[face[1]].co,mvert[face[0]].co);
+                       //VecSubf(side2, mvert[face[2]].co,mvert[face[0]].co);
+                       //Crossf(norm1,side1,side2);
+                       gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
+                       gzwrite(gzf, &(face[1]), sizeof( face[1] )); 
+                       gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
+                       if(face[3]) { 
+                               //VecSubf(side1, mvert[face[2]].co,mvert[face[0]].co);
+                               //VecSubf(side2, mvert[face[3]].co,mvert[face[0]].co);
+                               //Crossf(norm2,side1,side2);
+                               //inpf = Inpf(norm1,norm2);
+                               //if(inpf>0.) {
+                               gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
+                               gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
+                               gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
+                               //} else {
+                                       //gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
+                                       //gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
+                                       //gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
+                               //}
+                       } // quad
+               }
+       }
+
+       snprintf(debugStrBuffer,256,"Done. #Vertices: %d, #Triangles: %d\n", totvert, totface ); 
+       elbeemDebugOut(debugStrBuffer);
+       
+       gzclose( gzf );
+       dm->release(dm);
+}
+
+void initElbeemMesh(struct Object *ob, 
+               int *numVertices, float **vertices, 
+               int *numTriangles, int **triangles,
+               int useGlobalCoords) 
+{
+       DerivedMesh *dm = NULL;
+       MVert *mvert;
+       MFace *mface;
+       int countTris=0, i, totvert, totface;
+       float *verts;
+       int *tris;
+
+       dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
+       //dm = mesh_create_derived_no_deform(ob,NULL);
+
+       mvert = dm->getVertArray(dm);
+       mface = dm->getFaceArray(dm);
+       totvert = dm->getNumVerts(dm);
+       totface = dm->getNumFaces(dm);
+
+       *numVertices = totvert;
+       verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
+       for(i=0; i<totvert; i++) {
+               VECCOPY( &verts[i*3], mvert[i].co);
+               if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, &verts[i*3]); }
+       }
+       *vertices = verts;
+
+       for(i=0; i<totface; i++) {
+               countTris++;
+               if(mface[i].v4) { countTris++; }
+       }
+       *numTriangles = countTris;
+       tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
+       countTris = 0;
+       for(i=0; i<totface; i++) {
+               int face[4];
+               face[0] = mface[i].v1;
+               face[1] = mface[i].v2;
+               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]; 
+               countTris++;
+               if(face[3]) { 
+                       tris[countTris*3+0] = face[0]; 
+                       tris[countTris*3+1] = face[2]; 
+                       tris[countTris*3+2] = face[3]; 
+                       countTris++;
+               }
+       }
+       *triangles = tris;
+
+       dm->release(dm);
+}
+
+/* read .bobj.gz file into a fluidsimDerivedMesh struct */
+Mesh* readBobjgz(char *filename, Mesh *orgmesh, float* bbstart, float *bbsize) //, fluidsimDerivedMesh *fsdm)
+{
+       int wri,i,j;
+       char debugStrBuffer[256];
+       float wrf;
+       Mesh *newmesh; 
+       const int debugBobjRead = 1;
+       // init data from old mesh (materials,flags)
+       MFace *origMFace = &((MFace*) orgmesh->mface)[0];
+       int mat_nr = -1;
+       int flag = -1;
+       MFace *fsface = NULL;
+       int gotBytes;
+       gzFile gzf;
+
+       if(!orgmesh) return NULL;
+       if(!origMFace) return NULL;
+       mat_nr = origMFace->mat_nr;
+       flag = origMFace->flag;
+
+       // similar to copy_mesh
+       newmesh = MEM_dupallocN(orgmesh);
+       newmesh->mat= orgmesh->mat;
+
+       newmesh->mvert= NULL;
+       newmesh->medge= NULL;
+       newmesh->mface= NULL;
+       newmesh->mtface= NULL;
+
+       newmesh->dvert = NULL;
+
+       newmesh->mcol= NULL;
+       newmesh->msticky= NULL;
+       newmesh->texcomesh= NULL;
+       memset(&newmesh->vdata, 0, sizeof(newmesh->vdata));
+       memset(&newmesh->edata, 0, sizeof(newmesh->edata));
+       memset(&newmesh->fdata, 0, sizeof(newmesh->fdata));
+
+       newmesh->key= NULL;
+       newmesh->totface = 0;
+       newmesh->totvert = 0;
+       newmesh->totedge = 0;
+       newmesh->medge = NULL;
+
+
+       snprintf(debugStrBuffer,256,"Reading '%s' GZ_BOBJ... ",filename); elbeemDebugOut(debugStrBuffer); 
+       gzf = gzopen(filename, "rb");
+       // gzf = fopen(filename, "rb");
+       // debug: fread(b,c,1,a) = gzread(a,b,c)
+       if (!gzf) {
+               //snprintf(debugStrBuffer,256,"readBobjgz::error - Unable to open file for reading '%s'\n", filename); // DEBUG
+               MEM_freeN(newmesh);
+               return NULL;
+       }
+
+       //if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, Invalid int size %d...\n", wri); return NULL; } // paranoia check
+       gotBytes = gzread(gzf, &wri, sizeof(wri));
+       newmesh->totvert = wri;
+       newmesh->mvert = CustomData_add_layer(&newmesh->vdata, CD_MVERT, CD_CALLOC, NULL, newmesh->totvert);
+       if(debugBobjRead){ snprintf(debugStrBuffer,256,"#vertices %d ", newmesh->totvert); elbeemDebugOut(debugStrBuffer); } //DEBUG
+       for(i=0; i<newmesh->totvert;i++) {
+               //if(debugBobjRead) snprintf(debugStrBuffer,256,"V %d = ",i);
+               for(j=0; j<3; j++) {
+                       gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
+                       newmesh->mvert[i].co[j] = wrf;
+                       //if(debugBobjRead) snprintf(debugStrBuffer,256,"%25.20f ", wrf);
+               }
+               //if(debugBobjRead) snprintf(debugStrBuffer,256,"\n");
+       }
+
+       // should be the same as Vertices.size
+       gotBytes = gzread(gzf, &wri, sizeof(wri));
+       if(wri != newmesh->totvert) {
+               // complain #vertices has to be equal to #normals, reset&abort
+               CustomData_free_layer_active(&newmesh->vdata, CD_MVERT, newmesh->totvert);
+               MEM_freeN(newmesh);
+               snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, #normals=%d, #vertices=%d, aborting...\n", wri,newmesh->totvert );
+               return NULL;
+       }
+       for(i=0; i<newmesh->totvert;i++) {
+               for(j=0; j<3; j++) {
+                       gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
+                       newmesh->mvert[i].no[j] = (short)(wrf*32767.0f);
+                       //newmesh->mvert[i].no[j] = 0.5; // DEBUG tst
+               }
+       //fprintf(stderr,"  DEBDPCN nm%d, %d = %d,%d,%d \n",
+                       //(int)(newmesh->mvert), i, newmesh->mvert[i].no[0], newmesh->mvert[i].no[1], newmesh->mvert[i].no[2]);
+       }
+       //fprintf(stderr,"  DPCN 0 = %d,%d,%d \n", newmesh->mvert[0].no[0], newmesh->mvert[0].no[1], newmesh->mvert[0].no[2]);
+
+       
+       /* compute no. of triangles */
+       gotBytes = gzread(gzf, &wri, sizeof(wri));
+       newmesh->totface = wri;
+       newmesh->mface = CustomData_add_layer(&newmesh->fdata, CD_MFACE, CD_CALLOC, NULL, newmesh->totface);
+       if(debugBobjRead){ snprintf(debugStrBuffer,256,"#faces %d ", newmesh->totface); elbeemDebugOut(debugStrBuffer); } //DEBUG
+       fsface = newmesh->mface;
+       for(i=0; i<newmesh->totface; i++) {
+               int face[4];
+
+               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;
+
+               fsface[i].v1 = face[0];
+               fsface[i].v2 = face[1];
+               fsface[i].v3 = face[2];
+               fsface[i].v4 = face[3];
+       }
+
+       // correct triangles with v3==0 for blender, cycle verts
+       for(i=0; i<newmesh->totface; i++) {
+               if(!fsface[i].v3) {
+                       int temp = fsface[i].v1;
+                       fsface[i].v1 = fsface[i].v2;
+                       fsface[i].v2 = fsface[i].v3;
+                       fsface[i].v3 = temp;
+               }
+       }
+       
+       gzclose( gzf );
+       for(i=0;i<newmesh->totface;i++) { 
+               fsface[i].mat_nr = mat_nr;
+               fsface[i].flag = flag;
+               fsface[i].edcode = ME_V1V2 | ME_V2V3 | ME_V3V1;
+               //snprintf(debugStrBuffer,256,"%d : %d,%d,%d\n", i,fsface[i].mat_nr, fsface[i].flag, fsface[i].edcode );
+       }
+
+       snprintf(debugStrBuffer,256," (%d,%d) done\n", newmesh->totvert,newmesh->totface); elbeemDebugOut(debugStrBuffer); //DEBUG
+       return newmesh;
+}
+
+/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
+void readVelgz(char *filename, Object *srcob)
+{
+       char debugStrBuffer[256];
+       int wri, i, j;
+       float wrf;
+       gzFile gzf;
+       MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
+       int len = strlen(filename);
+       Mesh *mesh = srcob->data;
+       // mesh and vverts have to be valid from loading...
+
+       // clean up in any case
+       for(i=0; i<mesh->totvert;i++) { 
+               for(j=0; j<3; j++) {
+                       vverts[i].co[j] = 0.; 
+               } 
+       } 
+       if(srcob->fluidsimSettings->domainNovecgen>0) return;
+
+       if(len<7) { 
+               //printf("readVelgz Eror: invalid filename '%s'\n",filename); // DEBUG
+               return; 
+       }
+
+       // .bobj.gz , correct filename
+       // 87654321
+       filename[len-6] = 'v';
+       filename[len-5] = 'e';
+       filename[len-4] = 'l';
+
+       snprintf(debugStrBuffer,256,"Reading '%s' GZ_VEL... ",filename); elbeemDebugOut(debugStrBuffer); 
+       gzf = gzopen(filename, "rb");
+       if (!gzf) { 
+               //printf("readVelgz Eror: unable to open file '%s'\n",filename); // DEBUG
+               return; 
+       }
+
+       gzread(gzf, &wri, sizeof( wri ));
+       if(wri != mesh->totvert) {
+               //printf("readVelgz Eror: invalid no. of velocities %d vs. %d aborting.\n" ,wri ,mesh->totvert ); // DEBUG
+               return; 
+       }
+
+       for(i=0; i<mesh->totvert;i++) {
+               for(j=0; j<3; j++) {
+                       gzread(gzf, &wrf, sizeof( wrf )); 
+                       vverts[i].co[j] = wrf;
+               }
+               //if(i<20) fprintf(stderr, "GZ_VELload %d = %f,%f,%f  \n",i,vverts[i].co[0],vverts[i].co[1],vverts[i].co[2]); // DEBUG
+       }
+
+       gzclose(gzf);
+}
+
+
+/* ***************************** fluidsim derived mesh ***************************** */
+
+/* check which file to load, and replace old mesh of the object with it */
+/* this replacement is undone at the end of mesh_calc_modifiers */
+void loadFluidsimMesh(Object *srcob, int useRenderParams)
+{
+       Mesh *mesh = NULL;
+       float *bbStart = NULL, *bbSize = NULL;
+       float lastBB[3];
+       int displaymode = 0;
+       int curFrame = G.scene->r.cfra - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
+       char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
+       char debugStrBuffer[256];
+       //snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
+
+       if((!srcob)||(!srcob->fluidsimSettings)) {
+               snprintf(debugStrBuffer,256,"DEBUG - Invalid loadFluidsimMesh call, rp %d, dm %d)\n", useRenderParams, displaymode); // debug
+               elbeemDebugOut(debugStrBuffer); // debug
+               return;
+       }
+       // make sure the original mesh data pointer is stored
+       if(!srcob->fluidsimSettings->orgMesh) {
+               srcob->fluidsimSettings->orgMesh = srcob->data;
+       }
+
+       // free old mesh, if there is one (todo, check if it's still valid?)
+       if(srcob->fluidsimSettings->meshSurface) {
+               Mesh *freeFsMesh = srcob->fluidsimSettings->meshSurface;
+
+               // similar to free_mesh(...) , but no things like unlink...
+               CustomData_free(&freeFsMesh->vdata, freeFsMesh->totvert);
+               CustomData_free(&freeFsMesh->edata, freeFsMesh->totedge);
+               CustomData_free(&freeFsMesh->fdata, freeFsMesh->totface);
+               MEM_freeN(freeFsMesh);
+               
+               if(srcob->data == srcob->fluidsimSettings->meshSurface)
+                srcob->data = srcob->fluidsimSettings->orgMesh;
+               srcob->fluidsimSettings->meshSurface = NULL;
+
+               if(srcob->fluidsimSettings->meshSurfNormals) MEM_freeN(srcob->fluidsimSettings->meshSurfNormals);
+               srcob->fluidsimSettings->meshSurfNormals = NULL;
+       } 
+
+       // init bounding box
+       bbStart = srcob->fluidsimSettings->bbStart; 
+       bbSize = srcob->fluidsimSettings->bbSize;
+       lastBB[0] = bbSize[0];  // TEST
+       lastBB[1] = bbSize[1]; 
+       lastBB[2] = bbSize[2];
+       fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize, &srcob->fluidsimSettings->meshBB);
+       // check free fsmesh... TODO
+       
+       if(!useRenderParams) {
+               displaymode = srcob->fluidsimSettings->guiDisplayMode;
+       } else {
+               displaymode = srcob->fluidsimSettings->renderDisplayMode;
+       }
+       
+       snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d), curFra=%d, sFra=%d #=%d \n", 
+                       srcob->id.name, useRenderParams, displaymode, G.scene->r.cfra, G.scene->r.sfra, curFrame ); // debug
+       elbeemDebugOut(debugStrBuffer); // debug
+
+       strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR);
+       // use preview or final mesh?
+       if(displaymode==1) {
+               // just display original object
+               srcob->data = srcob->fluidsimSettings->orgMesh;
+               return;
+       } else if(displaymode==2) {
+               strcat(targetDir,"fluidsurface_preview_#");
+       } else { // 3
+               strcat(targetDir,"fluidsurface_final_#");
+       }
+       BLI_convertstringcode(targetDir, G.sce, curFrame); // fixed #frame-no 
+       strcpy(targetFile,targetDir);
+       strcat(targetFile, ".bobj.gz");
+
+       snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile);  // debug
+       elbeemDebugOut(debugStrBuffer); // debug
+
+       if(displaymode!=2) { // dont add bounding box for final
+               mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh ,NULL,NULL);
+       } else {
+               mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh, bbSize,bbSize );
+       }
+       if(!mesh) {
+               // 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
+               srcob->data = srcob->fluidsimSettings->orgMesh;
+               return;
+       }
+
+       if((mesh)&&(mesh->totvert>0)) {
+               make_edges(mesh, 0);    // 0 = make all edges draw
+       }
+       srcob->fluidsimSettings->meshSurface = mesh;
+       srcob->data = mesh;
+       srcob->fluidsimSettings->meshSurfNormals = MEM_dupallocN(mesh->mvert);
+
+       // 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) {
+               readVelgz(targetFile, srcob);
+       } else {
+               // no data for preview, only clear...
+               int i,j;
+               for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }} 
+       }
+
+       //fprintf(stderr,"LOADFLM DEBXHCH fs=%d 3:%d,%d,%d \n", (int)mesh, ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[0], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[1], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[2]);
+       return;
+}
+
+/* helper function */
+/* init axis aligned BB for mesh object */
+void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
+                /*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh )
+{
+       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];
+
+       VECCOPY(vec, mesh->mvert[0].co); 
+       Mat4MulVecfl(obmat, vec);
+       bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
+       bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
+
+       for(i=1; i<mesh->totvert;i++) {
+               VECCOPY(vec, mesh->mvert[i].co);
+               Mat4MulVecfl(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;
+       }
+
+       // init bounding box mesh?
+       if(bbmesh) {
+               int i,j;
+               Mesh *newmesh = NULL;
+               if(!(*bbmesh)) { newmesh = MEM_callocN(sizeof(Mesh), "fluidsimGetAxisAlignedBB_meshbb"); }
+               else {           newmesh = *bbmesh; }
+
+               newmesh->totvert = 8;
+               if(!newmesh->mvert)
+                       newmesh->mvert = CustomData_add_layer(&newmesh->vdata, CD_MVERT, CD_CALLOC, NULL, newmesh->totvert);
+               for(i=0; i<8; i++) {
+                       for(j=0; j<3; j++) newmesh->mvert[i].co[j] = start[j]; 
+               }
+
+               newmesh->totface = 6;
+               if(!newmesh->mface)
+                       newmesh->mface = CustomData_add_layer(&newmesh->fdata, CD_MFACE, CD_CALLOC, NULL, newmesh->totface);
+
+               *bbmesh = newmesh;
+       }
+}
+
+#else // DISABLE_ELBEEM
+
+/* dummy for mesh_calc_modifiers */
+void loadFluidsimMesh(Object *srcob, int useRenderParams) {
 }
+
+#endif // DISABLE_ELBEEM
+