Cleanup: comments (long lines) in blenkernel
[blender.git] / source / blender / blenkernel / intern / subsurf_ccg.c
index 6009881963837c5175c21c5538eed20ff3d8565f..ceb501c5a994626ce1eb5a6875b0d1a7bf4ce0e4 100644 (file)
@@ -17,8 +17,8 @@
  * All rights reserved.
  */
 
-/** \file blender/blenkernel/intern/subsurf_ccg.c
- *  \ingroup bke
+/** \file
+ * \ingroup bke
  */
 
 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 #include "BKE_pbvh.h"
 #include "BKE_ccg.h"
 #include "BKE_cdderivedmesh.h"
-#include "BKE_global.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_mapping.h"
 #include "BKE_modifier.h"
 #include "BKE_multires.h"
+#include "BKE_object.h"
 #include "BKE_paint.h"
 #include "BKE_scene.h"
 #include "BKE_subsurf.h"
 #  include "BLI_array.h"
 #endif
 
-#include "GPU_draw.h"
-#include "GPU_glew.h"
-#include "GPU_buffers.h"
-#include "GPU_shader.h"
-#include "GPU_basic_shader.h"
-
 #include "CCGSubSurf.h"
 
 #ifdef WITH_OPENSUBDIV
@@ -95,310 +89,321 @@ static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
 
 static void *arena_alloc(CCGAllocatorHDL a, int numBytes)
 {
-       return BLI_memarena_alloc(a, numBytes);
+  return BLI_memarena_alloc(a, numBytes);
 }
 
 static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize)
 {
-       void *p2 = BLI_memarena_alloc(a, newSize);
-       if (ptr) {
-               memcpy(p2, ptr, oldSize);
-       }
-       return p2;
+  void *p2 = BLI_memarena_alloc(a, newSize);
+  if (ptr) {
+    memcpy(p2, ptr, oldSize);
+  }
+  return p2;
 }
 
 static void arena_free(CCGAllocatorHDL UNUSED(a), void *UNUSED(ptr))
 {
-       /* do nothing */
+  /* do nothing */
 }
 
 static void arena_release(CCGAllocatorHDL a)
 {
-       BLI_memarena_free(a);
+  BLI_memarena_free(a);
 }
 
 typedef enum {
-       CCG_USE_AGING = 1,
-       CCG_USE_ARENA = 2,
-       CCG_CALC_NORMALS = 4,
-       /* add an extra four bytes for a mask layer */
-       CCG_ALLOC_MASK = 8,
-       CCG_SIMPLE_SUBDIV = 16,
+  CCG_USE_AGING = 1,
+  CCG_USE_ARENA = 2,
+  CCG_CALC_NORMALS = 4,
+  /* add an extra four bytes for a mask layer */
+  CCG_ALLOC_MASK = 8,
+  CCG_SIMPLE_SUBDIV = 16,
 } CCGFlags;
 
-static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels,
-                               int numLayers, CCGFlags flags)
-{
-       CCGMeshIFC ifc;
-       CCGSubSurf *ccgSS;
-       int useAging = !!(flags & CCG_USE_AGING);
-       int useArena = flags & CCG_USE_ARENA;
-       int normalOffset = 0;
-
-       /* (subdivLevels == 0) is not allowed */
-       subdivLevels = MAX2(subdivLevels, 1);
-
-       if (prevSS) {
-               int oldUseAging;
-
-               ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
-
-               if ((oldUseAging != useAging) ||
-                   (ccgSubSurf_getSimpleSubdiv(prevSS) != !!(flags & CCG_SIMPLE_SUBDIV)))
-               {
-                       ccgSubSurf_free(prevSS);
-               }
-               else {
-                       ccgSubSurf_setSubdivisionLevels(prevSS, subdivLevels);
-
-                       return prevSS;
-               }
-       }
-
-       if (useAging) {
-               ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 12;
-       }
-       else {
-               ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8;
-       }
-       ifc.numLayers = numLayers;
-       ifc.vertDataSize = sizeof(float) * numLayers;
-       normalOffset += sizeof(float) * numLayers;
-       if (flags & CCG_CALC_NORMALS)
-               ifc.vertDataSize += sizeof(float) * 3;
-       if (flags & CCG_ALLOC_MASK)
-               ifc.vertDataSize += sizeof(float);
-       ifc.simpleSubdiv = !!(flags & CCG_SIMPLE_SUBDIV);
-
-       if (useArena) {
-               CCGAllocatorIFC allocatorIFC;
-               CCGAllocatorHDL allocator = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "subsurf arena");
-
-               allocatorIFC.alloc = arena_alloc;
-               allocatorIFC.realloc = arena_realloc;
-               allocatorIFC.free = arena_free;
-               allocatorIFC.release = arena_release;
-
-               ccgSS = ccgSubSurf_new(&ifc, subdivLevels, &allocatorIFC, allocator);
-       }
-       else {
-               ccgSS = ccgSubSurf_new(&ifc, subdivLevels, NULL, NULL);
-       }
-
-       if (useAging) {
-               ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8);
-       }
-
-       if (flags & CCG_ALLOC_MASK) {
-               normalOffset += sizeof(float);
-               /* mask is allocated after regular layers */
-               ccgSubSurf_setAllocMask(ccgSS, 1, sizeof(float) * numLayers);
-       }
-
-       if (flags & CCG_CALC_NORMALS)
-               ccgSubSurf_setCalcVertexNormals(ccgSS, 1, normalOffset);
-       else
-               ccgSubSurf_setCalcVertexNormals(ccgSS, 0, 0);
-
-       return ccgSS;
+static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int numLayers, CCGFlags flags)
+{
+  CCGMeshIFC ifc;
+  CCGSubSurf *ccgSS;
+  int useAging = !!(flags & CCG_USE_AGING);
+  int useArena = flags & CCG_USE_ARENA;
+  int normalOffset = 0;
+
+  /* (subdivLevels == 0) is not allowed */
+  subdivLevels = MAX2(subdivLevels, 1);
+
+  if (prevSS) {
+    int oldUseAging;
+
+    ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
+
+    if ((oldUseAging != useAging) ||
+        (ccgSubSurf_getSimpleSubdiv(prevSS) != !!(flags & CCG_SIMPLE_SUBDIV))) {
+      ccgSubSurf_free(prevSS);
+    }
+    else {
+      ccgSubSurf_setSubdivisionLevels(prevSS, subdivLevels);
+
+      return prevSS;
+    }
+  }
+
+  if (useAging) {
+    ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 12;
+  }
+  else {
+    ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8;
+  }
+  ifc.numLayers = numLayers;
+  ifc.vertDataSize = sizeof(float) * numLayers;
+  normalOffset += sizeof(float) * numLayers;
+  if (flags & CCG_CALC_NORMALS) {
+    ifc.vertDataSize += sizeof(float) * 3;
+  }
+  if (flags & CCG_ALLOC_MASK) {
+    ifc.vertDataSize += sizeof(float);
+  }
+  ifc.simpleSubdiv = !!(flags & CCG_SIMPLE_SUBDIV);
+
+  if (useArena) {
+    CCGAllocatorIFC allocatorIFC;
+    CCGAllocatorHDL allocator = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "subsurf arena");
+
+    allocatorIFC.alloc = arena_alloc;
+    allocatorIFC.realloc = arena_realloc;
+    allocatorIFC.free = arena_free;
+    allocatorIFC.release = arena_release;
+
+    ccgSS = ccgSubSurf_new(&ifc, subdivLevels, &allocatorIFC, allocator);
+  }
+  else {
+    ccgSS = ccgSubSurf_new(&ifc, subdivLevels, NULL, NULL);
+  }
+
+  if (useAging) {
+    ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8);
+  }
+
+  if (flags & CCG_ALLOC_MASK) {
+    normalOffset += sizeof(float);
+    /* mask is allocated after regular layers */
+    ccgSubSurf_setAllocMask(ccgSS, 1, sizeof(float) * numLayers);
+  }
+
+  if (flags & CCG_CALC_NORMALS) {
+    ccgSubSurf_setCalcVertexNormals(ccgSS, 1, normalOffset);
+  }
+  else {
+    ccgSubSurf_setCalcVertexNormals(ccgSS, 0, 0);
+  }
+
+  return ccgSS;
 }
 
 static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize)
 {
-       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));
-
-       if (x == 0) {
-               return v0idx;
-       }
-       else if (x == edgeSize - 1) {
-               return v1idx;
-       }
-       else {
-               return edgeBase + x - 1;
-       }
-}
-
-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(f);
-
-       if (x == gridSize - 1 && y == gridSize - 1) {
-               CCGVert *v = ccgSubSurf_getFaceVert(f, S);
-               return *((int *) ccgSubSurf_getVertUserData(ss, v));
-       }
-       else if (x == gridSize - 1) {
-               CCGVert *v = ccgSubSurf_getFaceVert(f, S);
-               CCGEdge *e = ccgSubSurf_getFaceEdge(f, S);
-               int edgeBase = *((int *) ccgSubSurf_getEdgeUserData(ss, e));
-               if (v == ccgSubSurf_getEdgeVert0(e)) {
-                       return edgeBase + (gridSize - 1 - y) - 1;
-               }
-               else {
-                       return edgeBase + (edgeSize - 2 - 1) - ((gridSize - 1 - y) - 1);
-               }
-       }
-       else if (y == gridSize - 1) {
-               CCGVert *v = ccgSubSurf_getFaceVert(f, S);
-               CCGEdge *e = ccgSubSurf_getFaceEdge(f, (S + numVerts - 1) % numVerts);
-               int edgeBase = *((int *) ccgSubSurf_getEdgeUserData(ss, e));
-               if (v == ccgSubSurf_getEdgeVert0(e)) {
-                       return edgeBase + (gridSize - 1 - x) - 1;
-               }
-               else {
-                       return edgeBase + (edgeSize - 2 - 1) - ((gridSize - 1 - x) - 1);
-               }
-       }
-       else if (x == 0 && y == 0) {
-               return faceBase;
-       }
-       else if (x == 0) {
-               S = (S + numVerts - 1) % numVerts;
-               return faceBase + 1 + (gridSize - 2) * S + (y - 1);
-       }
-       else if (y == 0) {
-               return faceBase + 1 + (gridSize - 2) * S + (x - 1);
-       }
-       else {
-               return faceBase + 1 + (gridSize - 2) * numVerts + S * (gridSize - 2) * (gridSize - 2) + (y - 1) * (gridSize - 2) + (x - 1);
-       }
-}
-
-static void get_face_uv_map_vert(UvVertMap *vmap, struct MPoly *mpoly, struct MLoop *ml, int fi, CCGVertHDL *fverts)
-{
-       UvMapVert *v, *nv;
-       int j, nverts = mpoly[fi].totloop;
-
-       for (j = 0; j < nverts; j++) {
-               for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, ml[j].v); v; v = v->next) {
-                       if (v->separate)
-                               nv = v;
-                       if (v->poly_index == fi)
-                               break;
-               }
-
-               fverts[j] = POINTER_FROM_UINT(mpoly[nv->poly_index].loopstart + nv->loop_of_poly_index);
-       }
+  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));
+
+  if (x == 0) {
+    return v0idx;
+  }
+  else if (x == edgeSize - 1) {
+    return v1idx;
+  }
+  else {
+    return edgeBase + x - 1;
+  }
+}
+
+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(f);
+
+  if (x == gridSize - 1 && y == gridSize - 1) {
+    CCGVert *v = ccgSubSurf_getFaceVert(f, S);
+    return *((int *)ccgSubSurf_getVertUserData(ss, v));
+  }
+  else if (x == gridSize - 1) {
+    CCGVert *v = ccgSubSurf_getFaceVert(f, S);
+    CCGEdge *e = ccgSubSurf_getFaceEdge(f, S);
+    int edgeBase = *((int *)ccgSubSurf_getEdgeUserData(ss, e));
+    if (v == ccgSubSurf_getEdgeVert0(e)) {
+      return edgeBase + (gridSize - 1 - y) - 1;
+    }
+    else {
+      return edgeBase + (edgeSize - 2 - 1) - ((gridSize - 1 - y) - 1);
+    }
+  }
+  else if (y == gridSize - 1) {
+    CCGVert *v = ccgSubSurf_getFaceVert(f, S);
+    CCGEdge *e = ccgSubSurf_getFaceEdge(f, (S + numVerts - 1) % numVerts);
+    int edgeBase = *((int *)ccgSubSurf_getEdgeUserData(ss, e));
+    if (v == ccgSubSurf_getEdgeVert0(e)) {
+      return edgeBase + (gridSize - 1 - x) - 1;
+    }
+    else {
+      return edgeBase + (edgeSize - 2 - 1) - ((gridSize - 1 - x) - 1);
+    }
+  }
+  else if (x == 0 && y == 0) {
+    return faceBase;
+  }
+  else if (x == 0) {
+    S = (S + numVerts - 1) % numVerts;
+    return faceBase + 1 + (gridSize - 2) * S + (y - 1);
+  }
+  else if (y == 0) {
+    return faceBase + 1 + (gridSize - 2) * S + (x - 1);
+  }
+  else {
+    return faceBase + 1 + (gridSize - 2) * numVerts + S * (gridSize - 2) * (gridSize - 2) +
+           (y - 1) * (gridSize - 2) + (x - 1);
+  }
+}
+
+static void get_face_uv_map_vert(
+    UvVertMap *vmap, struct MPoly *mpoly, struct MLoop *ml, int fi, CCGVertHDL *fverts)
+{
+  UvMapVert *v, *nv;
+  int j, nverts = mpoly[fi].totloop;
+
+  for (j = 0; j < nverts; j++) {
+    for (nv = v = BKE_mesh_uv_vert_map_get_vert(vmap, ml[j].v); v; v = v->next) {
+      if (v->separate) {
+        nv = v;
+      }
+      if (v->poly_index == fi) {
+        break;
+      }
+    }
+
+    fverts[j] = POINTER_FROM_UINT(mpoly[nv->poly_index].loopstart + nv->loop_of_poly_index);
+  }
 }
 
 static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MLoopUV *mloopuv)
 {
-       MPoly *mpoly = dm->getPolyArray(dm);
-       MLoop *mloop = dm->getLoopArray(dm);
-       int totvert = dm->getNumVerts(dm);
-       int totface = dm->getNumPolys(dm);
-       int i, seam;
-       UvMapVert *v;
-       UvVertMap *vmap;
-       float limit[2];
+  MPoly *mpoly = dm->getPolyArray(dm);
+  MLoop *mloop = dm->getLoopArray(dm);
+  int totvert = dm->getNumVerts(dm);
+  int totface = dm->getNumPolys(dm);
+  int i, seam;
+  UvMapVert *v;
+  UvVertMap *vmap;
+  float limit[2];
 #ifndef USE_DYNSIZE
-       CCGVertHDL *fverts = NULL;
-       BLI_array_declare(fverts);
+  CCGVertHDL *fverts = NULL;
+  BLI_array_declare(fverts);
 #endif
-       EdgeSet *eset;
-       float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
-
-       limit[0] = limit[1] = STD_UV_CONNECT_LIMIT;
-       /* previous behavior here is without accounting for winding, however this causes stretching in
-        * UV map in really simple cases with mirror + subsurf, see second part of T44530. Also, initially
-        * intention is to treat merged vertices from mirror modifier as seams.
-        * This fixes a very old regression (2.49 was correct here) */
-       vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, limit, false, true);
-       if (!vmap)
-               return 0;
-
-       ccgSubSurf_initFullSync(ss);
-
-       /* create vertices */
-       for (i = 0; i < totvert; i++) {
-               if (!BKE_mesh_uv_vert_map_get_vert(vmap, i))
-                       continue;
-
-               for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i)->next; v; v = v->next)
-                       if (v->separate)
-                               break;
-
-               seam = (v != NULL);
-
-               for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i); v; v = v->next) {
-                       if (v->separate) {
-                               CCGVert *ssv;
-                               int loopid = mpoly[v->poly_index].loopstart + v->loop_of_poly_index;
-                               CCGVertHDL vhdl = POINTER_FROM_INT(loopid);
-
-                               copy_v2_v2(uv, mloopuv[loopid].uv);
-
-                               ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
-                       }
-               }
-       }
-
-       /* create edges */
-       eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface));
-
-       for (i = 0; i < totface; i++) {
-               MPoly *mp = &mpoly[i];
-               int nverts = mp->totloop;
-               int j, j_next;
-               CCGFace *origf = ccgSubSurf_getFace(origss, POINTER_FROM_INT(i));
-               /* unsigned int *fv = &mp->v1; */
-               MLoop *ml = mloop + mp->loopstart;
+  EdgeSet *eset;
+  float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
+
+  limit[0] = limit[1] = STD_UV_CONNECT_LIMIT;
+  /* previous behavior here is without accounting for winding, however this causes stretching in
+   * UV map in really simple cases with mirror + subsurf, see second part of T44530.
+   * Also, initially intention is to treat merged vertices from mirror modifier as seams.
+   * This fixes a very old regression (2.49 was correct here) */
+  vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, limit, false, true);
+  if (!vmap) {
+    return 0;
+  }
+
+  ccgSubSurf_initFullSync(ss);
+
+  /* create vertices */
+  for (i = 0; i < totvert; i++) {
+    if (!BKE_mesh_uv_vert_map_get_vert(vmap, i)) {
+      continue;
+    }
+
+    for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i)->next; v; v = v->next) {
+      if (v->separate) {
+        break;
+      }
+    }
+
+    seam = (v != NULL);
+
+    for (v = BKE_mesh_uv_vert_map_get_vert(vmap, i); v; v = v->next) {
+      if (v->separate) {
+        CCGVert *ssv;
+        int loopid = mpoly[v->poly_index].loopstart + v->loop_of_poly_index;
+        CCGVertHDL vhdl = POINTER_FROM_INT(loopid);
+
+        copy_v2_v2(uv, mloopuv[loopid].uv);
+
+        ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
+      }
+    }
+  }
+
+  /* create edges */
+  eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface));
+
+  for (i = 0; i < totface; i++) {
+    MPoly *mp = &mpoly[i];
+    int nverts = mp->totloop;
+    int j, j_next;
+    CCGFace *origf = ccgSubSurf_getFace(origss, POINTER_FROM_INT(i));
+    /* unsigned int *fv = &mp->v1; */
+    MLoop *ml = mloop + mp->loopstart;
 
 #ifdef USE_DYNSIZE
-               CCGVertHDL fverts[nverts];
+    CCGVertHDL fverts[nverts];
 #else
-               BLI_array_clear(fverts);
-               BLI_array_grow_items(fverts, nverts);
+    BLI_array_clear(fverts);
+    BLI_array_grow_items(fverts, nverts);
 #endif
 
-               get_face_uv_map_vert(vmap, mpoly, ml, i, fverts);
+    get_face_uv_map_vert(vmap, mpoly, ml, i, fverts);
 
-               for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) {
-                       unsigned int v0 = POINTER_AS_UINT(fverts[j_next]);
-                       unsigned int v1 = POINTER_AS_UINT(fverts[j]);
+    for (j = 0, j_next = nverts - 1; j < nverts; j_next = j++) {
+      unsigned int v0 = POINTER_AS_UINT(fverts[j_next]);
+      unsigned int v1 = POINTER_AS_UINT(fverts[j]);
 
-                       if (BLI_edgeset_add(eset, v0, v1)) {
-                               CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next);
-                               CCGEdgeHDL ehdl = POINTER_FROM_INT(mp->loopstart + j_next);
-                               float crease = ccgSubSurf_getEdgeCrease(orige);
+      if (BLI_edgeset_add(eset, v0, v1)) {
+        CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next);
+        CCGEdgeHDL ehdl = POINTER_FROM_INT(mp->loopstart + j_next);
+        float crease = ccgSubSurf_getEdgeCrease(orige);
 
-                               ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e);
-                       }
-               }
-       }
+        ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e);
+      }
+    }
+  }
 
-       BLI_edgeset_free(eset);
+  BLI_edgeset_free(eset);
 
-       /* create faces */
-       for (i = 0; i < totface; i++) {
-               MPoly *mp = &mpoly[i];
-               MLoop *ml = &mloop[mp->loopstart];
-               int nverts = mp->totloop;
-               CCGFace *f;
+  /* create faces */
+  for (i = 0; i < totface; i++) {
+    MPoly *mp = &mpoly[i];
+    MLoop *ml = &mloop[mp->loopstart];
+    int nverts = mp->totloop;
+    CCGFace *f;
 
 #ifdef USE_DYNSIZE
-               CCGVertHDL fverts[nverts];
+    CCGVertHDL fverts[nverts];
 #else
-               BLI_array_clear(fverts);
-               BLI_array_grow_items(fverts, nverts);
+    BLI_array_clear(fverts);
+    BLI_array_grow_items(fverts, nverts);
 #endif
 
-               get_face_uv_map_vert(vmap, mpoly, ml, i, fverts);
-               ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), nverts, fverts, &f);
-       }
+    get_face_uv_map_vert(vmap, mpoly, ml, i, fverts);
+    ccgSubSurf_syncFace(ss, POINTER_FROM_INT(i), nverts, fverts, &f);
+  }
 
 #ifndef USE_DYNSIZE
-       BLI_array_free(fverts);
+  BLI_array_free(fverts);
 #endif
 
-       BKE_mesh_uv_vert_map_free(vmap);
-       ccgSubSurf_processSync(ss);
+  BKE_mesh_uv_vert_map_free(vmap);
+  ccgSubSurf_processSync(ss);
 
-       return 1;
+  return 1;
 }
 
 #ifdef WITH_OPENSUBDIV
@@ -407,259 +412,256 @@ static void UNUSED_FUNCTION(set_subsurf_osd_ccg_uv)(CCGSubSurf *ss,
                                                     DerivedMesh *result,
                                                     int layer_index)
 {
-       CCGFace **faceMap;
-       MTFace *tf;
-       MLoopUV *mluv;
-       CCGFaceIterator fi;
-       int index, gridSize, gridFaces, totface, x, y, S;
-       MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index);
-       /* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
-        * just tface except applying the modifier then looses subsurf UV */
-       MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, layer_index);
-       MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, layer_index);
-
-       if (dmloopuv == NULL || (tface == NULL && mloopuv == NULL)) {
-               return;
-       }
-
-       ccgSubSurf_evaluatorSetFVarUV(ss, dm, layer_index);
-
-       /* get some info from CCGSubSurf */
-       totface = ccgSubSurf_getNumFaces(ss);
-       gridSize = ccgSubSurf_getGridSize(ss);
-       gridFaces = gridSize - 1;
-
-       /* make a map from original faces to CCGFaces */
-       faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv");
-       for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
-               CCGFace *f = ccgFaceIterator_getCurrent(&fi);
-               faceMap[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))] = f;
-       }
-
-       /* load coordinates from uvss into tface */
-       tf = tface;
-       mluv = mloopuv;
-       for (index = 0; index < totface; index++) {
-               CCGFace *f = faceMap[index];
-               int numVerts = ccgSubSurf_getFaceNumVerts(f);
-               for (S = 0; S < numVerts; S++) {
-                       for (y = 0; y < gridFaces; y++) {
-                               for (x = 0; x < gridFaces; x++) {
-                                       const int delta[4][2] = {{0, 0},
-                                                                {0, 1},
-                                                                {1, 1},
-                                                                {1, 0}};
-                                       float uv[4][2];
-                                       int i;
-                                       for (i = 0; i < 4; i++) {
-                                               const int dx = delta[i][0],
-                                                         dy = delta[i][1];
-                                               const float grid_u = ((float)(x + dx)) / (gridSize - 1),
-                                                           grid_v = ((float)(y + dy)) / (gridSize - 1);
-                                               ccgSubSurf_evaluatorFVarUV(ss,
-                                                                          index,
-                                                                          S,
-                                                                          grid_u, grid_v,
-                                                                          uv[i]);
-                                       }
-                                       if (tf) {
-                                               copy_v2_v2(tf->uv[0], uv[0]);
-                                               copy_v2_v2(tf->uv[1], uv[1]);
-                                               copy_v2_v2(tf->uv[2], uv[2]);
-                                               copy_v2_v2(tf->uv[3], uv[3]);
-                                               tf++;
-                                       }
-                                       if (mluv) {
-                                               copy_v2_v2(mluv[0].uv, uv[0]);
-                                               copy_v2_v2(mluv[1].uv, uv[1]);
-                                               copy_v2_v2(mluv[2].uv, uv[2]);
-                                               copy_v2_v2(mluv[3].uv, uv[3]);
-                                               mluv += 4;
-                                       }
-                               }
-                       }
-               }
-       }
-       MEM_freeN(faceMap);
-}
-#endif  /* WITH_OPENSUBDIV */
+  CCGFace **faceMap;
+  MTFace *tf;
+  MLoopUV *mluv;
+  CCGFaceIterator fi;
+  int index, gridSize, gridFaces, totface, x, y, S;
+  MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer_index);
+  /* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
+   * just tface except applying the modifier then looses subsurf UV */
+  MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, layer_index);
+  MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, layer_index);
+
+  if (dmloopuv == NULL || (tface == NULL && mloopuv == NULL)) {
+    return;
+  }
+
+  ccgSubSurf_evaluatorSetFVarUV(ss, dm, layer_index);
+
+  /* get some info from CCGSubSurf */
+  totface = ccgSubSurf_getNumFaces(ss);
+  gridSize = ccgSubSurf_getGridSize(ss);
+  gridFaces = gridSize - 1;
+
+  /* make a map from original faces to CCGFaces */
+  faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv");
+  for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi);
+       ccgFaceIterator_next(&fi)) {
+    CCGFace *f = ccgFaceIterator_getCurrent(&fi);
+    faceMap[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))] = f;
+  }
+
+  /* load coordinates from uvss into tface */
+  tf = tface;
+  mluv = mloopuv;
+  for (index = 0; index < totface; index++) {
+    CCGFace *f = faceMap[index];
+    int numVerts = ccgSubSurf_getFaceNumVerts(f);
+    for (S = 0; S < numVerts; S++) {
+      for (y = 0; y < gridFaces; y++) {
+        for (x = 0; x < gridFaces; x++) {
+          const int delta[4][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
+          float uv[4][2];
+          int i;
+          for (i = 0; i < 4; i++) {
+            const int dx = delta[i][0], dy = delta[i][1];
+            const float grid_u = ((float)(x + dx)) / (gridSize - 1),
+                        grid_v = ((float)(y + dy)) / (gridSize - 1);
+            ccgSubSurf_evaluatorFVarUV(ss, index, S, grid_u, grid_v, uv[i]);
+          }
+          if (tf) {
+            copy_v2_v2(tf->uv[0], uv[0]);
+            copy_v2_v2(tf->uv[1], uv[1]);
+            copy_v2_v2(tf->uv[2], uv[2]);
+            copy_v2_v2(tf->uv[3], uv[3]);
+            tf++;
+          }
+          if (mluv) {
+            copy_v2_v2(mluv[0].uv, uv[0]);
+            copy_v2_v2(mluv[1].uv, uv[1]);
+            copy_v2_v2(mluv[2].uv, uv[2]);
+            copy_v2_v2(mluv[3].uv, uv[3]);
+            mluv += 4;
+          }
+        }
+      }
+    }
+  }
+  MEM_freeN(faceMap);
+}
+#endif /* WITH_OPENSUBDIV */
 
 static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
 {
-       CCGSubSurf *uvss;
-       CCGFace **faceMap;
-       MTFace *tf;
-       MLoopUV *mluv;
-       CCGFaceIterator fi;
-       int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
-       MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, n);
-       /* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
-        * just tface except applying the modifier then looses subsurf UV */
-       MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n);
-       MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, n);
-
-       if (!dmloopuv || (!tface && !mloopuv))
-               return;
-
-       /* create a CCGSubSurf from uv's */
-       uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 2, CCG_USE_ARENA);
-
-       if (!ss_sync_from_uv(uvss, ss, dm, dmloopuv)) {
-               ccgSubSurf_free(uvss);
-               return;
-       }
-
-       /* get some info from CCGSubSurf */
-       totface = ccgSubSurf_getNumFaces(uvss);
-       /* edgeSize = ccgSubSurf_getEdgeSize(uvss); */ /*UNUSED*/
-       gridSize = ccgSubSurf_getGridSize(uvss);
-       gridFaces = gridSize - 1;
-
-       /* make a map from original faces to CCGFaces */
-       faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv");
-       for (ccgSubSurf_initFaceIterator(uvss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
-               CCGFace *f = ccgFaceIterator_getCurrent(&fi);
-               faceMap[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))] = f;
-       }
-
-       /* load coordinates from uvss into tface */
-       tf = tface;
-       mluv = mloopuv;
-
-       for (index = 0; index < totface; index++) {
-               CCGFace *f = faceMap[index];
-               int numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               for (S = 0; S < numVerts; S++) {
-                       float (*faceGridData)[2] = ccgSubSurf_getFaceGridDataArray(uvss, f, S);
-
-                       for (y = 0; y < gridFaces; y++) {
-                               for (x = 0; x < gridFaces; x++) {
-                                       float *a = faceGridData[(y + 0) * gridSize + x + 0];
-                                       float *b = faceGridData[(y + 0) * gridSize + x + 1];
-                                       float *c = faceGridData[(y + 1) * gridSize + x + 1];
-                                       float *d = faceGridData[(y + 1) * gridSize + x + 0];
-
-                                       if (tf) {
-                                               copy_v2_v2(tf->uv[0], a);
-                                               copy_v2_v2(tf->uv[1], d);
-                                               copy_v2_v2(tf->uv[2], c);
-                                               copy_v2_v2(tf->uv[3], b);
-                                               tf++;
-                                       }
-
-                                       if (mluv) {
-                                               copy_v2_v2(mluv[0].uv, a);
-                                               copy_v2_v2(mluv[1].uv, d);
-                                               copy_v2_v2(mluv[2].uv, c);
-                                               copy_v2_v2(mluv[3].uv, b);
-                                               mluv += 4;
-                                       }
-
-                               }
-                       }
-               }
-       }
-
-       ccgSubSurf_free(uvss);
-       MEM_freeN(faceMap);
-}
-
-static void set_subsurf_uv(CCGSubSurf *ss,
-                           DerivedMesh *dm,
-                           DerivedMesh *result,
-                           int layer_index)
+  CCGSubSurf *uvss;
+  CCGFace **faceMap;
+  MTFace *tf;
+  MLoopUV *mluv;
+  CCGFaceIterator fi;
+  int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
+  MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, n);
+  /* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
+   * just tface except applying the modifier then looses subsurf UV */
+  MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n);
+  MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, n);
+
+  if (!dmloopuv || (!tface && !mloopuv)) {
+    return;
+  }
+
+  /* create a CCGSubSurf from uv's */
+  uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 2, CCG_USE_ARENA);
+
+  if (!ss_sync_from_uv(uvss, ss, dm, dmloopuv)) {
+    ccgSubSurf_free(uvss);
+    return;
+  }
+
+  /* get some info from CCGSubSurf */
+  totface = ccgSubSurf_getNumFaces(uvss);
+  /* edgeSize = ccgSubSurf_getEdgeSize(uvss); */ /*UNUSED*/
+  gridSize = ccgSubSurf_getGridSize(uvss);
+  gridFaces = gridSize - 1;
+
+  /* make a map from original faces to CCGFaces */
+  faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv");
+  for (ccgSubSurf_initFaceIterator(uvss, &fi); !ccgFaceIterator_isStopped(&fi);
+       ccgFaceIterator_next(&fi)) {
+    CCGFace *f = ccgFaceIterator_getCurrent(&fi);
+    faceMap[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))] = f;
+  }
+
+  /* load coordinates from uvss into tface */
+  tf = tface;
+  mluv = mloopuv;
+
+  for (index = 0; index < totface; index++) {
+    CCGFace *f = faceMap[index];
+    int numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+    for (S = 0; S < numVerts; S++) {
+      float(*faceGridData)[2] = ccgSubSurf_getFaceGridDataArray(uvss, f, S);
+
+      for (y = 0; y < gridFaces; y++) {
+        for (x = 0; x < gridFaces; x++) {
+          float *a = faceGridData[(y + 0) * gridSize + x + 0];
+          float *b = faceGridData[(y + 0) * gridSize + x + 1];
+          float *c = faceGridData[(y + 1) * gridSize + x + 1];
+          float *d = faceGridData[(y + 1) * gridSize + x + 0];
+
+          if (tf) {
+            copy_v2_v2(tf->uv[0], a);
+            copy_v2_v2(tf->uv[1], d);
+            copy_v2_v2(tf->uv[2], c);
+            copy_v2_v2(tf->uv[3], b);
+            tf++;
+          }
+
+          if (mluv) {
+            copy_v2_v2(mluv[0].uv, a);
+            copy_v2_v2(mluv[1].uv, d);
+            copy_v2_v2(mluv[2].uv, c);
+            copy_v2_v2(mluv[3].uv, b);
+            mluv += 4;
+          }
+        }
+      }
+    }
+  }
+
+  ccgSubSurf_free(uvss);
+  MEM_freeN(faceMap);
+}
+
+static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int layer_index)
 {
 #ifdef WITH_OPENSUBDIV
-       if (!ccgSubSurf_needGrids(ss)) {
-               /* GPU backend is used, no need to evaluate UVs on CPU. */
-               /* TODO(sergey): Think of how to support edit mode of UVs. */
-       }
-       else
+  if (!ccgSubSurf_needGrids(ss)) {
+    /* GPU backend is used, no need to evaluate UVs on CPU. */
+    /* TODO(sergey): Think of how to support edit mode of UVs. */
+  }
+  else
 #endif
-       {
-               set_subsurf_legacy_uv(ss, dm, result, layer_index);
-       }
+  {
+    set_subsurf_legacy_uv(ss, dm, result, layer_index);
+  }
 }
 
 /* face weighting */
