NLA SoC: Start of 'Meta' Strips
[blender.git] / source / blender / blenkernel / intern / DerivedMesh.c
index 4d3f9143b851699cb13e45f61795e768542895d7..090f256ab9fd52802976f777043fca80d8331781 100644 (file)
@@ -33,8 +33,6 @@
 #include <config.h>
 #endif
 
-#include <zlib.h>
-
 #include "PIL_time.h"
 
 #include "MEM_guardedalloc.h"
@@ -59,6 +57,7 @@
 #include "BLI_edgehash.h"
 #include "BLI_editVert.h"
 #include "BLI_linklist.h"
+#include "BLI_memarena.h"
 
 #include "BKE_cdderivedmesh.h"
 #include "BKE_customdata.h"
 #include "BKE_deform.h"
 #include "BKE_displist.h"
 #include "BKE_effect.h"
+#include "BKE_fluidsim.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
 #include "BKE_material.h"
 #include "BKE_modifier.h"
 #include "BKE_mesh.h"
-#include "BKE_multires.h"
 #include "BKE_object.h"
 #include "BKE_subsurf.h"
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
 #include "BKE_particle.h"
+#include "BKE_bvhutils.h"
 
-#ifdef WITH_VERSE
-#include "BKE_verse.h"
-#endif
+#include "BLO_sys_types.h" // for intptr_t support
 
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 
-// headers for fluidsim bobj meshes
-#include <stdlib.h>
-#include "LBM_fluidsim.h"
-#include "elbeem.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
 
 ///////////////////////////////////
 ///////////////////////////////////
 
-MVert *dm_getVertArray(DerivedMesh *dm)
+static MVert *dm_getVertArray(DerivedMesh *dm)
 {
        MVert *mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
 
@@ -107,7 +104,7 @@ MVert *dm_getVertArray(DerivedMesh *dm)
        return mvert;
 }
 
-MEdge *dm_getEdgeArray(DerivedMesh *dm)
+static MEdge *dm_getEdgeArray(DerivedMesh *dm)
 {
        MEdge *medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
 
@@ -121,7 +118,7 @@ MEdge *dm_getEdgeArray(DerivedMesh *dm)
        return medge;
 }
 
-MFace *dm_getFaceArray(DerivedMesh *dm)
+static MFace *dm_getFaceArray(DerivedMesh *dm)
 {
        MFace *mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
 
@@ -135,7 +132,7 @@ MFace *dm_getFaceArray(DerivedMesh *dm)
        return mface;
 }
 
-MVert *dm_dupVertArray(DerivedMesh *dm)
+static MVert *dm_dupVertArray(DerivedMesh *dm)
 {
        MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm),
                                 "dm_dupVertArray tmp");
@@ -145,7 +142,7 @@ MVert *dm_dupVertArray(DerivedMesh *dm)
        return tmp;
 }
 
-MEdge *dm_dupEdgeArray(DerivedMesh *dm)
+static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
 {
        MEdge *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumEdges(dm),
                                 "dm_dupEdgeArray tmp");
@@ -155,7 +152,7 @@ MEdge *dm_dupEdgeArray(DerivedMesh *dm)
        return tmp;
 }
 
-MFace *dm_dupFaceArray(DerivedMesh *dm)
+static MFace *dm_dupFaceArray(DerivedMesh *dm)
 {
        MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumFaces(dm),
                                 "dm_dupFaceArray tmp");
@@ -181,6 +178,8 @@ void DM_init_funcs(DerivedMesh *dm)
        dm->getVertDataArray = DM_get_vert_data_layer;
        dm->getEdgeDataArray = DM_get_edge_data_layer;
        dm->getFaceDataArray = DM_get_face_data_layer;
