Add tessellation data to DerivedMesh (LoopTri)
authorCampbell Barton <ideasman42@gmail.com>
Thu, 16 Jul 2015 17:36:03 +0000 (03:36 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 16 Jul 2015 17:55:14 +0000 (03:55 +1000)
This stores loop indices into the loop array giving easier acess
to data such as vertex-colors and UV's,
removing the need to store an MFace duplicate of custom-data.

This doesn't yet move all internal code from MFace to LoopTri just yet.

Only applies to:
- opengl drawing
- sculpting (pbvh)
- vertex/weight paint

Thanks to @psy-fi for review, fixes and improvements to drawing!

22 files changed:
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/BKE_cdderivedmesh.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_paint.h
source/blender/blenkernel/BKE_pbvh.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/editderivedmesh.c
source/blender/blenkernel/intern/mesh_evaluate.c
source/blender/blenkernel/intern/paint.c
source/blender/blenkernel/intern/pbvh.c
source/blender/blenkernel/intern/pbvh_intern.h
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenlib/BLI_math_geom.h
source/blender/blenlib/intern/math_geom.c
source/blender/editors/mesh/editface.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/gpu/GPU_buffers.h
source/blender/gpu/intern/gpu_buffers.c
source/blender/makesdna/DNA_customdata_types.h
source/blender/makesdna/DNA_meshdata_types.h

index 62c68380289648a62959d7460dbd38c70a97464f..0a4cc7f543f2ff285d28b248ddbb87c2e4f5ae0d 100644 (file)
@@ -185,6 +185,15 @@ struct DerivedMesh {
        int totmat; /* total materials. Will be valid only before object drawing. */
        struct Material **mat; /* material array. Will be valid only before object drawing */
 
+       /**
+        * \warning Typical access is done via #getLoopTriArray, #getNumLoopTri.
+        */
+       struct {
+               struct MLoopTri *array;
+               int num;
+               int num_alloc;
+       } looptris;
+
        /* use for converting to BMesh which doesn't store bevel weight and edge crease by default */
        char cd_flag;
 
@@ -201,6 +210,12 @@ struct DerivedMesh {
        /** Recalculates mesh tessellation */
        void (*recalcTessellation)(DerivedMesh *dm);
 
+       /** Loop tessellation cache */
+       void (*recalcLoopTri)(DerivedMesh *dm);
+       /** accessor functions */
+       const struct MLoopTri *(*getLoopTriArray)(DerivedMesh * dm);
+       int (*getNumLoopTri)(DerivedMesh *dm);
+
        /* Misc. Queries */
 
        /* Also called in Editmode */
@@ -594,10 +609,14 @@ void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
 void DM_ensure_normals(DerivedMesh *dm);
 void DM_ensure_tessface(DerivedMesh *dm);
 
+void DM_ensure_looptri_data(DerivedMesh *dm);
+void DM_ensure_looptri(DerivedMesh *dm);
+
 void DM_update_tessface_data(DerivedMesh *dm);
 
 void DM_update_materials(DerivedMesh *dm, struct Object *ob);
 struct MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr);
+struct MLoopUV *DM_paint_uvlayer_active_get_mloopuv(DerivedMesh *dm, int mat_nr);
 
 void DM_interp_vert_data(
         struct DerivedMesh *source, struct DerivedMesh *dest,
@@ -721,12 +740,12 @@ void DM_update_weight_mcol(
  * the DerivedMesh, with both a pointer for arrays and an offset for editmesh */
 typedef struct DMVertexAttribs {
        struct {
-               struct MTFace *array;
+               struct MLoopUV *array;
                int em_offset, gl_index, gl_texco;
        } tface[MAX_MTFACE];
 
        struct {
-               struct MCol *array;
+               struct MLoopCol *array;
                int em_offset, gl_index;
        } mcol[MAX_MCOL];
 
@@ -747,7 +766,7 @@ void DM_vertex_attributes_from_gpu(
         DerivedMesh *dm,
         struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
 
-void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert);
+void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop);
 
 void DM_add_tangent_layer(DerivedMesh *dm);
 void DM_calc_auto_bump_scale(DerivedMesh *dm);
index 59ec316a40397d2829351368a0bf65970b18acdf..c7ad6419560c0ad58d7514590667f3d9e686f46b 100644 (file)
@@ -125,6 +125,8 @@ void CDDM_calc_edges(struct DerivedMesh *dm);
 void CDDM_recalc_tessellation(struct DerivedMesh *dm);
 void CDDM_recalc_tessellation_ex(struct DerivedMesh *dm, const bool do_face_nor_cpy);
 
+void CDDM_recalc_looptri(struct DerivedMesh *dm);
+
 /* lowers the number of vertices/edges/faces in a CDDerivedMesh
  * the layer data stays the same size
  */
index 1ff2c6bc862f6fc7ef6b0584679db7cdda2a6818..afe6fda48edc5ea4955a96f4f756793c92dd5e96 100644 (file)
@@ -39,6 +39,7 @@ struct LinkNode;
 struct BLI_Stack;
 struct MemArena;
 struct BMesh;
+struct MLoopTri;
 struct Main;
 struct Mesh;
 struct MPoly;
@@ -178,6 +179,11 @@ void BKE_mesh_calc_normals_tessface(
         struct MVert *mverts, int numVerts,
         const struct MFace *mfaces, int numFaces,
         float (*r_faceNors)[3]);
+void BKE_mesh_calc_normals_looptri(
+        struct MVert *mverts, int numVerts,
+        const struct MLoop *mloop,
+        const struct MLoopTri *looptri, int looptri_num,
+        float (*r_tri_nors)[3]);
 void BKE_mesh_loop_tangents_ex(
         const struct MVert *mverts, const int numVerts, const struct MLoop *mloops,
         float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv,
@@ -285,6 +291,11 @@ int BKE_mesh_recalc_tessellation(
         struct MVert *mvert,
         int totface, int totloop, int totpoly,
         const bool do_face_nor_copy);
+void BKE_mesh_recalc_looptri(
+        const struct MLoop *mloop, const struct MPoly *mpoly,
+        const struct MVert *mvert,
+        int totloop, int totpoly,
+        struct MLoopTri *mlooptri);
 int BKE_mesh_mpoly_to_mface(
         struct CustomData *fdata, struct CustomData *ldata,
         struct CustomData *pdata, int totface, int totloop, int totpoly);
index 09ccc3dced73652ab30761ac8eaff501715a7599..c9192fddec6bcf1dd520f72c02343f8fc680f36b 100644 (file)
@@ -40,6 +40,8 @@ struct CurveMapping;
 struct MeshElemMap;
 struct GridPaintMask;
 struct Main;
+struct MLoop;
+struct MLoopTri;
 struct MFace;
 struct MVert;
 struct Object;
@@ -133,7 +135,7 @@ bool BKE_paint_select_vert_test(struct Object *ob);
 bool BKE_paint_select_elem_test(struct Object *ob);
 
 /* partial visibility */
-bool paint_is_face_hidden(const struct MFace *f, const struct MVert *mvert);
+bool paint_is_face_hidden(const struct MLoopTri *lt, const struct MVert *mvert, const struct MLoop *mloop);
 bool paint_is_grid_face_hidden(const unsigned int *grid_hidden,
                                int gridsize, int x, int y);
 bool paint_is_bmesh_face_hidden(struct BMFace *f);
index fbaf91d60bddca3320e2426a226cacde005b9508..79b285faaf56ac45affbe3d4f4fcbe49ce1a6a87 100644 (file)
@@ -34,7 +34,9 @@ struct CCGElem;
 struct CCGKey;
 struct CustomData;
 struct DMFlagMat;
-struct MFace;
+struct MPoly;
+struct MLoop;
+struct MLoopTri;
 struct MVert;
 struct PBVH;
 struct PBVHNode;
@@ -60,8 +62,10 @@ typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *
 
 PBVH *BKE_pbvh_new(void);
 void BKE_pbvh_build_mesh(
-        PBVH *bvh, const struct MFace *faces, struct MVert *verts,
-        int totface, int totvert, struct CustomData *vdata);
+        PBVH *bvh,
+        const struct MPoly *mpoly, const struct MLoop *mloop,
+        struct MVert *verts, int totvert, struct CustomData *vdata,
+        const struct MLoopTri *looptri, int looptri_num);
 void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
                           int totgrid,
                           struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
index 7ced227f5b732bf6620596bb02ba0e5762528552..1bf49ad8fb05cae79b060feb26d6487f9df1946d 100644 (file)
@@ -220,6 +220,11 @@ static MPoly *dm_dupPolyArray(DerivedMesh *dm)
        return tmp;
 }
 
+static int dm_getNumLoopTri(DerivedMesh *dm)
+{
+       return dm->looptris.num;
+}
+
 static CustomData *dm_getVertCData(DerivedMesh *dm)
 {
        return &dm->vertData;
@@ -263,6 +268,9 @@ void DM_init_funcs(DerivedMesh *dm)
        dm->dupLoopArray = dm_dupLoopArray;
        dm->dupPolyArray = dm_dupPolyArray;
 
+       /* subtypes handle getting actual data */
+       dm->getNumLoopTri = dm_getNumLoopTri;
+
        dm->getVertDataLayout = dm_getVertCData;
        dm->getEdgeDataLayout = dm_getEdgeCData;
        dm->getTessFaceDataLayout = dm_getTessFaceCData;
@@ -364,6 +372,10 @@ int DM_release(DerivedMesh *dm)
                        dm->totmat = 0;
                }
 
+               MEM_SAFE_FREE(dm->looptris.array);
+               dm->looptris.num = 0;
+               dm->looptris.num_alloc = 0;
+
                return 1;
        }
        else {
@@ -440,6 +452,47 @@ void DM_ensure_tessface(DerivedMesh *dm)
        dm->dirty &= ~DM_DIRTY_TESS_CDLAYERS;
 }
 
+/**
+ * Ensure the array is large enough
+ */
+void DM_ensure_looptri_data(DerivedMesh *dm)
+{
+       const unsigned int totpoly = dm->numPolyData;
+       const unsigned int totloop = dm->numLoopData;
+       const int looptris_num = poly_to_tri_count(totpoly, totloop);
+
+       if ((looptris_num > dm->looptris.num_alloc) ||
+           (looptris_num < dm->looptris.num_alloc * 2) ||
+           (totpoly == 0))
+       {
+               MEM_SAFE_FREE(dm->looptris.array);
+               dm->looptris.num_alloc = 0;
+               dm->looptris.num = 0;
+       }
+
+       if (totpoly) {
+               if (dm->looptris.array == NULL) {
+                       dm->looptris.array = MEM_mallocN(sizeof(*dm->looptris.array) * looptris_num, __func__);
+                       dm->looptris.num_alloc = looptris_num;
+               }
+
+               dm->looptris.num = looptris_num;
+       }
+}
+
+/**
+ * The purpose of this function is that we can call:
+ * `dm->getLoopTriArray(dm)` and get the array returned.
+ */
+void DM_ensure_looptri(DerivedMesh *dm)
+{
+       const int numPolys =  dm->getNumPolys(dm);
+
+       if ((dm->looptris.num == 0) && (numPolys != 0)) {
+               dm->recalcLoopTri(dm);
+       }
+}
+
 /* Update tessface CD data from loop/poly ones. Needed when not retessellating after modstack evaluation. */
 /* NOTE: Assumes dm has valid tessellated data! */
 void DM_update_tessface_data(DerivedMesh *dm)
@@ -546,6 +599,29 @@ MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr)
        return tf_base;
 }
 
+MLoopUV *DM_paint_uvlayer_active_get_mloopuv(DerivedMesh *dm, int mat_nr)
+{
+       MLoopUV *uv_base;
+
+       BLI_assert(mat_nr < dm->totmat);
+
+       if (dm->mat[mat_nr] && dm->mat[mat_nr]->texpaintslot &&
+           dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname)
+       {
+               uv_base = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV,
+                                                    dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname);
+               /* This can fail if we have changed the name in the UV layer list and have assigned the old name in the material
+                * texture slot.*/
+               if (!uv_base)
+                       uv_base = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
+       }
+       else {
+               uv_base = CustomData_get_layer(&dm->loopData, CD_MLOOPUV);
+       }
+
+       return uv_base;
+}
+
 void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask, bool take_ownership)
 {
        /* dm might depend on me, so we need to do everything with a local copy */
@@ -2031,7 +2107,12 @@ static void mesh_calc_modifiers(
        }
 
        if (sculpt_dyntopo == false) {
+               /* watch this! after 2.75a we move to from tessface to looptri (by default) */
+#if 0
                DM_ensure_tessface(finaldm);
+#else
+               DM_ensure_looptri(finaldm);
+#endif
 
                /* without this, drawing ngon tri's faces will show ugly tessellated face
                 * normals and will also have to calculate normals on the fly, try avoid
@@ -3160,17 +3241,20 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
                                attribs->tface[a].gl_texco = gattribs->layer[b].gltexco;
                        }
                        else {
+                               /* exception .. */
+                               CustomData *ldata = dm->getLoopDataLayout(dm);
+
                                if (gattribs->layer[b].name[0])
-                                       layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE,
+                                       layer = CustomData_get_named_layer_index(ldata, CD_MLOOPUV,
                                                                                 gattribs->layer[b].name);
                                else
-                                       layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE);
+                                       layer = CustomData_get_active_layer_index(ldata, CD_MLOOPUV);
 
                                a = attribs->tottface++;
 
                                if (layer != -1) {
-                                       attribs->tface[a].array = tfdata->layers[layer].data;
-                                       attribs->tface[a].em_offset = tfdata->layers[layer].offset;
+                                       attribs->tface[a].array = ldata->layers[layer].data;
+                                       attribs->tface[a].em_offset = ldata->layers[layer].offset;
                                }
                                else {
                                        attribs->tface[a].array = NULL;
@@ -3207,19 +3291,22 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
                                attribs->mcol[a].gl_index = gattribs->layer[b].glindex;
                        }
                        else {
+                               /* exception .. */
+                               CustomData *ldata = dm->getLoopDataLayout(dm);
+
                                /* vertex colors */
                                if (gattribs->layer[b].name[0])
-                                       layer = CustomData_get_named_layer_index(tfdata, CD_MCOL,
+                                       layer = CustomData_get_named_layer_index(ldata, CD_MLOOPCOL,
                                                                                 gattribs->layer[b].name);
                                else
-                                       layer = CustomData_get_active_layer_index(tfdata, CD_MCOL);
+                                       layer = CustomData_get_active_layer_index(ldata, CD_MLOOPCOL);
 
                                a = attribs->totmcol++;
 
                                if (layer != -1) {
-                                       attribs->mcol[a].array = tfdata->layers[layer].data;
+                                       attribs->mcol[a].array = ldata->layers[layer].data;
                                        /* odd, store the offset for a different layer type here, but editmode draw code expects it */
-                                       attribs->mcol[a].em_offset = tfdata->layers[layer].offset;
+                                       attribs->mcol[a].em_offset = ldata->layers[layer].offset;
                                }
                                else {
                                        attribs->mcol[a].array = NULL;
@@ -3266,13 +3353,15 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
        }
 }
 
-/* Set vertex shader attribute inputs for a particular tessface vert
+/**
+ * Set vertex shader attribute inputs for a particular tessface vert
  *
- * a: tessface index
- * index: vertex index
- * vert: corner index (0, 1, 2, 3)
+ * \param a: tessface index
+ * \param index: vertex index
+ * \param vert: corner index (0, 1, 2, 3)
+ * \param loop: absolute loop corner index
  */
-void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert)
+void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop)
 {
        const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
        int b;
@@ -3293,8 +3382,8 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert)
                const float *uv;
 
                if (attribs->tface[b].array) {
-                       MTFace *tf = &attribs->tface[b].array[a];
-                       uv = tf->uv[vert];
+                       const MLoopUV *mloopuv = &attribs->tface[b].array[loop];
+                       uv = mloopuv->uv;
                }
                else {
                        uv = zero;
@@ -3311,8 +3400,8 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert)
                GLubyte col[4];
 
                if (attribs->mcol[b].array) {
-                       MCol *cp = &attribs->mcol[b].array[a * 4 + vert];
-                       col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
+                       const MLoopCol *cp = &attribs->mcol[b].array[loop];
+                       copy_v4_v4_char((char *)col, &cp->r);
                }
                else {
                        col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
index c16af7c2412ef063395a0fd5da69245e2b568ec2..6f2579442c35041fe595ab1a47ef8711471f41e9 100644 (file)
@@ -296,15 +296,26 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
         * that this is actually for, to support a pbvh on a modified mesh */
        if (!cddm->pbvh && ob->type == OB_MESH) {
                Mesh *me = ob->data;
+               const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
+               MLoopTri *looptri;
                bool deformed;
 
                cddm->pbvh = BKE_pbvh_new();
                cddm->pbvh_draw = can_pbvh_draw(ob, dm);
 
-               BKE_mesh_tessface_ensure(me);
+               looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
+
+               BKE_mesh_recalc_looptri(
+                       me->mloop, me->mpoly,
+                       me->mvert,
+                       me->totloop, me->totpoly,
+                       looptri);
                
-               BKE_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
-                                   me->totface, me->totvert, &me->vdata);
+               BKE_pbvh_build_mesh(
+                       cddm->pbvh,
+                       me->mpoly, me->mloop,
+                       me->mvert, me->totvert, &me->vdata,
+                       looptri, looptris_num);
 
                pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color);
 
@@ -333,10 +344,10 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
        CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
        float (*face_nors)[3];
 
-       if (!cddm->pbvh || !cddm->pbvh_draw || !dm->numTessFaceData)
+       if (!cddm->pbvh || !cddm->pbvh_draw || !dm->numPolyData)
                return;
 
-       face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+       face_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL);
 
        BKE_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
 }