+#define SUB_ELEMS_FACE 50
+typedef float FaceVertWeight[SUB_ELEMS_FACE][SUB_ELEMS_FACE];
+
 typedef struct FaceVertWeightEntry {
-       FaceVertWeight *weight;
-       float *w;
-       int valid;
+  FaceVertWeight *weight;
+  float *w;
+  int valid;
 } FaceVertWeightEntry;
 
 typedef struct WeightTable {
-       FaceVertWeightEntry *weight_table;
-       int len;
+  FaceVertWeightEntry *weight_table;
+  int len;
 } WeightTable;
 
 static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen)
 {
-       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);
-
-                                       /* these values aren't used for tri's and cause divide by zero */
-                                       if (faceLen > 3) {
-                                               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;
-                               }
-                       }
-               }
-       }
-
-       return wtable->weight_table[faceLen].w;
+  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);
+
+          /* these values aren't used for tri's and cause divide by zero */
+          if (faceLen > 3) {
+            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;
+        }
+      }
+    }
+  }
+
+  return wtable->weight_table[faceLen].w;
 }
 
 static void free_ss_weights(WeightTable *wtable)
 {
-       int i;
+  int i;
 
-       for (i = 0; i < wtable->len; i++) {
-               if (wtable->weight_table[i].valid)
-                       MEM_freeN(wtable->weight_table[i].w);
-       }
+  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 (wtable->weight_table) {
+    MEM_freeN(wtable->weight_table);
+  }
 }
 
 static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
@@ -667,113 +669,110 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
                                          float (*vertexCos)[3],
                                          int useFlatSubdiv)
 {
-       float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
+  float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
 #ifndef USE_DYNSIZE
-       CCGVertHDL *fVerts = NULL;
-       BLI_array_declare(fVerts);
+  CCGVertHDL *fVerts = NULL;
+  BLI_array_declare(fVerts);
 #endif
-       MVert *mvert = dm->getVertArray(dm);
-       MEdge *medge = dm->getEdgeArray(dm);
-       /* MFace *mface = dm->getTessFaceArray(dm); */ /* UNUSED */
-       MVert *mv;
-       MEdge *me;
-       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);
-
-       mv = mvert;
-       index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
-       for (i = 0; i < totvert; i++, mv++) {
-               CCGVert *v;
-
-               if (vertexCos) {
-                       ccgSubSurf_syncVert(ss, POINTER_FROM_INT(i), vertexCos[i], 0, &v);
-               }
-               else {
-                       ccgSubSurf_syncVert(ss, POINTER_FROM_INT(i), mv->co, 0, &v);
-               }
-
-               ((int *)ccgSubSurf_getVertUserData(ss, v))[1] = (index) ? *index++ : i;
-       }
-
-       me = medge;
-       index = (int *)dm->getEdgeDataArray(dm, CD_ORIGINDEX);
-       for (i = 0; i < totedge; i++, me++) {
-               CCGEdge *e;
-               float crease;
-
-               crease = useFlatSubdiv ? creaseFactor :
-                        me->crease * creaseFactor / 255.0f;
-
-               ccgSubSurf_syncEdge(ss, POINTER_FROM_INT(i), POINTER_FROM_UINT(me->v1),
-                                   POINTER_FROM_UINT(me->v2), crease, &e);
-
-               ((int *)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index) ? *index++ : i;
-       }
-
-       mp = mpoly;
-       index = (int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
-       for (i = 0; i < dm->numPolyData; i++, mp++) {
-               CCGFace *f;
+  MVert *mvert = dm->getVertArray(dm);
+  MEdge *medge = dm->getEdgeArray(dm);
+  /* MFace *mface = dm->getTessFaceArray(dm); */ /* UNUSED */
+  MVert *mv;
+  MEdge *me;
+  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);
+
+  mv = mvert;
+  index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
+  for (i = 0; i < totvert; i++, mv++) {
+    CCGVert *v;
+
+    if (vertexCos) {
+      ccgSubSurf_syncVert(ss, POINTER_FROM_INT(i), vertexCos[i], 0, &v);
+    }
+    else {
+      ccgSubSurf_syncVert(ss, POINTER_FROM_INT(i), mv->co, 0, &v);
+    }
+
+    ((int *)ccgSubSurf_getVertUserData(ss, v))[1] = (index) ? *index++ : i;
+  }
+
+  me = medge;
+  index = (int *)dm->getEdgeDataArray(dm, CD_ORIGINDEX);
+  for (i = 0; i < totedge; i++, me++) {
+    CCGEdge *e;
+    float crease;
+
+    crease = useFlatSubdiv ? creaseFactor : me->crease * creaseFactor / 255.0f;
+
+    ccgSubSurf_syncEdge(
+        ss, POINTER_FROM_INT(i), POINTER_FROM_UINT(me->v1), POINTER_FROM_UINT(me->v2), crease, &e);
+
+    ((int *)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index) ? *index++ : i;
+  }
+
+  mp = mpoly;
+  index = (int *)dm->getPolyDataArray(dm, CD_ORIGINDEX);
+  for (i = 0; i < dm->numPolyData; i++, mp++) {
+    CCGFace *f;
 
 #ifdef USE_DYNSIZE
-               CCGVertHDL fVerts[mp->totloop];
+    CCGVertHDL fVerts[mp->totloop];
 #else
-               BLI_array_clear(fVerts);
-               BLI_array_grow_items(fVerts, mp->totloop);
+    BLI_array_clear(fVerts);
+    BLI_array_grow_items(fVerts, mp->totloop);
 #endif
 
-               ml = mloop + mp->loopstart;
-               for (j = 0; j < mp->totloop; j++, ml++) {
-                       fVerts[j] = POINTER_FROM_UINT(ml->v);
-               }
+    ml = mloop + mp->loopstart;
+    for (j = 0; j < mp->totloop; j++, ml++) {
+      fVerts[j] = POINTER_FROM_UINT(ml->v);
+    }
 
-               /* 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, POINTER_FROM_INT(i), mp->totloop,
-                                       fVerts, &f) == eCCGError_InvalidValue)
-               {
-                       static int hasGivenError = 0;
+    /* 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, POINTER_FROM_INT(i), mp->totloop, fVerts, &f) ==
+        eCCGError_InvalidValue) {
+      static int hasGivenError = 0;
 
-                       if (!hasGivenError) {
-                               //XXX error("Unrecoverable error in SubSurf calculation,"
-                               //      " mesh is inconsistent.");
+      if (!hasGivenError) {
+        //XXX error("Unrecoverable error in SubSurf calculation,"
+        //      " mesh is inconsistent.");
 
-                               hasGivenError = 1;
-                       }
+        hasGivenError = 1;
+      }
 
-                       return;
-               }
+      return;
+    }
 
-               ((int *)ccgSubSurf_getFaceUserData(ss, f))[1] = (index) ? *index++ : i;
-       }
+    ((int *)ccgSubSurf_getFaceUserData(ss, f))[1] = (index) ? *index++ : i;
+  }
 
-       ccgSubSurf_processSync(ss);
+  ccgSubSurf_processSync(ss);
 
 #ifndef USE_DYNSIZE
-       BLI_array_free(fVerts);
+  BLI_array_free(fVerts);
 #endif
 }
 
 #ifdef WITH_OPENSUBDIV
-static void ss_sync_osd_from_derivedmesh(CCGSubSurf *ss,
-                                         DerivedMesh *dm)
+static void ss_sync_osd_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm)
 {
-       ccgSubSurf_initFullSync(ss);
-       ccgSubSurf_prepareTopologyRefiner(ss, dm);
-       ccgSubSurf_processSync(ss);
+  ccgSubSurf_initFullSync(ss);
+  ccgSubSurf_prepareTopologyRefiner(ss, dm);
+  ccgSubSurf_processSync(ss);
 }
-#endif  /* WITH_OPENSUBDIV */
+#endif /* WITH_OPENSUBDIV */
 
 static void ss_sync_from_derivedmesh(CCGSubSurf *ss,
                                      DerivedMesh *dm,
@@ -782,3947 +781,1748 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss,
                                      bool use_subdiv_uvs)
 {
 #ifndef WITH_OPENSUBDIV
-       UNUSED_VARS(use_subdiv_uvs);
+  UNUSED_VARS(use_subdiv_uvs);
 #endif
 
 #ifdef WITH_OPENSUBDIV
-       /* Reset all related descriptors if actual mesh topology changed or if
-        * other evaluation-related settings changed.
-        */
-       if (!ccgSubSurf_needGrids(ss)) {
-               /* TODO(sergey): Use vertex coordinates and flat subdiv flag. */
-               ccgSubSurf__sync_subdivUvs(ss, use_subdiv_uvs);
-               ccgSubSurf_checkTopologyChanged(ss, dm);
-               ss_sync_osd_from_derivedmesh(ss, dm);
-       }
-       else
+  /* Reset all related descriptors if actual mesh topology changed or if
+   * other evaluation-related settings changed.
+   */
+  if (!ccgSubSurf_needGrids(ss)) {
+    /* TODO(sergey): Use vertex coordinates and flat subdiv flag. */
+    ccgSubSurf__sync_subdivUvs(ss, use_subdiv_uvs);
+    ccgSubSurf_checkTopologyChanged(ss, dm);
+    ss_sync_osd_from_derivedmesh(ss, dm);
+  }
+  else
 #endif
-       {
-               ss_sync_ccg_from_derivedmesh(ss, dm, vertexCos, use_flat_subdiv);
-       }
+  {
+    ss_sync_ccg_from_derivedmesh(ss, dm, vertexCos, use_flat_subdiv);
+  }
 }
 
 /***/
 
 static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v)
 {
-       return ((int *) ccgSubSurf_getVertUserData(ss, v))[1];
+  return ((int *)ccgSubSurf_getVertUserData(ss, v))[1];
 }
 
 static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e)
 {
-       return ((int *) ccgSubSurf_getEdgeUserData(ss, e))[1];
+  return ((int *)ccgSubSurf_getEdgeUserData(ss, e))[1];
 }
 
 static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f)
 {
-       return ((int *) ccgSubSurf_getFaceUserData(ss, f))[1];
+  return ((int *)ccgSubSurf_getFaceUserData(ss, f))[1];
 }
 
 static void minmax_v3_v3v3(const float vec[3], float min[3], float max[3])
 {
-       if (min[0] > vec[0]) min[0] = vec[0];
-       if (min[1] > vec[1]) min[1] = vec[1];
-       if (min[2] > vec[2]) min[2] = vec[2];
-       if (max[0] < vec[0]) max[0] = vec[0];
-       if (max[1] < vec[1]) max[1] = vec[1];
-       if (max[2] < vec[2]) max[2] = vec[2];
+  if (min[0] > vec[0]) {
+    min[0] = vec[0];
+  }
+  if (min[1] > vec[1]) {
+    min[1] = vec[1];
+  }
+  if (min[2] > vec[2]) {
+    min[2] = vec[2];
+  }
+  if (max[0] < vec[0]) {
+    max[0] = vec[0];
+  }
+  if (max[1] < vec[1]) {
+    max[1] = vec[1];
+  }
+  if (max[2] < vec[2]) {
+    max[2] = vec[2];
+  }
 }
 
 static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3])
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGVertIterator vi;
-       CCGEdgeIterator ei;
-       CCGFaceIterator fi;
-       CCGKey key;
-       int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
-       int gridSize = ccgSubSurf_getGridSize(ss);
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  CCGVertIterator vi;
+  CCGEdgeIterator ei;
+  CCGFaceIterator fi;
+  CCGKey key;
+  int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
+  int gridSize = ccgSubSurf_getGridSize(ss);
 
 #ifdef WITH_OPENSUBDIV
-       if (ccgdm->useGpuBackend) {
-               ccgSubSurf_getMinMax(ccgdm->ss, r_min, r_max);
-               return;
-       }
+  if (ccgdm->useGpuBackend) {
+    ccgSubSurf_getMinMax(ccgdm->ss, r_min, r_max);
+    return;
+  }
 #endif
 
-       CCG_key_top_level(&key, ss);
+  CCG_key_top_level(&key, ss);
 
-       if (!ccgSubSurf_getNumVerts(ss))
-               r_min[0] = r_min[1] = r_min[2] = r_max[0] = r_max[1] = r_max[2] = 0.0;
+  if (!ccgSubSurf_getNumVerts(ss)) {
+    r_min[0] = r_min[1] = r_min[2] = r_max[0] = r_max[1] = r_max[2] = 0.0;
+  }
 
-       for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
-               CCGVert *v = ccgVertIterator_getCurrent(&vi);
-               float *co = ccgSubSurf_getVertData(ss, v);
+  for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi);
+       ccgVertIterator_next(&vi)) {
+    CCGVert *v = ccgVertIterator_getCurrent(&vi);
+    float *co = ccgSubSurf_getVertData(ss, v);
 
-               minmax_v3_v3v3(co, r_min, r_max);
-       }
+    minmax_v3_v3v3(co, r_min, r_max);
+  }
 
-       for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
-               CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
-               CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
+  for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei);
+       ccgEdgeIterator_next(&ei)) {
+    CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
+    CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
 
-               for (i = 0; i < edgeSize; i++)
-                       minmax_v3_v3v3(CCG_elem_offset_co(&key, edgeData, i), r_min, r_max);
-       }
+    for (i = 0; i < edgeSize; i++) {
+      minmax_v3_v3v3(CCG_elem_offset_co(&key, edgeData, i), r_min, r_max);
+    }
+  }
 
-       for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
-               CCGFace *f = ccgFaceIterator_getCurrent(&fi);
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+  for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi);
+       ccgFaceIterator_next(&fi)) {
+    CCGFace *f = ccgFaceIterator_getCurrent(&fi);
+    int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
 
-               for (S = 0; S < numVerts; S++) {
-                       CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+    for (S = 0; S < numVerts; S++) {
+      CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
 
-                       for (y = 0; y < gridSize; y++)
-                               for (x = 0; x < gridSize; x++)
-                                       minmax_v3_v3v3(CCG_grid_elem_co(&key, faceGridData, x, y), r_min, r_max);
-               }
-       }
+      for (y = 0; y < gridSize; y++) {
+        for (x = 0; x < gridSize; x++) {
+          minmax_v3_v3v3(CCG_grid_elem_co(&key, faceGridData, x, y), r_min, r_max);
+        }
+      }
+    }
+  }
 }
 
 static int ccgDM_getNumVerts(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
 
-       return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
+  return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
 }
 
 static int ccgDM_getNumEdges(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
 
-       return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
+  return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
 }
 
 static int ccgDM_getNumPolys(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
 
-       return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
+  return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
 }
 
 static int ccgDM_getNumTessFaces(DerivedMesh *dm)
 {
-       return dm->numTessFaceData;
+  return dm->numTessFaceData;
 }
 
 static int ccgDM_getNumLoops(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
 
-       /* All subsurf faces are quads */
-       return 4 * ccgSubSurf_getNumFinalFaces(ccgdm->ss);
+  /* All subsurf faces are quads */
+  return 4 * ccgSubSurf_getNumFinalFaces(ccgdm->ss);
 }
 
 static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGElem *vd;
-       CCGKey key;
-       int i;
-
-       CCG_key_top_level(&key, ss);
-       memset(mv, 0, sizeof(*mv));
-
-       if ((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
-               /* this vert comes from face data */
-               int lastface = ccgSubSurf_getNumFaces(ss) - 1;
-               CCGFace *f;
-               int x, y, grid, numVerts;
-               int offset;
-               int gridSize = ccgSubSurf_getGridSize(ss);
-               int gridSideVerts;
-               int gridInternalVerts;
-               int gridSideEnd;
-               int gridInternalEnd;
-
-               i = 0;
-               while (i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert) {
-                       i++;
-               }
-
-               f = ccgdm->faceMap[i].face;
-               numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               gridSideVerts = gridSize - 2;
-               gridInternalVerts = gridSideVerts * gridSideVerts;
-
-               gridSideEnd = 1 + numVerts * gridSideVerts;
-               gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
-
-               offset = vertNum - ccgdm->faceMap[i].startVert;
-               if (offset < 1) {
-                       vd = ccgSubSurf_getFaceCenterData(f);
-                       copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
-                       normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
-               }
-               else if (offset < gridSideEnd) {
-                       offset -= 1;
-                       grid = offset / gridSideVerts;
-                       x = offset % gridSideVerts + 1;
-                       vd = ccgSubSurf_getFaceGridEdgeData(ss, f, grid, x);
-                       copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
-                       normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
-               }
-               else if (offset < gridInternalEnd) {
-                       offset -= gridSideEnd;
-                       grid = offset / gridInternalVerts;
-                       offset %= gridInternalVerts;
-                       y = offset / gridSideVerts + 1;
-                       x = offset % gridSideVerts + 1;
-                       vd = ccgSubSurf_getFaceGridData(ss, f, grid, x, y);
-                       copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
-                       normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
-               }
-       }
-       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;
-               int x;
-
-               i = 0;
-               while (i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert) {
-                       i++;
-               }
-
-               e = ccgdm->edgeMap[i].edge;
-
-               x = vertNum - ccgdm->edgeMap[i].startVert + 1;
-               vd = ccgSubSurf_getEdgeData(ss, e, x);
-               copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
-               normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
-       }
-       else {
-               /* this vert comes from vert data */
-               CCGVert *v;
-               i = vertNum - ccgdm->vertMap[0].startVert;
-
-               v = ccgdm->vertMap[i].vert;
-               vd = ccgSubSurf_getVertData(ss, v);
-               copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
-               normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
-       }
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  CCGElem *vd;
+  CCGKey key;
+  int i;
+
+  CCG_key_top_level(&key, ss);
+  memset(mv, 0, sizeof(*mv));
+
+  if ((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
+    /* this vert comes from face data */
+    int lastface = ccgSubSurf_getNumFaces(ss) - 1;
+    CCGFace *f;
+    int x, y, grid, numVerts;
+    int offset;
+    int gridSize = ccgSubSurf_getGridSize(ss);
+    int gridSideVerts;
+    int gridInternalVerts;
+    int gridSideEnd;
+    int gridInternalEnd;
+
+    i = 0;
+    while (i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert) {
+      i++;
+    }
+
+    f = ccgdm->faceMap[i].face;
+    numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+    gridSideVerts = gridSize - 2;
+    gridInternalVerts = gridSideVerts * gridSideVerts;
+
+    gridSideEnd = 1 + numVerts * gridSideVerts;
+    gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
+
+    offset = vertNum - ccgdm->faceMap[i].startVert;
+    if (offset < 1) {
+      vd = ccgSubSurf_getFaceCenterData(f);
+      copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
+      normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
+    }
+    else if (offset < gridSideEnd) {
+      offset -= 1;
+      grid = offset / gridSideVerts;
+      x = offset % gridSideVerts + 1;
+      vd = ccgSubSurf_getFaceGridEdgeData(ss, f, grid, x);
+      copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
+      normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
+    }
+    else if (offset < gridInternalEnd) {
+      offset -= gridSideEnd;
+      grid = offset / gridInternalVerts;
+      offset %= gridInternalVerts;
+      y = offset / gridSideVerts + 1;
+      x = offset % gridSideVerts + 1;
+      vd = ccgSubSurf_getFaceGridData(ss, f, grid, x, y);
+      copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
+      normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
+    }
+  }
+  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;
+    int x;
+
+    i = 0;
+    while (i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert) {
+      i++;
+    }
+
+    e = ccgdm->edgeMap[i].edge;
+
+    x = vertNum - ccgdm->edgeMap[i].startVert + 1;
+    vd = ccgSubSurf_getEdgeData(ss, e, x);
+    copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
+    normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
+  }
+  else {
+    /* this vert comes from vert data */
+    CCGVert *v;
+    i = vertNum - ccgdm->vertMap[0].startVert;
+
+    v = ccgdm->vertMap[i].vert;
+    vd = ccgSubSurf_getVertData(ss, v);
+    copy_v3_v3(mv->co, CCG_elem_co(&key, vd));
+    normal_float_to_short_v3(mv->no, CCG_elem_no(&key, vd));
+  }
 }
 
 static void ccgDM_getFinalVertCo(DerivedMesh *dm, int vertNum, float r_co[3])
 {
-       MVert mvert;
+  MVert mvert;
 
-       ccgDM_getFinalVert(dm, vertNum, &mvert);
-       copy_v3_v3(r_co, mvert.co);
+  ccgDM_getFinalVert(dm, vertNum, &mvert);
+  copy_v3_v3(r_co, mvert.co);
 }
 
 static void ccgDM_getFinalVertNo(DerivedMesh *dm, int vertNum, float r_no[3])
 {
-       MVert mvert;
+  MVert mvert;
 
-       ccgDM_getFinalVert(dm, vertNum, &mvert);
-       normal_short_to_float_v3(r_no, mvert.no);
+  ccgDM_getFinalVert(dm, vertNum, &mvert);
+  normal_short_to_float_v3(r_no, mvert.no);
 }
 
 static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       int i;