+
+       bvhcache_init(&dm->bvhCache);
 }
 
 void DM_init(DerivedMesh *dm,
@@ -217,6 +216,8 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
 int DM_release(DerivedMesh *dm)
 {
        if (dm->needsFree) {
+               bvhcache_free(&dm->bvhCache);
+
                CustomData_free(&dm->vertData, dm->numVertData);
                CustomData_free(&dm->edgeData, dm->numEdgeData);
                CustomData_free(&dm->faceData, dm->numFaceData);
@@ -408,38 +409,20 @@ void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices)
        CustomData_swap(&dm->faceData, index, corner_indices);
 }
 
+///
+
 static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
 {
        DerivedMesh *dm = CDDM_from_mesh(me, ob);
-       int i, dofluidsim;
-
-       dofluidsim = ((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
-                     (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
-                     (ob->fluidsimSettings->meshSurface) &&
-                     (me->totvert == ((Mesh *)(ob->fluidsimSettings->meshSurface))->totvert));
-
-       if (vertCos && !dofluidsim)
+       
+       if(!dm)
+               return NULL;
+       
+       if (vertCos)
                CDDM_apply_vert_coords(dm, vertCos);
 
        CDDM_calc_normals(dm);
 
-       /* 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");
-
-               for (i=0; i<me->totvert; i++) {
-                       VECCOPY(normals[i], fsvert[i].no);
-                       //mv->no[0]= 30000; mv->no[1]= mv->no[2]= 0; // DEBUG fixed test normals
-               }
-
-               CDDM_apply_vert_normals(dm, normals);
-
-               MEM_freeN(normals);
-       }
-
        return dm;
 }
 
@@ -478,7 +461,7 @@ static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData,
                EditVert *eve;
 
                for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (long) i++;
+                       eve->tmp.l = (intptr_t) 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 {
@@ -496,7 +479,7 @@ static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *us
                EditVert *eve;
 
                for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (long) i++;
+                       eve->tmp.l = (intptr_t) i++;
 
                glBegin(GL_LINES);
                for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
@@ -531,7 +514,7 @@ static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(vo
                EditVert *eve;
 
                for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (long) i++;
+                       eve->tmp.l = (intptr_t) i++;
 
                glBegin(GL_LINES);
                for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
@@ -618,7 +601,7 @@ static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *use
 
        if (emdm->vertexCos) {
                for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (long) i++;
+                       eve->tmp.l = (intptr_t) i++;
        }
 
        for(i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
@@ -636,7 +619,7 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
                EditVert *eve;
 
                for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (long) i++;
+                       eve->tmp.l = (intptr_t) i++;
 
                for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
                        int drawSmooth = (efa->flag & ME_SMOOTH);
@@ -732,7 +715,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
                EditVert *eve;
 
                for (i=0,eve=em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (long) i++;
+                       eve->tmp.l = (intptr_t) i++;
 
                for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
                        MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
@@ -891,6 +874,162 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void
        emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
 }
 
+static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs),
+               int (*setDrawOptions)(void *userData, int index), void *userData) 
+{
+       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditMesh *em= emdm->em;
+       float (*vertexCos)[3]= emdm->vertexCos;
+       float (*vertexNos)[3]= emdm->vertexNos;
+       EditVert *eve;
+       EditFace *efa;
+       DMVertexAttribs attribs;
+       GPUVertexAttribs gattribs;
+       MTFace *tf;
+       int transp, new_transp, orig_transp, tfoffset;
+       int i, b, matnr, new_matnr, dodraw, layer;
+
+       dodraw = 0;
+       matnr = -1;
+
+       transp = GPU_get_material_blend_mode();
+       orig_transp = transp;
+       layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE);
+       tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset;
+
+       memset(&attribs, 0, sizeof(attribs));
+
+       /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
+       glShadeModel(GL_SMOOTH);
+
+       for (i=0,eve=em->verts.first; eve; eve= eve->next)
+               eve->tmp.l = (intptr_t) i++;
+
+#define PASSATTRIB(efa, eve, vert) {                                                                                   \
+       if(attribs.totorco) {                                                                                                           \
+               float *orco = attribs.orco.array[eve->tmp.l];                                                   \
+               glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.tottface; b++) {                                                                         \
+               MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset);  \
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]);                  \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.totmcol; b++) {                                                                          \
+               MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset);                \
+               GLubyte col[4];                                                                                                                 \
+               col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
+               glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
+       }                                                                                                                                                       \
+       if(attribs.tottang) {                                                                                                           \
+               float *tang = attribs.tang.array[i*4 + vert];                                                   \
+               glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
+       }                                                                                                                                                       \
+}
+
+       for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
+               int drawSmooth= (efa->flag & ME_SMOOTH);
+
+               if(setDrawOptions && !setDrawOptions(userData, i))
+                       continue;
+
+               new_matnr = efa->mat_nr + 1;
+               if(new_matnr != matnr) {
+                       dodraw = setMaterial(matnr = new_matnr, &gattribs);
+                       if(dodraw)
+                               DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+               }
+
+               if(tfoffset != -1) {
+                       tf = (MTFace*)((char*)efa->data)+tfoffset;
+                       new_transp = tf->transp;
+
+                       if(new_transp != transp) {
+                               if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+                                       GPU_set_material_blend_mode(orig_transp);
+                               else
+                                       GPU_set_material_blend_mode(new_transp);
+                               transp = new_transp;
+                       }
+               }
+
+               if(dodraw) {
+                       glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+                       if (!drawSmooth) {
+                               if(vertexCos) glNormal3fv(emdm->faceNos[i]);
+                               else glNormal3fv(efa->n);
+
+                               PASSATTRIB(efa, efa->v1, 0);
+                               if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                               else glVertex3fv(efa->v1->co);
+
+                               PASSATTRIB(efa, efa->v2, 1);
+                               if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                               else glVertex3fv(efa->v2->co);
+
+                               PASSATTRIB(efa, efa->v3, 2);
+                               if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                               else glVertex3fv(efa->v3->co);
+
+                               if(efa->v4) {
+                                       PASSATTRIB(efa, efa->v4, 3);
+                                       if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                       else glVertex3fv(efa->v4->co);
+                               }
+                       } else {
+                               PASSATTRIB(efa, efa->v1, 0);
+                               if(vertexCos) {
+                                       glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                               }
+                               else {
+                                       glNormal3fv(efa->v1->no);
+                                       glVertex3fv(efa->v1->co);
+                               }
+
+                               PASSATTRIB(efa, efa->v2, 1);
+                               if(vertexCos) {
+                                       glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                               }
+                               else {
+                                       glNormal3fv(efa->v2->no);
+                                       glVertex3fv(efa->v2->co);
+                               }
+
+                               PASSATTRIB(efa, efa->v3, 2);
+                               if(vertexCos) {
+                                       glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
+                                       glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                               }
+                               else {
+                                       glNormal3fv(efa->v3->no);
+                                       glVertex3fv(efa->v3->co);
+                               }
+
+                               if(efa->v4) {
+                                       PASSATTRIB(efa, efa->v4, 3);
+                                       if(vertexCos) {
+                                               glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
+                                               glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                       }
+                                       else {
+                                               glNormal3fv(efa->v4->no);
+                                               glVertex3fv(efa->v4->co);
+                                       }
+                               }
+                       }
+                       glEnd();
+               }
+       }
+}
+
+static void emDM_drawFacesGLSL(DerivedMesh *dm,
+               int (*setMaterial)(int, void *attribs))
+{
+       dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -930,7 +1069,7 @@ static int emDM_getNumFaces(DerivedMesh *dm)
        return BLI_countlist(&emdm->em->faces);
 }
 
-void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
 {
        EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
        int i;
@@ -948,7 +1087,7 @@ void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
        vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
 }
 
-void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
+static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
 {
        EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
        EditEdge *ee = em->edges.first;
@@ -983,7 +1122,7 @@ void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
        }
 }
 
-void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
+static void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
 {
        EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
        EditFace *ef = em->faces.first;
@@ -1025,7 +1164,7 @@ void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
        test_index_face(face_r, NULL, 0, ef->v4?4:3);
 }
 
-void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
+static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
 {
        EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
 
@@ -1043,7 +1182,7 @@ void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
        }
 }
 
-void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
 {
        EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
        EditEdge *ee = em->edges.first;
@@ -1052,7 +1191,7 @@ void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
 
        /* store vertex indices in tmp union */
        for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
-               ev->tmp.l = (long) i;
+               ev->tmp.l = (intptr_t) i;
 
        for( ; ee; ee = ee->next, ++edge_r) {
                edge_r->crease = (unsigned char) (ee->crease*255.0f);
@@ -1071,7 +1210,7 @@ void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
        }
 }
 
-void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
+static void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
 {
        EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
        EditFace *ef = em->faces.first;
@@ -1080,7 +1219,7 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
 
        /* store vertexes indices in tmp union */
        for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
-               ev->tmp.l = (long) i;
+               ev->tmp.l = (intptr_t) i;
 
        for( ; ef; ef = ef->next, ++face_r) {
                face_r->mat_nr = ef->mat_nr;
@@ -1096,6 +1235,43 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
        }
 }
 
+static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
+{
+       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditMesh *em= emdm->em;
+       EditFace *efa;
+       char *data, *emdata;
+       void *datalayer;
+       int index, offset, size;
+
+       datalayer = DM_get_face_data_layer(dm, type);
+       if(datalayer)
+               return datalayer;
+
+       /* layers are store per face for editmesh, we convert to a temporary
+        * data layer array in the derivedmesh when these are requested */
+       if(type == CD_MTFACE || type == CD_MCOL) {
+               index = CustomData_get_layer_index(&em->fdata, type);
+
+               if(index != -1) {
+                       offset = em->fdata.layers[index].offset;
+                       size = CustomData_sizeof(type);
+
+                       DM_add_face_layer(dm, type, CD_CALLOC, NULL);
+                       index = CustomData_get_layer_index(&dm->faceData, type);
+                       dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY;
+
+                       data = datalayer = DM_get_face_data_layer(dm, type);
+                       for(efa=em->faces.first; efa; efa=efa->next, data+=size) {
+                               emdata = CustomData_em_get(&em->fdata, efa->data, type);
+                               memcpy(data, emdata, size);
+                       }
+               }
+       }
+
+       return datalayer;
+}
+
 static void emDM_release(DerivedMesh *dm)
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -1131,6 +1307,7 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
        emdm->dm.copyVertArray = emDM_copyVertArray;
        emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
        emdm->dm.copyFaceArray = emDM_copyFaceArray;
+       emdm->dm.getFaceDataArray = emDM_getFaceDataArray;
 
        emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
        emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
@@ -1141,7 +1318,9 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
        emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
        emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
        emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
+       emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
        emdm->dm.drawFacesTex = emDM_drawFacesTex;
+       emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
        emdm->dm.drawUVEdges = emDM_drawUVEdges;
 
        emdm->dm.release = emDM_release;
@@ -1167,7 +1346,7 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
                int i;
 
                for (i=0,eve=em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (long) i++;
+                       eve->tmp.l = (intptr_t) i++;
 
                emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno");
                emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno");
@@ -1207,682 +1386,210 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
        return (DerivedMesh*) emdm;
 }
 
-#ifdef WITH_VERSE
-
-/* verse derived mesh */
-typedef struct {
-       struct DerivedMesh dm;
-       struct VNode *vnode;
-       struct VLayer *vertex_layer;
-       struct VLayer *polygon_layer;
-       struct ListBase *edges;
-       float (*vertexCos)[3];
-} VDerivedMesh;
+/***/
 
-/* 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])
+DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, ModifierData *md)
 {
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseVert *vvert;
-
-       if(!vdm->vertex_layer) return;
-
-       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;
-       }
-}
+       Mesh *me = ob->data;
+       ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+       DerivedMesh *dm;
 
-/* this function return number of vertexes in vertex layer */
-static int vDM_getNumVerts(DerivedMesh *dm)
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+       md->scene= scene;
+       
+       if (!(md->mode&eModifierMode_Realtime)) return NULL;
+       if (mti->isDisabled && mti->isDisabled(md)) return NULL;
 
-       if(!vdm->vertex_layer) return 0;
-       else return vdm->vertex_layer->dl.da.count;
-}
+       if (mti->type==eModifierTypeType_OnlyDeform) {
+               int numVerts;
+               float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
 
-/* this function return number of 'fake' edges */
-static int vDM_getNumEdges(DerivedMesh *dm)
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+               mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0, 0);
+               dm = getMeshDerivedMesh(me, ob, deformedVerts);
 
-       return BLI_countlist(vdm->edges);
-}
+               MEM_freeN(deformedVerts);
+       } else {
+               DerivedMesh *tdm = getMeshDerivedMesh(me, ob, NULL);
+               dm = mti->applyModifier(md, ob, tdm, 0, 0);
 
-/* this function returns number of polygons in polygon layer */
-static int vDM_getNumFaces(DerivedMesh *dm)
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
+               if(tdm != dm) tdm->release(tdm);
+       }
 