@@ -354,37 +365,31 @@ static void cdDM_drawVerts(DerivedMesh *dm)
 static void cdDM_drawUVEdges(DerivedMesh *dm)
 {
        CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
-       MFace *mf = cddm->mface;
+       const MPoly *mpoly = cddm->mpoly;
+       int totpoly = dm->getNumPolys(dm);
+       int prevstart = 0;
+       bool prevdraw = true;
+       int curpos = 0;
        int i;
 
-       if (mf) {
-               int prevstart = 0;
-               bool prevdraw = true;
-               int curpos = 0;
-               
-               GPU_uvedge_setup(dm);
-               for (i = 0; i < dm->numTessFaceData; i++, mf++) {
-                       const bool draw = (mf->flag & ME_HIDE) == 0;
+       GPU_uvedge_setup(dm);
+       for (i = 0; i < totpoly; i++, mpoly++) {
+               const bool draw = (mpoly->flag & ME_HIDE) == 0;
 
-                       if (prevdraw != draw) {
-                               if (prevdraw && (curpos != prevstart)) {
-                                       glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
-                               }
-                               prevstart = curpos;
-                       }
-                       if (mf->v4) {
-                               curpos += 8;
-                       }
-                       else {
-                               curpos += 6;
+               if (prevdraw != draw) {
+                       if (prevdraw && (curpos != prevstart)) {
+                               glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
                        }
-                       prevdraw = draw;
+                       prevstart = curpos;
                }
-               if (prevdraw && (curpos != prevstart)) {
-                       glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
-               }
-               GPU_buffer_unbind();
+
+               curpos += 2 * mpoly->totloop;
+               prevdraw = draw;
+       }
+       if (prevdraw && (curpos != prevstart)) {
+               glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
        }
+       GPU_buffer_unbind();
 }
 
 static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
@@ -477,10 +482,10 @@ static void cdDM_drawFacesTex_common(
         void *userData, DMDrawFlag uvflag)
 {
        CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
-       const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
+       const MPoly *mpoly = cddm->mpoly;
        MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
-       MCol *mcol;
-       int i, orig;
+       const  MLoopCol *mloopcol;
+       int i;
        int colType, start_element, tot_drawn;
        bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
        int totpoly;
@@ -489,11 +494,7 @@ static void cdDM_drawFacesTex_common(
        int tot_element;
 
        /* double lookup */
-       const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
        const int *index_mp_to_orig  = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-       if (index_mf_to_mpoly == NULL) {
-               index_mp_to_orig = NULL;
-       }
 
        /* TODO: not entirely correct, but currently dynamic topology will
         *       destroy UVs anyway, so textured display wouldn't work anyway
@@ -511,15 +512,15 @@ static void cdDM_drawFacesTex_common(
                return;
        }
 
-       colType = CD_TEXTURE_MCOL;
-       mcol = dm->getTessFaceDataArray(dm, colType);
-       if (!mcol) {
+       colType = CD_TEXTURE_MLOOPCOL;
+       mloopcol = dm->getLoopDataArray(dm, colType);
+       if (!mloopcol) {
                colType = CD_PREVIEW_MCOL;
-               mcol = dm->getTessFaceDataArray(dm, colType);
+               mloopcol = dm->getLoopDataArray(dm, colType);
        }
-       if (!mcol) {
-               colType = CD_MCOL;
-               mcol = dm->getTessFaceDataArray(dm, colType);
+       if (!mloopcol) {
+               colType = CD_MLOOPCOL;
+               mloopcol = dm->getLoopDataArray(dm, colType);
        }
 
        cdDM_update_normals_from_pbvh(dm);
@@ -531,7 +532,7 @@ static void cdDM_drawFacesTex_common(
                GPU_texpaint_uv_setup(dm);
        else
                GPU_uv_setup(dm);
-       if (mcol) {
+       if (mloopcol) {
                GPU_color_setup(dm, colType);
        }
                
@@ -550,24 +551,18 @@ static void cdDM_drawFacesTex_common(
                        int actualFace = bufmat->polys[i];
                        DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
                        int flush = 0;
+                       int tot_tri_verts;
 
                        if (i != totpoly - 1)
                                next_actualFace = bufmat->polys[i + 1];
 
                        if (drawParams) {
-                               MTexPoly *tp = NULL;
-                               if (use_tface && mtexpoly && index_mf_to_mpoly) {
-                                       int actualFace_poly = index_mf_to_mpoly[actualFace];
-                                       if (actualFace_poly != ORIGINDEX_NONE) {
-                                               tp = &mtexpoly[actualFace_poly];
-                                       }
-                               }
-
-                               draw_option = drawParams(tp, (mcol != NULL), mf[actualFace].mat_nr);
+                               MTexPoly *tp = use_tface && mtexpoly ? &mtexpoly[actualFace] : NULL;
+                               draw_option = drawParams(tp, (mloopcol != NULL), mpoly[actualFace].mat_nr);
                        }
                        else {
-                               if (index_mf_to_mpoly) {
-                                       orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace);
+                               if (index_mp_to_orig) {
+                                       const int orig = index_mp_to_orig[actualFace];
                                        if (orig == ORIGINDEX_NONE) {
                                                /* XXX, this is not really correct
                                                 * it will draw the previous faces context for this one when we don't know its settings.
@@ -575,11 +570,11 @@ static void cdDM_drawFacesTex_common(
                                                draw_option = DM_DRAW_OPTION_NORMAL;
                                        }
                                        else if (drawParamsMapped) {
-                                               draw_option = drawParamsMapped(userData, orig, mf[actualFace].mat_nr);
+                                               draw_option = drawParamsMapped(userData, orig, mpoly[actualFace].mat_nr);
                                        }
                                }
                                else if (drawParamsMapped) {
-                                       draw_option = drawParamsMapped(userData, actualFace, mf[actualFace].mat_nr);
+                                       draw_option = drawParamsMapped(userData, actualFace, mpoly[actualFace].mat_nr);
                                }
                        }
 
@@ -592,14 +587,15 @@ static void cdDM_drawFacesTex_common(
                                flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
                        }
 
-                       tot_element += mf[actualFace].v4 ? 6 : 3;
+                       tot_tri_verts = ME_POLY_TRI_TOT(&mpoly[actualFace]) * 3;
+                       tot_element += tot_tri_verts;
 
                        if (flush) {
                                if (draw_option != DM_DRAW_OPTION_SKIP)
-                                       tot_drawn += mf[actualFace].v4 ? 6 : 3;
+                                       tot_drawn += tot_tri_verts;
 
                                if (tot_drawn) {
-                                       if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+                                       if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
                                                GPU_color_switch(1);
                                        else
                                                GPU_color_switch(0);
@@ -610,7 +606,7 @@ static void cdDM_drawFacesTex_common(
                                start_element = tot_element;
                        }
                        else {
-                               tot_drawn += mf[actualFace].v4 ? 6 : 3;
+                               tot_drawn += tot_tri_verts;
                        }
                }
        }
@@ -637,29 +633,24 @@ static void cdDM_drawMappedFaces(
         void *userData, DMDrawFlag flag)
 {
        CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
-       MFace *mf = cddm->mface;
-       MCol *mcol;
+       const MPoly *mpoly = cddm->mpoly;
+       const MLoopCol *mloopcol = NULL;
        int colType, useColors = flag & DM_DRAW_USE_COLORS, useHide = flag & DM_DRAW_SKIP_HIDDEN;
-       int i, orig;
+       int i, j, orig;
        int start_element = 0, tot_element, tot_drawn;
        int totpoly;
        int tottri;
        int mat_index;
        GPUBuffer *findex_buffer = NULL;
 
-       /* double lookup */
-       const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
        const int *index_mp_to_orig  = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-       if (index_mf_to_mpoly == NULL) {
-               index_mp_to_orig = NULL;
-       }
-
-       cdDM_update_normals_from_pbvh(dm);
 
        /* fist, setup common buffers */
        GPU_vertex_setup(dm);
        GPU_triangle_setup(dm);
 
+       totpoly = dm->getNumPolys(dm);
+
        /* if we do selection, fill the selection buffer color */
        if (G.f & G_BACKBUFSEL) {
                Mesh *me = userData;
@@ -669,46 +660,43 @@ static void cdDM_drawMappedFaces(
                fi_map = GPU_buffer_lock(findex_buffer, GPU_BINDING_ARRAY);
 
                if (fi_map) {
-                       for (i = 0; i < dm->numTessFaceData; i++, mf++) {
+                       for (i = 0; i < totpoly; i++, mpoly++) {
                                int selcol = 0xFFFFFFFF;
-                               orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i;
+                               orig = (index_mp_to_orig) ? index_mp_to_orig[i] : i;
 
                                if ((orig != ORIGINDEX_NONE) && (!useHide || !(me->mpoly[orig].flag & ME_HIDE))) {
                                        WM_framebuffer_index_get(orig + 1, &selcol);
                                }
 
-                               fi_map[start_element++] = selcol;
-                               fi_map[start_element++] = selcol;
-                               fi_map[start_element++] = selcol;
-
-                               if (mf->v4) {
+                               for (j = 0; j < mpoly->totloop; j++)
                                        fi_map[start_element++] = selcol;
-                               }
                        }
 
                        start_element = 0;
-                       mf = cddm->mface;
+                       mpoly = cddm->mpoly;
 
                        GPU_buffer_unlock(findex_buffer, GPU_BINDING_ARRAY);
                        GPU_buffer_bind_as_color(findex_buffer);
                }
        }
        else {
+               cdDM_update_normals_from_pbvh(dm);
+
                GPU_normal_setup(dm);
 
                if (useColors) {
-                       colType = CD_TEXTURE_MCOL;
-                       mcol = DM_get_tessface_data_layer(dm, colType);
-                       if (!mcol) {
-                               colType = CD_PREVIEW_MCOL;
-                               mcol = DM_get_tessface_data_layer(dm, colType);
+                       colType = CD_TEXTURE_MLOOPCOL;
+                       mloopcol = DM_get_loop_data_layer(dm, colType);
+                       if (!mloopcol) {
+                               colType = CD_PREVIEW_MLOOPCOL;
+                               mloopcol = DM_get_loop_data_layer(dm, colType);
                        }
-                       if (!mcol) {
-                               colType = CD_MCOL;
-                               mcol = DM_get_tessface_data_layer(dm, colType);
+                       if (!mloopcol) {
+                               colType = CD_MLOOPCOL;
+                               mloopcol = DM_get_loop_data_layer(dm, colType);
                        }
 
-                       if (useColors && mcol) {
+                       if (useColors && mloopcol) {
                                GPU_color_setup(dm, colType);
                        }
                }
@@ -744,12 +732,14 @@ static void cdDM_drawMappedFaces(
                                for (i = 0; i < totpoly; i++) {
                                        int actualFace = next_actualFace;
                                        int flush = 0;
+                                       int tot_tri_verts;
+
                                        draw_option = DM_DRAW_OPTION_NORMAL;
 
                                        if (i != totpoly - 1)
                                                next_actualFace = bufmat->polys[i + 1];
 
-                                       orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace;
+                                       orig = (index_mp_to_orig) ? index_mp_to_orig[i] : i;
 
                                        if (setDrawOptions != NULL && (orig != ORIGINDEX_NONE))
                                                draw_option = setDrawOptions(userData, orig);
@@ -770,11 +760,12 @@ static void cdDM_drawMappedFaces(
                                                flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
                                        }
 
-                                       tot_element += mf[actualFace].v4 ? 6 : 3;
+                                       tot_tri_verts = ME_POLY_TRI_TOT(&mpoly[actualFace]) * 3;
+                                       tot_element += tot_tri_verts;
 
                                        if (flush) {
                                                if (!ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE))
-                                                       tot_drawn += mf[actualFace].v4 ? 6 : 3;
+                                                       tot_drawn += tot_tri_verts;
 
                                                if (tot_drawn) {
                                                        GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
@@ -787,7 +778,7 @@ static void cdDM_drawMappedFaces(
                                                        glDisable(GL_POLYGON_STIPPLE);
                                        }
                                        else {
-                                               tot_drawn += mf[actualFace].v4 ? 6 : 3;
+                                               tot_drawn += tot_tri_verts;
                                        }
                                }
                        }
@@ -812,14 +803,15 @@ static void cdDM_drawMappedFacesTex(
        cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
 }
 
-static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int vert,
-                                    const short (*lnor)[3], const bool smoothnormal)
+static void cddm_draw_attrib_vertex(
+        DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int loop, int vert,
+        const float *lnor, const bool smoothnormal)
 {
-       DM_draw_attrib_vertex(attribs, a, index, vert);
+       DM_draw_attrib_vertex(attribs, a, index, vert, loop);
 
        /* vertex normal */
        if (lnor) {
-               glNormal3sv((const GLshort *)lnor);
+               glNormal3fv(lnor);
        }
        else if (smoothnormal) {
                glNormal3sv(mvert[index].no);
@@ -845,20 +837,19 @@ static void cdDM_drawMappedFacesGLSL(
        CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
        GPUVertexAttribs gattribs;
        const MVert *mvert = cddm->mvert;
-       const MFace *mface = cddm->mface;
+       const MPoly *mpoly = cddm->mpoly;
+       const MLoop *mloop = cddm->mloop;
+       const MLoopTri *lt = dm->getLoopTriArray(dm);
+       const int tottri = dm->getNumLoopTri(dm);
        /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
-       const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
-       const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+       const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+       const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
+       const int totpoly = dm->getNumPolys(dm);
        int a, b, matnr, new_matnr;
        bool do_draw;
        int orig;
 
-       /* double lookup */
-       const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
        const int *index_mp_to_orig  = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-       if (index_mf_to_mpoly == NULL) {
-               index_mp_to_orig = NULL;
-       }
 
        /* TODO: same as for solid draw, not entirely correct, but works fine for now,
         *       will skip using textures (dyntopo currently destroys UV anyway) and
@@ -888,12 +879,15 @@ static void cdDM_drawMappedFacesGLSL(
                DEBUG_VBO("Using legacy code. cdDM_drawMappedFacesGLSL\n");
                memset(&attribs, 0, sizeof(attribs));
 
-               glBegin(GL_QUADS);
+               glBegin(GL_TRIANGLES);
 
-               for (a = 0; a < dm->numTessFaceData; a++, mface++) {
-                       const bool smoothnormal = lnors || (mface->flag & ME_SMOOTH);
-                       const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL;
-                       new_matnr = mface->mat_nr;
+               for (a = 0; a < tottri; a++, lt++) {
+                       const MPoly *mp = &mpoly[lt->poly];
+                       const unsigned int  vtri[3] = {mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v};
+                       const unsigned int *ltri = lt->tri;
+                       const float *ln1 = NULL, *ln2 = NULL, *ln3 = NULL;
+                       const bool smoothnormal = lnors || (mp->flag & ME_SMOOTH);
+                       new_matnr = mp->mat_nr;
 
                        if (new_matnr != matnr) {
                                glEnd();
@@ -909,7 +903,7 @@ static void cdDM_drawMappedFacesGLSL(
                                continue;
                        }
                        else if (setDrawOptions) {
-                               orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+                               orig = (index_mp_to_orig) ? index_mp_to_orig[lt->poly] : lt->poly;
 
                                if (orig == ORIGINDEX_NONE) {
                                        /* since the material is set by setMaterial(), faces with no
@@ -928,46 +922,32 @@ static void cdDM_drawMappedFacesGLSL(
                                else {
                                        /* TODO ideally a normal layer should always be available */
                                        float nor[3];
-                                       if (mface->v4) {
-                                               normal_quad_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
-                                       }
-                                       else {
-                                               normal_tri_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
-                                       }
+                                       normal_tri_v3(nor, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co);
                                        glNormal3fv(nor);
                                }
                        }
                        else if (lnors) {
-                               ln1 = &lnors[a][0];
-                               ln2 = &lnors[a][1];
-                               ln3 = &lnors[a][2];
-                               ln4 = &lnors[a][3];
+                               ln1 = lnors[ltri[0]];
+                               ln2 = lnors[ltri[1]];
+                               ln3 = lnors[ltri[2]];
                        }
                        
-                       cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, ln1, smoothnormal);
-                       cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, ln2, smoothnormal);
-                       cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, ln3, smoothnormal);
-                       
-                       if (mface->v4)
-                               cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, ln4, smoothnormal);
-                       else
-                               cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, ln3, smoothnormal);
+                       cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[0], ltri[0], 0, ln1, smoothnormal);
+                       cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[1], ltri[1], 1, ln2, smoothnormal);
+                       cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[2], ltri[2], 2, ln3, smoothnormal);
                }
                glEnd();
        }
        else {
                GPUMaterialConv *matconv;
                int offset;
-               int totface = dm->getNumTessFaces(dm);
                int *mat_orig_to_new;
                int tot_active_mat;
                GPUBuffer *buffer = NULL;
                char *varray;
                int max_element_size = 0;
                int tot_loops = 0;
-               
-               const MFace *mf = mface;
-               
+
                GPU_vertex_setup(dm);
                GPU_normal_setup(dm);
                GPU_triangle_setup(dm);
@@ -1044,75 +1024,47 @@ static void cdDM_drawMappedFacesGLSL(
                                return;
                        }
 
-                       mface = mf;
-
-                       for (a = 0; a < totface; a++, mface++) {
-                               int i = mat_orig_to_new[mface->mat_nr];
+                       for (a = 0; a < totpoly; a++, mpoly++) {
+                               int j;
+                               int i = mat_orig_to_new[mpoly->mat_nr];
                                offset = tot_loops * max_element_size;
 
                                if (matconv[i].numdata != 0) {
                                        if (matconv[i].attribs.totorco && matconv[i].attribs.orco.array) {
-                                               copy_v3_v3((float *)&varray[offset], (float *)matconv[i].attribs.orco.array[mface->v1]);
-                                               copy_v3_v3((float *)&varray[offset + max_element_size], (float *)matconv[i].attribs.orco.array[mface->v2]);
-                                               copy_v3_v3((float *)&varray[offset + max_element_size * 2], (float *)matconv[i].attribs.orco.array[mface->v3]);
-                                               if (mface->v4) {
-                                                       copy_v3_v3((float *)&varray[offset + max_element_size * 3], (float *)matconv[i].attribs.orco.array[mface->v4]);
-                                               }
+                                               for (j = 0; j < mpoly->totloop; j++)
+                                                       copy_v3_v3((float *)&varray[offset + j * max_element_size],
+                                                                  (float *)matconv[i].attribs.orco.array[mloop[mpoly->loopstart + j].v]);
                                                offset += sizeof(float) * 3;
                                        }
                                        for (b = 0; b < matconv[i].attribs.tottface; b++) {
                                                if (matconv[i].attribs.tface[b].array) {
-                                                       MTFace *tf = &matconv[i].attribs.tface[b].array[a];
-                                                       copy_v2_v2((float *)&varray[offset], tf->uv[0]);
-                                                       copy_v2_v2((float *)&varray[offset + max_element_size], tf->uv[1]);
-                                                       copy_v2_v2((float *)&varray[offset + max_element_size * 2], tf->uv[2]);
-                                                       if (mface->v4) {
-                                                               copy_v2_v2((float *)&varray[offset + max_element_size * 3], tf->uv[3]);
-                                                       }
+                                                       const MLoopUV *mloopuv = matconv[i].attribs.tface[b].array;
+                                                       for (j = 0; j < mpoly->totloop; j++)
+                                                               copy_v2_v2((float *)&varray[offset + j * max_element_size], mloopuv[mpoly->loopstart + j].uv);
                                                        offset += sizeof(float) * 2;
                                                }
                                        }
                                        for (b = 0; b < matconv[i].attribs.totmcol; b++) {
                                                if (matconv[i].attribs.mcol[b].array) {
-                                                       MCol *cp = &matconv[i].attribs.mcol[b].array[a * 4 + 0];
-                                                       GLubyte col[4];
-                                                       col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
-                                                       copy_v4_v4_char((char *)&varray[offset], (char *)col);
-                                                       cp = &matconv[i].attribs.mcol[b].array[a * 4 + 1];
-                                                       col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
-                                                       copy_v4_v4_char((char *)&varray[offset + max_element_size], (char *)col);
-                                                       cp = &matconv[i].attribs.mcol[b].array[a * 4 + 2];
-                                                       col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
-                                                       copy_v4_v4_char((char *)&varray[offset + max_element_size * 2], (char *)col);
-                                                       if (mface->v4) {
-                                                               cp = &matconv[i].attribs.mcol[b].array[a * 4 + 3];
-                                                               col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a;
-                                                               copy_v4_v4_char((char *)&varray[offset + max_element_size * 3], (char *)col);
-                                                       }
+                                                       const MLoopCol *mloopcol = matconv[i].attribs.mcol[b].array;
+                                                       for (j = 0; j < mpoly->totloop; j++)
+                                                               copy_v4_v4_char((char *)&varray[offset + j * max_element_size], &mloopcol[mpoly->loopstart + j].r);
                                                        offset += sizeof(unsigned char) * 4;
                                                }
                                        }
+                                       /* TODO, handle tangents */
                                        if (matconv[i].attribs.tottang && matconv[i].attribs.tang.array) {
-                                               const float *tang = matconv[i].attribs.tang.array[a * 4 + 0];
+                                               const float *tang = matconv[i].attribs.tang.array[i * 4 + 0];
                                                copy_v4_v4((float *)&varray[offset], tang);
-                                               tang = matconv[i].attribs.tang.array[a * 4 + 1];
+                                               tang = matconv[i].attribs.tang.array[i * 4 + 1];
                                                copy_v4_v4((float *)&varray[offset + max_element_size], tang);
-                                               tang = matconv[i].attribs.tang.array[a * 4 + 2];
+                                               tang = matconv[i].attribs.tang.array[i * 4 + 2];
                                                copy_v4_v4((float *)&varray[offset + max_element_size * 2], tang);
-                                               if (mface->v4) {
-                                                       tang = matconv[i].attribs.tang.array[a * 4 + 3];
-                                                       copy_v4_v4((float *)&varray[offset + max_element_size * 3], tang);
-                                               }
                                                offset += sizeof(float) * 4;
                                        }
                                }
 
-                               if (mface->v4) {
-                                       tot_loops += 4;
-                               }
-                               else {
-                                       tot_loops += 3;
-                               }
+                               tot_loops += mpoly->totloop;
                        }
                        GPU_buffer_unlock(buffer, GPU_BINDING_ARRAY);
                }
@@ -1159,18 +1111,16 @@ static void cdDM_drawMappedFacesMat(
        GPUVertexAttribs gattribs;
        DMVertexAttribs attribs;
        MVert *mvert = cddm->mvert;
-       MFace *mf = cddm->mface;
-       const float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
-       const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+       const MPoly *mpoly = cddm->mpoly;
+       const MLoop *mloop = cddm->mloop;
+       const MLoopTri *lt = dm->getLoopTriArray(dm);
+       const int tottri = dm->getNumLoopTri(dm);
+       const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+       const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
        int a, matnr, new_matnr;
        int orig;
 
-       /* double lookup */
-       const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
        const int *index_mp_to_orig  = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-       if (index_mf_to_mpoly == NULL) {
-               index_mp_to_orig = NULL;
-       }
 
        /* TODO: same as for solid draw, not entirely correct, but works fine for now,
         *       will skip using textures (dyntopo currently destroys UV anyway) and
@@ -1193,14 +1143,17 @@ static void cdDM_drawMappedFacesMat(
 
        memset(&attribs, 0, sizeof(attribs));
 
-       glBegin(GL_QUADS);
+       glBegin(GL_TRIANGLES);
 
-       for (a = 0; a < dm->numTessFaceData; a++, mf++) {
-               const bool smoothnormal = lnors || (mf->flag & ME_SMOOTH);
-               const short (*ln1)[3] = NULL, (*ln2)[3] = NULL, (*ln3)[3] = NULL, (*ln4)[3] = NULL;
+       for (a = 0; a < tottri; a++, lt++) {
+               const MPoly *mp = &mpoly[lt->poly];
+               const unsigned int  vtri[3] = {mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v};
+               const unsigned int *ltri = lt->tri;
+               const bool smoothnormal = lnors || (mp->flag & ME_SMOOTH);
+               const float *ln1 = NULL, *ln2 = NULL, *ln3 = NULL;
 
                /* material */
-               new_matnr = mf->mat_nr + 1;
+               new_matnr = mp->mat_nr + 1;
 
                if (new_matnr != matnr) {
                        glEnd();
@@ -1208,12 +1161,12 @@ static void cdDM_drawMappedFacesMat(
                        setMaterial(userData, matnr = new_matnr, &gattribs);
                        DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
 
-                       glBegin(GL_QUADS);
+                       glBegin(GL_TRIANGLES);
                }
 
                /* skipping faces */
                if (setFace) {
-                       orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
+                       orig = (index_mp_to_orig) ? index_mp_to_orig[a] : lt->poly;
 
                        if (orig != ORIGINDEX_NONE && !setFace(userData, orig))
                                continue;
@@ -1227,31 +1180,20 @@ static void cdDM_drawMappedFacesMat(
                        else {
                                /* TODO ideally a normal layer should always be available */
                                float nor[3];
-
-                               if (mf->v4)
-                                       normal_quad_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
-                               else
-                                       normal_tri_v3(nor, mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
-
+                               normal_tri_v3(nor, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co);
                                glNormal3fv(nor);
                        }
                }
                else if (lnors) {
-                       ln1 = &lnors[a][0];
-                       ln2 = &lnors[a][1];
-                       ln3 = &lnors[a][2];
-                       ln4 = &lnors[a][3];
+                       ln1 = lnors[ltri[0]];
+                       ln2 = lnors[ltri[1]];
+                       ln3 = lnors[ltri[2]];
                }
 
                /* vertices */
-               cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v1, 0, ln1, smoothnormal);
-               cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v2, 1, ln2, smoothnormal);
-               cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, ln3, smoothnormal);
-
-               if (mf->v4)
-                       cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v4, 3, ln4, smoothnormal);
-               else
-                       cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, ln3, smoothnormal);
+               cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[0], ltri[0], 0, ln1, smoothnormal);
+               cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[1], ltri[1], 1, ln2, smoothnormal);
+               cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[2], ltri[2], 2, ln3, smoothnormal);
        }
        glEnd();
 
