svn merge ^/trunk/blender -r40372:40379
authorCampbell Barton <ideasman42@gmail.com>
Fri, 23 Sep 2011 06:18:03 +0000 (06:18 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 23 Sep 2011 06:18:03 +0000 (06:18 +0000)
1  2 
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/editors/armature/editarmature.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/editors/space_view3d/view3d_select.c

index 384de9963f8d51c1aa07d4d8063628b7795d6ec9,e955a47b1e76cf0e1a0795d6237fc2a65082dae0..13d9da487b936d62836a4d2e270ac098181a2a2c
@@@ -1,4 -1,4 +1,4 @@@
 -/*
 + /*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
   
  #include "GL/glew.h"
  
 +#include "BKE_cdderivedmesh.h"
 +#include "BKE_global.h"
 +#include "BKE_mesh.h"
 +#include "BKE_paint.h"
 +#include "BKE_utildefines.h"
 +#include "BKE_tessmesh.h"
 +
 +#include "BLI_editVert.h"
 +#include "BLI_scanfill.h"
 +#include "BLI_math.h"
  #include "BLI_blenlib.h"
  #include "BLI_edgehash.h"
  #include "BLI_editVert.h"
  #include "BLI_math.h"
  #include "BLI_pbvh.h"
 +#include "BLI_array.h"
 +#include "BLI_smallhash.h"
  #include "BLI_utildefines.h"
  
  #include "BKE_cdderivedmesh.h"
@@@ -86,8 -74,6 +86,8 @@@ typedef struct 
        MVert *mvert;
        MEdge *medge;
        MFace *mface;
 +      MLoop *mloop;
 +      MPoly *mpoly;
  
        /* Cached */
        struct PBVH *pbvh;
@@@ -109,16 -95,11 +109,16 @@@ static int cdDM_getNumEdges(DerivedMes
        return dm->numEdgeData;
  }
  
 -static int cdDM_getNumFaces(DerivedMesh *dm)
 +static int cdDM_getNumTessFaces(DerivedMesh *dm)
  {
        return dm->numFaceData;
  }
  
 +static int cdDM_getNumFaces(DerivedMesh *dm)
 +{
 +      return dm->numPolyData;
 +}
 +
  static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
  {
        CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@@ -155,18 -136,6 +155,18 @@@ static void cdDM_copyFaceArray(DerivedM
        memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
  }
  
 +static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *loop_r)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
 +      memcpy(loop_r, cddm->mloop, sizeof(*loop_r) * dm->numLoopData);
 +}
 +
 +static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *poly_r)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
 +      memcpy(poly_r, cddm->mpoly, sizeof(*poly_r) * dm->numPolyData);
 +}
 +
  static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
  {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
@@@ -236,7 -205,7 +236,7 @@@ static int can_pbvh_draw(Object *ob, De
        if(deformed)
                return 0;
  
 -      return (cddm->mvert == me->mvert) || ob->sculpt->kb;
 +      return cddm->mvert == me->mvert || ob->sculpt->kb;
  }
  
  static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
@@@ -325,7 -294,7 +325,7 @@@ static void cdDM_drawUVEdges(DerivedMes
  {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
        MFace *mf = cddm->mface;
 -      MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
 +      MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
        int i;
  
        if(mf) {
@@@ -496,7 -465,7 +496,7 @@@ static void cdDM_drawFacesSolid(Derived
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
        MVert *mvert = cddm->mvert;
        MFace *mface = cddm->mface;
 -      float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
 +      float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
        int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
  
  #define PASSVERT(index) {                                             \
@@@ -678,21 -647,21 +678,21 @@@ static void cdDM_drawFacesColored(Deriv
  }
  
  static void cdDM_drawFacesTex_common(DerivedMesh *dm,
 -                         int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
 -                         int (*drawParamsMapped)(void *userData, int index),
 -                         void *userData) 
 +               int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
 +               int (*drawParamsMapped)(void *userData, int index),
 +               void *userData) 
  {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
        MVert *mv = cddm->mvert;
 -      MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
 -      MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
 -      float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
 -      MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
 -      int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
 +      MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE);
 +      MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
 +      float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL);
 +      MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
 +      int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
        int startFace = 0, lastFlag = 0xdeadbeef;
 -      MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
 +      MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
        if(!mcol)
 -              mcol = dm->getFaceDataArray(dm, CD_MCOL);
 +              mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
  
        cdDM_update_normals_from_pbvh(dm);
  
                        unsigned char *cp = NULL;
  
                        if(drawParams) {
 -                              flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
 +                              flag = drawParams(tf? &tf[i]: NULL, mcol!=NULL, mf->mat_nr);
                        }
                        else {
                                if(index) {
                        }
                        
                        if( col != 0 ) {*/
 -                              unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
 -                              for( i=0; i < dm->getNumFaces(dm); i++ ) {
 +                              unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
 +                              for( i=0; i < dm->getNumTessFaces(dm); i++ ) {
                                        for( j=0; j < 4; j++ ) {
                                                colors[i*12+j*3] = col[i*4+j].r;
                                                colors[i*12+j*3+1] = col[i*4+j].g;
                                int flag = 1;
  
                                if(drawParams) {
 -                                      flag = drawParams(tf? &tf[actualFace]: NULL, mcol? &mcol[actualFace*4]: NULL, mf[actualFace].mat_nr);
 +                                      flag = drawParams(tf? &tf[actualFace]: NULL, mcol!=NULL, mf[actualFace].mat_nr);
                                }
                                else {
                                        if(index) {
        }
  }
  
 -static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
 +static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
  {
        cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
  }
@@@ -878,14 -847,14 +878,14 @@@ static void cdDM_drawMappedFaces(Derive
        MVert *mv = cddm->mvert;
        MFace *mf = cddm->mface;
        MCol *mc;
 -      float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
 -      int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
 +      float *nors= DM_get_tessface_data_layer(dm, CD_NORMAL);
 +      int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
  
 -      mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
 +      mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL);
        if(!mc)
 -              mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
 +              mc = DM_get_tessface_data_layer(dm, CD_WEIGHT_MCOL);
        if(!mc)
 -              mc = DM_get_face_data_layer(dm, CD_MCOL);
 +              mc = DM_get_tessface_data_layer(dm, CD_MCOL);
  
        cdDM_update_normals_from_pbvh(dm);
  
                                }
  
                                glEnd();
 -                      }
 +                      } /*else {
 +                              printf("eek in cddm draw mapped faces!\n");
 +                      }*/
                        
                        if (nors) nors += 3;
                }
@@@ -1042,7 -1009,6 +1042,7 @@@ static void cdDM_drawMappedFacesTex(Der
        cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
  }
  
 +
  static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, int smoothnormal)
  {
        int b;
        /* vertex normal */
        if(smoothnormal)
                glNormal3sv(mvert[index].no);
 -      
 +
        /* vertex coordinate */
        glVertex3fv(mvert[index].co);
  }
  
 +
  static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
  {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
        DMVertexAttribs attribs;
        MVert *mvert = cddm->mvert;
        MFace *mface = cddm->mface;
-       MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
 -      /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
 -      float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
++      /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
 +      float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL);
        int a, b, dodraw, matnr, new_matnr;
 -      int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
 +      int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
  
        cdDM_update_normals_from_pbvh(dm);
  
                        cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, smoothnormal);
                        cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, smoothnormal);
                        cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
 -
                        if(mface->v4)
                                cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, smoothnormal);
                        else
                                cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
 +
                }
                glEnd();
        }
@@@ -1457,72 -1422,35 +1457,72 @@@ static void cdDM_foreachMappedFaceCente
  {
        CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
        MVert *mv = cddm->mvert;
 -      MFace *mf = cddm->mface;
 -      int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
 +      MPoly *mf = cddm->mpoly;
 +      MLoop *ml = cddm->mloop;
 +      int i, j, orig, *index;
  
 -      for(i = 0; i < dm->numFaceData; i++, mf++) {
 +      index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
 +      mf = cddm->mpoly;
 +      for(i = 0; i < dm->numPolyData; i++, mf++) {
                float cent[3];
                float no[3];
  
                if (index) {
                        orig = *index++;
                        if(orig == ORIGINDEX_NONE) continue;
 -              }
 -              else
 +              } else
                        orig = i;
 +              
 +              ml = &cddm->mloop[mf->loopstart];
 +              cent[0] = cent[1] = cent[2] = 0.0f;
 +              for (j=0; j<mf->totloop; j++, ml++) {
 +                      add_v3_v3v3(cent, cent, mv[ml->v].co);
 +              }
 +              mul_v3_fl(cent, 1.0f / (float)j);
  
 -              VECCOPY(cent, mv[mf->v1].co);
 -              add_v3_v3(cent, mv[mf->v2].co);
 -              add_v3_v3(cent, mv[mf->v3].co);
 -
 -              if (mf->v4) {
 -                      normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
 -                      add_v3_v3(cent, mv[mf->v4].co);
 -                      mul_v3_fl(cent, 0.25f);
 +              ml = &cddm->mloop[mf->loopstart];
 +              if (j > 3) {
 +                      normal_quad_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
 +                                     mv[(ml+2)->v].co, mv[(ml+3)->v].co);
                } else {
 -                      normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
 -                      mul_v3_fl(cent, 0.33333333333f);
 +                      normal_tri_v3(no, mv[ml->v].co, mv[(ml+1)->v].co,
 +                                     mv[(ml+2)->v].co);
                }
  
                func(userData, orig, cent, no);
        }
 +
 +}
 +
 +static void cdDM_recalcTesselation(DerivedMesh *dm)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 +
 +      dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
 +              &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
 +              dm->numPolyData, 1, 0);
 +      
 +      cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
 +}
 +
 +/*ignores original poly origindex layer*/
 +static void cdDM_recalcTesselation2(DerivedMesh *dm)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 +
 +      dm->numFaceData = mesh_recalcTesselation(&dm->faceData, &dm->loopData, 
 +              &dm->polyData, cddm->mvert, dm->numFaceData, dm->numLoopData, 
 +              dm->numPolyData, 0, 0);
 +      
 +      cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
 +}
 +
 +void CDDM_recalc_tesselation(DerivedMesh *dm, int orig_use_polyorig)
 +{
 +      if (orig_use_polyorig)
 +              cdDM_recalcTesselation(dm);
 +      else
 +              cdDM_recalcTesselation2(dm);
  }
  
  static void cdDM_free_internal(CDDerivedMesh *cddm)
@@@ -1541,11 -1469,6 +1541,11 @@@ static void cdDM_release(DerivedMesh *d
        }
  }
  
 +int CDDM_Check(DerivedMesh *dm)
 +{
 +      return dm && dm->getMinMax == cdDM_getMinMax;
 +}
 +
  /**************** CDDM interface functions ****************/
  static CDDerivedMesh *cdDM_create(const char *desc)
  {
        dm->getMinMax = cdDM_getMinMax;
  
        dm->getNumVerts = cdDM_getNumVerts;
 -      dm->getNumFaces = cdDM_getNumFaces;
        dm->getNumEdges = cdDM_getNumEdges;
 +      dm->getNumTessFaces = cdDM_getNumTessFaces;
 +      dm->getNumFaces = cdDM_getNumFaces;
  
        dm->getVert = cdDM_getVert;
        dm->getEdge = cdDM_getEdge;
 -      dm->getFace = cdDM_getFace;
 +      dm->getTessFace = cdDM_getFace;
        dm->copyVertArray = cdDM_copyVertArray;
        dm->copyEdgeArray = cdDM_copyEdgeArray;
 -      dm->copyFaceArray = cdDM_copyFaceArray;
 +      dm->copyTessFaceArray = cdDM_copyFaceArray;
 +      dm->copyLoopArray = cdDM_copyLoopArray;
 +      dm->copyPolyArray = cdDM_copyPolyArray;
        dm->getVertData = DM_get_vert_data;
        dm->getEdgeData = DM_get_edge_data;
 -      dm->getFaceData = DM_get_face_data;
 +      dm->getTessFaceData = DM_get_face_data;
        dm->getVertDataArray = DM_get_vert_data_layer;
        dm->getEdgeDataArray = DM_get_edge_data_layer;
 -      dm->getFaceDataArray = DM_get_face_data_layer;
 +      dm->getTessFaceDataArray = DM_get_tessface_data_layer;
 +      
 +      //doesn't work yet for all cases
 +      //dm->recalcTesselation = cdDM_recalcTesselation;
  
        dm->getVertCos = cdDM_getVertCos;
        dm->getVertCo = cdDM_getVertCo;
        return cddm;
  }
  
 -DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
 +DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys)
  {
        CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
        DerivedMesh *dm = &cddm->dm;
  
 -      DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
 +      DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
  
        CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
        CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
        CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
 +      CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys);
  
        CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
        CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
        CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
 +      CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
 +      CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
  
        cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
        cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
        cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
 +      cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
 +      cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
  
        return dm;
  }