-       if(!vdm->polygon_layer) return 0;
-       else return vdm->polygon_layer->dl.da.count;
+       return dm;
 }
 
-/* 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)
+static float *get_editmesh_orco_verts(EditMesh *em)
 {
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseVert *vvert;
-       int i;
-
-       if(!vdm->vertex_layer) return;
-
-       for(vvert = vdm->vertex_layer->dl.lb.first, i=0 ; i<index; i++) vvert = vvert->next;
+       EditVert *eve;
+       float *orco;
+       int a, totvert;
 
-       if(vvert) {
-               VECCOPY(vert_r->co, vvert->co);
+       /* these may not really be the orco's, but it's only for preview.
+        * could be solver better once, but isn't simple */
 
-               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;
+       totvert= 0;
+       for(eve=em->verts.first; eve; eve=eve->next)
+               totvert++;
+       
+       orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco");
 
-               /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
-               vert_r->mat_nr = 0;
-               vert_r->flag = 0;
-       }
+       for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3)
+               VECCOPY(orco+a, eve->co);
+       
+       return orco;
 }
 
-/* this function returns fake verse edge */
-void vDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseEdge *vedge;
-       struct VLayer *vert_vlayer = vdm->vertex_layer;
-       struct VerseVert *vvert;
-       int j;
+/* orco custom data layer */
 
-       if(!vdm->vertex_layer || !vdm->edges) return;
+static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em)
+{
+       DerivedMesh *dm;
+       float (*orco)[3];
 
-       if(vdm->edges->first) {
-               struct VerseVert *vvert1, *vvert2;
+       if(em) {
+               dm= CDDM_from_editmesh(em, me);
+               orco= (float(*)[3])get_editmesh_orco_verts(em);
+       }
+       else {
+               dm= CDDM_from_mesh(me, ob);
+               orco= (float(*)[3])get_mesh_orco_verts(ob);
+       }
 
-               /* 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;
+       CDDM_apply_vert_coords(dm, orco);
+       CDDM_calc_normals(dm);
+       MEM_freeN(orco);
 
-               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;
-                               edge_r->bweight = 0;
-                               break;
-                       }
-               }
-       }
+       return dm;
 }
 
-/* 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)
+static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm)
 {
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseFace *vface;
-       struct VerseVert *vvert;
-       struct VerseVert *vvert0, *vvert1, *vvert2, *vvert3;
-       int i;
-
-       if(!vdm->vertex_layer || !vdm->polygon_layer) return;
+       float (*orco)[3], (*layerorco)[3];
+       int totvert;
 
-       for(vface = vdm->polygon_layer->dl.lb.first, i = 0; i < index; ++i) vface = vface->next;
+       totvert= dm->getNumVerts(dm);
 
-       face_r->mat_nr = 0;
-       face_r->flag = 0;
+       if(orcodm) {
+               orco= MEM_callocN(sizeof(float)*3*totvert, "dm orco");
 
-       /* 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;
-               }
+               if(orcodm->getNumVerts(orcodm) == totvert)
+                       orcodm->getVertCos(orcodm, orco);
+               else
+                       dm->getVertCos(dm, orco);
+       }
+       else {
+               if(em) orco= (float(*)[3])get_editmesh_orco_verts(em);
+               else orco= (float(*)[3])get_mesh_orco_verts(ob);
        }
 
-       test_index_face(face_r, NULL, 0, vface->vvert3?4:3);
-}
-
-/* fill array of mvert */
-void vDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseVert *vvert;
-
-       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;
+       transform_mesh_orco_verts(ob->data, orco, totvert, 0);
 
-               vert_r->mat_nr = 0;
-               vert_r->flag = 0;
+       if((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) {
+               memcpy(layerorco, orco, sizeof(float)*totvert);
+               MEM_freeN(orco);
        }
+       else
+               DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
 }
 
-/* dummy function, edges arent supported in verse mesh */
-void vDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-
-       if(!vdm->vertex_layer || !vdm->edges) return;
-
-       if(vdm->edges->first) {
-               struct VerseEdge *vedge;
-               struct VLayer *vert_vlayer = vdm->vertex_layer;
-               struct VerseVert *vvert, *vvert1, *vvert2;
-               int j;
-
-               /* 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;
+/* weight paint colors */
 
-               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;
-                       edge_r->bweight = 0;
-               }
-       }
-}
+/* 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.
+ */
 
-/* fill array of mfaces */
-void vDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
+void weight_to_rgb(float input, float *fr, float *fg, float *fb)
 {
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseFace *vface;
-       struct VerseVert *vvert;
-       int i;
+       float blend;
        
-       if(!vdm->vertex_layer || !vdm->polygon_layer) return;
+       blend= ((input/2.0f)+0.5f);
        
-       /* 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;
-
-       for(vface = vdm->polygon_layer->dl.lb.first; vface; vface = vface->next, ++face_r) {
-               face_r->mat_nr = 0;
-               face_r->flag = 0;
-
-               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;
-
-               test_index_face(face_r, NULL, 0, vface->vvert3?4:3);
+       if (input<=0.25f){      // blue->cyan
+               *fr= 0.0f;
+               *fg= blend*input*4.0f;
+               *fb= blend;
        }
-}
-
-/* return coordination of vertex with index */
-static void vDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseVert *vvert = NULL;
-
-       if(!vdm->vertex_layer) return;
-
-       vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index);
-       
-       if(vvert) {
-               VECCOPY(co_r, vdm->vertexCos ? vvert->cos : vvert->co);
+       else if (input<=0.50f){ // cyan->green
+               *fr= 0.0f;
+               *fg= blend;
+               *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
        }
-       else {
-               co_r[0] = co_r[1] = co_r[2] = 0.0;
+       else if (input<=0.75){  // green->yellow
+               *fr= blend * ((input-0.50f)*4.0f);
+               *fg= blend;
+               *fb= 0.0f;
        }
-}
-
-/* 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(!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;
+       else if (input<=1.0){ // yellow->red
+               *fr= blend;
+               *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
+               *fb= 0.0f;
        }
 }
 
-/* return normal of vertex with index */
-static void vDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
+static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col)
 {
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseVert *vvert = NULL;
-
-       if(!vdm->vertex_layer) return;
+       Mesh *me = ob->data;
+       float colf[4], input = 0.0f;
+       int i;
 
-       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;
+       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;            
        }