-
-       memset(med, 0, sizeof(*med));
-
-       if (edgeNum < ccgdm->edgeMap[0].startEdge) {
-               /* this edge comes from face data */
-               int lastface = ccgSubSurf_getNumFaces(ss) - 1;
-               CCGFace *f;
-               int x, y, grid /*, numVerts*/;
-               int offset;
-               int gridSize = ccgSubSurf_getGridSize(ss);
-               int edgeSize = ccgSubSurf_getEdgeSize(ss);
-               int gridSideEdges;
-               int gridInternalEdges;
-
-               /* code added in bmesh but works correctly without, commenting - campbell */
-#if 0
-               int lasti, previ;
-               i = lastface;
-               lasti = 0;
-               while (1) {
-                       previ = i;
-                       if (ccgdm->faceMap[i].startEdge >= edgeNum) {
-                               i -= fabsf(i - lasti) / 2.0f;
-                       }
-                       else if (ccgdm->faceMap[i].startEdge < edgeNum) {
-                               i += fabsf(i - lasti) / 2.0f;
-                       }
-                       else {
-                               break;
-                       }
-
-                       if (i < 0) {
-                               i = 0;
-                               break;
-                       }
-
-                       if (i > lastface) {
-                               i = lastface;
-                               break;
-
-                       }
-
-                       if (i == lasti)
-                               break;
-
-                       lasti = previ;
-               }
-
-               i = i > 0 ? i - 1 : i;
-#endif
-
-               i = 0;
-               while (i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge) {
-                       i++;
-               }
-
-               f = ccgdm->faceMap[i].face;
-               /* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/
-
-               gridSideEdges = gridSize - 1;
-               gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
-
-               offset = edgeNum - ccgdm->faceMap[i].startEdge;
-               grid = offset / (gridSideEdges + gridInternalEdges);
-               offset %= (gridSideEdges + gridInternalEdges);
-
-               if (offset < gridSideEdges) {
-                       x = offset;
-                       med->v1 = getFaceIndex(ss, f, grid, x, 0, edgeSize, gridSize);
-                       med->v2 = getFaceIndex(ss, f, grid, x + 1, 0, edgeSize, gridSize);
-               }
-               else {
-                       offset -= gridSideEdges;
-                       x = (offset / 2) / gridSideEdges + 1;
-                       y = (offset / 2) % gridSideEdges;
-                       if (offset % 2 == 0) {
-                               med->v1 = getFaceIndex(ss, f, grid, x, y, edgeSize, gridSize);
-                               med->v2 = getFaceIndex(ss, f, grid, x, y + 1, edgeSize, gridSize);
-                       }
-                       else {
-                               med->v1 = getFaceIndex(ss, f, grid, y, x, edgeSize, gridSize);
-                               med->v2 = getFaceIndex(ss, f, grid, y + 1, x, edgeSize, gridSize);
-                       }
-               }
-       }
-       else {
-               /* this vert comes from edge data */
-               CCGEdge *e;
-               int edgeSize = ccgSubSurf_getEdgeSize(ss);
-               int x;
-               short *edgeFlag;
-               unsigned int flags = 0;
-
-               i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
-
-               e = ccgdm->edgeMap[i].edge;
-
-               if (!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
-
-               x = edgeNum - ccgdm->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;
-               if (edgeFlag)
-                       flags |= (*edgeFlag & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER;
-               else
-                       flags |= ME_EDGEDRAW | ME_EDGERENDER;
-
-               med->flag = flags;
-       }
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  int i;
+
+  memset(med, 0, sizeof(*med));
+
+  if (edgeNum < ccgdm->edgeMap[0].startEdge) {
+    /* this edge comes from face data */
+    int lastface = ccgSubSurf_getNumFaces(ss) - 1;
+    CCGFace *f;
+    int x, y, grid /*, numVerts*/;
+    int offset;
+    int gridSize = ccgSubSurf_getGridSize(ss);
+    int edgeSize = ccgSubSurf_getEdgeSize(ss);
+    int gridSideEdges;
+    int gridInternalEdges;
+
+    i = 0;
+    while (i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge) {
+      i++;
+    }
+
+    f = ccgdm->faceMap[i].face;
+    /* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/
+
+    gridSideEdges = gridSize - 1;
+    gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
+
+    offset = edgeNum - ccgdm->faceMap[i].startEdge;
+    grid = offset / (gridSideEdges + gridInternalEdges);
+    offset %= (gridSideEdges + gridInternalEdges);
+
+    if (offset < gridSideEdges) {
+      x = offset;
+      med->v1 = getFaceIndex(ss, f, grid, x, 0, edgeSize, gridSize);
+      med->v2 = getFaceIndex(ss, f, grid, x + 1, 0, edgeSize, gridSize);
+    }
+    else {
+      offset -= gridSideEdges;
+      x = (offset / 2) / gridSideEdges + 1;
+      y = (offset / 2) % gridSideEdges;
+      if (offset % 2 == 0) {
+        med->v1 = getFaceIndex(ss, f, grid, x, y, edgeSize, gridSize);
+        med->v2 = getFaceIndex(ss, f, grid, x, y + 1, edgeSize, gridSize);
+      }
+      else {
+        med->v1 = getFaceIndex(ss, f, grid, y, x, edgeSize, gridSize);
+        med->v2 = getFaceIndex(ss, f, grid, y + 1, x, edgeSize, gridSize);
+      }
+    }
+  }
+  else {
+    /* this vert comes from edge data */
+    CCGEdge *e;
+    int edgeSize = ccgSubSurf_getEdgeSize(ss);
+    int x;
+    short *edgeFlag;
+    unsigned int flags = 0;
+
+    i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
+
+    e = ccgdm->edgeMap[i].edge;
+
+    if (!ccgSubSurf_getEdgeNumFaces(e)) {
+      flags |= ME_LOOSEEDGE;
+    }
+
+    x = edgeNum - ccgdm->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;
+    if (edgeFlag) {
+      flags |= (*edgeFlag & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER;
+    }
+    else {
+      flags |= ME_EDGEDRAW | ME_EDGERENDER;
+    }
+
+    med->flag = flags;
+  }
 }
 
 static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-       int gridSideEdges = gridSize - 1;
-       int gridFaces = gridSideEdges * gridSideEdges;
-       int i;
-       CCGFace *f;
-       /*int numVerts;*/
-       int offset;
-       int grid;
-       int x, y;
-       /*int lastface = ccgSubSurf_getNumFaces(ss) - 1;*/ /*UNUSED*/
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-
-       memset(mf, 0, sizeof(*mf));
-       if (faceNum >= ccgdm->dm.numTessFaceData)
-               return;
-
-       i = ccgdm->reverseFaceMap[faceNum];
-
-       f = ccgdm->faceMap[i].face;
-       /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/
-
-       offset = faceNum - ccgdm->faceMap[i].startFace;
-       grid = offset / gridFaces;
-       offset %= gridFaces;
-       y = offset / gridSideEdges;
-       x = offset % gridSideEdges;
-
-       mf->v1 = getFaceIndex(ss, f, grid, x + 0, y + 0, edgeSize, gridSize);
-       mf->v2 = getFaceIndex(ss, f, grid, x + 0, y + 1, edgeSize, gridSize);
-       mf->v3 = getFaceIndex(ss, f, grid, x + 1, y + 1, edgeSize, gridSize);
-       mf->v4 = getFaceIndex(ss, f, grid, x + 1, y + 0, edgeSize, gridSize);
-
-       if (faceFlags) {
-               mf->flag = faceFlags[i].flag;
-               mf->mat_nr = faceFlags[i].mat_nr;
-       }
-       else {
-               mf->flag = ME_SMOOTH;
-       }
-
-       mf->edcode = 0;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  int gridSize = ccgSubSurf_getGridSize(ss);
+  int edgeSize = ccgSubSurf_getEdgeSize(ss);
+  int gridSideEdges = gridSize - 1;
+  int gridFaces = gridSideEdges * gridSideEdges;
+  int i;
+  CCGFace *f;
+  /*int numVerts;*/
+  int offset;
+  int grid;
+  int x, y;
+  /*int lastface = ccgSubSurf_getNumFaces(ss) - 1;*/ /*UNUSED*/
+  DMFlagMat *faceFlags = ccgdm->faceFlags;
+
+  memset(mf, 0, sizeof(*mf));
+  if (faceNum >= ccgdm->dm.numTessFaceData) {
+    return;
+  }
+
+  i = ccgdm->reverseFaceMap[faceNum];
+
+  f = ccgdm->faceMap[i].face;
+  /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/
+
+  offset = faceNum - ccgdm->faceMap[i].startFace;
+  grid = offset / gridFaces;
+  offset %= gridFaces;
+  y = offset / gridSideEdges;
+  x = offset % gridSideEdges;
+
+  mf->v1 = getFaceIndex(ss, f, grid, x + 0, y + 0, edgeSize, gridSize);
+  mf->v2 = getFaceIndex(ss, f, grid, x + 0, y + 1, edgeSize, gridSize);
+  mf->v3 = getFaceIndex(ss, f, grid, x + 1, y + 1, edgeSize, gridSize);
+  mf->v4 = getFaceIndex(ss, f, grid, x + 1, y + 0, edgeSize, gridSize);
+
+  if (faceFlags) {
+    mf->flag = faceFlags[i].flag;
+    mf->mat_nr = faceFlags[i].mat_nr;
+  }
+  else {
+    mf->flag = ME_SMOOTH;
+  }
+
+  mf->edcode = 0;
 }
 
 /* Translate GridHidden into the ME_HIDE flag for MVerts. Assumes
  * vertices are in the order output by ccgDM_copyFinalVertArray. */
-void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly,
-                              MVert *mvert, const MDisps *mdisps)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       int level = ccgSubSurf_getSubdivisionLevels(ss);
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-       int totface = ccgSubSurf_getNumFaces(ss);
-       int i, j, x, y;
-
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-
-               for (j = 0; j < mpoly[i].totloop; j++) {
-                       const MDisps *md = &mdisps[mpoly[i].loopstart + j];
-                       int hidden_gridsize = BKE_ccg_gridsize(md->level);
-                       int factor = BKE_ccg_factor(level, md->level);
-                       BLI_bitmap *hidden = md->hidden;
-
-                       if (!hidden)
-                               continue;
-
-                       for (y = 0; y < gridSize; y++) {
-                               for (x = 0; x < gridSize; x++) {
-                                       int vndx, offset;
-
-                                       vndx = getFaceIndex(ss, f, j, x, y, edgeSize, gridSize);
-                                       offset = (y * factor) * hidden_gridsize + (x * factor);
-                                       if (BLI_BITMAP_TEST(hidden, offset))
-                                               mvert[vndx].flag |= ME_HIDE;
-                               }
-                       }
-               }
-       }
+void subsurf_copy_grid_hidden(DerivedMesh *dm,
+                              const MPoly *mpoly,
+                              MVert *mvert,
+                              const MDisps *mdisps)
+{
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  int level = ccgSubSurf_getSubdivisionLevels(ss);
+  int gridSize = ccgSubSurf_getGridSize(ss);
+  int edgeSize = ccgSubSurf_getEdgeSize(ss);
+  int totface = ccgSubSurf_getNumFaces(ss);
+  int i, j, x, y;
+
+  for (i = 0; i < totface; i++) {
+    CCGFace *f = ccgdm->faceMap[i].face;
+
+    for (j = 0; j < mpoly[i].totloop; j++) {
+      const MDisps *md = &mdisps[mpoly[i].loopstart + j];
+      int hidden_gridsize = BKE_ccg_gridsize(md->level);
+      int factor = BKE_ccg_factor(level, md->level);
+      BLI_bitmap *hidden = md->hidden;
+
+      if (!hidden) {
+        continue;
+      }
+
+      for (y = 0; y < gridSize; y++) {
+        for (x = 0; x < gridSize; x++) {
+          int vndx, offset;
+
+          vndx = getFaceIndex(ss, f, j, x, y, edgeSize, gridSize);
+          offset = (y * factor) * hidden_gridsize + (x * factor);
+          if (BLI_BITMAP_TEST(hidden, offset)) {
+            mvert[vndx].flag |= ME_HIDE;
+          }
+        }
+      }
+    }
+  }
 }
 
 /* Translate GridPaintMask into vertex paint masks. Assumes vertices
  * are in the order output by ccgDM_copyFinalVertArray. */
-void subsurf_copy_grid_paint_mask(DerivedMesh *dm, const MPoly *mpoly,
+void subsurf_copy_grid_paint_mask(DerivedMesh *dm,
+                                  const MPoly *mpoly,
                                   float *paint_mask,
                                   const GridPaintMask *grid_paint_mask)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       int level = ccgSubSurf_getSubdivisionLevels(ss);
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-       int totface = ccgSubSurf_getNumFaces(ss);
-       int i, j, x, y, factor, gpm_gridsize;
-
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               const MPoly *p = &mpoly[i];
-
-               for (j = 0; j < p->totloop; j++) {
-                       const GridPaintMask *gpm = &grid_paint_mask[p->loopstart + j];
-                       if (!gpm->data)
-                               continue;
-
-                       factor = BKE_ccg_factor(level, gpm->level);
-                       gpm_gridsize = BKE_ccg_gridsize(gpm->level);
-
-                       for (y = 0; y < gridSize; y++) {
-                               for (x = 0; x < gridSize; x++) {
-                                       int vndx, offset;
-
-                                       vndx = getFaceIndex(ss, f, j, x, y, edgeSize, gridSize);
-                                       offset = y * factor * gpm_gridsize + x * factor;
-                                       paint_mask[vndx] = gpm->data[offset];
-                               }
-                       }
-               }
-       }
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  int level = ccgSubSurf_getSubdivisionLevels(ss);
+  int gridSize = ccgSubSurf_getGridSize(ss);
+  int edgeSize = ccgSubSurf_getEdgeSize(ss);
+  int totface = ccgSubSurf_getNumFaces(ss);
+  int i, j, x, y, factor, gpm_gridsize;
+
+  for (i = 0; i < totface; i++) {
+    CCGFace *f = ccgdm->faceMap[i].face;
+    const MPoly *p = &mpoly[i];
+
+    for (j = 0; j < p->totloop; j++) {
+      const GridPaintMask *gpm = &grid_paint_mask[p->loopstart + j];
+      if (!gpm->data) {
+        continue;
+      }
+
+      factor = BKE_ccg_factor(level, gpm->level);
+      gpm_gridsize = BKE_ccg_gridsize(gpm->level);
+
+      for (y = 0; y < gridSize; y++) {
+        for (x = 0; x < gridSize; x++) {
+          int vndx, offset;
+
+          vndx = getFaceIndex(ss, f, j, x, y, edgeSize, gridSize);
+          offset = y * factor * gpm_gridsize + x * factor;
+          paint_mask[vndx] = gpm->data[offset];
+        }
+      }
+    }
+  }
 }
 
 /* utility function */
 BLI_INLINE void ccgDM_to_MVert(MVert *mv, const CCGKey *key, CCGElem *elem)
 {
-       copy_v3_v3(mv->co, CCG_elem_co(key, elem));
-       normal_float_to_short_v3(mv->no, CCG_elem_no(key, elem));
-       mv->flag = mv->bweight = 0;
+  copy_v3_v3(mv->co, CCG_elem_co(key, elem));
+  normal_float_to_short_v3(mv->no, CCG_elem_no(key, elem));
+  mv->flag = mv->bweight = 0;
 }
 
 static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGElem *vd;
-       CCGKey key;
-       int index;
-       int totvert, totedge, totface;
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-       unsigned int i = 0;
-
-       CCG_key_top_level(&key, ss);
-
-       totface = ccgSubSurf_getNumFaces(ss);
-       for (index = 0; index < totface; index++) {
-               CCGFace *f = ccgdm->faceMap[index].face;
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               vd = ccgSubSurf_getFaceCenterData(f);
-               ccgDM_to_MVert(&mvert[i++], &key, vd);
-
-               for (S = 0; S < numVerts; S++) {
-                       for (x = 1; x < gridSize - 1; x++) {
-                               vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
-                               ccgDM_to_MVert(&mvert[i++], &key, vd);
-                       }
-               }
-
-               for (S = 0; S < numVerts; S++) {
-                       for (y = 1; y < gridSize - 1; y++) {
-                               for (x = 1; x < gridSize - 1; x++) {
-                                       vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y);
-                                       ccgDM_to_MVert(&mvert[i++], &key, vd);
-                               }
-                       }
-               }
-       }
-
-       totedge = ccgSubSurf_getNumEdges(ss);
-       for (index = 0; index < totedge; index++) {
-               CCGEdge *e = ccgdm->edgeMap[index].edge;
-               int x;
-
-               for (x = 1; x < edgeSize - 1; x++) {
-                       /* This gives errors with -debug-fpe
-                        * the normals don't seem to be unit length.
-                        * this is most likely caused by edges with no
-                        * faces which are now zerod out, see comment in:
-                        * ccgSubSurf__calcVertNormals(), - campbell */
-                       vd = ccgSubSurf_getEdgeData(ss, e, x);
-                       ccgDM_to_MVert(&mvert[i++], &key, vd);
-               }
-       }
-
-       totvert = ccgSubSurf_getNumVerts(ss);
-       for (index = 0; index < totvert; index++) {
-               CCGVert *v = ccgdm->vertMap[index].vert;
-
-               vd = ccgSubSurf_getVertData(ss, v);
-               ccgDM_to_MVert(&mvert[i++], &key, vd);
-       }
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  CCGElem *vd;
+  CCGKey key;
+  int index;
+  int totvert, totedge, totface;
+  int gridSize = ccgSubSurf_getGridSize(ss);
+  int edgeSize = ccgSubSurf_getEdgeSize(ss);
+  unsigned int i = 0;
+
+  CCG_key_top_level(&key, ss);
+
+  totface = ccgSubSurf_getNumFaces(ss);
+  for (index = 0; index < totface; index++) {
+    CCGFace *f = ccgdm->faceMap[index].face;
+    int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+    vd = ccgSubSurf_getFaceCenterData(f);
+    ccgDM_to_MVert(&mvert[i++], &key, vd);
+
+    for (S = 0; S < numVerts; S++) {
+      for (x = 1; x < gridSize - 1; x++) {
+        vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
+        ccgDM_to_MVert(&mvert[i++], &key, vd);
+      }
+    }
+
+    for (S = 0; S < numVerts; S++) {
+      for (y = 1; y < gridSize - 1; y++) {
+        for (x = 1; x < gridSize - 1; x++) {
+          vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y);
+          ccgDM_to_MVert(&mvert[i++], &key, vd);
+        }
+      }
+    }
+  }
+
+  totedge = ccgSubSurf_getNumEdges(ss);
+  for (index = 0; index < totedge; index++) {
+    CCGEdge *e = ccgdm->edgeMap[index].edge;
+    int x;
+
+    for (x = 1; x < edgeSize - 1; x++) {
+      /* This gives errors with -debug-fpe
+       * the normals don't seem to be unit length.
+       * this is most likely caused by edges with no
+       * faces which are now zerod out, see comment in:
+       * ccgSubSurf__calcVertNormals(), - campbell */
+      vd = ccgSubSurf_getEdgeData(ss, e, x);
+      ccgDM_to_MVert(&mvert[i++], &key, vd);
+    }
+  }
+
+  totvert = ccgSubSurf_getNumVerts(ss);
+  for (index = 0; index < totvert; index++) {
+    CCGVert *v = ccgdm->vertMap[index].vert;
+
+    vd = ccgSubSurf_getVertData(ss, v);
+    ccgDM_to_MVert(&mvert[i++], &key, vd);
+  }
 }
 
-
 /* utility function */
 BLI_INLINE void ccgDM_to_MEdge(MEdge *med, const int v1, const int v2, const short flag)
 {
-       med->v1 = v1;
-       med->v2 = v2;
-       med->crease = med->bweight = 0;
-       med->flag = flag;
+  med->v1 = v1;
+  med->v2 = v2;
+  med->crease = med->bweight = 0;
+  med->flag = flag;
 }
 
 static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       int index;
-       int totedge, totface;
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-       unsigned int i = 0;
-       short *edgeFlags = ccgdm->edgeFlags;
-       const short ed_interior_flag = ccgdm->drawInteriorEdges ? (ME_EDGEDRAW | ME_EDGERENDER) : 0;
-
-       totface = ccgSubSurf_getNumFaces(ss);
-       for (index = 0; index < totface; index++) {
-               CCGFace *f = ccgdm->faceMap[index].face;
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               for (S = 0; S < numVerts; S++) {
-                       for (x = 0; x < gridSize - 1; x++) {
-                               ccgDM_to_MEdge(&medge[i++],
-                                              getFaceIndex(ss, f, S, x,     0, edgeSize, gridSize),
-                                              getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize),
-                                              ed_interior_flag);
-                       }
-
-                       for (x = 1; x < gridSize - 1; x++) {
-                               for (y = 0; y < gridSize - 1; y++) {
-                                       ccgDM_to_MEdge(&medge[i++],
-                                                      getFaceIndex(ss, f, S, x, y,    edgeSize, gridSize),
-                                                      getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize),
-                                                      ed_interior_flag);
-                                       ccgDM_to_MEdge(&medge[i++],
-                                                      getFaceIndex(ss, f, S, y, x,     edgeSize, gridSize),
-                                                      getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize),
-                                                      ed_interior_flag);
-                               }
-                       }
-               }
-       }
-
-       totedge = ccgSubSurf_getNumEdges(ss);
-       for (index = 0; index < totedge; index++) {
-               CCGEdge *e = ccgdm->edgeMap[index].edge;
-               short ed_flag = 0;
-               int x;
-               int edgeIdx = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(e));
-
-               if (!ccgSubSurf_getEdgeNumFaces(e)) {
-                       ed_flag |= ME_LOOSEEDGE;
-               }
-
-               if (edgeFlags) {
-                       if (edgeIdx != -1) {
-                               ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER);
-                       }
-               }
-               else {
-                       ed_flag |= ME_EDGEDRAW | ME_EDGERENDER;
-               }
-
-               for (x = 0; x < edgeSize - 1; x++) {
-                       ccgDM_to_MEdge(&medge[i++],
-                                      getEdgeIndex(ss, e, x, edgeSize),
-                                      getEdgeIndex(ss, e, x + 1, edgeSize),
-                                      ed_flag);
-               }
-       }
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  int index;
+  int totedge, totface;
+  int gridSize = ccgSubSurf_getGridSize(ss);
+  int edgeSize = ccgSubSurf_getEdgeSize(ss);
+  unsigned int i = 0;
+  short *edgeFlags = ccgdm->edgeFlags;
+  const short ed_interior_flag = ccgdm->drawInteriorEdges ? (ME_EDGEDRAW | ME_EDGERENDER) : 0;
+
+  totface = ccgSubSurf_getNumFaces(ss);
+  for (index = 0; index < totface; index++) {
+    CCGFace *f = ccgdm->faceMap[index].face;
+    int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+    for (S = 0; S < numVerts; S++) {
+      for (x = 0; x < gridSize - 1; x++) {
+        ccgDM_to_MEdge(&medge[i++],
+                       getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize),
+                       getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize),
+                       ed_interior_flag);
+      }
+
+      for (x = 1; x < gridSize - 1; x++) {
+        for (y = 0; y < gridSize - 1; y++) {
+          ccgDM_to_MEdge(&medge[i++],
+                         getFaceIndex(ss, f, S, x, y, edgeSize, gridSize),
+                         getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize),
+                         ed_interior_flag);
+          ccgDM_to_MEdge(&medge[i++],
+                         getFaceIndex(ss, f, S, y, x, edgeSize, gridSize),
+                         getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize),
+                         ed_interior_flag);
+        }
+      }
+    }
+  }
+
+  totedge = ccgSubSurf_getNumEdges(ss);
+  for (index = 0; index < totedge; index++) {
+    CCGEdge *e = ccgdm->edgeMap[index].edge;
+    short ed_flag = 0;
+    int x;
+    int edgeIdx = POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(e));
+
+    if (!ccgSubSurf_getEdgeNumFaces(e)) {
+      ed_flag |= ME_LOOSEEDGE;
+    }
+
+    if (edgeFlags) {
+      if (edgeIdx != -1) {
+        ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER);
+      }
+    }
+    else {
+      ed_flag |= ME_EDGEDRAW | ME_EDGERENDER;
+    }
+
+    for (x = 0; x < edgeSize - 1; x++) {
+      ccgDM_to_MEdge(&medge[i++],
+                     getEdgeIndex(ss, e, x, edgeSize),
+                     getEdgeIndex(ss, e, x + 1, edgeSize),
+                     ed_flag);
+    }
+  }
 }
 
 static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       int index;
-       int totface;
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-       int i = 0;
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-
-       totface = dm->getNumTessFaces(dm);
-       for (index = 0; index < totface; index++) {
-               CCGFace *f = ccgdm->faceMap[index].face;
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
-               /* keep types in sync with MFace, avoid many conversions */
-               char flag = (faceFlags) ? faceFlags[index].flag : ME_SMOOTH;
-               short mat_nr = (faceFlags) ? faceFlags[index].mat_nr : 0;
-
-               for (S = 0; S < numVerts; S++) {
-                       for (y = 0; y < gridSize - 1; y++) {
-                               for (x = 0; x < gridSize - 1; x++) {
-                                       MFace *mf = &mface[i];
-                                       mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
-                                                             edgeSize, gridSize);
-                                       mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
-                                                             edgeSize, gridSize);
-                                       mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
-                                                             edgeSize, gridSize);
-                                       mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
-                                                             edgeSize, gridSize);
-                                       mf->mat_nr = mat_nr;
-                                       mf->flag = flag;
-                                       mf->edcode = 0;
-
-                                       i++;
-                               }
-                       }
-               }
-       }
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  int index;
+  int totface;
+  int gridSize = ccgSubSurf_getGridSize(ss);
+  int edgeSize = ccgSubSurf_getEdgeSize(ss);
+  int i = 0;
+  DMFlagMat *faceFlags = ccgdm->faceFlags;
+
+  totface = dm->getNumTessFaces(dm);
+  for (index = 0; index < totface; index++) {
+    CCGFace *f = ccgdm->faceMap[index].face;
+    int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+    /* keep types in sync with MFace, avoid many conversions */
+    char flag = (faceFlags) ? faceFlags[index].flag : ME_SMOOTH;
+    short mat_nr = (faceFlags) ? faceFlags[index].mat_nr : 0;
+
+    for (S = 0; S < numVerts; S++) {
+      for (y = 0; y < gridSize - 1; y++) {
+        for (x = 0; x < gridSize - 1; x++) {
+          MFace *mf = &mface[i];
+          mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edgeSize, gridSize);
+          mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edgeSize, gridSize);
+          mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edgeSize, gridSize);
+          mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edgeSize, gridSize);
+          mf->mat_nr = mat_nr;
+          mf->flag = flag;
+          mf->edcode = 0;
+
+          i++;
+        }
+      }
+    }
+  }
 }
 
 typedef struct CopyFinalLoopArrayData {
-       CCGDerivedMesh *ccgdm;
-       MLoop *mloop;
-       int grid_size;
-       int *grid_offset;
-       int edge_size;
-       size_t mloop_index;
+  CCGDerivedMesh *ccgdm;
+  MLoop *mloop;
+  int grid_size;
+  int *grid_offset;
+  int edge_size;
+  size_t mloop_index;
 } CopyFinalLoopArrayData;
 
-static void copyFinalLoopArray_task_cb(
-        void *__restrict userdata,
-        const int iter,
-        const ParallelRangeTLS *__restrict UNUSED(tls))
-{
-       CopyFinalLoopArrayData *data = userdata;
-       CCGDerivedMesh *ccgdm = data->ccgdm;
-       CCGSubSurf *ss = ccgdm->ss;
-       const int grid_size = data->grid_size;
-       const int edge_size = data->edge_size;
-       CCGFace *f = ccgdm->faceMap[iter].face;
-       const int num_verts = ccgSubSurf_getFaceNumVerts(f);
-       const int grid_index = data->grid_offset[iter];
-       const size_t loop_index = 4 * (size_t)grid_index * (grid_size - 1) * (grid_size - 1);
-       MLoop *ml = &data->mloop[loop_index];
-       for (int S = 0; S < num_verts; S++) {
-               for (int y = 0; y < grid_size - 1; y++) {
-                       for (int x = 0; x < grid_size - 1; x++) {
-
-                               uint v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
-                                                      edge_size, grid_size);
-                               uint v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
-                                                      edge_size, grid_size);
-                               uint v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
-                                                      edge_size, grid_size);
-                               uint v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
-                                                      edge_size, grid_size);
-
-                               ml->v = v1;
-                               ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v1, v2));
-                               ml++;
-
-                               ml->v = v2;
-                               ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v2, v3));
-                               ml++;
-
-                               ml->v = v3;
-                               ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v3, v4));
-                               ml++;
-
-                               ml->v = v4;
-                               ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v4, v1));
-                               ml++;
-                       }
-               }
-       }
+static void copyFinalLoopArray_task_cb(void *__restrict userdata,
+                                       const int iter,
+                                       const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+  CopyFinalLoopArrayData *data = userdata;
+  CCGDerivedMesh *ccgdm = data->ccgdm;
+  CCGSubSurf *ss = ccgdm->ss;
+  const int grid_size = data->grid_size;
+  const int edge_size = data->edge_size;
+  CCGFace *f = ccgdm->faceMap[iter].face;
+  const int num_verts = ccgSubSurf_getFaceNumVerts(f);
+  const int grid_index = data->grid_offset[iter];
+  const size_t loop_index = 4 * (size_t)grid_index * (grid_size - 1) * (grid_size - 1);
+  MLoop *ml = &data->mloop[loop_index];
+  for (int S = 0; S < num_verts; S++) {
+    for (int y = 0; y < grid_size - 1; y++) {
+      for (int x = 0; x < grid_size - 1; x++) {
+
+        uint v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edge_size, grid_size);
+        uint v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edge_size, grid_size);
+        uint v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edge_size, grid_size);
+        uint v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edge_size, grid_size);
+
+        ml->v = v1;
+        ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v1, v2));
+        ml++;
+
+        ml->v = v2;
+        ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v2, v3));
+        ml++;
+
+        ml->v = v3;
+        ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v3, v4));
+        ml++;
+
+        ml->v = v4;
+        ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(ccgdm->ehash, v4, v1));
+        ml++;
+      }
+    }
+  }
 }
 
 static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-
-       if (!ccgdm->ehash) {
-               BLI_mutex_lock(&ccgdm->loops_cache_lock);
-               if (!ccgdm->ehash) {
-                       MEdge *medge;
-                       EdgeHash *ehash;
-
-                       ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData);
-                       medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm);
-
-                       for (int i = 0; i < ccgdm->dm.numEdgeData; i++) {
-                               BLI_edgehash_insert(ehash, medge[i].v1, medge[i].v2, POINTER_FROM_INT(i));
-                       }
-
-                       atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash);
-               }
-               BLI_mutex_unlock(&ccgdm->loops_cache_lock);
-       }
-
-       CopyFinalLoopArrayData data;
-       data.ccgdm = ccgdm;
-       data.mloop = mloop;
-       data.grid_size = ccgSubSurf_getGridSize(ss);
-       data.grid_offset = dm->getGridOffset(dm);
-       data.edge_size = ccgSubSurf_getEdgeSize(ss);
-
-       /* NOTE: For a dense subdivision we've got enough work for each face and
-        * hence can dedicate whole thread to single face. For less dense
-        * subdivision we handle multiple faces per thread.
-        */
-       data.mloop_index = data.grid_size >= 5 ? 1 : 8;
-
-       ParallelRangeSettings settings;
-       BLI_parallel_range_settings_defaults(&settings);
-       settings.min_iter_per_thread = 1;
-
-       BLI_task_parallel_range(0, ccgSubSurf_getNumFaces(ss),
-                               &data,
-                               copyFinalLoopArray_task_cb,
-                               &settings);
-}
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
 
