svn merge ^/trunk/blender -r44213:44235 --- fixes bmesh shading bug [#30125]
[blender.git] / source / blender / blenkernel / intern / editderivedmesh.c
index 62f11eb263110d9a144c290bad4bf7a29a7326d0..ee06600dab68f423e813a9cded4c4e76051278c4 100644 (file)
  *  \ingroup bke
  */
 
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+
 #include "GL/glew.h"
 
 #include "BLI_utildefines.h"
 #include "GPU_extensions.h"
 #include "GPU_material.h"
 
-#include <string.h>
-#include <limits.h>
-#include <math.h>
+/* bmesh */
+#include "BKE_tessmesh.h"
+#include "BLI_array.h"
+#include "BLI_scanfill.h"
+
+#include "bmesh.h"
+/* end bmesh */
 
 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
 
+
+BMEditMesh *BMEdit_Create(BMesh *bm, int do_tesselate)
+{
+       BMEditMesh *tm = MEM_callocN(sizeof(BMEditMesh), __func__);
+
+       tm->bm = bm;
+       if (do_tesselate) {
+               BMEdit_RecalcTesselation(tm);
+       }
+
+       return tm;
+}
+
+BMEditMesh *BMEdit_Copy(BMEditMesh *tm)
+{
+       BMEditMesh *tm2 = MEM_callocN(sizeof(BMEditMesh), __func__);
+       *tm2 = *tm;
+
+       tm2->derivedCage = tm2->derivedFinal = NULL;
+
+       tm2->bm = BM_mesh_copy(tm->bm);
+
+       /*The tesselation is NOT calculated on the copy here,
+         because currently all the callers of this function use
+         it to make a backup copy of the BMEditMesh to restore
+         it in the case of errors in an operation. For perf
+         reasons, in that case it makes more sense to do the
+         tesselation only when/if that copy ends up getting
+         used.*/
+       tm2->looptris = NULL;
+
+       tm2->vert_index = NULL;
+       tm2->edge_index = NULL;
+       tm2->face_index = NULL;
+
+       return tm2;
+}
+
+static void BMEdit_RecalcTesselation_intern(BMEditMesh *tm)
+{
+       /* use this to avoid locking pthread for _every_ polygon
+        * and calling the fill function */
+#define USE_TESSFACE_SPEEDUP
+
+       BMesh *bm = tm->bm;
+       BMLoop *(*looptris)[3]= NULL;
+       BLI_array_declare(looptris);
+       BMIter iter, liter;
+       BMFace *f;
+       BMLoop *l;
+       int i = 0, j;
+
+#if 0
+       /* note, we could be clever and re-use this array but would need to ensure
+        * its realloced at some point, for now just free it */
+       if (tm->looptris) MEM_freeN(tm->looptris);
+
+       /* Use tm->tottri when set, this means no reallocs while transforming,
+        * (unless scanfill fails), otherwise... */
+       /* allocate the length of totfaces, avoid many small reallocs,
+        * if all faces are tri's it will be correct, quads == 2x allocs */
+       BLI_array_reserve(looptris, (tm->tottri && tm->tottri < bm->totface * 3) ? tm->tottri : bm->totface);
+#else
+
+       /* this means no reallocs for quad dominant models, for */
+       if ( (tm->looptris != NULL) &&
+            (tm->tottri != 0) &&
+            /* (totrti <= bm->totface * 2) would be fine for all quads,
+                 * but incase there are some ngons, still re-use the array */
+            (tm->tottri <= bm->totface * 3))
+       {
+               looptris = tm->looptris;
+       }
+       else {
+               if (tm->looptris) MEM_freeN(tm->looptris);
+               BLI_array_reserve(looptris, bm->totface);
+       }
+
+#endif
+
+       f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL);
+       for ( ; f; f=BM_iter_step(&iter)) {
+               /*don't consider two-edged faces*/
+               if (f->len < 3) {
+                       /* do nothing */
+               }
+
+#ifdef USE_TESSFACE_SPEEDUP
+
+               /* no need to ensure the loop order, we know its ok */
+
+               else if (f->len == 3) {
+                       BLI_array_growone(looptris);
+                       l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
+                       for (j=0; l; l=BM_iter_step(&liter), j++) {
+                               looptris[i][j] = l;
+                       }
+                       i += 1;
+               }
+               else if (f->len == 4) {
+                       BMLoop *ltmp[4];
+                       BLI_array_growitems(looptris, 2);
+
+                       l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
+                       for (j=0; l; l=BM_iter_step(&liter), j++) {
+                               ltmp[j] = l;
+                       }
+
+                       looptris[i][0] = ltmp[0];
+                       looptris[i][1] = ltmp[1];
+                       looptris[i][2] = ltmp[2];
+                       i += 1;
+
+                       looptris[i][0] = ltmp[0];
+                       looptris[i][1] = ltmp[2];
+                       looptris[i][2] = ltmp[3];
+                       i += 1;
+               }
+
+#endif /* USE_TESSFACE_SPEEDUP */
+
+               else {
+                       EditVert *v, *lastv=NULL, *firstv=NULL;
+                       EditEdge *e;
+                       EditFace *efa;
+                       int totfilltri;
+
+                       BLI_begin_edgefill();
+                       /*scanfill time*/
+                       l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f);
+                       for (j=0; l; l=BM_iter_step(&liter), j++) {
+                               /*mark order*/
+                               BM_elem_index_set(l, j); /* set_loop */
+
+                               v = BLI_addfillvert(l->v->co);
+                               v->tmp.p = l;
+
+                               if (lastv) {
+                                       e = BLI_addfilledge(lastv, v);
+                               }
+
+                               lastv = v;
+                               if (firstv==NULL) firstv = v;
+                       }
+
+                       /*complete the loop*/
+                       BLI_addfilledge(firstv, v);
+
+                       totfilltri = BLI_edgefill(2);
+                       BLI_array_growitems(looptris, totfilltri);
+
+                       for (efa = fillfacebase.first; efa; efa=efa->next) {
+                               BMLoop *l1= efa->v1->tmp.p;
+                               BMLoop *l2= efa->v2->tmp.p;
+                               BMLoop *l3= efa->v3->tmp.p;
+
+                               if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop*, l1, l2); }
+                               if (BM_elem_index_get(l2) > BM_elem_index_get(l3)) { SWAP(BMLoop*, l2, l3); }
+                               if (BM_elem_index_get(l1) > BM_elem_index_get(l2)) { SWAP(BMLoop*, l1, l2); }
+
+                               looptris[i][0] = l1;
+                               looptris[i][1] = l2;
+                               looptris[i][2] = l3;
+                               i += 1;
+                       }
+
+                       BLI_end_edgefill();
+               }
+       }
+
+       tm->tottri = i;
+       tm->looptris = looptris;
+
+#undef USE_TESSFACE_SPEEDUP
+
+}
+
+void BMEdit_RecalcTesselation(BMEditMesh *em)
+{
+       BMEdit_RecalcTesselation_intern(em);
+
+       /* commented because editbmesh_build_data() ensures we get tessfaces */
+#if 0
+       if (em->derivedFinal && em->derivedFinal == em->derivedCage) {
+               if (em->derivedFinal->recalcTesselation)
+                       em->derivedFinal->recalcTesselation(em->derivedFinal);
+       }
+       else if (em->derivedFinal) {
+               if (em->derivedCage->recalcTesselation)
+                       em->derivedCage->recalcTesselation(em->derivedCage);
+               if (em->derivedFinal->recalcTesselation)
+                       em->derivedFinal->recalcTesselation(em->derivedFinal);
+       }
+#endif
+}
+
+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_stencil_layer(&bm->pdata, CD_MTEXPOLY);
+               CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
+       }
+}
+
+/*does not free the BMEditMesh struct itself*/
+void BMEdit_Free(BMEditMesh *em)
+{
+       if (em->derivedFinal) {
+               if (em->derivedFinal!=em->derivedCage) {
+                       em->derivedFinal->needsFree= 1;
+                       em->derivedFinal->release(em->derivedFinal);
+               }
+               em->derivedFinal= NULL;
+       }
+       if (em->derivedCage) {
+               em->derivedCage->needsFree= 1;
+               em->derivedCage->release(em->derivedCage);
+               em->derivedCage= NULL;
+       }
+
+       if (em->looptris) MEM_freeN(em->looptris);
+
+       if (em->vert_index) MEM_freeN(em->vert_index);
+       if (em->edge_index) MEM_freeN(em->edge_index);
+       if (em->face_index) MEM_freeN(em->face_index);
+
+       if (em->bm)
+               BM_mesh_free(em->bm);
+}
+
+/*
+ok, basic design:
+
+the bmesh derivedmesh exposes the mesh as triangles.  it stores pointers
+to three loops per triangle.  the derivedmesh stores a cache of tesselations
+for each face.  this cache will smartly update as needed (though at first
+it'll simply be more brute force).  keeping track of face/edge counts may
+be a small problbm.
+
+this won't be the most efficient thing, considering that internal edges and
+faces of tesselations are exposed.  looking up an edge by index in particular
+is likely to be a little slow.
+*/
+
+typedef struct EditDerivedBMesh {
+       DerivedMesh dm;
+
+       Object *ob;
+       BMEditMesh *tc;
+
+       float (*vertexCos)[3];
+       float (*vertexNos)[3];
+       float (*polyNos)[3];
+
+       /* private variables, for number of verts/edges/faces
+        * within the above hash/table members*/
+       int tv, te, tf;
+} EditDerivedBMesh;
+
+static void emDM_calcNormals(DerivedMesh *UNUSED(dm))
+{
+       /* Nothing to do: normals are already calculated and stored on the
+          BMVerts and BMFaces */
+}
+
+static void emDM_recalcTesselation(DerivedMesh *UNUSED(dm))
+{
+       /* do nothing */
+}
+
 static void emDM_foreachMappedVert(
                DerivedMesh *dm,
                void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
                void *userData)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditVert *eve;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMVert *eve;
