part 1 of cleaning up my little array macro library to be a formal API. also removed...
[blender.git] / source / blender / blenkernel / intern / editderivedbmesh.c
index 6f9ddd576becc2df7ba88414739597d5e3f5d9c7..6aca8d51bc26032e2cc8d2d3ed2b277e9ebe0584 100644 (file)
@@ -59,6 +59,8 @@
 #include "BLI_linklist.h"
 #include "BLI_memarena.h"
 #include "BLI_scanfill.h"
+#include "BLI_ghash.h"
+#include "BLI_array.h"
 
 #include "BKE_cdderivedmesh.h"
 #include "BKE_customdata.h"
@@ -119,95 +121,158 @@ BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
        return tm2;
 }
 
-void BMEdit_RecalcTesselation(BMEditMesh *tm)
+static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm)
 {
        BMesh *bm = tm->bm;
        BMLoop **looptris = NULL;
-       V_DYNDECLARE(looptris);
+       BLI_array_declare(looptris);
        BMIter iter, liter;
        BMFace *f;
        BMLoop *l;
-       int i = 0, j;
+       int i = 0, j, a, b;
        
        if (tm->looptris) MEM_freeN(tm->looptris);
 
+#if 0 //simple quad/triangle code for performance testing purposes
+       looptris = MEM_callocN(sizeof(void*)*bm->totface*8, "looptris");
+
        f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
        for ( ; f; f=BMIter_Step(&iter)) {
+               EditVert *v, *lastv=NULL, *firstv=NULL;
+               EditEdge *e;
+               EditFace *efa;
+
                /*don't consider two-edged faces*/
                if (f->len < 3) continue;
                
-               if (f->len <= 4) {
-                       /*triangle fan for quads.  should be recoded to
-                         just add one tri for tris, and two for quads,
-                         but this code works for now too.*/
-                       l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
-                       for (; l; l=BMIter_Step(&liter)) {
-                               if (l == f->loopbase) continue;
-                               if ((BMLoop*)l->head.next == f->loopbase) continue;
-
-                               V_GROW(looptris);
-                               V_GROW(looptris);
-                               V_GROW(looptris);
-
-                               looptris[i*3] = l;
-                               looptris[i*3+1] = (BMLoop*)l->head.next;
-                               looptris[i*3+2] = f->loopbase;
-
-                               i += 1;
-                       }
-               } else {
-                       /*scanfill time*/
-                       EditVert *v, *lastv=NULL, *firstv=NULL;
-                       EditEdge *e;
-                       EditFace *efa;
-
-                       l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
-                       for (j=0; l; l=BMIter_Step(&liter), j++) {
-                               /*mark order*/
-                               l->head.eflag2 = j;
-
-                               v = BLI_addfillvert(l->v->co);
-                               v->tmp.p = l;
-                               
-                               if (lastv) {
-                                       e = BLI_addfilledge(lastv, v);
-                               }
+               //BLI_array_growone(looptris);
+               //BLI_array_growone(looptris);
+               //BLI_array_growone(looptris);
 
-                               lastv = v;
-                               if (firstv==NULL) firstv = v;
+               looptris[i*3] = f->loopbase;
+               looptris[i*3+1] = f->loopbase->head.next;
+               looptris[i*3+2] = f->loopbase->head.next->next;
+               i++;
+
+               if (f->len > 3) {
+                       //BLI_array_growone(looptris);
+                       //BLI_array_growone(looptris);
+                       //BLI_array_growone(looptris);
+
+                       looptris[i*3] = f->loopbase;
+                       looptris[i*3+1] = f->loopbase->head.next->next;
+                       looptris[i*3+2] = f->loopbase->head.next->next->next;
+                       i++;
+               }
+
+       }
+
+       tm->tottri = i;
+       tm->looptris = looptris;
+       return;
+#endif
+
+       f = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
+       for ( ; f; f=BMIter_Step(&iter)) {
+               EditVert *v, *lastv=NULL, *firstv=NULL;
+               EditEdge *e;
+               EditFace *efa;
+
+               /*don't consider two-edged faces*/
+               if (f->len < 3) continue;
+               
+               /*scanfill time*/
+               l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
+               for (j=0; l; l=BMIter_Step(&liter), j++) {
+                       /*mark order*/
+                       l->head.eflag2 = j;
+
+                       v = BLI_addfillvert(l->v->co);
+                       v->tmp.p = l;
+                       
+                       if (lastv) {
+                               e = BLI_addfilledge(lastv, v);
                        }
 
-                       /*complete the loop*/
-                       BLI_addfilledge(firstv, v);
+                       lastv = v;
+                       if (firstv==NULL) firstv = v;
+               }
+
+               /*complete the loop*/
+               BLI_addfilledge(firstv, v);
+
+               BLI_edgefill(0, 0);
+               
+               for (efa = fillfacebase.first; efa; efa=efa->next) {
+                       BMLoop *l1, *l2, *l3;
 
-                       BLI_edgefill(0, 0);
+                       BLI_array_growone(looptris);
+                       BLI_array_growone(looptris);
+                       BLI_array_growone(looptris);
                        
-                       for (efa = fillfacebase.first; efa; efa=efa->next) {
-                               V_GROW(looptris);
-                               V_GROW(looptris);
-                               V_GROW(looptris);
-                               
-                               looptris[i*3] = efa->v1->tmp.p;
-                               looptris[i*3+1] = efa->v2->tmp.p;
-                               looptris[i*3+2] = efa->v3->tmp.p;
-
-                               if (looptris[i*3]->head.eflag2 > looptris[i*3+1]->head.eflag2);
-                                       SWAP(BMLoop*, looptris[i*3], looptris[i*3+1]);
-                               if (looptris[i*3+1]->head.eflag2 > looptris[i*3+2]->head.eflag2);
-                                       SWAP(BMLoop*, looptris[i*3+1], looptris[i*3+2]);
-                               if (looptris[i*3]->head.eflag2 > looptris[i*3+1]->head.eflag2);
-                                       SWAP(BMLoop*, looptris[i*3], looptris[i*3+1]);
-
-                               i += 1;
+                       looptris[i*3] = l1 = efa->v1->tmp.p;
+                       looptris[i*3+1] = l2 = efa->v2->tmp.p;
+                       looptris[i*3+2] = l3 = efa->v3->tmp.p;
+                       
+                       if (l1->head.eflag2 > l2->head.eflag2) {
+                               SWAP(BMLoop*, l1, l2);
+                       }
+                       if (l2->head.eflag2 > l3->head.eflag2) {
+                               SWAP(BMLoop*, l2, l3);
+                       }
+                       if (l1->head.eflag2 > l2->head.eflag2) {
+                               SWAP(BMLoop*, l1, l2);
                        }
-                       BLI_end_edgefill();
+                       
+                       looptris[i*3] = l1;
+                       looptris[i*3+1] = l2;
+                       looptris[i*3+2] = l3;
+
+                       i += 1;
                }
+
+               BLI_end_edgefill();
        }
 
        tm->tottri = i;
        tm->looptris = looptris;
 }
 
+void BMEdit_RecalcTesselation(BMEditMesh *tm)
+{
+       BMEdit_RecalcTesselation_intern(tm);
+
+       if (tm->derivedFinal && tm->derivedFinal == tm->derivedCage) {
+               if (tm->derivedFinal->recalcTesselation) 
+                       tm->derivedFinal->recalcTesselation(tm->derivedFinal);
+       } else if (tm->derivedFinal) {
+               if (tm->derivedCage->recalcTesselation) 
+                       tm->derivedCage->recalcTesselation(tm->derivedCage);
+               if (tm->derivedFinal->recalcTesselation) 
+                       tm->derivedFinal->recalcTesselation(tm->derivedFinal);
+       }
+}
+
+void BMEdit_UpdateLinkedCustomData(BMEditMesh *em)
+{
+       BMesh *bm = em->bm;
+       int act;
+
+       if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
+               act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
+               CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
+
+               act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
+               CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
+
+               act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
+               CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
+
+               act = CustomData_get_mask_layer(&bm->pdata, CD_MTEXPOLY);
+               CustomData_set_layer_mask(&bm->ldata, CD_MLOOPUV, act);
+       }
+}
+
 /*does not free the BMEditMesh struct itself*/
 void BMEdit_Free(BMEditMesh *em)
 {
@@ -259,8 +324,84 @@ typedef struct EditDerivedBMesh {
        float (*vertexCos)[3];
        float (*vertexNos)[3];
        float (*faceNos)[3];
+
+       /*lookup caches; these are rebuilt on dm->RecalcTesselation()
+         (or when the derivedmesh is created, of course)*/
+       GHash *vhash, *ehash, *fhash;
+       BMVert **vtable;
+       BMEdge **etable;
+       BMFace **ftable;
+
+       /*private variables, for number of verts/edges/faces
+         within the above hash/table members*/
+       int tv, te, tf;
+
+       /*customdata layout of the tesselated faces*/
+       CustomData tessface_layout;
 } EditDerivedBMesh;
 
+static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm)
+{
+       BMIter iter;
+       BMHeader *h;
+       int a, i, iters[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+       
+       bmdm->tv = bmdm->tc->bm->totvert;
+       bmdm->te = bmdm->tc->bm->totedge;
+       bmdm->tf = bmdm->tc->bm->totface;
+
+       if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
+       if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
+       if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
+
+       bmdm->vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+       bmdm->ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+       bmdm->fhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+       
+       if (bmdm->vtable) MEM_freeN(bmdm->vtable);
+       if (bmdm->etable) MEM_freeN(bmdm->etable);
+       if (bmdm->ftable) MEM_freeN(bmdm->ftable);
+       
+       if (bmdm->tc->bm->totvert)
+               bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
+       else bmdm->vtable = NULL;
+
+       if (bmdm->tc->bm->totedge)
+               bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
+       else bmdm->etable = NULL;
+       
+       if (bmdm->tc->bm->totface)
+               bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "bmdm->ftable");
+       else bmdm->ftable = NULL;
+       
+       for (a=0; a<3; a++) {
+               h = BMIter_New(&iter, bmdm->tc->bm, iters[a], NULL);
+               for (i=0; h; h=BMIter_Step(&iter), i++) {
+                       switch (a) {
+                               case 0:
+                                       bmdm->vtable[i] = (BMVert*) h;
+                                       BLI_ghash_insert(bmdm->vhash, h, SET_INT_IN_POINTER(i));
+                                       break;
+                               case 1:
+                                       bmdm->etable[i] = (BMEdge*) h;
+                                       BLI_ghash_insert(bmdm->ehash, h, SET_INT_IN_POINTER(i));
+                                       break;
+                               case 2:
+                                       bmdm->ftable[i] = (BMFace*) h;
+                                       BLI_ghash_insert(bmdm->fhash, h, SET_INT_IN_POINTER(i));
+                                       break;
+
+                       }
+               }
+       }
+}
+
+static void bmDM_recalcTesselation(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+
+       //bmdm_recalc_lookups(bmdm);
+}
 
 static void bmDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
 {
@@ -319,7 +460,7 @@ static void bmDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *us
                BMIter viter;
 
                eve = BMIter_New(&viter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
-               for (i=0; eve; eve=BMIter_Step(&viter)) {
+               for (i=0; eve; eve=BMIter_Step(&viter), i++) {
                        BMINDEX_SET(eve, i);
                }
 
@@ -434,11 +575,19 @@ static void bmDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3],
        cent[0] = cent[1] = cent[2] = 0.0f;
        
        /*simple (and stupid) median (average) based method :/ */
-
-       l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
-       for (; l; l=BMIter_Step(&iter)) {
-               VECADD(cent, cent, l->v->co);
-               tot++;
+       
+       if (vertexCos) {
+               l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
+               for (; l; l=BMIter_Step(&iter)) {
+                       VECADD(cent, cent, vertexCos[BMINDEX_GET(l->v)]);
+                       tot++;
+               }
+       } else {
+               l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
+               for (; l; l=BMIter_Step(&iter)) {
+                       VECADD(cent, cent, l->v->co);
+                       tot++;
+               }
        }
 
        if (tot==0) return;
@@ -456,7 +605,7 @@ static void bmDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *use
 
        if (bmdm->vertexCos) {
                eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
-               for (i=0; eve; eve=BMIter_Step(&iter));
+               for (i=0; eve; eve=BMIter_Step(&iter), i++)
                        BMINDEX_SET(eve, i);
        }
 
@@ -478,7 +627,7 @@ static void bmDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
                BMVert *eve;
                
                eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
-               for (i=0; eve; eve=BMIter_Step(&iter))
+               for (i=0; eve; eve=BMIter_Step(&iter), i++)
                        BMINDEX_SET(eve, i);
 
                efa = BMIter_New(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
@@ -489,8 +638,8 @@ static void bmDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
                        BMLoop **l = bmdm->tc->looptris[i];
                        int drawSmooth;
                        
-                       drawSmooth = (efa->head.flag & BM_SMOOTH);
                        efa = l[0]->f;
+                       drawSmooth = (efa->head.flag & BM_SMOOTH);
 
                        draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BMINDEX_GET(efa), &drawSmooth);
                        if(draw) {
@@ -504,7 +653,7 @@ static void bmDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
                                glBegin(GL_TRIANGLES);
 
                                if (!drawSmooth) {
-                                       glNormal3fv(efa->no);
+                                       glNormal3fv(bmdm->faceNos[i]);
                                        glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[0]->v)]);
                                        glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[1]->v)]);
                                        glVertex3fv(bmdm->vertexCos[(int) BMINDEX_GET(l[2]->v)]);
@@ -532,7 +681,6 @@ static void bmDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
                        int drawSmooth;
 
                        efa = l[0]->f;
-
                        drawSmooth = (efa->head.flag & BM_SMOOTH);
                        
                        draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BMINDEX_GET(efa), &drawSmooth);