-}
 
-/* draw all VerseVertexes */
-static void vDM_drawVerts(DerivedMesh *dm)
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseVert *vvert;
-
-       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();
-}
-
-/* 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)
-{
-       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;
-
-               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();
-       }
-}
-
-/* verse spec doesn't support edges ... loose edges can't exist */
-void vDM_drawLooseEdges(DerivedMesh *dm)
-{
-}
-
-/* draw uv edges, not supported yet */
-static void vDM_drawUVEdges(DerivedMesh *dm)
-{
-}
-
-/* draw all VerseFaces */
-static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseFace *vface;
-
-       if(!vdm->polygon_layer) return;
-
-       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;
-       }
-}
-
-/* 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))
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseFace *vface;
-
-       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;
-       }
-}
-
-/* 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)
-{
-       VDerivedMesh *vdm = (VDerivedMesh*)dm;
-       struct VerseFace *vface;
-
-       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 void vDM_foreachMappedVert(
-               DerivedMesh *dm,
-               void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
-               void *userData)
-{
-}
-
-/**/
-static void vDM_foreachMappedEdge(
-               DerivedMesh *dm,
-               void (*func)(void *userData, int index, float *v0co, float *v1co),
-               void *userData)
-{
-}
-
-/**/
-static void vDM_foreachMappedFaceCenter(
-               DerivedMesh *dm,
-               void (*func)(void *userData, int index, float *cent, float *no),
-               void *userData)
-{
-}
-
-/**/
-static void vDM_drawMappedFacesTex(
-               DerivedMesh *dm,
-               int (*setDrawParams)(void *userData, int index),
-               void *userData)
-{
-}
-
-/**/
-static void vDM_drawMappedFaces(
-               DerivedMesh *dm,
-               int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
-               void *userData,
-               int useColors)
-{
-}
-
-/**/
-static void vDM_drawMappedEdges(
-               DerivedMesh *dm,
-               int (*setDrawOptions)(void *userData, int index),
-               void *userData)
-{
-}
-
-/**/
-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;
-
-       if (DM_release(dm)) {
-               if(vdm->vertexCos) MEM_freeN(vdm->vertexCos);
-               MEM_freeN(vdm);
-       }
-}
-
-/* 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");
-
-       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;
-
-       /* 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);
+       CLAMP(input, 0.0f, 1.0f);
        
-       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;
+       if(coba)
+               do_colorband(coba, input, colf);
+       else
+               weight_to_rgb(input, colf, colf+1, colf+2);
        
-       vdm->dm.foreachMappedVert = vDM_foreachMappedVert;
-       vdm->dm.foreachMappedEdge = vDM_foreachMappedEdge;
-       vdm->dm.foreachMappedFaceCenter = vDM_foreachMappedFaceCenter;
-
-       vdm->dm.getVertCos = vDM_getVertCos;
-       vdm->dm.getVertCo = vDM_getVertCo;
-       vdm->dm.getVertNo = vDM_getVertNo;
-
-       vdm->dm.drawVerts = vDM_drawVerts;
-
-       vdm->dm.drawEdges = vDM_drawEdges;
-       vdm->dm.drawLooseEdges = vDM_drawLooseEdges;
-       vdm->dm.drawUVEdges = vDM_drawUVEdges;
-
-       vdm->dm.drawFacesSolid = vDM_drawFacesSolid;
-       vdm->dm.drawFacesTex = vDM_drawFacesTex;
-       vdm->dm.drawFacesColored = vDM_drawFacesColored;
-
-       vdm->dm.drawMappedFacesTex = vDM_drawMappedFacesTex;
-       vdm->dm.drawMappedFaces = vDM_drawMappedFaces;
-       vdm->dm.drawMappedEdges = vDM_drawMappedEdges;
-       vdm->dm.drawMappedEdgesInterp = vDM_drawMappedEdgesInterp;
-
-       vdm->dm.release = vDM_release;
-
-       vdm->vertexCos = vertexCos;
-
-       return (DerivedMesh*) vdm;
-}
-
-#endif
-
-/***/
-
-DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
-{
-       Mesh *me = ob->data;
-       ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-       DerivedMesh *dm;
-
-       if (!(md->mode&eModifierMode_Realtime)) return NULL;
-       if (mti->isDisabled && mti->isDisabled(md)) return NULL;
-
-       if (mti->type==eModifierTypeType_OnlyDeform) {
-               int numVerts;
-               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 {
-               DerivedMesh *tdm = getMeshDerivedMesh(me, ob, NULL);
-               dm = mti->applyModifier(md, ob, tdm, 0, 0);
-
-               if(tdm != dm) tdm->release(tdm);
-       }
-
-       return dm;
+       col[3] = (unsigned char)(colf[0] * 255.0f);
+       col[2] = (unsigned char)(colf[1] * 255.0f);
+       col[1] = (unsigned char)(colf[2] * 255.0f);
+       col[0] = 255;
 }
 
-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(FACESEL_PAINT_TEST || 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 | CD_MASK_ORCO;
-                               }
-                               if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) {
-                                       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 ColorBand *stored_cb= NULL;
 
-static DerivedMesh *create_orco_dm(Object *ob, Mesh *me)
+void vDM_ColorBand_store(ColorBand *coba)
 {
-       DerivedMesh *dm;
-       float (*orco)[3];
-
-       dm= CDDM_from_mesh(me, ob);
-       orco= (float(*)[3])get_mesh_orco_verts(ob);
-       CDDM_apply_vert_coords(dm, orco);
-       CDDM_calc_normals(dm);
-       MEM_freeN(orco);
-
-       return dm;
+       stored_cb= coba;
 }
 
-static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
+static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm)
 {
-       float (*orco)[3], (*layerorco)[3];
-       int totvert;
-
-       totvert= dm->getNumVerts(dm);
-
-       if(orcodm) {
-               orco= MEM_callocN(sizeof(float)*3*totvert, "dm orco");
-
-               if(orcodm->getNumVerts(orcodm) == totvert)
-                       orcodm->getVertCos(orcodm, orco);
-               else
-                       dm->getVertCos(dm, orco);
-       }
-       else
-               orco= (float(*)[3])get_mesh_orco_verts(ob);
-
-       transform_mesh_orco_verts(ob->data, orco, totvert, 0);
-
-       if((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) {
-               memcpy(layerorco, orco, sizeof(float)*totvert);
-               MEM_freeN(orco);
+       Mesh *me = ob->data;
+       MFace *mf = me->mface;
+       ColorBand *coba= stored_cb;     /* warning, not a local var */
+       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, coba, mf->v1, &wtcol[(i*4 + 0)*4]); 
+               calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]); 
+               calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]); 
+               if (mf->v4)
+                       calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]); 
        }
-       else
-               DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
+       
+       CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData);
 }
 
-static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
+/* new value for useDeform -1  (hack for the gameengine):
+ * - apply only the modifier stack of the object, skipping the virtual modifiers,
+ * - don't apply the key
+ * - apply deform modifiers and input vertexco
+ */
+static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos)[3],
                                 DerivedMesh **deform_r, DerivedMesh **final_r,
                                 int useRenderParams, int useDeform,