-static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mpoly)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       int index;
-       int totface;
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       /* int edgeSize = ccgSubSurf_getEdgeSize(ss); */ /* UNUSED */
-       int i = 0, k = 0;
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-
-       totface = ccgSubSurf_getNumFaces(ss);
-       for (index = 0; index < totface; index++) {
-               CCGFace *f = ccgdm->faceMap[index].face;
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
-               int flag = (faceFlags) ? faceFlags[index].flag : ME_SMOOTH;
-               int mat_nr = (faceFlags) ? faceFlags[index].mat_nr : 0;
-
-               for (S = 0; S < numVerts; S++) {
-                       for (y = 0; y < gridSize - 1; y++) {
-                               for (x = 0; x < gridSize - 1; x++) {
-                                       MPoly *mp = &mpoly[i];
-
-                                       mp->mat_nr = mat_nr;
-                                       mp->flag = flag;
-                                       mp->loopstart = k;
-                                       mp->totloop = 4;
-
-                                       k += 4;
-                                       i++;
-                               }
-                       }
-               }
-       }
-}
+  if (!ccgdm->ehash) {
+    BLI_mutex_lock(&ccgdm->loops_cache_lock);
+    if (!ccgdm->ehash) {
+      MEdge *medge;
+      EdgeHash *ehash;
 
-static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3])
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int i;
-       CCGVertIterator vi;
-       CCGEdgeIterator ei;
-       CCGFaceIterator fi;
-       CCGFace **faceMap2;
-       CCGEdge **edgeMap2;
-       CCGVert **vertMap2;
-       int index, totvert, totedge, totface;
-
-       totvert = ccgSubSurf_getNumVerts(ss);
-       vertMap2 = MEM_mallocN(totvert * sizeof(*vertMap2), "vertmap");
-       for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
-               CCGVert *v = ccgVertIterator_getCurrent(&vi);
-
-               vertMap2[POINTER_AS_INT(ccgSubSurf_getVertVertHandle(v))] = v;
-       }
-
-       totedge = ccgSubSurf_getNumEdges(ss);
-       edgeMap2 = MEM_mallocN(totedge * sizeof(*edgeMap2), "edgemap");
-       for (ccgSubSurf_initEdgeIterator(ss, &ei), i = 0; !ccgEdgeIterator_isStopped(&ei); i++, ccgEdgeIterator_next(&ei)) {
-               CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
-
-               edgeMap2[POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
-       }
-
-       totface = ccgSubSurf_getNumFaces(ss);
-       faceMap2 = MEM_mallocN(totface * sizeof(*faceMap2), "facemap");
-       for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
-               CCGFace *f = ccgFaceIterator_getCurrent(&fi);
-
-               faceMap2[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))] = f;
-       }
-
-       i = 0;
-       for (index = 0; index < totface; index++) {
-               CCGFace *f = faceMap2[index];
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               copy_v3_v3(cos[i++], ccgSubSurf_getFaceCenterData(f));
-
-               for (S = 0; S < numVerts; S++) {
-                       for (x = 1; x < gridSize - 1; x++) {
-                               copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
-                       }
-               }
-
-               for (S = 0; S < numVerts; S++) {
-                       for (y = 1; y < gridSize - 1; y++) {
-                               for (x = 1; x < gridSize - 1; x++) {
-                                       copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridData(ss, f, S, x, y));
-                               }
-                       }
-               }
-       }
-
-       for (index = 0; index < totedge; index++) {
-               CCGEdge *e = edgeMap2[index];
-               int x;
-
-               for (x = 1; x < edgeSize - 1; x++) {
-                       copy_v3_v3(cos[i++], ccgSubSurf_getEdgeData(ss, e, x));
-               }
-       }
-
-       for (index = 0; index < totvert; index++) {
-               CCGVert *v = vertMap2[index];
-               copy_v3_v3(cos[i++], ccgSubSurf_getVertData(ss, v));
-       }
-
-       MEM_freeN(vertMap2);
-       MEM_freeN(edgeMap2);
-       MEM_freeN(faceMap2);
-}
+      ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData);
+      medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm);
 
-static void ccgDM_foreachMappedVert(
-        DerivedMesh *dm,
-        void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]),
-        void *userData,
-        DMForeachFlag flag)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGVertIterator vi;
-       CCGKey key;
-       CCG_key_top_level(&key, ccgdm->ss);
-
-       for (ccgSubSurf_initVertIterator(ccgdm->ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
-               CCGVert *v = ccgVertIterator_getCurrent(&vi);
-               const int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
-
-               if (index != -1) {
-                       CCGElem *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
-                       const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL;
-                       func(userData, index, CCG_elem_co(&key, vd), no, NULL);
-               }
-       }
-}
+      for (int i = 0; i < ccgdm->dm.numEdgeData; i++) {
+        BLI_edgehash_insert(ehash, medge[i].v1, medge[i].v2, POINTER_FROM_INT(i));
+      }
 
-static void ccgDM_foreachMappedEdge(
-        DerivedMesh *dm,
-        void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
-        void *userData)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGEdgeIterator ei;
-       CCGKey key;
-       int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
-
-       CCG_key_top_level(&key, ss);
-
-       for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
-               CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
-               const int index = ccgDM_getEdgeMapIndex(ss, e);
-
-               if (index != -1) {
-                       CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
-                       for (i = 0; i < edgeSize - 1; i++) {
-                               func(userData, index, CCG_elem_offset_co(&key, edgeData, i), CCG_elem_offset_co(&key, edgeData, i + 1));
-                       }
-               }
-       }
-}
+      atomic_cas_ptr((void **)&ccgdm->ehash, ccgdm->ehash, ehash);
+    }
+    BLI_mutex_unlock(&ccgdm->loops_cache_lock);
+  }
 
-static void ccgDM_foreachMappedLoop(
-        DerivedMesh *dm,
-        void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]),
-        void *userData,
-        DMForeachFlag flag)
-{
-       /* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData, EditDerivedBMesh would
-        * return loop data from bmesh itself. */
-       const float (*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) : NULL;
-
-       MVert *mv = dm->getVertArray(dm);
-       MLoop *ml = dm->getLoopArray(dm);
-       MPoly *mp = dm->getPolyArray(dm);
-       const int *v_index = dm->getVertDataArray(dm, CD_ORIGINDEX);
-       const int *f_index = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-       int p_idx, i;
-
-       for (p_idx = 0; p_idx < dm->numPolyData; ++p_idx, ++mp) {
-               for (i = 0; i < mp->totloop; ++i, ++ml) {
-                       const int v_idx = v_index ? v_index[ml->v] : ml->v;
-                       const int f_idx = f_index ? f_index[p_idx] : p_idx;
-                       const float *no = lnors ? *lnors++ : NULL;
-                       if (!ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
-                               func(userData, v_idx, f_idx, mv[ml->v].co, no);
-                       }
-               }
-       }
-}
+  CopyFinalLoopArrayData data;
+  data.ccgdm = ccgdm;
+  data.mloop = mloop;
+  data.grid_size = ccgSubSurf_getGridSize(ss);
+  data.grid_offset = dm->getGridOffset(dm);
+  data.edge_size = ccgSubSurf_getEdgeSize(ss);
 
-static void ccgDM_drawVerts(DerivedMesh *dm)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       CCGVertIterator vi;
-       CCGEdgeIterator ei;
-       CCGFaceIterator fi;
-
-       glBegin(GL_POINTS);
-       for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) {
-               CCGVert *v = ccgVertIterator_getCurrent(&vi);
-               glVertex3fv(ccgSubSurf_getVertData(ss, v));
-       }
-
-       for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
-               CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
-               int x;
-
-               for (x = 1; x < edgeSize - 1; x++)
-                       glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x));
-       }
-
-       for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
-               CCGFace *f = ccgFaceIterator_getCurrent(&fi);
-               int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(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));
-               for (S = 0; S < numVerts; S++)
-                       for (y = 1; y < gridSize - 1; y++)
-                               for (x = 1; x < gridSize - 1; x++)
-                                       glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y));
-       }
-       glEnd();
-}
+  /* NOTE: For a dense subdivision we've got enough work for each face and
+   * hence can dedicate whole thread to single face. For less dense
+   * subdivision we handle multiple faces per thread.
+   */
+  data.mloop_index = data.grid_size >= 5 ? 1 : 8;
 
-static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm)
-{
-       if (ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) {
-               CCGFace **faces;
-               int totface;
-
-               BKE_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface);
-               if (totface) {
-                       ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface);
-                       ccgSubSurf_updateNormals(ccgdm->ss, faces, totface);
-                       MEM_freeN(faces);
-               }
-       }
-}
-
-static void ccgDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
-{
-       GPUDrawObject *gdo;
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-
-#ifdef WITH_OPENSUBDIV
-       if (ccgdm->useGpuBackend) {
-               /* TODO(sergey): We currently only support all edges drawing. */
-               if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true, -1)) {
-                       ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1);
-               }
-               return;
-       }
-#endif
-
-       ccgdm_pbvh_update(ccgdm);
-
-/* old debug feature for edges, unsupported for now */
-#if 0
-       int useAging = 0;
-
-       if (!(G.f & G_BACKBUFSEL)) {
-               CCGSubSurf *ss = ccgdm->ss;
-               ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
-
-               /* it needs some way to upload this to VBO now */
-               if (useAging) {
-                       int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4;
-                       glColor3ub(0, ageCol > 0 ? ageCol : 0, 0);
-               }
-       }
-#endif
+  ParallelRangeSettings settings;
+  BLI_parallel_range_settings_defaults(&settings);
+  settings.min_iter_per_thread = 1;
 
-       GPU_edge_setup(dm);
-       gdo = dm->drawObject;
-       if (gdo->edges && gdo->points) {
-               if (drawAllEdges && drawLooseEdges) {
-                       GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, (gdo->totedge - gdo->totinterior) * 2);
-               }
-               else if (drawAllEdges) {
-                       GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->loose_edge_offset * 2);
-               }
-               else {
-                       GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->tot_edge_drawn * 2);
-                       GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->loose_edge_offset * 2, gdo->tot_loose_edge_drawn * 2);
-               }
-       }
-
-       if (gdo->edges && ccgdm->drawInteriorEdges) {
-               GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->interior_offset * 2, gdo->totinterior * 2);
-       }
-       GPU_buffers_unbind();
+  BLI_task_parallel_range(
+      0, ccgSubSurf_getNumFaces(ss), &data, copyFinalLoopArray_task_cb, &settings);
 }
 
-static void ccgDM_drawLooseEdges(DerivedMesh *dm)
+static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mpoly)
 {
-       int start;
-       int count;
-
-#ifdef WITH_OPENSUBDIV
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       if (ccgdm->useGpuBackend) {
-               /* TODO(sergey): Needs implementation. */
-               return;
-       }
-#endif
-
-       GPU_edge_setup(dm);
-
-       start = (dm->drawObject->loose_edge_offset * 2);
-       count = (dm->drawObject->interior_offset - dm->drawObject->loose_edge_offset) * 2;
-
-       if (count) {
-               GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, start, count);
-       }
-
-       GPU_buffers_unbind();
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  int index;
+  int totface;
+  int gridSize = ccgSubSurf_getGridSize(ss);
+  /* int edgeSize = ccgSubSurf_getEdgeSize(ss); */ /* UNUSED */
+  int i = 0, k = 0;
+  DMFlagMat *faceFlags = ccgdm->faceFlags;
+
+  totface = ccgSubSurf_getNumFaces(ss);
+  for (index = 0; index < totface; index++) {
+    CCGFace *f = ccgdm->faceMap[index].face;
+    int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+    int flag = (faceFlags) ? faceFlags[index].flag : ME_SMOOTH;
+    int mat_nr = (faceFlags) ? faceFlags[index].mat_nr : 0;
+
+    for (S = 0; S < numVerts; S++) {
+      for (y = 0; y < gridSize - 1; y++) {
+        for (x = 0; x < gridSize - 1; x++) {
+          MPoly *mp = &mpoly[i];
+
+          mp->mat_nr = mat_nr;
+          mp->flag = flag;
+          mp->loopstart = k;
+          mp->totloop = 4;
+
+          k += 4;
+          i++;
+        }
+      }
+    }
+  }
 }
 
-static void ccgDM_NormalFast(float *a, float *b, float *c, float *d, float no[3])
-{
-       float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
-       float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
-
-       no[0] = b_dY * a_cZ - b_dZ * a_cY;
-       no[1] = b_dZ * a_cX - b_dX * a_cZ;
-       no[2] = b_dX * a_cY - b_dY * a_cX;
-
-       normalize_v3(no);
-}
-
-
-static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
+static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3])
 {
-       float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
-       float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
-       float no[3];
-
-       no[0] = b_dY * a_cZ - b_dZ * a_cY;
-       no[1] = b_dZ * a_cX - b_dX * a_cZ;
-       no[2] = b_dX * a_cY - b_dY * a_cX;
-
-       /* don't normalize, GL_NORMALIZE is enabled */
-       glNormal3fv(no);
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  int edgeSize = ccgSubSurf_getEdgeSize(ss);
+  int gridSize = ccgSubSurf_getGridSize(ss);
+  int i;
+  CCGVertIterator vi;
+  CCGEdgeIterator ei;
+  CCGFaceIterator fi;
+  CCGFace **faceMap2;
+  CCGEdge **edgeMap2;
+  CCGVert **vertMap2;
+  int index, totvert, totedge, totface;
+
+  totvert = ccgSubSurf_getNumVerts(ss);
+  vertMap2 = MEM_mallocN(totvert * sizeof(*vertMap2), "vertmap");
+  for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi);
+       ccgVertIterator_next(&vi)) {
+    CCGVert *v = ccgVertIterator_getCurrent(&vi);
+
+    vertMap2[POINTER_AS_INT(ccgSubSurf_getVertVertHandle(v))] = v;
+  }
+
+  totedge = ccgSubSurf_getNumEdges(ss);
+  edgeMap2 = MEM_mallocN(totedge * sizeof(*edgeMap2), "edgemap");
+  for (ccgSubSurf_initEdgeIterator(ss, &ei), i = 0; !ccgEdgeIterator_isStopped(&ei);
+       i++, ccgEdgeIterator_next(&ei)) {
+    CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
+
+    edgeMap2[POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
+  }
+
+  totface = ccgSubSurf_getNumFaces(ss);
+  faceMap2 = MEM_mallocN(totface * sizeof(*faceMap2), "facemap");
+  for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi);
+       ccgFaceIterator_next(&fi)) {
+    CCGFace *f = ccgFaceIterator_getCurrent(&fi);
+
+    faceMap2[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))] = f;
+  }
+
+  i = 0;
+  for (index = 0; index < totface; index++) {
+    CCGFace *f = faceMap2[index];
+    int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+    copy_v3_v3(cos[i++], ccgSubSurf_getFaceCenterData(f));
+
+    for (S = 0; S < numVerts; S++) {
+      for (x = 1; x < gridSize - 1; x++) {
+        copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
+      }
+    }
+
+    for (S = 0; S < numVerts; S++) {
+      for (y = 1; y < gridSize - 1; y++) {
+        for (x = 1; x < gridSize - 1; x++) {
+          copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridData(ss, f, S, x, y));
+        }
+      }
+    }
+  }
+
+  for (index = 0; index < totedge; index++) {
+    CCGEdge *e = edgeMap2[index];
+    int x;
+
+    for (x = 1; x < edgeSize - 1; x++) {
+      copy_v3_v3(cos[i++], ccgSubSurf_getEdgeData(ss, e, x));
+    }
+  }
+
+  for (index = 0; index < totvert; index++) {
+    CCGVert *v = vertMap2[index];
+    copy_v3_v3(cos[i++], ccgSubSurf_getVertData(ss, v));
+  }
+
+  MEM_freeN(vertMap2);
+  MEM_freeN(edgeMap2);
+  MEM_freeN(faceMap2);
+}
+
+static void ccgDM_foreachMappedVert(DerivedMesh *dm,
+                                    void (*func)(void *userData,
+                                                 int index,
+                                                 const float co[3],
+                                                 const float no_f[3],
+                                                 const short no_s[3]),
+                                    void *userData,
+                                    DMForeachFlag flag)
+{
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGVertIterator vi;
+  CCGKey key;
+  CCG_key_top_level(&key, ccgdm->ss);
+
+  for (ccgSubSurf_initVertIterator(ccgdm->ss, &vi); !ccgVertIterator_isStopped(&vi);
+       ccgVertIterator_next(&vi)) {
+    CCGVert *v = ccgVertIterator_getCurrent(&vi);
+    const int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
+
+    if (index != -1) {
+      CCGElem *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
+      const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL;
+      func(userData, index, CCG_elem_co(&key, vd), no, NULL);
+    }
+  }
 }
 
-/* Only used by non-editmesh types */
-static void ccgDM_buffer_copy_normal(
-        DerivedMesh *dm, short *varray)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int gridFaces = gridSize - 1;
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-       int i, totface = ccgSubSurf_getNumFaces(ss);
-       int shademodel;
-       int start = 0;
-
-       /* we are in sculpt mode, disable loop normals (since they won't get updated) */
-       if (ccgdm->pbvh)
-               lnors = NULL;
-
-       CCG_key_top_level(&key, ss);
-
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
-               int index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-               const float (*ln)[3] = NULL;
-
-               if (faceFlags) {
-                       shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
-               }
-               else {
-                       shademodel = GL_SMOOTH;
-               }
-
-               if (lnors) {
-                       ln = lnors;
-                       lnors += gridFaces * gridFaces * numVerts * 4;
-               }
-
-               for (S = 0; S < numVerts; S++) {
-                       CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
-
-                       if (ln) {
-                               /* Can't use quad strips here... */
-                               for (y = 0; y < gridFaces; y ++) {
-                                       for (x = 0; x < gridFaces; x ++) {
-                                               normal_float_to_short_v3(&varray[start + 0],  ln[0]);
-                                               normal_float_to_short_v3(&varray[start + 4],  ln[3]);
-                                               normal_float_to_short_v3(&varray[start + 8],  ln[2]);
-                                               normal_float_to_short_v3(&varray[start + 12], ln[1]);
-
-                                               start += 16;
-                                               ln += 4;
-                                       }
-                               }
-                       }
-                       else if (shademodel == GL_SMOOTH) {
-                               for (y = 0; y < gridFaces; y ++) {
-                                       for (x = 0; x < gridFaces; x ++) {
-                                               float *a = CCG_grid_elem_no(&key, faceGridData, x, y );
-                                               float *b = CCG_grid_elem_no(&key, faceGridData, x + 1, y);
-                                               float *c = CCG_grid_elem_no(&key, faceGridData, x + 1, y + 1);
-                                               float *d = CCG_grid_elem_no(&key, faceGridData, x, y + 1);
-
-                                               normal_float_to_short_v3(&varray[start], a);
-                                               normal_float_to_short_v3(&varray[start + 4], b);
-                                               normal_float_to_short_v3(&varray[start + 8], c);
-                                               normal_float_to_short_v3(&varray[start + 12], d);
-
-                                               start += 16;
-                                       }
-                               }
-                       }
-                       else {
-                               for (y = 0; y < gridFaces; y ++) {
-                                       for (x = 0; x < gridFaces; x ++) {
-                                               float f_no[3];
-                                               short f_no_s[3];
-
-                                               float *a = CCG_grid_elem_co(&key, faceGridData, x, y );
-                                               float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y );
-                                               float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
-                                               float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
-                                               ccgDM_NormalFast(a, b, c, d, f_no);
-                                               normal_float_to_short_v3(f_no_s, f_no);
-
-                                               copy_v3_v3_short(&varray[start], f_no_s);
-                                               copy_v3_v3_short(&varray[start + 4], f_no_s);
-                                               copy_v3_v3_short(&varray[start + 8], f_no_s);
-                                               copy_v3_v3_short(&varray[start + 12], f_no_s);
-
-                                               start += 16;
-                                       }
-                               }
-                       }
-               }
-       }
+static void ccgDM_foreachMappedEdge(
+    DerivedMesh *dm,
+    void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
+    void *userData)
+{
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  CCGEdgeIterator ei;
+  CCGKey key;
+  int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
+
+  CCG_key_top_level(&key, ss);
+
+  for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei);
+       ccgEdgeIterator_next(&ei)) {
+    CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
+    const int index = ccgDM_getEdgeMapIndex(ss, e);
+
+    if (index != -1) {
+      CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
+      for (i = 0; i < edgeSize - 1; i++) {
+        func(userData,
+             index,
+             CCG_elem_offset_co(&key, edgeData, i),
+             CCG_elem_offset_co(&key, edgeData, i + 1));
+      }
+    }
+  }
+}
+
+static void ccgDM_foreachMappedLoop(DerivedMesh *dm,
+                                    void (*func)(void *userData,
+                                                 int vertex_index,
+                                                 int face_index,
+                                                 const float co[3],
+                                                 const float no[3]),
+                                    void *userData,
+                                    DMForeachFlag flag)
+{
+  /* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData,
+   * EditDerivedBMesh would return loop data from bmesh itself. */
+  const float(*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) :
+                                                            NULL;
+
+  MVert *mv = dm->getVertArray(dm);
+  MLoop *ml = dm->getLoopArray(dm);
+  MPoly *mp = dm->getPolyArray(dm);
+  const int *v_index = dm->getVertDataArray(dm, CD_ORIGINDEX);
+  const int *f_index = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+  int p_idx, i;
+
+  for (p_idx = 0; p_idx < dm->numPolyData; ++p_idx, ++mp) {
+    for (i = 0; i < mp->totloop; ++i, ++ml) {
+      const int v_idx = v_index ? v_index[ml->v] : ml->v;
+      const int f_idx = f_index ? f_index[p_idx] : p_idx;
+      const float *no = lnors ? *lnors++ : NULL;
+      if (!ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
+        func(userData, v_idx, f_idx, mv[ml->v].co, no);
+      }
+    }
+  }
+}
+
+static void UNUSED_FUNCTION(ccgdm_pbvh_update)(CCGDerivedMesh *ccgdm)
+{
+  if (ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) {
+    CCGFace **faces;
+    int totface;
+
+    BKE_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface);
+    if (totface) {
+      ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface);
+      ccgSubSurf_updateNormals(ccgdm->ss, faces, totface);
+      MEM_freeN(faces);
+    }
+  }
 }
 
-typedef struct FaceCount {
-       unsigned int i_visible;
-       unsigned int i_hidden;
-       unsigned int i_tri_visible;
-       unsigned int i_tri_hidden;
-} FaceCount;
-
-
-/* Only used by non-editmesh types */
-static void ccgDM_buffer_copy_triangles(
-        DerivedMesh *dm, unsigned int *varray,
-        const int *mat_orig_to_new)
+static void ccgDM_foreachMappedFaceCenter(
+    DerivedMesh *dm,
+    void (*func)(void *userData, int index, const float co[3], const float no[3]),
+    void *userData,
+    DMForeachFlag flag)
 {
-       GPUBufferMaterial *gpumat, *gpumaterials = dm->drawObject->materials;
-       const int gpu_totmat = dm->drawObject->totmaterial;
-       const short dm_totmat = dm->totmat;
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int gridFaces = gridSize - 1;
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-       int i, totface = ccgSubSurf_getNumFaces(ss);
-       short mat_nr = -1;
-       int start;
-       int totloops = 0;
-       FaceCount *fc = MEM_mallocN(sizeof(*fc) * gpu_totmat, "gpumaterial.facecount");
-
-       CCG_key_top_level(&key, ss);
-
-       for (i = 0; i < gpu_totmat; i++) {
-               fc[i].i_visible = 0;
-               fc[i].i_tri_visible = 0;
-               fc[i].i_hidden = gpumaterials[i].totpolys - 1;
-               fc[i].i_tri_hidden = gpumaterials[i].totelements - 1;
-       }
-
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
-               int index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-               bool is_hidden;
-               int mati;
-
-               if (faceFlags) {
-                       mat_nr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat);
-                       is_hidden = (faceFlags[index].flag & ME_HIDE) != 0;
-               }
-               else {
-                       mat_nr = 0;
-                       is_hidden = false;
-               }
-               mati = mat_orig_to_new[mat_nr];
-               gpumat = dm->drawObject->materials + mati;
-
-               if (is_hidden) {
-                       for (S = 0; S < numVerts; S++) {
-                               for (y = 0; y < gridFaces; y++) {
-                                       for (x = 0; x < gridFaces; x++) {
-                                               start = gpumat->start + fc[mati].i_tri_hidden;
-
-                                               varray[start--] = totloops;
-                                               varray[start--] = totloops + 2;
-                                               varray[start--] = totloops + 3;
-
-                                               varray[start--] = totloops;
-                                               varray[start--] = totloops + 1;
-                                               varray[start--] = totloops + 2;
-
-                                               fc[mati].i_tri_hidden -= 6;
-
-                                               totloops += 4;
-                                       }
-                               }
-                       }
-                       gpumat->polys[fc[mati].i_hidden--] = i;
-               }
-               else {
-                       for (S = 0; S < numVerts; S++) {
-                               for (y = 0; y < gridFaces; y++) {
-                                       for (x = 0; x < gridFaces; x++) {
-                                               start = gpumat->start + fc[mati].i_tri_visible;
-
-                                               varray[start++] = totloops + 3;
-                                               varray[start++] = totloops + 2;
-                                               varray[start++] = totloops;
-
-                                               varray[start++] = totloops + 2;
-                                               varray[start++] = totloops + 1;
-                                               varray[start++] = totloops;
-
-                                               fc[mati].i_tri_visible += 6;
-
-                                               totloops += 4;
-                                       }
-                               }
-                       }
-                       gpumat->polys[fc[mati].i_visible++] = i;
-               }
-       }
-
-       /* set the visible polygons */
-       for (i = 0; i < gpu_totmat; i++) {
-               gpumaterials[i].totvisiblepolys = fc[i].i_visible;
-       }
-
-       MEM_freeN(fc);
-}
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  CCGKey key;
+  CCGFaceIterator fi;
 
+  CCG_key_top_level(&key, ss);
 
-/* Only used by non-editmesh types */
-static void ccgDM_buffer_copy_vertex(
-        DerivedMesh *dm, void *varray_p)
-{
-       float *varray = varray_p;
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int gridFaces = gridSize - 1;
-       int i, totface = ccgSubSurf_getNumFaces(ss);
-       int totedge = ccgSubSurf_getNumEdges(ss);
-       int start = 0;
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-
-       CCG_key_top_level(&key, ss);
-
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               for (S = 0; S < numVerts; S++) {
-                       CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
-                       for (y = 0; y < gridFaces; y++) {
-                               for (x = 0; x < gridFaces; x++) {
-                                       float *a = CCG_grid_elem_co(&key, faceGridData, x, y);
-                                       float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
-                                       float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
-                                       float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
-                                       copy_v3_v3(&varray[start], a);
-                                       copy_v3_v3(&varray[start + 3], b);
-                                       copy_v3_v3(&varray[start + 6], c);
-                                       copy_v3_v3(&varray[start + 9], d);
-
-                                       start += 12;
-                               }
-                       }
-               }
-       }
-
-       /* upload loose points */
-       for (i = 0; i < totedge; i++) {
-               CCGEdge *e = ccgdm->edgeMap[i].edge;
-               CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
-
-               if (!ccgSubSurf_getEdgeNumFaces(e)) {
-                       int j = 0;
-                       for (j = 0; j < edgeSize; j++) {
-                               copy_v3_v3(&varray[start], CCG_elem_offset_co(&key, edgeData, j));
-                               start += 3;
-                       }
-               }
-       }
-}
-
-/* Only used by non-editmesh types */
-static void ccgDM_buffer_copy_color(
-        DerivedMesh *dm, unsigned char *varray,
-        const void *user_data)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       const unsigned char *mloopcol = user_data;
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int gridFaces = gridSize - 1;
-       int i, totface = ccgSubSurf_getNumFaces(ss);
-       int start = 0;
-       int iface = 0;
-
-       CCG_key_top_level(&key, ss);
-
-
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               for (S = 0; S < numVerts; S++) {
-                       for (y = 0; y < gridFaces; y++) {
-                               for (x = 0; x < gridFaces; x++) {
-                                       copy_v4_v4_uchar(&varray[start + 0], &mloopcol[iface * 16 + 0]);
-                                       copy_v4_v4_uchar(&varray[start + 4], &mloopcol[iface * 16 + 12]);
-                                       copy_v4_v4_uchar(&varray[start + 8], &mloopcol[iface * 16 + 8]);
-                                       copy_v4_v4_uchar(&varray[start + 12], &mloopcol[iface * 16 + 4]);
-
-                                       start += 16;
-                                       iface++;
-                               }
-                       }
-               }
-       }
-}
+  for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi);
+       ccgFaceIterator_next(&fi)) {
+    CCGFace *f = ccgFaceIterator_getCurrent(&fi);
+    const int index = ccgDM_getFaceMapIndex(ss, f);
 
-static void ccgDM_buffer_copy_uv(
-        DerivedMesh *dm, void *varray_p)
-{
-       float *varray = varray_p;
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       MLoopUV *mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV);
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int gridFaces = gridSize - 1;
-       int i, totface = ccgSubSurf_getNumFaces(ss);
-       int start = 0;
-
-       CCG_key_top_level(&key, ss);
-
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               for (S = 0; S < numVerts; S++) {
-                       for (y = 0; y < gridFaces; y++) {
-                               for (x = 0; x < gridFaces; x++) {
-                                       copy_v2_v2(&varray[start + 0], mloopuv[0].uv);
-                                       copy_v2_v2(&varray[start + 2], mloopuv[3].uv);
-                                       copy_v2_v2(&varray[start + 4], mloopuv[2].uv);
-                                       copy_v2_v2(&varray[start + 6], mloopuv[1].uv);
-
-                                       mloopuv += 4;
-                                       start += 8;
-                               }
-                       }
-               }
-       }
+    if (index != -1) {
+      /* Face center data normal isn't updated atm. */
+      CCGElem *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0);
+      const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL;
+      func(userData, index, CCG_elem_co(&key, vd), no);
+    }
+  }
 }
 