+       BMIter iter;
        int i;
 
-       for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
-               if (emdm->vertexCos) {
-                       func(userData, i, emdm->vertexCos[i], emdm->vertexNos[i], NULL);
+       eve = BM_iter_new(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+       for (i=0; eve; i++, eve=BM_iter_step(&iter)) {
+               if (bmdm->vertexCos) {
+                       func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
                }
                else {
                        func(userData, i, eve->co, eve->no, NULL);
@@ -84,20 +376,24 @@ static void emDM_foreachMappedEdge(
                void (*func)(void *userData, int index, float *v0co, float *v1co),
                void *userData)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditEdge *eed;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMEdge *eed;
+       BMIter iter;
        int i;
 
-       if (emdm->vertexCos) {
-               EditVert *eve;
+       if (bmdm->vertexCos) {
+
+               BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
 
-               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       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]);
+               eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+               for (i=0; eed; i++,eed=BM_iter_step(&iter))
+                       func(userData, i,
+                                bmdm->vertexCos[BM_elem_index_get(eed->v1)],
+                                bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
        }
        else {
-               for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
+               eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+               for (i=0; eed; i++,eed=BM_iter_step(&iter))
                        func(userData, i, eed->v1->co, eed->v2->co);
        }
 }
@@ -107,28 +403,29 @@ static void emDM_drawMappedEdges(
                int (*setDrawOptions)(void *userData, int index),
                void *userData)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditEdge *eed;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMEdge *eed;
+       BMIter iter;
        int i;
 
-       if (emdm->vertexCos) {
-               EditVert *eve;
+       if (bmdm->vertexCos) {
 
-               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (intptr_t) i++;
+               BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
 
                glBegin(GL_LINES);
-               for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
+               eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+               for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
                        if (!setDrawOptions || setDrawOptions(userData, i)) {
-                               glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]);
-                               glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]);
+                               glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
+                               glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
                        }
                }
                glEnd();
        }
        else {
                glBegin(GL_LINES);
-               for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
+               eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+               for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
                        if (!setDrawOptions || setDrawOptions(userData, i)) {
                                glVertex3fv(eed->v1->co);
                                glVertex3fv(eed->v2->co);
@@ -151,30 +448,31 @@ static void emDM_drawMappedEdgesInterp(
                void (*setDrawInterpOptions)(void *userData, int index, float t),
                void *userData)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditEdge *eed;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMEdge *eed;
+       BMIter iter;
        int i;
 
-       if (emdm->vertexCos) {
-               EditVert *eve;
+       if (bmdm->vertexCos) {
 
-               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (intptr_t) i++;
+               BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
 
                glBegin(GL_LINES);
-               for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
+               eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+               for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
                        if (!setDrawOptions || setDrawOptions(userData, i)) {
                                setDrawInterpOptions(userData, i, 0.0);
-                               glVertex3fv(emdm->vertexCos[(int) eed->v1->tmp.l]);
+                               glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]);
                                setDrawInterpOptions(userData, i, 1.0);
-                               glVertex3fv(emdm->vertexCos[(int) eed->v2->tmp.l]);
+                               glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]);
                        }
                }
                glEnd();
        }
        else {
                glBegin(GL_LINES);
-               for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
+               eed = BM_iter_new(&iter, bmdm->tc->bm, BM_EDGES_OF_MESH, NULL);
+               for (i=0; eed; i++,eed=BM_iter_step(&iter)) {
                        if (!setDrawOptions || setDrawOptions(userData, i)) {
                                setDrawInterpOptions(userData, i, 0.0);
                                glVertex3fv(eed->v1->co);
@@ -188,57 +486,69 @@ static void emDM_drawMappedEdgesInterp(
 
 static void emDM_drawUVEdges(DerivedMesh *dm)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditFace *efa;
-       MTFace *tf;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMEditMesh *em = bmdm->tc;
+       BMFace *efa;
+       BMIter iter;
 
        glBegin(GL_LINES);
-       for (efa= emdm->em->faces.first; efa; efa= efa->next) {
-               tf = CustomData_em_get(&emdm->em->fdata, efa->data, CD_MTFACE);
+       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+               BMIter liter;
+               BMLoop *l;
+               MLoopUV *lastluv = NULL, *firstluv = NULL;
 
-               if (tf && !(efa->h)) {
-                       glVertex2fv(tf->uv[0]);
-                       glVertex2fv(tf->uv[1]);
+               if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
+                       continue;
 
-                       glVertex2fv(tf->uv[1]);
-                       glVertex2fv(tf->uv[2]);
+               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                       MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
-                       if (!efa->v4) {
-                               glVertex2fv(tf->uv[2]);
-                               glVertex2fv(tf->uv[0]);
-                       }
-                       else {
-                               glVertex2fv(tf->uv[2]);
-                               glVertex2fv(tf->uv[3]);
-                               glVertex2fv(tf->uv[3]);
-                               glVertex2fv(tf->uv[0]);
+                       if (luv) {
+                               if (lastluv)
+                                       glVertex2fv(luv->uv);
+                               glVertex2fv(luv->uv);
+
+                               lastluv = luv;
+                               if (!firstluv)
+                                       firstluv = luv;
                        }
                }
+
+               if (lastluv) {
+                       glVertex2fv(lastluv->uv);
+                       glVertex2fv(firstluv->uv);
+               }
        }
        glEnd();
 }
 
-static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3])
+static void emDM__calcFaceCent(BMesh *bm, BMFace *efa, float cent[3], float (*vertexCos)[3])
 {
+       BMIter iter;
+       BMLoop *l;
+       int tot = 0;
+
+       zero_v3(cent);
+
+       /*simple (and stupid) median (average) based method :/ */
+
        if (vertexCos) {
-               copy_v3_v3(cent, vertexCos[(int) efa->v1->tmp.l]);
-               add_v3_v3(cent, vertexCos[(int) efa->v2->tmp.l]);
-               add_v3_v3(cent, vertexCos[(int) efa->v3->tmp.l]);
-               if (efa->v4) add_v3_v3(cent, vertexCos[(int) efa->v4->tmp.l]);
+               l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, efa);
+               for (; l; l=BM_iter_step(&iter)) {
+                       add_v3_v3(cent, vertexCos[BM_elem_index_get(l->v)]);
+                       tot++;
+               }
        }
        else {
-               copy_v3_v3(cent, efa->v1->co);
-               add_v3_v3(cent, efa->v2->co);
-               add_v3_v3(cent, efa->v3->co);
-               if (efa->v4) add_v3_v3(cent, efa->v4->co);
+               l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, efa);
+               for (; l; l=BM_iter_step(&iter)) {
+                       add_v3_v3(cent, l->v->co);
+                       tot++;
+               }
        }
 
-       if (efa->v4) {
-               mul_v3_fl(cent, 0.25f);
-       }
-       else {
-               mul_v3_fl(cent, 0.33333333333f);
-       }
+       if (tot==0) return;
+       mul_v3_fl(cent, 1.0f/(float)tot);
 }
 
 static void emDM_foreachMappedFaceCenter(
@@ -246,24 +556,28 @@ static void emDM_foreachMappedFaceCenter(
                void (*func)(void *userData, int index, float *co, float *no),
                void *userData)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditVert *eve;
-       EditFace *efa;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       float (*polyNos)[3] = NULL;
+       BMFace *efa;
+       BMIter iter;
        float cent[3];
        int i;
 
-       if (emdm->vertexCos) {
-               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (intptr_t) i++;
+       /* ensure for face center calculation */
+       if (bmdm->vertexCos) {
+               BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT);
+               polyNos = bmdm->polyNos;
+
+               BLI_assert(polyNos != NULL);
        }
 
-       for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
-               emDM__calcFaceCent(efa, cent, emdm->vertexCos);
-               func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n);
+       efa = BM_iter_new(&iter, bmdm->tc->bm, BM_FACES_OF_MESH, NULL);
+       for (i=0; efa; efa=BM_iter_step(&iter), i++) {
+               emDM__calcFaceCent(bmdm->tc->bm, efa, cent, bmdm->vertexCos);
+               func(userData, i, cent, polyNos ? polyNos[i] : efa->no);
        }
 }
 
