NLA SoC: Start of 'Meta' Strips
[blender.git] / source / blender / blenkernel / intern / subsurf_ccg.c
index 9c9c4a884f480ea6d3c46f1f8b11ca6784f3fa74..15969fc9ab91b810b26735afb4f743a861e46018 100644 (file)
@@ -1,15 +1,12 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,7 +24,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #include <stdlib.h>
@@ -44,7 +41,6 @@
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
-#include "BKE_bad_level_calls.h"
 #include "BKE_cdderivedmesh.h"
 #include "BKE_customdata.h"
 #include "BKE_DerivedMesh.h"
@@ -52,6 +48,7 @@
 #include "BKE_utildefines.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
+#include "BKE_multires.h"
 #include "BKE_scene.h"
 #include "BKE_subsurf.h"
 
 
 #include "BIF_gl.h"
 
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_material.h"
+
 #include "CCGSubSurf.h"
 
 typedef struct _VertData {
@@ -85,9 +86,9 @@ struct CCGDerivedMesh {
 
 typedef struct CCGDerivedMesh CCGDerivedMesh;
 
-static int ccgDM_getVertMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGVert *v);
-static int ccgDM_getEdgeMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGEdge *e);
-static int ccgDM_getFaceMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGFace *f);
+static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v);
+static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e);
+static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f);
 
 ///
 
@@ -160,8 +161,8 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAgin
 }
 
 static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) {
-       CCGVert *v0 = ccgSubSurf_getEdgeVert0(ss, e);
-       CCGVert *v1 = ccgSubSurf_getEdgeVert1(ss, e);
+       CCGVert *v0 = ccgSubSurf_getEdgeVert0(e);
+       CCGVert *v1 = ccgSubSurf_getEdgeVert1(e);
        int v0idx = *((int*) ccgSubSurf_getVertUserData(ss, v0));
        int v1idx = *((int*) ccgSubSurf_getVertUserData(ss, v1));
        int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
@@ -176,7 +177,7 @@ static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) {
 }
 static 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(ss, f);
+       int numVerts = ccgSubSurf_getFaceNumVerts(f);
 
        if (x==gridSize-1 && y==gridSize-1) {
                CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
@@ -185,7 +186,7 @@ static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edg
                CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
                CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, S);
                int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
-               if (v==ccgSubSurf_getEdgeVert0(ss, e)) {
+               if (v==ccgSubSurf_getEdgeVert0(e)) {
                        return edgeBase + (gridSize-1-y)-1;
                } else {
                        return edgeBase + (edgeSize-2-1)-((gridSize-1-y)-1);
@@ -194,7 +195,7 @@ static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edg
                CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
                CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, (S+numVerts-1)%numVerts);
                int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
-               if (v==ccgSubSurf_getEdgeVert0(ss, e)) {
+               if (v==ccgSubSurf_getEdgeVert0(e)) {
                        return edgeBase + (gridSize-1-x)-1;
                } else {
                        return edgeBase + (edgeSize-2-1)-((gridSize-1-x)-1);
@@ -224,7 +225,7 @@ static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGV
                                break;
                }
 
-               fverts[j]= (CCGVertHDL)(nv->f*4 + nv->tfindex);
+               fverts[j]= SET_INT_IN_POINTER(nv->f*4 + nv->tfindex);
        }
 }
 
@@ -241,7 +242,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
        EdgeHash *ehash;
        float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
 
-       limit[0]= limit[1]= 0.0001f;
+       limit[0]= limit[1]= STD_UV_CONNECT_LIMIT;
        vmap= make_uv_vert_map(mface, tface, totface, totvert, 0, limit);
        if (!vmap)
                return 0;
@@ -262,7 +263,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
                for (v=get_uv_map_vert(vmap, i); v; v=v->next) {
                        if (v->separate) {
                                CCGVert *ssv;
-                               CCGVertHDL vhdl = (CCGVertHDL)(v->f*4 + v->tfindex);
+                               CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex);
                                float uv[3];
 
                                uv[0]= (tface+v->f)->uv[v->tfindex][0];
@@ -280,26 +281,26 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
        for (i=0; i<totface; i++) {
                MFace *mf = &((MFace*) mface)[i];
                int nverts= mf->v4? 4: 3;
-               CCGFace *origf= ccgSubSurf_getFace(origss, (CCGFaceHDL)i);
+               CCGFace *origf= ccgSubSurf_getFace(origss, SET_INT_IN_POINTER(i));
                unsigned int *fv = &mf->v1;
 
                get_face_uv_map_vert(vmap, mf, i, fverts);
 
                for (j=0; j<nverts; j++) {
-                       int v0 = (int)fverts[j];
-                       int v1 = (int)fverts[(j+1)%nverts];
+                       int v0 = GET_INT_FROM_POINTER(fverts[j]);
+                       int v1 = GET_INT_FROM_POINTER(fverts[(j+1)%nverts]);
                        MVert *mv0 = mvert + *(fv+j);
                        MVert *mv1 = mvert + *(fv+((j+1)%nverts));
 
                        if (!BLI_edgehash_haskey(ehash, v0, v1)) {
                                CCGEdge *e, *orige= ccgSubSurf_getFaceEdge(origss, origf, j);
-                               CCGEdgeHDL ehdl= (CCGEdgeHDL)(i*4 + j);
+                               CCGEdgeHDL ehdl= SET_INT_IN_POINTER(i*4 + j);
                                float crease;
 
                                if ((mv0->flag&mv1->flag) & ME_VERT_MERGED)
                                        crease = creaseFactor;
                                else
-                                       crease = ccgSubSurf_getEdgeCrease(origss, orige);
+                                       crease = ccgSubSurf_getEdgeCrease(orige);
 
                                ccgSubSurf_syncEdge(ss, ehdl, fverts[j], fverts[(j+1)%nverts], crease, &e);
                                BLI_edgehash_insert(ehash, v0, v1, NULL);
@@ -316,7 +317,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
                CCGFace *f;
 
                get_face_uv_map_vert(vmap, mf, i, fverts);
-               ccgSubSurf_syncFace(ss, (CCGFaceHDL)i, nverts, fverts, &f);
+               ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), nverts, fverts, &f);
        }
 
        free_uv_vert_map(vmap);
@@ -358,7 +359,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
        fi = ccgSubSurf_getFaceIterator(uvss);
        for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
-               faceMap[(int) ccgSubSurf_getFaceFaceHandle(uvss, f)] = f;
+               faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(uvss, f))] = f;
        }
        ccgFaceIterator_free(fi);
 