@@ -1287,59 +1229,48 @@ static void cdDM_buffer_copy_triangles(
         const int *mat_orig_to_new)
 {
        GPUBufferMaterial *gpumat;
-       MFace *f;
-       int i, start, totface, findex = 0;
+       int i, findex = 0;
+
+       const MPoly *mpoly;
+       const MLoopTri *lt = dm->getLoopTriArray(dm);
+       const int tottri = dm->getNumLoopTri(dm);
 
-       f = dm->getTessFaceArray(dm);
+       mpoly = dm->getPolyArray(dm);
 
-       totface = dm->getNumTessFaces(dm);
-       for (i = 0; i < totface; i++, f++) {
-               gpumat = dm->drawObject->materials + mat_orig_to_new[f->mat_nr];
+       for (i = 0; i < tottri; i++, lt++) {
+               int start;
+               gpumat = dm->drawObject->materials + mat_orig_to_new[mpoly[lt->poly].mat_nr];
                start = gpumat->counter;
 
                /* v1 v2 v3 */
-               varray[start++] = findex;
-               varray[start++] = findex + 1;
-               varray[start++] = findex + 2;
+               varray[start++] = lt->tri[0];
+               varray[start++] = lt->tri[1];
+               varray[start++] = lt->tri[2];
 
-               if (f->v4) {
-                       /* v3 v4 v1 */
-                       varray[start++] = findex + 2;
-                       varray[start++] = findex + 3;
-                       varray[start++] = findex;
-
-                       gpumat->counter += 6;
-                       findex += 4;
-               }
-               else {
-                       gpumat->counter += 3;
-                       findex += 3;
-               }
+               gpumat->counter += 3;
+               findex += 3;
        }
 }
 
 static void cdDM_buffer_copy_vertex(
         DerivedMesh *dm, float *varray)
 {
-       MVert *mvert;
-       MFace *f;
-       int i, j, start, totface;
+       const MVert *mvert;
+       const MPoly *mpoly;
+       const MLoop *mloop;
+
+       int i, j, start, totpoly;
 
        mvert = dm->getVertArray(dm);
-       f = dm->getTessFaceArray(dm);
+       mpoly = dm->getPolyArray(dm);
+       mloop = dm->getLoopArray(dm);
+       totpoly = dm->getNumPolys(dm);
 
        start = 0;
-       totface = dm->getNumTessFaces(dm);
-       for (i = 0; i < totface; i++, f++) {
-               /* v1 v2 v3 */
-               copy_v3_v3(&varray[start], mvert[f->v1].co);
-               copy_v3_v3(&varray[start + 3], mvert[f->v2].co);
-               copy_v3_v3(&varray[start + 6], mvert[f->v3].co);
-               start += 9;
-
-               if (f->v4) {
-                       /* v4 */
-                       copy_v3_v3(&varray[start], mvert[f->v4].co);
+
+       for (i = 0; i < totpoly; i++, mpoly++) {
+               for (j = 0; j < mpoly->totloop; j++) {
+                       copy_v3_v3(&varray[start], mvert[mloop[mpoly->loopstart + j].v].co);
                        start += 3;
                }
        }
@@ -1357,80 +1288,52 @@ static void cdDM_buffer_copy_vertex(
 static void cdDM_buffer_copy_normal(
         DerivedMesh *dm, short *varray)
 {
-       int i, totface;
+       int i, j, totpoly;
        int start;
 
-       const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
-       const short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
-       MVert *mvert = dm->getVertArray(dm);
-       MFace *f = dm->getTessFaceArray(dm);
+       const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+       const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
+
+       const MVert *mvert;
+       const MPoly *mpoly;
+       const MLoop *mloop;
+
+       mvert = dm->getVertArray(dm);
+       mpoly = dm->getPolyArray(dm);
+       mloop = dm->getLoopArray(dm);
+       totpoly = dm->getNumPolys(dm);
 
-       totface = dm->getNumTessFaces(dm);
        start = 0;
-       for (i = 0; i < totface; i++, f++) {
-               const int smoothnormal = (f->flag & ME_SMOOTH);
+       for (i = 0; i < totpoly; i++, mpoly++) {
+               const bool smoothnormal = (mpoly->flag & ME_SMOOTH) != 0;
 
-               if (tlnors) {
-                       const short (*ln)[3] = tlnors[i];
+               if (lnors) {
                        /* Copy loop normals */
-                       copy_v3_v3_short(&varray[start], ln[0]);
-                       copy_v3_v3_short(&varray[start + 4], ln[1]);
-                       copy_v3_v3_short(&varray[start + 8], ln[2]);
-                       start += 12;
-
-                       if (f->v4) {
-                               copy_v3_v3_short(&varray[start], ln[3]);
-                               start += 4;
+                       for (j = 0; j < mpoly->totloop; j++, start += 4) {
+                               normal_float_to_short_v3(&varray[start], lnors[mpoly->loopstart + j]);
                        }
                }
                else if (smoothnormal) {
-                       /* copy vertex normal */
-                       copy_v3_v3_short(&varray[start], mvert[f->v1].no);
-                       copy_v3_v3_short(&varray[start + 4], mvert[f->v2].no);
-                       copy_v3_v3_short(&varray[start + 8], mvert[f->v3].no);
-                       start += 12;
-
-                       if (f->v4) {
-                               copy_v3_v3_short(&varray[start], mvert[f->v4].no);
-                               start += 4;
-                       }
-               }
-               else if (nors) {
-                       /* copy cached face normal */
-                       short f_no_s[3];
-
-                       normal_float_to_short_v3(f_no_s, &nors[i * 3]);
-
-                       copy_v3_v3_short(&varray[start], f_no_s);
-                       copy_v3_v3_short(&varray[start + 4], f_no_s);
-                       copy_v3_v3_short(&varray[start + 8], f_no_s);
-                       start += 12;
-
-                       if (f->v4) {
-                               copy_v3_v3_short(&varray[start], f_no_s);
-                               start += 4;
+                       /* Copy vertex normal */
+                       for (j = 0; j < mpoly->totloop; j++, start += 4) {
+                               copy_v3_v3_short(&varray[start], mvert[mloop[mpoly->loopstart + j].v].no);
                        }
                }
                else {
-                       /* calculate face normal */
-                       float f_no[3];
+                       /* Copy cached OR calculated face normal */
                        short f_no_s[3];
 
-                       if (f->v4)
-                               normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
-                       else
-                               normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
-
-                       normal_float_to_short_v3(f_no_s, f_no);
-
-                       copy_v3_v3_short(&varray[start], f_no_s);
-                       copy_v3_v3_short(&varray[start + 4], f_no_s);
-                       copy_v3_v3_short(&varray[start + 8], f_no_s);
-                       start += 12;
+                       if (nors) {
+                               normal_float_to_short_v3(f_no_s, nors[i]);
+                       }
+                       else {
+                               float f_no[3];
+                               BKE_mesh_calc_poly_normal(mpoly, &mloop[mpoly->loopstart], mvert, f_no);
+                               normal_float_to_short_v3(f_no_s, f_no);
+                       }
 
-                       if (f->v4) {
+                       for (j = 0; j < mpoly->totloop; j++, start += 4) {
                                copy_v3_v3_short(&varray[start], f_no_s);
-                               start += 4;
                        }
                }
        }
@@ -1439,90 +1342,68 @@ static void cdDM_buffer_copy_normal(
 static void cdDM_buffer_copy_uv(
         DerivedMesh *dm, float *varray)
 {
+       int i, j, totpoly;
        int start;
-       int i, totface;
 
-       MTFace *mtface;
-       MFace *f;
+       const MPoly *mpoly;
+       const MLoopUV *mloopuv;
 
-       if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
+       if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) {
                return;
-       f = dm->getTessFaceArray(dm);
+       }
+
+       mpoly = dm->getPolyArray(dm);
+       totpoly = dm->getNumPolys(dm);
 
        start = 0;
-       totface = dm->getNumTessFaces(dm);
-       for (i = 0; i < totface; i++, f++) {
-               /* v1 v2 v3 */
-               copy_v2_v2(&varray[start], mtface[i].uv[0]);
-               copy_v2_v2(&varray[start + 2], mtface[i].uv[1]);
-               copy_v2_v2(&varray[start + 4], mtface[i].uv[2]);
-               start += 6;
-
-               if (f->v4) {
-                       /* v4 */
-                       copy_v2_v2(&varray[start], mtface[i].uv[3]);
+       for (i = 0; i < totpoly; i++, mpoly++) {
+               for (j = 0; j < mpoly->totloop; j++) {
+                       copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv);
                        start += 2;
                }
        }
 }
 
-
 static void cdDM_buffer_copy_uv_texpaint(
         DerivedMesh *dm, float *varray)
 {
+       int i, j, totpoly;
        int start;
-       int i, totface;
+
+       const MPoly *mpoly;
 
        int totmaterial = dm->totmat;
-       MTFace **mtface_base;
-       MTFace *stencil_base;
+       const MLoopUV **uv_base;
+       const MLoopUV  *uv_stencil_base;
        int stencil;
-       MFace *mf;
+
+       totpoly = dm->getNumPolys(dm);
 
        /* should have been checked for before, reassert */
-       BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
-       mf = dm->getTessFaceArray(dm);
-       mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
+       BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV));
+       uv_base = MEM_mallocN(totmaterial * sizeof(*uv_base), "texslots");
 
        for (i = 0; i < totmaterial; i++) {
-               mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
+               uv_base[i] = DM_paint_uvlayer_active_get_mloopuv(dm, i);
        }
 
-       stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
-       stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+       stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV);
+       uv_stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil);
 
-       totface = dm->getNumTessFaces(dm);
+       mpoly = dm->getPolyArray(dm);
        start = 0;
 
-       for (i = 0; i < totface; i++, mf++) {
-               int mat_i = mf->mat_nr;
-
-               /* v1 v2 v3 */
-               copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
-               copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
-               copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
-               copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
-               copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
-               copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
-               start += 12;
+       for (i = 0; i < totpoly; i++, mpoly++) {
+               int mat_i = mpoly->mat_nr;
 
-               if (mf->v4) {
-                       /* v4 */
-                       copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[3]);
-                       copy_v2_v2(&varray[start + 2], stencil_base[i].uv[3]);
+               for (j = 0; j < mpoly->totloop; j++) {
+                       copy_v2_v2(&varray[start], uv_base[mat_i][mpoly->loopstart + j].uv);
+                       copy_v2_v2(&varray[start + 2], uv_stencil_base[mpoly->loopstart + j].uv);
                        start += 4;
                }
        }
 
-       MEM_freeN(mtface_base);
-}
-
-
-static void copy_mcol_uc3(unsigned char *v, const unsigned char *col)
-{
-       v[0] = col[3];
-       v[1] = col[2];
-       v[2] = col[1];
+       MEM_freeN(uv_base);
 }
 
 /* treat varray_ as an array of MCol, four MCol's per face */
@@ -1530,22 +1411,19 @@ static void cdDM_buffer_copy_mcol(
         DerivedMesh *dm, unsigned char *varray,
         const void *user_data)
 {
-       int i, totface, start;
-       const unsigned char *mcol = user_data;
-       MFace *f = dm->getTessFaceArray(dm);
+       int i, j, totpoly;
+       int start;
+
+       const MLoopCol *mloopcol = user_data;
+       const MPoly *mpoly = dm->getPolyArray(dm);
+
+       totpoly = dm->getNumPolys(dm);
 
-       totface = dm->getNumTessFaces(dm);
        start = 0;
-       for (i = 0; i < totface; i++, f++) {
-               /* v1 v2 v3 */
-               copy_mcol_uc3(&varray[start], &mcol[i * 16]);
-               copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]);
-               copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]);
-               start += 9;
-
-               if (f->v4) {
-                       /* v3 v4 v1 */
-                       copy_mcol_uc3(&varray[start], &mcol[i * 16 + 12]);
+
+       for (i = 0; i < totpoly; i++, mpoly++) {
+               for (j = 0; j < mpoly->totloop; j++) {
+                       copy_v3_v3_char((char *)&varray[start], &mloopcol[mpoly->loopstart + j].r);
                        start += 3;
                }
        }
@@ -1614,34 +1492,23 @@ static void cdDM_buffer_copy_edge(
 static void cdDM_buffer_copy_uvedge(
         DerivedMesh *dm, float *varray)
 {
-       MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
-       int i, j = 0;
+       int i, j, totpoly;
+       int start;
+       const MLoopUV *mloopuv;
+       const MPoly *mpoly = dm->getPolyArray(dm);
 
-       if (!tf)
+       if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) {
                return;
+       }
 
-       for (i = 0; i < dm->numTessFaceData; i++, tf++) {
-               MFace mf;
-               dm->getTessFace(dm, i, &mf);
-
-               copy_v2_v2(&varray[j], tf->uv[0]);
-               copy_v2_v2(&varray[j + 2], tf->uv[1]);
-
-               copy_v2_v2(&varray[j + 4], tf->uv[1]);
-               copy_v2_v2(&varray[j + 6], tf->uv[2]);
-
-               if (!mf.v4) {
-                       copy_v2_v2(&varray[j + 8], tf->uv[2]);
-                       copy_v2_v2(&varray[j + 10], tf->uv[0]);
-                       j += 12;
-               }
-               else {
-                       copy_v2_v2(&varray[j + 8], tf->uv[2]);
-                       copy_v2_v2(&varray[j + 10], tf->uv[3]);
+       totpoly = dm->getNumPolys(dm);
+       start = 0;
 
-                       copy_v2_v2(&varray[j + 12], tf->uv[3]);
-                       copy_v2_v2(&varray[j + 14], tf->uv[0]);
-                       j += 16;
+       for (i = 0; i < totpoly; i++, mpoly++) {
+               for (j = 0; j < mpoly->totloop; j++) {
+                       copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv);
+                       copy_v2_v2(&varray[start + 2], mloopuv[mpoly->loopstart + (j + 1) % mpoly->totloop].uv);
+                       start += 4;
                }
        }
 }
@@ -1717,22 +1584,13 @@ static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, i
 
 #endif  /* USE_GPU_POINT_LINK */
 
-static int tri_indices[2][3] = {{0, 1, 2}, {2, 3, 0}};
-
-/* update the vert_points and triangle_to_mface fields with a new
- * triangle */
-static void cdDM_drawobject_add_triangle(GPUDrawObject *gdo,
-                                        int v1, int v2, int v3, bool quad, int loopindex)
-{
-       int i, v[3] = {v1, v2, v3};
-       int *tri_i = quad ? tri_indices[1] : tri_indices[0];
-       for (i = 0; i < 3; i++)
-               cdDM_drawobject_add_vert_point(gdo, v[i], loopindex + tri_i[i]);
-}
-
 /* for each vertex, build a list of points related to it; these lists
  * are stored in an array sized to the number of vertices */
-static void cdDM_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int totface, int totmat)
+static void cdDM_drawobject_init_vert_points(
+        GPUDrawObject *gdo,
+        const MPoly *mpoly, const MLoop *mloop,
+        int tot_poly,
+        int totmat)
 {
        GPUBufferMaterial *mat;
        int i, *mat_orig_to_new;
@@ -1764,24 +1622,18 @@ static void cdDM_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int t
                gdo->vert_points[i].point_index = -1;
        }
 
-       for (i = 0; i < totface; i++, f++) {
-               mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
+       for (i = 0; i < tot_poly; i++) {
+               int j;
+               const MPoly *mp = &mpoly[i];
+               mat = &gdo->materials[mat_orig_to_new[mp->mat_nr]];
 
                mat->polys[mat->counter++] = i;
 
-               /* add triangle */
-               cdDM_drawobject_add_triangle(gdo, f->v1, f->v2, f->v3, false, tot_loops);
-               mat->totelements += 3;
-
-               /* add second triangle for quads */
-               if (f->v4) {
-                       cdDM_drawobject_add_triangle(gdo, f->v3, f->v4, f->v1, true, tot_loops);
-                       mat->totelements += 3;
-                       tot_loops += 4;
-               }
-               else {
-                       tot_loops += 3;
+               /* assign unique indices to vertices of the mesh */
+               for (j = 0; j < mp->totloop; j++) {
+                       cdDM_drawobject_add_vert_point(gdo, mloop[mp->loopstart + j].v, tot_loops + j);
                }
+               tot_loops += mp->totloop;
        }
 
        /* map any unused vertices to loose points */
@@ -1806,30 +1658,29 @@ typedef struct {
 static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
 {
        GPUDrawObject *gdo;
-       MFace *mface;
+       const MPoly *mpoly;
+       const MLoop *mloop;
        int totmat = dm->totmat;
        GPUMaterialInfo *mat_info;
-       int i, curmat, totelements, totface, totloops;
+       int i, curmat, totelements, totloops, totpolys;
 
        /* object contains at least one material (default included) so zero means uninitialized dm */
        BLI_assert(totmat != 0);
 
-       mface = dm->getTessFaceArray(dm);
-       totface = dm->getNumTessFaces(dm);
+       mpoly = dm->getPolyArray(dm);
+       mloop = dm->getLoopArray(dm);
+
+       totpolys = dm->getNumPolys(dm);
 
        /* get the number of points used by each material, treating
         * each quad as two triangles */
        mat_info = MEM_callocN(sizeof(*mat_info) * totmat, "GPU_drawobject_new.mat_orig_to_new");
-       for (i = 0; i < totface; i++) {
-               mat_info[mface[i].mat_nr].polys++;
-               if (mface[i].v4) {
-                       mat_info[mface[i].mat_nr].elements += 6;
-                       mat_info[mface[i].mat_nr].loops += 4;
-               }
-               else {
-                       mat_info[mface[i].mat_nr].elements += 3;
-                       mat_info[mface[i].mat_nr].loops += 3;
-               }
+
+       for (i = 0; i < totpolys; i++) {
+               const int mat_nr = mpoly[i].mat_nr;
+               mat_info[mat_nr].polys++;
+               mat_info[mat_nr].elements += 3 * ME_POLY_TRI_TOT(&mpoly[i]);
+               mat_info[mat_nr].loops += mpoly[i].totloop;
        }
        /* create the GPUDrawObject */
        gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
@@ -1851,7 +1702,7 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
                if (mat_info[i].elements > 0) {
                        gdo->materials[curmat].start = totelements;
                        /* can set it to points now but used in cdDM_drawobject_init_vert_points as counter */
-                       gdo->materials[curmat].totelements = 0;
+                       gdo->materials[curmat].totelements = mat_info[i].elements;
                        gdo->materials[curmat].totloops = mat_info[i].loops;
                        gdo->materials[curmat].mat_nr = i;
                        gdo->materials[curmat].totpolys = mat_info[i].polys;
@@ -1868,7 +1719,7 @@ static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm)
        /* store total number of points used for triangles */
        gdo->tot_triangle_point = totelements;
 
-       cdDM_drawobject_init_vert_points(gdo, mface, totface, totmat);
+       cdDM_drawobject_init_vert_points(gdo, mpoly, mloop, totpolys, totmat);
        MEM_freeN(mat_info);
 
        return gdo;
@@ -2013,6 +1864,34 @@ void CDDM_recalc_tessellation(DerivedMesh *dm)
        CDDM_recalc_tessellation_ex(dm, true);
 }
 
+void CDDM_recalc_looptri(DerivedMesh *dm)
+{
+       CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
+       const unsigned int totpoly = dm->numPolyData;
+       const unsigned int totloop = dm->numLoopData;
+
+       DM_ensure_looptri_data(dm);
+
+       BKE_mesh_recalc_looptri(
+               cddm->mloop, cddm->mpoly,
+               cddm->mvert,
+               totloop, totpoly,
+               cddm->dm.looptris.array);
+}
+
+static const MLoopTri *cdDM_getLoopTriArray(DerivedMesh *dm)
+{
+       if (dm->looptris.array) {
+               BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+       }
+       else {
+               dm->recalcLoopTri(dm);
+
+               /* ccdm is an exception here, that recalcLoopTri will fill in the array too  */
+       }
+       return dm->looptris.array;
+}
+
 static void cdDM_free_internal(CDDerivedMesh *cddm)
 {
        if (cddm->pmap) MEM_freeN(cddm->pmap);
@@ -2063,10 +1942,13 @@ static CDDerivedMesh *cdDM_create(const char *desc)
        dm->getEdgeDataArray = DM_get_edge_data_layer;
        dm->getTessFaceDataArray = DM_get_tessface_data_layer;
 
+       dm->getLoopTriArray = cdDM_getLoopTriArray;
+
        dm->calcNormals = CDDM_calc_normals;
        dm->calcLoopNormals = CDDM_calc_loop_normals;
        dm->calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
        dm->recalcTessellation = CDDM_recalc_tessellation;
+       dm->recalcLoopTri = CDDM_recalc_looptri;
 
        dm->getVertCos = cdDM_getVertCos;
        dm->getVertCo = cdDM_getVertCo;
@@ -2628,16 +2510,15 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
                CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numTessFaceData);
        }
 
-       face_nors = MEM_mallocN(sizeof(*face_nors) * dm->numTessFaceData, "face_nors");
+       face_nors = MEM_mallocN(sizeof(*face_nors) * dm->numPolyData, "face_nors");
 
        /* calculate face normals */
-       BKE_mesh_calc_normals_mapping_ex(
+       BKE_mesh_calc_normals_poly(
                cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm),
-               dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numTessFaceData,
-               CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors,
+               dm->numLoopData, dm->numPolyData, face_nors,
                only_face_normals);
 
-       CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numTessFaceData);
+       CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numPolyData);
 
        cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
 }
index 58f25179c5c925246db114437a904e05dffc3cdb..b8fade6e4cd0e4260f00fbafb9d12c30b4e0d8ed 100644 (file)
@@ -242,6 +242,47 @@ static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
        /* do nothing */
 }
 
+static void emDM_recalcLoopTri(DerivedMesh *UNUSED(dm))
+{
+       /* Nothing to do: emDM tessellation is known,
+        * allocate and fill in with emDM_getLoopTriArray */
+}
+
+static const MLoopTri *emDM_getLoopTriArray(DerivedMesh *dm)
+{
+       if (dm->looptris.array) {
+               BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+       }
+       else {
+               EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
+               BMLoop *(*looptris)[3] = bmdm->em->looptris;
+               MLoopTri *mlooptri;
+               const int tottri = bmdm->em->tottri;
+               int i;
+
+               DM_ensure_looptri_data(dm);
+               mlooptri = dm->looptris.array;
+
+               BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+               BLI_assert(tottri == dm->looptris.num);
+
+               BM_mesh_elem_index_ensure(bmdm->em->bm, BM_FACE | BM_LOOP);
+
+               for (i = 0; i < tottri; i++) {
+                       BMLoop **ltri = looptris[i];
+                       MLoopTri *lt = &mlooptri[i];
+
+                       ARRAY_SET_ITEMS(
+                               lt->tri,
+                               BM_elem_index_get(ltri[0]),
+                               BM_elem_index_get(ltri[1]),
+                               BM_elem_index_get(ltri[2]));
+                       lt->poly = BM_elem_index_get(ltri[0]->f);
+               }
+       }
+       return dm->looptris.array;
+}
+
 static void emDM_foreachMappedVert(
         DerivedMesh *dm,
         void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
@@ -1794,6 +1835,8 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
        bmdm->dm.getNumLoops = emDM_getNumLoops;
        bmdm->dm.getNumPolys = emDM_getNumPolys;
 
+       bmdm->dm.getLoopTriArray = emDM_getLoopTriArray;
+
        bmdm->dm.getVert = emDM_getVert;
        bmdm->dm.getVertCo = emDM_getVertCo;
        bmdm->dm.getVertNo = emDM_getVertNo;
@@ -1812,6 +1855,7 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em,
        bmdm->dm.calcLoopNormals = emDM_calcLoopNormals;
        bmdm->dm.calcLoopNormalsSpaceArray = emDM_calcLoopNormalsSpaceArray;
        bmdm->dm.recalcTessellation = emDM_recalcTessellation;
+       bmdm->dm.recalcLoopTri = emDM_recalcLoopTri;
 
        bmdm->dm.foreachMappedVert = emDM_foreachMappedVert;
        bmdm->dm.foreachMappedLoop = emDM_foreachMappedLoop;
index 40a299ef34388f2a86012744f2ac15bd3da6b3c7..8ac0c7f7a6e73dbc6df315afd0fe22de656dc887 100644 (file)
@@ -328,6 +328,52 @@ void BKE_mesh_calc_normals_tessface(
                MEM_freeN(fnors);
 }
 
+void BKE_mesh_calc_normals_looptri(
+        MVert *mverts, int numVerts,
+        const MLoop *mloop,
+        const MLoopTri *looptri, int looptri_num,
+        float (*r_tri_nors)[3])
+{
+       float (*tnorms)[3] = MEM_callocN(sizeof(*tnorms) * (size_t)numVerts, "tnorms");
+       float (*fnors)[3] = (r_tri_nors) ? r_tri_nors : MEM_callocN(sizeof(*fnors) * (size_t)looptri_num, "meshnormals");
+       int i;
+
+       for (i = 0; i < looptri_num; i++) {
+               const MLoopTri *lt = &looptri[i];
+               float *f_no = fnors[i];
+               const unsigned int vtri[3] = {
+                   mloop[lt->tri[0]].v,
+                   mloop[lt->tri[1]].v,
+                   mloop[lt->tri[2]].v,
+               };
+
+               normal_tri_v3(
+                       f_no,
+                       mverts[vtri[0]].co, mverts[vtri[1]].co, mverts[vtri[2]].co);
+
+               accumulate_vertex_normals_tri(
+                       tnorms[vtri[0]], tnorms[vtri[1]], tnorms[vtri[2]],
+                       f_no, mverts[vtri[0]].co, mverts[vtri[1]].co, mverts[vtri[2]].co);
+       }
+
+       /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+       for (i = 0; i < numVerts; i++) {
+               MVert *mv = &mverts[i];
+               float *no = tnorms[i];
+
+               if (UNLIKELY(normalize_v3(no) == 0.0f)) {
+                       normalize_v3_v3(no, mv->co);
+               }
+
+               normal_float_to_short_v3(mv->no, no);
+       }
+
+       MEM_freeN(tnorms);
+
+       if (fnors != r_tri_nors)
+               MEM_freeN(fnors);
+}
+
 void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops)
 {
        if (!(lnors_spacearr->lspacearr && lnors_spacearr->loops_pool)) {
@@ -2541,6 +2587,136 @@ int BKE_mesh_recalc_tessellation(
 
 }
 
+/**
+ * Calculate tessellation into #MLoopTri which exist only for this purpose.
+ */
+void BKE_mesh_recalc_looptri(
+        const MLoop *mloop, const MPoly *mpoly,
+        const MVert *mvert,
+        int totloop, int totpoly,
+        MLoopTri *mlooptri)
+{
+       /* use this to avoid locking pthread for _every_ polygon
+        * and calling the fill function */
+
+#define USE_TESSFACE_SPEEDUP
+
+       const MPoly *mp;
+       const MLoop *ml;
+       MLoopTri *mlt;
+       MemArena *arena = NULL;
+       int poly_index, mlooptri_index;
+       unsigned int j;
+
+       mlooptri_index = 0;
+       mp = mpoly;
+       for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) {
+               const unsigned int mp_loopstart = (unsigned int)mp->loopstart;
+               const unsigned int mp_totloop = (unsigned int)mp->totloop;
+               unsigned int l1, l2, l3;
+               if (mp_totloop < 3) {
+                       /* do nothing */
+               }
+
+#ifdef USE_TESSFACE_SPEEDUP
+
+#define ML_TO_MLT(i1, i2, i3)  { \
+                       mlt = &mlooptri[mlooptri_index]; \
+                       l1 = mp_loopstart + i1; \
+                       l2 = mp_loopstart + i2; \
+                       l3 = mp_loopstart + i3; \
+                       ARRAY_SET_ITEMS(mlt->tri, l1, l2, l3); \
+                       mlt->poly = (unsigned int)poly_index; \
+               } ((void)0)
+
+               else if (mp_totloop == 3) {
+                       ML_TO_MLT(0, 1, 2);
+                       mlooptri_index++;
+               }
+               else if (mp_totloop == 4) {
+                       ML_TO_MLT(0, 1, 2);
+                       mlooptri_index++;
+                       ML_TO_MLT(0, 2, 3);
+                       mlooptri_index++;
+               }
+#endif /* USE_TESSFACE_SPEEDUP */
+               else {
+                       const float *co_curr, *co_prev;
+
+                       float normal[3];
+
+                       float axis_mat[3][3];
+                       float (*projverts)[2];
+                       unsigned int (*tris)[3];
+
+                       const unsigned int totfilltri = mp_totloop - 2;
+
+                       if (UNLIKELY(arena == NULL)) {
+                               arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+                       }
+
+                       tris = BLI_memarena_alloc(arena, sizeof(*tris) * (size_t)totfilltri);
+                       projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * (size_t)mp_totloop);
+
+                       zero_v3(normal);
+
+                       /* calc normal, flipped: to get a positive 2d cross product */
+                       ml = mloop + mp_loopstart;
+                       co_prev = mvert[ml[mp_totloop - 1].v].co;
+                       for (j = 0; j < mp_totloop; j++, ml++) {
+                               co_curr = mvert[ml->v].co;
+                               add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
+                               co_prev = co_curr;
+                       }
+                       if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+                               normal[2] = 1.0f;
+                       }
+
+                       /* project verts to 2d */
+                       axis_dominant_v3_to_m3_negate(axis_mat, normal);
+
+                       ml = mloop + mp_loopstart;
+                       for (j = 0; j < mp_totloop; j++, ml++) {
+                               mul_v2_m3v3(projverts[j], axis_mat, mvert[ml->v].co);
+                       }
+
+                       BLI_polyfill_calc_arena((const float (*)[2])projverts, mp_totloop, 1, tris, arena);
+
+                       /* apply fill */
+                       for (j = 0; j < totfilltri; j++) {
+                               unsigned int *tri = tris[j];
+
+                               mlt = &mlooptri[mlooptri_index];
+
+                               /* set loop indices, transformed to vert indices later */
+                               l1 = mp_loopstart + tri[0];
+                               l2 = mp_loopstart + tri[1];
+                               l3 = mp_loopstart + tri[2];
+
+                               ARRAY_SET_ITEMS(mlt->tri, l1, l2, l3);
+                               mlt->poly = (unsigned int)poly_index;
+
+                               mlooptri_index++;
+                       }
+
+                       BLI_memarena_clear(arena);
+               }
+       }
+
+       if (arena) {
+               BLI_memarena_free(arena);
+               arena = NULL;
+       }
+
+       BLI_assert(mlooptri_index == poly_to_tri_count(totpoly, totloop));
+
+#undef USE_TESSFACE_SPEEDUP
+#undef ML_TO_MLT
+}
+
+/* -------------------------------------------------------------------- */
+
+
 #ifdef USE_BMESH_SAVE_AS_COMPAT
 
 /**
index 0bda740af53a53987e58b9a81c358d9ffd510372..76e56f0bc300a5c98ca74dec93ce61a2c24457db 100644 (file)
@@ -470,12 +470,11 @@ void BKE_paint_stroke_get_average(Scene *scene, Object *ob, float stroke[3])
 
 /* returns non-zero if any of the face's vertices
  * are hidden, zero otherwise */
-bool paint_is_face_hidden(const MFace *f, const MVert *mvert)
+bool paint_is_face_hidden(const MLoopTri *lt, const MVert *mvert, const MLoop *mloop)
 {
-       return ((mvert[f->v1].flag & ME_HIDE) ||
-               (mvert[f->v2].flag & ME_HIDE) ||
-               (mvert[f->v3].flag & ME_HIDE) ||
-               (f->v4 && (mvert[f->v4].flag & ME_HIDE)));
+       return ((mvert[mloop[lt->tri[0]].v].flag & ME_HIDE) ||
+               (mvert[mloop[lt->tri[1]].v].flag & ME_HIDE) ||
+               (mvert[mloop[lt->tri[2]].v].flag & ME_HIDE));
 }
 
 /* returns non-zero if any of the corners of the grid
index edeba9fd7e6f83178f38e9d2698d3957248b13b4..6e379f293d73350c4e5a2e84db2a2a23b36c4dbb 100644 (file)
@@ -168,7 +168,7 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
 //     BB_expand(&node->vb, co);
 //}
 
-static int face_materials_match(const MFace *f1, const MFace *f2)
+static int face_materials_match(const MPoly *f1, const MPoly *f2)
 {
        return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
                (f1->mat_nr == f2->mat_nr));
@@ -201,21 +201,22 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis,
 /* Returns the index of the first element on the right of the partition */
 static int partition_indices_material(PBVH *bvh, int lo, int hi)
 {
-       const MFace *faces = bvh->faces;
+       const MPoly *mpoly = bvh->mpoly;
+       const MLoopTri *looptri = bvh->looptri;
        const DMFlagMat *flagmats = bvh->grid_flag_mats;
        const int *indices = bvh->prim_indices;
        const void *first;
        int i = lo, j = hi;
 
-       if (bvh->faces)
-               first = &faces[bvh->prim_indices[lo]];
+       if (bvh->looptri)
+               first = &looptri[bvh->prim_indices[lo]];
        else
                first = &flagmats[bvh->prim_indices[lo]];
 
        for (;; ) {
-               if (bvh->faces) {
-                       for (; face_materials_match(first, &faces[indices[i]]); i++) ;
-                       for (; !face_materials_match(first, &faces[indices[j]]); j--) ;
+               if (bvh->looptri) {
+                       for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) ;
+                       for (; !face_materials_match(first, &mpoly[looptri[indices[j]].poly]); j--) ;
                }
                else {
                        for (; grid_materials_match(first, &flagmats[indices[i]]); i++) ;
@@ -295,17 +296,18 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
        node->face_vert_indices = (const int (*)[4])face_vert_indices;
 
        for (i = 0; i < totface; ++i) {
-               const MFace *f = &bvh->faces[node->prim_indices[i]];
-               int sides = f->v4 ? 4 : 3;
+               const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]];
+               const int sides = 3;
 
                for (j = 0; j < sides; ++j) {
                        face_vert_indices[i][j] =
                                map_insert_vert(bvh, map, &node->face_verts,
-                                               &node->uniq_verts, (&f->v1)[j]);
+                                               &node->uniq_verts, bvh->mloop[lt->tri[j]].v);
                }
 
-               if (!paint_is_face_hidden(f, bvh->verts))
+               if (!paint_is_face_hidden(lt, bvh->verts, bvh->mloop)) {
                        has_visible = true;
+               }
        }
 
        vert_indices = MEM_callocN(sizeof(int) *
@@ -326,9 +328,8 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
        }
 
        for (i = 0; i < totface; ++i) {
-               const MFace *f = &bvh->faces[node->prim_indices[i]];
-               int sides = f->v4 ? 4 : 3;
-               
+               const int sides = 3;
+
                for (j = 0; j < sides; ++j) {
                        if (face_vert_indices[i][j] < 0)
                                face_vert_indices[i][j] =
@@ -406,7 +407,7 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
        /* Still need vb for searches */
        update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
                
-       if (bvh->faces)
+       if (bvh->looptri)
                build_mesh_leaf_node(bvh, bvh->nodes + node_index);
        else {
                build_grid_leaf_node(bvh, bvh->nodes + node_index);
@@ -417,25 +418,28 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
  * same material (including flat/smooth shading), non-zero otherwise */
 static int leaf_needs_material_split(PBVH *bvh, int offset, int count)
 {
-       int i, prim;
+       int i;
 
        if (count <= 1)
                return 0;
 
-       if (bvh->faces) {
-               const MFace *first = &bvh->faces[bvh->prim_indices[offset]];
+       if (bvh->looptri) {
+               const MLoopTri *first = &bvh->looptri[bvh->prim_indices[offset]];
+               const MPoly *mp = &bvh->mpoly[first->poly];
 
                for (i = offset + count - 1; i > offset; --i) {
-                       prim = bvh->prim_indices[i];
-                       if (!face_materials_match(first, &bvh->faces[prim]))
+                       int prim = bvh->prim_indices[i];
+                       const MPoly *mp_other = &bvh->mpoly[bvh->looptri[prim].poly];
+                       if (!face_materials_match(mp, mp_other)) {
                                return 1;
+                       }
                }
        }
        else {
                const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]];
 
                for (i = offset + count - 1; i > offset; --i) {
-                       prim = bvh->prim_indices[i];
+                       int prim = bvh->prim_indices[i];
                        if (!grid_materials_match(first, &bvh->grid_flag_mats[prim]))
                                return 1;
                }
@@ -534,15 +538,18 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
 
 /* Do a full rebuild with on Mesh data structure */
 void BKE_pbvh_build_mesh(
-        PBVH *bvh, const MFace *faces, MVert *verts,
-        int totface, int totvert, struct CustomData *vdata)
+        PBVH *bvh, const MPoly *mpoly, const MLoop *mloop, MVert *verts,
+        int totvert, struct CustomData *vdata,
+        const MLoopTri *looptri, int looptri_num)
 {
        BBC *prim_bbc = NULL;
        BB cb;
        int i, j;
 
        bvh->type = PBVH_FACES;
-       bvh->faces = faces;
+       bvh->mpoly = mpoly;
+       bvh->mloop = mloop;
+       bvh->looptri = looptri;
        bvh->verts = verts;
        bvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
        bvh->totvert = totvert;
@@ -552,25 +559,25 @@ void BKE_pbvh_build_mesh(
        BB_reset(&cb);
 
        /* For each face, store the AABB and the AABB centroid */
-       prim_bbc = MEM_mallocN(sizeof(BBC) * totface, "prim_bbc");
+       prim_bbc = MEM_mallocN(sizeof(BBC) * looptri_num, "prim_bbc");
 
-       for (i = 0; i < totface; ++i) {
-               const MFace *f = &faces[i];
-               const int sides = f->v4 ? 4 : 3;
+       for (i = 0; i < looptri_num; ++i) {
+               const MLoopTri *lt = &looptri[i];
+               const int sides = 3;
                BBC *bbc = prim_bbc + i;
 
                BB_reset((BB *)bbc);
 
                for (j = 0; j < sides; ++j)
-                       BB_expand((BB *)bbc, verts[(&f->v1)[j]].co);
+                       BB_expand((BB *)bbc, verts[bvh->mloop[lt->tri[j]].v].co);
 
                BBC_update_centroid(bbc);
 
                BB_expand(&cb, bbc->bcentroid);
        }
 
-       if (totface)
-               pbvh_build(bvh, &cb, prim_bbc, totface);
+       if (looptri_num)
+               pbvh_build(bvh, &cb, prim_bbc, looptri_num);
 
        MEM_freeN(prim_bbc);
        MEM_freeN(bvh->vert_bitmap);
@@ -657,12 +664,13 @@ void BKE_pbvh_free(PBVH *bvh)
                        /* if pbvh was deformed, new memory was allocated for verts/faces -- free it */
 
                        MEM_freeN((void *)bvh->verts);
-                       if (bvh->faces) {
-                               MEM_freeN((void *)bvh->faces);
-                       }
                }
        }
 
+       if (bvh->looptri) {
+               MEM_freeN((void *)bvh->looptri);
+       }
+
        if (bvh->nodes)
                MEM_freeN(bvh->nodes);
 
@@ -983,20 +991,23 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
                        totface = node->totprim;
 
                        for (i = 0; i < totface; ++i) {
-                               const MFace *f = &bvh->faces[faces[i]];
+                               const MLoopTri *lt = &bvh->looptri[faces[i]];
+                               const unsigned int vtri[3] = {
+                                   bvh->mloop[lt->tri[0]].v,
+                                   bvh->mloop[lt->tri[1]].v,
+                                   bvh->mloop[lt->tri[2]].v,
+                               };
                                float fn[3];
-                               const unsigned int *fv = &f->v1;
-                               int sides = (f->v4) ? 4 : 3;
+                               const int sides = 3;
 
-                               if (f->v4)
-                                       normal_quad_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co,
-                                                      bvh->verts[f->v3].co, bvh->verts[f->v4].co);
-                               else
-                                       normal_tri_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co,
-                                                     bvh->verts[f->v3].co);
+                               normal_tri_v3(
+                                       fn,
+                                       bvh->verts[vtri[0]].co,
+                                       bvh->verts[vtri[1]].co,
+                                       bvh->verts[vtri[2]].co);
 
                                for (j = 0; j < sides; ++j) {
-                                       int v = fv[j];
+                                       int v = vtri[j];
 
                                        if (bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
                                                /* this seems like it could be very slow but profile
@@ -1010,8 +1021,9 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
                                        }
                                }
 
-                               if (face_nors)
-                                       copy_v3_v3(face_nors[faces[i]], fn);
+                               if (face_nors) {
+                                       copy_v3_v3(face_nors[lt->poly], fn);
+                               }
                        }
                }
        }
@@ -1093,7 +1105,8 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
                                case PBVH_FACES:
                                        node->draw_buffers =
                                                GPU_build_mesh_pbvh_buffers(node->face_vert_indices,
-                                                                  bvh->faces, bvh->verts,
+                                                                  bvh->mpoly, bvh->mloop, bvh->looptri,
+                                                                  bvh->verts,
                                                                   node->prim_indices,
                                                                   node->totprim);
                                        break;
@@ -1515,15 +1528,16 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node,
                                     const float ray_normal[3], float *dist)
 {
        const MVert *vert = bvh->verts;
+       const MLoop *mloop = bvh->mloop;
        const int *faces = node->prim_indices;
        int i, totface = node->totprim;
        bool hit = false;
 
        for (i = 0; i < totface; ++i) {
-               const MFace *f = bvh->faces + faces[i];
+               const MLoopTri *lt = &bvh->looptri[faces[i]];
                const int *face_verts = node->face_vert_indices[i];
 
-               if (paint_is_face_hidden(f, vert))
+               if (paint_is_face_hidden(lt, vert, mloop))
                        continue;
 
                if (origco) {
@@ -1532,16 +1546,16 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, const PBVHNode *node,
                                                     origco[face_verts[0]],
                                                     origco[face_verts[1]],
                                                     origco[face_verts[2]],
-                                                    f->v4 ? origco[face_verts[3]] : NULL,
+                                                    NULL,
                                                     dist);
                }
                else {
                        /* intersect with current coordinates */
                        hit |= ray_face_intersection(ray_start, ray_normal,
-                                                    vert[f->v1].co,
-                                                    vert[f->v2].co,
-                                                    vert[f->v3].co,
-                                                    f->v4 ? vert[f->v4].co : NULL,
+                                                    vert[mloop[lt->tri[0]].v].co,
+                                                    vert[mloop[lt->tri[1]].v].co,
+                                                    vert[mloop[lt->tri[2]].v].co,
+                                                    NULL,
                                                     dist);
                }
        }
@@ -1874,8 +1888,8 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
                        /* original data and applying new coords to this arrays would lead to */
                        /* unneeded deformation -- duplicate verts/faces to avoid this */
 
-                       pbvh->verts = MEM_dupallocN(pbvh->verts);
-                       pbvh->faces = MEM_dupallocN(pbvh->faces);
+                       pbvh->verts   = MEM_dupallocN(pbvh->verts);
+                       pbvh->looptri = MEM_dupallocN(pbvh->looptri);
 
                        pbvh->deformed = 1;
                }
@@ -1890,7 +1904,11 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3])
                }
 
                /* coordinates are new -- normals should also be updated */
-               BKE_mesh_calc_normals_tessface(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL);
+               BKE_mesh_calc_normals_looptri(
+                       pbvh->verts, pbvh->totvert,
+                       pbvh->mloop,
+                       pbvh->looptri, pbvh->totprim,
+                       NULL);
 
                for (a = 0; a < pbvh->totnode; ++a)
                        BKE_pbvh_node_mark_update(&pbvh->nodes[a]);
index 74897d6f4cdefad05a78f89b2344051b1cc62554..5967704141fea1f867a4331df5b87851d69364bd 100644 (file)
@@ -133,7 +133,9 @@ struct PBVH {
 
        /* Mesh data */
        MVert *verts;
-       const MFace *faces;
+       const MPoly *mpoly;
+       const MLoop *mloop;
+       const MLoopTri *looptri;
        CustomData *vdata;
 
        /* Grid Data */
index aaf631abbf032b3e8bb1c8851e1ffb0bc100d3de..1ab6a354605661bd1f71134cd91b2cc0d526063f 100644 (file)
@@ -1769,7 +1769,7 @@ static void ccgDM_buffer_copy_normal(
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
        CCGSubSurf *ss = ccgdm->ss;
        CCGKey key;
-       const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
+       const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
        int gridSize = ccgSubSurf_getGridSize(ss);
        int gridFaces = gridSize - 1;
        DMFlagMat *faceFlags = ccgdm->faceFlags;
@@ -1784,7 +1784,7 @@ static void ccgDM_buffer_copy_normal(
                CCGFace *f = ccgdm->faceMap[i].face;
                int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
                int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
-               const short (*ln)[3] = NULL;
+               const float (*ln)[3] = NULL;
 
                if (faceFlags) {
                        shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
@@ -1794,8 +1794,8 @@ static void ccgDM_buffer_copy_normal(
                }
 
                if (lnors) {
-                       ln = *lnors;
-                       lnors += gridFaces * gridFaces * numVerts;
+                       ln = lnors;
+                       lnors += gridFaces * gridFaces * numVerts * 4;
                }
 
                for (S = 0; S < numVerts; S++) {
@@ -1805,10 +1805,10 @@ static void ccgDM_buffer_copy_normal(
                                /* Can't use quad strips here... */
                                for (y = 0; y < gridFaces; y ++) {
                                        for (x = 0; x < gridFaces; x ++) {
-                                               copy_v3_v3_short(&varray[start], ln[0]);
-                                               copy_v3_v3_short(&varray[start + 4], ln[3]);
-                                               copy_v3_v3_short(&varray[start + 8], ln[2]);
-                                               copy_v3_v3_short(&varray[start + 12], ln[1]);
+                                               normal_float_to_short_v3(&varray[start + 0],  ln[0]);
+                                               normal_float_to_short_v3(&varray[start + 4],  ln[3]);
+                                               normal_float_to_short_v3(&varray[start + 8],  ln[2]);
+                                               normal_float_to_short_v3(&varray[start + 12], ln[1]);
 
                                                start += 16;
                                                ln += 4;
@@ -1953,13 +1953,6 @@ static void ccgDM_buffer_copy_vertex(
        }
 }
 
-static void copy_mcol_uc3(unsigned char *v, const unsigned char *col)
-{
-       v[0] = col[3];
-       v[1] = col[2];
-       v[2] = col[1];
-}
-
 /* Only used by non-editmesh types */
 static void ccgDM_buffer_copy_color(
         DerivedMesh *dm, unsigned char *varray,
@@ -1968,7 +1961,7 @@ static void ccgDM_buffer_copy_color(
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
        CCGSubSurf *ss = ccgdm->ss;
        CCGKey key;
-       const unsigned char *mcol = user_data;
+       const char *mloopcol = user_data;
        int gridSize = ccgSubSurf_getGridSize(ss);
        int gridFaces = gridSize - 1;
        int i, totface = ccgSubSurf_getNumFaces(ss);
@@ -1985,10 +1978,10 @@ static void ccgDM_buffer_copy_color(
                for (S = 0; S < numVerts; S++) {
                        for (y = 0; y < gridFaces; y++) {
                                for (x = 0; x < gridFaces; x++) {
-                                       copy_mcol_uc3(&varray[start], &mcol[iface * 16]);
-                                       copy_mcol_uc3(&varray[start + 3], &mcol[iface * 16 + 12]);
-                                       copy_mcol_uc3(&varray[start + 6], &mcol[iface * 16 + 8]);
-                                       copy_mcol_uc3(&varray[start + 9], &mcol[iface * 16 + 4]);
+                                       copy_v3_v3_char((char *)&varray[start + 0], &mloopcol[iface * 16 + 0]);
+                                       copy_v3_v3_char((char *)&varray[start + 3], &mloopcol[iface * 16 + 12]);
+                                       copy_v3_v3_char((char *)&varray[start + 6], &mloopcol[iface * 16 + 8]);
+                                       copy_v3_v3_char((char *)&varray[start + 9], &mloopcol[iface * 16 + 4]);
 
                                        start += 12;
                                        iface++;
@@ -2005,7 +1998,7 @@ static void ccgDM_buffer_copy_uv(
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
        CCGSubSurf *ss = ccgdm->ss;
        CCGKey key;
-       MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+       MLoopUV *mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV);
        int gridSize = ccgSubSurf_getGridSize(ss);
        int gridFaces = gridSize - 1;
        int i, totface = ccgSubSurf_getNumFaces(ss);
@@ -2020,12 +2013,12 @@ static void ccgDM_buffer_copy_uv(
                for (S = 0; S < numVerts; S++) {
                        for (y = 0; y < gridFaces; y++) {
                                for (x = 0; x < gridFaces; x++) {
-                                       copy_v2_v2(&varray[start], tf->uv[0]);
-                                       copy_v2_v2(&varray[start + 2], tf->uv[3]);
-                                       copy_v2_v2(&varray[start + 4], tf->uv[2]);
-                                       copy_v2_v2(&varray[start + 6], tf->uv[1]);
+                                       copy_v2_v2(&varray[start + 0], mloopuv[0].uv);
+                                       copy_v2_v2(&varray[start + 2], mloopuv[3].uv);
+                                       copy_v2_v2(&varray[start + 4], mloopuv[2].uv);
+                                       copy_v2_v2(&varray[start + 6], mloopuv[1].uv);
 
-                                       tf++;
+                                       mloopuv += 4;
                                        start += 8;
                                }
                        }
@@ -2045,22 +2038,22 @@ static void ccgDM_buffer_copy_uv_texpaint(
        int start = 0;
        DMFlagMat *faceFlags = ccgdm->faceFlags;
        int totmaterial = dm->totmat;
-       MTFace **mtface_base;
-       MTFace *stencil_base;
+       MLoopUV **mloopuv_base;
+       MLoopUV  *stencil_base;
        int stencil;
 
        CCG_key_top_level(&key, ss);
 
        /* should have been checked for before, reassert */
-       BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
-       mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
+       BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV));
+       mloopuv_base = MEM_mallocN(totmaterial * sizeof(*mloopuv_base), "texslots");
 
        for (i = 0; i < totmaterial; i++) {
-               mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
+               mloopuv_base[i] = DM_paint_uvlayer_active_get_mloopuv(dm, i);
        }
 
-       stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
-       stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
+       stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV);
+       stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil);
 
        start = 0;
 
@@ -2080,23 +2073,23 @@ static void ccgDM_buffer_copy_uv_texpaint(
                for (S = 0; S < numVerts; S++) {
                        for (y = 0; y < gridFaces; y++) {
                                for (x = 0; x < gridFaces; x++) {
-                                       /* divide by 16, gives us current tface */
-                                       unsigned int i_tf = start / 16;
-                                       copy_v2_v2(&varray[start], mtface_base[matnr][i_tf].uv[0]);
-                                       copy_v2_v2(&varray[start + 2], stencil_base[i_tf].uv[0]);
-                                       copy_v2_v2(&varray[start + 4], mtface_base[matnr][i_tf].uv[3]);
-                                       copy_v2_v2(&varray[start + 6], stencil_base[i_tf].uv[3]);
-                                       copy_v2_v2(&varray[start + 8], mtface_base[matnr][i_tf].uv[2]);
-                                       copy_v2_v2(&varray[start + 10], stencil_base[i_tf].uv[2]);
-                                       copy_v2_v2(&varray[start + 12], mtface_base[matnr][i_tf].uv[1]);
-                                       copy_v2_v2(&varray[start + 14], stencil_base[i_tf].uv[1]);
+                                       /* divide by 4, gives us current loop-index */
+                                       unsigned int i_ml = start / 4;
+                                       copy_v2_v2(&varray[start + 0],  mloopuv_base[matnr][i_ml + 0].uv);
+                                       copy_v2_v2(&varray[start + 2],         stencil_base[i_ml + 0].uv);
+                                       copy_v2_v2(&varray[start + 4],  mloopuv_base[matnr][i_ml + 3].uv);
+                                       copy_v2_v2(&varray[start + 6],         stencil_base[i_ml + 3].uv);
+                                       copy_v2_v2(&varray[start + 8],  mloopuv_base[matnr][i_ml + 2].uv);
+                                       copy_v2_v2(&varray[start + 10],        stencil_base[i_ml + 2].uv);
+                                       copy_v2_v2(&varray[start + 12], mloopuv_base[matnr][i_ml + 1].uv);
+                                       copy_v2_v2(&varray[start + 14],        stencil_base[i_ml + 1].uv);
                                        start += 16;
                                }
                        }
                }
        }
 
-       MEM_freeN(mtface_base);
+       MEM_freeN(mloopuv_base);
 }
 
 static void ccgDM_copy_gpu_data(
@@ -2301,7 +2294,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
                index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize);   \
        else                                                                      \
                index = 0;                                                            \
-       DM_draw_attrib_vertex(&attribs, a, index, vert);                          \
+       DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert);          \
 } (void)0
 
        totface = ccgSubSurf_getNumFaces(ss);
@@ -2472,7 +2465,7 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
                index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize);   \
        else                                                                      \
                index = 0;                                                            \
-       DM_draw_attrib_vertex(&attribs, a, index, vert);                          \
+       DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert);          \
 } (void)0
 
        totface = ccgSubSurf_getNumFaces(ss);
@@ -2621,8 +2614,8 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
        CCGSubSurf *ss = ccgdm->ss;
        CCGKey key;
-       int colType = CD_TEXTURE_MCOL;
-       MCol *mcol = dm->getTessFaceDataArray(dm, colType);
+       int colType;
+       const  MLoopCol *mloopcol;
        MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
        DMFlagMat *faceFlags = ccgdm->faceFlags;
        DMDrawOption draw_option;
@@ -2637,13 +2630,15 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
        CCG_key_top_level(&key, ss);
        ccgdm_pbvh_update(ccgdm);
 
-       if (!mcol) {
+       colType = CD_TEXTURE_MLOOPCOL;
+       mloopcol = dm->getLoopDataArray(dm, colType);
+       if (!mloopcol) {
                colType = CD_PREVIEW_MCOL;
-               mcol = dm->getTessFaceDataArray(dm, colType);
+               mloopcol = dm->getLoopDataArray(dm, colType);
        }
-       if (!mcol) {
-               colType = CD_MCOL;
-               mcol = dm->getTessFaceDataArray(dm, colType);
+       if (!mloopcol) {
+               colType = CD_MLOOPCOL;
+               mloopcol = dm->getLoopDataArray(dm, colType);
        }
 
        GPU_vertex_setup(dm);
@@ -2653,7 +2648,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
                GPU_texpaint_uv_setup(dm);
        else
                GPU_uv_setup(dm);
-       if (mcol) {
+       if (mloopcol) {
                GPU_color_setup(dm, colType);
        }
 
@@ -2695,10 +2690,11 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
                        if (drawParams) {
                                MTexPoly tpoly;
                                if (tf) {
+                                       memset(&tpoly, 0, sizeof(tpoly));
                                        ME_MTEXFACE_CPY(&tpoly, tf + actualFace);
                                }
 
-                               draw_option = drawParams((use_tface && tf) ? &tpoly : NULL, (mcol != NULL), mat_nr);
+                               draw_option = drawParams((use_tface && tf) ? &tpoly : NULL, (mloopcol != NULL), mat_nr);
                        }
                        else if (index != ORIGINDEX_NONE)
                                draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL;
@@ -2721,7 +2717,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
                                        tot_drawn += facequads * 6;
 
                                if (tot_drawn) {
-                                       if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
+                                       if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
                                                GPU_color_switch(1);
                                        else
                                                GPU_color_switch(0);
@@ -2801,7 +2797,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
        CCGSubSurf *ss = ccgdm->ss;
        CCGKey key;
-       MCol *mcol = NULL;
+       MLoopCol *mloopcol = NULL;
        short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
        int i, gridSize = ccgSubSurf_getGridSize(ss);
        DMFlagMat *faceFlags = ccgdm->faceFlags;
@@ -2815,9 +2811,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
        (void)compareDrawOptions;
 
        if (useColors) {
-               mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
-               if (!mcol)
-                       mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
+               mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
+               if (!mloopcol)
+                       mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
        }
 
        totface = ccgSubSurf_getNumFaces(ss);
@@ -2835,9 +2831,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
                else if (faceFlags) drawSmooth = (lnors || (faceFlags[origIndex].flag & ME_SMOOTH));
                else drawSmooth = 1;
 
-               if (mcol) {
-                       cp = (unsigned char *)mcol;
-                       mcol += gridFaces * gridFaces * numVerts * 4;
+               if (mloopcol) {
+                       cp = (unsigned char *)mloopcol;
+                       mloopcol += gridFaces * gridFaces * numVerts * 4;
                }
 
                if (lnors) {
@@ -2881,16 +2877,16 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
                                                                float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
                                                                float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
 
-                                                               if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+                                                               if (cp) glColor3ubv(&cp[4]);
                                                                glNormal3sv(ln[0][1]);
                                                                glVertex3fv(d);
-                                                               if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+                                                               if (cp) glColor3ubv(&cp[8]);
                                                                glNormal3sv(ln[0][2]);
                                                                glVertex3fv(c);
-                                                               if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+                                                               if (cp) glColor3ubv(&cp[12]);
                                                                glNormal3sv(ln[0][3]);
                                                                glVertex3fv(b);
-                                                               if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+                                                               if (cp) glColor3ubv(&cp[0]);
                                                                glNormal3sv(ln[0][0]);
                                                                glVertex3fv(a);
 
@@ -2908,10 +2904,10 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
                                                                a = CCG_grid_elem(&key, faceGridData, x, y + 0);
                                                                b = CCG_grid_elem(&key, faceGridData, x, y + 1);
        
-                                                               if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+                                                               if (cp) glColor3ubv(&cp[0]);
                                                                glNormal3fv(CCG_elem_no(&key, a));
                                                                glVertex3fv(CCG_elem_co(&key, a));
-                                                               if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+                                                               if (cp) glColor3ubv(&cp[4]);
                                                                glNormal3fv(CCG_elem_no(&key, b));
                                                                glVertex3fv(CCG_elem_co(&key, b));
 
@@ -2923,10 +2919,10 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
                                                        a = CCG_grid_elem(&key, faceGridData, x, y + 0);
                                                        b = CCG_grid_elem(&key, faceGridData, x, y + 1);
 
-                                                       if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+                                                       if (cp) glColor3ubv(&cp[12]);
                                                        glNormal3fv(CCG_elem_no(&key, a));
                                                        glVertex3fv(CCG_elem_co(&key, a));
-                                                       if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+                                                       if (cp) glColor3ubv(&cp[8]);
                                                        glNormal3fv(CCG_elem_no(&key, b));
                                                        glVertex3fv(CCG_elem_co(&key, b));
 
@@ -2946,13 +2942,13 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
 
                                                                ccgDM_glNormalFast(a, b, c, d);
        
-                                                               if (cp) glColor3ub(cp[7], cp[6], cp[5]);
+                                                               if (cp) glColor3ubv(&cp[4]);
                                                                glVertex3fv(d);
-                                                               if (cp) glColor3ub(cp[11], cp[10], cp[9]);
+                                                               if (cp) glColor3ubv(&cp[8]);
                                                                glVertex3fv(c);
-                                                               if (cp) glColor3ub(cp[15], cp[14], cp[13]);
+                                                               if (cp) glColor3ubv(&cp[12]);
                                                                glVertex3fv(b);
-                                                               if (cp) glColor3ub(cp[3], cp[2], cp[1]);
+                                                               if (cp) glColor3ubv(&cp[0]);
                                                                glVertex3fv(a);
 
                                                                if (cp) cp += 16;
@@ -3568,10 +3564,15 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
        }
        else if (ob->type == OB_MESH) {
                Mesh *me = ob->data;
+               const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
+               MLoopTri *looptri;
+
+               looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
+
                ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
                BLI_assert(!(me->mface == NULL && me->mpoly != NULL)); /* BMESH ONLY complain if mpoly is valid but not mface */
-               BKE_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
-                                   me->totface, me->totvert, &me->vdata);
+               BKE_pbvh_build_mesh(ccgdm->pbvh, me->mpoly, me->mloop, me->mvert, me->totvert, &me->vdata,
+                                   looptri, looptris_num);
        }
 
        if (ccgdm->pbvh)
@@ -3585,6 +3586,47 @@ static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm))
        /* Nothing to do: CCG handles creating its own tessfaces */
 }
 
+static void ccgDM_recalcLoopTri(DerivedMesh *UNUSED(dm))
+{
+       /* Nothing to do: CCG tessellation is known,
+        * allocate and fill in with ccgDM_getLoopTriArray */
+}
+
+static const MLoopTri *ccgDM_getLoopTriArray(DerivedMesh *dm)
+{
+       if (dm->looptris.array) {
+               BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+       }
+       else {
+               MLoopTri *mlooptri;
+               const int tottri = dm->numTessFaceData * 2;
+               int i, poly_index;
+
+               DM_ensure_looptri_data(dm);
+               mlooptri = dm->looptris.array;
+
+               BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+               BLI_assert(tottri == dm->looptris.num);
+
+               for (i = 0, poly_index = 0; i < tottri; i += 2, poly_index += 1) {
+                       MLoopTri *lt;
+                       lt = &mlooptri[i];
+                       /* quad is (0, 3, 2, 1) */
+                       lt->tri[0] = (poly_index * 4) + 0;
+                       lt->tri[1] = (poly_index * 4) + 3;
+                       lt->tri[2] = (poly_index * 4) + 2;
+                       lt->poly = poly_index;
+
+                       lt = &mlooptri[i + 1];
+                       lt->tri[0] = (poly_index * 4) + 0;
+                       lt->tri[1] = (poly_index * 4) + 2;
+                       lt->tri[2] = (poly_index * 4) + 1;
+                       lt->poly = poly_index;
+               }
+       }
+       return dm->looptris.array;
+}
+
 static void ccgDM_calcNormals(DerivedMesh *dm)
 {
        /* Nothing to do: CCG calculates normals during drawing */
@@ -3667,6 +3709,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        /* reuse of ccgDM_getNumTessFaces is intentional here: subsurf polys are just created from tessfaces */
        ccgdm->dm.getNumPolys = ccgDM_getNumTessFaces;
 
+       ccgdm->dm.getLoopTriArray = ccgDM_getLoopTriArray;
+
        ccgdm->dm.getVert = ccgDM_getFinalVert;
        ccgdm->dm.getEdge = ccgDM_getFinalEdge;
        ccgdm->dm.getTessFace = ccgDM_getFinalFace;
@@ -3702,6 +3746,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals;
        ccgdm->dm.calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
        ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
+       ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri;
 
        ccgdm->dm.getVertCos = ccgdm_getVertCos;
        ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
index 359e2a97d9f24d1d733c0f9b535c5f6362b25fcb..5734d0125c76bc67b03022c19dfec2a3865bded0 100644 (file)
@@ -300,6 +300,11 @@ void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f
 
 /********************************** Normals **********************************/
 
+void accumulate_vertex_normals_tri(
+        float n1[3], float n2[3], float n3[3],
+        const float f_no[3],
+        const float co1[3], const float co2[3], const float co3[3]);
+
 void accumulate_vertex_normals(
         float n1[3], float n2[3], float n3[3], float n4[3],
         const float f_no[3],
index f40f1cc3f97173234f6e00e0dd85689fba74003b..4662762ad216c0b02225d53afdb676033eebadf8 100644 (file)
@@ -3549,6 +3549,40 @@ void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f
 
 /********************************* Normals **********************************/
 
+void accumulate_vertex_normals_tri(
+        float n1[3], float n2[3], float n3[3],
+        const float f_no[3],
+        const float co1[3], const float co2[3], const float co3[3])
+{
+       float vdiffs[3][3];
+       const int nverts = 3;
+
+       /* compute normalized edge vectors */
+       sub_v3_v3v3(vdiffs[0], co2, co1);
+       sub_v3_v3v3(vdiffs[1], co3, co2);
+       sub_v3_v3v3(vdiffs[2], co1, co3);
+
+       normalize_v3(vdiffs[0]);
+       normalize_v3(vdiffs[1]);
+       normalize_v3(vdiffs[2]);
+
+       /* accumulate angle weighted face normal */
+       {
+               float *vn[] = {n1, n2, n3};
+               const float *prev_edge = vdiffs[nverts - 1];
+               int i;
+
+               for (i = 0; i < nverts; i++) {
+                       const float *cur_edge = vdiffs[i];
+                       const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
+
+                       /* accumulate */
+                       madd_v3_v3fl(vn[i], f_no, fac);
+                       prev_edge = cur_edge;
+               }
+       }
+}
+
 void accumulate_vertex_normals(
         float n1[3], float n2[3], float n3[3], float n4[3],
         const float f_no[3],
index ca3c8a97d4012a99f4a7b2b8b21c83d825280efb..0017cd3c2aeeef8139160e1e77e6b88320820f9c 100644 (file)
@@ -62,9 +62,8 @@ void paintface_flush_flags(Object *ob)
        Mesh *me = BKE_mesh_from_object(ob);
        DerivedMesh *dm = ob->derivedFinal;
        MPoly *polys, *mp_orig;
-       MFace *faces;
        const int *index_array = NULL;
-       int totface, totpoly;
+       int totpoly;
        int i;
        
        if (me == NULL)
@@ -79,26 +78,7 @@ void paintface_flush_flags(Object *ob)
        if (dm == NULL)
                return;
 
-       /*
-        * Try to push updated mesh poly flags to three other data sets:
-        *  - Mesh polys => Mesh tess faces
-        *  - Mesh polys => Final derived polys
-        *  - Final derived polys => Final derived tessfaces
-        */
-
-       if ((index_array = CustomData_get_layer(&me->fdata, CD_ORIGINDEX))) {
-               faces = me->mface;
-               totface = me->totface;
-               
-               /* loop over tessfaces */
-               for (i = 0; i < totface; i++) {
-                       if (index_array[i] != ORIGINDEX_NONE) {
-                               /* Copy flags onto the original tessface from its original poly */
-                               mp_orig = me->mpoly + index_array[i];
-                               faces[i].flag = mp_orig->flag;
-                       }
-               }
-       }
+       /* Mesh polys => Final derived polys */
 
        if ((index_array = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX))) {
                polys = dm->getPolyArray(dm);
@@ -113,21 +93,6 @@ void paintface_flush_flags(Object *ob)
                        }
                }
        }
-
-       if ((index_array = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))) {
-               polys = dm->getPolyArray(dm);
-               faces = dm->getTessFaceArray(dm);
-               totface = dm->getNumTessFaces(dm);
-
-               /* loop over tessfaces */
-               for (i = 0; i < totface; i++) {
-                       if (index_array[i] != ORIGINDEX_NONE) {
-                               /* Copy flags onto the final tessface from its final poly */
-                               mp_orig = polys + index_array[i];
-                               faces[i].flag = mp_orig->flag;
-                       }
-               }
-       }
 }
 
 void paintface_hide(Object *ob, const bool unselected)
index e34bcf7c97b0740fe778598a060752a1046be82e..cafc773c48cb9f587e67cef39d64fd6ad102c9fd 100644 (file)
@@ -91,45 +91,6 @@ static bool vertex_paint_use_fast_update_check(Object *ob)
        return false;
 }
 
-/* if the polygons from the mesh and the 'derivedFinal' match
- * we can assume that no modifiers are applied and that its worth adding tessellated faces
- * so 'vertex_paint_use_fast_update_check()' returns true */
-static bool vertex_paint_use_tessface_check(Object *ob, Mesh *me)
-{
-       DerivedMesh *dm = ob->derivedFinal;
-
-       if (me && dm) {
-               return (me->mpoly == CustomData_get_layer(&dm->polyData, CD_MPOLY));
-       }
-
-       return false;
-}
-
-static void update_tessface_data(Object *ob, Mesh *me)
-{
-       if (vertex_paint_use_tessface_check(ob, me)) {
-               /* assume if these exist, that they are up to date & valid */
-               if (!me->mcol || !me->mface) {
-                       /* should always be true */
-                       /* XXX Why this clearing? tessface_calc will reset it anyway! */
-#if 0
-                       if (me->mcol) {
-                               memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface);
-                       }
-#endif
-
-                       /* create tessfaces because they will be used for drawing & fast updates */
-                       BKE_mesh_tessface_calc(me); /* does own call to update pointers */
-               }
-       }
-       else {
-               if (me->totface) {
-                       /* this wont be used, theres no need to keep it */
-                       BKE_mesh_tessface_clear(me);
-               }
-       }
-
-}
 /* polling - retrieve whether cursor should be set or operator should be done */
 
 /* Returns true if vertex paint mode is active */
@@ -205,80 +166,7 @@ unsigned int vpaint_get_current_col(Scene *scene, VPaint *vp)
        return *(unsigned int *)col;
 }
 
-static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag)
-{
-       /* if no mcol: do not do */
-       /* if tface: only the involved faces, otherwise all */
-       const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
-       MFace *mface;
-       int a;
-       short *scolmain, *scol;
-       char *mcol;
-       const bool *mftag;
-       
-       if (me->mcol == NULL || me->totvert == 0 || me->totface == 0) return;
-       
-       scolmain = MEM_callocN(4 * sizeof(short) * me->totvert, "colmain");
-       
-       mface = me->mface;
-       mcol = (char *)me->mcol;
-       for (a = me->totface; a > 0; a--, mface++, mcol += 16) {
-               if ((use_face_sel == false) || (mface->flag & ME_FACE_SEL)) {
-                       scol = scolmain + 4 * mface->v1;
-                       scol[0]++; scol[1] += mcol[1]; scol[2] += mcol[2]; scol[3] += mcol[3];
-                       scol = scolmain + 4 * mface->v2;
-                       scol[0]++; scol[1] += mcol[5]; scol[2] += mcol[6]; scol[3] += mcol[7];
-                       scol = scolmain + 4 * mface->v3;
-                       scol[0]++; scol[1] += mcol[9]; scol[2] += mcol[10]; scol[3] += mcol[11];
-                       if (mface->v4) {
-                               scol = scolmain + 4 * mface->v4;
-                               scol[0]++; scol[1] += mcol[13]; scol[2] += mcol[14]; scol[3] += mcol[15];
-                       }
-               }
-       }
-       
-       a = me->totvert;
-       scol = scolmain;
-       while (a--) {
-               if (scol[0] > 1) {
-                       scol[1] = divide_round_i(scol[1], scol[0]);
-                       scol[2] = divide_round_i(scol[2], scol[0]);
-                       scol[3] = divide_round_i(scol[3], scol[0]);
-               }
-               scol += 4;
-       }
-
-       mface = me->mface;
-       mcol = (char *)me->mcol;
-       mftag = mfacetag;
-       for (a = me->totface; a > 0; a--, mface++, mcol += 16, mftag += 4) {
-               if ((use_face_sel == false) || (mface->flag & ME_FACE_SEL)) {
-                       if (mftag[0]) {
-                               scol = scolmain + 4 * mface->v1;
-                               mcol[1] = scol[1]; mcol[2] = scol[2]; mcol[3] = scol[3];
-                       }
-
-                       if (mftag[1]) {
-                               scol = scolmain + 4 * mface->v2;
-                               mcol[5] = scol[1]; mcol[6] = scol[2]; mcol[7] = scol[3];
-                       }
-
-                       if (mftag[2]) {
-                               scol = scolmain + 4 * mface->v3;
-                               mcol[9] = scol[1]; mcol[10] = scol[2]; mcol[11] = scol[3];
-                       }
-
-                       if (mface->v4 && mftag[3]) {
-                               scol = scolmain + 4 * mface->v4;
-                               mcol[13] = scol[1]; mcol[14] = scol[2]; mcol[15] = scol[3];
-                       }
-               }
-       }
-
-       MEM_freeN(scolmain);
-}
-
-static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const bool do_tessface)
+static void do_shared_vertexcol(Mesh *me, bool *mlooptag)
 {
        const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
        MPoly *mp;
@@ -332,10 +220,6 @@ static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const
        }
 
        MEM_freeN(scol);
-
-       if (has_shared && do_tessface) {
-               do_shared_vertex_tesscol(me, mfacetag);
-       }
 }
 
 static bool make_vertexcol(Object *ob)  /* single ob */
@@ -352,17 +236,12 @@ static bool make_vertexcol(Object *ob)  /* single ob */
 
        /* copies from shadedisplist to mcol */
        if (!me->mloopcol && me->totloop) {
-               if (!me->mcol) {
-                       CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
-               }
                if (!me->mloopcol) {
                        CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
                }
                BKE_mesh_update_customdata_pointers(me, true);
        }
 
-       update_tessface_data(ob, me);
-       
        DAG_id_tag_update(&me->id, 0);
        
        return (me->mloopcol != NULL);
@@ -593,7 +472,7 @@ bool ED_vpaint_smooth(Object *ob)
        /* remove stale me->mcol, will be added later */
        BKE_mesh_tessface_clear(me);
 
-       do_shared_vertexcol(me, mlooptag, NULL, false);
+       do_shared_vertexcol(me, mlooptag);
 
        MEM_freeN(mlooptag);
 
@@ -2753,35 +2632,13 @@ typedef struct VPaintData {
         * array, otherwise we need to refresh the modifier stack */
        bool use_fast_update;
 
-       /* mpoly -> mface mapping */
-       MeshElemMap *polyfacemap;
-       void *polyfacemap_mem;
-
        /* loops tagged as having been painted, to apply shared vertex color
         * blending only to modified loops */
        bool *mlooptag;
-       bool *mfacetag;
 
        bool is_texbrush;
 } VPaintData;
 
-static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me)
-{
-       const int *tessface_origindex;
-
-       vd->polyfacemap = NULL;
-       vd->polyfacemap_mem = NULL;
-
-       tessface_origindex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX);
-
-       if (!tessface_origindex)
-               return;
-
-       BKE_mesh_origindex_map_create(&vd->polyfacemap, (int **)&vd->polyfacemap_mem,
-                                     me->totpoly,
-                                     tessface_origindex, me->totface);
-}
-
 static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2]))
 {
        Scene *scene = CTX_data_scene(C);
@@ -2804,11 +2661,6 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
        if (me->mloopcol == NULL)
                return false;
 
-       /* Update tessface data if needed
-        * Added here too because e.g. switching to/from edit mode would remove tessface data,
-        * yet "fast_update" could still be used! */
-       update_tessface_data(ob, me);
-
        /* make mode data storage */
        vpd = MEM_callocN(sizeof(struct VPaintData), "VPaintData");
        paint_stroke_set_mode_data(stroke, vpd);
@@ -2825,7 +2677,6 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
        /* are we painting onto a modified mesh?,
         * if not we can skip face map trickyness */
        if (vertex_paint_use_fast_update_check(ob)) {
-               vpaint_build_poly_facemap(vpd, me);
                vpd->use_fast_update = true;
 /*             printf("Fast update!\n");*/
        }
@@ -2837,8 +2688,6 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
        /* to keep tracked of modified loops for shared vertex color blending */
        if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
                vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
-               if (vpd->use_fast_update)
-                       vpd->mfacetag = MEM_mallocN(sizeof(bool) * me->totface * 4, "VPaintData mfacetag");
        }
 
        /* for filtering */