@@@ -1647,8 -1559,7 +1647,8 @@@ DerivedMesh *CDDM_from_mesh(Mesh *mesh
  
        /* this does a referenced copy, with an exception for fluidsim */
  
 -      DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
 +      DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface,
 +                  mesh->totloop, mesh->totpoly);
  
        dm->deformedOnly = 1;
  
                                         mesh->totvert);
        CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
                                         mesh->totedge);
 -      CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
 +      CustomData_merge(&mesh->fdata, &dm->faceData, mask|CD_MASK_ORIGINDEX, alloctype,
                                         mesh->totface);
 +      CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype,
 +                       mesh->totloop);
 +      CustomData_merge(&mesh->pdata, &dm->polyData, mask, alloctype,
 +                       mesh->totpoly);
  
        cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
        cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
 +      cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
 +      cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
        cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
  
 +      if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX))
 +              CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
 +
        return dm;
  }
  
 -DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
 +static DerivedMesh *disabled__CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
  {
        DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
 -                                                         BLI_countlist(&em->edges),
 -                                                         BLI_countlist(&em->faces));
 +                                 BLI_countlist(&em->edges),
 +                                 BLI_countlist(&em->faces), 0, 0);
        CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
        EditVert *eve;
        EditEdge *eed;
                                         CD_CALLOC, dm->numEdgeData); */
        CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
                                         CD_CALLOC, dm->numFaceData);
 +      CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
 +                       CD_CALLOC, dm->numFaceData);
  
        /* set eve->hash to vert index */
        for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
                /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
        }
  
 -      index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
 +      index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
        for(i = 0, efa = em->faces.first; i < dm->numFaceData;
                i++, efa = efa->next, index++) {
                MFace *mf = &mface[i];
@@@ -1787,17 -1687,15 +1787,17 @@@ DerivedMesh *CDDM_from_curve_customDB(O
        MVert *allvert;
        MEdge *alledge;
        MFace *allface;
 -      int totvert, totedge, totface;
 +      MLoop *allloop;
 +      MPoly *allpoly;
 +      int totvert, totedge, totface, totloop, totpoly;
  
        if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
 -              &totedge, &allface, &totface) != 0) {
 +              &totedge, &allface, &allloop, &allpoly, &totface, &totloop, &totpoly) != 0) {
                /* Error initializing mdata. This often happens when curve is empty */
 -              return CDDM_new(0, 0, 0);
 +              return CDDM_new(0, 0, 0, 0, 0);
        }
  
 -      dm = CDDM_new(totvert, totedge, totface);
 +      dm = CDDM_new(totvert, totedge, totface, totloop, totpoly);
        dm->deformedOnly = 1;
  
        cddm = (CDDerivedMesh*)dm;
        memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
        memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
        memcpy(cddm->mface, allface, totface*sizeof(MFace));
 +      memcpy(cddm->mloop, allloop, totloop*sizeof(MLoop));
 +      memcpy(cddm->mpoly, allpoly, totpoly*sizeof(MPoly));
  
        MEM_freeN(allvert);
        MEM_freeN(alledge);
        MEM_freeN(allface);
 +      MEM_freeN(allloop);
 +      MEM_freeN(allpoly);
 +
 +      return dm;
 +}
 +
 +static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata,
 +                                        int cdindex, BMLoop *l3[3],
 +                                        int numCol, int numTex)
 +{
 +      BMLoop *l;
 +      BMFace *f = l3[0]->f;
 +      MTFace *texface;
 +      MTexPoly *texpoly;
 +      MCol *mcol;
 +      MLoopCol *mloopcol;
 +      MLoopUV *mloopuv;
 +      int i, j, hasWCol = CustomData_has_layer(&bm->ldata, CD_WEIGHT_MLOOPCOL);
 +
 +      for(i=0; i < numTex; i++){
 +              texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
 +              texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i);
 +              
 +              texface->tpage = texpoly->tpage;
 +              texface->flag = texpoly->flag;
 +              texface->transp = texpoly->transp;
 +              texface->mode = texpoly->mode;
 +              texface->tile = texpoly->tile;
 +              texface->unwrap = texpoly->unwrap;
 +      
 +              for (j=0; j<3; j++) {
 +                      l = l3[j];
 +                      mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
 +                      texface->uv[j][0] = mloopuv->uv[0];
 +                      texface->uv[j][1] = mloopuv->uv[1];
 +              }
 +      }
 +
 +      for(i=0; i < numCol; i++){
 +              mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
 +              
 +              for (j=0; j<3; j++) {
 +                      l = l3[j];
 +                      mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
 +                      mcol[j].r = mloopcol->r;
 +                      mcol[j].g = mloopcol->g;
 +                      mcol[j].b = mloopcol->b;
 +                      mcol[j].a = mloopcol->a;
 +              }
 +      }
 +
 +      if (hasWCol) {
 +              mcol = CustomData_get(facedata, cdindex, CD_WEIGHT_MCOL);
 +
 +              for (j=0; j<3; j++) {
 +                      l = l3[j];
 +                      mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_WEIGHT_MLOOPCOL);
 +                      mcol[j].r = mloopcol->r;
 +                      mcol[j].g = mloopcol->g;
 +                      mcol[j].b = mloopcol->b;
 +                      mcol[j].a = mloopcol->a;
 +              }
 +      }
 +}
 +
 +DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdisps)
 +{
 +      DerivedMesh *dm = CDDM_new(em->bm->totvert, em->bm->totedge, 
 +                             em->tottri, em->bm->totloop, em->bm->totface);
 +      CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 +      BMesh *bm = em->bm;
 +      BMIter iter, liter;
 +      BMVert *eve;
 +      BMEdge *eed;
 +      BMFace *efa;
 +      MVert *mvert = cddm->mvert;
 +      MEdge *medge = cddm->medge;
 +      MFace *mface = cddm->mface;
 +      MLoop *mloop = cddm->mloop;
 +      MPoly *mpoly = cddm->mpoly;
 +      int numCol = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPCOL);
 +      int numTex = CustomData_number_of_layers(&em->bm->pdata, CD_MTEXPOLY);
 +      int i, j, *index, add_orig;
 +      int has_crease, has_edge_bweight, has_vert_bweight;
 +      int flag;
 +      
 +      has_edge_bweight = CustomData_has_layer(&em->bm->edata, CD_BWEIGHT);
 +      has_vert_bweight = CustomData_has_layer(&em->bm->vdata, CD_BWEIGHT);
 +      has_crease = CustomData_has_layer(&em->bm->edata, CD_CREASE);
 +      
 +      dm->deformedOnly = 1;
 +      
 +      /*don't add origindex layer if one already exists*/
 +      add_orig = !CustomData_has_layer(&em->bm->pdata, CD_ORIGINDEX);
 +
 +      flag = use_mdisps ? CD_MASK_DERIVEDMESH|CD_MASK_MDISPS : CD_MASK_DERIVEDMESH;
 +      
 +      /*don't process shapekeys, we only feed them through the modifier stack as needed,
 +      e.g. for applying modifiers or the like*/
 +      flag &= ~CD_SHAPEKEY;
 +      CustomData_merge(&em->bm->vdata, &dm->vertData, flag,
 +                       CD_CALLOC, dm->numVertData);
 +      CustomData_merge(&em->bm->edata, &dm->edgeData, flag,
 +                       CD_CALLOC, dm->numEdgeData);
 +      CustomData_merge(&em->bm->ldata, &dm->loopData, flag,
 +                       CD_CALLOC, dm->numLoopData);
 +      CustomData_merge(&em->bm->pdata, &dm->polyData, flag,
 +                       CD_CALLOC, dm->numPolyData);
 +      
 +      /*add tesselation mface layers*/
 +      CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri);
 +
 +      /* set vert index */
 +      eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +      for (i=0; eve; eve=BMIter_Step(&iter), i++)
 +              BM_SetIndex(eve, i);
 +
 +      index = dm->getVertDataArray(dm, CD_ORIGINDEX);
 +
 +      eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
 +      for (i=0; eve; eve=BMIter_Step(&iter), i++, index++) {
 +              MVert *mv = &mvert[i];
 +
 +              VECCOPY(mv->co, eve->co);
 +
 +              BM_SetIndex(eve, i);
 +
 +              mv->no[0] = eve->no[0] * 32767.0;
 +              mv->no[1] = eve->no[1] * 32767.0;
 +              mv->no[2] = eve->no[2] * 32767.0;
 +
 +              mv->flag = BMFlags_To_MEFlags(eve);
 +
 +              if (has_vert_bweight)
 +                      mv->bweight = (unsigned char)(BM_GetCDf(&bm->vdata, eve, CD_BWEIGHT)*255.0f);
 +
 +              if (add_orig) *index = i;
 +
 +              CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i);
 +      }
 +
 +      index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
 +      eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
 +      for (i=0; eed; eed=BMIter_Step(&iter), i++, index++) {
 +              MEdge *med = &medge[i];
 +
 +              BM_SetIndex(eed, i);
 +
 +              med->v1 = BM_GetIndex(eed->v1);
 +              med->v2 = BM_GetIndex(eed->v2);
 +              med->flag = ME_EDGEDRAW|ME_EDGERENDER;
 +
 +              if (has_crease)
 +                      med->crease = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_CREASE)*255.0f);
 +              if (has_edge_bweight)
 +                      med->bweight = (unsigned char)(BM_GetCDf(&bm->edata, eed, CD_BWEIGHT)*255.0f);
 +              
 +              med->flag = BMFlags_To_MEFlags(eed);
 +
 +              CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i);
 +              if (add_orig) *index = i;
 +      }
 +
 +      efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
 +      for (i=0; efa; i++, efa=BMIter_Step(&iter)) {
 +              BM_SetIndex(efa, i);
 +      }
 +
 +      index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
 +      for(i = 0; i < dm->numFaceData; i++, index++) {
 +              MFace *mf = &mface[i];
 +              BMLoop **l = em->looptris[i];
 +              efa = l[0]->f;
 +
 +              mf->v1 = BM_GetIndex(l[0]->v);
 +              mf->v2 = BM_GetIndex(l[1]->v);
 +              mf->v3 = BM_GetIndex(l[2]->v);
 +              mf->v4 = 0;
 +              mf->mat_nr = efa->mat_nr;
 +              mf->flag = BMFlags_To_MEFlags(efa);
 +              
 +              *index = add_orig ? BM_GetIndex(efa) : *(int*)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX);
 +
 +              loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
 +              test_index_face(mf, &dm->faceData, i, 3);
 +      }
 +      
 +      index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
 +      j = 0;
 +      efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
 +      for (i=0; efa; i++, efa=BMIter_Step(&iter), index++) {
 +              BMLoop *l;
 +              MPoly *mp = &mpoly[i];
 +
 +              mp->totloop = efa->len;
 +              mp->flag = BMFlags_To_MEFlags(efa);
 +              mp->loopstart = j;
 +              mp->mat_nr = efa->mat_nr;
 +              
 +              BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
 +                      mloop->v = BM_GetIndex(l->v);
 +                      mloop->e = BM_GetIndex(l->e);
 +                      CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l->head.data, j);
 +
 +                      j++;
 +                      mloop++;
 +              }
 +
 +              CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i);
 +
 +              if (add_orig) *index = i;
 +      }
  
        return dm;
  }
  
 -DerivedMesh *CDDM_copy(DerivedMesh *source)
 +DerivedMesh *CDDM_copy(DerivedMesh *source, int faces_from_tessfaces)
  {
        CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
        DerivedMesh *dm = &cddm->dm;
        int numVerts = source->numVertData;
        int numEdges = source->numEdgeData;
        int numFaces = source->numFaceData;
 +      int numLoops = source->numLoopData;
 +      int numPolys = source->numPolyData;
  
        /* ensure these are created if they are made on demand */
        source->getVertDataArray(source, CD_ORIGINDEX);
        source->getEdgeDataArray(source, CD_ORIGINDEX);
 -      source->getFaceDataArray(source, CD_ORIGINDEX);
 +      source->getTessFaceDataArray(source, CD_ORIGINDEX);
  
        /* this initializes dm, and copies all non mvert/medge/mface layers */
 -      DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
 +      DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces,
 +              numLoops, numPolys);
        dm->deformedOnly = source->deformedOnly;
  
        CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
        /* now add mvert/medge/mface layers */
        cddm->mvert = source->dupVertArray(source);
        cddm->medge = source->dupEdgeArray(source);
 -      cddm->mface = source->dupFaceArray(source);
 +      cddm->mface = source->dupTessFaceArray(source);
  
        CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
        CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
        CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
 +      
 +      if (!faces_from_tessfaces)
 +              DM_DupPolys(source, dm);
 +      else
 +              CDDM_tessfaces_to_faces(dm);
  
 +      cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
 +      cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
 +      
 +      cdDM_recalcTesselation((DerivedMesh *)cddm);
 +      
        return dm;
  }
  
  /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
   * relationship betwen mesh data this needs to be set by the caller. */
  DerivedMesh *CDDM_from_template(DerivedMesh *source,
 -                                                              int numVerts, int numEdges, int numFaces)
 +                                int numVerts, int numEdges, int numFaces,
 +                                                              int numLoops, int numPolys)
  {
        CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
        DerivedMesh *dm = &cddm->dm;
        /* ensure these are created if they are made on demand */
        source->getVertDataArray(source, CD_ORIGINDEX);
        source->getEdgeDataArray(source, CD_ORIGINDEX);
 -      source->getFaceDataArray(source, CD_ORIGINDEX);
 +      source->getTessFaceDataArray(source, CD_ORIGINDEX);
  
        /* this does a copy of all non mvert/medge/mface layers */
 -      DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
 +      DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces, numLoops, numPolys);
  
        /* now add mvert/medge/mface layers */
        CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
        CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
        CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
 +      CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
 +      CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
  
        if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
                CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
        cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
        cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
        cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
 +      cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
 +      cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
  
        return dm;
  }