@@ -566,178 +714,210 @@ static void bmDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
        }
 }
 
+static void bmdm_get_tri_tex(BMesh *bm, BMLoop **ls, MLoopUV *luv[3], MLoopCol *lcol[3], 
+                            int has_uv, int has_col)
+{
+       if (has_uv) { 
+               luv[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPUV);
+               luv[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPUV);
+               luv[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPUV);
+       }
+
+       if (has_col) {
+               lcol[0] = CustomData_bmesh_get(&bm->ldata, ls[0]->head.data, CD_MLOOPCOL);
+               lcol[1] = CustomData_bmesh_get(&bm->ldata, ls[1]->head.data, CD_MLOOPCOL);
+               lcol[2] = CustomData_bmesh_get(&bm->ldata, ls[2]->head.data, CD_MLOOPCOL);
+       }
+
+
+}
+
 static void bmDM_drawFacesTex_common(DerivedMesh *dm,
-               int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
+               int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
                int (*drawParamsMapped)(void *userData, int index),
                void *userData) 
 {
-#if 0
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMEditMesh *em = bmdm->tc;
        BMesh *bm= bmdm->tc->bm;
        float (*vertexCos)[3]= bmdm->vertexCos;
        float (*vertexNos)[3]= bmdm->vertexNos;
        BMFace *efa;
+       BMVert *eve;
        BMIter iter;
-       int i;
+       MLoopUV *luv[3], dummyluv = {0};
+       MLoopCol *lcol[3], dummylcol = {0};
+       int i, has_vcol = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
+       int has_uv = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
+       
+       luv[0] = luv[1] = luv[2] = &dummyluv;
+       lcol[0] = lcol[1] = lcol[2] = &dummylcol;
+
+       dummylcol.a = dummylcol.r = dummylcol.g = dummylcol.b = 255;
 
        /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
        glShadeModel(GL_SMOOTH);
        
-       if (vertexCos) {
-               BMVert *eve;
+       i = 0;
+       BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL)
+               BMINDEX_SET(efa, i++);
 
-               for (i=0,eve=bm->verts.first; eve; eve= eve->next)
+       if (vertexCos) {
+               i = 0;
+               BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
                        BMINDEX_SET(eve, i++);
-
-               for (i=0,efa= bm->faces.first; efa; i++,efa= efa->next) {
-                       MTFace *tf= CustomData_bm_get(&bm->pdata, efa->data, CD_MTFACE);
-                       MCol *mcol= CustomData_bm_get(&bm->pdata, efa->data, CD_MCOL);
+                               
+               glBegin(GL_TRIANGLES);
+               for (i=0; i<em->tottri; i++) {
+                       BMLoop **ls = em->looptris[i];
+                       MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
+                       MTFace mtf = {0};
                        unsigned char *cp= NULL;
-                       int drawSmooth= (efa->flag & ME_SMOOTH);
+                       int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
                        int flag;
 
+                       efa = ls[0]->f;
+                       
+                       if (has_uv) {
+                               mtf.flag = tp->flag;
+                               mtf.tpage = tp->tpage;
+                               mtf.transp = tp->transp;
+                               mtf.mode = tp->mode;
+                               mtf.tile = tp->tile;
+                               mtf.unwrap = tp->unwrap;
+                       }
+
                        if(drawParams)
-                               flag= drawParams(tf, mcol, efa->mat_nr);
+                               flag= drawParams(&mtf, has_vcol, efa->mat_nr);
                        else if(drawParamsMapped)
-                               flag= drawParamsMapped(userData, i);
+                               flag= drawParamsMapped(userData, BMINDEX_GET(efa));
                        else
                                flag= 1;
 
                        if(flag != 0) { /* flag 0 == the face is hidden or invisible */
                                
                                /* we always want smooth here since otherwise vertex colors dont interpolate */
-                               if (mcol) {
-                                       if (flag==1) {
-                                               cp= (unsigned char*)mcol;
-                                       }
-                               } else {
+                               if (!has_vcol) {
                                        glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
                                } 
                                
-                               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
                                if (!drawSmooth) {
                                        glNormal3fv(bmdm->faceNos[i]);
-
-                                       if(tf) glTexCoord2fv(tf->uv[0]);
-                                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                                       glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
-
-                                       if(tf) glTexCoord2fv(tf->uv[1]);
-                                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                                       glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
-
-                                       if(tf) glTexCoord2fv(tf->uv[2]);
-                                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                                       glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
-
-                                       if(efa->v4) {
-                                               if(tf) glTexCoord2fv(tf->uv[3]);
-                                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                                               glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
-                                       }
+                                       
+                                       bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+                                       
+                                       glTexCoord2fv(luv[0]->uv);
+                                       glColor3ub(lcol[0]->r, lcol[0]->g, lcol[0]->b);
+                                       glVertex3fv(vertexCos[BMINDEX_GET(ls[0]->v)]);
+
+                                       glTexCoord2fv(luv[1]->uv);
+                                       glColor3ub(lcol[1]->r, lcol[1]->g, lcol[1]->b);
+                                       glVertex3fv(vertexCos[BMINDEX_GET(ls[1]->v)]);
+
+                                       glTexCoord2fv(luv[2]->uv);
+                                       glColor3ub(lcol[2]->r, lcol[2]->g, lcol[2]->b);
+                                       glVertex3fv(vertexCos[BMINDEX_GET(ls[2]->v)]);
                                } else {
-                                       if(tf) glTexCoord2fv(tf->uv[0]);
-                                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                                       glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
-                                       glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
-
-                                       if(tf) glTexCoord2fv(tf->uv[1]);
-                                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                                       glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
-                                       glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
-
-                                       if(tf) glTexCoord2fv(tf->uv[2]);
-                                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                                       glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
-                                       glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
-
-                                       if(efa->v4) {
-                                               if(tf) glTexCoord2fv(tf->uv[3]);
-                                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                                               glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
-                                               glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
-                                       }
+                                       bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+                                       
+                                       glTexCoord2fv(luv[0]->uv);
+                                       glColor3ub(lcol[0]->r, lcol[0]->g, lcol[0]->b);
+                                       glNormal3fv(vertexNos[BMINDEX_GET(ls[0]->v)]);
+                                       glVertex3fv(vertexCos[BMINDEX_GET(ls[0]->v)]);
+
+                                       glTexCoord2fv(luv[1]->uv);
+                                       glColor3ub(lcol[1]->r, lcol[1]->g, lcol[1]->b);
+                                       glNormal3fv(vertexNos[BMINDEX_GET(ls[1]->v)]);
+                                       glVertex3fv(vertexCos[BMINDEX_GET(ls[1]->v)]);
+
+                                       glTexCoord2fv(luv[2]->uv);
+                                       glColor3ub(lcol[2]->r, lcol[2]->g, lcol[2]->b);
+                                       glNormal3fv(vertexNos[BMINDEX_GET(ls[2]->v)]);
+                                       glVertex3fv(vertexCos[BMINDEX_GET(ls[2]->v)]);
                                }
-                               glEnd();
                        }
                }
+               glEnd();
        } else {
-               for (i=0,efa= bm->faces.first; efa; i++,efa= efa->next) {
-                       MTFace *tf= CustomData_bm_get(&bm->pdata, efa->data, CD_MTFACE);
-                       MCol *mcol= CustomData_bm_get(&bm->pdata, efa->data, CD_MCOL);
+               i = 0;
+               BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+                       BMINDEX_SET(eve, i++);
+                               
+               for (i=0; i<em->tottri; i++) {
+                       BMLoop **ls = em->looptris[i];
+                       MTexPoly *tp= CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY);
+                       MTFace mtf = {0};
                        unsigned char *cp= NULL;
-                       int drawSmooth= (efa->flag & ME_SMOOTH);
+                       int drawSmooth= BM_TestHFlag(ls[0]->f, BM_SMOOTH);
                        int flag;
 
+                       efa = ls[0]->f;
+                       
+                       if (has_uv) {
+                               mtf.flag = tp->flag;
+                               mtf.tpage = tp->tpage;
+                               mtf.transp = tp->transp;
+                               mtf.mode = tp->mode;
+                               mtf.tile = tp->tile;
+                               mtf.unwrap = tp->unwrap;
+                       }
+
                        if(drawParams)
-                               flag= drawParams(tf, mcol, efa->mat_nr);
+                               flag= drawParams(&mtf, has_vcol, efa->mat_nr);
                        else if(drawParamsMapped)
-                               flag= drawParamsMapped(userData, i);
+                               flag= drawParamsMapped(userData, BMINDEX_GET(efa));
                        else
                                flag= 1;
 
                        if(flag != 0) { /* flag 0 == the face is hidden or invisible */
+                               
                                /* we always want smooth here since otherwise vertex colors dont interpolate */
-                               if (mcol) {
-                                       if (flag==1) {
-                                               cp= (unsigned char*)mcol;
-                                       }
-                               } else {
+                               if (!has_vcol) {
                                        glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
                                } 
-
-                               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+                               
+                               glBegin(GL_TRIANGLES);
                                if (!drawSmooth) {
-                                       glNormal3fv(efa->n);
-
-                                       if(tf) glTexCoord2fv(tf->uv[0]);
-                                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                                       glVertex3fv(efa->v1->co);
-
-                                       if(tf) glTexCoord2fv(tf->uv[1]);
-                                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                                       glVertex3fv(efa->v2->co);
-
-                                       if(tf) glTexCoord2fv(tf->uv[2]);
-                                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                                       glVertex3fv(efa->v3->co);
-
-                                       if(efa->v4) {
-                                               if(tf) glTexCoord2fv(tf->uv[3]);
-                                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                                               glVertex3fv(efa->v4->co);
-                                       }
+                                       glNormal3fv(efa->no);
+                                       
+                                       bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+                                       
+                                       glTexCoord2fv(luv[0]->uv);
+                                       glColor3ub(lcol[0]->r, lcol[0]->g, lcol[0]->b);
+                                       glVertex3fv(ls[0]->v->co);
+
+                                       glTexCoord2fv(luv[1]->uv);
+                                       glColor3ub(lcol[1]->r, lcol[1]->g, lcol[1]->b);
+                                       glVertex3fv(ls[1]->v->co);
+
+                                       glTexCoord2fv(luv[2]->uv);
+                                       glColor3ub(lcol[2]->r, lcol[2]->g, lcol[2]->b);
+                                       glVertex3fv(ls[2]->v->co);
                                } else {
-                                       if(tf) glTexCoord2fv(tf->uv[0]);
-                                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                                       glNormal3fv(efa->v1->no);
-                                       glVertex3fv(efa->v1->co);
-
-                                       if(tf) glTexCoord2fv(tf->uv[1]);
-                                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                                       glNormal3fv(efa->v2->no);
-                                       glVertex3fv(efa->v2->co);
-
-                                       if(tf) glTexCoord2fv(tf->uv[2]);
-                                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                                       glNormal3fv(efa->v3->no);
-                                       glVertex3fv(efa->v3->co);
-
-                                       if(efa->v4) {
-                                               if(tf) glTexCoord2fv(tf->uv[3]);
-                                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                                               glNormal3fv(efa->v4->no);
-                                               glVertex3fv(efa->v4->co);
-                                       }
+                                       bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
+                                       
+                                       glTexCoord2fv(luv[0]->uv);
+                                       glColor3ub(lcol[0]->r, lcol[0]->g, lcol[0]->b);
+                                       glNormal3fv(ls[0]->v->no);
+                                       glVertex3fv(ls[0]->v->co);
+
+                                       glTexCoord2fv(luv[1]->uv);
+                                       glColor3ub(lcol[1]->r, lcol[1]->g, lcol[1]->b);
+                                       glNormal3fv(ls[1]->v->no);
+                                       glVertex3fv(ls[1]->v->co);
+
+                                       glTexCoord2fv(luv[2]->uv);
+                                       glColor3ub(lcol[2]->r, lcol[2]->g, lcol[2]->b);
+                                       glNormal3fv(ls[2]->v->no);
+                                       glVertex3fv(ls[2]->v->co);
                                }
                                glEnd();
                        }
                }
        }
-#endif
 }
 
-static void bmDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
+static void bmDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
 {
        bmDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
 }
@@ -946,6 +1126,13 @@ static int bmDM_getNumTessFaces(DerivedMesh *dm)
        return bmdm->tc->tottri;
 }
 
+static int bmDM_getNumFaces(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       
+       return bmdm->tc->bm->totface;
+}
+
 static int bmvert_to_mvert(BMVert *ev, MVert *vert_r)
 {
        VECCOPY(vert_r->co, ev->co);
@@ -966,14 +1153,12 @@ static void bmDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
        BMIter iter;
        int i;
 
-       ev = BMIter_New(&iter, ((EditDerivedBMesh *)dm)->tc->bm, BM_VERTS_OF_MESH, NULL);
-       for(i = 0; i < index; ++i) ev = BMIter_Step(&iter);
-
-       if (!ev) {
+       if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tv) {
                printf("error in bmDM_getVert.\n");
                return;
        }
 
+       ev = ((EditDerivedBMesh *)dm)->vtable[index];
        bmvert_to_mvert(ev, vert_r);
 }
 
@@ -986,8 +1171,12 @@ static void bmDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
        BMIter iter;
        int i;
 
-       e = BMIter_New(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
-       for(i = 0; i < index; ++i) e = BMIter_Step(&iter);
+       if (index < 0 || index >= ((EditDerivedBMesh *)dm)->te) {
+               printf("error in bmDM_getEdge.\n");
+               return;
+       }
+
+       e = bmdm->etable[index];
 
        edge_r->crease = (unsigned char) (e->crease*255.0f);
        edge_r->bweight = (unsigned char) (e->bweight*255.0f);
@@ -999,65 +1188,36 @@ static void bmDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
        if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
 #endif
        
-       /*gah, stupid O(n^2) behaviour.  should cache this or something,
-         I probably could put it in the TessCache structure. . .*/
-       v1 = e->v1;
-       v2 = e->v2;
-       ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
-       for(i = 0; v1 || v2; i++, ev = BMIter_Step(&iter)) {
-               if(ev == v1) {
-                       edge_r->v1 = i;
-                       v1 = NULL;
-               }
-               if(ev == v2) {
-                       edge_r->v2 = i;
-                       v2 = NULL;
-               }
-       }
+       edge_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v1));
+       edge_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, e->v2));
 }
 