@@ -2859,14 +2708,10 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me,
        ViewContext *vc = &vpd->vc;
        Brush *brush = BKE_paint_brush(&vp->paint);
        MPoly *mpoly = &me->mpoly[index];
-       MFace *mf;
-       MCol *mc;
        MLoop *ml;
-       MLoopCol *mlc;
        unsigned int *lcol = ((unsigned int *)me->mloopcol) + mpoly->loopstart;
        unsigned int *lcolorig = ((unsigned int *)vp->vpaint_prev) + mpoly->loopstart;
        bool *mlooptag = (vpd->mlooptag) ? vpd->mlooptag + mpoly->loopstart : NULL;
-       bool *mftag;
        float alpha;
        int i, j;
        int totloop = mpoly->totloop;
@@ -2923,35 +2768,6 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me,
                        if (mlooptag) mlooptag[i] = 1;
                }
        }
-
-       if (vpd->use_fast_update) {
-               const MeshElemMap *map = &vpd->polyfacemap[index];
-
-               /* update vertex colors for tessellations incrementally,
-                * rather then regenerating the tessellation altogether */
-               for (i = 0; i < map->count; i++) {
-                       const int index_tessface = map->indices[i];
-
-                       mf = &me->mface[index_tessface];
-                       mc = &me->mcol[index_tessface * 4];
-                       mftag = &vpd->mfacetag[index_tessface * 4];
-
-                       ml = me->mloop + mpoly->loopstart;
-                       mlc = me->mloopcol + mpoly->loopstart;
-
-                       for (j = 0; j < totloop; j++, ml++, mlc++) {
-                               /* search for the loop vertex within the tessface */
-                               const int fidx = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, ml->v);
-                               if (fidx != -1) {
-                                       MESH_MLOOPCOL_TO_MCOL(mlc, mc + fidx);
-                                       if (mlooptag) {
-                                               mftag[fidx] = mlooptag[j];
-                                       }
-                               }
-                       }
-               }
-       }
-
 }
 
 static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