-/* note, material function is ignored for now. */
 static void emDM_drawMappedFaces(
                DerivedMesh *dm,
                int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
@@ -271,8 +585,11 @@ static void emDM_drawMappedFaces(
                int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
                void *userData, int UNUSED(useColors))
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditFace *efa;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMFace *efa;
+       struct BMLoop *(*looptris)[3]= bmdm->tc->looptris;
+       const int tottri= bmdm->tc->tottri;
+       const int lasttri= tottri - 1; /* compare agasint this a lot */
        int i, draw, flush;
        const int skip_normals= !glIsEnabled(GL_LIGHTING); /* could be passed as an arg */
 
@@ -285,21 +602,25 @@ static void emDM_drawMappedFaces(
        /* currently unused -- each original face is handled separately */
        (void)compareDrawOptions;
 
-       if (emdm->vertexCos) {
+       if (bmdm->vertexCos) {
                /* add direct access */
-               float (*vertexCos)[3]= emdm->vertexCos;
-               float (*vertexNos)[3]= emdm->vertexNos;
-               float (*faceNos)[3]=   emdm->faceNos;
-               EditVert *eve;
+               float (*vertexCos)[3]= bmdm->vertexCos;
+               float (*vertexNos)[3]= bmdm->vertexNos;
+               float (*polyNos)[3]=   bmdm->polyNos;
+               // int *triPolyMap= bmdm->triPolyMap;
+
+               BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_VERT | BM_FACE);
 
-               for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (intptr_t) i++;
+               for (i=0; i < tottri; i++) {
+                       BMLoop **l = looptris[i];
+                       int drawSmooth;
 
-               for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
-                       int drawSmooth = (efa->flag & ME_SMOOTH);
-                       draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth);
+                       efa = l[0]->f;
+                       drawSmooth= BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
+
+                       draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_elem_index_get(efa), &drawSmooth);
                        if (draw) {
-                               const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES;
+                               const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
                                if (draw==2) { /* enabled with stipple */
 
                                        if (poly_prev != GL_ZERO) glEnd();
@@ -312,49 +633,43 @@ static void emDM_drawMappedFaces(
                                if (skip_normals) {
                                        if (poly_type != poly_prev) {
                                                if (poly_prev != GL_ZERO) glEnd();
-                                               glBegin((poly_prev= poly_type));
+                                               glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
                                        }
-                                       glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
-                                       glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
-                                       glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
-                                       if (poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
                                }
                                else {
                                        const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
                                        if (shade_type != shade_prev) {
                                                if (poly_prev != GL_ZERO) glEnd();
                                                glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
-                                               glBegin((poly_prev= poly_type));
+                                               glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
                                        }
-                                       else if (poly_type != poly_prev) {
+                                       if (poly_type != poly_prev) {
                                                if (poly_prev != GL_ZERO) glEnd();
-                                               glBegin((poly_prev= poly_type));
+                                               glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
                                        }
 
                                        if (!drawSmooth) {
-                                               glNormal3fv(faceNos[i]);
-                                               glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
-                                               glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
-                                               glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
-                                               if (poly_type == GL_QUADS) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
+                                               glNormal3fv(polyNos[BM_elem_index_get(efa)]);
+                                               glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
+                                               glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
+                                               glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
                                        }
                                        else {
-                                               glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
-                                               glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
-                                               glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
-                                               glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
-                                               glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
-                                               glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
-                                               if (poly_type == GL_QUADS) {
-                                                       glNormal3fv(vertexNos[(int) efa->v4->tmp.l]);
-                                                       glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
-                                               }
+                                               glNormal3fv(vertexNos[BM_elem_index_get(l[0]->v)]);
+                                               glVertex3fv(vertexCos[BM_elem_index_get(l[0]->v)]);
+                                               glNormal3fv(vertexNos[BM_elem_index_get(l[1]->v)]);
+                                               glVertex3fv(vertexCos[BM_elem_index_get(l[1]->v)]);
+                                               glNormal3fv(vertexNos[BM_elem_index_get(l[2]->v)]);
+                                               glVertex3fv(vertexCos[BM_elem_index_get(l[2]->v)]);
                                        }
                                }
 
                                flush= (draw==2);
-                               if (!skip_normals && !flush && efa->next)
-                                       flush|= efa->mat_nr != efa->next->mat_nr;
+                               if (!skip_normals && !flush && (i != lasttri))
+                                       flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
 
                                if (flush) {
                                        glEnd();
@@ -366,11 +681,18 @@ static void emDM_drawMappedFaces(
                }
        }
        else {
-               for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
-                       int drawSmooth = (efa->flag & ME_SMOOTH);
-                       draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, i, &drawSmooth);
+               BM_mesh_elem_index_ensure(bmdm->tc->bm, BM_FACE);
+
+               for (i=0; i < tottri; i++) {
+                       BMLoop **l = looptris[i];
+                       int drawSmooth;
+
+                       efa = l[0]->f;
+                       drawSmooth= BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
+
+                       draw = setDrawOptions==NULL ? 1 : setDrawOptions(userData, BM_elem_index_get(efa), &drawSmooth);
                        if (draw) {
-                               const GLenum poly_type= efa->v4 ? GL_QUADS:GL_TRIANGLES;
+                               const GLenum poly_type= GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */
                                if (draw==2) { /* enabled with stipple */
 
                                        if (poly_prev != GL_ZERO) glEnd();
@@ -383,49 +705,44 @@ static void emDM_drawMappedFaces(
                                if (skip_normals) {
                                        if (poly_type != poly_prev) {
                                                if (poly_prev != GL_ZERO) glEnd();
-                                               glBegin((poly_prev= poly_type));
+                                               glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
                                        }
-                                       glVertex3fv(efa->v1->co);
-                                       glVertex3fv(efa->v2->co);
-                                       glVertex3fv(efa->v3->co);
-                                       if (poly_type == GL_QUADS) glVertex3fv(efa->v4->co);
+                                       glVertex3fv(l[0]->v->co);
+                                       glVertex3fv(l[1]->v->co);
+                                       glVertex3fv(l[2]->v->co);
                                }
                                else {
                                        const GLenum shade_type= drawSmooth ? GL_SMOOTH : GL_FLAT;
                                        if (shade_type != shade_prev) {
                                                if (poly_prev != GL_ZERO) glEnd();
                                                glShadeModel((shade_prev= shade_type)); /* same as below but switch shading */
-                                               glBegin((poly_prev= poly_type));
+                                               glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
                                        }
-                                       else if (poly_type != poly_prev) {
+                                       if (poly_type != poly_prev) {
                                                if (poly_prev != GL_ZERO) glEnd();
-                                               glBegin((poly_prev= poly_type));
+                                               glBegin((poly_prev= poly_type)); /* BMesh: will always be GL_TRIANGLES */
                                        }
 
                                        if (!drawSmooth) {
-                                               glNormal3fv(efa->n);
-                                               glVertex3fv(efa->v1->co);
-                                               glVertex3fv(efa->v2->co);
-                                               glVertex3fv(efa->v3->co);
-                                               if (poly_type == GL_QUADS) glVertex3fv(efa->v4->co);
+                                               glNormal3fv(efa->no);
+                                               glVertex3fv(l[0]->v->co);
+                                               glVertex3fv(l[1]->v->co);
+                                               glVertex3fv(l[2]->v->co);
                                        }
                                        else {
-                                               glNormal3fv(efa->v1->no);
-                                               glVertex3fv(efa->v1->co);
-                                               glNormal3fv(efa->v2->no);
-                                               glVertex3fv(efa->v2->co);
-                                               glNormal3fv(efa->v3->no);
-                                               glVertex3fv(efa->v3->co);
-                                               if (poly_type == GL_QUADS) {
-                                                       glNormal3fv(efa->v4->no);
-                                                       glVertex3fv(efa->v4->co);
-                                               }
+                                               glNormal3fv(l[0]->v->no);
+                                               glVertex3fv(l[0]->v->co);
+                                               glNormal3fv(l[1]->v->no);
+                                               glVertex3fv(l[1]->v->co);
+                                               glNormal3fv(l[2]->v->no);
+                                               glVertex3fv(l[2]->v->co);
                                        }
                                }
 
                                flush= (draw==2);
-                               if (!skip_normals && !flush && efa->next)
-                                       flush|= efa->mat_nr != efa->next->mat_nr;
+                               if (!skip_normals && !flush && (i != lasttri)) {
+                                       flush|= efa->mat_nr != looptris[i + 1][0]->f->mat_nr; /* TODO, make this neater */
+                               }
 
                                if (flush) {
                                        glEnd();
@@ -441,171 +758,199 @@ static void emDM_drawMappedFaces(
        if (poly_prev != GL_ZERO) glEnd();
 }
 
+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 emDM_drawFacesTex_common(
                DerivedMesh *dm,
-               int (*drawParams)(MTFace *tface, int has_mcol, int matnr),
+               int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
                int (*drawParamsMapped)(void *userData, int index),
                int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
                void *userData)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditMesh *em= emdm->em;
-       float (*vertexCos)[3]= emdm->vertexCos;
-       float (*vertexNos)[3]= emdm->vertexNos;
-       EditFace *efa;
-       int i;
+       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;
+       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);
 
        (void) compareDrawOptions;
 
+       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);
 
+       BM_mesh_elem_index_ensure(bm, BM_FACE);
+
        if (vertexCos) {
-               EditVert *eve;
+               BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+               glBegin(GL_TRIANGLES);
+               for (i=0; i<em->tottri; i++) {
+                       BMLoop **ls = em->looptris[i];
+                       MTexPoly *tp= has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
+                       MTFace mtf = {{{0}}};
+                       /*unsigned char *cp= NULL;*/ /*UNUSED*/
+                       int drawSmooth= BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
+                       int flag;
 
-               for (i=0,eve=em->verts.first; eve; eve= eve->next)
-                       eve->tmp.l = (intptr_t) i++;
+                       efa = ls[0]->f;
 
-               for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
-                       MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-                       MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
-                       unsigned char *cp= NULL;
-                       int drawSmooth= (efa->flag & ME_SMOOTH);
-                       int flag;
+                       if (has_uv) {
+                               ME_MTEXFACE_CPY(&mtf, tp);
+                       }
 
                        if (drawParams)
-                               flag= drawParams(tf, (mcol != NULL), efa->mat_nr);
+                               flag= drawParams(&mtf, has_vcol, efa->mat_nr);
                        else if (drawParamsMapped)
-                               flag= drawParamsMapped(userData, i);
+                               flag= drawParamsMapped(userData, BM_elem_index_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;
-                                       }
-                               }
-
-                               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
                                if (!drawSmooth) {
-                                       glNormal3fv(emdm->faceNos[i]);
+                                       glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
 
-                                       if (tf) glTexCoord2fv(tf->uv[0]);
-                                       if (cp) glColor3ub(cp[3], cp[2], cp[1]);
-                                       glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                                       bmdm_get_tri_tex(bm, ls, luv, lcol, has_uv, has_vcol);
 
-                                       if (tf) glTexCoord2fv(tf->uv[1]);
-                                       if (cp) glColor3ub(cp[7], cp[6], cp[5]);
-                                       glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                                       glTexCoord2fv(luv[0]->uv);
+                                       glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
 
-                                       if (tf) glTexCoord2fv(tf->uv[2]);
-                                       if (cp) glColor3ub(cp[11], cp[10], cp[9]);
-                                       glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                                       glTexCoord2fv(luv[1]->uv);
+                                       glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
 
-                                       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]);
-                                       }
+                                       glTexCoord2fv(luv[2]->uv);
+                                       glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+                                       glVertex3fv(vertexCos[BM_elem_index_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]->b, lcol[0]->g, lcol[0]->r);
+                                       glNormal3fv(vertexNos[BM_elem_index_get(ls[0]->v)]);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(ls[0]->v)]);
+
+                                       glTexCoord2fv(luv[1]->uv);
+                                       glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+                                       glNormal3fv(vertexNos[BM_elem_index_get(ls[1]->v)]);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(ls[1]->v)]);
+
+                                       glTexCoord2fv(luv[2]->uv);
+                                       glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+                                       glNormal3fv(vertexNos[BM_elem_index_get(ls[2]->v)]);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(ls[2]->v)]);
                                }
-                               glEnd();
                        }
                }
+               glEnd();
        }
        else {
-               for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
-                       MTFace *tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-                       MCol *mcol= CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
-                       unsigned char *cp= NULL;
-                       int drawSmooth= (efa->flag & ME_SMOOTH);
+               BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+               for (i=0; i<em->tottri; i++) {
+                       BMLoop **ls = em->looptris[i];
+                       MTexPoly *tp= has_uv ? CustomData_bmesh_get(&bm->pdata, ls[0]->f->head.data, CD_MTEXPOLY) : NULL;
+                       MTFace mtf = {{{0}}};
+                       /*unsigned char *cp= NULL;*/ /*UNUSED*/
+                       int drawSmooth= BM_elem_flag_test(ls[0]->f, BM_ELEM_SMOOTH);
                        int flag;
 
+                       efa = ls[0]->f;
+
+                       if (has_uv) {
+                               ME_MTEXFACE_CPY(&mtf, tp);
+                       }
+
                        if (drawParams)
-                               flag= drawParams(tf, (mcol != NULL), efa->mat_nr);
+                               flag= drawParams(&mtf, has_vcol, efa->mat_nr);
                        else if (drawParamsMapped)
-                               flag= drawParamsMapped(userData, i);
+                               flag= drawParamsMapped(userData, BM_elem_index_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;
-                                       }
-                               }
-
-                               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);
+
+                                       if (luv[0])
+                                               glTexCoord2fv(luv[0]->uv);
+                                       if (lcol[0])
+                                               glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+                                       else glColor3ub(0, 0, 0);
+                                       glVertex3fv(ls[0]->v->co);
+
+                                       if (luv[1])
+                                               glTexCoord2fv(luv[1]->uv);
+                                       if (lcol[1])
+                                               glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+                                       else glColor3ub(0, 0, 0);
+                                       glVertex3fv(ls[1]->v->co);
+
+                                       if (luv[2])
+                                               glTexCoord2fv(luv[2]->uv);
+                                       if (lcol[2])
+                                               glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+                                       else glColor3ub(0, 0, 0);
+                                       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);
+
+                                       if (luv[0])
+                                               glTexCoord2fv(luv[0]->uv);
+                                       if (lcol[0])
+                                               glColor3ub(lcol[0]->b, lcol[0]->g, lcol[0]->r);
+                                       else glColor3ub(0, 0, 0);
+                                       glNormal3fv(ls[0]->v->no);
+                                       glVertex3fv(ls[0]->v->co);
+
+                                       if (luv[1])
+                                               glTexCoord2fv(luv[1]->uv);
+                                       if (lcol[1])
+                                               glColor3ub(lcol[1]->b, lcol[1]->g, lcol[1]->r);
+                                       else glColor3ub(0, 0, 0);
+                                       glNormal3fv(ls[1]->v->no);
+                                       glVertex3fv(ls[1]->v->co);
+
+                                       if (luv[2])
+                                               glTexCoord2fv(luv[2]->uv);
+                                       if (lcol[2])
+                                               glColor3ub(lcol[2]->b, lcol[2]->g, lcol[2]->r);
+                                       else glColor3ub(0, 0, 0);
+                                       glNormal3fv(ls[2]->v->no);
+                                       glVertex3fv(ls[2]->v->co);
                                }
                                glEnd();
                        }