-                                int needMapping, CustomDataMask dataMask)
+                                int needMapping, CustomDataMask dataMask, int index)
 {
        Mesh *me = ob->data;
        ModifierData *firstmd, *md;
@@ -1891,59 +1598,51 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
        float (*deformedVerts)[3] = NULL;
        DerivedMesh *dm, *orcodm, *finaldm;
        int numVerts = me->totvert;
-       int fluidsimMeshUsed = 0;
        int required_mode;
 
-       md = firstmd = modifiers_getVirtualModifierList(ob);
+       md = firstmd = (useDeform<0) ? ob->modifiers.first : modifiers_getVirtualModifierList(ob);
 
        modifiers_clearErrors(ob);
 
+       if(useRenderParams) required_mode = eModifierMode_Render;
+       else required_mode = eModifierMode_Realtime;
+
        /* we always want to keep original indices */
        dataMask |= CD_MASK_ORIGINDEX;
 
-       datamasks = modifiers_calcDataMasks(md, dataMask);
+       datamasks = modifiers_calcDataMasks(ob, md, dataMask, required_mode);
        curr = datamasks;
 
        if(deform_r) *deform_r = NULL;
        *final_r = NULL;
 
-       /* replace original mesh by fluidsim surface mesh for fluidsim
-        * domain objects
-        */
-       if((G.obedit!=ob) && !needMapping) {
-               if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
-                       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;
-
        if(useDeform) {
-               if(do_ob_key(ob)) /* shape key makes deform verts */
+               if(useDeform > 0 && do_ob_key(scene, ob)) /* shape key makes deform verts */
                        deformedVerts = mesh_getVertexCos(me, &numVerts);
+               else if(inputVertexCos)
+                       deformedVerts = inputVertexCos;
                
                /* Apply all leading deforming modifiers */
-               for(; md; md = md->next, curr = curr->next) {
+               for(;md; md = md->next, curr = curr->next) {
                        ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 
-                       if((md->mode & required_mode) != required_mode) continue;
-                       if(mti->isDisabled && mti->isDisabled(md)) continue;
+                       md->scene= scene;
+                       
+                       if(!modifier_isEnabled(md, required_mode)) continue;
+                       if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
 
                        if(mti->type == eModifierTypeType_OnlyDeform) {
                                if(!deformedVerts)
                                        deformedVerts = mesh_getVertexCos(me, &numVerts);
 
-                               mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
+                               mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, useRenderParams, useDeform);
                        } else {
                                break;
                        }
+                       
+                       /* grab modifiers until index i */
+                       if((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
+                               break;
                }
 
                /* Result of all leading deforming modifiers is cached for
@@ -1951,36 +1650,19 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                 * 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 {
-               if(!fluidsimMeshUsed) {
-                       /* default behaviour for meshes */
-                       if(inputVertexCos)
-                               deformedVerts = inputVertexCos;
-                       else
-                               deformedVerts = mesh_getRefKeyCos(me, &numVerts);
-               } else {
-                       /* the fluid sim mesh might have more vertices than the original 
-                        * one, so inputVertexCos shouldnt be used
-                        */
-                       deformedVerts = mesh_getVertexCos(me, &numVerts);
-               }
+               /* default behaviour for meshes */
+               if(inputVertexCos)
+                       deformedVerts = inputVertexCos;
+               else
+                       deformedVerts = mesh_getRefKeyCos(me, &numVerts);
        }
 
 
@@ -1990,30 +1672,25 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
        dm = NULL;
        orcodm = NULL;
 
-#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) {
+       for(;md; md = md->next, curr = curr->next) {
                ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 
-               if((md->mode & required_mode) != required_mode) continue;
+               md->scene= scene;
+               
+               if(!modifier_isEnabled(md, required_mode)) continue;
                if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue;
                if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
                        modifier_setError(md, "Modifier requires original data, bad stack position.");
                        continue;
                }
-               if(mti->isDisabled && mti->isDisabled(md)) continue;
                if(needMapping && !modifier_supportsMapping(md)) continue;
+               if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
 
                /* add an orco layer if needed by this modifier */
                if(dm && mti->requiredDataMask) {
-                       mask = mti->requiredDataMask(md);
+                       mask = mti->requiredDataMask(ob, md);
                        if(mask & CD_MASK_ORCO)
-                               add_orco_dm(ob, dm, orcodm);
+                               add_orco_dm(ob, NULL, dm, orcodm);
                }
 
                /* How to apply modifier depends on (a) what we already have as
@@ -2039,7 +1716,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                                }
                        }
 
-                       mti->deformVerts(md, ob, dm, deformedVerts, numVerts);
+                       mti->deformVerts(md, ob, dm, deformedVerts, numVerts, useRenderParams, useDeform);
                } else {
                        DerivedMesh *ndm;
 
@@ -2060,13 +1737,16 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                                        CDDM_apply_vert_coords(dm, deformedVerts);
                                        CDDM_calc_normals(dm);
                                }
+
+                               if(dataMask & CD_MASK_WEIGHT_MCOL)
+                                       add_weight_mcol_dm(ob, dm);
                        }
 
                        /* create an orco derivedmesh in parallel */
-                       mask= (CustomDataMask)curr->link;
+                       mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link);
                        if(mask & CD_MASK_ORCO) {
                                if(!orcodm)
-                                       orcodm= create_orco_dm(ob, me);
+                                       orcodm= create_orco_dm(ob, me, NULL);
 
                                mask &= ~CD_MASK_ORCO;
                                DM_set_only_copy(orcodm, mask);
@@ -2083,7 +1763,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                        DM_set_only_copy(dm, mask);
                        
                        /* add an origspace layer if needed */
-                       if(((CustomDataMask)curr->link) & CD_MASK_ORIGSPACE)
+                       if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE)
                                if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
                                        DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
 
@@ -2103,6 +1783,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                                }
                        } 
                }
+               
+               /* grab modifiers until index i */
+               if((index >= 0) && (modifiers_indexInObject(ob, md) >= index))
+                       break;
        }
 
        for(md=firstmd; md; md=md->next)
@@ -2119,34 +1803,29 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
 
                CDDM_apply_vert_coords(finaldm, deformedVerts);
                CDDM_calc_normals(finaldm);
+
+               if(dataMask & CD_MASK_WEIGHT_MCOL)
+                       add_weight_mcol_dm(ob, finaldm);
        } else if(dm) {
                finaldm = dm;
        } else {
-#ifdef WITH_VERSE
-               if(me->vnode)
-                       finaldm = derivedmesh_from_versemesh(me->vnode, deformedVerts);
-               else {
-                       finaldm = CDDM_from_mesh(me, ob);
-                       if(deformedVerts) {
-                               CDDM_apply_vert_coords(finaldm, deformedVerts);
-                               CDDM_calc_normals(finaldm);
-                       }
-               }
-#else
                finaldm = CDDM_from_mesh(me, ob);
+
                if(deformedVerts) {
                        CDDM_apply_vert_coords(finaldm, deformedVerts);
                        CDDM_calc_normals(finaldm);
                }
-#endif
+
+               if(dataMask & CD_MASK_WEIGHT_MCOL)
+                       add_weight_mcol_dm(ob, finaldm);
        }
 
        /* add an orco layer if needed */
        if(dataMask & CD_MASK_ORCO) {
-               add_orco_dm(ob, finaldm, orcodm);
+               add_orco_dm(ob, NULL, finaldm, orcodm);
 
                if(deform_r && *deform_r)
-                       add_orco_dm(ob, *deform_r, NULL);
+                       add_orco_dm(ob, NULL, *deform_r, NULL);
        }
 
        *final_r = finaldm;
@@ -2158,9 +1837,6 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
                MEM_freeN(deformedVerts);
 
        BLI_linklist_free(datamasks, NULL);
-
-       /* restore mesh in any case */
-       if(fluidsimMeshUsed) ob->data = ob->fluidsimSettings->orgMesh;
 }
 
 static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
@@ -2182,29 +1858,26 @@ static int editmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm)
        ModifierTypeInfo *mti = modifierType_getInfo(md->type);
        int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
 