@@ -367,7 +368,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
 
        for(index = 0; index < totface; index++) {
                CCGFace *f = faceMap[index];
-               int numVerts = ccgSubSurf_getFaceNumVerts(uvss, f);
+               int numVerts = ccgSubSurf_getFaceNumVerts(f);
 
                for (S=0; S<numVerts; S++) {
                        VertData *faceGridData= ccgSubSurf_getFaceGridDataArray(uvss, f, S);
@@ -398,12 +399,12 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result,
 static unsigned int ss_getEdgeFlags(CCGSubSurf *ss, CCGEdge *e, int ssFromEditmesh, DispListMesh *dlm, MEdge *medge, MTFace *tface)
 {
        unsigned int flags = 0;
-       int N = ccgSubSurf_getEdgeNumFaces(ss, e);
+       int N = ccgSubSurf_getEdgeNumFaces(e);
 
        if (!N) flags |= ME_LOOSEEDGE;
 
        if (ssFromEditmesh) {
-               EditEdge *eed = ccgSubSurf_getEdgeEdgeHandle(ss, e);
+               EditEdge *eed = ccgSubSurf_getEdgeEdgeHandle(e);
 
                flags |= ME_EDGEDRAW|ME_EDGERENDER;
                if (eed->seam) {
@@ -469,9 +470,9 @@ static void calc_ss_weights(int gridFaces,
        }
 }
 
-DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
+static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
                                  int drawInteriorEdges, int useSubsurfUv,
-                                 DerivedMesh *dm)
+                                 DerivedMesh *dm, MultiresSubsurf *ms)
 {
        DerivedMesh *result;
        int edgeSize = ccgSubSurf_getEdgeSize(ss);
@@ -479,7 +480,6 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
        int gridFaces = gridSize - 1;
        int edgeBase, faceBase;
        int i, j, k, S, x, y, index;
-       int vertBase = 0;
        CCGVertIterator *vi;
        CCGEdgeIterator *ei;
        CCGFaceIterator *fi;
@@ -502,7 +502,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
        for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
 
-               vertMap2[(int) ccgSubSurf_getVertVertHandle(ss, v)] = v;
+               vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v;
        }
        ccgVertIterator_free(vi);
 
@@ -512,7 +512,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
        for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
 
-               edgeMap2[(int) ccgSubSurf_getEdgeEdgeHandle(ss, e)] = e;
+               edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
        }
 
        totface = ccgSubSurf_getNumFaces(ss);
@@ -521,18 +521,25 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
        for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
 
-               faceMap2[(int) ccgSubSurf_getFaceFaceHandle(ss, f)] = f;
+               faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))] = f;
        }
        ccgFaceIterator_free(fi);
 
-       if(dm) {
-               result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss),
-                                           ccgSubSurf_getNumFinalEdges(ss),
-                                           ccgSubSurf_getNumFinalFaces(ss));
-       } else {
-               result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss),
-                                 ccgSubSurf_getNumFinalEdges(ss),
-                                 ccgSubSurf_getNumFinalFaces(ss));
+       if(ms) {
+               result = MultiresDM_new(ms, dm, ccgSubSurf_getNumFinalVerts(ss),
+                                       ccgSubSurf_getNumFinalEdges(ss),
+                                       ccgSubSurf_getNumFinalFaces(ss));
+       }
+       else {
+               if(dm) {
+                       result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss),
+                                                   ccgSubSurf_getNumFinalEdges(ss),
+                                                   ccgSubSurf_getNumFinalFaces(ss));
+               } else {
+                       result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss),
+                                         ccgSubSurf_getNumFinalEdges(ss),
+                                         ccgSubSurf_getNumFinalFaces(ss));
+               }
        }
 
        // load verts