-static void ccgDM_buffer_copy_uv_texpaint(
-        DerivedMesh *dm, float *varray)
+static void ccgDM_release(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int gridFaces = gridSize - 1;
-       int i, totface = ccgSubSurf_getNumFaces(ss);
-       int start = 0;
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-       int dm_totmat = dm->totmat;
-       MLoopUV **mloopuv_base;
-       MLoopUV  *stencil_base;
-       int stencil;
-
-       CCG_key_top_level(&key, ss);
-
-       /* should have been checked for before, reassert */
-       BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV));
-       mloopuv_base = MEM_mallocN(dm_totmat * sizeof(*mloopuv_base), "texslots");
-
-       for (i = 0; i < dm_totmat; i++) {
-               mloopuv_base[i] = DM_paint_uvlayer_active_get(dm, i);
-       }
-
-       stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV);
-       stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil);
-
-       start = 0;
-
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
-               int index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-               int matnr;
-
-               if (faceFlags) {
-                       matnr = faceFlags[index].mat_nr;
-               }
-               else {
-                       matnr = 0;
-               }
-
-               for (S = 0; S < numVerts; S++) {
-                       for (y = 0; y < gridFaces; y++) {
-                               for (x = 0; x < gridFaces; x++) {
-                                       /* divide by 4, gives us current loop-index */
-                                       unsigned int i_ml = start / 4;
-                                       copy_v2_v2(&varray[start + 0],  mloopuv_base[matnr][i_ml + 0].uv);
-                                       copy_v2_v2(&varray[start + 2],         stencil_base[i_ml + 0].uv);
-                                       copy_v2_v2(&varray[start + 4],  mloopuv_base[matnr][i_ml + 3].uv);
-                                       copy_v2_v2(&varray[start + 6],         stencil_base[i_ml + 3].uv);
-                                       copy_v2_v2(&varray[start + 8],  mloopuv_base[matnr][i_ml + 2].uv);
-                                       copy_v2_v2(&varray[start + 10],        stencil_base[i_ml + 2].uv);
-                                       copy_v2_v2(&varray[start + 12], mloopuv_base[matnr][i_ml + 1].uv);
-                                       copy_v2_v2(&varray[start + 14],        stencil_base[i_ml + 1].uv);
-                                       start += 16;
-                               }
-                       }
-               }
-       }
-
-       MEM_freeN(mloopuv_base);
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+
+  if (DM_release(dm)) {
+    /* Before freeing, need to update the displacement map */
+    if (ccgdm->multires.modified_flags) {
+      /* Check that mmd still exists */
+      if (!ccgdm->multires.local_mmd &&
+          BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) < 0) {
+        ccgdm->multires.mmd = NULL;
+      }
+
+      if (ccgdm->multires.mmd) {
+        if (ccgdm->multires.modified_flags & MULTIRES_COORDS_MODIFIED) {
+          multires_modifier_update_mdisps(dm, NULL);
+        }
+        if (ccgdm->multires.modified_flags & MULTIRES_HIDDEN_MODIFIED) {
+          multires_modifier_update_hidden(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->gridOffset) {
+      MEM_freeN(ccgdm->gridOffset);
+    }
+    if (ccgdm->gridFlagMats) {
+      MEM_freeN(ccgdm->gridFlagMats);
+    }
+    if (ccgdm->gridHidden) {
+      /* Using dm->getNumGrids(dm) accesses freed memory */
+      uint numGrids = ccgdm->numGrid;
+      for (uint i = 0; i < numGrids; i++) {
+        if (ccgdm->gridHidden[i]) {
+          MEM_freeN(ccgdm->gridHidden[i]);
+        }
+      }
+      MEM_freeN(ccgdm->gridHidden);
+    }
+    if (ccgdm->freeSS) {
+      ccgSubSurf_free(ccgdm->ss);
+    }
+    if (ccgdm->pmap) {
+      MEM_freeN(ccgdm->pmap);
+    }
+    if (ccgdm->pmap_mem) {
+      MEM_freeN(ccgdm->pmap_mem);
+    }
+    MEM_freeN(ccgdm->edgeFlags);
+    MEM_freeN(ccgdm->faceFlags);
+    if (ccgdm->useGpuBackend == false) {
+      MEM_freeN(ccgdm->vertMap);
+      MEM_freeN(ccgdm->edgeMap);
+      MEM_freeN(ccgdm->faceMap);
+    }
+
+    BLI_mutex_end(&ccgdm->loops_cache_lock);
+    BLI_rw_mutex_end(&ccgdm->origindex_cache_rwlock);
+
+    MEM_freeN(ccgdm);
+  }
 }
 
-static void ccgDM_buffer_copy_uvedge(
-        DerivedMesh *dm, float *varray)
+static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
 {
-       int i, totpoly;
-       int start;
-       const MLoopUV *mloopuv;
-#ifndef USE_LOOP_LAYOUT_FAST
-       const MPoly *mpoly = dm->getPolyArray(dm);
-#endif
+  if (type == CD_ORIGINDEX) {
+    /* create origindex on demand to save memory */
+    CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+    CCGSubSurf *ss = ccgdm->ss;
+    int *origindex;
+    int a, index, totnone, totorig;
 
-       if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) {
-               return;
-       }
-
-       totpoly = dm->getNumPolys(dm);
-       start = 0;
-
-#ifndef USE_LOOP_LAYOUT_FAST
-       for (i = 0; i < totpoly; i++, mpoly++) {
-               for (j = 0; j < mpoly->totloop; j++) {
-                       copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv);
-                       copy_v2_v2(&varray[start + 2], mloopuv[mpoly->loopstart + (j + 1) % mpoly->totloop].uv);
-                       start += 4;
-               }
-       }
-#else
-       for (i = 0; i < totpoly; i++) {
-               copy_v2_v2(&varray[start +  0], mloopuv[(i * 4) + 0].uv);
-               copy_v2_v2(&varray[start +  2], mloopuv[(i * 4) + 1].uv);
+    /* Avoid re-creation if the layer exists already */
+    BLI_rw_mutex_lock(&ccgdm->origindex_cache_rwlock, THREAD_LOCK_READ);
+    origindex = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
+    BLI_rw_mutex_unlock(&ccgdm->origindex_cache_rwlock);
+    if (origindex) {
+      return origindex;
+    }
 
-               copy_v2_v2(&varray[start +  4], mloopuv[(i * 4) + 1].uv);
-               copy_v2_v2(&varray[start +  6], mloopuv[(i * 4) + 2].uv);
+    BLI_rw_mutex_lock(&ccgdm->origindex_cache_rwlock, THREAD_LOCK_WRITE);
+    DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
+    origindex = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
 
-               copy_v2_v2(&varray[start +  8], mloopuv[(i * 4) + 2].uv);
-               copy_v2_v2(&varray[start + 10], mloopuv[(i * 4) + 3].uv);
+    totorig = ccgSubSurf_getNumVerts(ss);
+    totnone = dm->numVertData - totorig;
 
-               copy_v2_v2(&varray[start + 12], mloopuv[(i * 4) + 3].uv);
-               copy_v2_v2(&varray[start + 14], mloopuv[(i * 4) + 0].uv);
-
-               start += 16;
-       }
-#endif
-}
+    /* original vertices are at the end */
+    for (a = 0; a < totnone; a++) {
+      origindex[a] = ORIGINDEX_NONE;
+    }
 
-static void ccgDM_buffer_copy_edge(
-        DerivedMesh *dm, unsigned int *varray)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       /* getEdgeSuze returns num of verts, edges is one less */
-       int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss) - 1;
-       int totedge = ccgSubSurf_getNumEdges(ss);
-       int grid_face_side = ccgSubSurf_getGridSize(ss) - 1;
-       int totface = ccgSubSurf_getNumFaces(ss);
-       unsigned int index_start;
-       unsigned int tot_interior = 0;
-       unsigned int grid_tot_face = grid_face_side * grid_face_side;
-
-       unsigned int iloose, inorm, iloosehidden, inormhidden;
-       unsigned int tot_loose_hidden = 0, tot_loose = 0;
-       unsigned int tot_hidden = 0, tot = 0;
-       unsigned int iloosevert;
-       /* int tot_interior = 0; */
-
-       /* first, handle hidden/loose existing edges, then interior edges */
-       for (j = 0; j < totedge; j++) {
-               CCGEdge *e = ccgdm->edgeMap[j].edge;
-
-               if (ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW)) {
-                       if (!ccgSubSurf_getEdgeNumFaces(e)) tot_loose_hidden++;
-                       else tot_hidden++;
-               }
-               else {
-                       if (!ccgSubSurf_getEdgeNumFaces(e)) tot_loose++;
-                       else tot++;
-               }
-       }
-
-       inorm = 0;
-       inormhidden = tot * edgeSize;
-       iloose = (tot + tot_hidden) * edgeSize;
-       iloosehidden = (tot + tot_hidden + tot_loose) * edgeSize;
-       iloosevert = dm->drawObject->tot_loop_verts;
-
-       /* part one, handle all normal edges */
-       for (j = 0; j < totedge; j++) {
-               CCGFace *f;
-               int fhandle = 0;
-               int totvert = 0;
-               unsigned int S = 0;
-               CCGEdge *e = ccgdm->edgeMap[j].edge;
-               bool isloose = !ccgSubSurf_getEdgeNumFaces(e);
-
-               if (!isloose) {
-                       CCGVert *v1, *v2;
-                       CCGVert *ev1 = ccgSubSurf_getEdgeVert0(e);
-                       CCGVert *ev2 = ccgSubSurf_getEdgeVert1(e);
-
-                       f = ccgSubSurf_getEdgeFace(e, 0);
-                       fhandle = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-                       totvert = ccgSubSurf_getFaceNumVerts(f);
-
-                       /* find the index of vertices in the face */
-                       for (i = 0; i < totvert; i++) {
-                               v1 = ccgSubSurf_getFaceVert(f, i);
-                               v2 = ccgSubSurf_getFaceVert(f, (i + 1) % totvert);
-
-                               if ((ev1 == v1 && ev2 == v2) || (ev1 == v2 && ev2 == v1)) {
-                                       S = i;
-                                       break;
-                               }
-                       }
-               }
-
-               if (ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW)) {
-                       if (isloose) {
-                               for (i = 0; i < edgeSize; i++) {
-                                       varray[iloosehidden * 2] = iloosevert;
-                                       varray[iloosehidden * 2 + 1] = iloosevert + 1;
-                                       iloosehidden++;
-                                       iloosevert++;
-                               }
-                               /* we are through with this loose edge and moving to the next, so increase by one */
-                               iloosevert++;
-                       }
-                       else {
-                               index_start = ccgdm->faceMap[fhandle].startFace;
-
-                               for (i = 0; i < grid_face_side; i++) {
-                                       varray[inormhidden * 2] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 1;
-                                       varray[inormhidden * 2 + 1] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 2;
-                                       varray[inormhidden * 2 + 2] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 2;
-                                       varray[inormhidden * 2 + 3] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 3;
-                                       inormhidden += 2;
-                               }
-                       }
-               }
-               else {
-                       if (isloose) {
-                               for (i = 0; i < edgeSize; i++) {
-                                       varray[iloose * 2] = iloosevert;
-                                       varray[iloose * 2 + 1] = iloosevert + 1;
-                                       iloose++;
-                                       iloosevert++;
-                               }
-                               /* we are through with this loose edge and moving to the next, so increase by one */
-                               iloosevert++;
-                       }
-                       else {
-                               index_start = ccgdm->faceMap[fhandle].startFace;
-
-                               for (i = 0; i < grid_face_side; i++) {
-                                       varray[inorm * 2] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 1;
-                                       varray[inorm * 2 + 1] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 2;
-                                       varray[inorm * 2 + 2] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 2;
-                                       varray[inorm * 2 + 3] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 3;
-                                       inorm += 2;
-                               }
-                       }
-               }
-       }
-
-       /* part two, handle interior edges */
-       inorm = totedge * grid_face_side * 2;
-
-       index_start = 0;
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               unsigned int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               for (S = 0; S < numVerts; S++) {
-                       for (x = 1; x < grid_face_side; x++) {
-                               for (y = 0; y < grid_face_side; y++) {
-                                       unsigned int tmp = (index_start + x * grid_face_side + y) * 4;
-                                       varray[inorm * 2] = tmp;
-                                       varray[inorm * 2 + 1] = tmp + 1;
-                                       inorm++;
-                               }
-                       }
-                       for (x = 0; x < grid_face_side; x++) {
-                               for (y = 0; y < grid_face_side; y++) {
-                                       unsigned int tmp = (index_start + x * grid_face_side + y) * 4;
-                                       varray[inorm * 2] = tmp + 3;
-                                       varray[inorm * 2 + 1] = tmp;
-                                       inorm++;
-                               }
-                       }
-
-                       tot_interior += grid_face_side * (2 * grid_face_side - 1);
-                       index_start += grid_tot_face;
-               }
-       }
-
-       dm->drawObject->tot_loose_edge_drawn = tot_loose * edgeSize;
-       dm->drawObject->loose_edge_offset = (tot + tot_hidden) * edgeSize;
-       dm->drawObject->tot_edge_drawn = tot * edgeSize;
-
-       dm->drawObject->interior_offset = totedge * edgeSize;
-       dm->drawObject->totinterior = tot_interior;
-}
+    for (index = 0; index < totorig; index++, a++) {
+      CCGVert *v = ccgdm->vertMap[index].vert;
+      origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v);
+    }
+    BLI_rw_mutex_unlock(&ccgdm->origindex_cache_rwlock);
 
-static void ccgDM_copy_gpu_data(
-        DerivedMesh *dm, int type, void *varray_p,
-        const int *mat_orig_to_new, const void *user_data)
-{
-       /* 'varray_p' cast is redundant but include for self-documentation */
-       switch (type) {
-               case GPU_BUFFER_VERTEX:
-                       ccgDM_buffer_copy_vertex(dm, (float *)varray_p);
-                       break;
-               case GPU_BUFFER_NORMAL:
-                       ccgDM_buffer_copy_normal(dm, (short *)varray_p);
-                       break;
-               case GPU_BUFFER_UV:
-                       ccgDM_buffer_copy_uv(dm, (float *)varray_p);
-                       break;
-               case GPU_BUFFER_UV_TEXPAINT:
-                       ccgDM_buffer_copy_uv_texpaint(dm, (float *)varray_p);
-                       break;
-               case GPU_BUFFER_COLOR:
-                       ccgDM_buffer_copy_color(dm, (unsigned char *)varray_p, user_data);
-                       break;
-               case GPU_BUFFER_UVEDGE:
-                       ccgDM_buffer_copy_uvedge(dm, (float *)varray_p);
-                       break;
-               case GPU_BUFFER_EDGE:
-                       ccgDM_buffer_copy_edge(dm, (unsigned int *)varray_p);
-                       break;
-               case GPU_BUFFER_TRIANGLES:
-                       ccgDM_buffer_copy_triangles(dm, (unsigned int *)varray_p, mat_orig_to_new);
-                       break;
-               default:
-                       break;
-       }
-}
+    return origindex;
+  }
 
-static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       GPUDrawObject *gdo;
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-       int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
-       const short dm_totmat = (faceFlags) ? dm->totmat : 1;
-       GPUBufferMaterial *matinfo;
-       int i;
-       unsigned int tot_internal_edges = 0;
-       int edgeVerts = ccgSubSurf_getEdgeSize(ss);
-       int edgeSize = edgeVerts - 1;
-
-       int totedge = ccgSubSurf_getNumEdges(ss);
-       int totface = ccgSubSurf_getNumFaces(ss);
-
-       /* object contains at least one material (default included) so zero means uninitialized dm */
-       BLI_assert(dm_totmat != 0);
-
-       matinfo = MEM_callocN(sizeof(*matinfo) * dm_totmat, "GPU_drawobject_new.mat_orig_to_new");
-
-       if (faceFlags) {
-               for (i = 0; i < totface; i++) {
-                       CCGFace *f = ccgdm->faceMap[i].face;
-                       int numVerts = ccgSubSurf_getFaceNumVerts(f);
-                       int index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-                       const short new_matnr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat);
-                       matinfo[new_matnr].totelements += numVerts * gridFaces * gridFaces * 6;
-                       matinfo[new_matnr].totloops += numVerts * gridFaces * gridFaces * 4;
-                       matinfo[new_matnr].totpolys++;
-                       tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1);
-               }
-       }
-       else {
-               for (i = 0; i < totface; i++) {
-                       CCGFace *f = ccgdm->faceMap[i].face;
-                       int numVerts = ccgSubSurf_getFaceNumVerts(f);
-                       matinfo[0].totelements += numVerts * gridFaces * gridFaces * 6;
-                       matinfo[0].totloops += numVerts * gridFaces * gridFaces * 4;
-                       matinfo[0].totpolys++;
-                       tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1);
-               }
-       }
-
-       /* create the GPUDrawObject */
-       gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
-       gdo->totvert = 0; /* used to count indices, doesn't really matter for ccgsubsurf */
-       gdo->totedge = (totedge * edgeSize + tot_internal_edges);
-
-       GPU_buffer_material_finalize(gdo, matinfo, dm_totmat);
-
-       /* store total number of points used for triangles */
-       gdo->tot_triangle_point = ccgSubSurf_getNumFinalFaces(ss) * 6;
-       gdo->tot_loop_verts = ccgSubSurf_getNumFinalFaces(ss) * 4;
-
-       /* finally, count loose points */
-       for (i = 0; i < totedge; i++) {
-               CCGEdge *e = ccgdm->edgeMap[i].edge;
-
-               if (!ccgSubSurf_getEdgeNumFaces(e))
-                       gdo->tot_loose_point += edgeVerts;
-       }
-
-       return gdo;
+  return DM_get_vert_data_layer(dm, type);
 }
 
-/* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
+static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
 {
-       int a;
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-
-       ccgdm_pbvh_update(ccgdm);
-
-       if (ccgdm->pbvh && ccgdm->multires.mmd) {
-               if (BKE_pbvh_has_faces(ccgdm->pbvh)) {
-                       BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
-                                     setMaterial, false, fast);
-               }
+  if (type == CD_ORIGINDEX) {
+    /* create origindex on demand to save memory */
+    CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+    CCGSubSurf *ss = ccgdm->ss;
+    int *origindex;
+    int a, i, index, totnone, totorig, totedge;
+    int edgeSize = ccgSubSurf_getEdgeSize(ss);
 
-               return;
-       }
-
-#ifdef WITH_OPENSUBDIV
-       if (ccgdm->useGpuBackend) {
-               CCGSubSurf *ss = ccgdm->ss;
-               const DMFlagMat *faceFlags = ccgdm->faceFlags;
-               const int level = ccgSubSurf_getSubdivisionLevels(ss);
-               const int face_side = 1 << level;
-               const int grid_side = 1 << (level - 1);
-               const int face_patches = face_side * face_side;
-               const int grid_patches = grid_side * grid_side;
-               const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
-               int i, current_patch = 0;
-               int mat_nr = -1;
-               bool draw_smooth = false;
-               int start_draw_patch = -1, num_draw_patches = 0;
-               if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, setMaterial != NULL, -1) == false)) {
-                       return;
-               }
-               if (setMaterial == NULL) {
-                       ccgSubSurf_drawGLMesh(ss,
-                                             true,
-                                             -1,
-                                             -1);
-                       return;
-               }
-               for (i = 0; i < num_base_faces; ++i) {
-                       const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
-                       const int num_patches = (num_face_verts == 4) ? face_patches
-                                                                     : num_face_verts * grid_patches;
-                       int new_matnr;
-                       bool new_draw_smooth;
-                       if (faceFlags) {
-                               new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
-                               new_matnr = (faceFlags[i].mat_nr + 1);
-                       }
-                       else {
-                               new_draw_smooth = true;
-                               new_matnr = 1;
-                       }
-                       if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
-                               if (num_draw_patches != 0) {
-                                       bool do_draw = setMaterial(mat_nr, NULL);
-                                       if (do_draw) {
-                                               glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
-                                               ccgSubSurf_drawGLMesh(ss,
-                                                                     true,
-                                                                     start_draw_patch,
-                                                                     num_draw_patches);
-                                       }
-                               }
-                               start_draw_patch = current_patch;
-                               num_draw_patches = num_patches;
-                               mat_nr = new_matnr;
-                               draw_smooth = new_draw_smooth;
-                       }
-                       else {
-                               num_draw_patches += num_patches;
-                       }
-                       current_patch += num_patches;
-               }
-               if (num_draw_patches != 0) {
-                       bool do_draw = setMaterial(mat_nr, NULL);
-                       if (do_draw) {
-                               glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
-                               ccgSubSurf_drawGLMesh(ss,
-                                                     true,
-                                                     start_draw_patch,
-                                                     num_draw_patches);
-                       }
-               }
-               glShadeModel(GL_SMOOTH);
-               return;
-       }
-#endif
+    /* Avoid re-creation if the layer exists already */
+    origindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
+    if (origindex) {
+      return origindex;
+    }
 
-       GPU_vertex_setup(dm);
-       GPU_normal_setup(dm);
-       GPU_triangle_setup(dm);
-       for (a = 0; a < dm->drawObject->totmaterial; a++) {
-               if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
-                       GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, dm->drawObject->materials[a].start,
-                                                dm->drawObject->materials[a].totelements);
-               }
-       }
-       GPU_buffers_unbind();
-}
+    DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
+    origindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
 
-typedef struct {
-       DMVertexAttribs attribs;
-       int numdata;
+    totedge = ccgSubSurf_getNumEdges(ss);
+    totorig = totedge * (edgeSize - 1);
+    totnone = dm->numEdgeData - totorig;
 
-       GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
-} GPUMaterialConv;
+    /* original edges are at the end */
+    for (a = 0; a < totnone; a++) {
+      origindex[a] = ORIGINDEX_NONE;
+    }
 
-/* Only used by non-editmesh types */
-static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
-                                      DMSetMaterial setMaterial,
-                                      DMSetDrawOptions setDrawOptions,
-                                      void *userData)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       GPUVertexAttribs gattribs;
-       int a, b;
-       const DMFlagMat *faceFlags = ccgdm->faceFlags;
-       unsigned char *varray;
-       size_t max_element_size = 0;
-       int tot_loops = 0;
-       int totpoly = ccgSubSurf_getNumFaces(ss);
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int gridFaces = gridSize - 1;
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
+    for (index = 0; index < totedge; index++) {
+      CCGEdge *e = ccgdm->edgeMap[index].edge;
+      int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
 
-#ifdef WITH_OPENSUBDIV
-       if (ccgdm->useGpuBackend) {
-               const int level = ccgSubSurf_getSubdivisionLevels(ss);
-               const int face_side = 1 << level;
-               const int grid_side = 1 << (level - 1);
-               const int face_patches = face_side * face_side;
-               const int grid_patches = grid_side * grid_side;
-               const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
-               int i, current_patch = 0;
-               int mat_nr = -1;
-               bool draw_smooth = false;
-               int start_draw_patch = -1, num_draw_patches = 0;
-               GPU_draw_update_fvar_offset(dm);
-               if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, false, -1) == false)) {
-                       return;
-               }
-               for (i = 0; i < num_base_faces; ++i) {
-                       const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
-                       const int num_patches = (num_face_verts == 4) ? face_patches
-                                                                     : num_face_verts * grid_patches;
-                       int new_matnr;
-                       bool new_draw_smooth;
-
-                       if (faceFlags) {
-                               new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
-                               new_matnr = (faceFlags[i].mat_nr + 1);
-                       }
-                       else {
-                               new_draw_smooth = true;
-                               new_matnr = 1;
-                       }
-                       if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
-                               if (num_draw_patches != 0) {
-                                       bool do_draw = setMaterial(mat_nr, &gattribs);
-                                       if (do_draw) {
-                                               glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
-                                               ccgSubSurf_drawGLMesh(ss,
-                                                                     true,
-                                                                     start_draw_patch,
-                                                                     num_draw_patches);
-                                       }
-                               }
-                               start_draw_patch = current_patch;
-                               num_draw_patches = num_patches;
-                               mat_nr = new_matnr;
-                               draw_smooth = new_draw_smooth;
-                       }
-                       else {
-                               num_draw_patches += num_patches;
-                       }
-                       current_patch += num_patches;
-               }
-               if (num_draw_patches != 0) {
-                       bool do_draw = setMaterial(mat_nr, &gattribs);
-                       if (do_draw) {
-                               glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
-                               ccgSubSurf_drawGLMesh(ss,
-                                                     true,
-                                                     start_draw_patch,
-                                                     num_draw_patches);
-                       }
-               }
-               glShadeModel(GL_SMOOTH);
-               return;
-       }
-#endif
+      for (i = 0; i < edgeSize - 1; i++, a++) {
+        origindex[a] = mapIndex;
+      }
+    }
 