@@ -617,7 +962,7 @@ static void emDM_drawFacesTex_common(
 
 static void emDM_drawFacesTex(
                DerivedMesh *dm,
-               int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr),
+               int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr),
                int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
                void *userData)
 {
@@ -639,54 +984,56 @@ static void emDM_drawMappedFacesGLSL(
                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= {{{0}}};
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMesh *bm= bmdm->tc->bm;
+       BMEditMesh *em = bmdm->tc;
+       float (*vertexCos)[3]= bmdm->vertexCos;
+       float (*vertexNos)[3]= bmdm->vertexNos;
+       BMFace *efa;
+       BMLoop **ltri;
+       DMVertexAttribs attribs;
        GPUVertexAttribs gattribs;
-       /* int tfoffset; */ /* UNUSED */
-       int i, b, matnr, new_matnr, dodraw /* , layer */ /* UNUSED */;
+
+       int i, b, matnr, new_matnr, dodraw;
 
        dodraw = 0;
        matnr = -1;
 
-       /* layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); */ /* UNUSED */
-       /* tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; */ /* UNUSED */
+       memset(&attribs, 0, sizeof(attribs));
 
        /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
        glShadeModel(GL_SMOOTH);
+       BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
 
-       for (i=0,eve=em->verts.first; eve; eve= eve->next)
-               eve->tmp.l = (intptr_t) i++;
-
-#define PASSATTRIB(efa, eve, vert) {                                                                                   \
+#define PASSATTRIB(loop, eve, vert) {                                                                                  \
        if (attribs.totorco) {                                                                                                          \
-               float *orco = attribs.orco.array[eve->tmp.l];                                                   \
+               float *orco = attribs.orco.array[BM_elem_index_get(eve)];                                               \
                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]);                  \
+               MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
        }                                                                                                                                                       \
        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);                                    \