@@ -542,27 +549,28 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
 
        for(index = 0; index < totface; index++) {
                CCGFace *f = faceMap2[index];
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
                FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
                int vertIdx[4];
 
                for(S = 0; S < numVerts; S++) {
                        CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
 
-                       vertIdx[S] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+                       vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
                }
 
                DM_interp_vert_data(dm, result, vertIdx, weight[0][0], numVerts, i);
-               VecCopyf(mvert->co, ccgSubSurf_getFaceCenterData(ss, f));
+               VecCopyf(mvert->co, ccgSubSurf_getFaceCenterData(f));
                *origIndex = ORIGINDEX_NONE;
                ++mvert;
                ++origIndex;
                i++;
-               
+
                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;
+
                        for(x = 1; x < gridFaces; x++) {
                                float w[4];
                                w[prevS]  = weight[x][0][0];
@@ -572,6 +580,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
                                DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i);
                                VecCopyf(mvert->co,
                                         ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
+
                                *origIndex = ORIGINDEX_NONE;
                                ++mvert;
                                ++origIndex;
@@ -583,6 +592,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
                        int prevS = (S - 1 + numVerts) % numVerts;
                        int nextS = (S + 1) % numVerts;
                        int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+
                        for(y = 1; y < gridFaces; y++) {
                                for(x = 1; x < gridFaces; x++) {
                                        float w[4];
@@ -612,10 +622,10 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
                int vertIdx[2];
 
                CCGVert *v;
-               v = ccgSubSurf_getEdgeVert0(ss, e);
-               vertIdx[0] = (int)ccgSubSurf_getVertVertHandle(ss, v);
-               v = ccgSubSurf_getEdgeVert1(ss, e);
-               vertIdx[1] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+               v = ccgSubSurf_getEdgeVert0(e);
+               vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+               v = ccgSubSurf_getEdgeVert1(e);
+               vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 
                for(x = 1; x < edgeSize - 1; x++) {
                        float w[2];
@@ -633,18 +643,17 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
                edgeBase += edgeSize-2;
        }
 
-       vertBase = i;
        for(index = 0; index < totvert; index++) {
                CCGVert *v = vertMap2[index];
                int vertIdx;
 
-               vertIdx = (int)ccgSubSurf_getVertVertHandle(ss, v);
+               vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 
                DM_copy_vert_data(dm, result, vertIdx, i, 1);
                VecCopyf(mvert->co, ccgSubSurf_getVertData(ss, v));
 
                *((int*)ccgSubSurf_getVertUserData(ss, v)) = i;
-               *origIndex = ccgDM_getVertMapIndex(NULL, ss, v);
+               *origIndex = ccgDM_getVertMapIndex(ss, v);
                ++mvert;
                ++origIndex;
                i++;
@@ -657,7 +666,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
 
        for(index = 0; index < totface; index++) {
                CCGFace *f = faceMap2[index];
-               int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int numVerts = ccgSubSurf_getFaceNumVerts(f);
 
                for(k = 0; k < numVerts; k++) {
                        for(x = 0; x < gridFaces; x++) {
@@ -699,9 +708,10 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
        for(index = 0; index < totedge; index++) {
                CCGEdge *e = edgeMap2[index];
                unsigned int flags = 0;
-               int edgeIdx = (int)ccgSubSurf_getEdgeEdgeHandle(ss, e);
+               char bweight = 0;
+               int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
 
-               if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE;
+               if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
 
 
                if(edgeIdx != -1 && dm) {
@@ -709,13 +719,15 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
                        dm->getEdge(dm, edgeIdx, &origMed);
 
                        flags |= origMed.flag;
+                       bweight = origMed.bweight;
                }
 
                for(x = 0; x < edgeSize - 1; x++) {
                        med->v1 = getEdgeIndex(ss, e, x, edgeSize);
                        med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize);
                        med->flag = flags;
-                       *origIndex = ccgDM_getEdgeMapIndex(NULL, ss, e);
+                       med->bweight = bweight;
+                       *origIndex = ccgDM_getEdgeMapIndex(ss, e);
                        ++med;
                        ++origIndex;
                        i++;
@@ -729,11 +741,11 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
 
        for(index = 0; index < totface; index++) {
                CCGFace *f = faceMap2[index];
-               int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int numVerts = ccgSubSurf_getFaceNumVerts(f);
                int mat_nr;
                int flag;
-               int mapIndex = ccgDM_getFaceMapIndex(NULL, ss, f);
-               int faceIdx = (int)ccgSubSurf_getFaceFaceHandle(ss, f);
+               int mapIndex = ccgDM_getFaceMapIndex(ss, f);
+               int faceIdx = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
 
                if(!ssFromEditmesh) {
                        MFace origMFace;
@@ -837,9 +849,9 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
                CCGVert *v;
 
                if(vertexCos) {
-                       ccgSubSurf_syncVert(ss, (CCGVertHDL)i, vertexCos[i], 0, &v);
+                       ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), vertexCos[i], 0, &v);
                } else {
-                       ccgSubSurf_syncVert(ss, (CCGVertHDL)i, mv->co, 0, &v);
+                       ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), mv->co, 0, &v);
                }
 
                ((int*)ccgSubSurf_getVertUserData(ss, v))[1] = *index;
@@ -854,8 +866,8 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
                crease = useFlatSubdiv ? creaseFactor :
                                         me->crease * creaseFactor / 255.0f;
 
-               ccgSubSurf_syncEdge(ss, (CCGEdgeHDL)i, (CCGVertHDL)me->v1,
-                                   (CCGVertHDL)me->v2, crease, &e);
+               ccgSubSurf_syncEdge(ss, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(me->v1),
+                                   SET_INT_IN_POINTER(me->v2), crease, &e);
 
                ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = *index;
        }
@@ -865,22 +877,22 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
        for (i = 0; i < totface; i++, mf++, index++) {
                CCGFace *f;
 
-               fVerts[0] = (CCGVertHDL) mf->v1;
-               fVerts[1] = (CCGVertHDL) mf->v2;
-               fVerts[2] = (CCGVertHDL) mf->v3;
-               fVerts[3] = (CCGVertHDL) mf->v4;
+               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);
 
                // 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, (CCGFaceHDL)i, fVerts[3] ? 4 : 3,
+               if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fVerts[3] ? 4 : 3,
                                       fVerts, &f) == eCCGError_InvalidValue) {
                        static int hasGivenError = 0;
 
                        if(!hasGivenError) {
-                               error("Unrecoverable error in SubSurf calculation,"
-                                     " mesh is inconsistent.");
+                               //XXX error("Unrecoverable error in SubSurf calculation,"
+                               //      " mesh is inconsistent.");
 
                                hasGivenError = 1;
                        }
@@ -896,15 +908,15 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
 
 /***/
 
-static int ccgDM_getVertMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGVert *v) {
+static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v) {
        return ((int*) ccgSubSurf_getVertUserData(ss, v))[1];
 }
 
-static int ccgDM_getEdgeMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGEdge *e) {
+static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e) {
        return ((int*) ccgSubSurf_getEdgeUserData(ss, e))[1];
 }
 
-static int ccgDM_getFaceMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGFace *f) {
+static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f) {
        return ((int*) ccgSubSurf_getFaceUserData(ss, f))[1];
 }
 
@@ -937,7 +949,7 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
 
        for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
 
                for (S=0; S<numVerts; S++) {
                        VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
@@ -976,7 +988,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
 
        memset(mv, 0, sizeof(*mv));
 
-       if(vertNum < ccgdm->edgeMap[0].startVert) {
+       if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
                /* this vert comes from face data */
                int lastface = ccgSubSurf_getNumFaces(ss) - 1;
                CCGFace *f;
@@ -993,7 +1005,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
                        ++i;
 
                f = ccgdm->faceMap[i].face;
-               numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               numVerts = ccgSubSurf_getFaceNumVerts(f);
 
                gridSideVerts = gridSize - 2;
                gridInternalVerts = gridSideVerts * gridSideVerts;
@@ -1003,7 +1015,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
 
                offset = vertNum - ccgdm->faceMap[i].startVert;
                if(offset < 1) {
-                       VecCopyf(mv->co, ccgSubSurf_getFaceCenterData(ss, f));
+                       VecCopyf(mv->co, ccgSubSurf_getFaceCenterData(f));
                } else if(offset < gridSideEnd) {
                        offset -= 1;
                        grid = offset / gridSideVerts;
@@ -1017,7 +1029,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
                        x = offset % gridSideVerts + 1;
                        VecCopyf(mv->co, ccgSubSurf_getFaceGridData(ss, f, grid, x, y));
                }
-       } else if(vertNum < ccgdm->vertMap[0].startVert) {
+       } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
                /* this vert comes from edge data */
                CCGEdge *e;
                int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
@@ -1065,7 +1077,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
                        ++i;
 
                f = ccgdm->faceMap[i].face;
-               numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               numVerts = ccgSubSurf_getFaceNumVerts(f);
 
                gridSideEdges = gridSize - 1;
                gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; 
@@ -1101,7 +1113,7 @@ static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
 
                e = ccgdm->edgeMap[i].edge;
 
-               if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE;
+               if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
 
                x = edgeNum - ccgdm->edgeMap[i].startEdge;
 
@@ -1143,7 +1155,7 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
                ++i;
 
        f = ccgdm->faceMap[i].face;
-       numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+       numVerts = ccgSubSurf_getFaceNumVerts(f);
 
        offset = faceNum - ccgdm->faceMap[i].startFace;
        grid = offset / gridFaces;
@@ -1173,9 +1185,9 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
        totface = ccgSubSurf_getNumFaces(ss);
        for(index = 0; index < totface; index++) {
                CCGFace *f = ccgdm->faceMap[index].face;
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
 
-               VecCopyf(mvert[i++].co, ccgSubSurf_getFaceCenterData(ss, f));
+               VecCopyf(mvert[i++].co, ccgSubSurf_getFaceCenterData(f));
                
                for(S = 0; S < numVerts; S++) {
                        for(x = 1; x < gridSize - 1; x++) {
@@ -1228,7 +1240,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
        totface = ccgSubSurf_getNumFaces(ss);
        for(index = 0; index < totface; index++) {
                CCGFace *f = ccgdm->faceMap[index].face;
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
 
                for(S = 0; S < numVerts; S++) {
                        for(x = 0; x < gridSize - 1; x++) {
@@ -1272,9 +1284,9 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
                CCGEdge *e = ccgdm->edgeMap[index].edge;
                unsigned int flags = 0;
                int x;
-               int edgeIdx = (int)ccgSubSurf_getEdgeEdgeHandle(ss, e);
+               int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
 
-               if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE;
+               if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
 
                if(edgeFlags) {
                        if(edgeIdx != -1) {
@@ -1309,7 +1321,7 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
        totface = ccgSubSurf_getNumFaces(ss);
        for(index = 0; index < totface; index++) {
                CCGFace *f = ccgdm->faceMap[index].face;
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
                int mat_nr = 0;
                int flag = ME_SMOOTH; /* assume face is smooth by default */
 
@@ -1356,7 +1368,7 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
        for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
 
-               vertMap2[(int) ccgSubSurf_getVertVertHandle(ss, v)] = v;
+               vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v;
        }
        ccgVertIterator_free(vi);
 
@@ -1366,7 +1378,7 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
        for (i=0; !ccgEdgeIterator_isStopped(ei); i++,ccgEdgeIterator_next(ei)) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
 
-               edgeMap2[(int) ccgSubSurf_getEdgeEdgeHandle(ss, e)] = e;
+               edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
        }
 
        totface = ccgSubSurf_getNumFaces(ss);
@@ -1375,16 +1387,16 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
        for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
 
-               faceMap2[(int) ccgSubSurf_getFaceFaceHandle(ss, f)] = f;
+               faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))] = f;
        }
        ccgFaceIterator_free(fi);
 
        i = 0;
        for (index=0; index<totface; index++) {
                CCGFace *f = faceMap2[index];
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
 
-               VecCopyf(cos[i++], ccgSubSurf_getFaceCenterData(ss, f));
+               VecCopyf(cos[i++], ccgSubSurf_getFaceCenterData(f));
                
                for (S=0; S<numVerts; S++) {
                        for (x=1; x<gridSize-1; x++) {
@@ -1426,7 +1438,7 @@ static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData
        for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
                VertData *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
-               int index = ccgDM_getVertMapIndex(ccgdm, ccgdm->ss, v);
+               int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
 
                if (index!=-1)
                        func(userData, index, vd->co, vd->no, NULL);
@@ -1443,7 +1455,7 @@ static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData
        for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
                VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
-               int index = ccgDM_getEdgeMapIndex(ccgdm, ss, e);
+               int index = ccgDM_getEdgeMapIndex(ss, e);
 
                if (index!=-1) {
                        for (i=0; i<edgeSize-1; i++)
@@ -1484,9 +1496,9 @@ static void ccgDM_drawVerts(DerivedMesh *dm) {
        fi = ccgSubSurf_getFaceIterator(ss);
        for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
 
-               glVertex3fv(ccgSubSurf_getFaceCenterData(ss, f));
+               glVertex3fv(ccgSubSurf_getFaceCenterData(f));
                for (S=0; S<numVerts; S++)
                        for (x=1; x<gridSize-1; x++)
                                glVertex3fv(ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
@@ -1513,7 +1525,7 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
                VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
 
-               if (!drawLooseEdges && !ccgSubSurf_getEdgeNumFaces(ss, e))
+               if (!drawLooseEdges && !ccgSubSurf_getEdgeNumFaces(e))
                        continue;
 
                if (useAging && !(G.f&G_BACKBUFSEL)) {
@@ -1536,7 +1548,7 @@ static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) {
        if (ccgdm->drawInteriorEdges) {
                for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                        CCGFace *f = ccgFaceIterator_getCurrent(fi);
-                       int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+                       int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
 
                        for (S=0; S<numVerts; S++) {
                                VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
@@ -1574,7 +1586,7 @@ static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
                VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
 
-               if (!ccgSubSurf_getEdgeNumFaces(ss, e)) {
+               if (!ccgSubSurf_getEdgeNumFaces(e)) {
                        glBegin(GL_LINE_STRIP);
                        for (i=0; i<edgeSize-1; i++) {
                                glVertex3fv(edgeData[i].co);
@@ -1602,7 +1614,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
 }
 
        /* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
+static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
@@ -1611,8 +1623,8 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
 
        for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
-               int index = (int) ccgSubSurf_getFaceFaceHandle(ss, f);
+               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+               int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
                int drawSmooth, mat_nr;
 
                if(faceFlags) {
@@ -1624,7 +1636,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
                        mat_nr= 0;
                }
                
-               if (!setMaterial(mat_nr+1))
+               if (!setMaterial(mat_nr+1, NULL))
                        continue;
 
                glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
@@ -1669,6 +1681,168 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) {
 
        ccgFaceIterator_free(fi);
 }
+
+       /* 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;
+       CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
+       GPUVertexAttribs gattribs;
+       DMVertexAttribs attribs;
+       MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
+       int gridSize = ccgSubSurf_getGridSize(ss);
+       int gridFaces = gridSize - 1;
+       int edgeSize = ccgSubSurf_getEdgeSize(ss);
+       int transp, orig_transp, new_transp;
+       char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS);
+       int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
+
+       doDraw = 0;
+       numVerts = 0;
+       matnr = -1;
+       transp = GPU_get_material_blend_mode();
+       orig_transp = transp;
+
+       memset(&attribs, 0, sizeof(attribs));
+
+#define PASSATTRIB(dx, dy, vert) {                                                                                             \
+       if(attribs.totorco) {                                                                                                           \
+               index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize);                 \
+               glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.tottface; b++) {                                                                         \
+               MTFace *tf = &attribs.tface[b].array[a];                                                                \
+               glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);                   \
+       }                                                                                                                                                       \
+       for(b = 0; b < attribs.totmcol; b++) {                                                                          \
+               MCol *cp = &attribs.mcol[b].array[a*4 + vert];                                                  \
+               GLubyte col[4];                                                                                                                 \
+               col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;                             \
+               glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                                    \
+       }                                                                                                                                                       \
+       if(attribs.tottang) {                                                                                                           \
+               float *tang = attribs.tang.array[a*4 + vert];                                                   \
+               glVertexAttrib3fvARB(attribs.tang.glIndex, tang);                                               \
+       }                                                                                                                                                       \
+}
+
+       totface = ccgSubSurf_getNumFaces(ss);
+       for(a = 0, i = 0; i < totface; i++) {
+               CCGFace *f = ccgdm->faceMap[i].face;
+               int S, x, y, drawSmooth;
+               int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
+               int origIndex = ccgDM_getFaceMapIndex(ss, f);
+               
+               numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+               if(faceFlags) {
+                       drawSmooth = (faceFlags[index*4] & ME_SMOOTH);
+                       new_matnr= faceFlags[index*4 + 1] + 1;
+               }
+               else {
+                       drawSmooth = 1;
+                       new_matnr= 1;
+               }
+
+               if(new_matnr != matnr) {
+                       doDraw = setMaterial(matnr = new_matnr, &gattribs);
+                       if(doDraw)
+                               DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+               }
+
+               if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) {
+                       a += gridFaces*gridFaces*numVerts;
+                       continue;
+               }
+
+               if(tf) {
+                       new_transp = tf[i].transp;
+
+                       if(new_transp != transp) {
+                               if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
+                                       GPU_set_material_blend_mode(orig_transp);
+                               else
+                                       GPU_set_material_blend_mode(new_transp);
+                               transp = new_transp;
+                       }
+               }
+
+               glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
+               for (S=0; S<numVerts; S++) {
+                       VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+                       VertData *vda, *vdb;
+
+                       if (drawSmooth) {
+                               for (y=0; y<gridFaces; y++) {
+                                       glBegin(GL_QUAD_STRIP);
+                                       for (x=0; x<gridFaces; x++) {
+                                               vda = &faceGridData[(y+0)*gridSize + x];
+                                               vdb = &faceGridData[(y+1)*gridSize + x];
+                                               
+                                               PASSATTRIB(0, 0, 0);
+                                               glNormal3fv(vda->no);
+                                               glVertex3fv(vda->co);
+
+                                               PASSATTRIB(0, 1, 1);
+                                               glNormal3fv(vdb->no);
+                                               glVertex3fv(vdb->co);
+
+                                               if(x != gridFaces-1)
+                                                       a++;
+                                       }
+
+                                       vda = &faceGridData[(y+0)*gridSize + x];
+                                       vdb = &faceGridData[(y+1)*gridSize + x];
+
+                                       PASSATTRIB(0, 0, 3);
+                                       glNormal3fv(vda->no);
+                                       glVertex3fv(vda->co);
+
+                                       PASSATTRIB(0, 1, 2);
+                                       glNormal3fv(vdb->no);
+                                       glVertex3fv(vdb->co);
+
+                                       glEnd();
+
+                                       a++;
+                               }
+                       } else {
+                               glBegin(GL_QUADS);
+                               for (y=0; y<gridFaces; y++) {
+                                       for (x=0; x<gridFaces; x++) {
+                                               float *aco = faceGridData[(y+0)*gridSize + x].co;
+                                               float *bco = faceGridData[(y+0)*gridSize + x + 1].co;
+                                               float *cco = faceGridData[(y+1)*gridSize + x + 1].co;
+                                               float *dco = faceGridData[(y+1)*gridSize + x].co;
+
+                                               ccgDM_glNormalFast(aco, bco, cco, dco);
+
+                                               PASSATTRIB(0, 1, 1);
+                                               glVertex3fv(dco);
+                                               PASSATTRIB(1, 1, 2);
+                                               glVertex3fv(cco);
+                                               PASSATTRIB(1, 0, 3);
+                                               glVertex3fv(bco);
+                                               PASSATTRIB(0, 0, 0);
+                                               glVertex3fv(aco);
+                                               
+                                               a++;
+                                       }
+                               }
+                               glEnd();
+                       }
+               }
+       }
+
+#undef PASSATTRIB
+
+       ccgFaceIterator_free(fi);
+}
+
+static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
+       dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+}
+
 static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
@@ -1692,7 +1866,7 @@ static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned ch
        glBegin(GL_QUADS);
        for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
 
                for (S=0; S<numVerts; S++) {
                        VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
@@ -1750,9 +1924,9 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
        totface = ccgSubSurf_getNumFaces(ss);
        for(i = 0; i < totface; i++) {
                CCGFace *f = ccgdm->faceMap[i].face;
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
-               int drawSmooth, index = ccgDM_getFaceMapIndex(ccgdm, ss, f);
-               int origIndex = (int)ccgSubSurf_getFaceFaceHandle(ss, f);
+               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));
                unsigned char *cp= NULL;
                int mat_nr;
 
@@ -1833,28 +2007,28 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
                                glBegin(GL_QUADS);
                                for (y=0; y<gridFaces; y++) {
                                        for (x=0; x<gridFaces; x++) {
-                                               float *a = faceGridData[(y+0)*gridSize + x].co;
-                                               float *b = faceGridData[(y+0)*gridSize + x + 1].co;
-                                               float *c = faceGridData[(y+1)*gridSize + x + 1].co;
-                                               float *d = faceGridData[(y+1)*gridSize + x].co;
+                                               float *a_co = faceGridData[(y+0)*gridSize + x].co;
+                                               float *b_co = faceGridData[(y+0)*gridSize + x + 1].co;
+                                               float *c_co = faceGridData[(y+1)*gridSize + x + 1].co;
+                                               float *d_co = faceGridData[(y+1)*gridSize + x].co;
 
-                                               ccgDM_glNormalFast(a, b, c, d);
+                                               ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
 
                                                if(tf) glTexCoord2fv(tf->uv[1]);
                                                if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                                               glVertex3fv(d);
+                                               glVertex3fv(d_co);
 
                                                if(tf) glTexCoord2fv(tf->uv[2]);
                                                if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                                               glVertex3fv(c);
+                                               glVertex3fv(c_co);
 
                                                if(tf) glTexCoord2fv(tf->uv[3]);
                                                if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                                               glVertex3fv(b);
+                                               glVertex3fv(b_co);
 
                                                if(tf) glTexCoord2fv(tf->uv[0]);
                                                if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                                               glVertex3fv(a);
+                                               glVertex3fv(a_co);
 
                                                if(tf) tf++;
                                                if(cp) cp += 16;
@@ -1910,7 +2084,6 @@ static void ccgDM_drawUVEdges(DerivedMesh *dm)
 }
 
 static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) {
-       GLubyte act_face_stipple[32*32/8] = DM_FACE_STIPPLE;
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
        CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
@@ -1919,11 +2092,11 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u
 
        for (i=0; !ccgFaceIterator_isStopped(fi); i++,ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
-               int drawSmooth, index = ccgDM_getFaceMapIndex(ccgdm, ss, f);
+               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+               int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
                int origIndex;
 
-               origIndex = (int)ccgSubSurf_getFaceFaceHandle(ss, f);
+               origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
 
                if(faceFlags) drawSmooth = (faceFlags[origIndex*4] & ME_SMOOTH);
                else drawSmooth = 1;
@@ -1935,7 +2108,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u
                        if (draw) {
                                if (draw==2) {
                                        glEnable(GL_POLYGON_STIPPLE);
-                                       glPolygonStipple(act_face_stipple);
+                                       glPolygonStipple(stipple_quarttone);
                                }
                                
                                for (S=0; S<numVerts; S++) {
@@ -2001,7 +2174,7 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *u
        for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
                VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
-               int index = ccgDM_getEdgeMapIndex(ccgdm, ss, e);
+               int index = ccgDM_getEdgeMapIndex(ss, e);
 
                glBegin(GL_LINE_STRIP);
                if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
@@ -2031,7 +2204,7 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(v
        for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
                VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
-               int index = ccgDM_getEdgeMapIndex(ccgdm, ss, e);
+               int index = ccgDM_getEdgeMapIndex(ss, e);
 
                glBegin(GL_LINE_STRIP);
                if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
@@ -2058,7 +2231,7 @@ static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *us
 
        for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
-               int index = ccgDM_getFaceMapIndex(ccgdm, ss, f);
+               int index = ccgDM_getFaceMapIndex(ss, f);
 
                if (index!=-1) {
                                /* Face center data normal isn't updated atm. */
@@ -2094,17 +2267,17 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        int index, totvert, totedge, totface;
        int i;
        int vertNum, edgeNum, faceNum;
-       int *vertOrigIndex, *edgeOrigIndex, *faceOrigIndex;
+       int *vertOrigIndex, *faceOrigIndex; /* *edgeOrigIndex - as yet, unused  */
        int *edgeFlags;
        char *faceFlags;
        int edgeSize;
        int gridSize;
        int gridFaces;
        int gridSideVerts;
-       int gridInternalVerts;
+       /*int gridInternalVerts; - as yet unused */
        int gridSideEdges;
        int gridInternalEdges;
-       MVert *mvert = NULL;
+       /* MVert *mvert = NULL; - as yet unused */
        MEdge *medge = NULL;
        MFace *mface = NULL;
        FaceVertWeight *qweight, *tweight;
@@ -2147,8 +2320,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
        ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
        ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
+       ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
        ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
        ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
+       ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
        ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
 
        ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
@@ -2166,7 +2341,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
 
-               ccgdm->vertMap[(int) ccgSubSurf_getVertVertHandle(ss, v)].vert = v;
+               ccgdm->vertMap[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))].vert = v;
        }
        ccgVertIterator_free(vi);
 
@@ -2176,7 +2351,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
                CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
 
-               ccgdm->edgeMap[(int) ccgSubSurf_getEdgeEdgeHandle(ss, e)].edge = e;
+               ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
        }
 
        totface = ccgSubSurf_getNumFaces(ss);
@@ -2185,7 +2360,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
                CCGFace *f = ccgFaceIterator_getCurrent(fi);
 
-               ccgdm->faceMap[(int) ccgSubSurf_getFaceFaceHandle(ss, f)].face = f;
+               ccgdm->faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))].face = f;
        }
        ccgFaceIterator_free(fi);
 
@@ -2193,7 +2368,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        gridSize = ccgSubSurf_getGridSize(ss);
        gridFaces = gridSize - 1;
        gridSideVerts = gridSize - 2;
-       gridInternalVerts = gridSideVerts * gridSideVerts;
+       /*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
        gridSideEdges = gridSize - 1;
        gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; 
 
@@ -2203,22 +2378,22 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        edgeNum = 0;
        faceNum = 0;
 
-       mvert = dm->getVertArray(dm);
+       /* mvert = dm->getVertArray(dm); - as yet unused */
        medge = dm->getEdgeArray(dm);
        mface = dm->getFaceArray(dm);
 
        vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
-       edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);
+       /*edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);*/
        faceOrigIndex = DM_get_face_data_layer(&ccgdm->dm, CD_ORIGINDEX);
 
        faceFlags = DM_get_face_data_layer(&ccgdm->dm, CD_FLAGS);
 
        for(index = 0; index < totface; ++index) {
                CCGFace *f = ccgdm->faceMap[index].face;
-               int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+               int numVerts = ccgSubSurf_getFaceNumVerts(f);
                int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
-               int mapIndex = ccgDM_getFaceMapIndex(ccgdm, ss, f);
-               int origIndex = (int)ccgSubSurf_getFaceFaceHandle(ss, f);
+               int mapIndex = ccgDM_getFaceMapIndex(ss, f);
+               int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
                FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
                int S, x, y;
                int vertIdx[4];
@@ -2233,7 +2408,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
                for(S = 0; S < numVerts; S++) {
                        CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
 
-                       vertIdx[S] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+                       vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
                }
 
                DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0],
@@ -2336,16 +2511,16 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
        for(index = 0; index < totedge; ++index) {
                CCGEdge *e = ccgdm->edgeMap[index].edge;
                int numFinalEdges = edgeSize - 1;
-               int mapIndex = ccgDM_getEdgeMapIndex(ccgdm, ss, e);
+               int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
                int x;
                int vertIdx[2];
-               int edgeIdx = (int)ccgSubSurf_getEdgeEdgeHandle(ss, e);
+               int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
 
                CCGVert *v;
-               v = ccgSubSurf_getEdgeVert0(ss, e);
-               vertIdx[0] = (int)ccgSubSurf_getVertVertHandle(ss, v);
-               v = ccgSubSurf_getEdgeVert1(ss, e);
-               vertIdx[1] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+               v = ccgSubSurf_getEdgeVert0(e);
+               vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+               v = ccgSubSurf_getEdgeVert1(e);
+               vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 
                ccgdm->edgeMap[index].startVert = vertNum;
                ccgdm->edgeMap[index].startEdge = edgeNum;
@@ -2376,10 +2551,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
 
        for(index = 0; index < totvert; ++index) {
                CCGVert *v = ccgdm->vertMap[index].vert;
-               int mapIndex = ccgDM_getVertMapIndex(ccgdm, ccgdm->ss, v);
+               int mapIndex = ccgDM_getVertMapIndex(ccgdm->ss, v);
                int vertIdx;
 
-               vertIdx = (int)ccgSubSurf_getVertVertHandle(ss, v);
+               vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
 
                ccgdm->vertMap[index].startVert = vertNum;
 
@@ -2401,9 +2576,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
 
 /***/
 
-struct DerivedMesh *subsurf_make_derived_from_derived(
+struct DerivedMesh *subsurf_make_derived_from_derived_with_multires(
                         struct DerivedMesh *dm,
                         struct SubsurfModifierData *smd,
+                       struct MultiresSubsurf *ms,
                         int useRenderParams, float (*vertCos)[3],
                         int isFinalCalc, int editMode)
 {
@@ -2426,7 +2602,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
                CCGSubSurf *ss;
                int levels;
                
-               levels= get_render_subsurf_level(&G.scene->r, smd->renderLevels);
+               levels= smd->renderLevels; // XXX get_render_subsurf_level(&scene->r, smd->renderLevels);
                if(levels == 0)
                        return dm;
                
@@ -2435,7 +2611,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
                ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
 
                result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
-                                            useSubsurfUv, dm);
+                                            useSubsurfUv, dm, ms);
 
                ccgSubSurf_free(ss);
                
@@ -2466,7 +2642,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
 
 
                        return ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
-                                              useSubsurfUv, dm);
+                                                  useSubsurfUv, dm, ms);
 
                        /*return (DerivedMesh *)getCCGDerivedMesh(smd->mCache,
                                                        drawInteriorEdges,
@@ -2486,7 +2662,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
                                                    useSubsurfUv, dm);*/
 
                        result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
-                                                    useSubsurfUv, dm);
+                                                    useSubsurfUv, dm, ms);
 
                        ccgSubSurf_free(ss);
 
@@ -2495,6 +2671,15 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
        }
 }
 
+struct DerivedMesh *subsurf_make_derived_from_derived(
+                        struct DerivedMesh *dm,
+                        struct SubsurfModifierData *smd,
+                        int useRenderParams, float (*vertCos)[3],
+                        int isFinalCalc, int editMode)
+{
+       return subsurf_make_derived_from_derived_with_multires(dm, smd, NULL, useRenderParams, vertCos, isFinalCalc, editMode);
+}
+
 void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) 
 {
        /* Finds the subsurf limit positions for the verts in a mesh 
@@ -2512,9 +2697,9 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
        vi = ccgSubSurf_getVertIterator(ss);
        for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
                CCGVert *v = ccgVertIterator_getCurrent(vi);
-               int idx = (int) ccgSubSurf_getVertVertHandle(ss, v);
-               int N = ccgSubSurf_getVertNumEdges(ss, v);
-               int numFaces = ccgSubSurf_getVertNumFaces(ss, v);
+               int idx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
+               int N = ccgSubSurf_getVertNumEdges(v);
+               int numFaces = ccgSubSurf_getVertNumFaces(v);
                float *co;
                int i;
                 
@@ -2522,12 +2707,12 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
                face_sum[0]= face_sum[1]= face_sum[2]= 0.0;
 
                for (i=0; i<N; i++) {
-                       CCGEdge *e = ccgSubSurf_getVertEdge(ss, v, i);
+                       CCGEdge *e = ccgSubSurf_getVertEdge(v, i);
                        VecAddf(edge_sum, edge_sum, ccgSubSurf_getEdgeData(ss, e, 1));
                }
                for (i=0; i<numFaces; i++) {
-                       CCGFace *f = ccgSubSurf_getVertFace(ss, v, i);
-                       VecAddf(face_sum, face_sum, ccgSubSurf_getFaceCenterData(ss, f));
+                       CCGFace *f = ccgSubSurf_getVertFace(v, i);
+                       VecAddf(face_sum, face_sum, ccgSubSurf_getFaceCenterData(f));
                }
 
                /* ad-hoc correction for boundary vertices, to at least avoid them