@@@ -2144,228 -1810,22 +2144,228 @@@ void CDDM_apply_vert_normals(DerivedMes
  void CDDM_calc_normals(DerivedMesh *dm)
  {
        CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 -      float (*face_nors)[3];
 -
 +      float (*face_nors)[3] = NULL;
 +      
        if(dm->numVertData == 0) return;
  
        /* we don't want to overwrite any referenced layers */
        cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
 +      
 +      /*set tesselation origindex values to map to poly indices, rather then poly
 +        poly origindex values*/
 +      cdDM_recalcTesselation2(dm);
 +      
 +      face_nors = MEM_mallocN(sizeof(float)*3*dm->numFaceData, "face_nors");
 +      
 +      /* calculate face normals */
 +      mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), 
 +                                        dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numFaceData, 
 +                                        CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors);
 +      
 +      /*restore tesselation origindex indices to poly origindex indices*/
 +      cdDM_recalcTesselation(dm);
  
 -      /* make a face normal layer if not present */
 -      face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
 -      if(!face_nors)
 -              face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
 -                                                                               NULL, dm->numFaceData);
 +      CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, 
 +              face_nors, dm->numFaceData);
 +}
  
 -      /* calculate face normals */
 -      mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors);
 +#if 1
 +/*merge verts
 + 
 +  vtargetmap is a table that maps vertices to target vertices.  a value of -1
 +  indicates a vertex is a target, and is to be kept.
 +  
 +  this frees dm, and returns a new one.
 +  
 +  this is a really horribly written function.  ger. - joeedh
 +
 + */
 +DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, int *vtargetmap)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 +      CDDerivedMesh *cddm2 = NULL;
 +      MVert *mv, *mvert = NULL;
 +      BLI_array_declare(mvert);
 +      MEdge *me, *medge = NULL;
 +      BLI_array_declare(medge);
 +      MPoly *mp, *mpoly = NULL;
 +      BLI_array_declare(mpoly);
 +      MLoop *ml, *mloop = NULL;
 +      BLI_array_declare(mloop);
 +      EdgeHash *ehash = BLI_edgehash_new();
 +      int *newv = NULL, *newe = NULL, *newl = NULL;
 +      int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL;
 +      BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp);
 +      int i, j, c, totloop, totpoly;
 +      
 +      totloop = dm->numLoopData;
 +      totpoly = dm->numPolyData;
 +      
 +      newv = MEM_callocN(sizeof(int)*dm->numVertData, "newv vtable CDDM_merge_verts");
 +      newe = MEM_callocN(sizeof(int)*dm->numEdgeData, "newv etable CDDM_merge_verts");
 +      newl = MEM_callocN(sizeof(int)*totloop, "newv ltable CDDM_merge_verts");
 +      
 +      /*fill newl with destination vertex indices*/
 +      mv = cddm->mvert;
 +      c = 0;
 +      for (i=0; i<dm->numVertData; i++, mv++) {
 +              if (vtargetmap[i] == -1) {
 +                      BLI_array_append(oldv, i);
 +                      newv[i] = c++;
 +                      BLI_array_append(mvert, *mv);
 +              }
 +      }
 +      
 +      /*now link target vertices to destination indices*/
 +      for (i=0; i<dm->numVertData; i++) {
 +              if (vtargetmap[i] != -1) {
 +                      newv[i] = newv[vtargetmap[i]];
 +              }
 +      }
 +      
 +      /*find-replace merged vertices with target vertices*/   
 +      ml = cddm->mloop;
 +      c = 0;
 +      for (i=0; i<totloop; i++, ml++) {
 +              if (ml->v == -1)
 +                      continue;
 +              
 +              if (vtargetmap[ml->v] != -1)
 +                      ml->v = vtargetmap[ml->v];
 +      }
 +      
 +      /*now go through and fix edges and faces*/
 +      me = cddm->medge;
 +      c = 0;
 +      for (i=0; i<dm->numEdgeData; i++, me++) {
 +              int v1, v2;
 +              
 +              if (me->v1 == me->v2) {
 +                      newe[i] = -1;
 +                      continue;
 +              }
 +              
 +              if (vtargetmap[me->v1] != -1)
 +                      v1 = vtargetmap[me->v1];
 +              else
 +                      v1 = me->v1;
 +              
 +              if (vtargetmap[me->v2] != -1)
 +                      v2 = vtargetmap[me->v2];
 +              else
 +                      v2 = me->v2;
 +              
 +              if (BLI_edgehash_haskey(ehash, v1, v2)) {
 +                      newe[i] = GET_INT_FROM_POINTER(BLI_edgehash_lookup(ehash, v1, v2));
 +              } else {
 +                      BLI_array_append(olde, i);
 +                      newe[i] = c;
 +                      BLI_array_append(medge, *me);
 +                      BLI_edgehash_insert(ehash, v1, v2, SET_INT_IN_POINTER(c));
 +                      c++;
 +              }
 +      }
 +      
 +      mp = cddm->mpoly;
 +      for (i=0; i<totpoly; i++, mp++) {
 +              MPoly *mp2;
 +              
 +              ml = cddm->mloop + mp->loopstart;
 +              
 +              c = 0;
 +              for (j=0; j<mp->totloop; j++, ml++) {
 +                      if (ml->v == -1)
 +                              continue;
 +                      
 +                      me = cddm->medge + ml->e;
 +                      if (me->v1 != me->v2) {
 +                              BLI_array_append(oldl, j+mp->loopstart);
 +                              BLI_array_append(mloop, *ml);
 +                              newl[j+mp->loopstart] = BLI_array_count(mloop)-1;
 +                              c++;
 +                      }
 +              }
 +              
 +              if (!c)
 +                      continue;
 +              
 +              mp2 = BLI_array_append(mpoly, *mp);
 +              mp2->totloop = c;
 +              mp2->loopstart = BLI_array_count(mloop) - c;
 +              
 +              BLI_array_append(oldp, i);
 +      }
 +      
 +      /*create new cddm*/     
 +      cddm2 = (CDDerivedMesh*) CDDM_from_template((DerivedMesh*)cddm, BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly));
 +      
 +      /*update edge indices and copy customdata*/
 +      me = medge;
 +      for (i=0; i<cddm2->dm.numEdgeData; i++, me++) {
 +              if (newv[me->v1] != -1)
 +                      me->v1 = newv[me->v1];
 +              if (newv[me->v2] != -1)
 +                      me->v2 = newv[me->v2];
 +              
 +              CustomData_copy_data(&dm->edgeData, &cddm2->dm.edgeData, olde[i], i, 1);
 +      }
 +      
 +      /*update loop indices and copy customdata*/
 +      ml = mloop;
 +      for (i=0; i<cddm2->dm.numLoopData; i++, ml++) {
 +              if (newe[ml->e] != -1)
 +                      ml->e = newe[ml->e];
 +              if (newv[ml->v] != -1)
 +                      ml->v = newv[ml->v];
 +                      
 +              CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1);
 +      }
 +      
 +      /*copy vertex customdata*/      
 +      mv = mvert;
 +      for (i=0; i<cddm2->dm.numVertData; i++, mv++) {
 +              CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1);
 +      }
 +      
 +      /*copy poly customdata*/
 +      mp = mpoly;
 +      for (i=0; i<cddm2->dm.numPolyData; i++, mp++) {
 +              CustomData_copy_data(&dm->polyData, &cddm2->dm.polyData, oldp[i], i, 1);
 +      }
 +      
 +      /*copy over data.  CustomData_add_layer can do this, need to look it up.*/
 +      memcpy(cddm2->mvert, mvert, sizeof(MVert)*BLI_array_count(mvert));
 +      memcpy(cddm2->medge, medge, sizeof(MEdge)*BLI_array_count(medge));
 +      memcpy(cddm2->mloop, mloop, sizeof(MLoop)*BLI_array_count(mloop));
 +      memcpy(cddm2->mpoly, mpoly, sizeof(MPoly)*BLI_array_count(mpoly));
 +      BLI_array_free(mvert); BLI_array_free(medge); BLI_array_free(mloop); BLI_array_free(mpoly);
 +
 +      CDDM_recalc_tesselation((DerivedMesh*)cddm2, 1);
 +      
 +      if (newv) 
 +              MEM_freeN(newv); 
 +      if (newe)
 +              MEM_freeN(newe); 
 +      if (newl)
 +              MEM_freeN(newl);
 +      if (oldv) 
 +              MEM_freeN(oldv); 
 +      if (olde) 
 +              MEM_freeN(olde); 
 +      if (oldl) 
 +              MEM_freeN(oldl); 
 +      if (oldp) 
 +              MEM_freeN(oldp);
 +      if (ehash)
 +              BLI_edgehash_free(ehash, NULL);
 +
 +      /*free old derivedmesh*/
 +      dm->needsFree = 1;
 +      dm->release(dm);
 +      
 +      return (DerivedMesh*)cddm2;
  }
 +#endif
  
  void CDDM_calc_edges(DerivedMesh *dm)
  {
        BLI_edgehash_free(eh, NULL);
  }
  
 +
 +void CDDM_calc_edges_poly(DerivedMesh *dm)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 +      CustomData edgeData;
 +      EdgeHashIterator *ehi;
 +      MPoly *mp = cddm->mpoly;
 +      MLoop *ml;
 +      MEdge *med;
 +      EdgeHash *eh = BLI_edgehash_new();
 +      int v1, v2;
 +      int *eindex;
 +      int i, j, k, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData;
 +
 +      eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
 +
 +      med = cddm->medge;
 +      if (med) {
 +              for (i=0; i < numEdges; i++, med++) {
 +                      BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i+1));
 +              }
 +      }
 +
 +      for (i=0; i < maxFaces; i++, mp++) {
 +              ml = cddm->mloop + mp->loopstart;
 +              for (j=0; j<mp->totloop; j++, ml++) {
 +                      v1 = ml->v;
 +                      v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
 +                      if (!BLI_edgehash_haskey(eh, v1, v2)) {
 +                              BLI_edgehash_insert(eh, v1, v2, NULL);
 +                      }
 +              }
 +      }
 +
 +      k = numEdges;
 +      numEdges = BLI_edgehash_size(eh);
 +
 +      /* write new edges into a temporary CustomData */
 +      memset(&edgeData, 0, sizeof(edgeData));
 +      CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
 +      CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
 +
 +      ehi = BLI_edgehashIterator_new(eh);
 +      med = CustomData_get_layer(&edgeData, CD_MEDGE);
 +      index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
 +      for(i = 0; !BLI_edgehashIterator_isDone(ehi);
 +          BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
 +              BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
 +              j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
 +
 +              med->flag = ME_EDGEDRAW|ME_EDGERENDER;
 +              *index = j==0 ? ORIGINDEX_NONE : eindex[j-1];
 +
 +              BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i));
 +      }
 +      BLI_edgehashIterator_free(ehi);
 +
 +      /* free old CustomData and assign new one */
 +      CustomData_free(&dm->edgeData, dm->numEdgeData);
 +      dm->edgeData = edgeData;
 +      dm->numEdgeData = numEdges;
 +
 +      cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
 +
 +      mp = cddm->mpoly;
 +      for (i=0; i < maxFaces; i++, mp++) {
 +              ml = cddm->mloop + mp->loopstart;
 +              for (j=0; j<mp->totloop; j++, ml++) {
 +                      v1 = ml->v;
 +                      v2 = (cddm->mloop + mp->loopstart + ((j+1)%mp->totloop))->v;
 +                      ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, v1, v2));
 +              }
 +      }
 +
 +      BLI_edgehash_free(eh, NULL);
 +}
 +
  void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
  {
        if (numVerts < dm->numVertData)
@@@ -2534,7 -1917,7 +2534,7 @@@ MEdge *CDDM_get_edge(DerivedMesh *dm, i
        return &((CDDerivedMesh*)dm)->medge[index];
  }
  
 -MFace *CDDM_get_face(DerivedMesh *dm, int index)
 +MFace *CDDM_get_tessface(DerivedMesh *dm, int index)
  {
        return &((CDDerivedMesh*)dm)->mface[index];
  }
@@@ -2549,125 -1932,8 +2549,125 @@@ MEdge *CDDM_get_edges(DerivedMesh *dm
        return ((CDDerivedMesh*)dm)->medge;
  }
  
 -MFace *CDDM_get_faces(DerivedMesh *dm)
 +MFace *CDDM_get_tessfaces(DerivedMesh *dm)
  {
        return ((CDDerivedMesh*)dm)->mface;
  }
  
 +MLoop *CDDM_get_loops(DerivedMesh *dm)
 +{
 +      return ((CDDerivedMesh*)dm)->mloop;
 +}
 +
 +MPoly *CDDM_get_polys(DerivedMesh *dm)
 +{
 +      return ((CDDerivedMesh*)dm)->mpoly;
 +}
 +
 +void CDDM_tessfaces_to_faces(DerivedMesh *dm)
 +{
 +      /*converts mfaces to mpolys/mloops*/
 +      CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 +      MFace *mf;
 +      MEdge *me;
 +      MLoop *ml;
 +      MPoly *mp;
 +      EdgeHash *eh = BLI_edgehash_new();
 +      int i, l, totloop, *index1, *index2;
 +      
 +      /*ensure we have all the edges we need*/
 +      CDDM_calc_edges(dm);
 +
 +      /*build edge hash*/
 +      me = cddm->medge;
 +      for (i=0; i<cddm->dm.numEdgeData; i++, me++) {
 +              BLI_edgehash_insert(eh, me->v1, me->v2, SET_INT_IN_POINTER(i));
 +      }
 +
 +      mf = cddm->mface;
 +      totloop = 0;
 +      for (i=0; i<cddm->dm.numFaceData; i++, mf++) {
 +              totloop += mf->v4 ? 4 : 3;
 +      }
 +
 +      CustomData_free(&cddm->dm.polyData, cddm->dm.numPolyData);
 +      CustomData_free(&cddm->dm.loopData, cddm->dm.numLoopData);
 +      
 +      cddm->dm.numLoopData = totloop;
 +      cddm->dm.numPolyData = cddm->dm.numFaceData;
 +
 +      if (!totloop) return;
 +
 +      cddm->mloop = MEM_callocN(sizeof(MLoop)*totloop, "cddm->mloop in CDDM_tessfaces_to_faces");
 +      cddm->mpoly = MEM_callocN(sizeof(MPoly)*cddm->dm.numFaceData, "cddm->mpoly in CDDM_tessfaces_to_faces");
 +      
 +      CustomData_add_layer(&cddm->dm.loopData, CD_MLOOP, CD_ASSIGN, cddm->mloop, totloop);
 +      CustomData_add_layer(&cddm->dm.polyData, CD_MPOLY, CD_ASSIGN, cddm->mpoly, cddm->dm.numPolyData);
 +      CustomData_merge(&cddm->dm.faceData, &cddm->dm.polyData, 
 +              CD_MASK_ORIGINDEX, CD_DUPLICATE, cddm->dm.numFaceData);
 +
 +      index1 = CustomData_get_layer(&cddm->dm.faceData, CD_ORIGINDEX);
 +      index2 = CustomData_get_layer(&cddm->dm.polyData, CD_ORIGINDEX);
 +
 +      mf = cddm->mface;
 +      mp = cddm->mpoly;
 +      ml = cddm->mloop;
 +      l = 0;
 +      for (i=0; i<cddm->dm.numFaceData; i++, mf++, mp++) {
 +              mp->flag = mf->flag;
 +              mp->loopstart = l;
 +              mp->mat_nr = mf->mat_nr;
 +              mp->totloop = mf->v4 ? 4 : 3;
 +              
 +              ml->v = mf->v1;
 +              ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v1, mf->v2));
 +              ml++, l++;
 +
 +              ml->v = mf->v2;
 +              ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v2, mf->v3));
 +              ml++, l++;
 +
 +              ml->v = mf->v3;
 +              ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v3, mf->v4?mf->v4:mf->v1));
 +              ml++, l++;
 +
 +              if (mf->v4) {
 +                      ml->v = mf->v4;
 +                      ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(eh, mf->v4, mf->v1));
 +                      ml++, l++;
 +              }
 +
 +      }
 +
 +      BLI_edgehash_free(eh, NULL);
 +}
 +
 +void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 +      
 +      if (!CustomData_has_layer(&dm->vertData, CD_MVERT))
 +              CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData);
 +                              
 +      cddm->mvert = mvert;
 +}
 +
 +void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 +
 +      if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE))
 +              CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, medge, dm->numEdgeData);
 +
 +      cddm->medge = medge;
 +}
 +
 +void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
 +{
 +      CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
 +
 +      if (!CustomData_has_layer(&dm->faceData, CD_MFACE))
 +              CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, mface, dm->numFaceData);
 +
 +      cddm->mface = mface;
 +}
index c1682b0976d6fb4d2199d45bce0dbb994ea57e77,225ada0e6240cee38b1372d14a19f52f3b16d0b1..5d2dee69e2673175712af58a6e4968a5a2e8ac50
  #include "DNA_object_types.h"
  #include "DNA_scene_types.h"
  
 +#include "BLI_utildefines.h"
  #include "BLI_blenlib.h"
  #include "BLI_edgehash.h"
  #include "BLI_math.h"
  #include "BLI_memarena.h"
  #include "BLI_pbvh.h"
 -#include "BLI_utildefines.h"
  
  #include "BKE_cdderivedmesh.h"
  #include "BKE_global.h"
  #include "BKE_paint.h"
  #include "BKE_scene.h"
  #include "BKE_subsurf.h"
 +#include "BKE_tessmesh.h"
 +
 +#include "PIL_time.h"
 +#include "BLI_array.h"
  
  #include "GL/glew.h"
  
  
  extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
  
 -static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v);
 -static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e);
 -static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f);
 +static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
 +                                         int drawInteriorEdges,
 +                                         int useSubsurfUv,
 +                                         DerivedMesh *dm);
  static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
  
  ///
@@@ -166,8 -161,7 +166,8 @@@ static int getEdgeIndex(CCGSubSurf *ss
                return edgeBase + x-1;
        }
  }
 -static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
 +
 +BM_INLINE int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
        int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f));
        int numVerts = ccgSubSurf_getFaceNumVerts(f);
  
@@@ -222,16 -216,10 +222,16 @@@ static void get_face_uv_map_vert(UvVert
  }
  
  static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MTFace *tface) {
 -      MFace *mface = dm->getFaceArray(dm);
 +#if 1 /*BMESH_TODO*/
 +      (void)ss;
 +      (void)origss;
 +      (void)dm;
 +      (void)tface;
 +#else
 +      MFace *mface = dm->getTessFaceArray(dm);
        MVert *mvert = dm->getVertArray(dm);
        int totvert = dm->getNumVerts(dm);
 -      int totface = dm->getNumFaces(dm);
 +      int totface = dm->getNumTessFaces(dm);
        int i, j, seam;
        UvMapVert *v;
        UvVertMap *vmap;
        free_uv_vert_map(vmap);
        ccgSubSurf_processSync(ss);
  
 +#endif
        return 1;
  }
  
@@@ -395,123 -382,65 +395,123 @@@ static void set_subsurf_uv(CCGSubSurf *
  }
  
  /* face weighting */
 -static void calc_ss_weights(int gridFaces,
 -                                                      FaceVertWeight **qweight, FaceVertWeight **tweight)
 +typedef struct FaceVertWeightEntry {
 +      FaceVertWeight *weight;
 +      float *w;
 +      int valid;
 +} FaceVertWeightEntry;
 +
 +typedef struct WeightTable {
 +      FaceVertWeightEntry *weight_table;
 +      int len;
 +} WeightTable;
 +
 +static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen)
  {
 -      FaceVertWeight *qw, *tw;
 -      int x, y, j;
 -      int numWeights = gridFaces * gridFaces;
 -
 -      *tweight = MEM_mallocN(sizeof(**tweight) * numWeights, "ssTriWeight");
 -      *qweight = MEM_mallocN(sizeof(**qweight) * numWeights, "ssQuadWeight");
 -
 -      qw = *qweight;
 -      tw = *tweight;
 -
 -      for (y = 0; y < gridFaces; y++) {
 -              for (x = 0; x < gridFaces; x++) {
 -                      for (j = 0; j < 4; j++) {
 -                              int fx = x + (j == 2 || j == 3);
 -                              int fy = y + (j == 1 || j == 2);
 -                              float x_v = (float) fx / gridFaces;
 -                              float y_v = (float) fy / gridFaces;
 -                              float tx_v = (1.0f - x_v), ty_v = (1.0f - y_v);
 -                              float center = (1.0f / 3.0f) * tx_v * ty_v;
 -
 -                              (*tw)[j][0] = center + 0.5f * tx_v * y_v;
 -                              (*tw)[j][2] = center + 0.5f * x_v * ty_v;
 -                              (*tw)[j][1] = 1.0f - (*tw)[j][0] - (*tw)[j][2];
 -                              (*tw)[j][3] = 0.0f;
 -
 -                              tx_v *= 0.5f;
 -                              ty_v *= 0.5f;
 -
 -                              (*qw)[j][3] = tx_v * ty_v;
 -                              (*qw)[j][0] = (*qw)[j][3] + tx_v * y_v;
 -                              (*qw)[j][2] = (*qw)[j][3] + x_v * ty_v;
 -                              (*qw)[j][1] = 1.0f - (*qw)[j][0] - (*qw)[j][2] - (*qw)[j][3];
 +      int x, y, i, j;
 +      float *w, w1, w2, w4, fac, fac2, fx, fy;
 +
 +      if (wtable->len <= faceLen) {
 +              void *tmp = MEM_callocN(sizeof(FaceVertWeightEntry)*(faceLen+1), "weight table alloc 2");
 +              
 +              if (wtable->len) {
 +                      memcpy(tmp, wtable->weight_table, sizeof(FaceVertWeightEntry)*wtable->len);
 +                      MEM_freeN(wtable->weight_table);
 +              }
 +              
 +              wtable->weight_table = tmp;
 +              wtable->len = faceLen+1;
 +      }
  
 +      if (!wtable->weight_table[faceLen].valid) {
 +              wtable->weight_table[faceLen].valid = 1;
 +              wtable->weight_table[faceLen].w = w = MEM_callocN(sizeof(float)*faceLen*faceLen*(gridCuts+2)*(gridCuts+2), "weight table alloc");
 +              fac = 1.0f / (float)faceLen;
 +
 +              for (i=0; i<faceLen; i++) {
 +                      for (x=0; x<gridCuts+2; x++) {
 +                              for (y=0; y<gridCuts+2; y++) {
 +                                      fx = 0.5f - (float)x / (float)(gridCuts+1) / 2.0f;
 +                                      fy = 0.5f - (float)y / (float)(gridCuts+1) / 2.0f;
 +                              
 +                                      fac2 = faceLen - 4;
 +                                      w1 = (1.0f - fx) * (1.0f - fy) + (-fac2*fx*fy*fac);
 +                                      w2 = (1.0f - fx + fac2*fx*-fac) * (fy);
 +                                      w4 = (fx) * (1.0f - fy + -fac2*fy*fac);
 +                                      
 +                                      fac2 = 1.0f - (w1+w2+w4);
 +                                      fac2 = fac2 / (float)(faceLen-3);
 +                                      for (j=0; j<faceLen; j++)
 +                                              w[j] = fac2;
 +                                      
 +                                      w[i] = w1;
 +                                      w[(i-1+faceLen)%faceLen] = w2;
 +                                      w[(i+1)%faceLen] = w4;
 +
 +                                      w += faceLen;
 +                              }
                        }
 -                      tw++;
 -                      qw++;
                }
        }
 +
 +      return wtable->weight_table[faceLen].w;
 +}
 +
 +static void free_ss_weights(WeightTable *wtable)
 +{
 +      int i;
 +
 +      for (i=0; i<wtable->len; i++) {
 +              if (wtable->weight_table[i].valid)
 +                      MEM_freeN(wtable->weight_table[i].w);
 +      }
 +      
 +      if (wtable->weight_table)
 +              MEM_freeN(wtable->weight_table);
 +}
 +
 +#if 0
 +static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
 +                                                               int drawInteriorEdges, int useSubsurfUv,
 +                                                               DerivedMesh *dm, struct MultiresSubsurf *ms)
 +{
 +      DerivedMesh *cgdm, *result;
 +      double curt = PIL_check_seconds_timer();
 +
 +      cgdm = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
 +      result = CDDM_copy(cgdm, 1);
 +
 +      printf("subsurf conversion time: %.6lf\n", PIL_check_seconds_timer() - curt);
 +
 +      cgdm->needsFree = 1;
 +      cgdm->release(cgdm);
 +
 +      CDDM_calc_normals(result);
 +
 +      return result;
  }
 +#endif
  
 -static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
 +static int ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
                                                                         float (*vertexCos)[3], int useFlatSubdiv)
  {
        float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
 -      CCGVertHDL fVerts[4];
 -      int totvert = dm->getNumVerts(dm);
 -      int totedge = dm->getNumEdges(dm);
 -      int totface = dm->getNumFaces(dm);
 -      int i;
 -      int *index;
 +      CCGVertHDL *fVerts = NULL;
 +      BLI_array_declare(fVerts);
        MVert *mvert = dm->getVertArray(dm);
        MEdge *medge = dm->getEdgeArray(dm);
 -      MFace *mface = dm->getFaceArray(dm);
 +      /* MFace *mface = dm->getTessFaceArray(dm); */ /* UNUSED */
        MVert *mv;
        MEdge *me;
 -      MFace *mf;
 +      MLoop *mloop = dm->getLoopArray(dm), *ml;
 +      MPoly *mpoly = dm->getPolyArray(dm), *mp;
 +      /*MFace *mf;*/ /*UNUSED*/
 +      int totvert = dm->getNumVerts(dm);
 +      int totedge = dm->getNumEdges(dm);
 +      /*int totface = dm->getNumTessFaces(dm);*/ /*UNUSED*/
 +      /*int totpoly = dm->getNumFaces(dm);*/ /*UNUSED*/
 +      int i, j;
 +      int *index;
  
        ccgSubSurf_initFullSync(ss);
  
                ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index)? *index++: i;
        }
  
 -      mf = mface;
 -      index = (int *)dm->getFaceDataArray(dm, CD_ORIGINDEX);
 -      for (i = 0; i < totface; i++, mf++) {
 -              CCGFace *f;
 +      mp = mpoly;
 +      index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
 +      for (i=0; i<dm->numPolyData; i++, mp++) {
 +              CCGFace *f=NULL;
 +
 +              BLI_array_empty(fVerts);
  
 -              fVerts[0] = SET_INT_IN_POINTER(mf->v1);
 -              fVerts[1] = SET_INT_IN_POINTER(mf->v2);
 -              fVerts[2] = SET_INT_IN_POINTER(mf->v3);
 -              fVerts[3] = SET_INT_IN_POINTER(mf->v4);
 +              ml = mloop + mp->loopstart;
 +              for (j=0; j<mp->totloop; j++, ml++) {
 +                      BLI_array_append(fVerts, SET_INT_IN_POINTER(ml->v));
 +              }
  
 -              // this is very bad, means mesh is internally consistent.
 -              // it is not really possible to continue without modifying
 -              // other parts of code significantly to handle missing faces.
 -              // since this really shouldn't even be possible we just bail.
 -              if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fVerts[3] ? 4 : 3,
 +              /* this is very bad, means mesh is internally inconsistent.
 +               * it is not really possible to continue without modifying
 +               * other parts of code significantly to handle missing faces.
 +               * since this really shouldn't even be possible we just bail.*/
 +              if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), mp->totloop,
                                                           fVerts, &f) == eCCGError_InvalidValue) {
                        static int hasGivenError = 0;
  
                        if(!hasGivenError) {
 -                              //XXX error("Unrecoverable error in SubSurf calculation,"
 -                              //      " mesh is inconsistent.");
 +                              printf("Unrecoverable error in SubSurf calculation,"
 +                                         " mesh is inconsistent.\n");
  
                                hasGivenError = 1;
                        }
  
 -                      return;
 +                      return 0;
                }
  
 -              ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = (index)? *index++: i;
 +              ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = index ? *index++: i;
        }
  
        ccgSubSurf_processSync(ss);
 +
 +      BLI_array_free(fVerts);
 +      return 1;
  }
  
  /***/