+               MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
+               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];                                                   \
-               glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                                               \
+               glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
        }                                                                                                                                                       \
-}
+       }
+
 
-       for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
-               int drawSmooth= (efa->flag & ME_SMOOTH);
+       for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
+               int drawSmooth;
 
-               if (setDrawOptions && !setDrawOptions(userData, i))
+               efa = ltri[0]->f;
+               drawSmooth= BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
+
+               if (setDrawOptions && !setDrawOptions(userData, BM_elem_index_get(efa)))
                        continue;
 
                new_matnr = efa->mat_nr + 1;
@@ -697,70 +1044,52 @@ static void emDM_drawMappedFacesGLSL(
                }
 
                if (dodraw) {
-                       glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+                       glBegin(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);
+                               if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
+                               else glNormal3fv(efa->no);
 
-                               PASSATTRIB(efa, efa->v2, 1);
-                               if (vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
-                               else glVertex3fv(efa->v2->co);
+                               PASSATTRIB(ltri[0], ltri[0]->v, 0);
+                               if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
+                               else glVertex3fv(ltri[0]->v->co);
 
-                               PASSATTRIB(efa, efa->v3, 2);
-                               if (vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
-                               else glVertex3fv(efa->v3->co);
+                               PASSATTRIB(ltri[1], ltri[1]->v, 1);
+                               if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
+                               else glVertex3fv(ltri[1]->v->co);
 
-                               if (efa->v4) {
-                                       PASSATTRIB(efa, efa->v4, 3);
-                                       if (vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]);
-                                       else glVertex3fv(efa->v4->co);
-                               }
+                               PASSATTRIB(ltri[2], ltri[2]->v, 2);
+                               if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
+                               else glVertex3fv(ltri[2]->v->co);
                        }
                        else {
-                               PASSATTRIB(efa, efa->v1, 0);
+                               PASSATTRIB(ltri[0], ltri[0]->v, 0);
                                if (vertexCos) {
-                                       glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
-                                       glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                                       glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
                                }
                                else {
-                                       glNormal3fv(efa->v1->no);
-                                       glVertex3fv(efa->v1->co);
+                                       glNormal3fv(ltri[0]->v->no);
+                                       glVertex3fv(ltri[0]->v->co);
                                }
 
-                               PASSATTRIB(efa, efa->v2, 1);
+                               PASSATTRIB(ltri[1], ltri[1]->v, 1);
                                if (vertexCos) {
-                                       glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
-                                       glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                                       glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
                                }
                                else {
-                                       glNormal3fv(efa->v2->no);
-                                       glVertex3fv(efa->v2->co);
+                                       glNormal3fv(ltri[1]->v->no);
+                                       glVertex3fv(ltri[1]->v->co);
                                }
 
-                               PASSATTRIB(efa, efa->v3, 2);
+                               PASSATTRIB(ltri[2], ltri[2]->v, 2);
                                if (vertexCos) {
-                                       glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
-                                       glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                                       glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
+                                       glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
                                }
                                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);
-                                       }
+                                       glNormal3fv(ltri[2]->v->no);
+                                       glVertex3fv(ltri[2]->v->co);
                                }
                        }
                        glEnd();