-       CCG_key_top_level(&key, ss);
-       ccgdm_pbvh_update(ccgdm);
-
-       if (setDrawOptions != NULL) {
-               const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
-               DMVertexAttribs attribs = {{{NULL}}};
-               int i;
-               int matnr = -1;
-               int do_draw = 0;
-
-#define PASSATTRIB(dx, dy, vert) {                                           \
-    if (attribs.totorco)                                                     \
-        index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize);  \
-    else                                                                     \
-        index = 0;                                                           \
-    DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert);       \
-    DM_draw_attrib_vertex_uniforms(&attribs);                                \
-} (void)0
-
-               totpoly = ccgSubSurf_getNumFaces(ss);
-               for (a = 0, i = 0; i < totpoly; i++) {
-                       CCGFace *f = ccgdm->faceMap[i].face;
-                       const float (*ln)[3] = NULL;
-                       int S, x, y, drawSmooth;
-                       int index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-                       int origIndex = ccgDM_getFaceMapIndex(ss, f);
-
-                       int numVerts = ccgSubSurf_getFaceNumVerts(f);
-                       int new_matnr;
-
-                       if (faceFlags) {
-                               drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH));
-                               new_matnr = faceFlags[index].mat_nr + 1;
-                       }
-                       else {
-                               drawSmooth = 1;
-                               new_matnr = 1;
-                       }
-
-                       if (lnors) {
-                               ln = lnors;
-                               lnors += (gridFaces * gridFaces * numVerts) * 4;
-                       }
-
-                       if (new_matnr != matnr) {
-                               do_draw = setMaterial(matnr = new_matnr, &gattribs);
-                               if (do_draw)
-                                       DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
-                       }
-
-                       if (!do_draw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) &&
-                                       (setDrawOptions(userData, origIndex) == DM_DRAW_OPTION_SKIP)))
-                       {
-                               a += gridFaces * gridFaces * numVerts;
-                               continue;
-                       }
-
-                       glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT);
-                       for (S = 0; S < numVerts; S++) {
-                               CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
-                               CCGElem *vda, *vdb;
-
-                               if (ln) {
-                                       glBegin(GL_QUADS);
-                                       for (y = 0; y < gridFaces; y++) {
-                                               for (x = 0; x < gridFaces; x++) {
-                                                       float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
-                                                       float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
-                                                       float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
-                                                       float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
-                                                       PASSATTRIB(0, 1, 1);
-                                                       glNormal3fv(ln[1]);
-                                                       glVertex3fv(dco);
-                                                       PASSATTRIB(1, 1, 2);
-                                                       glNormal3fv(ln[2]);
-                                                       glVertex3fv(cco);
-                                                       PASSATTRIB(1, 0, 3);
-                                                       glNormal3fv(ln[3]);
-                                                       glVertex3fv(bco);
-                                                       PASSATTRIB(0, 0, 0);
-                                                       glNormal3fv(ln[0]);
-                                                       glVertex3fv(aco);
-
-                                                       ln += 4;
-                                                       a++;
-                                               }
-                                       }
-                                       glEnd();
-                               }
-                               else if (drawSmooth) {
-                                       for (y = 0; y < gridFaces; y++) {
-                                               glBegin(GL_QUAD_STRIP);
-                                               for (x = 0; x < gridFaces; x++) {
-                                                       vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
-                                                       vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
-
-                                                       PASSATTRIB(0, 0, 0);
-                                                       glNormal3fv(CCG_elem_no(&key, vda));
-                                                       glVertex3fv(CCG_elem_co(&key, vda));
-
-                                                       PASSATTRIB(0, 1, 1);
-                                                       glNormal3fv(CCG_elem_no(&key, vdb));
-                                                       glVertex3fv(CCG_elem_co(&key, vdb));
-
-                                                       if (x != gridFaces - 1)
-                                                               a++;
-                                               }
-
-                                               vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
-                                               vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
-
-                                               PASSATTRIB(0, 0, 3);
-                                               glNormal3fv(CCG_elem_no(&key, vda));
-                                               glVertex3fv(CCG_elem_co(&key, vda));
-
-                                               PASSATTRIB(0, 1, 2);
-                                               glNormal3fv(CCG_elem_no(&key, vdb));
-                                               glVertex3fv(CCG_elem_co(&key, vdb));
-
-                                               glEnd();
-
-                                               a++;
-                                       }
-                               }
-                               else {
-                                       glBegin(GL_QUADS);
-                                       for (y = 0; y < gridFaces; y++) {
-                                               for (x = 0; x < gridFaces; x++) {
-                                                       float *aco = CCG_grid_elem_co(&key, faceGridData, x, y);
-                                                       float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
-                                                       float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
-                                                       float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
-                                                       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();
-                               }
-                       }
-               }
-
-               glShadeModel(GL_SMOOTH);
-#undef PASSATTRIB
-       }
-       else {
-               GPUMaterialConv *matconv;
-               size_t offset;
-               int *mat_orig_to_new;
-               int tot_active_mat;
-               GPUBuffer *buffer = NULL;
-
-               GPU_vertex_setup(dm);
-               GPU_normal_setup(dm);
-               GPU_triangle_setup(dm);
-
-               tot_active_mat = dm->drawObject->totmaterial;
-
-               matconv = MEM_callocN(sizeof(*matconv) * tot_active_mat,
-                                     "cdDM_drawMappedFacesGLSL.matconv");
-               mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
-                                             "cdDM_drawMappedFacesGLSL.mat_orig_to_new");
-
-               /* part one, check what attributes are needed per material */
-               for (a = 0; a < tot_active_mat; a++) {
-                       int new_matnr;
-                       int do_draw;
-
-                       new_matnr = dm->drawObject->materials[a].mat_nr;
-
-                       /* map from original material index to new
-                        * GPUBufferMaterial index */
-                       mat_orig_to_new[new_matnr] = a;
-                       do_draw = setMaterial(new_matnr + 1, &gattribs);
-
-                       if (do_draw) {
-                               int numdata = 0;
-                               DM_vertex_attributes_from_gpu(dm, &gattribs, &matconv[a].attribs);
-
-                               if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
-                                       matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
-                                       matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index;
-                                       matconv[a].datatypes[numdata].size = 3;
-                                       matconv[a].datatypes[numdata].type = GL_FLOAT;
-                                       numdata++;
-                               }
-                               for (b = 0; b < matconv[a].attribs.tottface; b++) {
-                                       if (matconv[a].attribs.tface[b].array) {
-                                               matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index;
-                                               matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index;
-                                               matconv[a].datatypes[numdata].size = 2;
-                                               matconv[a].datatypes[numdata].type = GL_FLOAT;
-                                               numdata++;
-                                       }
-                               }
-                               for (b = 0; b < matconv[a].attribs.totmcol; b++) {
-                                       if (matconv[a].attribs.mcol[b].array) {
-                                               matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index;
-                                               matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index;
-                                               matconv[a].datatypes[numdata].size = 4;
-                                               matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE;
-                                               numdata++;
-                                       }
-                               }
-                               for (b = 0; b < matconv[a].attribs.tottang; b++) {
-                                       if (matconv[a].attribs.tottang && matconv[a].attribs.tang[b].array) {
-                                               matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index;
-                                               matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index;
-                                               matconv[a].datatypes[numdata].size = 4;
-                                               matconv[a].datatypes[numdata].type = GL_FLOAT;
-                                               numdata++;
-                                       }
-                               }
-                               if (numdata != 0) {
-                                       matconv[a].numdata = numdata;
-                                       max_element_size = max_ii(GPU_attrib_element_size(matconv[a].datatypes, numdata), max_element_size);
-                               }
-                       }
-               }
-
-               /* part two, generate and fill the arrays with the data */
-               if (max_element_size > 0) {
-                       buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts);
-
-                       varray = GPU_buffer_lock_stream(buffer, GPU_BINDING_ARRAY);
-                       if (varray == NULL) {
-                               GPU_buffers_unbind();
-                               GPU_buffer_free(buffer);
-                               MEM_freeN(mat_orig_to_new);
-                               MEM_freeN(matconv);
-                               fprintf(stderr, "Out of memory, can't draw object\n");
-                               return;
-                       }
-
-                       for (a = 0; a < totpoly; a++) {
-                               CCGFace *f = ccgdm->faceMap[a].face;
-                               int orig_index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-                               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
-                               int i;
-
-                               if (faceFlags) {
-                                       i = mat_orig_to_new[faceFlags[orig_index].mat_nr];
-                               }
-                               else {
-                                       i = mat_orig_to_new[0];
-                               }
-
-                               if (matconv[i].numdata != 0) {
-                                       for (S = 0; S < numVerts; S++) {
-                                               for (y = 0; y < gridFaces; y++) {
-                                                       for (x = 0; x < gridFaces; x++) {
-
-                                                               offset = tot_loops * max_element_size;
-
-                                                               if (matconv[i].attribs.totorco && matconv[i].attribs.orco.array) {
-                                                                       int index;
-
-                                                                       index = getFaceIndex(ss, f, S, x, y, edgeSize, gridSize);
-                                                                       copy_v3_v3((float *)&varray[offset],
-                                                                                  (float *)matconv[i].attribs.orco.array[index]);
-                                                                       index = getFaceIndex(ss, f, S, x + 1, y, edgeSize, gridSize);
-                                                                       copy_v3_v3((float *)&varray[offset + max_element_size],
-                                                                               (float *)matconv[i].attribs.orco.array[index]);
-                                                                       index = getFaceIndex(ss, f, S, x + 1, y + 1, edgeSize, gridSize);
-                                                                       copy_v3_v3((float *)&varray[offset + 2 * max_element_size],
-                                                                               (float *)matconv[i].attribs.orco.array[index]);
-                                                                       index = getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize);
-                                                                       copy_v3_v3((float *)&varray[offset + 3 * max_element_size],
-                                                                               (float *)matconv[i].attribs.orco.array[index]);
-
-                                                                       offset += sizeof(float) * 3;
-                                                               }
-                                                               for (b = 0; b < matconv[i].attribs.tottface; b++) {
-                                                                       if (matconv[i].attribs.tface[b].array) {
-                                                                               const MLoopUV *mloopuv = matconv[i].attribs.tface[b].array + tot_loops;
-
-                                                                               copy_v2_v2((float *)&varray[offset], mloopuv[0].uv);
-                                                                               copy_v2_v2((float *)&varray[offset + max_element_size], mloopuv[3].uv);
-                                                                               copy_v2_v2((float *)&varray[offset + 2 * max_element_size], mloopuv[2].uv);
-                                                                               copy_v2_v2((float *)&varray[offset + 3 * max_element_size], mloopuv[1].uv);
-
-                                                                               offset += sizeof(float) * 2;
-                                                                       }
-                                                               }
-                                                               for (b = 0; b < matconv[i].attribs.totmcol; b++) {
-                                                                       if (matconv[i].attribs.mcol[b].array) {
-                                                                               const MLoopCol *mloopcol = matconv[i].attribs.mcol[b].array + tot_loops;
-
-                                                                               copy_v4_v4_uchar(&varray[offset], &mloopcol[0].r);
-                                                                               copy_v4_v4_uchar(&varray[offset + max_element_size], &mloopcol[3].r);
-                                                                               copy_v4_v4_uchar(&varray[offset + 2 * max_element_size], &mloopcol[2].r);
-                                                                               copy_v4_v4_uchar(&varray[offset + 3 * max_element_size], &mloopcol[1].r);
-
-                                                                               offset += sizeof(unsigned char) * 4;
-                                                                       }
-                                                               }
-                                                               for (b = 0; b < matconv[i].attribs.tottang; b++) {
-                                                                       if (matconv[i].attribs.tottang && matconv[i].attribs.tang[b].array) {
-                                                                               const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang[b].array + tot_loops;
-
-                                                                               copy_v4_v4((float *)&varray[offset], looptang[0]);
-                                                                               copy_v4_v4((float *)&varray[offset + max_element_size], looptang[3]);
-                                                                               copy_v4_v4((float *)&varray[offset + 2 * max_element_size], looptang[2]);
-                                                                               copy_v4_v4((float *)&varray[offset + 3 * max_element_size], looptang[1]);
-
-                                                                               offset += sizeof(float) * 4;
-                                                                       }
-                                                               }
-
-                                                               tot_loops += 4;
-                                                       }
-                                               }
-                                       }
-                               }
-                               else {
-                                       tot_loops += 4 * numVerts * gridFaces * gridFaces;
-                               }
-                       }
-                       GPU_buffer_unlock(buffer, GPU_BINDING_ARRAY);
-               }
-
-               for (a = 0; a < tot_active_mat; a++) {
-                       int new_matnr;
-                       int do_draw;
-
-                       new_matnr = dm->drawObject->materials[a].mat_nr;
-
-                       do_draw = setMaterial(new_matnr + 1, &gattribs);
-
-                       if (do_draw) {
-                               if (matconv[a].numdata) {
-                                       GPU_interleaved_attrib_setup(buffer, matconv[a].datatypes, matconv[a].numdata, max_element_size);
-                               }
-                               GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES,
-                                                        dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
-                               if (matconv[a].numdata) {
-                                       GPU_interleaved_attrib_unbind();
-                               }
-                       }
-               }
-
-               GPU_buffers_unbind();
-               if (buffer)
-                       GPU_buffer_free(buffer);
-
-               MEM_freeN(mat_orig_to_new);
-               MEM_freeN(matconv);
-       }
-}
+    return origindex;
+  }
 
-static void ccgDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial)
-{
-       dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
+  return DM_get_edge_data_layer(dm, type);
 }
 
-/* Only used by non-editmesh types */
-static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
-                                     void (*setMaterial)(void *userData, int matnr, void *attribs),
-                                     bool (*setFace)(void *userData, int index), void *userData)
+static void *ccgDM_get_tessface_data_layer(DerivedMesh *dm, int type)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       GPUVertexAttribs gattribs;
-       DMVertexAttribs attribs = {{{NULL}}};
-       int gridSize = ccgSubSurf_getGridSize(ss);
-       int gridFaces = gridSize - 1;
-       int edgeSize = ccgSubSurf_getEdgeSize(ss);
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-       const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
-       int a, i, numVerts, matnr, totface;
+  if (type == CD_ORIGINDEX) {
+    /* create origindex on demand to save memory */
+    int *origindex;
 
-#ifdef WITH_OPENSUBDIV
-       if (ccgdm->useGpuBackend) {
-               const int level = ccgSubSurf_getSubdivisionLevels(ss);
-               const int face_side = 1 << level;
-               const int grid_side = 1 << (level - 1);
-               const int face_patches = face_side * face_side;
-               const int grid_patches = grid_side * grid_side;
-               const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
-               int current_patch = 0;
-               int mat_nr = -1;
-               bool draw_smooth = false;
-               int start_draw_patch = -1, num_draw_patches = 0;
-               GPU_draw_update_fvar_offset(dm);
-               if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, -1) == false)) {
-                       return;
-               }
-               for (i = 0; i < num_base_faces; ++i) {
-                       const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
-                       const int num_patches = (num_face_verts == 4) ? face_patches
-                                                                     : num_face_verts * grid_patches;
-                       int new_matnr;
-                       bool new_draw_smooth;
-
-                       if (faceFlags) {
-                               new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
-                               new_matnr = (faceFlags[i].mat_nr + 1);
-                       }
-                       else {
-                               new_draw_smooth = true;
-                               new_matnr = 1;
-                       }
-                       if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) {
-                               if (num_draw_patches != 0) {
-                                       setMaterial(userData, mat_nr, &gattribs);
-                                       glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
-                                       ccgSubSurf_drawGLMesh(ss,
-                                                             true,
-                                                             start_draw_patch,
-                                                             num_draw_patches);
-                               }
-                               start_draw_patch = current_patch;
-                               num_draw_patches = num_patches;
-                               mat_nr = new_matnr;
-                               draw_smooth = new_draw_smooth;
-                       }
-                       else {
-                               num_draw_patches += num_patches;
-                       }
-                       current_patch += num_patches;
-               }
-               if (num_draw_patches != 0) {
-                       setMaterial(userData, mat_nr, &gattribs);
-                       glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
-                       ccgSubSurf_drawGLMesh(ss,
-                                             true,
-                                             start_draw_patch,
-                                             num_draw_patches);
-               }
-               glShadeModel(GL_SMOOTH);
-               return;
-       }
-#endif
+    /* Avoid re-creation if the layer exists already */
+    origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
+    if (origindex) {
+      return origindex;
+    }
 
-       CCG_key_top_level(&key, ss);
-       ccgdm_pbvh_update(ccgdm);
-
-       matnr = -1;
-
-#define PASSATTRIB(dx, dy, vert) {                                           \
-    if (attribs.totorco)                                                     \
-        index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize);  \
-    else                                                                     \
-        index = 0;                                                           \
-    DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert);       \
-    DM_draw_attrib_vertex_uniforms(&attribs);                                \
-} (void)0
-
-       totface = ccgSubSurf_getNumFaces(ss);
-       for (a = 0, i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               const float (*ln)[3] = NULL;
-               int S, x, y, drawSmooth;
-               int index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-               int origIndex = ccgDM_getFaceMapIndex(ss, f);
-               int new_matnr;
-
-               numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               /* get flags */
-               if (faceFlags) {
-                       drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH));
-                       new_matnr = faceFlags[index].mat_nr + 1;
-               }
-               else {
-                       drawSmooth = 1;
-                       new_matnr = 1;
-               }
-
-               if (lnors) {
-                       ln = lnors;
-                       lnors += (gridFaces * gridFaces * numVerts) * 4;
-               }
-
-               /* material */
-               if (new_matnr != matnr) {
-                       setMaterial(userData, matnr = new_matnr, &gattribs);
-                       DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
-               }
-
-               /* face hiding */
-               if ((setFace && (origIndex != ORIGINDEX_NONE) && !setFace(userData, origIndex))) {
-                       a += gridFaces * gridFaces * numVerts;
-                       continue;
-               }
-
-               /* draw face*/
-               glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT);
-               for (S = 0; S < numVerts; S++) {
-                       CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
-                       CCGElem *vda, *vdb;
-
-                       if (ln) {
-                               glBegin(GL_QUADS);
-                               for (y = 0; y < gridFaces; y++) {
-                                       for (x = 0; x < gridFaces; x++) {
-                                               float *aco = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
-                                               float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
-                                               float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
-                                               float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
-                                               PASSATTRIB(0, 1, 1);
-                                               glNormal3fv(ln[1]);
-                                               glVertex3fv(dco);
-                                               PASSATTRIB(1, 1, 2);
-                                               glNormal3fv(ln[2]);
-                                               glVertex3fv(cco);
-                                               PASSATTRIB(1, 0, 3);
-                                               glNormal3fv(ln[3]);
-                                               glVertex3fv(bco);
-                                               PASSATTRIB(0, 0, 0);
-                                               glNormal3fv(ln[0]);
-                                               glVertex3fv(aco);
-
-                                               ln += 4;
-                                               a++;
-                                       }
-                               }
-                               glEnd();
-                       }
-                       else if (drawSmooth) {
-                               for (y = 0; y < gridFaces; y++) {
-                                       glBegin(GL_QUAD_STRIP);
-                                       for (x = 0; x < gridFaces; x++) {
-                                               vda = CCG_grid_elem(&key, faceGridData, x, y);
-                                               vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
-
-                                               PASSATTRIB(0, 0, 0);
-                                               glNormal3fv(CCG_elem_no(&key, vda));
-                                               glVertex3fv(CCG_elem_co(&key, vda));
-
-                                               PASSATTRIB(0, 1, 1);
-                                               glNormal3fv(CCG_elem_no(&key, vdb));
-                                               glVertex3fv(CCG_elem_co(&key, vdb));
-
-                                               if (x != gridFaces - 1)
-                                                       a++;
-                                       }
-
-                                       vda = CCG_grid_elem(&key, faceGridData, x, y + 0);
-                                       vdb = CCG_grid_elem(&key, faceGridData, x, y + 1);
-
-                                       PASSATTRIB(0, 0, 3);
-                                       glNormal3fv(CCG_elem_no(&key, vda));
-                                       glVertex3fv(CCG_elem_co(&key, vda));
-
-                                       PASSATTRIB(0, 1, 2);
-                                       glNormal3fv(CCG_elem_no(&key, vdb));
-                                       glVertex3fv(CCG_elem_co(&key, vdb));
-
-                                       glEnd();
-
-                                       a++;
-                               }
-                       }
-                       else {
-                               glBegin(GL_QUADS);
-                               for (y = 0; y < gridFaces; y++) {
-                                       for (x = 0; x < gridFaces; x++) {
-                                               float *aco = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
-                                               float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
-                                               float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
-                                               float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
-                                               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();
-                       }
-               }
-       }
-
-       glShadeModel(GL_SMOOTH);
-#undef PASSATTRIB
-}
+    DM_add_tessface_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
+    origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
 
-static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
-                                      DMSetDrawOptionsTex drawParams,
-                                      DMSetDrawOptionsMappedTex drawParamsMapped,
-                                      DMCompareDrawOptions compareDrawOptions,
-                                      void *userData, DMDrawFlag flag)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       int colType;
-       const MLoopCol *mloopcol = NULL;
-       MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-       DMDrawOption draw_option;
-       int i, totpoly;
-       bool flush;
-       const bool use_tface = (flag & DM_DRAW_USE_ACTIVE_UV) != 0;
-       const bool use_colors = (flag & DM_DRAW_USE_COLORS) != 0;
-       unsigned int next_actualFace;
-       unsigned int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
-       int mat_index;
-       int tot_element, start_element, tot_drawn;
-
-       if (use_colors) {
-               colType = CD_TEXTURE_MLOOPCOL;
-               mloopcol = dm->getLoopDataArray(dm, colType);
-               if (!mloopcol) {
-                       colType = CD_PREVIEW_MLOOPCOL;
-                       mloopcol = dm->getLoopDataArray(dm, colType);
-               }
-               if (!mloopcol) {
-                       colType = CD_MLOOPCOL;
-                       mloopcol = dm->getLoopDataArray(dm, colType);
-               }
-       }
+    /* silly loop counting up */
+    range_vn_i(origindex, dm->getNumTessFaces(dm), 0);
 
-#ifdef WITH_OPENSUBDIV
-       if (ccgdm->useGpuBackend) {
-               const int active_uv_layer = CustomData_get_active_layer_index(&dm->loopData, CD_MLOOPUV);
-               if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, active_uv_layer) == false)) {
-                       return;
-               }
-               if (drawParams == NULL) {
-                       ccgSubSurf_drawGLMesh(ss, true, -1, -1);
-                       return;
-               }
-               const int level = ccgSubSurf_getSubdivisionLevels(ss);
-               const int face_side = 1 << level;
-               const int grid_side = 1 << (level - 1);
-               const int face_patches = face_side * face_side;
-               const int grid_patches = grid_side * grid_side;
-               const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
-               int current_patch = 0;
-               int mat_nr = -1;
-               int start_draw_patch = 0, num_draw_patches = 0;
-               bool draw_smooth = false;
-               for (i = 0; i < num_base_faces; ++i) {
-                       const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
-                       const int num_patches = (num_face_verts == 4) ? face_patches
-                                                                     : num_face_verts * grid_patches;
-                       if (faceFlags) {
-                               mat_nr = faceFlags[i].mat_nr;
-                               draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
-                       }
-                       else {
-                               mat_nr = 0;
-                               draw_smooth = false;
-                       }
-
-                       if (drawParams != NULL) {
-                               MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[i] : NULL;
-                               draw_option = drawParams(tp, (mloopcol != NULL), mat_nr);
-                       }
-                       else {
-                               draw_option = (drawParamsMapped)
-                                                 ? drawParamsMapped(userData, i, mat_nr)
-                                                 : DM_DRAW_OPTION_NORMAL;
-                       }
-
-                       flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == num_base_faces - 1);
-
-                       const int next_face = min_ii(i + 1, num_base_faces - 1);
-                       if (!flush && compareDrawOptions) {
-                               flush |= compareDrawOptions(userData, i, next_face) == 0;
-                       }
-                       if (!flush && faceFlags) {
-                               bool new_draw_smooth = (faceFlags[next_face].flag & ME_SMOOTH);
-                               flush |= (new_draw_smooth != draw_smooth);
-                       }
-
-                       current_patch += num_patches;
-
-                       if (flush) {
-                               if (draw_option != DM_DRAW_OPTION_SKIP) {
-                                       num_draw_patches += num_patches;
-                               }
-                               if (num_draw_patches != 0) {
-                                       glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
-                                       ccgSubSurf_drawGLMesh(ss,
-                                                             true,
-                                                             start_draw_patch,
-                                                             num_draw_patches);
-                               }
-                               start_draw_patch = current_patch;
-                               num_draw_patches = 0;
-                       }
-                       else {
-                               num_draw_patches += num_patches;
-                       }
-               }
-               glShadeModel(GL_SMOOTH);
-               return;
-       }
-#endif
+    return origindex;
+  }
 
-       CCG_key_top_level(&key, ss);
-       ccgdm_pbvh_update(ccgdm);
-
-       GPU_vertex_setup(dm);
-       GPU_normal_setup(dm);
-       GPU_triangle_setup(dm);
-       if (flag & DM_DRAW_USE_TEXPAINT_UV)
-               GPU_texpaint_uv_setup(dm);
-       else
-               GPU_uv_setup(dm);
-       if (mloopcol) {
-               GPU_color_setup(dm, colType);
-       }
-
-       next_actualFace = 0;
-
-       /* lastFlag = 0; */ /* UNUSED */
-       for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
-               GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
-               next_actualFace = bufmat->polys[0];
-               totpoly = bufmat->totpolys;
-
-               tot_element = 0;
-               tot_drawn = 0;
-               start_element = 0;
-
-               for (i = 0; i < totpoly; i++) {
-                       int polyindex = bufmat->polys[i];
-                       CCGFace *f = ccgdm->faceMap[polyindex].face;
-                       int numVerts = ccgSubSurf_getFaceNumVerts(f);
-                       int index = ccgDM_getFaceMapIndex(ss, f);
-                       int orig_index = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-                       int mat_nr;
-                       int facequads = numVerts * gridFaces * gridFaces;
-                       int actualFace = ccgdm->faceMap[polyindex].startFace;
-
-                       if (i != totpoly - 1) {
-                               polyindex = bufmat->polys[i + 1];
-                               next_actualFace = ccgdm->faceMap[polyindex].startFace;
-                       }
-
-                       if (faceFlags) {
-                               mat_nr = faceFlags[orig_index].mat_nr;
-                       }
-                       else {
-                               mat_nr = 0;
-                       }
-
-                       if (drawParams) {
-                               MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[actualFace] : NULL;
-                               draw_option = drawParams(tp, (mloopcol != NULL), mat_nr);
-                       }
-                       else if (index != ORIGINDEX_NONE)
-                               draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL;
-                       else
-                               draw_option = DM_DRAW_OPTION_NORMAL;
-
-                       /* flush buffer if current triangle isn't drawable or it's last triangle */
-                       flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
-
-                       if (!flush && compareDrawOptions) {
-                               /* also compare draw options and flush buffer if they're different
-                                * need for face selection highlight in edit mode */
-                               flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
-                       }
-
-                       tot_element += facequads * 6;
-
-                       if (flush) {
-                               if (draw_option != DM_DRAW_OPTION_SKIP)
-                                       tot_drawn += facequads * 6;
-
-                               if (tot_drawn) {
-                                       if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
-                                               GPU_color_switch(1);
-                                       else
-                                               GPU_color_switch(0);
-
-                                       GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
-                                       tot_drawn = 0;
-                               }
-
-                               start_element = tot_element;
-                       }
-                       else {
-                               tot_drawn += facequads * 6;
-                       }
-               }
-       }
-
-
-       GPU_buffers_unbind();
-}
+  if (type == CD_TESSLOOPNORMAL) {
+    /* Create tessloopnormal on demand to save memory. */
+    /* Note that since tessellated face corners are the same a loops in CCGDM,
+     * and since all faces have four loops/corners, we can simplify the code
+     * here by converting tessloopnormals from 'short (*)[4][3]' to 'short (*)[3]'. */
+    short(*tlnors)[3];
 
-static void ccgDM_drawFacesTex(DerivedMesh *dm,
-                               DMSetDrawOptionsTex setDrawOptions,
-                               DMCompareDrawOptions compareDrawOptions,
-                               void *userData, DMDrawFlag flag)
-{
-       ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag);
-}
+    /* Avoid re-creation if the layer exists already */
+    tlnors = DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
+    if (!tlnors) {
+      float(*lnors)[3];
+      short(*tlnors_it)[3];
+      const int numLoops = ccgDM_getNumLoops(dm);
+      int i;
 
-static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
-                                     DMSetDrawOptionsMappedTex setDrawOptions,
-                                     DMCompareDrawOptions compareDrawOptions,
-                                     void *userData, DMDrawFlag flag)
-{
-       ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
-}
+      lnors = dm->getLoopDataArray(dm, CD_NORMAL);
+      if (!lnors) {
+        return NULL;
+      }
 
-/* same as cdDM_drawUVEdges */
-static void ccgDM_drawUVEdges(DerivedMesh *dm)
-{
-       MPoly *mpoly = dm->getPolyArray(dm);
-       int totpoly = dm->getNumPolys(dm);
-       int prevstart = 0;
-       bool prevdraw = true;
-       int curpos = 0;
-       int i;
-
-       GPU_uvedge_setup(dm);
-       for (i = 0; i < totpoly; i++, mpoly++) {
-               const bool draw = (mpoly->flag & ME_HIDE) == 0;
-
-               if (prevdraw != draw) {
-                       if (prevdraw && (curpos != prevstart)) {
-                               glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
-                       }
-                       prevstart = curpos;
-               }
-
-               curpos += 2 * mpoly->totloop;
-               prevdraw = draw;
-       }
-       if (prevdraw && (curpos != prevstart)) {
-               glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
-       }
-       GPU_buffers_unbind();
-}
+      DM_add_tessface_layer(dm, CD_TESSLOOPNORMAL, CD_CALLOC, NULL);
+      tlnors = tlnors_it = (short(*)[3])DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
 
-static void ccgDM_drawMappedFaces(DerivedMesh *dm,
-                                  DMSetDrawOptions setDrawOptions,
-                                  DMSetMaterial setMaterial,
-                                  DMCompareDrawOptions compareDrawOptions,
-                                  void *userData, DMDrawFlag flag)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       MLoopCol *mloopcol = NULL;
-       const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
-       int i, gridSize = ccgSubSurf_getGridSize(ss);
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-       int useColors = flag & DM_DRAW_USE_COLORS;
-       int gridFaces = gridSize - 1, totface;
-       int prev_mat_nr = -1;
-
-       if (ccgdm->pbvh) {
-               if (G.debug_value == 14)
-                       BKE_pbvh_draw_BB(ccgdm->pbvh);
-       }
+      /* With ccgdm, we have a simple one to one mapping between loops
+       * and tessellated face corners. */
+      for (i = 0; i < numLoops; ++i, ++tlnors_it, ++lnors) {
+        normal_float_to_short_v3(*tlnors_it, *lnors);
+      }
+    }
 
-#ifdef WITH_OPENSUBDIV
-       if (ccgdm->useGpuBackend) {
-               int new_matnr;
-               bool draw_smooth, do_draw = true;
-               if (setDrawOptions == NULL) {
-                       /* TODO(sergey): This is for cases when vertex colors or weights
-                        * are visualising. Currently we don't have CD layers for this data
-                        * and here we only make it so there's no garbage displayed.
-                        *
-                        * In the future we'll either need to have CD for this data or pass
-                        * this data as face-varying or vertex-varying data in OSD mesh.
-                        */
-                       glColor3f(0.8f, 0.8f, 0.8f);
-               }
-               if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, -1) == false)) {
-                       return;
-               }
-               if (faceFlags) {
-                       draw_smooth = (faceFlags[0].flag & ME_SMOOTH);
-                       new_matnr = (faceFlags[0].mat_nr + 1);
-               }
-               else {
-                       draw_smooth = true;
-                       new_matnr = 1;
-               }
-               if (setMaterial) {
-                       setMaterial(new_matnr, NULL);
-               }
-               if (setDrawOptions) {
-                       if (setDrawOptions(userData, 0) == DM_DRAW_OPTION_SKIP) {
-                               do_draw = false;
-                       }
-               }
-               if (do_draw) {
-                       glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
-                       ccgSubSurf_drawGLMesh(ss, true, -1, -1);
-                       glShadeModel(GL_SMOOTH);
-               }
-               return;
-       }
-#endif
+    return tlnors;
+  }
 