@@@ -597,9 -521,9 +597,9 @@@ static int ccgDM_getFaceMapIndex(CCGSub
        return ((int*) ccgSubSurf_getFaceUserData(ss, f))[1];
  }
  
 -static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss);
        CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
        ccgEdgeIterator_free(ei);
        ccgVertIterator_free(vi);
  }
 -static int ccgDM_getNumVerts(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 +static int cgdm_getNumVerts(DerivedMesh *dm) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
  
 -      return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
 +      return ccgSubSurf_getNumFinalVerts(cgdm->ss);
  }
 -static int ccgDM_getNumEdges(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 +static int cgdm_getNumEdges(DerivedMesh *dm) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
  
 -      return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
 +      return ccgSubSurf_getNumFinalEdges(cgdm->ss);
  }
 -static int ccgDM_getNumFaces(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 +static int cgdm_getNumTessFaces(DerivedMesh *dm) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
  
 -      return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
 +      return ccgSubSurf_getNumFinalFaces(cgdm->ss);
  }
  
  static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        DMGridData *vd;
        int i;
  
        memset(mv, 0, sizeof(*mv));
  
 -      if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
 +      if((vertNum < cgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
                /* this vert comes from face data */
                int lastface = ccgSubSurf_getNumFaces(ss) - 1;
                CCGFace *f;
                int gridInternalEnd;
  
                i = 0;
 -              while(i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert)
 +              while(i < lastface && vertNum >= cgdm->faceMap[i + 1].startVert)
                        ++i;
  
 -              f = ccgdm->faceMap[i].face;
 +              f = cgdm->faceMap[i].face;
                numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                gridSideVerts = gridSize - 2;
                gridSideEnd = 1 + numVerts * gridSideVerts;
                gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
  
 -              offset = vertNum - ccgdm->faceMap[i].startVert;
 +              offset = vertNum - cgdm->faceMap[i].startVert;
                if(offset < 1) {
                        vd = ccgSubSurf_getFaceCenterData(f);
                        copy_v3_v3(mv->co, vd->co);
                        copy_v3_v3(mv->co, vd->co);
                        normal_float_to_short_v3(mv->no, vd->no);
                }
 -      } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
 +      } else if((vertNum < cgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
                /* this vert comes from edge data */
                CCGEdge *e;
                int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
                int x;
  
                i = 0;
 -              while(i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert)
 +              while(i < lastedge && vertNum >= cgdm->edgeMap[i + 1].startVert)
                        ++i;
  
 -              e = ccgdm->edgeMap[i].edge;
 +              e = cgdm->edgeMap[i].edge;
  
 -              x = vertNum - ccgdm->edgeMap[i].startVert + 1;
 +              x = vertNum - cgdm->edgeMap[i].startVert + 1;
                vd = ccgSubSurf_getEdgeData(ss, e, x);
                copy_v3_v3(mv->co, vd->co);
                normal_float_to_short_v3(mv->no, vd->no);
        } else {
                /* this vert comes from vert data */
                CCGVert *v;
 -              i = vertNum - ccgdm->vertMap[0].startVert;
 +              i = vertNum - cgdm->vertMap[0].startVert;
  
 -              v = ccgdm->vertMap[i].vert;
 +              v = cgdm->vertMap[i].vert;
                vd = ccgSubSurf_getVertData(ss, v);
                copy_v3_v3(mv->co, vd->co);
                normal_float_to_short_v3(mv->no, vd->no);
@@@ -759,13 -683,13 +759,13 @@@ static void ccgDM_getFinalVertNo(Derive
  
  static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int i;
  
        memset(med, 0, sizeof(*med));
  
 -      if(edgeNum < ccgdm->edgeMap[0].startEdge) {
 +      if(edgeNum < cgdm->edgeMap[0].startEdge) {
                /* this edge comes from face data */
                int lastface = ccgSubSurf_getNumFaces(ss) - 1;
                CCGFace *f;
                int edgeSize = ccgSubSurf_getEdgeSize(ss);
                int gridSideEdges;
                int gridInternalEdges;
 +                              int lasti, previ;
 +
 +                              i = lastface;
 +                              lasti = 0;
 +                              while (1) {
 +                                      previ = i;
 +                                      if (cgdm->faceMap[i].startEdge >= edgeNum) {
 +                                              i -= fabsf(i-lasti)/2.0f;
 +                                      } else if (cgdm->faceMap[i].startEdge < edgeNum) {
 +                                              i += fabsf(i-lasti)/2.0f;
 +                                      } else {
 +                                              break;
 +                                      }
  
 -              i = 0;
 -              while(i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge)
 +                                      if (i < 0) {
 +                                              i = 0;
 +                                              break;
 +                                      }
 +
 +                                      if (i > lastface) {
 +                                              i = lastface;
 +                                              break;
 +
 +                                      }
 +
 +                                      if (i == lasti)
 +                                         break;
 +
 +                                      lasti = previ;
 +                              }
 +
 +                              i = i > 0 ? i - 1 : i;
 +              while(i < lastface && edgeNum >= cgdm->faceMap[i + 1].startEdge)
                        ++i;
  
 -              f = ccgdm->faceMap[i].face;
 +              f = cgdm->faceMap[i].face;
                /* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/
  
                gridSideEdges = gridSize - 1;
                gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; 
  
 -              offset = edgeNum - ccgdm->faceMap[i].startEdge;
 +              offset = edgeNum - cgdm->faceMap[i].startEdge;
                grid = offset / (gridSideEdges + gridInternalEdges);
                offset %= (gridSideEdges + gridInternalEdges);
  
                short *edgeFlag;
                unsigned int flags = 0;
  
 -              i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
 +              i = (edgeNum - cgdm->edgeMap[0].startEdge) / (edgeSize - 1);
  
 -              e = ccgdm->edgeMap[i].edge;
 +              e = cgdm->edgeMap[i].edge;
  
                if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
  
 -              x = edgeNum - ccgdm->edgeMap[i].startEdge;
 +              x = edgeNum - cgdm->edgeMap[i].startEdge;
  
                med->v1 = getEdgeIndex(ss, e, x, edgeSize);
                med->v2 = getEdgeIndex(ss, e, x+1, edgeSize);
  
 -              edgeFlag = (ccgdm->edgeFlags)? &ccgdm->edgeFlags[i]: NULL;
 +              edgeFlag = (cgdm->edgeFlags)? &cgdm->edgeFlags[i]: NULL;
                if(edgeFlag)
                        flags |= (*edgeFlag & (ME_SEAM | ME_SHARP))
                                         | ME_EDGEDRAW | ME_EDGERENDER;
  
  static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int gridSize = ccgSubSurf_getGridSize(ss);
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int gridSideEdges = gridSize - 1;
        int offset;
        int grid;
        int x, y;
 -      int lastface = ccgSubSurf_getNumFaces(ss) - 1;
 -      char *faceFlags = ccgdm->faceFlags;
 +      /*int lastface = ccgSubSurf_getNumFaces(ss) - 1;*/ /*UNUSED*/
 +      char *faceFlags = cgdm->faceFlags;
  
        memset(mf, 0, sizeof(*mf));
 +      if (faceNum >= cgdm->dm.numFaceData)
 +              return;
  
 -      i = 0;
 -      while(i < lastface && faceNum >= ccgdm->faceMap[i + 1].startFace)
 -              ++i;
 +      i = cgdm->reverseFaceMap[faceNum];
  
 -      f = ccgdm->faceMap[i].face;
 +      f = cgdm->faceMap[i].face;
        /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/
  
 -      offset = faceNum - ccgdm->faceMap[i].startFace;
 +      offset = faceNum - cgdm->faceMap[i].startFace;
        grid = offset / gridFaces;
        offset %= gridFaces;
        y = offset / gridSideEdges;
  
  static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        DMGridData *vd;
        int index;
        int totvert, totedge, totface;
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(index = 0; index < totface; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                vd= ccgSubSurf_getFaceCenterData(f);
  
        totedge = ccgSubSurf_getNumEdges(ss);
        for(index = 0; index < totedge; index++) {
 -              CCGEdge *e = ccgdm->edgeMap[index].edge;
 +              CCGEdge *e = cgdm->edgeMap[index].edge;
                int x;
  
                for(x = 1; x < edgeSize - 1; x++, i++) {
  
        totvert = ccgSubSurf_getNumVerts(ss);
        for(index = 0; index < totvert; index++) {
 -              CCGVert *v = ccgdm->vertMap[index].vert;
 +              CCGVert *v = cgdm->vertMap[index].vert;
  
                vd= ccgSubSurf_getVertData(ss, v);
                copy_v3_v3(mvert[i].co, vd->co);
  
  static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int index;
        int totedge, totface;
        int gridSize = ccgSubSurf_getGridSize(ss);
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int i = 0;
 -      short *edgeFlags = ccgdm->edgeFlags;
 +      short *edgeFlags = cgdm->edgeFlags;
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(index = 0; index < totface; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                for(S = 0; S < numVerts; S++) {
                        for(x = 0; x < gridSize - 1; x++) {
                                MEdge *med = &medge[i];
  
 -                              if(ccgdm->drawInteriorEdges)
 +                              if(cgdm->drawInteriorEdges)
                                        med->flag = ME_EDGEDRAW | ME_EDGERENDER;
                                med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize);
                                med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize);
                                        MEdge *med;
  
                                        med = &medge[i];
 -                                      if(ccgdm->drawInteriorEdges)
 +                                      if(cgdm->drawInteriorEdges)
                                                med->flag = ME_EDGEDRAW | ME_EDGERENDER;
                                        med->v1 = getFaceIndex(ss, f, S, x, y,
                                                                                   edgeSize, gridSize);
                                        i++;
  
                                        med = &medge[i];
 -                                      if(ccgdm->drawInteriorEdges)
 +                                      if(cgdm->drawInteriorEdges)
                                                med->flag = ME_EDGEDRAW | ME_EDGERENDER;
                                        med->v1 = getFaceIndex(ss, f, S, y, x,
                                                                                   edgeSize, gridSize);
  
        totedge = ccgSubSurf_getNumEdges(ss);
        for(index = 0; index < totedge; index++) {
 -              CCGEdge *e = ccgdm->edgeMap[index].edge;
 +              CCGEdge *e = cgdm->edgeMap[index].edge;
                unsigned int flags = 0;
                int x;
                int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
  
  static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int index;
        int totface;
        int gridSize = ccgSubSurf_getGridSize(ss);
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int i = 0;
 -      char *faceFlags = ccgdm->faceFlags;
 +      char *faceFlags = cgdm->faceFlags;
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(index = 0; index < totface; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
                int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH;
                int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0;
                                                                                  edgeSize, gridSize);
                                        mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
                                                                                  edgeSize, gridSize);
 +                                      if (faceFlags) {
 +                                              mat_nr = faceFlags[index*2+1];
 +                                              mf->flag = faceFlags[index*2];
 +                                      } else mf->flag = flag;
 +
                                        mf->mat_nr = mat_nr;
                                        mf->flag = flag;
  
        }
  }
  
 -static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
 +{
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
 +      int index;
 +      int totface;
 +      int gridSize = ccgSubSurf_getGridSize(ss);
 +      int edgeSize = ccgSubSurf_getEdgeSize(ss);
 +      int i = 0;
 +      MLoop *mv;
 +      /* char *faceFlags = cgdm->faceFlags; */ /* UNUSED */
 +
 +      if (!cgdm->ehash) {
 +              MEdge *medge;
 +
 +              cgdm->ehash = BLI_edgehash_new();
 +              medge = cgdm->dm.getEdgeArray((DerivedMesh*)cgdm);
 +
 +              for (i=0; i<cgdm->dm.numEdgeData; i++) {
 +                      BLI_edgehash_insert(cgdm->ehash, medge[i].v1, medge[i].v2, SET_INT_IN_POINTER(i));
 +              }
 +      }
 +
 +      totface = ccgSubSurf_getNumFaces(ss);
 +      mv = mloop;
 +      for(index = 0; index < totface; index++) {
 +              CCGFace *f = cgdm->faceMap[index].face;
 +              int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
 +              /* int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH; */ /* UNUSED */
 +              /* int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0; */ /* UNUSED */
 +
 +              for(S = 0; S < numVerts; S++) {
 +                      for(y = 0; y < gridSize - 1; y++) {
 +                              for(x = 0; x < gridSize - 1; x++) {
 +                                      int v1, v2, v3, v4;
 +
 +                                      v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
 +                                                                                edgeSize, gridSize);
 +
 +                                      v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
 +                                                                                edgeSize, gridSize);
 +                                      v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
 +                                                                                edgeSize, gridSize);
 +                                      v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
 +                                                                                edgeSize, gridSize);
 +
 +                                      mv->v = v1;
 +                                      mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v1, v2));
 +                                      mv++, i++;
 +
 +                                      mv->v = v2;
 +                                      mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v2, v3));
 +                                      mv++, i++;
 +
 +                                      mv->v = v3;
 +                                      mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v3, v4));
 +                                      mv++, i++;
 +
 +                                      mv->v = v4;
 +                                      mv->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(cgdm->ehash, v4, v1));
 +                                      mv++, i++;
 +                              }
 +                      }
 +              }
 +      }
 +}
 +
 +
 +static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mface)
 +{
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
 +      int index;
 +      int totface;
 +      int gridSize = ccgSubSurf_getGridSize(ss);
 +      /* int edgeSize = ccgSubSurf_getEdgeSize(ss); */ /* UNUSED */
 +      int i = 0, k = 0;
 +      char *faceFlags = cgdm->faceFlags;
 +
 +      totface = ccgSubSurf_getNumFaces(ss);
 +      for(index = 0; index < totface; index++) {
 +              CCGFace *f = cgdm->faceMap[index].face;
 +              int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
 +              int flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH;
 +              int mat_nr = (faceFlags)? faceFlags[index*2+1]: 0;
 +
 +              for(S = 0; S < numVerts; S++) {
 +                      for(y = 0; y < gridSize - 1; y++) {
 +                              for(x = 0; x < gridSize - 1; x++) {
 +                                      MPoly *mf = &mface[i];
 +
 +                                      if (faceFlags) {
 +                                              mat_nr = faceFlags[index*2+1];
 +                                              mf->flag = faceFlags[index*2];
 +                                      } else mf->flag = flag;
 +
 +                                      mf->mat_nr = mat_nr;
 +                                      mf->flag = flag;
 +                                      mf->loopstart = k;
 +                                      mf->totloop = 4;
 +
 +                                      k += 4;
 +                                      i++;
 +                              }
 +                      }
 +              }
 +      }
 +}
 +
 +static void cgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int gridSize = ccgSubSurf_getGridSize(ss);
        int i;
        MEM_freeN(edgeMap2);
        MEM_freeN(faceMap2);
  }
 -static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGVertIterator *vi = ccgSubSurf_getVertIterator(ccgdm->ss);
 +static void cgdm_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGVertIterator *vi = ccgSubSurf_getVertIterator(cgdm->ss);
  
        for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
 -              DMGridData *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
 -              int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
 +              DMGridData *vd = ccgSubSurf_getVertData(cgdm->ss, v);
 +              int index = ccgDM_getVertMapIndex(cgdm->ss, v);
  
                if (index!=-1)
                        func(userData, index, vd->co, vd->no, NULL);
  
        ccgVertIterator_free(vi);
  }
 -static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
        int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
  
  }
  
  static void ccgDM_drawVerts(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
        int gridSize = ccgSubSurf_getGridSize(ss);
        CCGVertIterator *vi;
@@@ -1464,8 -1244,8 +1464,8 @@@ static void ccgDM_drawEdges(DerivedMes
        ccgEdgeIterator_free(ei);
  }
  static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
        int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
  
@@@ -1588,20 -1368,20 +1588,20 @@@ static void ccgDM_drawFacesSolid(Derive
  }
  
        /* Only used by non-editmesh types */
 -static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
        GPUVertexAttribs gattribs;
        DMVertexAttribs attribs= {{{NULL}}};
-       MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE);
 -      /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
