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 2964914de4b6a2cd47098b6e0da0c6dd58cee3e8..6aca8d51bc26032e2cc8d2d3ed2b277e9ebe0584 100644 (file)
@@ -60,6 +60,7 @@
 #include "BLI_memarena.h"
 #include "BLI_scanfill.h"
 #include "BLI_ghash.h"
+#include "BLI_array.h"
 
 #include "BKE_cdderivedmesh.h"
 #include "BKE_customdata.h"
@@ -124,85 +125,113 @@ 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);
+               BLI_edgefill(0, 0);
+               
+               for (efa = fillfacebase.first; efa; efa=efa->next) {
+                       BMLoop *l1, *l2, *l3;
+
+                       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;
@@ -224,6 +253,26 @@ void BMEdit_RecalcTesselation(BMEditMesh *tm)
        }
 }
 
+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)
 {
@@ -286,6 +335,9 @@ typedef struct EditDerivedBMesh {
        /*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)
@@ -310,9 +362,17 @@ static void bmdm_recalc_lookups(EditDerivedBMesh *bmdm)
        if (bmdm->etable) MEM_freeN(bmdm->etable);
        if (bmdm->ftable) MEM_freeN(bmdm->ftable);
        
-       bmdm->vtable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totvert, "bmdm->vtable");
-       bmdm->etable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totedge, "bmdm->etable");
-       bmdm->ftable = MEM_mallocN(sizeof(void**)*bmdm->tc->bm->totface, "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);
@@ -340,8 +400,7 @@ static void bmDM_recalcTesselation(DerivedMesh *dm)
 {
        EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
-       BMEdit_RecalcTesselation_intern(bmdm->tc);
-       bmdm_recalc_lookups(bmdm);
+       //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)
@@ -401,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);
                }
 
@@ -516,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;
@@ -538,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);
        }
 
@@ -560,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);
@@ -571,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) {
@@ -586,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)]);
@@ -614,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);
@@ -648,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);
 }
@@ -1217,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;
 
@@ -1230,11 +1328,11 @@ 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;
                                /*BMESH_TODO: need to still add tface data,
@@ -1277,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;
@@ -1295,16 +1395,16 @@ 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)
@@ -1343,15 +1443,15 @@ DMLoopIter *bmDM_newLoopsIter(void *faceiter)
 
        iter->bm = fiter->bm;
        iter->f = fiter->f;
-       iter->nextl = BMIter_New(&iter->iter, iter->bm, BM_LOOPS_OF_FACE, iter->f);
+       iter->l = BMIter_New(&iter->iter, iter->bm, BM_LOOPS_OF_FACE, iter->f);
 
        iter->head.step = bmDM_loopIterStep;
        iter->head.getLoopCDData = bmDM_getLoopCDData;
        iter->head.getVertCDData = bmDM_getVertCDData;
 
-       bmvert_to_mvert(iter->nextl->v, &iter->head.v);
-       iter->head.vindex = BMINDEX_GET(iter->nextl->v);
-       iter->head.eindex = BMINDEX_GET(iter->nextl->e);
+       bmvert_to_mvert(iter->l->v, &iter->head.v);
+       iter->head.vindex = BMINDEX_GET(iter->l->v);
+       iter->head.eindex = BMINDEX_GET(iter->l->e);
 
        return (DMLoopIter*) iter;
 }
@@ -1403,23 +1503,88 @@ 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;
@@ -1470,7 +1635,7 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *ob,
        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);
@@ -1505,7 +1670,7 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, Object *ob,
                }
        }
 
-       bmdm_recalc_lookups(bmdm);
+       //bmdm_recalc_lookups(bmdm);
 
        return (DerivedMesh*) bmdm;
 }