-       CCG_key_top_level(&key, ss);
-
-       /* currently unused -- each original face is handled separately */
-       (void)compareDrawOptions;
-
-       if (useColors) {
-               mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL);
-               if (!mloopcol)
-                       mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL);
-       }
-
-       totface = ccgSubSurf_getNumFaces(ss);
-       for (i = 0; i < totface; i++) {
-               CCGFace *f = ccgdm->faceMap[i].face;
-               int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
-               int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
-               int origIndex;
-               unsigned char *cp = NULL;
-               const float (*ln)[3] = NULL;
-
-               origIndex = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-
-               if (flag & DM_DRAW_ALWAYS_SMOOTH) drawSmooth = 1;
-               else if (faceFlags) drawSmooth = (lnors || (faceFlags[origIndex].flag & ME_SMOOTH));
-               else drawSmooth = 1;
-
-               if (mloopcol) {
-                       cp = (unsigned char *)mloopcol;
-                       mloopcol += gridFaces * gridFaces * numVerts * 4;
-               }
-
-               if (lnors) {
-                       ln = lnors;
-                       lnors += (gridFaces * gridFaces * numVerts) * 4;
-               }
-
-               {
-                       DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
-
-                       if (setMaterial) {
-                               int mat_nr = faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1;
-
-                               if (mat_nr != prev_mat_nr) {
-                                       setMaterial(mat_nr, NULL);  /* XXX, no faceFlags no material */
-                                       prev_mat_nr = mat_nr;
-                               }
-                       }
-
-                       if (setDrawOptions && (index != ORIGINDEX_NONE))
-                               draw_option = setDrawOptions(userData, index);
-
-                       if (draw_option != DM_DRAW_OPTION_SKIP) {
-                               if (draw_option == DM_DRAW_OPTION_STIPPLE) {
-                                       GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
-                                       GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
-                               }
-
-                               for (S = 0; S < numVerts; S++) {
-                                       CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
-                                       if (ln) {
-                                               glBegin(GL_QUADS);
-                                               for (y = 0; y < gridFaces; y++) {
-                                                       for (x = 0; x < gridFaces; x++) {
-                                                               float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
-                                                               float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
-                                                               float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
-                                                               float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
-                                                               if (cp) glColor4ubv(&cp[4]);
-                                                               glNormal3fv(ln[1]);
-                                                               glVertex3fv(d);
-                                                               if (cp) glColor4ubv(&cp[8]);
-                                                               glNormal3fv(ln[2]);
-                                                               glVertex3fv(c);
-                                                               if (cp) glColor4ubv(&cp[12]);
-                                                               glNormal3fv(ln[3]);
-                                                               glVertex3fv(b);
-                                                               if (cp) glColor4ubv(&cp[0]);
-                                                               glNormal3fv(ln[0]);
-                                                               glVertex3fv(a);
-
-                                                               if (cp) cp += 16;
-                                                               ln += 4;
-                                                       }
-                                               }
-                                               glEnd();
-                                       }
-                                       else if (drawSmooth) {
-                                               for (y = 0; y < gridFaces; y++) {
-                                                       CCGElem *a, *b;
-                                                       glBegin(GL_QUAD_STRIP);
-                                                       for (x = 0; x < gridFaces; x++) {
-                                                               a = CCG_grid_elem(&key, faceGridData, x, y + 0);
-                                                               b = CCG_grid_elem(&key, faceGridData, x, y + 1);
-
-                                                               if (cp) glColor4ubv(&cp[0]);
-                                                               glNormal3fv(CCG_elem_no(&key, a));
-                                                               glVertex3fv(CCG_elem_co(&key, a));
-                                                               if (cp) glColor4ubv(&cp[4]);
-                                                               glNormal3fv(CCG_elem_no(&key, b));
-                                                               glVertex3fv(CCG_elem_co(&key, b));
-
-                                                               if (x != gridFaces - 1) {
-                                                                       if (cp) cp += 16;
-                                                               }
-                                                       }
-
-                                                       a = CCG_grid_elem(&key, faceGridData, x, y + 0);
-                                                       b = CCG_grid_elem(&key, faceGridData, x, y + 1);
-
-                                                       if (cp) glColor4ubv(&cp[12]);
-                                                       glNormal3fv(CCG_elem_no(&key, a));
-                                                       glVertex3fv(CCG_elem_co(&key, a));
-                                                       if (cp) glColor4ubv(&cp[8]);
-                                                       glNormal3fv(CCG_elem_no(&key, b));
-                                                       glVertex3fv(CCG_elem_co(&key, b));
-
-                                                       if (cp) cp += 16;
-
-                                                       glEnd();
-                                               }
-                                       }
-                                       else {
-                                               glBegin(GL_QUADS);
-                                               for (y = 0; y < gridFaces; y++) {
-                                                       for (x = 0; x < gridFaces; x++) {
-                                                               float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0);
-                                                               float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0);
-                                                               float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
-                                                               float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
-
-                                                               ccgDM_glNormalFast(a, b, c, d);
-
-                                                               if (cp) glColor4ubv(&cp[4]);
-                                                               glVertex3fv(d);
-                                                               if (cp) glColor4ubv(&cp[8]);
-                                                               glVertex3fv(c);
-                                                               if (cp) glColor4ubv(&cp[12]);
-                                                               glVertex3fv(b);
-                                                               if (cp) glColor4ubv(&cp[0]);
-                                                               glVertex3fv(a);
-
-                                                               if (cp) cp += 16;
-                                                       }
-                                               }
-                                               glEnd();
-                                       }
-                               }
-                               if (draw_option == DM_DRAW_OPTION_STIPPLE)
-                                       GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-                       }
-               }
-       }
+  return DM_get_tessface_data_layer(dm, type);
 }
 
-static void ccgDM_drawMappedEdges(DerivedMesh *dm,
-                                  DMSetDrawOptions setDrawOptions,
-                                  void *userData)
+static void *ccgDM_get_poly_data_layer(DerivedMesh *dm, int type)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGEdgeIterator ei;
-       CCGKey key;
-       int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
+  if (type == CD_ORIGINDEX) {
+    /* create origindex on demand to save memory */
+    CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+    CCGSubSurf *ss = ccgdm->ss;
+    int *origindex;
+    int a, i, index, totface;
+    int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
 
-#ifdef WITH_OPENSUBDIV
-       if (ccgdm->useGpuBackend) {
-               /* TODO(sergey): Only draw edges from base mesh. */
-               if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true, -1)) {
-                       if (!setDrawOptions || (setDrawOptions(userData, 0) != DM_DRAW_OPTION_SKIP)) {
-                               ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1);
-                       }
-               }
-               return;
-       }
-#endif
+    /* Avoid re-creation if the layer exists already */
+    origindex = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
+    if (origindex) {
+      return origindex;
+    }
 
-       CCG_key_top_level(&key, ss);
-       ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
-
-       for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
-               CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
-               CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
-               int index = ccgDM_getEdgeMapIndex(ss, e);
-
-               glBegin(GL_LINE_STRIP);
-               if (index != -1 && (!setDrawOptions || (setDrawOptions(userData, index) != DM_DRAW_OPTION_SKIP))) {
-                       if (useAging && !(G.f & G_BACKBUFSEL)) {
-                               int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4;
-                               glColor3ub(0, ageCol > 0 ? ageCol : 0, 0);
-                       }
-
-                       for (i = 0; i < edgeSize - 1; i++) {
-                               glVertex3fv(CCG_elem_offset_co(&key, edgeData, i));
-                               glVertex3fv(CCG_elem_offset_co(&key, edgeData, i + 1));
-                       }
-               }
-               glEnd();
-       }
-}
+    DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
+    origindex = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
 
-static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm,
-                                        DMSetDrawOptions setDrawOptions,
-                                        DMSetDrawInterpOptions setDrawInterpOptions,
-                                        void *userData)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       CCGEdgeIterator ei;
-       int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
+    totface = ccgSubSurf_getNumFaces(ss);
 
-#ifdef WITH_OPENSUBDIV
-       if (ccgdm->useGpuBackend) {
-               BLI_assert(!"Not currently supported");
-               return;
-       }
-#endif
+    for (a = 0, index = 0; index < totface; index++) {
+      CCGFace *f = ccgdm->faceMap[index].face;
+      int numVerts = ccgSubSurf_getFaceNumVerts(f);
+      int mapIndex = ccgDM_getFaceMapIndex(ss, f);
 
-       CCG_key_top_level(&key, ss);
-       ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
-
-       for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) {
-               CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
-               CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
-               int index = ccgDM_getEdgeMapIndex(ss, e);
-
-               glBegin(GL_LINE_STRIP);
-               if (index != -1 && (!setDrawOptions || (setDrawOptions(userData, index) != DM_DRAW_OPTION_SKIP))) {
-                       for (i = 0; i < edgeSize; i++) {
-                               setDrawInterpOptions(userData, index, (float) i / (edgeSize - 1));
-
-                               if (useAging && !(G.f & G_BACKBUFSEL)) {
-                                       int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4;
-                                       glColor3ub(0, ageCol > 0 ? ageCol : 0, 0);
-                               }
-
-                               glVertex3fv(CCG_elem_offset_co(&key, edgeData, i));
-                       }
-               }
-               glEnd();
-       }
-}
+      for (i = 0; i < gridFaces * gridFaces * numVerts; i++, a++) {
+        origindex[a] = mapIndex;
+      }
+    }
 
-static void ccgDM_foreachMappedFaceCenter(
-        DerivedMesh *dm,
-        void (*func)(void *userData, int index, const float co[3], const float no[3]),
-        void *userData,
-        DMForeachFlag flag)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGKey key;
-       CCGFaceIterator fi;
-
-       CCG_key_top_level(&key, ss);
-
-       for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) {
-               CCGFace *f = ccgFaceIterator_getCurrent(&fi);
-               const int index = ccgDM_getFaceMapIndex(ss, f);
-
-               if (index != -1) {
-                       /* Face center data normal isn't updated atm. */
-                       CCGElem *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0);
-                       const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL;
-                       func(userData, index, CCG_elem_co(&key, vd), no);
-               }
-       }
-}
+    return origindex;
+  }
 