@@ -3003,8 +2819,6 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
        /* clear modified tag for blur tool */
        if (vpd->mlooptag)
                memset(vpd->mlooptag, 0, sizeof(bool) * me->totloop);
-       if (vpd->mfacetag)
-               memset(vpd->mfacetag, 0, sizeof(bool) * me->totface * 4);
 
        for (index = 0; index < totindex; index++) {
                if (indexar[index] && indexar[index] <= me->totpoly) {
@@ -3016,8 +2830,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 
        /* was disabled because it is slow, but necessary for blur */
        if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) {
-               int do_tessface = vpd->use_fast_update;
-               do_shared_vertexcol(me, vpd->mlooptag, vpd->mfacetag, do_tessface);
+               do_shared_vertexcol(me, vpd->mlooptag);
        }
 
        ED_region_tag_redraw(vc->ar);
@@ -3046,20 +2859,9 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
        /* frees prev buffer */
        copy_vpaint_prev(ts->vpaint, NULL, 0);
 
-       if (vpd->polyfacemap) {
-               MEM_freeN(vpd->polyfacemap);
-       }
-
-       if (vpd->polyfacemap_mem) {
-               MEM_freeN(vpd->polyfacemap_mem);
-       }
-
        if (vpd->mlooptag)
                MEM_freeN(vpd->mlooptag);
 
-       if (vpd->mfacetag)
-               MEM_freeN(vpd->mfacetag);
-
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
 
        MEM_freeN(vpd);
index b0250dfdec049581d137012d8c958ad3f637bede..9ccacbad4a21f3c54db9dfdbb9c063ec6b2bf240 100644 (file)
@@ -80,14 +80,14 @@ typedef struct drawEMTFMapped_userData {
        BMEditMesh *em;
        bool has_mcol;
        int cd_poly_tex_offset;
-       MFace *mf;
-       MTFace *tf;
+       const MPoly *mpoly;
+       const MTexPoly *mtexpoly;
 } drawEMTFMapped_userData;
 
 typedef struct drawTFace_userData {
-       Mesh *me;
-       MFace *mf;
-       MTFace *tf;
+       const Mesh *me;
+       const MPoly *mpoly;
+       const MTexPoly *mtexpoly;
 } drawTFace_userData;
 
 /**************************** Face Select Mode *******************************/
@@ -590,11 +590,12 @@ static DMDrawOption draw_tface__set_draw(MTexPoly *mtexpoly, const bool UNUSED(h
 
 static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol)
 {
+       const MPoly *mp = dm->getPolyArray(dm);
+       const int mpoly_num = dm->getNumPolys(dm);
        MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
-       MFace *mface = dm->getTessFaceArray(dm);
-       MCol *finalCol;
+       MLoopCol *finalCol;
        int i, j;
-       MCol *mcol = NULL;
+       MLoopCol *mloopcol = NULL;
 
        /* cache material values to avoid a lot of lookups */
        Material *ma = NULL;
@@ -606,108 +607,94 @@ static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol)
        } copy_mode = COPY_CALC;
 
        if (use_mcol) {
-               mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
-               if (!mcol)
-                       mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
+               mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
+               if (!mloopcol)
+                       mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
        }
 
-       if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) {
-               finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL);
+       if (CustomData_has_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL)) {
+               finalCol = CustomData_get_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL);
        }
        else {
-               finalCol = MEM_mallocN(sizeof(MCol) * 4 * dm->getNumTessFaces(dm), "add_tface_color_layer");
-
-               CustomData_add_layer(&dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numTessFaceData);
+               finalCol = MEM_mallocN(sizeof(MLoopCol) * dm->numLoopData, "add_tface_color_layer");
+               CustomData_add_layer(&dm->loopData, CD_TEXTURE_MLOOPCOL, CD_ASSIGN, finalCol, dm->numLoopData);
        }
 