++      /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
        int gridSize = ccgSubSurf_getGridSize(ss);
        int gridFaces = gridSize - 1;
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
 -      char *faceFlags = ccgdm->faceFlags;
 +      char *faceFlags = cgdm->faceFlags;
        int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
  
 -      ccgdm_pbvh_update(ccgdm);
 +      ccgdm_pbvh_update(cgdm);
  
        doDraw = 0;
        matnr = -1;
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(a = 0, i = 0; i < totface; i++) {
 -              CCGFace *f = ccgdm->faceMap[i].face;
 +              CCGFace *f = cgdm->faceMap[i].face;
                int S, x, y, drawSmooth;
                int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
                int origIndex = ccgDM_getFaceMapIndex(ss, f);
        ccgFaceIterator_free(fi);
  }
  
 -static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
 +static void cgdm_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
        dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
  }
  
 -static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
        int gridSize = ccgSubSurf_getGridSize(ss);
        unsigned char *cp1, *cp2;
        int useTwoSide=1;
  
 -      ccgdm_pbvh_update(ccgdm);
 +      ccgdm_pbvh_update(cgdm);
  
        cp1= col1;
        if(col2) {
        ccgFaceIterator_free(fi);
  }
  
 -static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
 -      int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
 +static void cgdm_drawFacesTex_common(DerivedMesh *dm,
 +      int (*drawParams)(MTFace *tface, int has_vcol, int matnr),
        int (*drawParamsMapped)(void *userData, int index),
        void *userData) 
  {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 -      MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
 -      MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
 -      char *faceFlags = ccgdm->faceFlags;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
 +      MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
 +      MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
 +      char *faceFlags = cgdm->faceFlags;
        int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss);
        int gridFaces = gridSize - 1;
  
 -      ccgdm_pbvh_update(ccgdm);
 +      ccgdm_pbvh_update(cgdm);
  
        if(!mcol)
 -              mcol = dm->getFaceDataArray(dm, CD_MCOL);
 +              mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(i = 0; i < totface; i++) {
 -              CCGFace *f = ccgdm->faceMap[i].face;
 +              CCGFace *f = cgdm->faceMap[i].face;
                int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
                int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
                int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
                }
  
                if(drawParams)
 -                      flag = drawParams(tf, mcol, mat_nr);
 +                      flag = drawParams(tf, mcol!=NULL, mat_nr);
                else if (index != ORIGINDEX_NONE)
                        flag= (drawParamsMapped)? drawParamsMapped(userData, index): 1;
                else
        }
  }
  
 -static void ccgDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
 +static void cgdm_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_vcol, int matnr))
  {
 -      ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
 +      cgdm_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
  }
  
 -static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
 +static void cgdm_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
  {
 -      ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
 +      cgdm_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
  }
  
 -static void ccgDM_drawUVEdges(DerivedMesh *dm)
 +static void cgdm_drawUVEdges(DerivedMesh *dm)
  {
  
 -      MFace *mf = dm->getFaceArray(dm);
 -      MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
 +      MFace *mf = dm->getTessFaceArray(dm);
 +      MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
        int i;
        
        if (tf) {
  
  static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs),
                        int (*compareDrawOptions)(void *userData, int cur_index, int next_index)) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        MCol *mcol= NULL;
        int i, gridSize = ccgSubSurf_getGridSize(ss);
 -      char *faceFlags = ccgdm->faceFlags;
 +      char *faceFlags = cgdm->faceFlags;
        int gridFaces = gridSize - 1, totface;
  
        /* currently unused -- each original face is handled separately */
        (void)compareDrawOptions;
  
        if(useColors) {
 -              mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
 +              mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
                if(!mcol)
 -                      mcol = dm->getFaceDataArray(dm, CD_MCOL);
 +                      mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
        }
  
        totface = ccgSubSurf_getNumFaces(ss);
        for(i = 0; i < totface; i++) {
 -              CCGFace *f = ccgdm->faceMap[i].face;
 +              CCGFace *f = cgdm->faceMap[i].face;
                int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
                int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
                int origIndex;
                }
        }
  }
 -static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
        int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
  
  
        ccgEdgeIterator_free(ei);
  }
 -static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
        int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
  
  
        ccgEdgeIterator_free(ei);
  }
 -static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
 -      CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
 -      CCGSubSurf *ss = ccgdm->ss;
 +static void cgdm_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
 +      CCGDerivedMesh *cgdm = (CCGDerivedMesh*) dm;
 +      CCGSubSurf *ss = cgdm->ss;
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
  
        for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
        ccgFaceIterator_free(fi);
  }
  
 -static void ccgDM_release(DerivedMesh *dm) {
 +static void cgdm_release(DerivedMesh *dm) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
  
        if (DM_release(dm)) {
                                ccgdm->multires.update(dm);
                }
  
 +              if (ccgdm->ehash)
 +                      BLI_edgehash_free(ccgdm->ehash, NULL);
 +
 +              if(ccgdm->reverseFaceMap) MEM_freeN(ccgdm->reverseFaceMap);
                if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces);
                if(ccgdm->gridData) MEM_freeN(ccgdm->gridData);
                if(ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency);
        }
  }
  
 +static void ccg_loops_to_corners(CustomData *fdata, CustomData *ldata, 
 +                        CustomData *pdata, int loopstart, int findex, 
 +                        int polyindex, int numTex, int numCol) 
 +{
 +      MTFace *texface;
 +      MTexPoly *texpoly;
 +      MCol *mcol;
 +      MLoopCol *mloopcol;
 +      MLoopUV *mloopuv;
 +      int i, j, hasWCol = CustomData_has_layer(ldata, CD_WEIGHT_MLOOPCOL);
 +
 +      for(i=0; i < numTex; i++){
 +              texface = CustomData_get_n(fdata, CD_MTFACE, findex, i);
 +              texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i);
 +              
 +              texface->tpage = texpoly->tpage;
 +              texface->flag = texpoly->flag;
 +              texface->transp = texpoly->transp;
 +              texface->mode = texpoly->mode;
 +              texface->tile = texpoly->tile;
 +              texface->unwrap = texpoly->unwrap;
 +
 +              mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
 +              for (j=0; j<4; j++, mloopuv++) {
 +                      texface->uv[j][0] = mloopuv->uv[0];
 +                      texface->uv[j][1] = mloopuv->uv[1];
 +              }
 +      }
 +
 +      for(i=0; i < numCol; i++){
 +              mloopcol = CustomData_get_n(ldata, CD_MLOOPCOL, loopstart, i);
 +              mcol = CustomData_get_n(fdata, CD_MCOL, findex, i);
 +
 +              for (j=0; j<4; j++, mloopcol++) {
 +                      mcol[j].r = mloopcol->r;
 +                      mcol[j].g = mloopcol->g;
 +                      mcol[j].b = mloopcol->b;
 +                      mcol[j].a = mloopcol->a;
 +              }
 +      }
 +      
 +      if (hasWCol) {
 +              mloopcol = CustomData_get(ldata, loopstart, CD_WEIGHT_MLOOPCOL);
 +              mcol = CustomData_get(fdata, findex, CD_WEIGHT_MCOL);
 +
 +              for (j=0; j<4; j++, mloopcol++) {
 +                      mcol[j].r = mloopcol->r;
 +                      mcol[j].g = mloopcol->g;
 +                      mcol[j].b = mloopcol->b;
 +                      mcol[j].a = mloopcol->a;
 +              }
 +      }
 +}
 +
  static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
  {
        if(type == CD_ORIGINDEX) {
                /* create origindex on demand to save memory */
 -              CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -              CCGSubSurf *ss= ccgdm->ss;
 +              CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +              CCGSubSurf *ss= cgdm->ss;
                int *origindex;
                int a, index, totnone, totorig;
  
                        origindex[a]= ORIGINDEX_NONE;
  
                for(index=0; index<totorig; index++, a++) {
 -                      CCGVert *v = ccgdm->vertMap[index].vert;
 -                      origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v);
 +                      CCGVert *v = cgdm->vertMap[index].vert;
 +                      origindex[a] = ccgDM_getVertMapIndex(cgdm->ss, v);
                }
  
                return origindex;
@@@ -2306,8 -2028,8 +2306,8 @@@ static void *ccgDM_get_edge_data_layer(
  {
        if(type == CD_ORIGINDEX) {
                /* create origindex on demand to save memory */
 -              CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -              CCGSubSurf *ss= ccgdm->ss;
 +              CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +              CCGSubSurf *ss= cgdm->ss;
                int *origindex;
                int a, i, index, totnone, totorig, totedge;
                int edgeSize= ccgSubSurf_getEdgeSize(ss);
                        origindex[a]= ORIGINDEX_NONE;
  
                for(index=0; index<totedge; index++) {
 -                      CCGEdge *e= ccgdm->edgeMap[index].edge;
 +                      CCGEdge *e= cgdm->edgeMap[index].edge;
                        int mapIndex= ccgDM_getEdgeMapIndex(ss, e);
  
                        for(i = 0; i < edgeSize - 1; i++, a++)
@@@ -2341,19 -2063,19 +2341,19 @@@ static void *ccgDM_get_face_data_layer(
  {
        if(type == CD_ORIGINDEX) {
                /* create origindex on demand to save memory */
 -              CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -              CCGSubSurf *ss= ccgdm->ss;
 +              CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +              CCGSubSurf *ss= cgdm->ss;
                int *origindex;
                int a, i, index, totface;
                int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
  
                DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
 -              origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX);
 +              origindex= DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
  
                totface= ccgSubSurf_getNumFaces(ss);
  
                for(a=0, index=0; index<totface; index++) {
 -                      CCGFace *f = ccgdm->faceMap[index].face;
 +                      CCGFace *f = cgdm->faceMap[index].face;
                        int numVerts = ccgSubSurf_getFaceNumVerts(f);
                        int mapIndex = ccgDM_getFaceMapIndex(ss, f);
  
                return origindex;
        }
  
 -      return DM_get_face_data_layer(dm, type);
 +      return DM_get_tessface_data_layer(dm, type);
  }
  
  static int ccgDM_getNumGrids(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
        int index, numFaces, numGrids;
  
 -      numFaces= ccgSubSurf_getNumFaces(ccgdm->ss);
 +      numFaces= ccgSubSurf_getNumFaces(cgdm->ss);
        numGrids= 0;
  
        for(index=0; index<numFaces; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                numGrids += ccgSubSurf_getFaceNumVerts(f);
        }
  
  
  static int ccgDM_getGridSize(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -      return ccgSubSurf_getGridSize(ccgdm->ss);
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +      return ccgSubSurf_getGridSize(cgdm->ss);
  }
  
 -static int ccgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset)
 +static int cgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset)
  {
        CCGFace *adjf;
        CCGEdge *e;
  
  static void ccgdm_create_grids(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 -      CCGSubSurf *ss= ccgdm->ss;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
 +      CCGSubSurf *ss= cgdm->ss;
        DMGridData **gridData;
        DMGridAdjacency *gridAdjacency, *adj;
        CCGFace **gridFaces;
        int *gridOffset;
        int index, numFaces, numGrids, S, gIndex /*, gridSize*/;
  
 -      if(ccgdm->gridData)
 +      if(cgdm->gridData)
                return;
        
        numGrids = ccgDM_getNumGrids(dm);
        /*gridSize = ccgDM_getGridSize(dm);*/  /*UNUSED*/
  
        /* compute offset into grid array for each face */
 -      gridOffset = MEM_mallocN(sizeof(int)*numFaces, "ccgdm.gridOffset");
 +      gridOffset = MEM_mallocN(sizeof(int)*numFaces, "cgdm.gridOffset");
  
        for(gIndex = 0, index = 0; index < numFaces; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                gridOffset[index] = gIndex;
        }
  
        /* compute grid data */
 -      gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "ccgdm.gridData");
 -      gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "ccgdm.gridAdjacency");
 -      gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "ccgdm.gridFaces");
 +      gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "cgdm.gridData");
 +      gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "cgdm.gridAdjacency");
 +      gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "cgdm.gridFaces");
  
        for(gIndex = 0, index = 0; index < numFaces; index++) {
 -              CCGFace *f = ccgdm->faceMap[index].face;
 +              CCGFace *f = cgdm->faceMap[index].face;
                int numVerts = ccgSubSurf_getFaceNumVerts(f);
  
                for(S = 0; S < numVerts; S++, gIndex++) {
  
                        adj->index[0] = gIndex - S + nextS;
                        adj->rotation[0] = 3;
 -                      adj->index[1] = ccgdm_adjacent_grid(ss, gridOffset, f, prevS, 0);
 +                      adj->index[1] = cgdm_adjacent_grid(ss, gridOffset, f, prevS, 0);
                        adj->rotation[1] = 1;
 -                      adj->index[2] = ccgdm_adjacent_grid(ss, gridOffset, f, S, 1);
 +                      adj->index[2] = cgdm_adjacent_grid(ss, gridOffset, f, S, 1);
                        adj->rotation[2] = 3;
                        adj->index[3] = gIndex - S + prevS;
                        adj->rotation[3] = 1;
                }
        }
  
 -      ccgdm->gridData = gridData;
 -      ccgdm->gridFaces = gridFaces;
 -      ccgdm->gridAdjacency = gridAdjacency;
 -      ccgdm->gridOffset = gridOffset;
 +      cgdm->gridData = gridData;
 +      cgdm->gridFaces = gridFaces;
 +      cgdm->gridAdjacency = gridAdjacency;
 +      cgdm->gridOffset = gridOffset;
  }
  
  static DMGridData **ccgDM_getGridData(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
  
        ccgdm_create_grids(dm);
 -      return ccgdm->gridData;
 +      return cgdm->gridData;
  }
  
  static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
  
        ccgdm_create_grids(dm);
 -      return ccgdm->gridAdjacency;
 +      return cgdm->gridAdjacency;
  }
  
  static int *ccgDM_getGridOffset(DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
 +      CCGDerivedMesh *cgdm= (CCGDerivedMesh*)dm;
  
        ccgdm_create_grids(dm);
 -      return ccgdm->gridOffset;
 +      return cgdm->gridOffset;
  }
  
  static ListBase *ccgDM_getFaceMap(Object *ob, DerivedMesh *dm)