-static void bmDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
+static void bmDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
 {
-       BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+       BMesh *bm = bmdm->tc->bm;
        BMFace *ef;
-       BMVert *ev, *v1, *v2, *v3;
        BMIter iter;
        BMLoop **l;
        int i;
        
+       if (index < 0 || index >= ((EditDerivedBMesh *)dm)->tf) {
+               printf("error in bmDM_getTessFace.\n");
+               return;
+       }
+
        l = ((EditDerivedBMesh *)dm)->tc->looptris[index];
 
        ef = l[0]->f;
 
        face_r->mat_nr = (unsigned char) ef->mat_nr;
-       //need to convert flags here!
        face_r->flag = BMFlags_To_MEFlags(ef);
 
-       /*while it's possible to store a cache to lookup these indices faster,
-         that would require going over the code and ensuring the cache is
-         always up to date.*/
-       v1 = l[0]->v;
-       v2 = l[1]->v;
-       v3 = l[2]->v;
+       face_r->v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[0]->v));
+       face_r->v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[1]->v));
+       face_r->v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(bmdm->vhash, l[2]->v));
        face_r->v4 = 0;
 
-       ev = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
-       for(i = 0, ev; v1 || v2 || v3;
-           i++, ev = BMIter_Step(&iter)) {
-               if(ev == v1) {
-                       face_r->v1 = i;
-                       v1 = NULL;
-               }
-               if(ev == v2) {
-                       face_r->v2 = i;
-                       v2 = NULL;
-               }
-               if(ev == v3) {
-                       face_r->v3 = i;
-                       v3 = NULL;
-               }
-       }
-
        test_index_face(face_r, NULL, 0, 3);
 }
 