@@ -781,12 +1110,13 @@ static void emDM_drawMappedFacesMat(
                void (*setMaterial)(void *userData, int, void *attribs),
                int (*setFace)(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;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMesh *bm= bmdm->tc->bm;
+       BMEditMesh *em = bmdm->tc;
+       float (*vertexCos)[3]= bmdm->vertexCos;
+       float (*vertexNos)[3]= bmdm->vertexNos;
+       BMFace *efa;
+       BMLoop **ltri;
        DMVertexAttribs attribs= {{{0}}};
        GPUVertexAttribs gattribs;
        int i, b, matnr, new_matnr;
@@ -796,29 +1126,22 @@ static void emDM_drawMappedFacesMat(
        /* 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++;
+       BM_mesh_elem_index_ensure(bm, BM_VERT);
 
-#define PASSATTRIB(efa, eve, vert) {                                                                                   \
+#define PASSATTRIB(loop, eve, vert) {                                                                                  \
        if (attribs.totorco) {                                                                                                          \
-               float *orco = attribs.orco.array[eve->tmp.l];                                                   \
-               if (attribs.orco.glTexco)                                                                                               \
-                       glTexCoord3fv(orco);                                                                                            \
-               else                                                                                                                                    \
-                       glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                       \
+               float *orco = attribs.orco.array[BM_elem_index_get(eve)];                                               \
+               glVertexAttrib3fvARB(attribs.orco.glIndex, orco);                                               \
        }                                                                                                                                                       \
        for (b = 0; b < attribs.tottface; b++) {                                                                        \
-               MTFace *_tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset);  \
-               if (attribs.tface[b].glTexco)                                                                                   \
-                       glTexCoord2fv(_tf->uv[vert]);                                                                           \
-               else                                                                                                                                    \
-                       glVertexAttrib2fvARB(attribs.tface[b].glIndex, _tf->uv[vert]);          \
+               MLoopUV *_luv = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, b);\
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, _luv->uv);                               \
        }                                                                                                                                                       \
        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);                                    \
+               MLoopCol *_cp = CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPCOL, b);\
+               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];                                                   \
@@ -826,11 +1149,14 @@ static void emDM_drawMappedFacesMat(
        }                                                                                                                                                       \
 }
 
-       for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) {
-               int drawSmooth= (efa->flag & ME_SMOOTH);
+       for (i=0, ltri=em->looptris[0]; i<em->tottri; i++, ltri += 3) {
+               int drawSmooth;
+
+               efa = ltri[0]->f;
+               drawSmooth = BM_elem_flag_test(efa, BM_ELEM_SMOOTH);
 
                /* face hiding */
-               if (setFace && !setFace(userData, i))
+               if (setFace && !setFace(userData, BM_elem_index_get(efa)))
                        continue;
 
                /* material */
@@ -841,70 +1167,53 @@ static void emDM_drawMappedFacesMat(
                }
 
                /* face */
-               glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
+               glBegin(GL_TRIANGLES);
                if (!drawSmooth) {
-                       if (vertexCos) glNormal3fv(emdm->faceNos[i]);
-                       else glNormal3fv(efa->n);
+                       if (vertexCos) glNormal3fv(bmdm->polyNos[BM_elem_index_get(efa)]);
+                       else glNormal3fv(efa->no);
 
-                       PASSATTRIB(efa, efa->v1, 0);
-                       if (vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
-                       else glVertex3fv(efa->v1->co);
+                       PASSATTRIB(ltri[0], ltri[0]->v, 0);
+                       if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
+                       else glVertex3fv(ltri[0]->v->co);
 
-                       PASSATTRIB(efa, efa->v2, 1);
-                       if (vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
-                       else glVertex3fv(efa->v2->co);
+                       PASSATTRIB(ltri[1], ltri[1]->v, 1);
+                       if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
+                       else glVertex3fv(ltri[1]->v->co);
 
-                       PASSATTRIB(efa, efa->v3, 2);
-                       if (vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
-                       else glVertex3fv(efa->v3->co);
+                       PASSATTRIB(ltri[2], ltri[2]->v, 2);
+                       if (vertexCos) glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
+                       else glVertex3fv(ltri[2]->v->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);
+                       PASSATTRIB(ltri[0], ltri[0]->v, 0);
                        if (vertexCos) {
-                               glNormal3fv(vertexNos[(int) efa->v1->tmp.l]);
-                               glVertex3fv(vertexCos[(int) efa->v1->tmp.l]);
+                               glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
+                               glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
                        }
                        else {
-                               glNormal3fv(efa->v1->no);
-                               glVertex3fv(efa->v1->co);
+                               glNormal3fv(ltri[0]->v->no);
+                               glVertex3fv(ltri[0]->v->co);
                        }
 
-                       PASSATTRIB(efa, efa->v2, 1);
+                       PASSATTRIB(ltri[1], ltri[1]->v, 1);
                        if (vertexCos) {
-                               glNormal3fv(vertexNos[(int) efa->v2->tmp.l]);
-                               glVertex3fv(vertexCos[(int) efa->v2->tmp.l]);
+                               glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
+                               glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
                        }
                        else {
-                               glNormal3fv(efa->v2->no);
-                               glVertex3fv(efa->v2->co);
+                               glNormal3fv(ltri[1]->v->no);
+                               glVertex3fv(ltri[1]->v->co);
                        }
 
-                       PASSATTRIB(efa, efa->v3, 2);
+                       PASSATTRIB(ltri[2], ltri[2]->v, 2);
                        if (vertexCos) {
-                               glNormal3fv(vertexNos[(int) efa->v3->tmp.l]);
-                               glVertex3fv(vertexCos[(int) efa->v3->tmp.l]);
+                               glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
+                               glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
                        }
                        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);
-                               }
+                               glNormal3fv(ltri[2]->v->no);
+                               glVertex3fv(ltri[2]->v->co);
                        }
                }
                glEnd();
@@ -914,14 +1223,16 @@ static void emDM_drawMappedFacesMat(
 
 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditVert *eve;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMVert *eve;
+       BMIter iter;
        int i;
 
-       if (emdm->em->verts.first) {
-               for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
-                       if (emdm->vertexCos) {
-                               DO_MINMAX(emdm->vertexCos[i], min_r, max_r);
+       if (bmdm->tc->bm->totvert) {
+               eve = BM_iter_new(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+               for (i=0; eve; eve=BM_iter_step(&iter), i++) {
+                       if (bmdm->vertexCos) {
+                               DO_MINMAX(bmdm->vertexCos[i], min_r, max_r);
                        }
                        else {
                                DO_MINMAX(eve->co, min_r, max_r);
@@ -934,236 +1245,271 @@ static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
 }
 static int emDM_getNumVerts(DerivedMesh *dm)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
-       return BLI_countlist(&emdm->em->verts);
+       return bmdm->tc->bm->totvert;
 }
 
 static int emDM_getNumEdges(DerivedMesh *dm)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
-       return BLI_countlist(&emdm->em->edges);
+       return bmdm->tc->bm->totedge;
 }
 
-static int emDM_getNumFaces(DerivedMesh *dm)
+static int emDM_getNumTessFaces(DerivedMesh *dm)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
-       return BLI_countlist(&emdm->em->faces);
+       return bmdm->tc->tottri;
 }
 
-static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
+static int emDM_getNumLoops(DerivedMesh *dm)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditVert *eve;
-       int i;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
-       for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
-               if (emdm->vertexCos) {
-                       copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
-               }
-               else {
-                       copy_v3_v3(cos_r[i], eve->co);
-               }
-       }
+       return bmdm->tc->bm->totloop;
 }
 
-static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+static int emDM_getNumPolys(DerivedMesh *dm)
 {
-       EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
-       int i;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
 
-       for (i = 0; i < index; ++i) ev = ev->next;
+       return bmdm->tc->bm->totface;
+}
 
+static int bmvert_to_mvert(BMesh *bm, BMVert *ev, MVert *vert_r)
+{
        copy_v3_v3(vert_r->co, ev->co);
 
        normal_float_to_short_v3(vert_r->no, ev->no);
 
-       /* TODO what to do with vert_r->flag? */
-       vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
+       vert_r->flag = BM_vert_flag_to_mflag(ev);
+
+       if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+               vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
+       }
+
+       return 1;
+}
+
+static void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+       BMVert *ev;
+
+       if (index < 0 || index >= bmdm->tv) {
+               printf("error in emDM_getVert.\n");
+               return;
+       }
+
+       // ev = EDBM_get_vert_for_index(bmdm->tc, index);
+       ev = BM_vert_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
+
+       bmvert_to_mvert(bmdm->tc->bm, ev, vert_r);
 }
 
 static void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
 {
-       EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
-       EditEdge *ee = em->edges.first;
-       EditVert *ev, *v1, *v2;
-       int i;
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+       BMesh *bm = bmdm->tc->bm;
+       BMEdge *e;
 
-       for (i = 0; i < index; ++i) ee = ee->next;
+       if (index < 0 || index >= bmdm->te) {
+               printf("error in emDM_getEdge.\n");
+               return;
+       }
 
-       edge_r->crease = (unsigned char) (ee->crease*255.0f);
-       edge_r->bweight = (unsigned char) (ee->bweight*255.0f);
-       /* TODO what to do with edge_r->flag? */
-       edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
-       if (ee->seam) edge_r->flag |= ME_SEAM;
-       if (ee->sharp) edge_r->flag |= ME_SHARP;
-#if 0
-       /* this needs setup of f2 field */
-       if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
-#endif
+       // e = EDBM_get_edge_for_index(bmdm->tc, index);
+       e = BM_edge_at_index(bmdm->tc->bm, index); /* warning, does list loop, _not_ ideal */
 
-       /* goddamn, we have to search all verts to find indices */
-       v1 = ee->v1;
-       v2 = ee->v2;
-       for (i = 0, ev = em->verts.first; v1 || v2; i++, ev = ev->next) {
-               if (ev == v1) {
-                       edge_r->v1 = i;
-                       v1 = NULL;
-               }
-               if (ev == v2) {
-                       edge_r->v2 = i;
-                       v2 = NULL;
-               }
+       if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
+               edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT)*255.0f);
        }
+
+       if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
+               edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, e, CD_CREASE)*255.0f);
+       }
+
+       edge_r->flag = BM_edge_flag_to_mflag(e);
+
+       edge_r->v1 = BM_elem_index_get(e->v1);
+       edge_r->v2 = BM_elem_index_get(e->v2);
 }
 
-static void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
+static void emDM_getTessFace(DerivedMesh *dm, int index, MFace *face_r)
 {
-       EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
-       EditFace *ef = em->faces.first;
-       EditVert *ev, *v1, *v2, *v3, *v4;
-       int i;
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+       BMFace *ef;
+       BMLoop **l;
 
-       for (i = 0; i < index; ++i) ef = ef->next;
+       if (index < 0 || index >= bmdm->tf) {
+               printf("error in emDM_getTessFace.\n");
+               return;
+       }
 
-       face_r->mat_nr = ef->mat_nr;
-       face_r->flag = ef->flag;
+       l = bmdm->tc->looptris[index];
 
-       /* goddamn, we have to search all verts to find indices */
-       v1 = ef->v1;
-       v2 = ef->v2;
-       v3 = ef->v3;
-       v4 = ef->v4;
-       if (!v4) face_r->v4 = 0;
+       ef = l[0]->f;
 
-       for (i = 0, ev = em->verts.first; v1 || v2 || v3 || v4;
-               i++, ev = ev->next) {
-               if (ev == v1) {
-                       face_r->v1 = i;
-                       v1 = NULL;
-               }
-               if (ev == v2) {
-                       face_r->v2 = i;
-                       v2 = NULL;
-               }
-               if (ev == v3) {
-                       face_r->v3 = i;
-                       v3 = NULL;
-               }
-               if (ev == v4) {
-                       face_r->v4 = i;
-                       v4 = NULL;
-               }
-       }
+       face_r->mat_nr = (unsigned char) ef->mat_nr;
+       face_r->flag = BM_face_flag_to_mflag(ef);
+
+       face_r->v1 = BM_elem_index_get(l[0]->v);
+       face_r->v2 = BM_elem_index_get(l[1]->v);
+       face_r->v3 = BM_elem_index_get(l[2]->v);
+       face_r->v4 = 0;
 
-       test_index_face(face_r, NULL, 0, ef->v4?4:3);
+       test_index_face(face_r, NULL, 0, 3);
 }
 
 static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditVert *ev = emdm->em->verts.first;