@@@ -2591,74 -2313,50 +2591,74 @@@ static CCGDerivedMesh *getCCGDerivedMes
                                                                                 int useSubsurfUv,
                                                                                 DerivedMesh *dm)
  {
 -      CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
 +      CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "cgdm");
        CCGVertIterator *vi;
        CCGEdgeIterator *ei;
        CCGFaceIterator *fi;
        int index, totvert, totedge, totface;
        int i;
        int vertNum, edgeNum, faceNum;
 +      int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex; /* *edgeOrigIndex - as yet, unused  */
        short *edgeFlags;
        char *faceFlags;
 -      int edgeSize;
 +      int *loopidx = NULL, *vertidx = NULL;
 +      BLI_array_declare(loopidx);
 +      BLI_array_declare(vertidx);
 +      int loopindex, loopindex2;
 +      int edgeSize, has_edge_origindex;
        int gridSize;
 -      int gridFaces;
 +      int gridFaces, gridCuts;
        /*int gridSideVerts;*/
        int gridSideEdges;
 +      int numTex, numCol;
        int gridInternalEdges;
 +      float *w = NULL;
 +      WeightTable wtable = {0};
 +      MCol *mcol;
        MEdge *medge = NULL;
 -      MFace *mface = NULL;
 -      int *orig_indices;
 -      FaceVertWeight *qweight, *tweight;
 +      /* MFace *mface = NULL; */
 +      MPoly *mpoly = NULL;
  
        DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
                                         ccgSubSurf_getNumFinalVerts(ss),
                                         ccgSubSurf_getNumFinalEdges(ss),
 +                                       ccgSubSurf_getNumFinalFaces(ss),
 +                                       ccgSubSurf_getNumFinalFaces(ss)*4, 
                                         ccgSubSurf_getNumFinalFaces(ss));
 +      
 +      numTex = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPUV);
 +      numCol = CustomData_number_of_layers(&ccgdm->dm.loopData, CD_MLOOPCOL);
 +      
 +      if (numTex && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MTFACE) != numTex)
 +              CustomData_from_bmeshpoly(&ccgdm->dm.faceData, &ccgdm->dm.polyData, &ccgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss));
 +      else if (numCol && CustomData_number_of_layers(&ccgdm->dm.faceData, CD_MCOL) != numCol)
 +              CustomData_from_bmeshpoly(&ccgdm->dm.faceData, &ccgdm->dm.polyData, &ccgdm->dm.loopData, ccgSubSurf_getNumFinalFaces(ss));
  
 -      ccgdm->dm.getMinMax = ccgDM_getMinMax;
 -      ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
 -      ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
 +      ccgdm->dm.getMinMax = cgdm_getMinMax;
 +      ccgdm->dm.getNumVerts = cgdm_getNumVerts;
 +      ccgdm->dm.getNumEdges = cgdm_getNumEdges;
 +      ccgdm->dm.getNumTessFaces = cgdm_getNumTessFaces;
 +      ccgdm->dm.getNumFaces = cgdm_getNumTessFaces;
 +
 +      ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
 +      ccgdm->dm.getPBVH = ccgDM_getPBVH;
  
 -      ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
        ccgdm->dm.getVert = ccgDM_getFinalVert;
        ccgdm->dm.getEdge = ccgDM_getFinalEdge;
 -      ccgdm->dm.getFace = ccgDM_getFinalFace;
 +      ccgdm->dm.getTessFace = ccgDM_getFinalFace;
        ccgdm->dm.getVertCo = ccgDM_getFinalVertCo;
        ccgdm->dm.getVertNo = ccgDM_getFinalVertNo;
        ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
        ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
 -      ccgdm->dm.copyFaceArray = ccgDM_copyFinalFaceArray;
 +      ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
 +      ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray;
 +      ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray;
        ccgdm->dm.getVertData = DM_get_vert_data;
        ccgdm->dm.getEdgeData = DM_get_edge_data;
 -      ccgdm->dm.getFaceData = DM_get_face_data;
 +      ccgdm->dm.getTessFaceData = DM_get_face_data;
        ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
        ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
 -      ccgdm->dm.getFaceDataArray = ccgDM_get_face_data_layer;
 +      ccgdm->dm.getTessFaceDataArray = ccgDM_get_face_data_layer;
        ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
        ccgdm->dm.getGridSize = ccgDM_getGridSize;
        ccgdm->dm.getGridData = ccgDM_getGridData;
        ccgdm->dm.getFaceMap = ccgDM_getFaceMap;
        ccgdm->dm.getPBVH = ccgDM_getPBVH;
  
 -      ccgdm->dm.getVertCos = ccgdm_getVertCos;
 -      ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
 -      ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
 -      ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
 +      ccgdm->dm.getTessFace = ccgDM_getFinalFace;
 +      ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
 +      ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
 +      ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
 +      ccgdm->dm.getVertData = DM_get_vert_data;
 +      ccgdm->dm.getEdgeData = DM_get_edge_data;
 +      ccgdm->dm.getTessFaceData = DM_get_face_data;
 +      ccgdm->dm.getVertDataArray = DM_get_vert_data_layer;
 +      ccgdm->dm.getEdgeDataArray = DM_get_edge_data_layer;
 +      ccgdm->dm.getTessFaceDataArray = DM_get_tessface_data_layer;
 +
 +      ccgdm->dm.getVertCos = cgdm_getVertCos;
 +      ccgdm->dm.foreachMappedVert = cgdm_foreachMappedVert;
 +      ccgdm->dm.foreachMappedEdge = cgdm_foreachMappedEdge;
 +      ccgdm->dm.foreachMappedFaceCenter = cgdm_foreachMappedFaceCenter;
        
        ccgdm->dm.drawVerts = ccgDM_drawVerts;
        ccgdm->dm.drawEdges = ccgDM_drawEdges;
        ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
        ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
 -      ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
 -      ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
 -      ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
 +      ccgdm->dm.drawFacesColored = cgdm_drawFacesColored;
 +      ccgdm->dm.drawFacesTex = cgdm_drawFacesTex;
 +      ccgdm->dm.drawFacesGLSL = cgdm_drawFacesGLSL;
        ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
 -      ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
 -      ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
 -      ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
 +      ccgdm->dm.drawMappedFacesTex = cgdm_drawMappedFacesTex;
 +      ccgdm->dm.drawMappedFacesGLSL = cgdm_drawMappedFacesGLSL;
 +      ccgdm->dm.drawUVEdges = cgdm_drawUVEdges;
  
 -      ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
 -      ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
 +      ccgdm->dm.drawMappedEdgesInterp = cgdm_drawMappedEdgesInterp;
 +      ccgdm->dm.drawMappedEdges = cgdm_drawMappedEdges;
        
 -      ccgdm->dm.release = ccgDM_release;
 +      ccgdm->dm.release = cgdm_release;
        
        ccgdm->ss = ss;
        ccgdm->drawInteriorEdges = drawInteriorEdges;
        ccgdm->useSubsurfUv = useSubsurfUv;
  
        totvert = ccgSubSurf_getNumVerts(ss);
 -      ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
 +      ccgdm->vertMap = MEM_callocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
        vi = ccgSubSurf_getVertIterator(ss);
        for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
        ccgVertIterator_free(vi);
  
        totedge = ccgSubSurf_getNumEdges(ss);
 -      ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
 +      ccgdm->edgeMap = MEM_callocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
        ei = ccgSubSurf_getEdgeIterator(ss);
        for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
        }
  
        totface = ccgSubSurf_getNumFaces(ss);
 -      ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
 +      ccgdm->faceMap = MEM_callocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
        fi = ccgSubSurf_getFaceIterator(ss);
        for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
        }
        ccgFaceIterator_free(fi);
  
 +      ccgdm->reverseFaceMap = MEM_callocN(sizeof(int)*ccgSubSurf_getNumFinalFaces(ss), "reverseFaceMap");
 +
        edgeSize = ccgSubSurf_getEdgeSize(ss);
        gridSize = ccgSubSurf_getGridSize(ss);
        gridFaces = gridSize - 1;
 -      /*gridSideVerts = gridSize - 2;*/ /*UNUSED*/
 -      /*gridInternalVerts = gridSideVerts * gridSideVerts; */ /*UNUSED*/
 +      gridCuts = gridSize - 2;
 +      /*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
        gridSideEdges = gridSize - 1;
        gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; 
  
 -      calc_ss_weights(gridFaces, &qweight, &tweight);
 -
        vertNum = 0;
        edgeNum = 0;
        faceNum = 0;
  
 -      /* mvert = dm->getVertArray(dm); - as yet unused */
 +      /* mvert = dm->getVertArray(dm); */ /* UNUSED */
        medge = dm->getEdgeArray(dm);
 -      mface = dm->getFaceArray(dm);
 +      /* mface = dm->getTessFaceArray(dm); */ /* UNUSED */
  
 +      mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
 +      base_polyOrigIndex = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
 +      
 +      /*CDDM hack*/
 +      edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "faceFlags");
        faceFlags = ccgdm->faceFlags = MEM_callocN(sizeof(char)*2*totface, "faceFlags");
  
 -      orig_indices = (int*)ccgdm->dm.getFaceDataArray(&ccgdm->dm, CD_ORIGINDEX);
 -      for(index = 0; index < totface; ++index) {
 +      vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
 +      /*edgeOrigIndex = DM_get_edge_data_layer(&cgdm->dm, CD_ORIGINDEX);*/
 +      faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX);
 +
 +      polyOrigIndex = DM_get_face_data_layer(&ccgdm->dm, CD_ORIGINDEX);
 +
 +      if (!CustomData_has_layer(&ccgdm->dm.faceData, CD_MCOL))
 +              DM_add_tessface_layer(&ccgdm->dm, CD_MCOL, CD_CALLOC, NULL);
 +
 +      mcol = DM_get_tessface_data_layer(&ccgdm->dm, CD_MCOL);
 +      has_edge_origindex = CustomData_has_layer(&ccgdm->dm.edgeData, CD_ORIGINDEX);
 +
 +      faceNum = 0;
 +      loopindex = loopindex2 = 0; //current loop index
 +      for (index = 0; index < totface; index++) {
                CCGFace *f = ccgdm->faceMap[index].face;
                int numVerts = ccgSubSurf_getFaceNumVerts(f);
                int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
                int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
 -              FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
 -              int S, x, y;
 -              int vertIdx[4];
 +              int g2_wid = gridCuts+2;
 +              float *w2;
 +              int s, x, y;
 +              
 +              origIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
 +              
 +              w = get_ss_weights(&wtable, gridCuts, numVerts);
  
                ccgdm->faceMap[index].startVert = vertNum;
                ccgdm->faceMap[index].startEdge = edgeNum;
                ccgdm->faceMap[index].startFace = faceNum;
 -
 -              if(orig_indices)
 -                      orig_indices[faceNum] = origIndex;
 +              
 +              faceFlags[0] = mpoly ?  mpoly[origIndex].flag : 0;
 +              faceFlags[1] = mpoly ? mpoly[origIndex].mat_nr : 0;
 +              faceFlags += 2;
  
                /* set the face base vert */
                *((int*)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
  
 -              for(S = 0; S < numVerts; S++) {
 -                      CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
 +              BLI_array_empty(loopidx);               
 +              for (s=0; s<numVerts; s++) {
 +                      BLI_array_growone(loopidx);
 +                      loopidx[s] = loopindex++;
 +              }
 +              
 +              BLI_array_empty(vertidx);
 +                              for(s = 0; s < numVerts; s++) {
 +                      CCGVert *v = ccgSubSurf_getFaceVert(ss, f, s);
 +                      
 +                      BLI_array_growone(vertidx);
 +                      vertidx[s] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 +              }
 +              
  
 -                      vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 +              /*I think this is for interpolating the center vert?*/
 +              w2 = w; // + numVerts*(g2_wid-1)*(g2_wid-1); //numVerts*((g2_wid-1)*g2_wid+g2_wid-1);
 +              DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
 +                                  numVerts, vertNum);
 +              if (vertOrigIndex) {
 +                      *vertOrigIndex = ORIGINDEX_NONE;
 +                      ++vertOrigIndex;
                }
  
 -              DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0],
 -                                                      numVerts, vertNum);
                ++vertNum;
  
 -              for(S = 0; S < numVerts; S++) {
 -                      int prevS = (S - 1 + numVerts) % numVerts;
 -                      int nextS = (S + 1) % numVerts;
 -                      int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
 +              /*interpolate per-vert data*/
 +              for(s = 0; s < numVerts; s++) {
                        for(x = 1; x < gridFaces; x++) {
 -                              float w[4];
 -                              w[prevS]  = weight[x][0][0];
 -                              w[S]      = weight[x][0][1];
 -                              w[nextS]  = weight[x][0][2];
 -                              w[otherS] = weight[x][0][3];
 -                              DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
 -                                                                      numVerts, vertNum);
 +                              w2 = w + s*numVerts*g2_wid*g2_wid + x*numVerts;
 +                              DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
 +                                                  numVerts, vertNum);
 +
 +                              if (vertOrigIndex) {
 +                                      *vertOrigIndex = ORIGINDEX_NONE;
 +                                      ++vertOrigIndex;
 +                              }
 +
                                ++vertNum;
                        }
                }
  
 -              for(S = 0; S < numVerts; S++) {
 -                      int prevS = (S - 1 + numVerts) % numVerts;
 -                      int nextS = (S + 1) % numVerts;
 -                      int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
 +              /*interpolate per-vert data*/
 +              for(s = 0; s < numVerts; s++) {
                        for(y = 1; y < gridFaces; y++) {
                                for(x = 1; x < gridFaces; x++) {
 -                                      float w[4];
 -                                      w[prevS]  = weight[y * gridFaces + x][0][0];
 -                                      w[S]      = weight[y * gridFaces + x][0][1];
 -                                      w[nextS]  = weight[y * gridFaces + x][0][2];
 -                                      w[otherS] = weight[y * gridFaces + x][0][3];
 -                                      DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
 -                                                                              numVerts, vertNum);
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts;
 +                                      DM_interp_vert_data(dm, &ccgdm->dm, vertidx, w2,
 +                                                          numVerts, vertNum);
 +
 +                                      if (vertOrigIndex) {
 +                                              *vertOrigIndex = ORIGINDEX_NONE;
 +                                              ++vertOrigIndex;
 +                                      }
 +
                                        ++vertNum;
                                }
                        }
                }
  
 -              for(S = 0; S < numVerts; S++) {
 -                      int prevS = (S - 1 + numVerts) % numVerts;
 -                      int nextS = (S + 1) % numVerts;
 -                      int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
 -
 -                      weight = (numVerts == 4) ? qweight : tweight;
 -
 -                      for(y = 0; y < gridFaces; y++) {
 -                              for(x = 0; x < gridFaces; x++) {
 -                                      FaceVertWeight w;
 -                                      int j;
 -
 -                                      for(j = 0; j < 4; ++j) {
 -                                              w[j][prevS]  = (*weight)[j][0];
 -                                              w[j][S]      = (*weight)[j][1];
 -                                              w[j][nextS]  = (*weight)[j][2];
 -                                              w[j][otherS] = (*weight)[j][3];
 +              if (has_edge_origindex) {
 +                      for(i = 0; i < numFinalEdges; ++i)
 +                              *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
 +                                                       CD_ORIGINDEX) = ORIGINDEX_NONE;
 +              }
 +
 +              for (s=0; s<numVerts; s++) {
 +                      /*interpolate per-face data*/
 +                      for (y=0; y<gridFaces; y++) {
 +                              for (x=0; x<gridFaces; x++) {
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + (y*g2_wid+x)*numVerts;
 +                                      CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
 +                                                        loopidx, w2, NULL, numVerts, loopindex2);
 +                                      loopindex2++;
 +
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x))*numVerts;
 +                                      CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
 +                                                        loopidx, w2, NULL, numVerts, loopindex2);
 +                                      loopindex2++;
 +
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + ((y+1)*g2_wid+(x+1))*numVerts;
 +                                      CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
 +                                                        loopidx, w2, NULL, numVerts, loopindex2);
 +                                      loopindex2++;
 +                                      
 +                                      w2 = w + s*numVerts*g2_wid*g2_wid + ((y)*g2_wid+(x+1))*numVerts;
 +                                      CustomData_interp(&dm->loopData, &ccgdm->dm.loopData,
 +                                                        loopidx, w2, NULL, numVerts, loopindex2);
 +                                      loopindex2++;
 +
 +                                      /*copy over poly data, e.g. mtexpoly*/
 +                                      CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
 +
 +                                      /*generate tesselated face data used for drawing*/
 +                                      ccg_loops_to_corners(&ccgdm->dm.faceData, &ccgdm->dm.loopData,
 +                                              &ccgdm->dm.polyData, loopindex2-4, faceNum, faceNum, numTex, numCol);
 +                                      
 +                                      /*set original index data*/
 +                                      if (faceOrigIndex) {
 +                                              *faceOrigIndex = origIndex;
 +                                              faceOrigIndex++;
 +                                      }
 +                                      if (polyOrigIndex) {
 +                                              *polyOrigIndex = origIndex;
 +                                              polyOrigIndex++;
                                        }
  
 -                                      DM_interp_face_data(dm, &ccgdm->dm, &origIndex, NULL,
 -                                                                              &w, 1, faceNum);
 -                                      weight++;
 +                                      ccgdm->reverseFaceMap[faceNum] = index;
  
 -                                      ++faceNum;
 +                                      faceNum++;
                                }
                        }
                }
  
 -              faceFlags[index*2] = mface[origIndex].flag;
 -              faceFlags[index*2 + 1] = mface[origIndex].mat_nr;
 -
                edgeNum += numFinalEdges;
        }
  
 -      if(useSubsurfUv) {
 -              CustomData *fdata = &ccgdm->dm.faceData;
 -              CustomData *dmfdata = &dm->faceData;
 -              int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE);
 -              int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE);
 -
 -              for (i=0; i<numlayer && i<dmnumlayer; i++)
 -                      set_subsurf_uv(ss, dm, &ccgdm->dm, i);
 -      }
 -
 -      edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "edgeFlags");
 -
        for(index = 0; index < totedge; ++index) {
                CCGEdge *e = ccgdm->edgeMap[index].edge;
                int numFinalEdges = edgeSize - 1;
 +              int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
                int x;
                int vertIdx[2];
                int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
                ccgdm->edgeMap[index].startVert = vertNum;
                ccgdm->edgeMap[index].startEdge = edgeNum;
  
 +              if(edgeIdx >= 0 && edgeFlags)
 +                      edgeFlags[edgeIdx] = medge[edgeIdx].flag;
 +
                /* set the edge base vert */
                *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
  
                        w[1] = (float) x / (edgeSize - 1);
                        w[0] = 1 - w[1];
                        DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum);
 +                      if (vertOrigIndex) {
 +                              *vertOrigIndex = ORIGINDEX_NONE;
 +                              ++vertOrigIndex;
 +                      }
                        ++vertNum;
                }
  
 -              edgeFlags[index]= medge[edgeIdx].flag;
 +              for(i = 0; i < numFinalEdges; ++i) {
 +                      if (has_edge_origindex) {
 +                              *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
 +                                               CD_ORIGINDEX) = mapIndex;
 +                      }
 +              }
  
                edgeNum += numFinalEdges;
        }
  
        for(index = 0; index < totvert; ++index) {
                CCGVert *v = ccgdm->vertMap[index].vert;
 -              int vertIdx;
 +              int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v);
 +              int vidx;
  
 -              vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 +              vidx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
  
                ccgdm->vertMap[index].startVert = vertNum;
  
                /* set the vert base vert */
                *((int*) ccgSubSurf_getVertUserData(ss, v)) = vertNum;
  
 -              DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1);
 +              DM_copy_vert_data(dm, &ccgdm->dm, vidx, vertNum, 1);
  
 +              if (vertOrigIndex) {
 +                      *vertOrigIndex = mapIndex;
 +                      ++vertOrigIndex;
 +              }
                ++vertNum;
        }
  
 -      MEM_freeN(qweight);
 -      MEM_freeN(tweight);
 +      ccgdm->dm.numVertData = vertNum;
 +      ccgdm->dm.numEdgeData = edgeNum;
 +      ccgdm->dm.numFaceData = faceNum;
 +      ccgdm->dm.numLoopData = loopindex2;
 +      ccgdm->dm.numPolyData = faceNum;
 +
 +      BLI_array_free(vertidx);
 +      BLI_array_free(loopidx);
 +      free_ss_weights(&wtable);
  
        return ccgdm;
  }