@@ -1155,7 +1315,7 @@ static void *bmDM_getFaceDataArray(DerivedMesh *dm, int type)
        void *datalayer;
        int index, offset, size, i;
 
-       datalayer = DM_get_face_data_layer(dm, type);
+       datalayer = DM_get_tessface_data_layer(dm, type);
        if(datalayer)
                return datalayer;
 
@@ -1168,16 +1328,16 @@ static void *bmDM_getFaceDataArray(DerivedMesh *dm, int type)
                        offset = bm->pdata.layers[index].offset;
                        size = CustomData_sizeof(type);
 
-                       DM_add_face_layer(dm, type, CD_CALLOC, NULL);
+                       DM_add_tessface_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);
+                       data = datalayer = DM_get_tessface_data_layer(dm, type);
                        for (i=0; i<bmdm->tc->tottri; i++, data+=size) {
                                efa = bmdm->tc->looptris[i][0]->f;
-                               /*need to still add tface data, derived from the
-                                 loops.*/
-                               bmdata = CustomData_bmesh_get(&bm->pdata, efa->data, type);
+                               /*BMESH_TODO: need to still add tface data,
+                                 derived from the loops.*/
+                               bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
                                memcpy(data, bmdata, size);
                        }
                }
@@ -1215,6 +1375,8 @@ void bmDM_faceIterStep(void *self)
        iter->head.flags = BMFlags_To_MEFlags(iter->f);
        iter->head.index++;
 