-       for (i = 0; i < dm->getNumTessFaces(dm); i++) {
-               const short mat_nr = mface[i].mat_nr;
+       for (i = mpoly_num; i--; mp++) {
+               const short mat_nr = mp->mat_nr;
 
                if (UNLIKELY(mat_nr_prev != mat_nr)) {
-                       ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1);
+                       ma = give_current_material(Gtexdraw.ob, mat_nr + 1);
                        copy_mode = COPY_CALC;
                        mat_nr_prev = mat_nr;
                }
 
                /* avoid lookups  */
                if (copy_mode == COPY_ORIG) {
-                       memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4);
+                       memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
                }
                else if (copy_mode == COPY_PREV) {
-                       memcpy(&finalCol[i * 4], &finalCol[(i - 1) * 4], sizeof(MCol) * 4);
+                       int loop_index = mp->loopstart;
+                       const MLoopCol *lcol_prev = &finalCol[(mp - 1)->loopstart];
+                       for (j = 0; j < mp->totloop; j++, loop_index++) {
+                               finalCol[loop_index] = *lcol_prev;
+                       }
                }
 
                /* (copy_mode == COPY_CALC) */
                else if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
-                       if (mcol) {
-                               memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4);
+                       if (mloopcol) {
+                               memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
                                copy_mode = COPY_ORIG;
                        }
                        else {
-                               for (j = 0; j < 4; j++) {
-                                       finalCol[i * 4 + j].b = 255;
-                                       finalCol[i * 4 + j].g = 255;
-                                       finalCol[i * 4 + j].r = 255;
-                               }
+                               memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
                                copy_mode = COPY_PREV;
                        }
                }
                else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw)) {
-                       for (j = 0; j < 4; j++) {
-                               finalCol[i * 4 + j].b = 255;
-                               finalCol[i * 4 + j].g = 0;
-                               finalCol[i * 4 + j].r = 255;
+                       int loop_index = mp->loopstart;
+                       for (j = 0; j < mp->totloop; j++, loop_index++) {
+                               finalCol[loop_index].r = 255;
+                               finalCol[loop_index].g = 0;
+                               finalCol[loop_index].b = 255;
                        }
                        copy_mode = COPY_PREV;
                }
                else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
-                       for (j = 0; j < 4; j++) {
-                               finalCol[i * 4 + j].b = Gtexdraw.obcol[0];
-                               finalCol[i * 4 + j].g = Gtexdraw.obcol[1];
-                               finalCol[i * 4 + j].r = Gtexdraw.obcol[2];
+                       int loop_index = mp->loopstart;;
+                       for (j = 0; j < mp->totloop; j++, loop_index++) {
+                               copy_v3_v3_char(&finalCol[loop_index].r, (char *)Gtexdraw.obcol);
                        }
                        copy_mode = COPY_PREV;
                }
                else {
-                       if (mcol) {
-                               memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4);
+                       if (mloopcol) {
+                               memcpy(&finalCol[mp->loopstart], &mloopcol[mp->loopstart], sizeof(*finalCol) * mp->totloop);
                                copy_mode = COPY_ORIG;
                        }
                        else if (mtexpoly) {
-                               for (j = 0; j < 4; j++) {
-                                       finalCol[i * 4 + j].b = 255;
-                                       finalCol[i * 4 + j].g = 255;
-                                       finalCol[i * 4 + j].r = 255;
-                               }
+                               memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
                                copy_mode = COPY_PREV;
                        }
                        else {
-                               if (ma) {
-                                       float col[3];
-                                       MCol tcol;
-
-                                       if (Gtexdraw.color_profile) {
-                                               linearrgb_to_srgb_v3_v3(col, &ma->r);
-                                       }
-                                       else {
-                                               copy_v3_v3(col, &ma->r);
-                                       }
+                               float col[3];
 
-                                       tcol.b = FTOCHAR(col[0]);
-                                       tcol.g = FTOCHAR(col[1]);
-                                       tcol.r = FTOCHAR(col[2]);
-                                       tcol.a = 255;
+                               if (ma) {
+                                       int loop_index = mp->loopstart;
+                                       MLoopCol lcol;
 
-                                       for (j = 0; j < 4; j++) {
-                                               finalCol[i * 4 + j] = tcol;
+                                       if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
+                                       else copy_v3_v3(col, &ma->r);
+                                       rgb_float_to_uchar((unsigned char *)&lcol.r, col);
+                                       lcol.a = 255;
+                                       
+                                       for (j = 0; j < mp->totloop; j++, loop_index++) {
+                                               finalCol[loop_index] = lcol;
                                        }
                                }
                                else {
-                                       for (j = 0; j < 4; j++) {
-                                               finalCol[i * 4 + j].b = 255;
-                                               finalCol[i * 4 + j].g = 255;
-                                               finalCol[i * 4 + j].r = 255;
-                                       }
+                                       memset(&finalCol[mp->loopstart], 0xff, sizeof(*finalCol) * mp->totloop);
                                }
                                copy_mode = COPY_PREV;
                        }
@@ -717,7 +704,7 @@ static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol)
 
 static DMDrawOption draw_tface_mapped__set_draw(void *userData, int origindex, int UNUSED(mat_nr))
 {
-       Mesh *me = ((drawTFace_userData *)userData)->me;
+       const Mesh *me = ((drawTFace_userData *)userData)->me;
 
        /* array checked for NULL before calling */
        MPoly *mpoly = &me->mpoly[origindex];
@@ -915,10 +902,10 @@ static int compareDrawOptions(void *userData, int cur_index, int next_index)
 {
        drawTFace_userData *data = userData;
 
-       if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
+       if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr)
                return 0;
 
-       if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
+       if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage)
                return 0;
 
        return 1;
@@ -929,10 +916,10 @@ static int compareDrawOptionsEm(void *userData, int cur_index, int next_index)
 {
        drawEMTFMapped_userData *data = userData;
 
-       if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
+       if (data->mpoly && data->mpoly[cur_index].mat_nr != data->mpoly[next_index].mat_nr)
                return 0;
 
-       if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
+       if (data->mtexpoly && data->mtexpoly[cur_index].tpage != data->mtexpoly[next_index].tpage)
                return 0;
 
        return 1;
@@ -964,8 +951,8 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
                data.has_mcol = CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_MLOOPCOL);
                data.cd_poly_tex_offset = CustomData_get_offset(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY);
 
-               data.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
-               data.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+               data.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY);
+               data.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
 
                dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data, 0);
        }