-       if((md->mode & required_mode) != required_mode) return 0;
+       if(!modifier_isEnabled(md, required_mode)) return 0;
        if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
                modifier_setError(md, "Modifier requires original data, bad stack position.");
                return 0;
        }
-       if(mti->isDisabled && mti->isDisabled(md)) return 0;
-       if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0;
-       if(md->mode & eModifierMode_DisableTemporary) return 0;
        
        return 1;
 }
 
-static void editmesh_calc_modifiers(DerivedMesh **cage_r,
+static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, DerivedMesh **cage_r,
                                     DerivedMesh **final_r,
                                     CustomDataMask dataMask)
 {
-       Object *ob = G.obedit;
-       EditMesh *em = G.editMesh;
        ModifierData *md;
        float (*deformedVerts)[3] = NULL;
-       DerivedMesh *dm;
+       CustomDataMask mask;
+       DerivedMesh *dm, *orcodm = NULL;
        int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
        LinkNode *datamasks, *curr;
+       int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
 
        modifiers_clearErrors(ob);
 
@@ -2214,19 +1887,28 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
 
        dm = NULL;
        md = ob->modifiers.first;
-
+       
        /* we always want to keep original indices */
        dataMask |= CD_MASK_ORIGINDEX;
 
-       datamasks = modifiers_calcDataMasks(md, dataMask);
+       datamasks = modifiers_calcDataMasks(ob, md, dataMask, required_mode);
 
        curr = datamasks;
        for(i = 0; md; i++, md = md->next, curr = curr->next) {
                ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 
+               md->scene= scene;
+               
                if(!editmesh_modifier_is_enabled(md, dm))
                        continue;
 
+               /* add an orco layer if needed by this modifier */
+               if(dm && mti->requiredDataMask) {
+                       mask = mti->requiredDataMask(ob, md);
+                       if(mask & CD_MASK_ORCO)
+                               add_orco_dm(ob, em, dm, orcodm);
+               }
+
                /* 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.
@@ -2277,10 +1959,27 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
                                }
                        }
 
+                       /* create an orco derivedmesh in parallel */
+                       mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link);
+                       if(mask & CD_MASK_ORCO) {
+                               if(!orcodm)
+                                       orcodm= create_orco_dm(ob, ob->data, em);
+
+                               mask &= ~CD_MASK_ORCO;
+                               DM_set_only_copy(orcodm, mask);
+                               ndm = mti->applyModifierEM(md, ob, em, orcodm);
+
+                               if(ndm) {
+                                       /* if the modifier returned a new dm, release the old one */
+                                       if(orcodm && orcodm != ndm) orcodm->release(orcodm);
+                                       orcodm = ndm;
+                               }
+                       }
+
                        /* set the DerivedMesh to only copy needed data */
-                       DM_set_only_copy(dm, (CustomDataMask)curr->link);
+                       DM_set_only_copy(dm, (CustomDataMask)GET_INT_FROM_POINTER(curr->link));
 
-                       if(((CustomDataMask)curr->link) & CD_MASK_ORIGSPACE)
+                       if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE)
                                if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE))
                                        DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL);
                        
@@ -2335,98 +2034,15 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
                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, ColorBand *coba, int vert, unsigned char *col)
-{
-       Mesh *me = ob->data;
-       float colf[4], 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);
-       
-       if(coba)
-               do_colorband(coba, input, colf);
-       else
-               weight_to_rgb(input, colf, colf+1, colf+2);
-       
-       col[3] = (unsigned char)(colf[0] * 255.0f);
-       col[2] = (unsigned char)(colf[1] * 255.0f);
-       col[1] = (unsigned char)(colf[2] * 255.0f);
-       col[0] = 255;
-}
-
-static ColorBand *stored_cb= NULL;
+       /* add an orco layer if needed */
+       if(dataMask & CD_MASK_ORCO)
+               add_orco_dm(ob, em, *final_r, orcodm);
 
-void vDM_ColorBand_store(ColorBand *coba)
-{
-       stored_cb= coba;
-}
+       if(orcodm)
+               orcodm->release(orcodm);
 
-static unsigned char *calc_weightpaint_colors(Object *ob) 
-{
-       Mesh *me = ob->data;
-       MFace *mf = me->mface;
-       ColorBand *coba= stored_cb;     /* warning, not a local var */
-       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, coba, mf->v1, &wtcol[(i*4 + 0)*4]); 
-               calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]); 
-               calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]); 
-               if (mf->v4)
-                       calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]); 
-       }
-       
-       return wtcol;
+       if(deformedVerts)
+               MEM_freeN(deformedVerts);
 }
 
 static void clear_mesh_caches(Object *ob)
@@ -2457,59 +2073,38 @@ static void clear_mesh_caches(Object *ob)
        }
 }
 
-static void mesh_build_data(Object *ob, CustomDataMask dataMask)
+static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
 {
-       Mesh *me = ob->data;
+       Object *obact = scene->basact?scene->basact->object:NULL;
+       int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT);
+       int needMapping = editing && (ob==obact);
        float min[3], max[3];
-
+       
        clear_mesh_caches(ob);
 
-       if(ob!=G.obedit) {
-               Object *obact = G.scene->basact?G.scene->basact->object:NULL;
-               int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT);
-               int needMapping = editing && (ob==obact);
-
-               if( (G.f & G_WEIGHTPAINT) && ob==obact ) {
-                       MCol *wpcol = (MCol*)calc_weightpaint_colors(ob);
-                       int layernum = CustomData_number_of_layers(&me->fdata, CD_MCOL);
+       mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
+                                               &ob->derivedFinal, 0, 1,
+                                               needMapping, dataMask, -1);
 
-                       /* 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);
-
-                       CustomData_free_layer_active(&me->fdata, CD_MCOL, me->totface);
-               } else {
-                       mesh_calc_modifiers(ob, NULL, &ob->derivedDeform,
-                                           &ob->derivedFinal, G.rendering, 1,
-                                           needMapping, dataMask);
-               }
+       INIT_MINMAX(min, max);
 
-               INIT_MINMAX(min, max);
+       ob->derivedFinal->getMinMax(ob->derivedFinal, min, max);
 
-               ob->derivedFinal->getMinMax(ob->derivedFinal, min, max);
+       if(!ob->bb)
+               ob->bb= MEM_callocN(sizeof(BoundBox), "bb");
+       boundbox_set_from_min_max(ob->bb, min, max);
 
-               if(!ob->bb)
-                       ob->bb= MEM_callocN(sizeof(BoundBox), "bb");
-               boundbox_set_from_min_max(ob->bb, min, max);
+       ob->derivedFinal->needsFree = 0;
+       ob->derivedDeform->needsFree = 0;
+       ob->lastDataMask = dataMask;
 
-               ob->derivedFinal->needsFree = 0;
-               ob->derivedDeform->needsFree = 0;
-               ob->lastDataMask = dataMask;
-       }
 }
 
-static void editmesh_build_data(CustomDataMask dataMask)
+static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask)
 {
        float min[3], max[3];
 
-       EditMesh *em = G.editMesh;
-
-       clear_mesh_caches(G.obedit);
+       clear_mesh_caches(obedit);
 
        if (em->derivedFinal) {
                if (em->derivedFinal!=em->derivedCage) {
@@ -2524,211 +2119,143 @@ static void editmesh_build_data(CustomDataMask dataMask)
                em->derivedCage = NULL;
        }
 
-       editmesh_calc_modifiers(&em->derivedCage, &em->derivedFinal, dataMask);
+       editmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask);
        em->lastDataMask = dataMask;
 
        INIT_MINMAX(min, max);
 
        em->derivedFinal->getMinMax(em->derivedFinal, min, max);
 
-       if(!G.obedit->bb)
-               G.obedit->bb= MEM_callocN(sizeof(BoundBox), "bb");
-       boundbox_set_from_min_max(G.obedit->bb, min, max);
+       if(!obedit->bb)
+               obedit->bb= MEM_callocN(sizeof(BoundBox), "bb");
+       boundbox_set_from_min_max(obedit->bb, min, max);
 
        em->derivedFinal->needsFree = 0;
        em->derivedCage->needsFree = 0;
 }
 
-void makeDerivedMesh(Object *ob, CustomDataMask dataMask)
+void makeDerivedMesh(Scene *scene, Object *ob, EditMesh *em, CustomDataMask dataMask)
 {
-       if (ob==G.obedit) {
-               editmesh_build_data(dataMask);
+       if (em) {
+               editmesh_build_data(scene, ob, em, dataMask);
        } else {
-               mesh_build_data(ob, dataMask);
+               mesh_build_data(scene, ob, dataMask);
        }
 }
 
 /***/
 