-static void ccgDM_release(DerivedMesh *dm)
-{
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
-
-       if (DM_release(dm)) {
-               /* Before freeing, need to update the displacement map */
-               if (ccgdm->multires.modified_flags) {
-                       /* Check that mmd still exists */
-                       if (!ccgdm->multires.local_mmd &&
-                           BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) < 0)
-                       {
-                               ccgdm->multires.mmd = NULL;
-                       }
-
-                       if (ccgdm->multires.mmd) {
-                               if (ccgdm->multires.modified_flags & MULTIRES_COORDS_MODIFIED)
-                                       multires_modifier_update_mdisps(dm);
-                               if (ccgdm->multires.modified_flags & MULTIRES_HIDDEN_MODIFIED)
-                                       multires_modifier_update_hidden(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->gridOffset) MEM_freeN(ccgdm->gridOffset);
-               if (ccgdm->gridFlagMats) MEM_freeN(ccgdm->gridFlagMats);
-               if (ccgdm->gridHidden) {
-                       /* Using dm->getNumGrids(dm) accesses freed memory */
-                       uint numGrids = ccgdm->numGrid;
-                       for (uint i = 0; i < numGrids; i++) {
-                               if (ccgdm->gridHidden[i]) {
-                                       MEM_freeN(ccgdm->gridHidden[i]);
-                               }
-                       }
-                       MEM_freeN(ccgdm->gridHidden);
-               }
-               if (ccgdm->freeSS) ccgSubSurf_free(ccgdm->ss);
-               if (ccgdm->pmap) MEM_freeN(ccgdm->pmap);
-               if (ccgdm->pmap_mem) MEM_freeN(ccgdm->pmap_mem);
-               MEM_freeN(ccgdm->edgeFlags);
-               MEM_freeN(ccgdm->faceFlags);
-               if (ccgdm->useGpuBackend == false) {
-                       MEM_freeN(ccgdm->vertMap);
-                       MEM_freeN(ccgdm->edgeMap);
-                       MEM_freeN(ccgdm->faceMap);
-               }
-
-               BLI_mutex_end(&ccgdm->loops_cache_lock);
-               BLI_rw_mutex_end(&ccgdm->origindex_cache_rwlock);
-
-               MEM_freeN(ccgdm);
-       }
-}
-
-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;
-               int *origindex;
-               int a, index, totnone, totorig;
-
-               /* Avoid re-creation if the layer exists already */
-               BLI_rw_mutex_lock(&ccgdm->origindex_cache_rwlock, THREAD_LOCK_READ);
-               origindex = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
-               BLI_rw_mutex_unlock(&ccgdm->origindex_cache_rwlock);
-               if (origindex) {
-                       return origindex;
-               }
-
-               BLI_rw_mutex_lock(&ccgdm->origindex_cache_rwlock, THREAD_LOCK_WRITE);
-               DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
-               origindex = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
-
-               totorig = ccgSubSurf_getNumVerts(ss);
-               totnone = dm->numVertData - totorig;
-
-               /* original vertices are at the end */
-               for (a = 0; a < totnone; a++)
-                       origindex[a] = ORIGINDEX_NONE;
-
-               for (index = 0; index < totorig; index++, a++) {
-                       CCGVert *v = ccgdm->vertMap[index].vert;
-                       origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v);
-               }
-               BLI_rw_mutex_unlock(&ccgdm->origindex_cache_rwlock);
-
-               return origindex;
-       }
-
-       return DM_get_vert_data_layer(dm, type);
-}
-
-static void *ccgDM_get_edge_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;
-               int *origindex;
-               int a, i, index, totnone, totorig, totedge;
-               int edgeSize = ccgSubSurf_getEdgeSize(ss);
-
-               /* Avoid re-creation if the layer exists already */
-               origindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
-               if (origindex) {
-                       return origindex;
-               }
-
-               DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
-               origindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
-
-               totedge = ccgSubSurf_getNumEdges(ss);
-               totorig = totedge * (edgeSize - 1);
-               totnone = dm->numEdgeData - totorig;
-
-               /* original edges are at the end */
-               for (a = 0; a < totnone; a++)
-                       origindex[a] = ORIGINDEX_NONE;
-
-               for (index = 0; index < totedge; index++) {
-                       CCGEdge *e = ccgdm->edgeMap[index].edge;
-                       int mapIndex = ccgDM_getEdgeMapIndex(ss, e);
-
-                       for (i = 0; i < edgeSize - 1; i++, a++)
-                               origindex[a] = mapIndex;
-               }
-
-               return origindex;
-       }
-
-       return DM_get_edge_data_layer(dm, type);
-}
-
-static void *ccgDM_get_tessface_data_layer(DerivedMesh *dm, int type)
-{
-       if (type == CD_ORIGINDEX) {
-               /* create origindex on demand to save memory */
-               int *origindex;
-
-               /* Avoid re-creation if the layer exists already */
-               origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
-               if (origindex) {
-                       return origindex;
-               }
-
-               DM_add_tessface_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
-               origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
-
-               /* silly loop counting up */
-               range_vn_i(origindex, dm->getNumTessFaces(dm), 0);
-
-               return origindex;
-       }
-
-       if (type == CD_TESSLOOPNORMAL) {
-               /* Create tessloopnormal on demand to save memory. */
-               /* Note that since tessellated face corners are the same a loops in CCGDM, and since all faces have four
-                * loops/corners, we can simplify the code here by converting tessloopnormals from 'short (*)[4][3]'
-                * to 'short (*)[3]'.
-                */
-               short (*tlnors)[3];
-
-               /* Avoid re-creation if the layer exists already */
-               tlnors = DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
-               if (!tlnors) {
-                       float (*lnors)[3];
-                       short (*tlnors_it)[3];
-                       const int numLoops = ccgDM_getNumLoops(dm);
-                       int i;
-
-                       lnors = dm->getLoopDataArray(dm, CD_NORMAL);
-                       if (!lnors) {
-                               return NULL;
-                       }
-
-                       DM_add_tessface_layer(dm, CD_TESSLOOPNORMAL, CD_CALLOC, NULL);
-                       tlnors = tlnors_it = (short (*)[3])DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
-
-                       /* With ccgdm, we have a simple one to one mapping between loops and tessellated face corners. */
-                       for (i = 0; i < numLoops; ++i, ++tlnors_it, ++lnors) {
-                               normal_float_to_short_v3(*tlnors_it, *lnors);
-                       }
-               }
-
-               return tlnors;
-       }
-
-       return DM_get_tessface_data_layer(dm, type);
-}
-
-static void *ccgDM_get_poly_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;
-               int *origindex;
-               int a, i, index, totface;
-               int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
-
-               /* Avoid re-creation if the layer exists already */
-               origindex = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
-               if (origindex) {
-                       return origindex;
-               }
-
-               DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
-               origindex = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
-
-               totface = ccgSubSurf_getNumFaces(ss);
-
-               for (a = 0, index = 0; index < totface; index++) {
-                       CCGFace *f = ccgdm->faceMap[index].face;
-                       int numVerts = ccgSubSurf_getFaceNumVerts(f);
-                       int mapIndex = ccgDM_getFaceMapIndex(ss, f);
-
-                       for (i = 0; i < gridFaces * gridFaces * numVerts; i++, a++)
-                               origindex[a] = mapIndex;
-               }
-
-               return origindex;
-       }
-
-       return DM_get_poly_data_layer(dm, type);
+  return DM_get_poly_data_layer(dm, type);
 }
 
 static void *ccgDM_get_vert_data(DerivedMesh *dm, int index, int type)
 {
-       if (type == CD_ORIGINDEX) {
-               /* ensure creation of CD_ORIGINDEX layer */
-               ccgDM_get_vert_data_layer(dm, type);
-       }
+  if (type == CD_ORIGINDEX) {
+    /* ensure creation of CD_ORIGINDEX layer */
+    ccgDM_get_vert_data_layer(dm, type);
+  }
 
-       return DM_get_vert_data(dm, index, type);
+  return DM_get_vert_data(dm, index, type);
 }
 
 static void *ccgDM_get_edge_data(DerivedMesh *dm, int index, int type)
 {
-       if (type == CD_ORIGINDEX) {
-               /* ensure creation of CD_ORIGINDEX layer */
-               ccgDM_get_edge_data_layer(dm, type);
-       }
+  if (type == CD_ORIGINDEX) {
+    /* ensure creation of CD_ORIGINDEX layer */
+    ccgDM_get_edge_data_layer(dm, type);
+  }
 
-       return DM_get_edge_data(dm, index, type);
+  return DM_get_edge_data(dm, index, type);
 }
 
 static void *ccgDM_get_tessface_data(DerivedMesh *dm, int index, int type)
 {
-       if (ELEM(type, CD_ORIGINDEX, CD_TESSLOOPNORMAL)) {
-               /* ensure creation of CD_ORIGINDEX/CD_TESSLOOPNORMAL layers */
-               ccgDM_get_tessface_data_layer(dm, type);
-       }
+  if (ELEM(type, CD_ORIGINDEX, CD_TESSLOOPNORMAL)) {
+    /* ensure creation of CD_ORIGINDEX/CD_TESSLOOPNORMAL layers */
+    ccgDM_get_tessface_data_layer(dm, type);
+  }
 
-       return DM_get_tessface_data(dm, index, type);
+  return DM_get_tessface_data(dm, index, type);
 }
 
 static void *ccgDM_get_poly_data(DerivedMesh *dm, int index, int type)
 {
-       if (type == CD_ORIGINDEX) {
-               /* ensure creation of CD_ORIGINDEX layer */
-               ccgDM_get_tessface_data_layer(dm, type);
-       }
+  if (type == CD_ORIGINDEX) {
+    /* ensure creation of CD_ORIGINDEX layer */
+    ccgDM_get_tessface_data_layer(dm, type);
+  }
 
-       return DM_get_poly_data(dm, index, type);
+  return DM_get_poly_data(dm, index, type);
 }
 
 static int ccgDM_getNumGrids(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-       int index, numFaces, numGrids;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  int index, numFaces, numGrids;
 
-       numFaces = ccgSubSurf_getNumFaces(ccgdm->ss);
-       numGrids = 0;
+  numFaces = ccgSubSurf_getNumFaces(ccgdm->ss);
+  numGrids = 0;
 
-       for (index = 0; index < numFaces; index++) {
-               CCGFace *f = ccgdm->faceMap[index].face;
-               numGrids += ccgSubSurf_getFaceNumVerts(f);
-       }
+  for (index = 0; index < numFaces; index++) {
+    CCGFace *f = ccgdm->faceMap[index].face;
+    numGrids += ccgSubSurf_getFaceNumVerts(f);
+  }
 
-       return numGrids;
+  return numGrids;
 }
 
 static int ccgDM_getGridSize(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-       return ccgSubSurf_getGridSize(ccgdm->ss);
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  return ccgSubSurf_getGridSize(ccgdm->ss);
 }
 
 static void ccgdm_create_grids(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-       CCGSubSurf *ss = ccgdm->ss;
-       CCGElem **gridData;
-       DMFlagMat *gridFlagMats;
-       CCGFace **gridFaces;
-       int *gridOffset;
-       int index, numFaces, numGrids, S, gIndex /*, gridSize*/;
-
-       if (ccgdm->gridData)
-               return;
-
-       numGrids = ccgDM_getNumGrids(dm);
-       numFaces = ccgSubSurf_getNumFaces(ss);
-       /*gridSize = ccgDM_getGridSize(dm);*/  /*UNUSED*/
-
-       /* compute offset into grid array for each face */
-       gridOffset = MEM_mallocN(sizeof(int) * numFaces, "ccgdm.gridOffset");
-
-       for (gIndex = 0, index = 0; index < numFaces; index++) {
-               CCGFace *f = ccgdm->faceMap[index].face;
-               int numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               gridOffset[index] = gIndex;
-               gIndex += numVerts;
-       }
-
-       /* compute grid data */
-       gridData = MEM_mallocN(sizeof(CCGElem *) * numGrids, "ccgdm.gridData");
-       gridFaces = MEM_mallocN(sizeof(CCGFace *) * numGrids, "ccgdm.gridFaces");
-       gridFlagMats = MEM_mallocN(sizeof(DMFlagMat) * numGrids, "ccgdm.gridFlagMats");
-
-       ccgdm->gridHidden = MEM_callocN(sizeof(*ccgdm->gridHidden) * numGrids, "ccgdm.gridHidden");
-
-       for (gIndex = 0, index = 0; index < numFaces; index++) {
-               CCGFace *f = ccgdm->faceMap[index].face;
-               int numVerts = ccgSubSurf_getFaceNumVerts(f);
-
-               for (S = 0; S < numVerts; S++, gIndex++) {
-                       gridData[gIndex] = ccgSubSurf_getFaceGridDataArray(ss, f, S);
-                       gridFaces[gIndex] = f;
-                       gridFlagMats[gIndex] = ccgdm->faceFlags[index];
-               }
-       }
-
-       ccgdm->gridData = gridData;
-       ccgdm->gridFaces = gridFaces;
-       ccgdm->gridOffset = gridOffset;
-       ccgdm->gridFlagMats = gridFlagMats;
-       ccgdm->numGrid = numGrids;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGSubSurf *ss = ccgdm->ss;
+  CCGElem **gridData;
+  DMFlagMat *gridFlagMats;
+  CCGFace **gridFaces;
+  int *gridOffset;
+  int index, numFaces, numGrids, S, gIndex /*, gridSize*/;
+
+  if (ccgdm->gridData) {
+    return;
+  }
+
+  numGrids = ccgDM_getNumGrids(dm);
+  numFaces = ccgSubSurf_getNumFaces(ss);
+  /*gridSize = ccgDM_getGridSize(dm);*/ /*UNUSED*/
+
+  /* compute offset into grid array for each face */
+  gridOffset = MEM_mallocN(sizeof(int) * numFaces, "ccgdm.gridOffset");
+
+  for (gIndex = 0, index = 0; index < numFaces; index++) {
+    CCGFace *f = ccgdm->faceMap[index].face;
+    int numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+    gridOffset[index] = gIndex;
+    gIndex += numVerts;
+  }
+
+  /* compute grid data */
+  gridData = MEM_mallocN(sizeof(CCGElem *) * numGrids, "ccgdm.gridData");
+  gridFaces = MEM_mallocN(sizeof(CCGFace *) * numGrids, "ccgdm.gridFaces");
+  gridFlagMats = MEM_mallocN(sizeof(DMFlagMat) * numGrids, "ccgdm.gridFlagMats");
+
+  ccgdm->gridHidden = MEM_callocN(sizeof(*ccgdm->gridHidden) * numGrids, "ccgdm.gridHidden");
+
+  for (gIndex = 0, index = 0; index < numFaces; index++) {
+    CCGFace *f = ccgdm->faceMap[index].face;
+    int numVerts = ccgSubSurf_getFaceNumVerts(f);
+
+    for (S = 0; S < numVerts; S++, gIndex++) {
+      gridData[gIndex] = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+      gridFaces[gIndex] = f;
+      gridFlagMats[gIndex] = ccgdm->faceFlags[index];
+    }
+  }
+
+  ccgdm->gridData = gridData;
+  ccgdm->gridFaces = gridFaces;
+  ccgdm->gridOffset = gridOffset;
+  ccgdm->gridFlagMats = gridFlagMats;
+  ccgdm->numGrid = numGrids;
 }
 
 static CCGElem **ccgDM_getGridData(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
 
-       ccgdm_create_grids(dm);
-       return ccgdm->gridData;
+  ccgdm_create_grids(dm);
+  return ccgdm->gridData;
 }
 
 static int *ccgDM_getGridOffset(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
 
-       ccgdm_create_grids(dm);
-       return ccgdm->gridOffset;
+  ccgdm_create_grids(dm);
+  return ccgdm->gridOffset;
 }
 
 static void ccgDM_getGridKey(DerivedMesh *dm, CCGKey *key)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-       CCG_key_top_level(key, ccgdm->ss);
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCG_key_top_level(key, ccgdm->ss);
 }
 
 static DMFlagMat *ccgDM_getGridFlagMats(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
 
-       ccgdm_create_grids(dm);
-       return ccgdm->gridFlagMats;
+  ccgdm_create_grids(dm);
+  return ccgdm->gridFlagMats;
 }
 
 static BLI_bitmap **ccgDM_getGridHidden(DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
 
-       ccgdm_create_grids(dm);
-       return ccgdm->gridHidden;
+  ccgdm_create_grids(dm);
+  return ccgdm->gridHidden;
 }
 
 static const MeshElemMap *ccgDM_getPolyMap(Object *ob, DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
 
-       if (!ccgdm->multires.mmd && !ccgdm->pmap && ob->type == OB_MESH) {
-               Mesh *me = ob->data;
+  if (!ccgdm->multires.mmd && !ccgdm->pmap && ob->type == OB_MESH) {
+    Mesh *me = ob->data;
 
-               BKE_mesh_vert_poly_map_create(&ccgdm->pmap, &ccgdm->pmap_mem,
-                                    me->mpoly, me->mloop,
-                                    me->totvert, me->totpoly, me->totloop);
-       }
+    BKE_mesh_vert_poly_map_create(&ccgdm->pmap,
+                                  &ccgdm->pmap_mem,
+                                  me->mpoly,
+                                  me->mloop,
+                                  me->totvert,
+                                  me->totpoly,
+                                  me->totloop);
+  }
 
-       return ccgdm->pmap;
+  return ccgdm->pmap;
 }
 
 static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm)
 {
-       MultiresModifierData *mmd = ccgdm->multires.mmd;
+  MultiresModifierData *mmd = ccgdm->multires.mmd;
 
-       /* both of multires and subsurf modifiers are CCG, but
-        * grids should only be used when sculpting on multires */
-       if (!mmd)
-               return 0;
+  /* both of multires and subsurf modifiers are CCG, but
+   * grids should only be used when sculpting on multires */
+  if (!mmd) {
+    return 0;
+  }
 
-       return 1;
+  return 1;
 }
 
 static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
 {
-       CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-       CCGKey key;
-       int numGrids;
-
-       CCG_key_top_level(&key, ccgdm->ss);
-
-       if (!ob) {
-               ccgdm->pbvh = NULL;
-               return NULL;
-       }
-
-       if (!ob->sculpt)
-               return NULL;
-
-       bool grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
-       if ((ob->mode & OB_MODE_SCULPT) == 0) {
-               /* In vwpaint, we may use a grid_pbvh for multires/subsurf, under certain conditions.
-                * More complex cases break 'history' trail back to original vertices, in that case we fall back to
-                * deformed cage only (i.e. original deformed mesh). */
-               VirtualModifierData virtualModifierData;
-               ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
-
-               grid_pbvh = true;
-               bool has_one_ccg_modifier = false;
-               for (; md; md = md->next) {
-                       /* We can only accept to use this ccgdm if:
-                        *   - it's the only active ccgdm in the stack.
-                        *   - there is no topology-modifying modifier in the stack.
-                        * Otherwise, there is no way to map back to original geometry from grid-generated PBVH.
-                        */
-                       const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
-                       if (!modifier_isEnabled(NULL, md, eModifierMode_Realtime)) {
-                               continue;
-                       }
-                       if (ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical)) {
-                               continue;
-                       }
-
-                       if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
-                               if (has_one_ccg_modifier) {
-                                       /* We only allow a single active ccg modifier in the stack. */
-                                       grid_pbvh = false;
-                                       break;
-                               }
-                               has_one_ccg_modifier = true;
-                               continue;
-                       }
-
-                       /* Any other non-deforming modifier makes it impossible to use grid pbvh. */
-                       grid_pbvh = false;
-                       break;
-               }
-       }
-
-       if (ob->sculpt->pbvh) {
-               /* Note that we have to clean up exisitng pbvh instead of updating it in case it does not match current
-                * grid_pbvh status. */
-               const PBVHType pbvh_type = BKE_pbvh_type(ob->sculpt->pbvh);
-               if (grid_pbvh) {
-                       if (pbvh_type == PBVH_GRIDS) {
-                               /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
-                                * but this can be freed on ccgdm release, this updates the pointers
-                                * when the ccgdm gets remade, the assumption is that the topology
-                                * does not change. */
-                               ccgdm_create_grids(dm);
-                               BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, (void **)ccgdm->gridFaces,
-                                                     ccgdm->gridFlagMats, ccgdm->gridHidden);
-                       }
-                       else {
-                               BKE_pbvh_free(ob->sculpt->pbvh);
-                               ob->sculpt->pbvh = NULL;
-                       }
-               }
-               else if (pbvh_type == PBVH_GRIDS) {
-                       BKE_pbvh_free(ob->sculpt->pbvh);
-                       ob->sculpt->pbvh = NULL;
-               }
-
-               ccgdm->pbvh = ob->sculpt->pbvh;
-       }
-
-       if (ccgdm->pbvh) {
-               return ccgdm->pbvh;
-       }
-
-       /* No pbvh exists yet, we need to create one. only in case of multires
-        * we build a pbvh over the modified mesh, in other cases the base mesh
-        * is being sculpted, so we build a pbvh from that. */
-       /* Note: vwpaint tries to always build a pbvh over the modified mesh. */
-       if (grid_pbvh) {
-               ccgdm_create_grids(dm);
-
-               numGrids = ccgDM_getNumGrids(dm);
-
-               ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
-               BKE_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData,
-                                    numGrids, &key, (void **) ccgdm->gridFaces, ccgdm->gridFlagMats, ccgdm->gridHidden);
-       }
-       else if (ob->type == OB_MESH) {
-               Mesh *me = ob->data;
-               const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
-               MLoopTri *looptri;
-
-               looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
-
-               BKE_mesh_recalc_looptri(
-                       me->mloop, me->mpoly,
-                       me->mvert,
-                       me->totloop, me->totpoly,
-                       looptri);
-
-               ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
-               BKE_pbvh_build_mesh(ccgdm->pbvh, me->mpoly, me->mloop, me->mvert, me->totvert, &me->vdata,
-                                   looptri, looptris_num);
-
-               if (ob->sculpt->modifiers_active && ob->derivedDeform != NULL) {
-                       DerivedMesh *deformdm = ob->derivedDeform;
-                       float (*vertCos)[3];
-                       int totvert;
-
-                       totvert = deformdm->getNumVerts(deformdm);
-                       vertCos = MEM_malloc_arrayN(totvert, sizeof(float[3]), "ccgDM_getPBVH vertCos");
-                       deformdm->getVertCos(deformdm, vertCos);
-                       BKE_pbvh_apply_vertCos(ccgdm->pbvh, vertCos);
-                       MEM_freeN(vertCos);
-               }
-       }
-
-       if (ccgdm->pbvh != NULL) {
-               pbvh_show_diffuse_color_set(ccgdm->pbvh, ob->sculpt->show_diffuse_color);
-               pbvh_show_mask_set(ccgdm->pbvh, ob->sculpt->show_mask);
-       }
-
-       return ccgdm->pbvh;
+  CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
+  CCGKey key;
+  int numGrids;
+
+  CCG_key_top_level(&key, ccgdm->ss);
+
+  if (!ob) {
+    ccgdm->pbvh = NULL;
+    return NULL;
+  }
+
+  if (!ob->sculpt) {
+    return NULL;
+  }
+
+  bool grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
+  if ((ob->mode & OB_MODE_SCULPT) == 0) {
+    /* In vwpaint, we may use a grid_pbvh for multires/subsurf, under certain conditions.
+     * More complex cases break 'history' trail back to original vertices,
+     * in that case we fall back to deformed cage only (i.e. original deformed mesh). */
+    VirtualModifierData virtualModifierData;
+    ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+
+    grid_pbvh = true;
+    bool has_one_ccg_modifier = false;
+    for (; md; md = md->next) {
+      /* We can only accept to use this ccgdm if:
+       *   - it's the only active ccgdm in the stack.
+       *   - there is no topology-modifying modifier in the stack.
+       * Otherwise, there is no way to map back to original geometry from grid-generated PBVH.
+       */
+      const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+      if (!modifier_isEnabled(NULL, md, eModifierMode_Realtime)) {
+        continue;
+      }
+      if (ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical)) {
+        continue;
+      }
+
+      if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
+        if (has_one_ccg_modifier) {
+          /* We only allow a single active ccg modifier in the stack. */
+          grid_pbvh = false;
+          break;
+        }
+        has_one_ccg_modifier = true;
+        continue;
+      }
+
+      /* Any other non-deforming modifier makes it impossible to use grid pbvh. */
+      grid_pbvh = false;
+      break;
+    }
+  }
+
+  if (ob->sculpt->pbvh) {
+    /* Note that we have to clean up exisitng pbvh instead of updating it in case it does not
+     * match current grid_pbvh status. */
+    const PBVHType pbvh_type = BKE_pbvh_type(ob->sculpt->pbvh);
+    if (grid_pbvh) {
+      if (pbvh_type == PBVH_GRIDS) {
+        /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
+         * but this can be freed on ccgdm release, this updates the pointers
+         * when the ccgdm gets remade, the assumption is that the topology
+         * does not change. */
+        ccgdm_create_grids(dm);
+        BKE_pbvh_grids_update(ob->sculpt->pbvh,
+                              ccgdm->gridData,
+                              (void **)ccgdm->gridFaces,
+                              ccgdm->gridFlagMats,
+                              ccgdm->gridHidden);
+      }
+      else {
+        BKE_pbvh_free(ob->sculpt->pbvh);
+        ob->sculpt->pbvh = NULL;
+      }
+    }
+    else if (pbvh_type == PBVH_GRIDS) {
+      BKE_pbvh_free(ob->sculpt->pbvh);
+      ob->sculpt->pbvh = NULL;
+    }
+
+    ccgdm->pbvh = ob->sculpt->pbvh;
+  }
+
+  if (ccgdm->pbvh) {
+    return ccgdm->pbvh;
+  }
+
+  /* No pbvh exists yet, we need to create one. only in case of multires
+   * we build a pbvh over the modified mesh, in other cases the base mesh
+   * is being sculpted, so we build a pbvh from that. */
+  /* Note: vwpaint tries to always build a pbvh over the modified mesh. */
+  if (grid_pbvh) {
+    ccgdm_create_grids(dm);
+
+    numGrids = ccgDM_getNumGrids(dm);
+
+    ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
+    BKE_pbvh_build_grids(ccgdm->pbvh,
+                         ccgdm->gridData,
+                         numGrids,
+                         &key,
+                         (void **)ccgdm->gridFaces,
+                         ccgdm->gridFlagMats,
+                         ccgdm->gridHidden);
+  }
+  else if (ob->type == OB_MESH) {
+    Mesh *me = BKE_object_get_original_mesh(ob);
+    const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
+    MLoopTri *looptri;
+
+    looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
+
+    BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
+
+    ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
+    BKE_pbvh_build_mesh(ccgdm->pbvh,
+                        me->mpoly,
+                        me->mloop,
+                        me->mvert,
+                        me->totvert,
+                        &me->vdata,
+                        &me->ldata,
+                        looptri,
+                        looptris_num);
+
+    if (ob->sculpt->modifiers_active && ob->derivedDeform != NULL) {
+      DerivedMesh *deformdm = ob->derivedDeform;
+      float(*vertCos)[3];
+      int totvert;
+
+      totvert = deformdm->getNumVerts(deformdm);
+      vertCos = MEM_malloc_arrayN(totvert, sizeof(float[3]), "ccgDM_getPBVH vertCos");
+      deformdm->getVertCos(deformdm, vertCos);
+      BKE_pbvh_apply_vertCos(ccgdm->pbvh, vertCos, totvert);
+      MEM_freeN(vertCos);
+    }
+  }
+
+  if (ccgdm->pbvh != NULL) {
+    pbvh_show_diffuse_color_set(ccgdm->pbvh, ob->sculpt->show_diffuse_color);
+    pbvh_show_mask_set(ccgdm->pbvh, ob->sculpt->show_mask);
+  }
+
+  return ccgdm->pbvh;
 }
 
 static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm))
 {
-       /* Nothing to do: CCG handles creating its own tessfaces */
+  /* Nothing to do: CCG handles creating its own tessfaces */
 }
 
 /* WARNING! *MUST* be called in an 'loops_cache_rwlock' protected thread context! */
 static void ccgDM_recalcLoopTri(DerivedMesh *dm)
 {
-       MLoopTri *mlooptri = dm->looptris.array;
-       const int tottri = dm->numPolyData * 2;
-       int i, poly_index;
-
-       DM_ensure_looptri_data(dm);
-       mlooptri = dm->looptris.array_wip;
-
-       BLI_assert(tottri == 0 || mlooptri != NULL);
-       BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
-       BLI_assert(tottri == dm->looptris.num);
-
-       for (i = 0, poly_index = 0; i < tottri; i += 2, poly_index += 1) {
-               MLoopTri *lt;
-               lt = &mlooptri[i];
-               /* quad is (0, 3, 2, 1) */
-               lt->tri[0] = (poly_index * 4) + 0;
-               lt->tri[1] = (poly_index * 4) + 2;
-               lt->tri[2] = (poly_index * 4) + 3;
-               lt->poly = poly_index;
-
-               lt = &mlooptri[i + 1];
-               lt->tri[0] = (poly_index * 4) + 0;
-               lt->tri[1] = (poly_index * 4) + 1;
-               lt->tri[2] = (poly_index * 4) + 2;
-               lt->poly = poly_index;
-       }
-
-       BLI_assert(dm->looptris.array == NULL);
-       atomic_cas_ptr((void **)&dm->looptris.array, dm->looptris.array, dm->looptris.array_wip);
-       dm->looptris.array_wip = NULL;
+  MLoopTri *mlooptri = dm->looptris.array;
+  const int tottri = dm->numPolyData * 2;
+  int i, poly_index;
+
+  DM_ensure_looptri_data(dm);
+  mlooptri = dm->looptris.array_wip;
+
+  BLI_assert(tottri == 0 || mlooptri != NULL);
+  BLI_assert(poly_to_tri_count(dm->numPolyData, dm->numLoopData) == dm->looptris.num);
+  BLI_assert(tottri == dm->looptris.num);
+
+  for (i = 0, poly_index = 0; i < tottri; i += 2, poly_index += 1) {
+    MLoopTri *lt;
+    lt = &mlooptri[i];
+    /* quad is (0, 3, 2, 1) */
+    lt->tri[0] = (poly_index * 4) + 0;
+    lt->tri[1] = (poly_index * 4) + 2;
+    lt->tri[2] = (poly_index * 4) + 3;
+    lt->poly = poly_index;
+
+    lt = &mlooptri[i + 1];
+    lt->tri[0] = (poly_index * 4) + 0;
+    lt->tri[1] = (poly_index * 4) + 1;
+    lt->tri[2] = (poly_index * 4) + 2;
+    lt->poly = poly_index;
+  }
+
+  BLI_assert(dm->looptris.array == NULL);
+  atomic_cas_ptr((void **)&dm->looptris.array, dm->looptris.array, dm->looptris.array_wip);
+  dm->looptris.array_wip = NULL;
 }
 
 static void ccgDM_calcNormals(DerivedMesh *dm)
 {
-       /* Nothing to do: CCG calculates normals during drawing */
-       dm->dirty &= ~DM_DIRTY_NORMALS;
+  /* Nothing to do: CCG calculates normals during drawing */
+  dm->dirty &= ~DM_DIRTY_NORMALS;
 }
 
 static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
 {
-       ccgdm->dm.getMinMax = ccgDM_getMinMax;
-       ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
-       ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
-       ccgdm->dm.getNumLoops = ccgDM_getNumLoops;
-       /* reuse of ccgDM_getNumTessFaces is intentional here: subsurf polys are just created from tessfaces */
-       ccgdm->dm.getNumPolys = ccgDM_getNumPolys;
-       ccgdm->dm.getNumTessFaces = ccgDM_getNumTessFaces;
-
-       ccgdm->dm.getVert = ccgDM_getFinalVert;
-       ccgdm->dm.getEdge = ccgDM_getFinalEdge;
-       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.copyTessFaceArray = ccgDM_copyFinalFaceArray;
-       ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray;
-       ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray;
-
-       ccgdm->dm.getVertData = ccgDM_get_vert_data;
-       ccgdm->dm.getEdgeData = ccgDM_get_edge_data;
-       ccgdm->dm.getTessFaceData = ccgDM_get_tessface_data;
-       ccgdm->dm.getPolyData = ccgDM_get_poly_data;
-       ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
-       ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
-       ccgdm->dm.getTessFaceDataArray = ccgDM_get_tessface_data_layer;
-       ccgdm->dm.getPolyDataArray = ccgDM_get_poly_data_layer;
-       ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
-       ccgdm->dm.getGridSize = ccgDM_getGridSize;
-       ccgdm->dm.getGridData = ccgDM_getGridData;
-       ccgdm->dm.getGridOffset = ccgDM_getGridOffset;
-       ccgdm->dm.getGridKey = ccgDM_getGridKey;
-       ccgdm->dm.getGridFlagMats = ccgDM_getGridFlagMats;
-       ccgdm->dm.getGridHidden = ccgDM_getGridHidden;
-       ccgdm->dm.getPolyMap = ccgDM_getPolyMap;
-       ccgdm->dm.getPBVH = ccgDM_getPBVH;
-
-       ccgdm->dm.calcNormals = ccgDM_calcNormals;
-       ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals;
-       ccgdm->dm.calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
-       ccgdm->dm.calcLoopTangents = DM_calc_loop_tangents;
-       ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
-       ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri;
-
-       ccgdm->dm.getVertCos = ccgdm_getVertCos;
-       ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
-       ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
-       ccgdm->dm.foreachMappedLoop = ccgDM_foreachMappedLoop;
-       ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
-
-       ccgdm->dm.drawVerts = ccgDM_drawVerts;
-       ccgdm->dm.drawEdges = ccgDM_drawEdges;
-       ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
-       ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
-       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.drawMappedFacesMat = ccgDM_drawMappedFacesMat;
-       ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
-
-       ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
-       ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
-       ccgdm->dm.gpuObjectNew = ccgDM_GPUObjectNew;
-       ccgdm->dm.copy_gpu_data = ccgDM_copy_gpu_data;
-
-       ccgdm->dm.release = ccgDM_release;
-}
-
-static void create_ccgdm_maps(CCGDerivedMesh *ccgdm,
-                              CCGSubSurf *ss)
-{
-       CCGVertIterator vi;
-       CCGEdgeIterator ei;
-       CCGFaceIterator fi;
-       int totvert, totedge, totface;
-
-       totvert = ccgSubSurf_getNumVerts(ss);
-       ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
-       for (ccgSubSurf_initVertIterator(ss, &vi);
-            !ccgVertIterator_isStopped(&vi);
-            ccgVertIterator_next(&vi))
-       {
-               CCGVert *v = ccgVertIterator_getCurrent(&vi);
-
-               ccgdm->vertMap[POINTER_AS_INT(ccgSubSurf_getVertVertHandle(v))].vert = v;
-       }
-
-       totedge = ccgSubSurf_getNumEdges(ss);
-       ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
-       for (ccgSubSurf_initEdgeIterator(ss, &ei);
-            !ccgEdgeIterator_isStopped(&ei);
-            ccgEdgeIterator_next(&ei))
-       {
-               CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
-
-               ccgdm->edgeMap[POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
-       }
-
-       totface = ccgSubSurf_getNumFaces(ss);
-       ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
-       for (ccgSubSurf_initFaceIterator(ss, &fi);
-            !ccgFaceIterator_isStopped(&fi);
-            ccgFaceIterator_next(&fi))
-       {
-               CCGFace *f = ccgFaceIterator_getCurrent(&fi);
-
-               ccgdm->faceMap[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))].face = f;
-       }
+  ccgdm->dm.getMinMax = ccgDM_getMinMax;
+  ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
+  ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
+  ccgdm->dm.getNumLoops = ccgDM_getNumLoops;
+  /* reuse of ccgDM_getNumTessFaces is intentional here:
+   * subsurf polys are just created from tessfaces */
+  ccgdm->dm.getNumPolys = ccgDM_getNumPolys;
+  ccgdm->dm.getNumTessFaces = ccgDM_getNumTessFaces;
+
+  ccgdm->dm.getVert = ccgDM_getFinalVert;
+  ccgdm->dm.getEdge = ccgDM_getFinalEdge;
+  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.copyTessFaceArray = ccgDM_copyFinalFaceArray;
+  ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray;
+  ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray;
+
+  ccgdm->dm.getVertData = ccgDM_get_vert_data;
+  ccgdm->dm.getEdgeData = ccgDM_get_edge_data;
+  ccgdm->dm.getTessFaceData = ccgDM_get_tessface_data;
+  ccgdm->dm.getPolyData = ccgDM_get_poly_data;
+  ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
+  ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
+  ccgdm->dm.getTessFaceDataArray = ccgDM_get_tessface_data_layer;
+  ccgdm->dm.getPolyDataArray = ccgDM_get_poly_data_layer;
+  ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
+  ccgdm->dm.getGridSize = ccgDM_getGridSize;
+  ccgdm->dm.getGridData = ccgDM_getGridData;
+  ccgdm->dm.getGridOffset = ccgDM_getGridOffset;
+  ccgdm->dm.getGridKey = ccgDM_getGridKey;
+  ccgdm->dm.getGridFlagMats = ccgDM_getGridFlagMats;
+  ccgdm->dm.getGridHidden = ccgDM_getGridHidden;
+  ccgdm->dm.getPolyMap = ccgDM_getPolyMap;
+  ccgdm->dm.getPBVH = ccgDM_getPBVH;
+
+  ccgdm->dm.calcNormals = ccgDM_calcNormals;
+  ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals;
+  ccgdm->dm.calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
+  ccgdm->dm.calcLoopTangents = DM_calc_loop_tangents;
+  ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
+  ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri;
+
+  ccgdm->dm.getVertCos = ccgdm_getVertCos;
+  ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
+  ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
+  ccgdm->dm.foreachMappedLoop = ccgDM_foreachMappedLoop;
+  ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
+
+  ccgdm->dm.release = ccgDM_release;
+}
+
+static void create_ccgdm_maps(CCGDerivedMesh *ccgdm, CCGSubSurf *ss)
+{
+  CCGVertIterator vi;
+  CCGEdgeIterator ei;
+  CCGFaceIterator fi;
+  int totvert, totedge, totface;
+
+  totvert = ccgSubSurf_getNumVerts(ss);
+  ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
+  for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi);
+       ccgVertIterator_next(&vi)) {
+    CCGVert *v = ccgVertIterator_getCurrent(&vi);
+
+    ccgdm->vertMap[POINTER_AS_INT(ccgSubSurf_getVertVertHandle(v))].vert = v;
+  }
+
+  totedge = ccgSubSurf_getNumEdges(ss);
+  ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
+  for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei);
+       ccgEdgeIterator_next(&ei)) {
+    CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
+
+    ccgdm->edgeMap[POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
+  }
+
+  totface = ccgSubSurf_getNumFaces(ss);
+  ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
+  for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi);
+       ccgFaceIterator_next(&fi)) {
+    CCGFace *f = ccgFaceIterator_getCurrent(&fi);
+
+    ccgdm->faceMap[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))].face = f;
+  }
 }
 
 /* Fill in all geometry arrays making it possible to access any
@@ -4733,391 +2533,375 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
                                    DerivedMesh *dm,
                                    bool useSubsurfUv)
 {
-       const int totvert = ccgSubSurf_getNumVerts(ss);
-       const int totedge = ccgSubSurf_getNumEdges(ss);
-       const int totface = ccgSubSurf_getNumFaces(ss);
-       int index;
-       int i;
-       int vertNum = 0, edgeNum = 0, faceNum = 0;
-       int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex, *edgeOrigIndex;
-       short *edgeFlags = ccgdm->edgeFlags;
-       DMFlagMat *faceFlags = ccgdm->faceFlags;
-       int *polyidx = NULL;
+  const int totvert = ccgSubSurf_getNumVerts(ss);
+  const int totedge = ccgSubSurf_getNumEdges(ss);
+  const int totface = ccgSubSurf_getNumFaces(ss);
+  int index;
+  int i;
+  int vertNum = 0, edgeNum = 0, faceNum = 0;
+  int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex, *edgeOrigIndex;
+  short *edgeFlags = ccgdm->edgeFlags;
+  DMFlagMat *faceFlags = ccgdm->faceFlags;
+  int *polyidx = NULL;
 #ifndef USE_DYNSIZE
-       int *loopidx = NULL, *vertidx = NULL;
-       BLI_array_declare(loopidx);
-       BLI_array_declare(vertidx);
-#endif
-       int loopindex, loopindex2;
-       int edgeSize;
-       int gridSize;
-       int gridFaces, gridCuts;
-       int gridSideEdges;
-       int gridInternalEdges;
-       WeightTable wtable = {NULL};
-       MEdge *medge = NULL;
-       MPoly *mpoly = NULL;
-       bool has_edge_cd;
-
-       edgeSize = ccgSubSurf_getEdgeSize(ss);
-       gridSize = ccgSubSurf_getGridSize(ss);
-       gridFaces = gridSize - 1;
-       gridCuts = gridSize - 2;
-       /*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
-       gridSideEdges = gridSize - 1;
-       gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
-
-       /* mvert = dm->getVertArray(dm); */ /* UNUSED */
-       medge = dm->getEdgeArray(dm);
-       /* mface = dm->getTessFaceArray(dm); */ /* UNUSED */
-
-       mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
-       base_polyOrigIndex = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
-
-       vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
-       edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);
-
-       faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX);
-       polyOrigIndex = DM_get_poly_data_layer(&ccgdm->dm, CD_ORIGINDEX);
-
-       has_edge_cd = ((ccgdm->dm.edgeData.totlayer - (edgeOrigIndex ? 1 : 0)) != 0);
-
-#if 0
-       /* this is not in trunk, can gives problems because colors initialize
-        * as black, just don't do it!, it works fine - campbell */
-       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);
+  int *loopidx = NULL, *vertidx = NULL;
+  BLI_array_declare(loopidx);
+  BLI_array_declare(vertidx);
 #endif
-
-       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 = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
-               int g2_wid = gridCuts + 2;
-               float *w, *w2;
-               int s, x, y;
+  int loopindex, loopindex2;
+  int edgeSize;
+  int gridSize;
+  int gridFaces, gridCuts;
+  int gridSideEdges;
+  int gridInternalEdges;
+  WeightTable wtable = {NULL};
+  MEdge *medge = NULL;
+  MPoly *mpoly = NULL;
+  bool has_edge_cd;
+
+  edgeSize = ccgSubSurf_getEdgeSize(ss);
+  gridSize = ccgSubSurf_getGridSize(ss);
+  gridFaces = gridSize - 1;
+  gridCuts = gridSize - 2;
+  /*gridInternalVerts = gridSideVerts * gridSideVerts; - as yet, unused */
+  gridSideEdges = gridSize - 1;
+  gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
+
+  /* mvert = dm->getVertArray(dm); */ /* UNUSED */
+  medge = dm->getEdgeArray(dm);
+  /* mface = dm->getTessFaceArray(dm); */ /* UNUSED */
+
+  mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
+  base_polyOrigIndex = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
+
+  vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
+  edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);
+
+  faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX);
+  polyOrigIndex = DM_get_poly_data_layer(&ccgdm->dm, CD_ORIGINDEX);
+
+  has_edge_cd = ((ccgdm->dm.edgeData.totlayer - (edgeOrigIndex ? 1 : 0)) != 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 = POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f));
+    int g2_wid = gridCuts + 2;
+    float *w, *w2;
+    int s, x, y;
 #ifdef USE_DYNSIZE
-               int loopidx[numVerts], vertidx[numVerts];
+    int loopidx[numVerts], vertidx[numVerts];
 #endif
-               w = get_ss_weights(&wtable, gridCuts, numVerts);
+    w = get_ss_weights(&wtable, gridCuts, numVerts);
 
-               ccgdm->faceMap[index].startVert = vertNum;
-               ccgdm->faceMap[index].startEdge = edgeNum;
-               ccgdm->faceMap[index].startFace = faceNum;
+    ccgdm->faceMap[index].startVert = vertNum;
+    ccgdm->faceMap[index].startEdge = edgeNum;
+    ccgdm->faceMap[index].startFace = faceNum;
 
-               faceFlags->flag = mpoly ?  mpoly[origIndex].flag : 0;
-               faceFlags->mat_nr = mpoly ? mpoly[origIndex].mat_nr : 0;
-               faceFlags++;
+    faceFlags->flag = mpoly ? mpoly[origIndex].flag : 0;
+    faceFlags->mat_nr = mpoly ? mpoly[origIndex].mat_nr : 0;
+    faceFlags++;
 
-               /* set the face base vert */
-               *((int *)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
+    /* set the face base vert */
+    *((int *)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
 
 #ifndef USE_DYNSIZE
-               BLI_array_clear(loopidx);
-               BLI_array_grow_items(loopidx, numVerts);
+    BLI_array_clear(loopidx);
+    BLI_array_grow_items(loopidx, numVerts);
 #endif
-               for (s = 0; s < numVerts; s++) {
-                       loopidx[s] = loopindex++;
-               }
+    for (s = 0; s < numVerts; s++) {
+      loopidx[s] = loopindex++;
+    }
 
 #ifndef USE_DYNSIZE
-               BLI_array_clear(vertidx);
-               BLI_array_grow_items(vertidx, numVerts);
+    BLI_array_clear(vertidx);
+    BLI_array_grow_items(vertidx, numVerts);
 #endif
-               for (s = 0; s < numVerts; s++) {
-                       CCGVert *v = ccgSubSurf_getFaceVert(f, s);
-                       vertidx[s] = POINTER_AS_INT(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++;
-               }
-
-               vertNum++;
-
-               /*interpolate per-vert data*/
-               for (s = 0; s < numVerts; s++) {
-                       for (x = 1; x < gridFaces; x++) {
-                               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++;
-                       }
-               }
-
-               /*interpolate per-vert data*/
-               for (s = 0; s < numVerts; s++) {
-                       for (y = 1; y < gridFaces; y++) {
-                               for (x = 1; x < gridFaces; x++) {
-                                       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++;
-                               }
-                       }
-               }
-
-               if (edgeOrigIndex) {
-                       for (i = 0; i < numFinalEdges; ++i) {
-                               edgeOrigIndex[edgeNum + i] = 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);
-
-                                       /*set original index data*/
-                                       if (faceOrigIndex) {
-                                               /* reference the index in 'polyOrigIndex' */
-                                               *faceOrigIndex = faceNum;
-                                               faceOrigIndex++;
-                                       }
-                                       if (polyOrigIndex) {
-                                               *polyOrigIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
-                                               polyOrigIndex++;
-                                       }
-
-                                       ccgdm->reverseFaceMap[faceNum] = index;
-
-                                       /* This is a simple one to one mapping, here... */
-                                       if (polyidx) {
-                                               polyidx[faceNum] = faceNum;
-                                       }
-
-                                       faceNum++;
-                               }
-                       }
-               }
-
-               edgeNum += numFinalEdges;
-       }
-
-       for (index = 0; index < totedge; ++index) {
-     &nbs