@@@ -3004,7 -2616,7 +3004,7 @@@ struct DerivedMesh *subsurf_make_derive
        int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
        int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
        int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
 -      CCGDerivedMesh *result;
 +      CCGDerivedMesh *result = NULL;
  
        if(forEditMode) {
                int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels;
  
                result->freeSS = 1;
        } else {
 -              int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
 +              int useIncremental = 1; //(smd->flags & eSubsurfModifierFlag_Incremental);
                int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
                int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels;
                CCGSubSurf *ss;
                        smd->mCache = ss = _getSubSurf(smd->mCache, levels,
                                                                                   useAging, 0, useSimple);
  
 -                      ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
 +                      if (!ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple)) {
 +                              //ccgSubSurf_free(smd->mCache);
 +                              smd->mCache = ss = _getSubSurf(NULL, levels,
 +                                                                                         useAging, 0, useSimple);
 +                              
 +                              ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
 +      
 +                      }
  
                        result = getCCGDerivedMesh(smd->mCache,
                                                                           drawInteriorEdges,
                                result->freeSS = 1;
                }
        }
 -
 -      return (DerivedMesh*)result;
 +      
 +      return (DerivedMesh *)result;
  }
  
  void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) 
index a16c900c1b6f3512802e8459f592d983e5900bfd,566ff09c366223988470dfdeb5f4789ed0eb1645..d8dfec82e15db699c53c177058d404da01044621
@@@ -2126,7 -2126,7 +2126,7 @@@ typedef struct UndoArmature 
        ListBase lb;
  } UndoArmature;
  
 -static void undoBones_to_editBones(void *uarmv, void *armv)
 +static void undoBones_to_editBones(void *uarmv, void *armv, void *UNUSED(data))
  {
        UndoArmature *uarm= uarmv;
        bArmature *arm= armv;
        }
  }
  
 -static void *editBones_to_undoBones(void *armv)
 +static void *editBones_to_undoBones(void *armv, void *UNUSED(obdata))
  {
        bArmature *arm= armv;
        UndoArmature *uarm;
@@@ -4298,7 -4298,7 +4298,7 @@@ int ED_do_pose_selectbuffer(Scene *scen
                 * note, special exception for armature mode so we can do multi-select
                 * we could check for multi-select explicitly but think its fine to
                 * always give pradictable behavior in weight paint mode - campbell */
-               if (!(extend) || (base->object != ob_act && !(ob_act->mode & OB_MODE_WEIGHT_PAINT))) {
+               if (!(extend) || ((ob_act && ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0)) {
                        ED_pose_deselectall(ob, 0);
                        nearBone->flag |= (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
                        arm->act_bone= nearBone;
@@@ -4524,8 -4524,7 +4524,8 @@@ static void envelope_bone_weighting(Obj
  
        /* for each vertex in the mesh */
        for (i=0; i < mesh->totvert; i++) {
 -              iflip = (dgroupflip)? mesh_get_x_mirror_vert(ob, i): 0;
 +              /*BMESH_TODO*/
 +              iflip = 0; //(dgroupflip)? mesh_get_x_mirror_vert(ob, i): 0;
                
                /* for each skinnable bone */
                for (j=0; j < numbones; ++j) {
@@@ -4718,7 -4717,7 +4718,7 @@@ static void add_verts_to_dgroups(Report
        }
  
        /* only generated in some cases but can call anyway */
 -      mesh_octree_table(ob, NULL, NULL, 'e');
 +      //BMESH_TODO mesh_octree_table(ob, NULL, NULL, 'e');
  
        /* free the memory allocated */
        MEM_freeN(bonelist);
index 9b7e697f7d6be0444053a1a92265bcb4d324bb0f,37abf01b0da10bdbabe4d32546d4b83db39d06fc..b93c03f1f89cd3dae9d12408e071d3810d243b87
@@@ -34,7 -34,6 +34,7 @@@
  
  #include "MEM_guardedalloc.h"
  
 +#include "BLI_utildefines.h"
  #include "BLI_blenlib.h"
  #include "BLI_math.h"
  #include "BLI_edgehash.h"
@@@ -47,7 -46,6 +47,7 @@@
  #include "DNA_scene_types.h"
  #include "DNA_screen_types.h"
  #include "DNA_view3d_types.h"
 +#include "DNA_windowmanager_types.h"
  #include "DNA_object_types.h"
  
  #include "BKE_DerivedMesh.h"
@@@ -56,7 -54,6 +56,7 @@@
  #include "BKE_material.h"
  #include "BKE_paint.h"
  #include "BKE_property.h"
 +#include "BKE_tessmesh.h"
  
  
  #include "BIF_gl.h"
@@@ -365,7 -362,7 +365,7 @@@ static void draw_textured_end(void
        glPopMatrix();
  }
  
 -static int draw_tface__set_draw_legacy(MTFace *tface, MCol *mcol, int matnr)
 +static int draw_tface__set_draw_legacy(MTFace *tface, int has_vcol, int matnr)
  {
        Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
        int validtexture=0;
        } else if (ma && ma->shade_flag&MA_OBCOLOR) {
                glColor3ubv(Gtexdraw.obcol);
                return 2; /* Don't set color */
 -      } else if (!mcol) {
 +      } else if (!has_vcol) {
                if (tface) glColor3f(1.0, 1.0, 1.0);
                else {
                        if(ma) {
                return 1; /* Set color from mcol */
        }
  }
 -static int draw_tface__set_draw(MTFace *tface, MCol *mcol, int matnr)
 +static int draw_tface__set_draw(MTFace *tface, int has_vcol, int matnr)
  {
        Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
  
                return 2; /* Don't set color */
        } else if (tface && tface->mode&TF_OBCOL) {
                return 2; /* Don't set color */
 -      } else if (!mcol) {
 +      } else if (!has_vcol) {
                return 1; /* Don't set color */
        } else {
                return 1; /* Set color from mcol */
  static void add_tface_color_layer(DerivedMesh *dm)
  {
        MTFace *tface = DM_get_face_data_layer(dm, CD_MTFACE);
 -      MFace *mface = DM_get_face_data_layer(dm, CD_MFACE);
 +      MFace *mface = dm->getTessFaceArray(dm);
        MCol *finalCol;
        int i,j;
 -      MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
 +      MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL);
        if(!mcol)
 -              mcol = dm->getFaceDataArray(dm, CD_MCOL);
 +              mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
  
 -      finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumFaces(dm),"add_tface_color_layer");
 -      for(i=0;i<dm->getNumFaces(dm);i++) {
 +      finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumTessFaces(dm),"add_tface_color_layer");
 +      for(i=0;i<dm->getNumTessFaces(dm);i++) {
                Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
  
                if (ma && (ma->game.flag&GEMAT_INVISIBLE)) {
  static int draw_tface_mapped__set_draw(void *userData, int index)
  {
        Mesh *me = (Mesh*)userData;
 -      MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
 -      MFace *mface = &me->mface[index];
 -      MCol *mcol = (me->mcol)? &me->mcol[index]: NULL;
 -      const int matnr = mface->mat_nr;
 -      if (mface->flag & ME_HIDE) return 0;
 -      return draw_tface__set_draw(tface, mcol, matnr);
 +      MTexPoly *tpoly = (me->mtpoly)? &me->mtpoly[index]: NULL;
 +      MPoly *mpoly = (me->mpoly)? &me->mpoly[index]: NULL;
 +      MTFace mtf;
 +      int has_vcol= (me->mcol != NULL);
 +      int matnr = me->mpoly[index].mat_nr;
 +
 +      if (mpoly && mpoly->flag&ME_HIDE) return 0;
 +
 +      memset(&mtf, 0, sizeof(mtf));
 +      if (tpoly) {
 +              mtf.flag = tpoly->flag;
 +              mtf.tpage = tpoly->tpage;
 +              mtf.transp = tpoly->transp;
 +              mtf.mode = tpoly->mode;
 +              mtf.tile = tpoly->tile;
 +              mtf.unwrap = tpoly->unwrap;
 +      }
 +
 +      return draw_tface__set_draw(&mtf, has_vcol, matnr);
  }
  
  static int draw_em_tf_mapped__set_draw(void *userData, int index)
  {
 -      EditMesh *em = userData;
 -      EditFace *efa= EM_get_face_for_index(index);
 -      MTFace *tface;
 -      MCol *mcol;
 +      BMEditMesh *em = userData;
 +      BMFace *efa= EDBM_get_face_for_index(em, index);
 +      MTexPoly *tpoly;
 +      MTFace mtf;
 +      int has_vcol;
        int matnr;
  
 -      if (efa->h)
 +      if (efa==NULL || BM_TestHFlag(efa, BM_HIDDEN))
                return 0;
  
 -      tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 -      mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
 +      tpoly = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
 +      has_vcol = CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
        matnr = efa->mat_nr;
  
 -      return draw_tface__set_draw_legacy(tface, mcol, matnr);
 +      memset(&mtf, 0, sizeof(mtf));
 +
 +      if (tpoly) {
 +              mtf.flag = tpoly->flag;
 +              mtf.tpage = tpoly->tpage;
 +              mtf.transp = tpoly->transp;
 +              mtf.mode = tpoly->mode;
 +              mtf.tile = tpoly->tile;
 +              mtf.unwrap = tpoly->unwrap;
 +      }
 +
 +      return draw_tface__set_draw_legacy(&mtf, has_vcol, matnr);
  }
  
  static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
  {
        Mesh *me = (Mesh*)userData;
-       Material *ma;
  
        if (me->mface) {
-               int matnr = me->mface[index].mat_nr;
-               ma = me->mat[matnr];
-       }
+               short matnr= me->mface[index].mat_nr;
+               Material *ma= me->mat[matnr];
  
-       if ( ma && (ma->game.flag & GEMAT_INVISIBLE)) {
-               return 0;
+               if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
+                       return 0;
+               }
        }
  
        *drawSmooth_r = 1;
@@@ -661,7 -632,7 +660,7 @@@ void draw_mesh_textured(Scene *scene, V
        glColor4f(1.0f,1.0f,1.0f,1.0f);
  
        if(ob->mode & OB_MODE_EDIT) {
 -              dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, me->edit_mesh);
 +              dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, me->edit_btmesh);
        }
        else if(faceselect) {
                if(ob->mode & OB_MODE_WEIGHT_PAINT)
index 7dc4112d7296bc3c3d338e03dd55598598ba90ab,d2c7ae337298ec8dbb3628180fc650c42d1ea7ea..f0db5920a0df47725e39ab1a1b75dcbcc829ca42
@@@ -1,5 -1,5 +1,5 @@@
  /*
 - * $Id$
 + * $Id: view3d_select.c 35106 2011-02-23 10:52:22Z jesterking $
   *
   * ***** BEGIN GPL LICENSE BLOCK *****
   *
@@@ -62,7 -62,7 +62,7 @@@
  #include "BKE_context.h"
  #include "BKE_paint.h"
  #include "BKE_armature.h"
 -
 +#include "BKE_tessmesh.h"
  
  #include "BIF_gl.h"
  #include "BIF_glutil.h"
@@@ -161,49 -161,43 +161,49 @@@ void view3d_get_transformation(ARegion 
  
  /* local prototypes */
  
 -static void EM_backbuf_checkAndSelectVerts(EditMesh *em, int select)
 +static void EDBM_backbuf_checkAndSelectVerts(BMEditMesh *em, int select)
  {
 -      EditVert *eve;
 -      int index= em_wireoffs;
 +      BMVert *eve;
 +      BMIter iter;
 +      int index= bm_wireoffs;
  
 -      for(eve= em->verts.first; eve; eve= eve->next, index++) {
 -              if(eve->h==0) {
 -                      if(EM_check_backbuf(index)) {
 -                              eve->f = select?(eve->f|1):(eve->f&~1);
 +      eve = BMIter_New(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
 +      for ( ; eve; eve=BMIter_Step(&iter), index++) {
 +              if(!BM_TestHFlag(eve, BM_HIDDEN)) {
 +                      if(EDBM_check_backbuf(index)) {
 +                              BM_Select_Vert(em->bm, eve, select);
                        }
                }
        }
  }
  
 -static void EM_backbuf_checkAndSelectEdges(EditMesh *em, int select)
 +static void EDBM_backbuf_checkAndSelectEdges(BMEditMesh *em, int select)
  {
 -      EditEdge *eed;
 -      int index= em_solidoffs;
 +      BMEdge *eed;
 +      BMIter iter;
 +      int index= bm_solidoffs;
  
 -      for(eed= em->edges.first; eed; eed= eed->next, index++) {
 -              if(eed->h==0) {
 -                      if(EM_check_backbuf(index)) {
 -                              EM_select_edge(eed, select);
 +      eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
 +      for ( ; eed; eed=BMIter_Step(&iter), index++) {
 +              if(!BM_TestHFlag(eed, BM_HIDDEN)) {
 +                      if(EDBM_check_backbuf(index)) {
 +                              BM_Select_Edge(em->bm, eed, select);
                        }
                }
        }
  }
  
 -static void EM_backbuf_checkAndSelectFaces(EditMesh *em, int select)
 +static void EDBM_backbuf_checkAndSelectFaces(BMEditMesh *em, int select)
  {
 -      EditFace *efa;
 +      BMFace *efa;
 +      BMIter iter;
        int index= 1;
  
 -      for(efa= em->faces.first; efa; efa= efa->next, index++) {
 -              if(efa->h==0) {
 -                      if(EM_check_backbuf(index)) {
 -                              EM_select_face_fgon(em, efa, select);
 +      efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
 +      for ( ; efa; efa=BMIter_Step(&iter), index++) {
 +              if(!BM_TestHFlag(efa, BM_HIDDEN)) {
 +                      if(EDBM_check_backbuf(index)) {
 +                              BM_Select_Face(em->bm, efa, select);
                        }
                }
        }
  
  
  /* object mode, EM_ prefix is confusing here, rename? */
 -static void EM_backbuf_checkAndSelectVerts_obmode(Mesh *me, int select)
 +static void EDBM_backbuf_checkAndSelectVerts_obmode(Mesh *me, int select)
  {
        MVert *mv = me->mvert;
        int a;
  
        if (mv) {
                for(a=1; a<=me->totvert; a++, mv++) {
 -                      if(EM_check_backbuf(a)) {
 +                      if(EDBM_check_backbuf(a)) {
                                if(!(mv->flag & ME_HIDE)) {
                                        mv->flag = select?(mv->flag|SELECT):(mv->flag&~SELECT);
                                }
        }
  }
  /* object mode, EM_ prefix is confusing here, rename? */
 -static void EM_backbuf_checkAndSelectTFaces(Mesh *me, int select)
 +
 +static void EDBM_backbuf_checkAndSelectTFaces(Mesh *me, int select)
  {
 -      MFace *mface = me->mface;
 +      MPoly *mpoly = me->mpoly;
        int a;
  
 -      if (mface) {
 -              for(a=1; a<=me->totface; a++, mface++) {
 -                      if(EM_check_backbuf(a)) {
 -                              mface->flag = select?(mface->flag|ME_FACE_SEL):(mface->flag&~ME_FACE_SEL);
 +      if (mpoly) {
 +              for(a=1; a<=me->totpoly; a++, mpoly++) {
 +                      if(EDBM_check_backbuf(a)) {
 +                              mpoly->flag = select?(mpoly->flag|ME_FACE_SEL):(mpoly->flag&~ME_FACE_SEL);
                        }
                }
        }
@@@ -456,39 -449,39 +456,39 @@@ static void lasso_select_boundbox(rcti 
        }
  }
  
 -static void do_lasso_select_mesh__doSelectVert(void *userData, EditVert *eve, int x, int y, int UNUSED(index))
 +static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index))
  {
        struct { ViewContext vc; rcti *rect; int (*mcords)[2], moves, select, pass, done; } *data = userData;
  
        if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
 -              eve->f = data->select?(eve->f|1):(eve->f&~1);
 +              BM_Select(data->vc.em->bm, eve, data->select);
        }
  }
 -static void do_lasso_select_mesh__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
 +static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index)
  {
        struct { ViewContext vc; rcti *rect; int (*mcords)[2], moves, select, pass, done; } *data = userData;
  
 -      if (EM_check_backbuf(em_solidoffs+index)) {
 +      if (EDBM_check_backbuf(bm_solidoffs+index)) {
                if (data->pass==0) {
                        if (    edge_fully_inside_rect(data->rect, x0, y0, x1, y1)  &&
                                        lasso_inside(data->mcords, data->moves, x0, y0) &&
                                        lasso_inside(data->mcords, data->moves, x1, y1)) {
 -                              EM_select_edge(eed, data->select);
 +                              BM_Select(data->vc.em->bm, eed, data->select);
                                data->done = 1;
                        }
                } else {
                        if (lasso_inside_edge(data->mcords, data->moves, x0, y0, x1, y1)) {
 -                              EM_select_edge(eed, data->select);
 +                              BM_Select(data->vc.em->bm, eed, data->select);
                        }
                }
        }
  }
 -static void do_lasso_select_mesh__doSelectFace(void *userData, EditFace *efa, int x, int y, int UNUSED(index))
 +static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index))
  {
        struct { ViewContext vc; rcti *rect; int (*mcords)[2], moves, select, pass, done; } *data = userData;
  
        if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
 -              EM_select_face_fgon(data->vc.em, efa, data->select);
 +              BM_Select(data->vc.em->bm, efa, data->select);
        }
  }
  
@@@ -502,7 -495,7 +502,7 @@@ static void do_lasso_select_mesh(ViewCo
        lasso_select_boundbox(&rect, mcords, moves);
        
        /* set editmesh */
 -      vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
 +      vc->em= ((Mesh *)vc->obedit->data)->edit_btmesh;
  
        data.vc= *vc;
        data.rect = &rect;
        data.pass = 0;
  
        if (extend == 0 && select)
 -              EM_deselect_all(vc->em);
 +              EDBM_clear_flag_all(vc->em, BM_SELECT);
  
         /* for non zbuf projections, dont change the GL state */
        ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
  
        glLoadMatrixf(vc->rv3d->viewmat);
 -      bbsel= EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
 +      bbsel= EDBM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
        
        if(ts->selectmode & SCE_SELECT_VERTEX) {
                if (bbsel) {
 -                      EM_backbuf_checkAndSelectVerts(vc->em, select);
 +                      EDBM_backbuf_checkAndSelectVerts(vc->em, select);
                }
                else {
                        mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, 1);
        
        if(ts->selectmode & SCE_SELECT_FACE) {
                if (bbsel) {
 -                      EM_backbuf_checkAndSelectFaces(vc->em, select);
 +                      EDBM_backbuf_checkAndSelectFaces(vc->em, select);
                }
                else {
                        mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data);
                }
        }
        
 -      EM_free_backbuf();
 -      EM_selectmode_flush(vc->em);    
 +      EDBM_free_backbuf();
 +      EDBM_selectmode_flush(vc->em);  
  }
  
  #if 0
@@@ -828,14 -821,14 +828,14 @@@ static void do_lasso_select_paintvert(V
  
        if(extend==0 && select)
                paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
 -      em_vertoffs= me->totvert+1;     /* max index array */
 +      bm_vertoffs= me->totvert+1;     /* max index array */
  
        lasso_select_boundbox(&rect, mcords, moves);
 -      EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
 +      EDBM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
  
 -      EM_backbuf_checkAndSelectVerts_obmode(me, select);
 +      EDBM_backbuf_checkAndSelectVerts_obmode(me, select);
  
 -      EM_free_backbuf();
 +      EDBM_free_backbuf();
  
        paintvert_flush_flags(ob);
  }
@@@ -851,14 -844,14 +851,14 @@@ static void do_lasso_select_paintface(V
        if(extend==0 && select)
                paintface_deselect_all_visible(ob, SEL_DESELECT, FALSE); /* flush selection at the end */
  
 -      em_vertoffs= me->totface+1;     /* max index array */
 +      bm_vertoffs= me->totpoly+1;     /* max index array */
  
        lasso_select_boundbox(&rect, mcords, moves);
 -      EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
 +      EDBM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
        
 -      EM_backbuf_checkAndSelectTFaces(me, select);
 +      EDBM_backbuf_checkAndSelectTFaces(me, select);
  
 -      EM_free_backbuf();
 +      EDBM_free_backbuf();
  
        paintface_flush_flags(ob);
  }
@@@ -1552,37 -1545,37 +1552,37 @@@ static int do_lattice_box_select(ViewCo
        return OPERATOR_FINISHED;
  }
  
 -static void do_mesh_box_select__doSelectVert(void *userData, EditVert *eve, int x, int y, int UNUSED(index))
 +static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index))
  {
        struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
  
        if (BLI_in_rcti(data->rect, x, y)) {
 -              eve->f = data->select?(eve->f|1):(eve->f&~1);
 +              BM_Select(data->vc.em->bm, eve, data->select);
        }
  }
 -static void do_mesh_box_select__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
 +static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index)
  {
        struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
  
 -      if(EM_check_backbuf(em_solidoffs+index)) {
 +      if(EDBM_check_backbuf(bm_solidoffs+index)) {
                if (data->pass==0) {
                        if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) {
 -                              EM_select_edge(eed, data->select);
 +                              BM_Select(data->vc.em->bm, eed, data->select);
                                data->done = 1;
                        }
                } else {
                        if (edge_inside_rect(data->rect, x0, y0, x1, y1)) {
 -                              EM_select_edge(eed, data->select);
 +                              BM_Select(data->vc.em->bm, eed, data->select);
                        }
                }
        }
  }
 -static void do_mesh_box_select__doSelectFace(void *userData, EditFace *efa, int x, int y, int UNUSED(index))
 +static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index))
  {
        struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
  
        if (BLI_in_rcti(data->rect, x, y)) {
 -              EM_select_face_fgon(data->vc.em, efa, data->select);
 +              BM_Select(data->vc.em->bm, efa, data->select);
        }
  }
  static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int extend)
        data.done = 0;
  
        if (extend == 0 && select)
 -              EM_deselect_all(vc->em);
 +              EDBM_clear_flag_all(vc->em, BM_SELECT);
  
        /* for non zbuf projections, dont change the GL state */
        ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
  
        glLoadMatrixf(vc->rv3d->viewmat);
 -      bbsel= EM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
 +      bbsel= EDBM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
  
        if(ts->selectmode & SCE_SELECT_VERTEX) {
                if (bbsel) {
 -                      EM_backbuf_checkAndSelectVerts(vc->em, select);
 +                      EDBM_backbuf_checkAndSelectVerts(vc->em, select);
                } else {
                        mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, 1);
                }
        
        if(ts->selectmode & SCE_SELECT_FACE) {
                if(bbsel) {
 -                      EM_backbuf_checkAndSelectFaces(vc->em, select);
 +                      EDBM_backbuf_checkAndSelectFaces(vc->em, select);
                } else {
                        mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data);
                }
        }
        
 -      EM_free_backbuf();
 +      EDBM_free_backbuf();
                
 -      EM_selectmode_flush(vc->em);
 +      EDBM_selectmode_flush(vc->em);
        
        return OPERATOR_FINISHED;
  }
@@@ -1869,7 -1862,7 +1869,7 @@@ static int view3d_borderselect_exec(bCo
        if(vc.obedit) {
                switch(vc.obedit->type) {
                case OB_MESH:
 -                      vc.em= ((Mesh *)vc.obedit->data)->edit_mesh;
 +                      vc.em= ((Mesh *)vc.obedit->data)->edit_btmesh;
                        ret= do_mesh_box_select(&vc, &rect, select, extend);
  //                    if (EM_texFaceCheck())
                        if(ret & OPERATOR_FINISHED) {
@@@ -1983,17 -1976,18 +1983,18 @@@ static int vertsel_vert_pick(struct bCo
  
  /* mouse selection in weight paint */
  /* gets called via generic mouse select operator */
int mouse_wp_select(bContext *C, const int mval[2], short extend, Object *obact, Mesh* me)
static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], short extend, Object *obact)
  {
+       Mesh* me= obact->data; /* already checked for NULL */
        unsigned int index = 0;
        MVert *mv;
        if(vertsel_vert_pick(C, me, mval, &index, 1)) {
                mv = me->mvert+index;
                if(extend) {
-                       mv->flag ^= 1;
+                       mv->flag ^= SELECT;
                } else {
                        paintvert_deselect_all_visible(obact, SEL_DESELECT, FALSE);
-                       mv->flag |= 1;
+                       mv->flag |= SELECT;
                }
                paintvert_flush_flags(obact);
                WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obact->data);
@@@ -2046,12 -2040,10 +2047,10 @@@ static int view3d_select_invoke(bContex
                return PE_mouse_particles(C, event->mval, extend);
        else if(obact && paint_facesel_test(obact))
                retval = paintface_mouse_select(C, obact, event->mval, extend);
-       
-       else if (paint_vertsel_test(obact)) {
-               retval = mouse_wp_select(C, event->mval, extend, obact, obact->data);
-       } else {
+       else if (paint_vertsel_test(obact))
+               retval = mouse_weight_paint_vertex_select(C, event->mval, extend, obact);
+       else
                retval = mouse_select(C, event->mval, extend, center, enumerate);
-       }
  
        /* passthrough allows tweaks
         * FINISHED to signal one operator worked
@@@ -2086,32 -2078,32 +2085,32 @@@ void VIEW3D_OT_select(wmOperatorType *o
  
  /* -------------------- circle select --------------------------------------------- */
  
 -static void mesh_circle_doSelectVert(void *userData, EditVert *eve, int x, int y, int UNUSED(index))
 +static void mesh_circle_doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index))
  {
        struct {ViewContext *vc; short select; int mval[2]; float radius; } *data = userData;
        int mx = x - data->mval[0], my = y - data->mval[1];
        float r = sqrt(mx*mx + my*my);
  
        if (r<=data->radius) {
 -              eve->f = data->select?(eve->f|1):(eve->f&~1);
 +              BM_Select(data->vc->em->bm, eve, data->select);
        }
  }
 -static void mesh_circle_doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index))
 +static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index))
  {
        struct {ViewContext *vc; short select; int mval[2]; float radius; } *data = userData;
  
        if (edge_inside_circle(data->mval[0], data->mval[1], (short) data->radius, x0, y0, x1, y1)) {
 -              EM_select_edge(eed, data->select);
 +              BM_Select(data->vc->em->bm, eed, data->select);
        }
  }
 -static void mesh_circle_doSelectFace(void *userData, EditFace *efa, int x, int y, int UNUSED(index))
 +static void mesh_circle_doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index))
  {
        struct {ViewContext *vc; short select; int mval[2]; float radius; } *data = userData;
        int mx = x - data->mval[0], my = y - data->mval[1];
        float r = sqrt(mx*mx + my*my);
        
        if (r<=data->radius) {
 -              EM_select_face_fgon(data->vc->em, efa, data->select);
 +              BM_Select(data->vc->em->bm, efa, data->select);
        }
  }
  
@@@ -2121,10 -2113,10 +2120,10 @@@ static void mesh_circle_select(ViewCont
        int bbsel;
        struct {ViewContext *vc; short select; int mval[2]; float radius; } data;
        
 -      bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
 +      bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
        ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
  
 -      vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
 +      vc->em= ((Mesh *)vc->obedit->data)->edit_btmesh;
  
        data.vc = vc;
        data.select = select;
  
        if(ts->selectmode & SCE_SELECT_VERTEX) {
                if(bbsel) {
 -                      EM_backbuf_checkAndSelectVerts(vc->em, select==LEFTMOUSE);
 +                      EDBM_backbuf_checkAndSelectVerts(vc->em, select==LEFTMOUSE);
                } else {
                        mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, 1);
                }
  
        if(ts->selectmode & SCE_SELECT_EDGE) {
                if (bbsel) {
 -                      EM_backbuf_checkAndSelectEdges(vc->em, select==LEFTMOUSE);
 +                      EDBM_backbuf_checkAndSelectEdges(vc->em, select==LEFTMOUSE);
                } else {
                        mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, 0);
                }
        
        if(ts->selectmode & SCE_SELECT_FACE) {
                if(bbsel) {
 -                      EM_backbuf_checkAndSelectFaces(vc->em, select==LEFTMOUSE);
 +                      EDBM_backbuf_checkAndSelectFaces(vc->em, select==LEFTMOUSE);
                } else {
                        mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data);
                }
        }
  
 -      EM_free_backbuf();
 -      EM_selectmode_flush(vc->em);
 +      EDBM_free_backbuf();
 +      EDBM_selectmode_flush(vc->em);
  }
  
  static void paint_facesel_circle_select(ViewContext *vc, int select, const int mval[2], float rad)
        int bbsel;
  
        if (me) {
 -              em_vertoffs= me->totface+1;     /* max index array */
 +              bm_vertoffs= me->totpoly+1;     /* max index array */
  
 -              bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
 -              EM_backbuf_checkAndSelectTFaces(me, select==LEFTMOUSE);
 -              EM_free_backbuf();
 +              bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
 +              EDBM_backbuf_checkAndSelectTFaces(me, select==LEFTMOUSE);
 +              EDBM_free_backbuf();
        }
  }
  
@@@ -2183,11 -2175,11 +2182,11 @@@ static void paint_vertsel_circle_select
        int bbsel;
        /* struct {ViewContext *vc; short select; int mval[2]; float radius; } data = {NULL}; */ /* UNUSED */
        if (me) {
 -              em_vertoffs= me->totvert+1;     /* max index array */
 +              bm_vertoffs= me->totvert+1;     /* max index array */
  
 -              bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
 -              EM_backbuf_checkAndSelectVerts_obmode(me, select==LEFTMOUSE);
 -              EM_free_backbuf();
 +              bbsel= EDBM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0f));
 +              EDBM_backbuf_checkAndSelectVerts_obmode(me, select==LEFTMOUSE);
 +              EDBM_free_backbuf();
  
                paintvert_flush_flags(ob);
        }