@@ -976,8 +963,8 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
                else {
                        drawTFace_userData userData;
 
-                       userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
-                       userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+                       userData.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY);
+                       userData.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
                        userData.me = me;
                        dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, &userData, uvflag);
                }
@@ -987,8 +974,8 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
                
                update_tface_color_layer(dm, !(ob->mode & OB_MODE_TEXTURE_PAINT));
                
-               userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
-               userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
+               userData.mpoly = DM_get_poly_data_layer(dm, CD_MPOLY);
+               userData.mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
                userData.me = NULL;
                
                dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData, uvflag);
index 9c2ca6c5305ca26894b1455f5d167f5f73716677..12e66264661858c96dde0d03f6f776657080bdb6 100644 (file)
@@ -212,9 +212,12 @@ void GPU_interleaved_attrib_unbind(void);
 typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
 
 /* build */
-GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(const int (*face_vert_indices)[4],
-        const struct MFace *mface, const struct MVert *mvert,
-        const int *face_indices, int totface);
+GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
+        const int (*face_vert_indices)[4],
+        const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopTri *looptri,
+        const struct MVert *verts,
+        const int *face_indices,
+        const int  face_indices_len);
 
 GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
                                     unsigned int **grid_hidden, int gridsize, const struct CCGKey *key);