-       int i;
+       BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+       BMVert *ev;
+       BMIter iter;
 
-       for (i=0; ev; ev = ev->next, ++vert_r, ++i) {
-               if (emdm->vertexCos)
-                       copy_v3_v3(vert_r->co, emdm->vertexCos[i]);
-               else
-                       copy_v3_v3(vert_r->co, ev->co);
+       ev = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL);
+       for ( ; ev; ev = BM_iter_step(&iter), ++vert_r) {
+               copy_v3_v3(vert_r->co, ev->co);
 
                normal_float_to_short_v3(vert_r->no, ev->no);
 
-               /* TODO what to do with vert_r->flag? */
-               vert_r->flag = 0;
-               vert_r->bweight = (unsigned char) (ev->bweight*255.0f);
+               vert_r->flag = BM_vert_flag_to_mflag(ev);
+
+               if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+                       vert_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->vdata, ev, CD_BWEIGHT)*255.0f);
+               }
        }
 }
 
 static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
 {
-       EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
-       EditEdge *ee = em->edges.first;
-       EditVert *ev;
-       int i;
+       BMesh *bm = ((EditDerivedBMesh *)dm)->tc->bm;
+       BMEdge *ee;
+       BMIter iter;
+       int has_bweight = CustomData_has_layer(&bm->edata, CD_BWEIGHT);
+       int has_crease = CustomData_has_layer(&bm->edata, CD_CREASE);
+
+       BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+       ee = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL);
+       for ( ; ee; ee=BM_iter_step(&iter), edge_r++) {
+               if (has_bweight) {
+                       edge_r->bweight = (unsigned char) (BM_elem_float_data_get(&bm->edata, ee, CD_BWEIGHT)*255.0f);
+               }
 
-       /* store vertex indices in tmp union */
-       for (ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
-               ev->tmp.l = (intptr_t) i;
-
-       for ( ; ee; ee = ee->next, ++edge_r) {
-               edge_r->crease = (unsigned char) (ee->crease*255.0f);
-               edge_r->bweight = (unsigned char) (ee->bweight*255.0f);
-               /* TODO what to do with edge_r->flag? */
-               edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
-               if (ee->seam) edge_r->flag |= ME_SEAM;
-               if (ee->sharp) edge_r->flag |= ME_SHARP;
-#if 0
-               /* this needs setup of f2 field */
-               if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
-#endif
+               if (has_crease) {
+                       edge_r->crease = (unsigned char) (BM_elem_float_data_get(&bm->edata, ee, CD_CREASE)*255.0f);
+               }
+
+               edge_r->flag = BM_edge_flag_to_mflag(ee);
 
-               edge_r->v1 = (int)ee->v1->tmp.l;
-               edge_r->v2 = (int)ee->v2->tmp.l;
+               edge_r->v1 = BM_elem_index_get(ee->v1);
+               edge_r->v2 = BM_elem_index_get(ee->v2);
        }
 }
 
-static void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
+static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r)
 {
-       EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
-       EditFace *ef = em->faces.first;
-       EditVert *ev;
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+       BMesh *bm = bmdm->tc->bm;
+       BMFace *ef;
+       BMLoop **l;
        int i;
 
-       /* store vertexes indices in tmp union */
-       for (ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
-               ev->tmp.l = (intptr_t) i;
+       BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+       for (i=0; i<bmdm->tc->tottri; i++, face_r++) {
+               l = bmdm->tc->looptris[i];
+               ef = l[0]->f;
+
+               face_r->mat_nr = (unsigned char) ef->mat_nr;
+
+               face_r->flag = BM_face_flag_to_mflag(ef);
+
+               face_r->v1 = BM_elem_index_get(l[0]->v);
+               face_r->v2 = BM_elem_index_get(l[1]->v);
+               face_r->v3 = BM_elem_index_get(l[2]->v);
+               face_r->v4 = 0;
+
+               test_index_face(face_r, NULL, 0, 3);
+       }
+}
+
 
-       for ( ; ef; ef = ef->next, ++face_r) {
-               face_r->mat_nr = ef->mat_nr;
-               face_r->flag = ef->flag;
+static void emDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+       BMesh *bm = bmdm->tc->bm;
+       BMIter iter, liter;
+       BMFace *f;
+       BMLoop *l;
+
+       BM_mesh_elem_index_ensure(bm, BM_VERT | BM_EDGE);
+
+       BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+               BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+                       loop_r->v = BM_elem_index_get(l->v);
+                       loop_r->e = BM_elem_index_get(l->e);
+                       loop_r++;
+               }
+       }
+}
+
+static void emDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+       BMesh *bm = bmdm->tc->bm;
+       BMIter iter;
+       BMFace *f;
+       int i;
 
-               face_r->v1 = (int)ef->v1->tmp.l;
-               face_r->v2 = (int)ef->v2->tmp.l;
-               face_r->v3 = (int)ef->v3->tmp.l;
-               if (ef->v4) face_r->v4 = (int)ef->v4->tmp.l;
-               else face_r->v4 = 0;
+       i = 0;
+       BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+               poly_r->flag = BM_face_flag_to_mflag(f);
+               poly_r->loopstart = i;
+               poly_r->totloop = f->len;
+               poly_r->mat_nr = f->mat_nr;
 
-               test_index_face(face_r, NULL, 0, ef->v4?4:3);
+               poly_r++;
+               i += f->len;
        }
 }
 
-static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
+static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
-       EditMesh *em= emdm->em;
-       EditFace *efa;
-       char *data, *emdata;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh*) dm;
+       BMesh *bm= bmdm->tc->bm;
+       BMFace *efa;
+       char *data, *bmdata;
        void *datalayer;
-       int index, size;
+       int index /*, offset*/ /*UNUSED */, size, i;
 
-       datalayer = DM_get_face_data_layer(dm, type);
+       datalayer = DM_get_tessface_data_layer(dm, type);
        if (datalayer)
                return datalayer;
 
-       /* layers are store per face for editmesh, we convert to a temporary
+       /* layers are store per face for editmesh, we convert to a tbmporary
         * 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);
+               index = CustomData_get_layer_index(&bm->pdata, type);
 
                if (index != -1) {
-                       /* int offset = em->fdata.layers[index].offset; */ /* UNUSED */
+                       /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
                        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);
-                       for (efa=em->faces.first; efa; efa=efa->next, data+=size) {
-                               emdata = CustomData_em_get(&em->fdata, efa->data, type);
-                               memcpy(data, emdata, size);
+                       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,
+                                 derived from the loops.*/
+                               bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, type);
+                               memcpy(data, bmdata, size);
                        }
                }
        }
@@ -1171,120 +1517,188 @@ static void *emDM_getFaceDataArray(DerivedMesh *dm, int type)
        return datalayer;
 }
 