+       iter->head.len = iter->f->len;
+
        iter->nextf = BMIter_Step(&iter->iter);
 
        if (!iter->nextf) iter->head.done = 1;
@@ -1225,24 +1387,24 @@ void *bmDM_getFaceCDData(void *self, int type, int layer)
        bmDM_faceIter *iter = self;
 
        if (layer == -1) 
-               return CustomData_bmesh_get(&iter->bm->pdata, iter->f->data, type);
-       else return CustomData_bmesh_get_n(&iter->bm->pdata, iter->f->data, type, layer);
+               return CustomData_bmesh_get(&iter->bm->pdata, iter->f->head.data, type);
+       else return CustomData_bmesh_get_n(&iter->bm->pdata, iter->f->head.data, type, layer);
 }
 
 void bmDM_loopIterStep(void *self)
 {
        bmDM_loopIter *iter = self;
 
-       iter->l = iter->nextl;
+       iter->l = BMIter_Step(&iter->iter);
+       if (!iter->l) {
+               iter->head.done = 1;
+               return;
+       }
 
        bmvert_to_mvert(iter->l->v, &iter->head.v);
        iter->head.index++;
        iter->head.vindex = BMINDEX_GET(iter->l->v);
        iter->head.eindex = BMINDEX_GET(iter->l->e);
-
-       iter->nextl = BMIter_Step(&iter->iter);
-
-       if (!iter->nextl) iter->head.done = 1;
 }
 
 void *bmDM_getLoopCDData(void *self, int type, int layer)