index d30ca9f27df3975017de38350a150f1223b5ae59..cd3a5d6d72584482d35a1351281ef4511c931e17 100644 (file)
@@ -644,11 +644,11 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
 
        /* special handling for MCol and UV buffers */
        if (type == GPU_BUFFER_COLOR) {
-               if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
+               if (!(user_data = DM_get_loop_data_layer(dm, dm->drawObject->colType)))
                        return NULL;
        }
        else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) {
-               if (!DM_get_tessface_data_layer(dm, CD_MTFACE))
+               if (!DM_get_loop_data_layer(dm, CD_MLOOPUV))
                        return NULL;
        }
 
@@ -1090,10 +1090,13 @@ struct GPU_PBVH_Buffers {
        GLenum index_type;
 
        /* mesh pointers in case buffer allocation fails */
-       const MFace *mface;
+       const MPoly *mpoly;
+       const MLoop *mloop;
+       const MLoopTri *looptri;
        const MVert *mvert;
+
        const int *face_indices;
-       int totface;
+       int        face_indices_len;
        const float *vmask;
 
        /* grid pointers */
@@ -1177,7 +1180,7 @@ void GPU_update_mesh_pbvh_buffers(
         const int (*face_vert_indices)[4], bool show_diffuse_color)
 {
        VertexBufferFormat *vert_data;
-       int i, j, k;
+       int i, j;
 
        buffers->vmask = vmask;
        buffers->show_diffuse_color = show_diffuse_color;
@@ -1190,9 +1193,10 @@ void GPU_update_mesh_pbvh_buffers(
                if (buffers->use_matcaps)
                        diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
                else if (show_diffuse_color) {
-                       const MFace *f = buffers->mface + buffers->face_indices[0];
+                       const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+                       const MPoly *mp = &buffers->mpoly[lt->poly];
 
-                       GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+                       GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
                }
 
                copy_v4_v4(buffers->diffuse_color, diffuse_color);
@@ -1225,72 +1229,61 @@ void GPU_update_mesh_pbvh_buffers(
                                                rgb_float_to_uchar(out->color, diffuse_color); \
                                } (void)0
 
-                               for (i = 0; i < buffers->totface; i++) {
-                                       const MFace *f = buffers->mface + buffers->face_indices[i];
-
-                                       UPDATE_VERTEX(i, f->v1, 0, diffuse_color);
-                                       UPDATE_VERTEX(i, f->v2, 1, diffuse_color);
-                                       UPDATE_VERTEX(i, f->v3, 2, diffuse_color);
-                                       if (f->v4)
-                                               UPDATE_VERTEX(i, f->v4, 3, diffuse_color);
+                               for (i = 0; i < buffers->face_indices_len; i++) {
+                                       const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
+                                       const unsigned int vtri[3] = {
+                                           buffers->mloop[lt->tri[0]].v,
+                                           buffers->mloop[lt->tri[1]].v,
+                                           buffers->mloop[lt->tri[2]].v,
+                                       };
+
+                                       UPDATE_VERTEX(i, vtri[0], 0, diffuse_color);
+                                       UPDATE_VERTEX(i, vtri[1], 1, diffuse_color);
+                                       UPDATE_VERTEX(i, vtri[2], 2, diffuse_color);
                                }
 #undef UPDATE_VERTEX
                        }
                        else {
-                               for (i = 0; i < buffers->totface; ++i) {
-                                       const MFace *f = &buffers->mface[buffers->face_indices[i]];
-                                       const unsigned int *fv = &f->v1;
-                                       const int vi[2][3] = {{0, 1, 2}, {3, 0, 2}};
+                               for (i = 0; i < buffers->face_indices_len; ++i) {
+                                       const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
+                                       const unsigned int vtri[3] = {
+                                           buffers->mloop[lt->tri[0]].v,
+                                           buffers->mloop[lt->tri[1]].v,
+                                           buffers->mloop[lt->tri[2]].v,
+                                       };
                                        float fno[3];
                                        short no[3];
 
                                        float fmask;
 
-                                       if (paint_is_face_hidden(f, mvert))
+                                       if (paint_is_face_hidden(lt, mvert, buffers->mloop))
                                                continue;
 
                                        /* Face normal and mask */
-                                       if (f->v4) {
-                                               normal_quad_v3(fno,
-                                                                          mvert[fv[0]].co,
-                                                                          mvert[fv[1]].co,
-                                                                          mvert[fv[2]].co,
-                                                                          mvert[fv[3]].co);
-                                               if (vmask) {
-                                                       fmask = (vmask[fv[0]] +
-                                                                        vmask[fv[1]] +
-                                                                        vmask[fv[2]] +
-                                                                        vmask[fv[3]]) * 0.25f;
-                                               }
-                                       }
-                                       else {
-                                               normal_tri_v3(fno,
-                                                                         mvert[fv[0]].co,
-                                                                         mvert[fv[1]].co,
-                                                                         mvert[fv[2]].co);
-                                               if (vmask) {
-                                                       fmask = (vmask[fv[0]] +
-                                                                        vmask[fv[1]] +
-                                                                        vmask[fv[2]]) / 3.0f;
-                                               }
+                                       normal_tri_v3(fno,
+                                                     mvert[vtri[0]].co,
+                                                     mvert[vtri[1]].co,
+                                                     mvert[vtri[2]].co);
+                                       if (vmask) {
+                                               fmask = (vmask[vtri[0]] +
+                                                        vmask[vtri[1]] +
+                                                        vmask[vtri[2]]) / 3.0f;
                                        }
                                        normal_float_to_short_v3(no, fno);
 
-                                       for (j = 0; j < (f->v4 ? 2 : 1); j++) {
-                                               for (k = 0; k < 3; k++) {
-                                                       const MVert *v = &mvert[fv[vi[j][k]]];
-                                                       VertexBufferFormat *out = vert_data;
+                                       for (j = 0; j < 3; j++) {
+                                               const MVert *v = &mvert[vtri[j]];
+                                               VertexBufferFormat *out = vert_data;
 
-                                                       copy_v3_v3(out->co, v->co);
-                                                       memcpy(out->no, no, sizeof(short) * 3);
+                                               copy_v3_v3(out->co, v->co);
+                                               copy_v3_v3_short(out->no, no);
 
-                                                       if (vmask)
-                                                               gpu_color_from_mask_copy(fmask, diffuse_color, out->color);
-                                                       else
-                                                               rgb_float_to_uchar(out->color, diffuse_color);
+                                               if (vmask)
+                                                       gpu_color_from_mask_copy(fmask, diffuse_color, out->color);
+                                               else
+                                                       rgb_float_to_uchar(out->color, diffuse_color);
 
-                                                       vert_data++;
-                                               }
+                                               vert_data++;
                                        }
                                }
                        }
@@ -1308,35 +1301,39 @@ void GPU_update_mesh_pbvh_buffers(
        buffers->mvert = mvert;
 }
 
-GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(const int (*face_vert_indices)[4],
-        const MFace *mface, const MVert *mvert,
+GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
+        const int (*face_vert_indices)[4],
+        const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri,
+        const MVert *mvert,
         const int *face_indices,
-        int totface)
+        const int  face_indices_len)
 {
        GPU_PBVH_Buffers *buffers;
        unsigned short *tri_data;
-       int i, j, k, tottri;
+       int i, j, tottri;
 
        buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
        buffers->index_type = GL_UNSIGNED_SHORT;
-       buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH;
+       buffers->smooth = mpoly[face_indices[0]].flag & ME_SMOOTH;
 
        buffers->show_diffuse_color = false;
        buffers->use_matcaps = false;
 
        /* Count the number of visible triangles */
-       for (i = 0, tottri = 0; i < totface; ++i) {
-               const MFace *f = &mface[face_indices[i]];
-               if (!paint_is_face_hidden(f, mvert))
-                       tottri += f->v4 ? 2 : 1;
+       for (i = 0, tottri = 0; i < face_indices_len; ++i) {
+               const MLoopTri *lt = &looptri[face_indices[i]];
+               if (!paint_is_face_hidden(lt, mvert, mloop))
+                       tottri++;
        }
 
        if (tottri == 0) {
                buffers->tot_tri = 0;
 
-               buffers->mface = mface;
+               buffers->mpoly = mpoly;
+               buffers->mloop = mloop;
+               buffers->looptri = looptri;
                buffers->face_indices = face_indices;
-               buffers->totface = 0;
+               buffers->face_indices_len = 0;
 
                return buffers;
        }
@@ -1351,26 +1348,16 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(const int (*face_vert_indices)[4],
                /* Fill the triangle buffer */
                tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX);
                if (tri_data) {
-                       for (i = 0; i < totface; ++i) {
-                               const MFace *f = mface + face_indices[i];
-                               int v[3];
+                       for (i = 0; i < face_indices_len; ++i) {
+                               const MLoopTri *lt = &looptri[face_indices[i]];
 
                                /* Skip hidden faces */
-                               if (paint_is_face_hidden(f, mvert))
+                               if (paint_is_face_hidden(lt, mvert, mloop))
                                        continue;
 
-                               v[0] = 0;
-                               v[1] = 1;
-                               v[2] = 2;
-
-                               for (j = 0; j < (f->v4 ? 2 : 1); ++j) {
-                                       for (k = 0; k < 3; ++k) {
-                                               *tri_data = face_vert_indices[i][v[k]];
-                                               tri_data++;
-                                       }
-                                       v[0] = 3;
-                                       v[1] = 0;
-                                       v[2] = 2;
+                               for (j = 0; j < 3; ++j) {
+                                       *tri_data = face_vert_indices[i][j];
+                                       tri_data++;
                                }
                        }
                        GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
@@ -1385,9 +1372,12 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(const int (*face_vert_indices)[4],
 
        buffers->tot_tri = tottri;
 
-       buffers->mface = mface;
+       buffers->mpoly = mpoly;
+       buffers->mloop = mloop;
+       buffers->looptri = looptri;
+
        buffers->face_indices = face_indices;
-       buffers->totface = totface;
+       buffers->face_indices_len = face_indices_len;
 
        return buffers;
 }
@@ -1946,9 +1936,10 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
        /* sets material from the first face, to solve properly face would need to
         * be sorted in buckets by materials */
        if (setMaterial) {
-               if (buffers->totface) {
-                       const MFace *f = &buffers->mface[buffers->face_indices[0]];
-                       if (!setMaterial(f->mat_nr + 1, NULL))
+               if (buffers->face_indices_len) {
+                       const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+                       const MPoly *mp = &buffers->mpoly[lt->poly];
+                       if (!setMaterial(mp->mat_nr + 1, NULL))
                                return;
                }
                else if (buffers->totgrid) {
@@ -1962,7 +1953,7 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
                }
        }
 
-       glShadeModel((buffers->smooth || buffers->totface) ? GL_SMOOTH : GL_FLAT);
+       glShadeModel((buffers->smooth || buffers->face_indices_len) ? GL_SMOOTH : GL_FLAT);
 
        if (buffers->vert_buf) {
                char *base = NULL;
@@ -2056,10 +2047,11 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
        if ((buffers->show_diffuse_color == false) || use_matcaps)
                return false;
 
-       if (buffers->mface) {
-               const MFace *f = &buffers->mface[buffers->face_indices[0]];
+       if (buffers->looptri) {
+               const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+               const MPoly *mp = &buffers->mpoly[lt->poly];
 
-               GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+               GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
        }
        else if (buffers->use_bmesh) {
                /* due to dynamic nature of dyntopo, only get first material */
index a92c8b3307c2ba779e84970e85aa96c7d54f44d1..79be28bb1aa67e7622aee7bcfd2fed25768efb21 100644 (file)
@@ -99,7 +99,7 @@ typedef enum CustomDataType {
        CD_MDISPS           = 19,
        CD_PREVIEW_MCOL     = 20,  /* for displaying weightpaint colors */
 /*     CD_ID_MCOL          = 21, */
-       CD_TEXTURE_MCOL     = 22,
+       CD_TEXTURE_MLOOPCOL = 22,
        CD_CLOTH_ORCO       = 23,
        CD_RECAST           = 24,
 
index b76f40c884d59426dc43b2067a6343795857bb56..12c6e0ec0a5a35abd78612bc66f5ae8f048e156a 100644 (file)
@@ -89,6 +89,14 @@ typedef struct MLoop {
        unsigned int e;  /* edge index */
 } MLoop;
 
+/* runtime only */
+#
+#
+typedef struct MLoopTri {
+       unsigned int tri[3];
+       unsigned int poly;
+} MLoopTri;
+
 typedef struct MTexPoly {
        struct Image *tpage;
        char flag, transp;
@@ -345,6 +353,9 @@ enum {
 #define ME_POLY_LOOP_PREV(mloop, mp, i)  (&(mloop)[(mp)->loopstart + (((i) + (mp)->totloop - 1) % (mp)->totloop)])
 #define ME_POLY_LOOP_NEXT(mloop, mp, i)  (&(mloop)[(mp)->loopstart + (((i) + 1) % (mp)->totloop)])
 
+/* number of tri's that make up this polygon once tessellated */
+#define ME_POLY_TRI_TOT(mp) ((mp)->totloop - 2)
+
 /* mselect->type */
 enum {
        ME_VSEL = 0,