+static void emDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
+{
+       EditDerivedBMesh *emdm= (EditDerivedBMesh*) dm;
+       BMVert *eve;
+       BMIter iter;
+       int i;
+
+       i= 0;
+       BM_ITER(eve, &iter, emdm->tc->bm, BM_VERTS_OF_MESH, NULL) {
+               if (emdm->vertexCos) {
+                       copy_v3_v3(cos_r[i], emdm->vertexCos[i]);
+               }
+               else {
+                       copy_v3_v3(cos_r[i], eve->co);
+               }
+
+               i++;
+       }
+}
+
 static void emDM_release(DerivedMesh *dm)
 {
-       EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+       EditDerivedBMesh *bmdm= (EditDerivedBMesh *)dm;
 
        if (DM_release(dm)) {
-               if (emdm->vertexCos) {
-                       MEM_freeN(emdm->vertexCos);
-                       MEM_freeN(emdm->vertexNos);
-                       MEM_freeN(emdm->faceNos);
+               if (bmdm->vertexCos) {
+                       MEM_freeN(bmdm->vertexCos);
+                       MEM_freeN(bmdm->vertexNos);
+                       MEM_freeN(bmdm->polyNos);
                }
 
-               MEM_freeN(emdm);
+               MEM_freeN(bmdm);
        }
 }
 
-DerivedMesh *editmesh_get_derived(
-               EditMesh *em,
-               float (*vertexCos)[3])
+static CustomData *bmDm_getVertDataLayout(DerivedMesh *dm)
 {
-       EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 
-       DM_init(&emdm->dm, DM_TYPE_EDITMESH, BLI_countlist(&em->verts),
-                                        BLI_countlist(&em->edges), BLI_countlist(&em->faces));
+       return &bmdm->tc->bm->vdata;
+}
 
-       emdm->dm.getMinMax = emDM_getMinMax;
+static CustomData *bmDm_getEdgeDataLayout(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 
-       emdm->dm.getNumVerts = emDM_getNumVerts;
-       emdm->dm.getNumEdges = emDM_getNumEdges;
-       emdm->dm.getNumFaces = emDM_getNumFaces;
+       return &bmdm->tc->bm->edata;
+}
 
-       emdm->dm.getVertCos = emDM_getVertCos;
+static CustomData *bmDm_getTessFaceDataLayout(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 
-       emdm->dm.getVert = emDM_getVert;
-       emdm->dm.getEdge = emDM_getEdge;
-       emdm->dm.getFace = emDM_getFace;
-       emdm->dm.copyVertArray = emDM_copyVertArray;
-       emdm->dm.copyEdgeArray = emDM_copyEdgeArray;
-       emdm->dm.copyFaceArray = emDM_copyFaceArray;
-       emdm->dm.getFaceDataArray = emDM_getFaceDataArray;
+       return &bmdm->dm.faceData;
+}
 
-       emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
-       emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
-       emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
+static CustomData *bmDm_getLoopDataLayout(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
 
-       emdm->dm.drawEdges = emDM_drawEdges;
-       emdm->dm.drawMappedEdges = emDM_drawMappedEdges;
-       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.drawMappedFacesMat = emDM_drawMappedFacesMat;
-       emdm->dm.drawUVEdges = emDM_drawUVEdges;
+       return &bmdm->tc->bm->ldata;
+}
 
-       emdm->dm.release = emDM_release;
+static CustomData *bmDm_getPolyDataLayout(DerivedMesh *dm)
+{
+       EditDerivedBMesh *bmdm = (EditDerivedBMesh*)dm;
+
+       return &bmdm->tc->bm->pdata;
+}
 
-       emdm->em = em;
-       emdm->vertexCos = vertexCos;
 
-       if (CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) {
-               EditVert *eve;
+DerivedMesh *getEditDerivedBMesh(
+               BMEditMesh *em,
+               Object *UNUSED(ob),
+               float (*vertexCos)[3])
+{
+       EditDerivedBMesh *bmdm = MEM_callocN(sizeof(*bmdm), __func__);
+       BMesh *bm = em->bm;
+
+       bmdm->tc = em;
+
+       DM_init((DerivedMesh*)bmdm, DM_TYPE_EDITBMESH, em->bm->totvert,
+                em->bm->totedge, em->tottri, em->bm->totloop, em->bm->totface);
+
+       CustomData_from_bmeshpoly(&bmdm->dm.faceData, &em->bm->pdata, &em->bm->ldata, 0);
+
+       bmdm->dm.getVertCos = emDM_getVertCos;
+       bmdm->dm.getMinMax = emDM_getMinMax;
+
+       bmdm->dm.getVertDataLayout = bmDm_getVertDataLayout;
+       bmdm->dm.getEdgeDataLayout = bmDm_getEdgeDataLayout;
+       bmdm->dm.getTessFaceDataLayout = bmDm_getTessFaceDataLayout;
+       bmdm->dm.getLoopDataLayout = bmDm_getLoopDataLayout;
+       bmdm->dm.getPolyDataLayout = bmDm_getPolyDataLayout;
+
+       bmdm->dm.getNumVerts = emDM_getNumVerts;
+       bmdm->dm.getNumEdges = emDM_getNumEdges;
+       bmdm->dm.getNumTessFaces = emDM_getNumTessFaces;
+       bmdm->dm.getNumLoops = emDM_getNumLoops;
+       bmdm->dm.getNumPolys = emDM_getNumPolys;
+
+       bmdm->dm.getVert = emDM_getVert;
+       bmdm->dm.getEdge = emDM_getEdge;
+       bmdm->dm.getTessFace = emDM_getTessFace;
+       bmdm->dm.copyVertArray = emDM_copyVertArray;
+       bmdm->dm.copyEdgeArray = emDM_copyEdgeArray;
+       bmdm->dm.copyTessFaceArray = emDM_copyTessFaceArray;
+       bmdm->dm.copyLoopArray = emDM_copyLoopArray;
+       bmdm->dm.copyPolyArray = emDM_copyPolyArray;
+
+       bmdm->dm.getTessFaceDataArray = emDM_getTessFaceDataArray;
+
+       bmdm->dm.calcNormals = emDM_calcNormals;
+       bmdm->dm.recalcTesselation = emDM_recalcTesselation;
+
+       bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
+       bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
+       bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
+
+       bmdm->dm.drawEdges = emDM_drawEdges;
+       bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
+       bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
+       bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
+       bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
+       bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
+       bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
+       bmdm->dm.drawFacesTex = emDM_drawFacesTex;
+       bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
+       bmdm->dm.drawUVEdges = emDM_drawUVEdges;
+
+       bmdm->dm.release = emDM_release;
+
+       bmdm->vertexCos = vertexCos;
+
+       if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) {
+               BMIter iter;
+               BMVert *eve;
                int i;
 
-               DM_add_vert_layer(&emdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
+               DM_add_vert_layer(&bmdm->dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
 
-               for (eve = em->verts.first, i = 0; eve; eve = eve->next, ++i)
-                       DM_set_vert_data(&emdm->dm, i, CD_MDEFORMVERT,
-                                                        CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT));
+               eve = BM_iter_new(&iter, bmdm->tc->bm, BM_VERTS_OF_MESH, NULL);
+               for (i=0; eve; eve=BM_iter_step(&iter), i++)
+                       DM_set_vert_data(&bmdm->dm, i, CD_MDEFORMVERT,
+                                                        CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MDEFORMVERT));
        }
 
        if (vertexCos) {
-               EditVert *eve;
-               EditFace *efa;
-               int totface = BLI_countlist(&em->faces);
+               BMFace *efa;
+               BMVert *eve;
+               BMIter fiter;
+               BMIter viter;
                int i;
 
-               for (i=0,eve=em->verts.first; eve; eve= eve->next)
-                       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");
+               BM_mesh_elem_index_ensure(bm, BM_VERT);
 
-               for (i=0, efa= em->faces.first; efa; i++, efa=efa->next) {
-                       float *v1 = vertexCos[(int) efa->v1->tmp.l];
-                       float *v2 = vertexCos[(int) efa->v2->tmp.l];
-                       float *v3 = vertexCos[(int) efa->v3->tmp.l];
-                       float *no = emdm->faceNos[i];
+               bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
+               bmdm->polyNos = MEM_mallocN(sizeof(*bmdm->polyNos)*bm->totface, "bmdm_pno");
 
-                       if (efa->v4) {
-                               float *v4 = vertexCos[(int) efa->v4->tmp.l];
+               i = 0;
+               BM_ITER(efa, &fiter, bm, BM_FACES_OF_MESH, NULL) {
+                       BM_elem_index_set(efa, i); /* set_inline */
+                       BM_face_normal_update_vcos(bm, efa, bmdm->polyNos[i], vertexCos);
+                       i++;
+               }
+               bm->elem_index_dirty &= ~BM_FACE;
 
-                               normal_quad_v3( no,v1, v2, v3, v4);
-                               add_v3_v3(emdm->vertexNos[(int) efa->v4->tmp.l], no);
-                       }
-                       else {
-                               normal_tri_v3( no,v1, v2, v3);
+               eve=BM_iter_new(&viter, bm, BM_VERTS_OF_MESH, NULL);
+               for (i=0; eve; eve=BM_iter_step(&viter), i++) {
+                       float *no = bmdm->vertexNos[i];
+                       BM_ITER(efa, &fiter, bm, BM_FACES_OF_VERT, eve) {
+                               add_v3_v3(no, bmdm->polyNos[BM_elem_index_get(efa)]);
                        }
 
-                       add_v3_v3(emdm->vertexNos[(int) efa->v1->tmp.l], no);
-                       add_v3_v3(emdm->vertexNos[(int) efa->v2->tmp.l], no);
-                       add_v3_v3(emdm->vertexNos[(int) efa->v3->tmp.l], no);
-               }
-
-               for (i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
-                       float *no = emdm->vertexNos[i];
                        /* following Mesh convention; we use vertex coordinate itself
                         * for normal in this case */
-                       if (normalize_v3(no) == 0.0f) {
-                               normalize_v3_v3(no, vertexCos[i]);
+                       if (normalize_v3(no)==0.0) {
+                               copy_v3_v3(no, vertexCos[i]);
+                               normalize_v3(no);
                        }
                }
        }
 
-       return (DerivedMesh*) emdm;
+       return (DerivedMesh*) bmdm;
 }
-