@@ -1250,8 +1412,8 @@ void *bmDM_getLoopCDData(void *self, int type, int layer)
        bmDM_loopIter *iter = self;
 
        if (layer == -1) 
-               return CustomData_bmesh_get(&iter->bm->ldata, iter->l->data, type);
-       else return CustomData_bmesh_get_n(&iter->bm->ldata, iter->l->data, type, layer);
+               return CustomData_bmesh_get(&iter->bm->ldata, iter->l->head.data, type);
+       else return CustomData_bmesh_get_n(&iter->bm->ldata, iter->l->head.data, type, layer);
 }
 
 void *bmDM_getVertCDData(void *self, int type, int layer)
@@ -1259,8 +1421,8 @@ void *bmDM_getVertCDData(void *self, int type, int layer)
        bmDM_loopIter *iter = self;
 
        if (layer == -1) 
-               return CustomData_bmesh_get(&iter->bm->vdata, iter->l->v->data, type);
-       else return CustomData_bmesh_get_n(&iter->bm->vdata, iter->l->v->data, type, layer);
+               return CustomData_bmesh_get(&iter->bm->vdata, iter->l->v->head.data, type);
+       else return CustomData_bmesh_get_n(&iter->bm->vdata, iter->l->v->head.data, type, layer);
 }
 
 void bmDM_iterFree(void *self)