-DerivedMesh *mesh_get_derived_final(Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dataMask)
 {
        /* 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);
+               mesh_build_data(scene, ob, dataMask);
 
        return ob->derivedFinal;
 }
 
-DerivedMesh *mesh_get_derived_deform(Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask dataMask)
 {
        /* 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);
+               mesh_build_data(scene, ob, dataMask);
 
        return ob->derivedDeform;
 }
 
-/* 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 *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask dataMask)
 {
-       float *vert_copy= NULL;
-
-       if(me->mr && !(me->mr->flag & MULTIRES_NO_RENDER)) {
-               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], me->mr->verts[i].co);
-       
-               /* Goto the pin level for multires */
-               me->mr->newlvl= me->mr->pinlvl;
-               multires_set_level(ob, me, 1);
-       }
+       DerivedMesh *final;
        
-       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, CustomDataMask dataMask)
-{
-       if(me->mr && !(me->mr->flag & MULTIRES_NO_RENDER)) {
-               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;
-                       MVert *vertdup= NULL;
-                       int i;
-
-                       /* Copy the verts into the mesh */
-                       vertdup= (*dm)->dupVertArray(*dm);
-                       (*dm)->release(*dm);
-                       for(i=0; i<me->totvert; ++i)
-                               me->mvert[i]= vertdup[i];
-                       /* Free vertdup after use*/
-                       MEM_freeN(vertdup);
-                       /* Go to the render level */
-                       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);
-
-                       if(dataMask & CD_MASK_ORCO)
-                               add_orco_dm(ob, *dm, NULL);
-
-                       /* 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(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1);
+
+       return final;
 }
 
-/* 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 *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDataMask dataMask, int index)
 {
        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, dataMask);
+       mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index);
 
        return final;
 }
 
-DerivedMesh *mesh_create_derived_view(Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_create_derived_view(Scene *scene, Object *ob, CustomDataMask dataMask)
 {
        DerivedMesh *final;
 
-       mesh_calc_modifiers(ob, NULL, NULL, &final, 0, 1, 0, dataMask);
+       mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1);
 
        return final;
 }
 
-DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3],
+DerivedMesh *mesh_create_derived_no_deform(Scene *scene, Object *ob, float (*vertCos)[3],
                                            CustomDataMask dataMask)
 {
        DerivedMesh *final;
        
-       mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0, 0, dataMask);
+       mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1);
+
+       return final;
+}
+
+DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*vertCos)[3],
+                                            CustomDataMask dataMask)
+{
+       DerivedMesh *final;
+       
+       mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1);
 
        return final;
 }
 
-DerivedMesh *mesh_create_derived_no_deform_render(Object *ob,
+DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob,
                                                   float (*vertCos)[3],
                                                   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, vertCos, NULL, &final, 1, 0, 0, dataMask);
-       multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask);
+       mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1);
 
        return final;
 }
 
 /***/
 
-DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r,
+DerivedMesh *editmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, EditMesh *em, DerivedMesh **final_r,
                                                  CustomDataMask dataMask)
 {
        /* 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);
+       if(!em->derivedCage ||
+          (em->lastDataMask & dataMask) != dataMask)
+               editmesh_build_data(scene, obedit, em, dataMask);
 
-       *final_r = G.editMesh->derivedFinal;
-       return G.editMesh->derivedCage;
+       *final_r = em->derivedFinal;
+       return em->derivedCage;
 }
 
-DerivedMesh *editmesh_get_derived_cage(CustomDataMask dataMask)
+DerivedMesh *editmesh_get_derived_cage(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask)
 {
        /* 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);
+       if(!em->derivedCage ||
+          (em->lastDataMask & dataMask) != dataMask)
+               editmesh_build_data(scene, obedit, em, dataMask);
 
-       return G.editMesh->derivedCage;
+       return em->derivedCage;
 }
 
-DerivedMesh *editmesh_get_derived_base(void)
+DerivedMesh *editmesh_get_derived_base(Object *obedit, EditMesh *em)
 {
-       return getEditMeshDerivedMesh(G.editMesh, G.obedit, NULL);
+       return getEditMeshDerivedMesh(em, obedit, NULL);
 }
 
 
@@ -2758,7 +2285,7 @@ static void make_vertexcosnos__mapFunc(void *userData, int index, float *co, flo
 /* 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)
+float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
 {
        Mesh *me= ob->data;
        DerivedMesh *dm;
@@ -2768,7 +2295,7 @@ float *mesh_get_mapped_verts_nors(Object *ob)
        if(ob->type!=OB_MESH || me->totvert==0)
                return NULL;
        
-       dm= mesh_get_derived_final(ob, CD_MASK_BAREMESH);
+       dm= mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
        vertexcosnos= MEM_callocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
        
        if(dm->foreachMappedVert) {
@@ -2790,10 +2317,8 @@ float *mesh_get_mapped_verts_nors(Object *ob)
 
 /* ********* crazyspace *************** */
 
-int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**deformcos)[3])
+int editmesh_get_first_deform_matrices(Object *ob, EditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3])
 {
-       Object *ob = G.obedit;
-       EditMesh *em = G.editMesh;
        ModifierData *md;
        DerivedMesh *dm;
        int i, a, numleft = 0, numVerts = 0;
@@ -2844,582 +2369,211 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo
        return numleft;
 }
 
-/* ************************* fluidsim bobj file handling **************************** */
-
-#ifndef DISABLE_ELBEEM
-
-#ifdef WIN32
-#ifndef snprintf
-#define snprintf _snprintf
-#endif
-#endif
+/* ******************* GLSL ******************** */
 
-/* write .bobj.gz file for a mesh object */
-void writeBobjgz(char *filename, struct Object *ob, int useGlobalCoords, int append, float time) 
+void DM_add_tangent_layer(DerivedMesh *dm)
 {
-       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);
-       }
+       /* mesh vars */
+       MTFace *mtface, *tf;
+       MFace *mface, *mf;
+       MVert *mvert, *v1, *v2, *v3, *v4;
+       MemArena *arena= NULL;
+       VertexTangent **vtangents= NULL;
+       float (*orco)[3]= NULL, (*tangent)[3];
+       float *uv1, *uv2, *uv3, *uv4, *vtang;
+       float fno[3], tang[3], uv[4][2];
+       int i, j, len, mf_vi[4], totvert, totface;
 
-       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);
+       if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
                return;
-       }
 
-       dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
-       //dm = mesh_create_derived_no_deform(ob,NULL);
+       /* check we have all the needed layers */
+       totvert= dm->getNumVerts(dm);
+       totface= dm->getNumFaces(dm);
 