@@ -1304,7 +1466,7 @@ static DMFaceIter *bmDM_getFaceIter(void *dm)
        int i;
 
        iter->bm = bmdm->tc->bm;
-       iter->f = BMIter_New(&iter->iter, iter->bm, BM_FACES_OF_MESH, NULL);
+       iter->f = iter->nextf = BMIter_New(&iter->iter, iter->bm, BM_FACES_OF_MESH, NULL);
        
        iter->head.step = bmDM_faceIterStep;
        iter->head.free = bmDM_iterFree;
@@ -1341,36 +1503,103 @@ static void bmDM_release(void *dm)
                        MEM_freeN(bmdm->faceNos);
                }
                
+               if (bmdm->fhash) BLI_ghash_free(bmdm->fhash, NULL, NULL);
+               if (bmdm->ehash) BLI_ghash_free(bmdm->ehash, NULL, NULL);
+               if (bmdm->vhash) BLI_ghash_free(bmdm->vhash, NULL, NULL);
+
+               if (bmdm->vtable) MEM_freeN(bmdm->vtable);
+               if (bmdm->etable) MEM_freeN(bmdm->etable);
+               if (bmdm->ftable) MEM_freeN(bmdm->ftable);
+               
                MEM_freeN(bmdm);
        }
 }
 
+CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+       return &bmdm->tc->bm->vdata;
+}
+
+CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+       return &bmdm->tc->bm->edata;
+}
+
+CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+       return &bmdm->tessface_layout;
+}
+
+CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+       return &bmdm->tc->bm->ldata;
+}
+
+CustomData *bmDm_getFaceDataLayout(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+       return &bmdm->tc->bm->pdata;
+}
+
+
 DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *ob,
                                            float (*vertexCos)[3])
 {
        EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), "bmdm");
        BMesh *bm = em->bm;
-
+       int i;
+       
        bmdm->tc = em;
 
        DM_init((DerivedMesh*)bmdm, em->bm->totvert, em->bm->totedge, em->tottri,
                 em->bm->totloop, em->bm->totface);
+       
+       for (i=0; i<bm->ldata.totlayer; i++) {
+               if (bm->ldata.layers[i].type == CD_MLOOPCOL) {
+                       CustomData_add_layer(&bmdm->tessface_layout, CD_MCOL, CD_ASSIGN, NULL, 0);
+               } else if (bm->ldata.layers[i].type == CD_MLOOPUV) {
+                       CustomData_add_layer(&bmdm->tessface_layout, CD_MTFACE, CD_ASSIGN, NULL, 0);
+               }
+       }
+
+       bmdm->dm.numVertData = bm->totvert;
+       bmdm->dm.numEdgeData = bm->totedge;
+       bmdm->dm.numFaceData = em->tottri;
+       bmdm->dm.numLoopData = bm->totloop;
+       bmdm->dm.numPolyData = bm->totface;
 
        bmdm->dm.getMinMax = bmDM_getMinMax;
 
+       bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
+       bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
+       bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
+       bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
+       bmdm->dm.getFaceDataLayout = bmDm_getFaceDataLayout;
+
        bmdm->dm.getNumVerts = bmDM_getNumVerts;
        bmdm->dm.getNumEdges = bmDM_getNumEdges;
        bmdm->dm.getNumTessFaces = bmDM_getNumTessFaces;
+       bmdm->dm.getNumFaces = bmDM_getNumFaces;
 
        bmdm->dm.getVert = bmDM_getVert;
        bmdm->dm.getEdge = bmDM_getEdge;
-       bmdm->dm.getTessFace = bmDM_getFace;
+       bmdm->dm.getTessFace = bmDM_getTessFace;
        bmdm->dm.copyVertArray = bmDM_copyVertArray;
        bmdm->dm.copyEdgeArray = bmDM_copyEdgeArray;
        bmdm->dm.copyTessFaceArray = bmDM_copyFaceArray;
        bmdm->dm.getTessFaceDataArray = bmDM_getFaceDataArray;
 
        bmdm->dm.newFaceIter = bmDM_getFaceIter;
+       bmdm->dm.recalcTesselation = bmDM_recalcTesselation;
 
        bmdm->dm.foreachMappedVert = bmDM_foreachMappedVert;
        bmdm->dm.foreachMappedEdge = bmDM_foreachMappedEdge;
@@ -1400,13 +1629,13 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *ob,
                eve = BMIter_New(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
                for (i=0; eve; eve=BMIter_Step(&iter), i++)
                        DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
-                                        CustomData_bmesh_get(&bm->vdata, eve->data, CD_MDEFORMVERT));
+                                        CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
        }
 
        if(vertexCos) {
                BMVert *eve;
                BMIter iter;
-               int totface = bm->totface;
+               int totface = bmdm->tc->tottri;
                int i;
                
                eve=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
@@ -1441,5 +1670,7 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *ob,
                }
        }
 
+       //bmdm_recalc_lookups(bmdm);
+
        return (DerivedMesh*) bmdm;
 }