-       mvert = dm->getVertArray(dm);
-       mface = dm->getFaceArray(dm);
-       totvert = dm->getNumVerts(dm);
-       totface = dm->getNumFaces(dm);
+       mvert= dm->getVertArray(dm);
+       mface= dm->getFaceArray(dm);
+       mtface= dm->getFaceDataArray(dm, CD_MTFACE);
 
-       // write time value for appended anim mesh
-       if(append) {
-               gzwrite(gzf, &time, sizeof(time));
+       if(!mtface) {
+               orco= dm->getVertDataArray(dm, CD_ORCO);
+               if(!orco)
+                       return;
        }
-
-       // 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 )); 
+       
+       /* create tangent layer */
+       DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
+       tangent= DM_get_face_data_layer(dm, CD_TANGENT);
+       
+       /* allocate some space */
+       arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
+       BLI_memarena_use_calloc(arena);
+       vtangents= MEM_callocN(sizeof(VertexTangent*)*totvert, "VertexTangent");
+       
+       /* sum tangents at connected vertices */
+       for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) {
+               v1= &mvert[mf->v1];
+               v2= &mvert[mf->v2];
+               v3= &mvert[mf->v3];
+
+               if (mf->v4) {
+                       v4= &mvert[mf->v4];
+                       CalcNormFloat4(v4->co, v3->co, v2->co, v1->co, fno);
                }
-       }
-
-       // 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 )); 
+               else {
+                       v4= NULL;
+                       CalcNormFloat(v3->co, v2->co, v1->co, fno);
                }
-       }
-
-       // 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++; }
+               
+               if(mtface) {
+                       uv1= tf->uv[0];
+                       uv2= tf->uv[1];
+                       uv3= tf->uv[2];
+                       uv4= tf->uv[3];
                }
-               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
+               else {
+                       uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
+                       spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
+                       spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
+                       spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
+                       if(v4)
+                               spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
                }
-       }
-
-       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++;
+               
+               tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang);
+               sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
+               sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2);
+               sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
+               
+               if(mf->v4) {
+                       v4= &mvert[mf->v4];
+                       
+                       tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang);
+                       sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
+                       sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
+                       sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4);
                }
        }
-       *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);
+       
+       /* write tangent to layer */
+       for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) {
+               len= (mf->v4)? 4 : 3; 
+               
+               if(mtface) {
+                       uv1= tf->uv[0];
+                       uv2= tf->uv[1];
+                       uv3= tf->uv[2];
+                       uv4= tf->uv[3];
                }
-               //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
+               else {
+                       uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
+                       spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
+                       spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
+                       spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
+                       if(len==4)
+                               spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
                }
-       //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]);
+               
+               mf_vi[0]= mf->v1;
+               mf_vi[1]= mf->v2;
+               mf_vi[2]= mf->v3;
+               mf_vi[3]= mf->v4;
+               
+               for(j=0; j<len; j++) {
+                       vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]);
 
-       
-       /* 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;
+                       VECCOPY(tangent[j], vtang);
+                       Normalize(tangent[j]);
                }
        }
        
-       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);
+       BLI_memarena_free(arena);
+       MEM_freeN(vtangents);
 }
 
-
-/* ***************************** 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)
+void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs)
 {
-       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
+       CustomData *vdata, *fdata, *tfdata = NULL;
+       int a, b, layer;
 
-       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;
-       }
+       /* From the layers requested by the GLSL shader, figure out which ones are
+        * actually available for this derivedmesh, and retrieve the pointers */
 
-       // free old mesh, if there is one (todo, check if it's still valid?)
-       if(srcob->fluidsimSettings->meshSurface) {
-               Mesh *freeFsMesh = srcob->fluidsimSettings->meshSurface;
+       memset(attribs, 0, sizeof(DMVertexAttribs));
 
-               // 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);
-       BLI_convertstringframe(targetDir, curFrame); // fixed #frame-no 
-       
-       strcpy(targetFile,targetDir);
-       strcat(targetFile, ".bobj.gz");
+       vdata = &dm->vertData;
+       fdata = &dm->faceData;
 
-       snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile);  // debug
-       elbeemDebugOut(debugStrBuffer); // debug
+       /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we
+        * can use offsets instead */
+       if(dm->release == emDM_release)
+               tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata;
+       else
+               tfdata = fdata;
+
+       /* add a tangent layer if necessary */
+       for(b = 0; b < gattribs->totlayer; b++)
+               if(gattribs->layer[b].type == CD_TANGENT)
+                       if(CustomData_get_layer_index(fdata, CD_TANGENT) == -1)
+                               DM_add_tangent_layer(dm);
+
+       for(b = 0; b < gattribs->totlayer; b++) {
+               if(gattribs->layer[b].type == CD_MTFACE) {
+                       /* uv coordinates */
+                       if(gattribs->layer[b].name[0])
+                               layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE,
+                                       gattribs->layer[b].name);
+                       else
+                               layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE);
 
-       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);
-                               }
+                       if(layer != -1) {
+                               a = attribs->tottface++;
+
+                               attribs->tface[a].array = tfdata->layers[layer].data;
+                               attribs->tface[a].emOffset = tfdata->layers[layer].offset;
+                               attribs->tface[a].glIndex = gattribs->layer[b].glindex;
                        }
                }
-               
-               // display org. object upon failure
-               srcob->data = srcob->fluidsimSettings->orgMesh;
-               return;
-       }
+               else if(gattribs->layer[b].type == CD_MCOL) {
+                       /* vertex colors */
+                       if(gattribs->layer[b].name[0])
+                               layer = CustomData_get_named_layer_index(tfdata, CD_MCOL,
+                                       gattribs->layer[b].name);
+                       else
+                               layer = CustomData_get_active_layer_index(tfdata, CD_MCOL);
 
-       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);
+                       if(layer != -1) {
+                               a = attribs->totmcol++;
 
-       // 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.; }} 
-       }
+                               attribs->mcol[a].array = tfdata->layers[layer].data;
+                               attribs->mcol[a].emOffset = tfdata->layers[layer].offset;
+                               attribs->mcol[a].glIndex = gattribs->layer[b].glindex;
+                       }
+               }
+               else if(gattribs->layer[b].type == CD_TANGENT) {
+                       /* tangents */
+                       layer = CustomData_get_layer_index(fdata, CD_TANGENT);
 
-       //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;
-}
+                       if(layer != -1) {
+                               attribs->tottang = 1;
 
-/* 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]; 
+                               attribs->tang.array = fdata->layers[layer].data;
+                               attribs->tang.emOffset = fdata->layers[layer].offset;
+                               attribs->tang.glIndex = gattribs->layer[b].glindex;
+                       }
                }
+               else if(gattribs->layer[b].type == CD_ORCO) {
+                       /* original coordinates */
+                       layer = CustomData_get_layer_index(vdata, CD_ORCO);
 
-               newmesh->totface = 6;
-               if(!newmesh->mface)
-                       newmesh->mface = CustomData_add_layer(&newmesh->fdata, CD_MFACE, CD_CALLOC, NULL, newmesh->totface);
+                       if(layer != -1) {
+                               attribs->totorco = 1;
 
-               *bbmesh = newmesh;
+                               attribs->orco.array = vdata->layers[layer].data;
+                               attribs->orco.emOffset = vdata->layers[layer].offset;
+                               attribs->orco.glIndex = gattribs->layer[b].glindex;
+                       }
+               }
        }
 }
 
-#else // DISABLE_ELBEEM
-
-/* dummy for mesh_calc_modifiers */
-void loadFluidsimMesh(Object *srcob, int useRenderParams) {
-}
-
-#endif // DISABLE_ELBEEM
-