Blender V2.61 - r43446

subsurf_ccg.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2005 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <stdio.h>
00036 #include <math.h>
00037 #include <float.h>
00038 
00039 #include "MEM_guardedalloc.h"
00040 
00041 #include "DNA_mesh_types.h"
00042 #include "DNA_meshdata_types.h"
00043 #include "DNA_modifier_types.h"
00044 #include "DNA_object_types.h"
00045 #include "DNA_scene_types.h"
00046 
00047 #include "BLI_blenlib.h"
00048 #include "BLI_edgehash.h"
00049 #include "BLI_math.h"
00050 #include "BLI_memarena.h"
00051 #include "BLI_pbvh.h"
00052 #include "BLI_utildefines.h"
00053 
00054 #include "BKE_cdderivedmesh.h"
00055 #include "BKE_global.h"
00056 #include "BKE_mesh.h"
00057 #include "BKE_modifier.h"
00058 #include "BKE_paint.h"
00059 #include "BKE_scene.h"
00060 #include "BKE_subsurf.h"
00061 
00062 #include "GL/glew.h"
00063 
00064 #include "GPU_draw.h"
00065 #include "GPU_extensions.h"
00066 #include "GPU_material.h"
00067 
00068 #include "CCGSubSurf.h"
00069 
00070 extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */
00071 
00072 static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v);
00073 static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e);
00074 static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f);
00075 static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
00076 
00078 
00079 static void *arena_alloc(CCGAllocatorHDL a, int numBytes) {
00080     return BLI_memarena_alloc(a, numBytes);
00081 }
00082 static void *arena_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) {
00083     void *p2 = BLI_memarena_alloc(a, newSize);
00084     if (ptr) {
00085         memcpy(p2, ptr, oldSize);
00086     }
00087     return p2;
00088 }
00089 static void arena_free(CCGAllocatorHDL UNUSED(a), void *UNUSED(ptr)) {
00090 }
00091 static void arena_release(CCGAllocatorHDL a) {
00092     BLI_memarena_free(a);
00093 }
00094 
00095 static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, int useAging, int useArena, int UNUSED(useFlatSubdiv)) {
00096     CCGMeshIFC ifc;
00097     CCGSubSurf *ccgSS;
00098 
00099         /* subdivLevels==0 is not allowed */
00100     subdivLevels = MAX2(subdivLevels, 1);
00101 
00102     if (prevSS) {
00103         int oldUseAging;
00104 
00105         useAging = !!useAging;
00106         ccgSubSurf_getUseAgeCounts(prevSS, &oldUseAging, NULL, NULL, NULL);
00107 
00108         if (oldUseAging!=useAging) {
00109             ccgSubSurf_free(prevSS);
00110         } else {
00111             ccgSubSurf_setSubdivisionLevels(prevSS, subdivLevels);
00112 
00113             return prevSS;
00114         }
00115     }
00116 
00117     if (useAging) {
00118         ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 12;
00119     } else {
00120         ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 8;
00121     }
00122     ifc.vertDataSize = sizeof(DMGridData);
00123 
00124     if (useArena) {
00125         CCGAllocatorIFC allocatorIFC;
00126         CCGAllocatorHDL allocator = BLI_memarena_new((1<<16), "subsurf arena");
00127 
00128         allocatorIFC.alloc = arena_alloc;
00129         allocatorIFC.realloc = arena_realloc;
00130         allocatorIFC.free = arena_free;
00131         allocatorIFC.release = arena_release;
00132 
00133         ccgSS = ccgSubSurf_new(&ifc, subdivLevels, &allocatorIFC, allocator);
00134     } else {
00135         ccgSS = ccgSubSurf_new(&ifc, subdivLevels, NULL, NULL);
00136     }
00137 
00138     if (useAging) {
00139         ccgSubSurf_setUseAgeCounts(ccgSS, 1, 8, 8, 8);
00140     }
00141 
00142     ccgSubSurf_setCalcVertexNormals(ccgSS, 1, offsetof(DMGridData, no));
00143 
00144     return ccgSS;
00145 }
00146 
00147 static int getEdgeIndex(CCGSubSurf *ss, CCGEdge *e, int x, int edgeSize) {
00148     CCGVert *v0 = ccgSubSurf_getEdgeVert0(e);
00149     CCGVert *v1 = ccgSubSurf_getEdgeVert1(e);
00150     int v0idx = *((int*) ccgSubSurf_getVertUserData(ss, v0));
00151     int v1idx = *((int*) ccgSubSurf_getVertUserData(ss, v1));
00152     int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
00153 
00154     if (x==0) {
00155         return v0idx;
00156     } else if (x==edgeSize-1) {
00157         return v1idx;
00158     } else {
00159         return edgeBase + x-1;
00160     }
00161 }
00162 static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize) {
00163     int faceBase = *((int*) ccgSubSurf_getFaceUserData(ss, f));
00164     int numVerts = ccgSubSurf_getFaceNumVerts(f);
00165 
00166     if (x==gridSize-1 && y==gridSize-1) {
00167         CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
00168         return *((int*) ccgSubSurf_getVertUserData(ss, v));
00169     } else if (x==gridSize-1) {
00170         CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
00171         CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, S);
00172         int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
00173         if (v==ccgSubSurf_getEdgeVert0(e)) {
00174             return edgeBase + (gridSize-1-y)-1;
00175         } else {
00176             return edgeBase + (edgeSize-2-1)-((gridSize-1-y)-1);
00177         }
00178     } else if (y==gridSize-1) {
00179         CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
00180         CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, (S+numVerts-1)%numVerts);
00181         int edgeBase = *((int*) ccgSubSurf_getEdgeUserData(ss, e));
00182         if (v==ccgSubSurf_getEdgeVert0(e)) {
00183             return edgeBase + (gridSize-1-x)-1;
00184         } else {
00185             return edgeBase + (edgeSize-2-1)-((gridSize-1-x)-1);
00186         }
00187     } else if (x==0 && y==0) {
00188         return faceBase;
00189     } else if (x==0) {
00190         S = (S+numVerts-1)%numVerts;
00191         return faceBase + 1 + (gridSize-2)*S + (y-1);
00192     } else if (y==0) {
00193         return faceBase + 1 + (gridSize-2)*S + (x-1);
00194     } else {
00195         return faceBase + 1 + (gridSize-2)*numVerts + S*(gridSize-2)*(gridSize-2) + (y-1)*(gridSize-2) + (x-1);
00196     }
00197 }
00198 
00199 static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGVertHDL *fverts) {
00200     unsigned int *fv = &mf->v1;
00201     UvMapVert *v, *nv;
00202     int j, nverts= mf->v4? 4: 3;
00203 
00204     for (j=0; j<nverts; j++, fv++) {
00205         for (nv=v=get_uv_map_vert(vmap, *fv); v; v=v->next) {
00206             if (v->separate)
00207                 nv= v;
00208             if (v->f == fi)
00209                 break;
00210         }
00211 
00212         fverts[j]= SET_INT_IN_POINTER(nv->f*4 + nv->tfindex);
00213     }
00214 }
00215 
00216 static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MTFace *tface) {
00217     MFace *mface = dm->getFaceArray(dm);
00218     MVert *mvert = dm->getVertArray(dm);
00219     int totvert = dm->getNumVerts(dm);
00220     int totface = dm->getNumFaces(dm);
00221     int i, j, seam;
00222     UvMapVert *v;
00223     UvVertMap *vmap;
00224     float limit[2];
00225     CCGVertHDL fverts[4];
00226     EdgeHash *ehash;
00227     float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss);
00228     float uv[3]= {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */
00229 
00230     limit[0]= limit[1]= STD_UV_CONNECT_LIMIT;
00231     vmap= make_uv_vert_map(mface, tface, totface, totvert, 0, limit);
00232     if (!vmap)
00233         return 0;
00234     
00235     ccgSubSurf_initFullSync(ss);
00236 
00237     /* create vertices */
00238     for (i=0; i<totvert; i++) {
00239         if (!get_uv_map_vert(vmap, i))
00240             continue;
00241 
00242         for (v=get_uv_map_vert(vmap, i)->next; v; v=v->next)
00243             if (v->separate)
00244                 break;
00245 
00246         seam = (v != NULL) || ((mvert+i)->flag & ME_VERT_MERGED);
00247 
00248         for (v=get_uv_map_vert(vmap, i); v; v=v->next) {
00249             if (v->separate) {
00250                 CCGVert *ssv;
00251                 CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex);
00252 
00253                 copy_v2_v2(uv, (tface+v->f)->uv[v->tfindex]);
00254 
00255                 ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
00256             }
00257         }
00258     }
00259 
00260     /* create edges */
00261     ehash = BLI_edgehash_new();
00262 
00263     for (i=0; i<totface; i++) {
00264         MFace *mf = &((MFace*) mface)[i];
00265         int nverts= mf->v4? 4: 3;
00266         CCGFace *origf= ccgSubSurf_getFace(origss, SET_INT_IN_POINTER(i));
00267         unsigned int *fv = &mf->v1;
00268 
00269         get_face_uv_map_vert(vmap, mf, i, fverts);
00270 
00271         for (j=0; j<nverts; j++) {
00272             int v0 = GET_INT_FROM_POINTER(fverts[j]);
00273             int v1 = GET_INT_FROM_POINTER(fverts[(j+1)%nverts]);
00274             MVert *mv0 = mvert + *(fv+j);
00275             MVert *mv1 = mvert + *(fv+((j+1)%nverts));
00276 
00277             if (!BLI_edgehash_haskey(ehash, v0, v1)) {
00278                 CCGEdge *e, *orige= ccgSubSurf_getFaceEdge(origss, origf, j);
00279                 CCGEdgeHDL ehdl= SET_INT_IN_POINTER(i*4 + j);
00280                 float crease;
00281 
00282                 if ((mv0->flag&mv1->flag) & ME_VERT_MERGED)
00283                     crease = creaseFactor;
00284                 else
00285                     crease = ccgSubSurf_getEdgeCrease(orige);
00286 
00287                 ccgSubSurf_syncEdge(ss, ehdl, fverts[j], fverts[(j+1)%nverts], crease, &e);
00288                 BLI_edgehash_insert(ehash, v0, v1, NULL);
00289             }
00290         }
00291     }
00292 
00293     BLI_edgehash_free(ehash, NULL);
00294 
00295     /* create faces */
00296     for (i=0; i<totface; i++) {
00297         MFace *mf = &((MFace*) mface)[i];
00298         int nverts= mf->v4? 4: 3;
00299         CCGFace *f;
00300 
00301         get_face_uv_map_vert(vmap, mf, i, fverts);
00302         ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), nverts, fverts, &f);
00303     }
00304 
00305     free_uv_vert_map(vmap);
00306     ccgSubSurf_processSync(ss);
00307 
00308     return 1;
00309 }
00310 
00311 static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, int n)
00312 {
00313     CCGSubSurf *uvss;
00314     CCGFace **faceMap;
00315     MTFace *tf;
00316     CCGFaceIterator *fi;
00317     int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
00318     MTFace *dmtface = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, n);
00319     MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n);
00320 
00321     if(!dmtface || !tface)
00322         return;
00323 
00324     /* create a CCGSubSurf from uv's */
00325     uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 0, 1, 0);
00326 
00327     if(!ss_sync_from_uv(uvss, ss, dm, dmtface)) {
00328         ccgSubSurf_free(uvss);
00329         return;
00330     }
00331 
00332     /* get some info from CCGSubSurf */
00333     totface = ccgSubSurf_getNumFaces(uvss);
00334     /* edgeSize = ccgSubSurf_getEdgeSize(uvss); */ /*UNUSED*/
00335     gridSize = ccgSubSurf_getGridSize(uvss);
00336     gridFaces = gridSize - 1;
00337 
00338     /* make a map from original faces to CCGFaces */
00339     faceMap = MEM_mallocN(totface*sizeof(*faceMap), "facemapuv");
00340 
00341     fi = ccgSubSurf_getFaceIterator(uvss);
00342     for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
00343         CCGFace *f = ccgFaceIterator_getCurrent(fi);
00344         faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(uvss, f))] = f;
00345     }
00346     ccgFaceIterator_free(fi);
00347 
00348     /* load coordinates from uvss into tface */
00349     tf= tface;
00350 
00351     for(index = 0; index < totface; index++) {
00352         CCGFace *f = faceMap[index];
00353         int numVerts = ccgSubSurf_getFaceNumVerts(f);
00354 
00355         for (S=0; S<numVerts; S++) {
00356             DMGridData *faceGridData= ccgSubSurf_getFaceGridDataArray(uvss, f, S);
00357 
00358             for(y = 0; y < gridFaces; y++) {
00359                 for(x = 0; x < gridFaces; x++) {
00360                     copy_v2_v2(tf->uv[0], faceGridData[(y + 0)*gridSize + x + 0].co);
00361                     copy_v2_v2(tf->uv[1], faceGridData[(y + 1)*gridSize + x + 0].co);
00362                     copy_v2_v2(tf->uv[2], faceGridData[(y + 1)*gridSize + x + 1].co);
00363                     copy_v2_v2(tf->uv[3], faceGridData[(y + 0)*gridSize + x + 1].co);
00364 
00365                     tf++;
00366                 }
00367             }
00368         }
00369     }
00370 
00371     ccgSubSurf_free(uvss);
00372     MEM_freeN(faceMap);
00373 }
00374 
00375 /* face weighting */
00376 static void calc_ss_weights(int gridFaces,
00377                             FaceVertWeight **qweight, FaceVertWeight **tweight)
00378 {
00379     FaceVertWeight *qw, *tw;
00380     int x, y, j;
00381     int numWeights = gridFaces * gridFaces;
00382 
00383     *tweight = MEM_mallocN(sizeof(**tweight) * numWeights, "ssTriWeight");
00384     *qweight = MEM_mallocN(sizeof(**qweight) * numWeights, "ssQuadWeight");
00385 
00386     qw = *qweight;
00387     tw = *tweight;
00388 
00389     for (y = 0; y < gridFaces; y++) {
00390         for (x = 0; x < gridFaces; x++) {
00391             for (j = 0; j < 4; j++) {
00392                 int fx = x + (j == 2 || j == 3);
00393                 int fy = y + (j == 1 || j == 2);
00394                 float x_v = (float) fx / gridFaces;
00395                 float y_v = (float) fy / gridFaces;
00396                 float tx_v = (1.0f - x_v), ty_v = (1.0f - y_v);
00397                 float center = (1.0f / 3.0f) * tx_v * ty_v;
00398 
00399                 (*tw)[j][0] = center + 0.5f * tx_v * y_v;
00400                 (*tw)[j][2] = center + 0.5f * x_v * ty_v;
00401                 (*tw)[j][1] = 1.0f - (*tw)[j][0] - (*tw)[j][2];
00402                 (*tw)[j][3] = 0.0f;
00403 
00404                 tx_v *= 0.5f;
00405                 ty_v *= 0.5f;
00406 
00407                 (*qw)[j][3] = tx_v * ty_v;
00408                 (*qw)[j][0] = (*qw)[j][3] + tx_v * y_v;
00409                 (*qw)[j][2] = (*qw)[j][3] + x_v * ty_v;
00410                 (*qw)[j][1] = 1.0f - (*qw)[j][0] - (*qw)[j][2] - (*qw)[j][3];
00411 
00412             }
00413             tw++;
00414             qw++;
00415         }
00416     }
00417 }
00418 
00419 static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
00420                                      float (*vertexCos)[3], int useFlatSubdiv)
00421 {
00422     float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
00423     CCGVertHDL fVerts[4];
00424     int totvert = dm->getNumVerts(dm);
00425     int totedge = dm->getNumEdges(dm);
00426     int totface = dm->getNumFaces(dm);
00427     int i;
00428     int *index;
00429     MVert *mvert = dm->getVertArray(dm);
00430     MEdge *medge = dm->getEdgeArray(dm);
00431     MFace *mface = dm->getFaceArray(dm);
00432     MVert *mv;
00433     MEdge *me;
00434     MFace *mf;
00435 
00436     ccgSubSurf_initFullSync(ss);
00437 
00438     mv = mvert;
00439     index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
00440     for(i = 0; i < totvert; i++, mv++) {
00441         CCGVert *v;
00442 
00443         if(vertexCos) {
00444             ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), vertexCos[i], 0, &v);
00445         } else {
00446             ccgSubSurf_syncVert(ss, SET_INT_IN_POINTER(i), mv->co, 0, &v);
00447         }
00448 
00449         ((int*)ccgSubSurf_getVertUserData(ss, v))[1] = (index)? *index++: i;
00450     }
00451 
00452     me = medge;
00453     index = (int *)dm->getEdgeDataArray(dm, CD_ORIGINDEX);
00454     for(i = 0; i < totedge; i++, me++) {
00455         CCGEdge *e;
00456         float crease;
00457 
00458         crease = useFlatSubdiv ? creaseFactor :
00459                                  me->crease * creaseFactor / 255.0f;
00460 
00461         ccgSubSurf_syncEdge(ss, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(me->v1),
00462                             SET_INT_IN_POINTER(me->v2), crease, &e);
00463 
00464         ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = (index)? *index++: i;
00465     }
00466 
00467     mf = mface;
00468     index = (int *)dm->getFaceDataArray(dm, CD_ORIGINDEX);
00469     for (i = 0; i < totface; i++, mf++) {
00470         CCGFace *f;
00471 
00472         fVerts[0] = SET_INT_IN_POINTER(mf->v1);
00473         fVerts[1] = SET_INT_IN_POINTER(mf->v2);
00474         fVerts[2] = SET_INT_IN_POINTER(mf->v3);
00475         fVerts[3] = SET_INT_IN_POINTER(mf->v4);
00476 
00477         /* this is very bad, means mesh is internally inconsistent.
00478          * it is not really possible to continue without modifying
00479          * other parts of code significantly to handle missing faces.
00480          * since this really shouldn't even be possible we just bail.*/
00481         if(ccgSubSurf_syncFace(ss, SET_INT_IN_POINTER(i), fVerts[3] ? 4 : 3,
00482                                fVerts, &f) == eCCGError_InvalidValue) {
00483             static int hasGivenError = 0;
00484 
00485             if(!hasGivenError) {
00486                 //XXX error("Unrecoverable error in SubSurf calculation,"
00487                 //      " mesh is inconsistent.");
00488 
00489                 hasGivenError = 1;
00490             }
00491 
00492             return;
00493         }
00494 
00495         ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = (index)? *index++: i;
00496     }
00497 
00498     ccgSubSurf_processSync(ss);
00499 }
00500 
00501 /***/
00502 
00503 static int ccgDM_getVertMapIndex(CCGSubSurf *ss, CCGVert *v) {
00504     return ((int*) ccgSubSurf_getVertUserData(ss, v))[1];
00505 }
00506 
00507 static int ccgDM_getEdgeMapIndex(CCGSubSurf *ss, CCGEdge *e) {
00508     return ((int*) ccgSubSurf_getEdgeUserData(ss, e))[1];
00509 }
00510 
00511 static int ccgDM_getFaceMapIndex(CCGSubSurf *ss, CCGFace *f) {
00512     return ((int*) ccgSubSurf_getFaceUserData(ss, f))[1];
00513 }
00514 
00515 static void ccgDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) {
00516     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00517     CCGSubSurf *ss = ccgdm->ss;
00518     CCGVertIterator *vi = ccgSubSurf_getVertIterator(ss);
00519     CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
00520     CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
00521     int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
00522     int gridSize = ccgSubSurf_getGridSize(ss);
00523 
00524     if (!ccgSubSurf_getNumVerts(ss))
00525         min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
00526 
00527     for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
00528         CCGVert *v = ccgVertIterator_getCurrent(vi);
00529         float *co = ccgSubSurf_getVertData(ss, v);
00530 
00531         DO_MINMAX(co, min_r, max_r);
00532     }
00533 
00534     for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
00535         CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
00536         DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
00537 
00538         for (i=0; i<edgeSize; i++)
00539             DO_MINMAX(edgeData[i].co, min_r, max_r);
00540     }
00541 
00542     for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
00543         CCGFace *f = ccgFaceIterator_getCurrent(fi);
00544         int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
00545 
00546         for (S=0; S<numVerts; S++) {
00547             DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
00548 
00549             for (y=0; y<gridSize; y++)
00550                 for (x=0; x<gridSize; x++)
00551                     DO_MINMAX(faceGridData[y*gridSize + x].co, min_r, max_r);
00552         }
00553     }
00554 
00555     ccgFaceIterator_free(fi);
00556     ccgEdgeIterator_free(ei);
00557     ccgVertIterator_free(vi);
00558 }
00559 static int ccgDM_getNumVerts(DerivedMesh *dm) {
00560     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00561 
00562     return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
00563 }
00564 static int ccgDM_getNumEdges(DerivedMesh *dm) {
00565     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00566 
00567     return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
00568 }
00569 static int ccgDM_getNumFaces(DerivedMesh *dm) {
00570     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00571 
00572     return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
00573 }
00574 
00575 static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
00576 {
00577     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00578     CCGSubSurf *ss = ccgdm->ss;
00579     DMGridData *vd;
00580     int i;
00581 
00582     memset(mv, 0, sizeof(*mv));
00583 
00584     if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) {
00585         /* this vert comes from face data */
00586         int lastface = ccgSubSurf_getNumFaces(ss) - 1;
00587         CCGFace *f;
00588         int x, y, grid, numVerts;
00589         int offset;
00590         int gridSize = ccgSubSurf_getGridSize(ss);
00591         int gridSideVerts;
00592         int gridInternalVerts;
00593         int gridSideEnd;
00594         int gridInternalEnd;
00595 
00596         i = 0;
00597         while(i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert)
00598             ++i;
00599 
00600         f = ccgdm->faceMap[i].face;
00601         numVerts = ccgSubSurf_getFaceNumVerts(f);
00602 
00603         gridSideVerts = gridSize - 2;
00604         gridInternalVerts = gridSideVerts * gridSideVerts;
00605 
00606         gridSideEnd = 1 + numVerts * gridSideVerts;
00607         gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
00608 
00609         offset = vertNum - ccgdm->faceMap[i].startVert;
00610         if(offset < 1) {
00611             vd = ccgSubSurf_getFaceCenterData(f);
00612             copy_v3_v3(mv->co, vd->co);
00613             normal_float_to_short_v3(mv->no, vd->no);
00614         } else if(offset < gridSideEnd) {
00615             offset -= 1;
00616             grid = offset / gridSideVerts;
00617             x = offset % gridSideVerts + 1;
00618             vd = ccgSubSurf_getFaceGridEdgeData(ss, f, grid, x);
00619             copy_v3_v3(mv->co, vd->co);
00620             normal_float_to_short_v3(mv->no, vd->no);
00621         } else if(offset < gridInternalEnd) {
00622             offset -= gridSideEnd;
00623             grid = offset / gridInternalVerts;
00624             offset %= gridInternalVerts;
00625             y = offset / gridSideVerts + 1;
00626             x = offset % gridSideVerts + 1;
00627             vd = ccgSubSurf_getFaceGridData(ss, f, grid, x, y);
00628             copy_v3_v3(mv->co, vd->co);
00629             normal_float_to_short_v3(mv->no, vd->no);
00630         }
00631     } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) {
00632         /* this vert comes from edge data */
00633         CCGEdge *e;
00634         int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
00635         int x;
00636 
00637         i = 0;
00638         while(i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert)
00639             ++i;
00640 
00641         e = ccgdm->edgeMap[i].edge;
00642 
00643         x = vertNum - ccgdm->edgeMap[i].startVert + 1;
00644         vd = ccgSubSurf_getEdgeData(ss, e, x);
00645         copy_v3_v3(mv->co, vd->co);
00646         normal_float_to_short_v3(mv->no, vd->no);
00647     } else {
00648         /* this vert comes from vert data */
00649         CCGVert *v;
00650         i = vertNum - ccgdm->vertMap[0].startVert;
00651 
00652         v = ccgdm->vertMap[i].vert;
00653         vd = ccgSubSurf_getVertData(ss, v);
00654         copy_v3_v3(mv->co, vd->co);
00655         normal_float_to_short_v3(mv->no, vd->no);
00656     }
00657 }
00658 
00659 static void ccgDM_getFinalVertCo(DerivedMesh *dm, int vertNum, float co_r[3])
00660 {
00661     MVert mvert;
00662 
00663     ccgDM_getFinalVert(dm, vertNum, &mvert);
00664     copy_v3_v3(co_r, mvert.co);
00665 }
00666 
00667 static void ccgDM_getFinalVertNo(DerivedMesh *dm, int vertNum, float no_r[3])
00668 {
00669     MVert mvert;
00670 
00671     ccgDM_getFinalVert(dm, vertNum, &mvert);
00672     normal_short_to_float_v3(no_r, mvert.no);
00673 }
00674 
00675 static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
00676 {
00677     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00678     CCGSubSurf *ss = ccgdm->ss;
00679     int i;
00680 
00681     memset(med, 0, sizeof(*med));
00682 
00683     if(edgeNum < ccgdm->edgeMap[0].startEdge) {
00684         /* this edge comes from face data */
00685         int lastface = ccgSubSurf_getNumFaces(ss) - 1;
00686         CCGFace *f;
00687         int x, y, grid /*, numVerts*/;
00688         int offset;
00689         int gridSize = ccgSubSurf_getGridSize(ss);
00690         int edgeSize = ccgSubSurf_getEdgeSize(ss);
00691         int gridSideEdges;
00692         int gridInternalEdges;
00693 
00694         i = 0;
00695         while(i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge)
00696             ++i;
00697 
00698         f = ccgdm->faceMap[i].face;
00699         /* numVerts = ccgSubSurf_getFaceNumVerts(f); */ /*UNUSED*/
00700 
00701         gridSideEdges = gridSize - 1;
00702         gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; 
00703 
00704         offset = edgeNum - ccgdm->faceMap[i].startEdge;
00705         grid = offset / (gridSideEdges + gridInternalEdges);
00706         offset %= (gridSideEdges + gridInternalEdges);
00707 
00708         if(offset < gridSideEdges) {
00709             x = offset;
00710             med->v1 = getFaceIndex(ss, f, grid, x, 0, edgeSize, gridSize);
00711             med->v2 = getFaceIndex(ss, f, grid, x+1, 0, edgeSize, gridSize);
00712         } else {
00713             offset -= gridSideEdges;
00714             x = (offset / 2) / gridSideEdges + 1;
00715             y = (offset / 2) % gridSideEdges;
00716             if(offset % 2 == 0) {
00717                 med->v1 = getFaceIndex(ss, f, grid, x, y, edgeSize, gridSize);
00718                 med->v2 = getFaceIndex(ss, f, grid, x, y+1, edgeSize, gridSize);
00719             } else {
00720                 med->v1 = getFaceIndex(ss, f, grid, y, x, edgeSize, gridSize);
00721                 med->v2 = getFaceIndex(ss, f, grid, y+1, x, edgeSize, gridSize);
00722             }
00723         }
00724     } else {
00725         /* this vert comes from edge data */
00726         CCGEdge *e;
00727         int edgeSize = ccgSubSurf_getEdgeSize(ss);
00728         int x;
00729         short *edgeFlag;
00730         unsigned int flags = 0;
00731 
00732         i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
00733 
00734         e = ccgdm->edgeMap[i].edge;
00735 
00736         if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
00737 
00738         x = edgeNum - ccgdm->edgeMap[i].startEdge;
00739 
00740         med->v1 = getEdgeIndex(ss, e, x, edgeSize);
00741         med->v2 = getEdgeIndex(ss, e, x+1, edgeSize);
00742 
00743         edgeFlag = (ccgdm->edgeFlags)? &ccgdm->edgeFlags[i]: NULL;
00744         if(edgeFlag)
00745             flags |= (*edgeFlag & (ME_SEAM | ME_SHARP))
00746                      | ME_EDGEDRAW | ME_EDGERENDER;
00747         else
00748             flags |= ME_EDGEDRAW | ME_EDGERENDER;
00749 
00750         med->flag = flags;
00751     }
00752 }
00753 
00754 static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
00755 {
00756     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00757     CCGSubSurf *ss = ccgdm->ss;
00758     int gridSize = ccgSubSurf_getGridSize(ss);
00759     int edgeSize = ccgSubSurf_getEdgeSize(ss);
00760     int gridSideEdges = gridSize - 1;
00761     int gridFaces = gridSideEdges * gridSideEdges;
00762     int i;
00763     CCGFace *f;
00764     /*int numVerts;*/
00765     int offset;
00766     int grid;
00767     int x, y;
00768     int lastface = ccgSubSurf_getNumFaces(ss) - 1;
00769     char *faceFlags = ccgdm->faceFlags;
00770 
00771     memset(mf, 0, sizeof(*mf));
00772 
00773     i = 0;
00774     while(i < lastface && faceNum >= ccgdm->faceMap[i + 1].startFace)
00775         ++i;
00776 
00777     f = ccgdm->faceMap[i].face;
00778     /*numVerts = ccgSubSurf_getFaceNumVerts(f);*/ /*UNUSED*/
00779 
00780     offset = faceNum - ccgdm->faceMap[i].startFace;
00781     grid = offset / gridFaces;
00782     offset %= gridFaces;
00783     y = offset / gridSideEdges;
00784     x = offset % gridSideEdges;
00785 
00786     mf->v1 = getFaceIndex(ss, f, grid, x+0, y+0, edgeSize, gridSize);
00787     mf->v2 = getFaceIndex(ss, f, grid, x+0, y+1, edgeSize, gridSize);
00788     mf->v3 = getFaceIndex(ss, f, grid, x+1, y+1, edgeSize, gridSize);
00789     mf->v4 = getFaceIndex(ss, f, grid, x+1, y+0, edgeSize, gridSize);
00790 
00791     if(faceFlags) {
00792         mf->flag = faceFlags[i*2];
00793         mf->mat_nr = faceFlags[i*2+1];
00794     }
00795     else mf->flag = ME_SMOOTH;
00796 }
00797 
00798 static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert)
00799 {
00800     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00801     CCGSubSurf *ss = ccgdm->ss;
00802     DMGridData *vd;
00803     int index;
00804     int totvert, totedge, totface;
00805     int gridSize = ccgSubSurf_getGridSize(ss);
00806     int edgeSize = ccgSubSurf_getEdgeSize(ss);
00807     int i = 0;
00808 
00809     totface = ccgSubSurf_getNumFaces(ss);
00810     for(index = 0; index < totface; index++) {
00811         CCGFace *f = ccgdm->faceMap[index].face;
00812         int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
00813 
00814         vd= ccgSubSurf_getFaceCenterData(f);
00815         copy_v3_v3(mvert[i].co, vd->co);
00816         normal_float_to_short_v3(mvert[i].no, vd->no);
00817         i++;
00818         
00819         for(S = 0; S < numVerts; S++) {
00820             for(x = 1; x < gridSize - 1; x++, i++) {
00821                 vd= ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
00822                 copy_v3_v3(mvert[i].co, vd->co);
00823                 normal_float_to_short_v3(mvert[i].no, vd->no);
00824             }
00825         }
00826 
00827         for(S = 0; S < numVerts; S++) {
00828             for(y = 1; y < gridSize - 1; y++) {
00829                 for(x = 1; x < gridSize - 1; x++, i++) {
00830                     vd= ccgSubSurf_getFaceGridData(ss, f, S, x, y);
00831                     copy_v3_v3(mvert[i].co, vd->co);
00832                     normal_float_to_short_v3(mvert[i].no, vd->no);
00833                 }
00834             }
00835         }
00836     }
00837 
00838     totedge = ccgSubSurf_getNumEdges(ss);
00839     for(index = 0; index < totedge; index++) {
00840         CCGEdge *e = ccgdm->edgeMap[index].edge;
00841         int x;
00842 
00843         for(x = 1; x < edgeSize - 1; x++, i++) {
00844             vd= ccgSubSurf_getEdgeData(ss, e, x);
00845             copy_v3_v3(mvert[i].co, vd->co);
00846             /* This gives errors with -debug-fpe
00847              * the normals dont seem to be unit length.
00848              * this is most likely caused by edges with no
00849              * faces which are now zerod out, see comment in:
00850              * ccgSubSurf__calcVertNormals(), - campbell */
00851             normal_float_to_short_v3(mvert[i].no, vd->no);
00852         }
00853     }
00854 
00855     totvert = ccgSubSurf_getNumVerts(ss);
00856     for(index = 0; index < totvert; index++) {
00857         CCGVert *v = ccgdm->vertMap[index].vert;
00858 
00859         vd= ccgSubSurf_getVertData(ss, v);
00860         copy_v3_v3(mvert[i].co, vd->co);
00861         normal_float_to_short_v3(mvert[i].no, vd->no);
00862         i++;
00863     }
00864 }
00865 
00866 static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
00867 {
00868     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00869     CCGSubSurf *ss = ccgdm->ss;
00870     int index;
00871     int totedge, totface;
00872     int gridSize = ccgSubSurf_getGridSize(ss);
00873     int edgeSize = ccgSubSurf_getEdgeSize(ss);
00874     int i = 0;
00875     short *edgeFlags = ccgdm->edgeFlags;
00876 
00877     totface = ccgSubSurf_getNumFaces(ss);
00878     for(index = 0; index < totface; index++) {
00879         CCGFace *f = ccgdm->faceMap[index].face;
00880         int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
00881 
00882         for(S = 0; S < numVerts; S++) {
00883             for(x = 0; x < gridSize - 1; x++) {
00884                 MEdge *med = &medge[i];
00885 
00886                 if(ccgdm->drawInteriorEdges)
00887                     med->flag = ME_EDGEDRAW | ME_EDGERENDER;
00888                 med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize);
00889                 med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize);
00890                 i++;
00891             }
00892 
00893             for(x = 1; x < gridSize - 1; x++) {
00894                 for(y = 0; y < gridSize - 1; y++) {
00895                     MEdge *med;
00896 
00897                     med = &medge[i];
00898                     if(ccgdm->drawInteriorEdges)
00899                         med->flag = ME_EDGEDRAW | ME_EDGERENDER;
00900                     med->v1 = getFaceIndex(ss, f, S, x, y,
00901                                            edgeSize, gridSize);
00902                     med->v2 = getFaceIndex(ss, f, S, x, y + 1,
00903                                            edgeSize, gridSize);
00904                     i++;
00905 
00906                     med = &medge[i];
00907                     if(ccgdm->drawInteriorEdges)
00908                         med->flag = ME_EDGEDRAW | ME_EDGERENDER;
00909                     med->v1 = getFaceIndex(ss, f, S, y, x,
00910                                            edgeSize, gridSize);
00911                     med->v2 = getFaceIndex(ss, f, S, y + 1, x,
00912                                            edgeSize, gridSize);
00913                     i++;
00914                 }
00915             }
00916         }
00917     }
00918 
00919     totedge = ccgSubSurf_getNumEdges(ss);
00920     for(index = 0; index < totedge; index++) {
00921         CCGEdge *e = ccgdm->edgeMap[index].edge;
00922         unsigned int flags = 0;
00923         int x;
00924         int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
00925 
00926         if(!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE;
00927 
00928         if(edgeFlags) {
00929             if(edgeIdx != -1) {
00930                 flags |= (edgeFlags[index] & (ME_SEAM | ME_SHARP))
00931                          | ME_EDGEDRAW | ME_EDGERENDER;
00932             }
00933         } else {
00934             flags |= ME_EDGEDRAW | ME_EDGERENDER;
00935         }
00936 
00937         for(x = 0; x < edgeSize - 1; x++) {
00938             MEdge *med = &medge[i];
00939             med->v1 = getEdgeIndex(ss, e, x, edgeSize);
00940             med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize);
00941             med->flag = flags;
00942             i++;
00943         }
00944     }
00945 }
00946 
00947 static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
00948 {
00949     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00950     CCGSubSurf *ss = ccgdm->ss;
00951     int index;
00952     int totface;
00953     int gridSize = ccgSubSurf_getGridSize(ss);
00954     int edgeSize = ccgSubSurf_getEdgeSize(ss);
00955     int i = 0;
00956     char *faceFlags = ccgdm->faceFlags;
00957 
00958     totface = ccgSubSurf_getNumFaces(ss);
00959     for(index = 0; index < totface; index++) {
00960         CCGFace *f = ccgdm->faceMap[index].face;
00961         int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
00962         /* keep types in sync with MFace, avoid many conversions */
00963         char flag = (faceFlags)? faceFlags[index*2]: ME_SMOOTH;
00964         short mat_nr = (faceFlags)? faceFlags[index*2+1]: 0;
00965 
00966         for(S = 0; S < numVerts; S++) {
00967             for(y = 0; y < gridSize - 1; y++) {
00968                 for(x = 0; x < gridSize - 1; x++) {
00969                     MFace *mf = &mface[i];
00970                     mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
00971                                           edgeSize, gridSize);
00972                     mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
00973                                           edgeSize, gridSize);
00974                     mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
00975                                           edgeSize, gridSize);
00976                     mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
00977                                           edgeSize, gridSize);
00978                     mf->mat_nr = mat_nr;
00979                     mf->flag = flag;
00980 
00981                     i++;
00982                 }
00983             }
00984         }
00985     }
00986 }
00987 
00988 static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
00989     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
00990     CCGSubSurf *ss = ccgdm->ss;
00991     int edgeSize = ccgSubSurf_getEdgeSize(ss);
00992     int gridSize = ccgSubSurf_getGridSize(ss);
00993     int i;
00994     CCGVertIterator *vi;
00995     CCGEdgeIterator *ei;
00996     CCGFaceIterator *fi;
00997     CCGFace **faceMap2;
00998     CCGEdge **edgeMap2;
00999     CCGVert **vertMap2;
01000     int index, totvert, totedge, totface;
01001     
01002     totvert = ccgSubSurf_getNumVerts(ss);
01003     vertMap2 = MEM_mallocN(totvert*sizeof(*vertMap2), "vertmap");
01004     vi = ccgSubSurf_getVertIterator(ss);
01005     for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
01006         CCGVert *v = ccgVertIterator_getCurrent(vi);
01007 
01008         vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v;
01009     }
01010     ccgVertIterator_free(vi);
01011 
01012     totedge = ccgSubSurf_getNumEdges(ss);
01013     edgeMap2 = MEM_mallocN(totedge*sizeof(*edgeMap2), "edgemap");
01014     ei = ccgSubSurf_getEdgeIterator(ss);
01015     for (i=0; !ccgEdgeIterator_isStopped(ei); i++,ccgEdgeIterator_next(ei)) {
01016         CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
01017 
01018         edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
01019     }
01020 
01021     totface = ccgSubSurf_getNumFaces(ss);
01022     faceMap2 = MEM_mallocN(totface*sizeof(*faceMap2), "facemap");
01023     fi = ccgSubSurf_getFaceIterator(ss);
01024     for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
01025         CCGFace *f = ccgFaceIterator_getCurrent(fi);
01026 
01027         faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))] = f;
01028     }
01029     ccgFaceIterator_free(fi);
01030 
01031     i = 0;
01032     for (index=0; index<totface; index++) {
01033         CCGFace *f = faceMap2[index];
01034         int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
01035 
01036         copy_v3_v3(cos[i++], ccgSubSurf_getFaceCenterData(f));
01037         
01038         for (S=0; S<numVerts; S++) {
01039             for (x=1; x<gridSize-1; x++) {
01040                 copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
01041             }
01042         }
01043 
01044         for (S=0; S<numVerts; S++) {
01045             for (y=1; y<gridSize-1; y++) {
01046                 for (x=1; x<gridSize-1; x++) {
01047                     copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridData(ss, f, S, x, y));
01048                 }
01049             }
01050         }
01051     }
01052 
01053     for (index=0; index<totedge; index++) {
01054         CCGEdge *e= edgeMap2[index];
01055         int x;
01056 
01057         for (x=1; x<edgeSize-1; x++) {
01058             copy_v3_v3(cos[i++], ccgSubSurf_getEdgeData(ss, e, x));
01059         }
01060     }
01061 
01062     for (index=0; index<totvert; index++) {
01063         CCGVert *v = vertMap2[index];
01064         copy_v3_v3(cos[i++], ccgSubSurf_getVertData(ss, v));
01065     }
01066 
01067     MEM_freeN(vertMap2);
01068     MEM_freeN(edgeMap2);
01069     MEM_freeN(faceMap2);
01070 }
01071 static void ccgDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData) {
01072     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01073     CCGVertIterator *vi = ccgSubSurf_getVertIterator(ccgdm->ss);
01074 
01075     for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
01076         CCGVert *v = ccgVertIterator_getCurrent(vi);
01077         DMGridData *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
01078         int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
01079 
01080         if (index!=-1)
01081             func(userData, index, vd->co, vd->no, NULL);
01082     }
01083 
01084     ccgVertIterator_free(vi);
01085 }
01086 static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData) {
01087     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01088     CCGSubSurf *ss = ccgdm->ss;
01089     CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
01090     int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
01091 
01092     for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
01093         CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
01094         DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
01095         int index = ccgDM_getEdgeMapIndex(ss, e);
01096 
01097         if (index!=-1) {
01098             for (i=0; i<edgeSize-1; i++)
01099                 func(userData, index, edgeData[i].co, edgeData[i+1].co);
01100         }
01101     }
01102 
01103     ccgEdgeIterator_free(ei);
01104 }
01105 
01106 static void ccgDM_drawVerts(DerivedMesh *dm) {
01107     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01108     CCGSubSurf *ss = ccgdm->ss;
01109     int edgeSize = ccgSubSurf_getEdgeSize(ss);
01110     int gridSize = ccgSubSurf_getGridSize(ss);
01111     CCGVertIterator *vi;
01112     CCGEdgeIterator *ei;
01113     CCGFaceIterator *fi;
01114 
01115     glBegin(GL_POINTS);
01116     vi = ccgSubSurf_getVertIterator(ss);
01117     for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
01118         CCGVert *v = ccgVertIterator_getCurrent(vi);
01119         glVertex3fv(ccgSubSurf_getVertData(ss, v));
01120     }
01121     ccgVertIterator_free(vi);
01122 
01123     ei = ccgSubSurf_getEdgeIterator(ss);
01124     for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
01125         CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
01126         int x;
01127 
01128         for (x=1; x<edgeSize-1; x++)
01129             glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x));
01130     }
01131     ccgEdgeIterator_free(ei);
01132 
01133     fi = ccgSubSurf_getFaceIterator(ss);
01134     for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
01135         CCGFace *f = ccgFaceIterator_getCurrent(fi);
01136         int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
01137 
01138         glVertex3fv(ccgSubSurf_getFaceCenterData(f));
01139         for (S=0; S<numVerts; S++)
01140             for (x=1; x<gridSize-1; x++)
01141                 glVertex3fv(ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
01142         for (S=0; S<numVerts; S++)
01143             for (y=1; y<gridSize-1; y++)
01144                 for (x=1; x<gridSize-1; x++)
01145                     glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y));
01146     }
01147     ccgFaceIterator_free(fi);
01148     glEnd();
01149 }
01150 
01151 static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm)
01152 {
01153     if(ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) {
01154         CCGFace **faces;
01155         int totface;
01156 
01157         BLI_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void***)&faces, &totface);
01158         if(totface) {
01159             ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface);
01160             ccgSubSurf_updateNormals(ccgdm->ss, faces, totface);
01161             MEM_freeN(faces);
01162         }
01163     }
01164 }
01165 
01166 static void ccgDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int UNUSED(drawAllEdges)) {
01167     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01168     CCGSubSurf *ss = ccgdm->ss;
01169     int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss);
01170     int totedge = ccgSubSurf_getNumEdges(ss);
01171     int gridSize = ccgSubSurf_getGridSize(ss);
01172     int useAging;
01173 
01174     ccgdm_pbvh_update(ccgdm);
01175 
01176     ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
01177 
01178     for (j=0; j< totedge; j++) {
01179         CCGEdge *e = ccgdm->edgeMap[j].edge;
01180         DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
01181 
01182         if (!drawLooseEdges && !ccgSubSurf_getEdgeNumFaces(e))
01183             continue;
01184 
01185         if(ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW))
01186             continue;
01187 
01188         if (useAging && !(G.f&G_BACKBUFSEL)) {
01189             int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
01190             glColor3ub(0, ageCol>0?ageCol:0, 0);
01191         }
01192 
01193         glBegin(GL_LINE_STRIP);
01194         for (i=0; i<edgeSize-1; i++) {
01195             glVertex3fv(edgeData[i].co);
01196             glVertex3fv(edgeData[i+1].co);
01197         }
01198         glEnd();
01199     }
01200 
01201     if (useAging && !(G.f&G_BACKBUFSEL)) {
01202         glColor3ub(0, 0, 0);
01203     }
01204 
01205     if (ccgdm->drawInteriorEdges) {
01206         int totface = ccgSubSurf_getNumFaces(ss);
01207 
01208         for(j = 0; j < totface; j++) {
01209             CCGFace *f = ccgdm->faceMap[j].face;
01210             int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
01211 
01212             for (S=0; S<numVerts; S++) {
01213                 DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
01214 
01215                 glBegin(GL_LINE_STRIP);
01216                 for (x=0; x<gridSize; x++)
01217                     glVertex3fv(faceGridData[x].co);
01218                 glEnd();
01219                 for (y=1; y<gridSize-1; y++) {
01220                     glBegin(GL_LINE_STRIP);
01221                     for (x=0; x<gridSize; x++)
01222                         glVertex3fv(faceGridData[y*gridSize + x].co);
01223                     glEnd();
01224                 }
01225                 for (x=1; x<gridSize-1; x++) {
01226                     glBegin(GL_LINE_STRIP);
01227                     for (y=0; y<gridSize; y++)
01228                         glVertex3fv(faceGridData[y*gridSize + x].co);
01229                     glEnd();
01230                 }
01231             }
01232         }
01233     }
01234 }
01235 static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
01236     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01237     CCGSubSurf *ss = ccgdm->ss;
01238     int totedge = ccgSubSurf_getNumEdges(ss);
01239     int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss);
01240 
01241     for (j=0; j< totedge; j++) {
01242         CCGEdge *e = ccgdm->edgeMap[j].edge;
01243         DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
01244 
01245         if (!ccgSubSurf_getEdgeNumFaces(e)) {
01246             glBegin(GL_LINE_STRIP);
01247             for (i=0; i<edgeSize-1; i++) {
01248                 glVertex3fv(edgeData[i].co);
01249                 glVertex3fv(edgeData[i+1].co);
01250             }
01251             glEnd();
01252         }
01253     }
01254 }
01255 
01256 static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
01257 {
01258     float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
01259     float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
01260     float no[3];
01261 
01262     no[0] = b_dY*a_cZ - b_dZ*a_cY;
01263     no[1] = b_dZ*a_cX - b_dX*a_cZ;
01264     no[2] = b_dX*a_cY - b_dY*a_cX;
01265 
01266     /* don't normalize, GL_NORMALIZE is enabled */
01267     glNormal3fv(no);
01268 }
01269 
01270     /* Only used by non-editmesh types */
01271 static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int fast, int (*setMaterial)(int, void *attribs)) {
01272     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01273     CCGSubSurf *ss = ccgdm->ss;
01274     int gridSize = ccgSubSurf_getGridSize(ss);
01275     char *faceFlags = ccgdm->faceFlags;
01276     int step = (fast)? gridSize-1: 1;
01277     int i, totface = ccgSubSurf_getNumFaces(ss);
01278     int drawcurrent = 0, matnr = -1, shademodel = -1;
01279 
01280     ccgdm_pbvh_update(ccgdm);
01281 
01282     if(ccgdm->pbvh && ccgdm->multires.mmd && !fast) {
01283         if(dm->numFaceData) {
01284             /* should be per face */
01285             if(!setMaterial(faceFlags[1]+1, NULL))
01286                 return;
01287 
01288             glShadeModel((faceFlags[0] & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
01289             BLI_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL, (faceFlags[0] & ME_SMOOTH));
01290             glShadeModel(GL_FLAT);
01291         }
01292 
01293         return;
01294     }
01295 
01296     for(i = 0; i < totface; i++) {
01297         CCGFace *f = ccgdm->faceMap[i].face;
01298         int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
01299         int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
01300         int new_matnr, new_shademodel;
01301 
01302         if(faceFlags) {
01303             new_shademodel = (faceFlags[index*2] & ME_SMOOTH)? GL_SMOOTH: GL_FLAT;
01304             new_matnr= faceFlags[index*2 + 1];
01305         }
01306         else {
01307             new_shademodel = GL_SMOOTH;
01308             new_matnr= 0;
01309         }
01310         
01311         if(shademodel != new_shademodel || matnr != new_matnr) {
01312             matnr= new_matnr;
01313             shademodel= new_shademodel;
01314 
01315             drawcurrent= setMaterial(matnr+1, NULL);
01316 
01317             glShadeModel(shademodel);
01318         }
01319 
01320         if(!drawcurrent)
01321             continue;
01322 
01323         for (S=0; S<numVerts; S++) {
01324             DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
01325 
01326             if (shademodel == GL_SMOOTH) {
01327                 for (y=0; y<gridSize-1; y+=step) {
01328                     glBegin(GL_QUAD_STRIP);
01329                     for (x=0; x<gridSize; x+=step) {
01330                         DMGridData *a = &faceGridData[(y+0)*gridSize + x];
01331                         DMGridData *b = &faceGridData[(y+step)*gridSize + x];
01332 
01333                         glNormal3fv(a->no);
01334                         glVertex3fv(a->co);
01335                         glNormal3fv(b->no);
01336                         glVertex3fv(b->co);
01337                     }
01338                     glEnd();
01339                 }
01340             } else {
01341                 glBegin(GL_QUADS);
01342                 for (y=0; y<gridSize-1; y+=step) {
01343                     for (x=0; x<gridSize-1; x+=step) {
01344                         float *a = faceGridData[(y+0)*gridSize + x].co;
01345                         float *b = faceGridData[(y+0)*gridSize + x + step].co;
01346                         float *c = faceGridData[(y+step)*gridSize + x + step].co;
01347                         float *d = faceGridData[(y+step)*gridSize + x].co;
01348 
01349                         ccgDM_glNormalFast(a, b, c, d);
01350 
01351                         glVertex3fv(d);
01352                         glVertex3fv(c);
01353                         glVertex3fv(b);
01354                         glVertex3fv(a);
01355                     }
01356                 }
01357                 glEnd();
01358             }
01359         }
01360     }
01361 }
01362 
01363     /* Only used by non-editmesh types */
01364 static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
01365             int (*setMaterial)(int, void *attribs),
01366             int (*setDrawOptions)(void *userData, int index),
01367             void *userData)
01368 {
01369     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01370     CCGSubSurf *ss = ccgdm->ss;
01371     GPUVertexAttribs gattribs;
01372     DMVertexAttribs attribs= {{{NULL}}};
01373     /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
01374     int gridSize = ccgSubSurf_getGridSize(ss);
01375     int gridFaces = gridSize - 1;
01376     int edgeSize = ccgSubSurf_getEdgeSize(ss);
01377     char *faceFlags = ccgdm->faceFlags;
01378     int a, b, i, doDraw, numVerts, matnr, new_matnr, totface;
01379 
01380     ccgdm_pbvh_update(ccgdm);
01381 
01382     doDraw = 0;
01383     matnr = -1;
01384 
01385 #define PASSATTRIB(dx, dy, vert) {                                              \
01386     if(attribs.totorco) {                                                       \
01387         index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize);         \
01388         glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
01389     }                                                                           \
01390     for(b = 0; b < attribs.tottface; b++) {                                     \
01391         MTFace *tf = &attribs.tface[b].array[a];                                \
01392         glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);           \
01393     }                                                                           \
01394     for(b = 0; b < attribs.totmcol; b++) {                                      \
01395         MCol *cp = &attribs.mcol[b].array[a*4 + vert];                          \
01396         GLubyte col[4];                                                         \
01397         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;             \
01398         glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                    \
01399     }                                                                           \
01400     if(attribs.tottang) {                                                       \
01401         float *tang = attribs.tang.array[a*4 + vert];                           \
01402         glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                       \
01403     }                                                                           \
01404 }
01405 
01406     totface = ccgSubSurf_getNumFaces(ss);
01407     for(a = 0, i = 0; i < totface; i++) {
01408         CCGFace *f = ccgdm->faceMap[i].face;
01409         int S, x, y, drawSmooth;
01410         int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
01411         int origIndex = ccgDM_getFaceMapIndex(ss, f);
01412         
01413         numVerts = ccgSubSurf_getFaceNumVerts(f);
01414 
01415         if(faceFlags) {
01416             drawSmooth = (faceFlags[index*2] & ME_SMOOTH);
01417             new_matnr= faceFlags[index*2 + 1] + 1;
01418         }
01419         else {
01420             drawSmooth = 1;
01421             new_matnr= 1;
01422         }
01423 
01424         if(new_matnr != matnr) {
01425             doDraw = setMaterial(matnr = new_matnr, &gattribs);
01426             if(doDraw)
01427                 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
01428         }
01429 
01430         if(!doDraw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) && !setDrawOptions(userData, origIndex))) {
01431             a += gridFaces*gridFaces*numVerts;
01432             continue;
01433         }
01434 
01435         glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
01436         for (S=0; S<numVerts; S++) {
01437             DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
01438             DMGridData *vda, *vdb;
01439 
01440             if (drawSmooth) {
01441                 for (y=0; y<gridFaces; y++) {
01442                     glBegin(GL_QUAD_STRIP);
01443                     for (x=0; x<gridFaces; x++) {
01444                         vda = &faceGridData[(y+0)*gridSize + x];
01445                         vdb = &faceGridData[(y+1)*gridSize + x];
01446                         
01447                         PASSATTRIB(0, 0, 0);
01448                         glNormal3fv(vda->no);
01449                         glVertex3fv(vda->co);
01450 
01451                         PASSATTRIB(0, 1, 1);
01452                         glNormal3fv(vdb->no);
01453                         glVertex3fv(vdb->co);
01454 
01455                         if(x != gridFaces-1)
01456                             a++;
01457                     }
01458 
01459                     vda = &faceGridData[(y+0)*gridSize + x];
01460                     vdb = &faceGridData[(y+1)*gridSize + x];
01461 
01462                     PASSATTRIB(0, 0, 3);
01463                     glNormal3fv(vda->no);
01464                     glVertex3fv(vda->co);
01465 
01466                     PASSATTRIB(0, 1, 2);
01467                     glNormal3fv(vdb->no);
01468                     glVertex3fv(vdb->co);
01469 
01470                     glEnd();
01471 
01472                     a++;
01473                 }
01474             } else {
01475                 glBegin(GL_QUADS);
01476                 for (y=0; y<gridFaces; y++) {
01477                     for (x=0; x<gridFaces; x++) {
01478                         float *aco = faceGridData[(y+0)*gridSize + x].co;
01479                         float *bco = faceGridData[(y+0)*gridSize + x + 1].co;
01480                         float *cco = faceGridData[(y+1)*gridSize + x + 1].co;
01481                         float *dco = faceGridData[(y+1)*gridSize + x].co;
01482 
01483                         ccgDM_glNormalFast(aco, bco, cco, dco);
01484 
01485                         PASSATTRIB(0, 1, 1);
01486                         glVertex3fv(dco);
01487                         PASSATTRIB(1, 1, 2);
01488                         glVertex3fv(cco);
01489                         PASSATTRIB(1, 0, 3);
01490                         glVertex3fv(bco);
01491                         PASSATTRIB(0, 0, 0);
01492                         glVertex3fv(aco);
01493                         
01494                         a++;
01495                     }
01496                 }
01497                 glEnd();
01498             }
01499         }
01500     }
01501 
01502 #undef PASSATTRIB
01503 }
01504 
01505 static void ccgDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) {
01506     dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
01507 }
01508 
01509     /* Only used by non-editmesh types */
01510 static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, void (*setMaterial)(void *userData, int, void *attribs), int (*setFace)(void *userData, int index), void *userData) {
01511     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01512     CCGSubSurf *ss = ccgdm->ss;
01513     GPUVertexAttribs gattribs;
01514     DMVertexAttribs attribs= {{{NULL}}};
01515     int gridSize = ccgSubSurf_getGridSize(ss);
01516     int gridFaces = gridSize - 1;
01517     int edgeSize = ccgSubSurf_getEdgeSize(ss);
01518     char *faceFlags = ccgdm->faceFlags;
01519     int a, b, i, numVerts, matnr, new_matnr, totface;
01520 
01521     ccgdm_pbvh_update(ccgdm);
01522 
01523     matnr = -1;
01524 
01525 #define PASSATTRIB(dx, dy, vert) {                                              \
01526     if(attribs.totorco) {                                                       \
01527         index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize);         \
01528         if(attribs.orco.glTexco)                                                \
01529             glTexCoord3fv(attribs.orco.array[index]);                           \
01530         else                                                                    \
01531             glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]);  \
01532     }                                                                           \
01533     for(b = 0; b < attribs.tottface; b++) {                                     \
01534         MTFace *tf = &attribs.tface[b].array[a];                                \
01535         if(attribs.tface[b].glTexco)                                            \
01536             glTexCoord2fv(tf->uv[vert]);                                        \
01537         else                                                                    \
01538             glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]);       \
01539     }                                                                           \
01540     for(b = 0; b < attribs.totmcol; b++) {                                      \
01541         MCol *cp = &attribs.mcol[b].array[a*4 + vert];                          \
01542         GLubyte col[4];                                                         \
01543         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;             \
01544         glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col);                    \
01545     }                                                                           \
01546     if(attribs.tottang) {                                                       \
01547         float *tang = attribs.tang.array[a*4 + vert];                           \
01548         glVertexAttrib4fvARB(attribs.tang.glIndex, tang);                       \
01549     }                                                                           \
01550 }
01551 
01552     totface = ccgSubSurf_getNumFaces(ss);
01553     for(a = 0, i = 0; i < totface; i++) {
01554         CCGFace *f = ccgdm->faceMap[i].face;
01555         int S, x, y, drawSmooth;
01556         int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
01557         int origIndex = ccgDM_getFaceMapIndex(ss, f);
01558         
01559         numVerts = ccgSubSurf_getFaceNumVerts(f);
01560 
01561         /* get flags */
01562         if(faceFlags) {
01563             drawSmooth = (faceFlags[index*2] & ME_SMOOTH);
01564             new_matnr= faceFlags[index*2 + 1] + 1;
01565         }
01566         else {
01567             drawSmooth = 1;
01568             new_matnr= 1;
01569         }
01570 
01571         /* material */
01572         if(new_matnr != matnr) {
01573             setMaterial(userData, matnr = new_matnr, &gattribs);
01574             DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
01575         }
01576 
01577         /* face hiding */
01578         if((setFace && (origIndex != ORIGINDEX_NONE) && !setFace(userData, origIndex))) {
01579             a += gridFaces*gridFaces*numVerts;
01580             continue;
01581         }
01582 
01583         /* draw face*/
01584         glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT);
01585         for (S=0; S<numVerts; S++) {
01586             DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
01587             DMGridData *vda, *vdb;
01588 
01589             if (drawSmooth) {
01590                 for (y=0; y<gridFaces; y++) {
01591                     glBegin(GL_QUAD_STRIP);
01592                     for (x=0; x<gridFaces; x++) {
01593                         vda = &faceGridData[(y+0)*gridSize + x];
01594                         vdb = &faceGridData[(y+1)*gridSize + x];
01595                         
01596                         PASSATTRIB(0, 0, 0);
01597                         glNormal3fv(vda->no);
01598                         glVertex3fv(vda->co);
01599 
01600                         PASSATTRIB(0, 1, 1);
01601                         glNormal3fv(vdb->no);
01602                         glVertex3fv(vdb->co);
01603 
01604                         if(x != gridFaces-1)
01605                             a++;
01606                     }
01607 
01608                     vda = &faceGridData[(y+0)*gridSize + x];
01609                     vdb = &faceGridData[(y+1)*gridSize + x];
01610 
01611                     PASSATTRIB(0, 0, 3);
01612                     glNormal3fv(vda->no);
01613                     glVertex3fv(vda->co);
01614 
01615                     PASSATTRIB(0, 1, 2);
01616                     glNormal3fv(vdb->no);
01617                     glVertex3fv(vdb->co);
01618 
01619                     glEnd();
01620 
01621                     a++;
01622                 }
01623             } else {
01624                 glBegin(GL_QUADS);
01625                 for (y=0; y<gridFaces; y++) {
01626                     for (x=0; x<gridFaces; x++) {
01627                         float *aco = faceGridData[(y+0)*gridSize + x].co;
01628                         float *bco = faceGridData[(y+0)*gridSize + x + 1].co;
01629                         float *cco = faceGridData[(y+1)*gridSize + x + 1].co;
01630                         float *dco = faceGridData[(y+1)*gridSize + x].co;
01631 
01632                         ccgDM_glNormalFast(aco, bco, cco, dco);
01633 
01634                         PASSATTRIB(0, 1, 1);
01635                         glVertex3fv(dco);
01636                         PASSATTRIB(1, 1, 2);
01637                         glVertex3fv(cco);
01638                         PASSATTRIB(1, 0, 3);
01639                         glVertex3fv(bco);
01640                         PASSATTRIB(0, 0, 0);
01641                         glVertex3fv(aco);
01642                         
01643                         a++;
01644                     }
01645                 }
01646                 glEnd();
01647             }
01648         }
01649     }
01650 
01651 #undef PASSATTRIB
01652 }
01653 
01654 
01655 static void ccgDM_drawFacesColored(DerivedMesh *dm, int UNUSED(useTwoSided), unsigned char *col1, unsigned char *col2) {
01656     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01657     CCGSubSurf *ss = ccgdm->ss;
01658     int gridSize = ccgSubSurf_getGridSize(ss);
01659     unsigned char *cp1, *cp2;
01660     int useTwoSide=1, i, totface;
01661 
01662     ccgdm_pbvh_update(ccgdm);
01663 
01664     cp1= col1;
01665     if(col2) {
01666         cp2= col2;
01667     } else {
01668         cp2= NULL;
01669         useTwoSide= 0;
01670     }
01671 
01672     glShadeModel(GL_SMOOTH);
01673 
01674     if(col2) {
01675         glEnable(GL_CULL_FACE);
01676     }
01677 
01678     glBegin(GL_QUADS);
01679     totface = ccgSubSurf_getNumFaces(ss);
01680     for(i = 0; i < totface; i++) {
01681         CCGFace *f = ccgdm->faceMap[i].face;
01682         int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
01683 
01684         for (S=0; S<numVerts; S++) {
01685             DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
01686             for (y=0; y<gridSize-1; y++) {
01687                 for (x=0; x<gridSize-1; x++) {
01688                     float *a = faceGridData[(y+0)*gridSize + x].co;
01689                     float *b = faceGridData[(y+0)*gridSize + x + 1].co;
01690                     float *c = faceGridData[(y+1)*gridSize + x + 1].co;
01691                     float *d = faceGridData[(y+1)*gridSize + x].co;
01692 
01693                     glColor3ub(cp1[3], cp1[2], cp1[1]);
01694                     glVertex3fv(d);
01695                     glColor3ub(cp1[7], cp1[6], cp1[5]);
01696                     glVertex3fv(c);
01697                     glColor3ub(cp1[11], cp1[10], cp1[9]);
01698                     glVertex3fv(b);
01699                     glColor3ub(cp1[15], cp1[14], cp1[13]);
01700                     glVertex3fv(a);
01701 
01702                     if (useTwoSide) {
01703                         glColor3ub(cp2[15], cp2[14], cp2[13]);
01704                         glVertex3fv(a);
01705                         glColor3ub(cp2[11], cp2[10], cp2[9]);
01706                         glVertex3fv(b);
01707                         glColor3ub(cp2[7], cp2[6], cp2[5]);
01708                         glVertex3fv(c);
01709                         glColor3ub(cp2[3], cp2[2], cp2[1]);
01710                         glVertex3fv(d);
01711                     }
01712 
01713                     if (cp2) cp2+=16;
01714                     cp1+=16;
01715                 }
01716             }
01717         }
01718     }
01719     glEnd();
01720 }
01721 
01722 static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
01723     int (*drawParams)(MTFace *tface, int has_mcol, int matnr),
01724     int (*drawParamsMapped)(void *userData, int index),
01725     int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
01726     void *userData) 
01727 {
01728     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01729     CCGSubSurf *ss = ccgdm->ss;
01730     MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
01731     MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
01732     char *faceFlags = ccgdm->faceFlags;
01733     int i, totface, flag, gridSize = ccgSubSurf_getGridSize(ss);
01734     int gridFaces = gridSize - 1;
01735 
01736     (void) compareDrawOptions;
01737 
01738     ccgdm_pbvh_update(ccgdm);
01739 
01740     if(!mcol)
01741         mcol = dm->getFaceDataArray(dm, CD_MCOL);
01742 
01743     if(!mcol)
01744         mcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
01745 
01746     totface = ccgSubSurf_getNumFaces(ss);
01747     for(i = 0; i < totface; i++) {
01748         CCGFace *f = ccgdm->faceMap[i].face;
01749         int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
01750         int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
01751         int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
01752         unsigned char *cp= NULL;
01753         int mat_nr;
01754 
01755         if(faceFlags) {
01756             drawSmooth = (faceFlags[origIndex*2] & ME_SMOOTH);
01757             mat_nr= faceFlags[origIndex*2 + 1];
01758         }
01759         else {
01760             drawSmooth = 1;
01761             mat_nr= 0;
01762         }
01763 
01764         if(drawParams)
01765             flag = drawParams(tf, (mcol != NULL), mat_nr);
01766         else if (index != ORIGINDEX_NONE)
01767             flag= (drawParamsMapped)? drawParamsMapped(userData, index): 1;
01768         else
01769             flag= GPU_enable_material(mat_nr, NULL) ? 1:0;
01770 
01771 
01772         if (flag == 0) { /* flag 0 == the face is hidden or invisible */
01773             if(tf) tf += gridFaces*gridFaces*numVerts;
01774             if(mcol) mcol += gridFaces*gridFaces*numVerts*4;
01775             continue;
01776         }
01777 
01778         /* flag 1 == use vertex colors */
01779         if(mcol) {
01780             if(flag==1) cp= (unsigned char*)mcol;
01781             mcol += gridFaces*gridFaces*numVerts*4;
01782         }
01783 
01784         for (S=0; S<numVerts; S++) {
01785             DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
01786             DMGridData *a, *b;
01787 
01788             if (drawSmooth) {
01789                 glShadeModel(GL_SMOOTH);
01790                 for (y=0; y<gridFaces; y++) {
01791                     glBegin(GL_QUAD_STRIP);
01792                     for (x=0; x<gridFaces; x++) {
01793                         a = &faceGridData[(y+0)*gridSize + x];
01794                         b = &faceGridData[(y+1)*gridSize + x];
01795 
01796                         if(tf) glTexCoord2fv(tf->uv[0]);
01797                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
01798                         glNormal3fv(a->no);
01799                         glVertex3fv(a->co);
01800 
01801                         if(tf) glTexCoord2fv(tf->uv[1]);
01802                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
01803                         glNormal3fv(b->no);
01804                         glVertex3fv(b->co);
01805                         
01806                         if(x != gridFaces-1) {
01807                             if(tf) tf++;
01808                             if(cp) cp += 16;
01809                         }
01810                     }
01811 
01812                     a = &faceGridData[(y+0)*gridSize + x];
01813                     b = &faceGridData[(y+1)*gridSize + x];
01814 
01815                     if(tf) glTexCoord2fv(tf->uv[3]);
01816                     if(cp) glColor3ub(cp[15], cp[14], cp[13]);
01817                     glNormal3fv(a->no);
01818                     glVertex3fv(a->co);
01819 
01820                     if(tf) glTexCoord2fv(tf->uv[2]);
01821                     if(cp) glColor3ub(cp[11], cp[10], cp[9]);
01822                     glNormal3fv(b->no);
01823                     glVertex3fv(b->co);
01824 
01825                     if(tf) tf++;
01826                     if(cp) cp += 16;
01827 
01828                     glEnd();
01829                 }
01830             } else {
01831                 glShadeModel(GL_FLAT);
01832                 glBegin(GL_QUADS);
01833                 for (y=0; y<gridFaces; y++) {
01834                     for (x=0; x<gridFaces; x++) {
01835                         float *a_co = faceGridData[(y+0)*gridSize + x].co;
01836                         float *b_co = faceGridData[(y+0)*gridSize + x + 1].co;
01837                         float *c_co = faceGridData[(y+1)*gridSize + x + 1].co;
01838                         float *d_co = faceGridData[(y+1)*gridSize + x].co;
01839 
01840                         ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
01841 
01842                         if(tf) glTexCoord2fv(tf->uv[1]);
01843                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
01844                         glVertex3fv(d_co);
01845 
01846                         if(tf) glTexCoord2fv(tf->uv[2]);
01847                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
01848                         glVertex3fv(c_co);
01849 
01850                         if(tf) glTexCoord2fv(tf->uv[3]);
01851                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
01852                         glVertex3fv(b_co);
01853 
01854                         if(tf) glTexCoord2fv(tf->uv[0]);
01855                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
01856                         glVertex3fv(a_co);
01857 
01858                         if(tf) tf++;
01859                         if(cp) cp += 16;
01860                     }
01861                 }
01862                 glEnd();
01863             }
01864         }
01865     }
01866 }
01867 
01868 static void ccgDM_drawFacesTex(DerivedMesh *dm,
01869                int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr),
01870                int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
01871                void *userData)
01872 {
01873     ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
01874 }
01875 
01876 static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
01877     int (*setDrawOptions)(void *userData, int index),
01878     int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
01879     void *userData)
01880 {
01881     ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
01882 }
01883 
01884 static void ccgDM_drawUVEdges(DerivedMesh *dm)
01885 {
01886 
01887     MFace *mf = dm->getFaceArray(dm);
01888     MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
01889     int i;
01890     
01891     if (tf) {
01892         glBegin(GL_LINES);
01893         for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
01894             if(!(mf->flag&ME_HIDE)) {
01895                 glVertex2fv(tf->uv[0]);
01896                 glVertex2fv(tf->uv[1]);
01897     
01898                 glVertex2fv(tf->uv[1]);
01899                 glVertex2fv(tf->uv[2]);
01900     
01901                 if(!mf->v4) {
01902                     glVertex2fv(tf->uv[2]);
01903                     glVertex2fv(tf->uv[0]);
01904                 } else {
01905                     glVertex2fv(tf->uv[2]);
01906                     glVertex2fv(tf->uv[3]);
01907     
01908                     glVertex2fv(tf->uv[3]);
01909                     glVertex2fv(tf->uv[0]);
01910                 }
01911             }
01912         }
01913         glEnd();
01914     }
01915 }
01916 
01917 static void ccgDM_drawMappedFaces(DerivedMesh *dm,
01918             int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
01919             int (*setMaterial)(int, void *attribs),
01920             int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
01921             void *userData, int useColors)
01922 {
01923     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
01924     CCGSubSurf *ss = ccgdm->ss;
01925     MCol *mcol= NULL;
01926     int i, gridSize = ccgSubSurf_getGridSize(ss);
01927     char *faceFlags = ccgdm->faceFlags;
01928     int gridFaces = gridSize - 1, totface;
01929 
01930     /* currently unused -- each original face is handled separately */
01931     (void)compareDrawOptions;
01932 
01933     if(useColors) {
01934         mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
01935         if(!mcol)
01936             mcol = dm->getFaceDataArray(dm, CD_MCOL);
01937     }
01938 
01939     totface = ccgSubSurf_getNumFaces(ss);
01940     for(i = 0; i < totface; i++) {
01941         CCGFace *f = ccgdm->faceMap[i].face;
01942         int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
01943         int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f);
01944         int origIndex;
01945         unsigned char *cp= NULL;
01946 
01947         origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
01948 
01949         if(faceFlags) drawSmooth = (faceFlags[origIndex*2] & ME_SMOOTH);
01950         else drawSmooth = 1;
01951 
01952         if(mcol) {
01953             cp= (unsigned char*)mcol;
01954             mcol += gridFaces*gridFaces*numVerts*4;
01955         }
01956 
01957         {
01958             int draw= 1;
01959 
01960             if(index == ORIGINDEX_NONE)
01961                 draw= setMaterial(faceFlags ? faceFlags[origIndex*2 + 1] + 1: 1, NULL); /* XXX, no faceFlags no material */
01962             else if (setDrawOptions)
01963                 draw= setDrawOptions(userData, index, &drawSmooth);
01964 
01965             if (draw) {
01966                 if (draw==2) {
01967                       glEnable(GL_POLYGON_STIPPLE);
01968                       glPolygonStipple(stipple_quarttone);
01969                 }
01970 
01971                 /* no need to set shading mode to flat because
01972                 *  normals are already used to change shading */
01973                 glShadeModel(GL_SMOOTH);
01974                 
01975                 for (S=0; S<numVerts; S++) {
01976                     DMGridData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
01977                     if (drawSmooth) {
01978                         for (y=0; y<gridFaces; y++) {
01979                             DMGridData *a, *b;
01980                             glBegin(GL_QUAD_STRIP);
01981                             for (x=0; x<gridFaces; x++) {
01982                                 a = &faceGridData[(y+0)*gridSize + x];
01983                                 b = &faceGridData[(y+1)*gridSize + x];
01984     
01985                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
01986                                 glNormal3fv(a->no);
01987                                 glVertex3fv(a->co);
01988                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
01989                                 glNormal3fv(b->no);
01990                                 glVertex3fv(b->co);
01991 
01992                                 if(x != gridFaces-1) {
01993                                     if(cp) cp += 16;
01994                                 }
01995                             }
01996 
01997                             a = &faceGridData[(y+0)*gridSize + x];
01998                             b = &faceGridData[(y+1)*gridSize + x];
01999 
02000                             if(cp) glColor3ub(cp[15], cp[14], cp[13]);
02001                             glNormal3fv(a->no);
02002                             glVertex3fv(a->co);
02003                             if(cp) glColor3ub(cp[11], cp[10], cp[9]);
02004                             glNormal3fv(b->no);
02005                             glVertex3fv(b->co);
02006 
02007                             if(cp) cp += 16;
02008 
02009                             glEnd();
02010                         }
02011                     } else {
02012                         glBegin(GL_QUADS);
02013                         for (y=0; y<gridFaces; y++) {
02014                             for (x=0; x<gridFaces; x++) {
02015                                 float *a = faceGridData[(y+0)*gridSize + x].co;
02016                                 float *b = faceGridData[(y+0)*gridSize + x + 1].co;
02017                                 float *c = faceGridData[(y+1)*gridSize + x + 1].co;
02018                                 float *d = faceGridData[(y+1)*gridSize + x].co;
02019 
02020                                 ccgDM_glNormalFast(a, b, c, d);
02021     
02022                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
02023                                 glVertex3fv(d);
02024                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
02025                                 glVertex3fv(c);
02026                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
02027                                 glVertex3fv(b);
02028                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
02029                                 glVertex3fv(a);
02030 
02031                                 if(cp) cp += 16;
02032                             }
02033                         }
02034                         glEnd();
02035                     }
02036                 }
02037                 if (draw==2)
02038                     glDisable(GL_POLYGON_STIPPLE);
02039             }
02040         }
02041     }
02042 }
02043 static void ccgDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) {
02044     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
02045     CCGSubSurf *ss = ccgdm->ss;
02046     CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
02047     int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
02048 
02049     ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
02050 
02051     for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
02052         CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
02053         DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
02054         int index = ccgDM_getEdgeMapIndex(ss, e);
02055 
02056         glBegin(GL_LINE_STRIP);
02057         if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
02058             if (useAging && !(G.f&G_BACKBUFSEL)) {
02059                 int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
02060                 glColor3ub(0, ageCol>0?ageCol:0, 0);
02061             }
02062 
02063             for (i=0; i<edgeSize-1; i++) {
02064                 glVertex3fv(edgeData[i].co);
02065                 glVertex3fv(edgeData[i+1].co);
02066             }
02067         }
02068         glEnd();
02069     }
02070 
02071     ccgEdgeIterator_free(ei);
02072 }
02073 static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) {
02074     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
02075     CCGSubSurf *ss = ccgdm->ss;
02076     CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss);
02077     int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss);
02078 
02079     ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL);
02080 
02081     for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
02082         CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
02083         DMGridData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
02084         int index = ccgDM_getEdgeMapIndex(ss, e);
02085 
02086         glBegin(GL_LINE_STRIP);
02087         if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
02088             for (i=0; i<edgeSize; i++) {
02089                 setDrawInterpOptions(userData, index, (float) i/(edgeSize-1));
02090 
02091                 if (useAging && !(G.f&G_BACKBUFSEL)) {
02092                     int ageCol = 255-ccgSubSurf_getEdgeAge(ss, e)*4;
02093                     glColor3ub(0, ageCol>0?ageCol:0, 0);
02094                 }
02095 
02096                 glVertex3fv(edgeData[i].co);
02097             }
02098         }
02099         glEnd();
02100     }
02101 
02102     ccgEdgeIterator_free(ei);
02103 }
02104 static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData) {
02105     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
02106     CCGSubSurf *ss = ccgdm->ss;
02107     CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
02108 
02109     for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
02110         CCGFace *f = ccgFaceIterator_getCurrent(fi);
02111         int index = ccgDM_getFaceMapIndex(ss, f);
02112 
02113         if (index!=-1) {
02114                 /* Face center data normal isn't updated atm. */
02115             DMGridData *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0);
02116 
02117             func(userData, index, vd->co, vd->no);
02118         }
02119     }
02120 
02121     ccgFaceIterator_free(fi);
02122 }
02123 
02124 static void ccgDM_release(DerivedMesh *dm) {
02125     CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
02126 
02127     if (DM_release(dm)) {
02128         /* Before freeing, need to update the displacement map */
02129         if(ccgdm->multires.modified) {
02130             /* Check that mmd still exists */
02131             if(!ccgdm->multires.local_mmd && BLI_findindex(&ccgdm->multires.ob->modifiers, ccgdm->multires.mmd) < 0)
02132                 ccgdm->multires.mmd = NULL;
02133             if(ccgdm->multires.mmd)
02134                 ccgdm->multires.update(dm);
02135         }
02136 
02137         if(ccgdm->gridFaces) MEM_freeN(ccgdm->gridFaces);
02138         if(ccgdm->gridData) MEM_freeN(ccgdm->gridData);
02139         if(ccgdm->gridAdjacency) MEM_freeN(ccgdm->gridAdjacency);
02140         if(ccgdm->gridOffset) MEM_freeN(ccgdm->gridOffset);
02141         if(ccgdm->freeSS) ccgSubSurf_free(ccgdm->ss);
02142         if(ccgdm->fmap) MEM_freeN(ccgdm->fmap);
02143         if(ccgdm->fmap_mem) MEM_freeN(ccgdm->fmap_mem);
02144         MEM_freeN(ccgdm->edgeFlags);
02145         MEM_freeN(ccgdm->faceFlags);
02146         MEM_freeN(ccgdm->vertMap);
02147         MEM_freeN(ccgdm->edgeMap);
02148         MEM_freeN(ccgdm->faceMap);
02149         MEM_freeN(ccgdm);
02150     }
02151 }
02152 
02153 static void *ccgDM_get_vert_data_layer(DerivedMesh *dm, int type)
02154 {
02155     if(type == CD_ORIGINDEX) {
02156         /* create origindex on demand to save memory */
02157         CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02158         CCGSubSurf *ss= ccgdm->ss;
02159         int *origindex;
02160         int a, index, totnone, totorig;
02161 
02162         DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
02163         origindex= DM_get_vert_data_layer(dm, CD_ORIGINDEX);
02164 
02165         totorig = ccgSubSurf_getNumVerts(ss);
02166         totnone= dm->numVertData - totorig;
02167 
02168         /* original vertices are at the end */
02169         for(a=0; a<totnone; a++)
02170             origindex[a]= ORIGINDEX_NONE;
02171 
02172         for(index=0; index<totorig; index++, a++) {
02173             CCGVert *v = ccgdm->vertMap[index].vert;
02174             origindex[a] = ccgDM_getVertMapIndex(ccgdm->ss, v);
02175         }
02176 
02177         return origindex;
02178     }
02179 
02180     return DM_get_vert_data_layer(dm, type);
02181 }
02182 
02183 static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
02184 {
02185     if(type == CD_ORIGINDEX) {
02186         /* create origindex on demand to save memory */
02187         CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02188         CCGSubSurf *ss= ccgdm->ss;
02189         int *origindex;
02190         int a, i, index, totnone, totorig, totedge;
02191         int edgeSize= ccgSubSurf_getEdgeSize(ss);
02192 
02193         DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
02194         origindex= DM_get_edge_data_layer(dm, CD_ORIGINDEX);
02195 
02196         totedge= ccgSubSurf_getNumEdges(ss);
02197         totorig= totedge*(edgeSize - 1);
02198         totnone= dm->numEdgeData - totorig;
02199 
02200         /* original edges are at the end */
02201         for(a=0; a<totnone; a++)
02202             origindex[a]= ORIGINDEX_NONE;
02203 
02204         for(index=0; index<totedge; index++) {
02205             CCGEdge *e= ccgdm->edgeMap[index].edge;
02206             int mapIndex= ccgDM_getEdgeMapIndex(ss, e);
02207 
02208             for(i = 0; i < edgeSize - 1; i++, a++)
02209                 origindex[a]= mapIndex;
02210         }
02211 
02212         return origindex;
02213     }
02214 
02215     return DM_get_edge_data_layer(dm, type);
02216 }
02217 
02218 static void *ccgDM_get_face_data_layer(DerivedMesh *dm, int type)
02219 {
02220     if(type == CD_ORIGINDEX) {
02221         /* create origindex on demand to save memory */
02222         CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02223         CCGSubSurf *ss= ccgdm->ss;
02224         int *origindex;
02225         int a, i, index, totface;
02226         int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
02227 
02228         DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
02229         origindex= DM_get_face_data_layer(dm, CD_ORIGINDEX);
02230 
02231         totface= ccgSubSurf_getNumFaces(ss);
02232 
02233         for(a=0, index=0; index<totface; index++) {
02234             CCGFace *f = ccgdm->faceMap[index].face;
02235             int numVerts = ccgSubSurf_getFaceNumVerts(f);
02236             int mapIndex = ccgDM_getFaceMapIndex(ss, f);
02237 
02238             for(i=0; i<gridFaces*gridFaces*numVerts; i++, a++)
02239                 origindex[a]= mapIndex;
02240         }
02241 
02242         return origindex;
02243     }
02244 
02245     return DM_get_face_data_layer(dm, type);
02246 }
02247 
02248 static int ccgDM_getNumGrids(DerivedMesh *dm)
02249 {
02250     CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02251     int index, numFaces, numGrids;
02252 
02253     numFaces= ccgSubSurf_getNumFaces(ccgdm->ss);
02254     numGrids= 0;
02255 
02256     for(index=0; index<numFaces; index++) {
02257         CCGFace *f = ccgdm->faceMap[index].face;
02258         numGrids += ccgSubSurf_getFaceNumVerts(f);
02259     }
02260 
02261     return numGrids;
02262 }
02263 
02264 static int ccgDM_getGridSize(DerivedMesh *dm)
02265 {
02266     CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02267     return ccgSubSurf_getGridSize(ccgdm->ss);
02268 }
02269 
02270 static int ccgdm_adjacent_grid(CCGSubSurf *ss, int *gridOffset, CCGFace *f, int S, int offset)
02271 {
02272     CCGFace *adjf;
02273     CCGEdge *e;
02274     int i, j= 0, numFaces, fIndex, numEdges= 0;
02275 
02276     e = ccgSubSurf_getFaceEdge(ss, f, S);
02277     numFaces = ccgSubSurf_getEdgeNumFaces(e);
02278 
02279     if(numFaces != 2)
02280         return -1;
02281 
02282     for(i = 0; i < numFaces; i++) {
02283         adjf = ccgSubSurf_getEdgeFace(e, i);
02284 
02285         if(adjf != f) {
02286             numEdges = ccgSubSurf_getFaceNumVerts(adjf);
02287             for(j = 0; j < numEdges; j++)
02288                 if(ccgSubSurf_getFaceEdge(ss, adjf, j) == e)
02289                     break;
02290 
02291             if(j != numEdges)
02292                 break;
02293         }
02294     }
02295 
02296     if(numEdges == 0)
02297         return -1;
02298     
02299     fIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, adjf));
02300 
02301     return gridOffset[fIndex] + (j + offset)%numEdges;
02302 }
02303 
02304 static void ccgdm_create_grids(DerivedMesh *dm)
02305 {
02306     CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02307     CCGSubSurf *ss= ccgdm->ss;
02308     DMGridData **gridData;
02309     DMGridAdjacency *gridAdjacency, *adj;
02310     CCGFace **gridFaces;
02311     int *gridOffset;
02312     int index, numFaces, numGrids, S, gIndex /*, gridSize*/;
02313 
02314     if(ccgdm->gridData)
02315         return;
02316     
02317     numGrids = ccgDM_getNumGrids(dm);
02318     numFaces = ccgSubSurf_getNumFaces(ss);
02319     /*gridSize = ccgDM_getGridSize(dm);*/  /*UNUSED*/
02320 
02321     /* compute offset into grid array for each face */
02322     gridOffset = MEM_mallocN(sizeof(int)*numFaces, "ccgdm.gridOffset");
02323 
02324     for(gIndex = 0, index = 0; index < numFaces; index++) {
02325         CCGFace *f = ccgdm->faceMap[index].face;
02326         int numVerts = ccgSubSurf_getFaceNumVerts(f);
02327 
02328         gridOffset[index] = gIndex;
02329         gIndex += numVerts;
02330     }
02331 
02332     /* compute grid data */
02333     gridData = MEM_mallocN(sizeof(DMGridData*)*numGrids, "ccgdm.gridData");
02334     gridAdjacency = MEM_mallocN(sizeof(DMGridAdjacency)*numGrids, "ccgdm.gridAdjacency");
02335     gridFaces = MEM_mallocN(sizeof(CCGFace*)*numGrids, "ccgdm.gridFaces");
02336 
02337     for(gIndex = 0, index = 0; index < numFaces; index++) {
02338         CCGFace *f = ccgdm->faceMap[index].face;
02339         int numVerts = ccgSubSurf_getFaceNumVerts(f);
02340 
02341         for(S = 0; S < numVerts; S++, gIndex++) {
02342             int prevS = (S - 1 + numVerts) % numVerts;
02343             int nextS = (S + 1 + numVerts) % numVerts;
02344 
02345             gridData[gIndex] = ccgSubSurf_getFaceGridDataArray(ss, f, S);
02346             gridFaces[gIndex] = f;
02347 
02348             adj = &gridAdjacency[gIndex];
02349 
02350             adj->index[0] = gIndex - S + nextS;
02351             adj->rotation[0] = 3;
02352             adj->index[1] = ccgdm_adjacent_grid(ss, gridOffset, f, prevS, 0);
02353             adj->rotation[1] = 1;
02354             adj->index[2] = ccgdm_adjacent_grid(ss, gridOffset, f, S, 1);
02355             adj->rotation[2] = 3;
02356             adj->index[3] = gIndex - S + prevS;
02357             adj->rotation[3] = 1;
02358         }
02359     }
02360 
02361     ccgdm->gridData = gridData;
02362     ccgdm->gridFaces = gridFaces;
02363     ccgdm->gridAdjacency = gridAdjacency;
02364     ccgdm->gridOffset = gridOffset;
02365 }
02366 
02367 static DMGridData **ccgDM_getGridData(DerivedMesh *dm)
02368 {
02369     CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02370 
02371     ccgdm_create_grids(dm);
02372     return ccgdm->gridData;
02373 }
02374 
02375 static DMGridAdjacency *ccgDM_getGridAdjacency(DerivedMesh *dm)
02376 {
02377     CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02378 
02379     ccgdm_create_grids(dm);
02380     return ccgdm->gridAdjacency;
02381 }
02382 
02383 static int *ccgDM_getGridOffset(DerivedMesh *dm)
02384 {
02385     CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02386 
02387     ccgdm_create_grids(dm);
02388     return ccgdm->gridOffset;
02389 }
02390 
02391 static ListBase *ccgDM_getFaceMap(Object *ob, DerivedMesh *dm)
02392 {
02393     CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02394 
02395     if(!ccgdm->multires.mmd && !ccgdm->fmap && ob->type == OB_MESH) {
02396         Mesh *me= ob->data;
02397 
02398         create_vert_face_map(&ccgdm->fmap, &ccgdm->fmap_mem, me->mface,
02399                      me->totvert, me->totface);
02400     }
02401 
02402     return ccgdm->fmap;
02403 }
02404 
02405 static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm)
02406 {
02407     MultiresModifierData *mmd= ccgdm->multires.mmd;
02408 
02409     /* both of multires and subsurm modifiers are CCG, but
02410        grids should only be used when sculpting on multires */
02411     if(!mmd)
02412         return 0;
02413 
02414     return 1;
02415 }
02416 
02417 static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
02418 {
02419     CCGDerivedMesh *ccgdm= (CCGDerivedMesh*)dm;
02420     int gridSize, numGrids, grid_pbvh;
02421 
02422     if(!ob) {
02423         ccgdm->pbvh= NULL;
02424         return NULL;
02425     }
02426 
02427     if(!ob->sculpt)
02428         return NULL;
02429 
02430     grid_pbvh= ccgDM_use_grid_pbvh(ccgdm);
02431 
02432     if(ob->sculpt->pbvh) {
02433         if(grid_pbvh) {
02434             /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
02435                but this can be freed on ccgdm release, this updates the pointers
02436                when the ccgdm gets remade, the assumption is that the topology
02437                does not change. */
02438             ccgdm_create_grids(dm);
02439             BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void**)ccgdm->gridFaces);
02440         }
02441 
02442         ccgdm->pbvh = ob->sculpt->pbvh;
02443     }
02444 
02445     if(ccgdm->pbvh)
02446         return ccgdm->pbvh;
02447 
02448     /* no pbvh exists yet, we need to create one. only in case of multires
02449        we build a pbvh over the modified mesh, in other cases the base mesh
02450        is being sculpted, so we build a pbvh from that. */
02451     if(grid_pbvh) {
02452         ccgdm_create_grids(dm);
02453 
02454         gridSize = ccgDM_getGridSize(dm);
02455         numGrids = ccgDM_getNumGrids(dm);
02456 
02457         ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new();
02458         BLI_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
02459             numGrids, gridSize, (void**)ccgdm->gridFaces);
02460     } else if(ob->type == OB_MESH) {
02461         Mesh *me= ob->data;
02462         ob->sculpt->pbvh= ccgdm->pbvh = BLI_pbvh_new();
02463         BLI_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
02464                    me->totface, me->totvert);
02465     }
02466 
02467     return ccgdm->pbvh;
02468 }
02469 
02470 static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
02471                                          int drawInteriorEdges,
02472                                          int useSubsurfUv,
02473                                          DerivedMesh *dm)
02474 {
02475     CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
02476     CCGVertIterator *vi;
02477     CCGEdgeIterator *ei;
02478     CCGFaceIterator *fi;
02479     int index, totvert, totedge, totface;
02480     int i;
02481     int vertNum, edgeNum, faceNum;
02482     short *edgeFlags;
02483     char *faceFlags;
02484     int edgeSize;
02485     int gridSize;
02486     int gridFaces;
02487     /*int gridSideVerts;*/
02488     int gridSideEdges;
02489     int gridInternalEdges;
02490     MEdge *medge = NULL;
02491     MFace *mface = NULL;
02492     int *orig_indices;
02493     FaceVertWeight *qweight, *tweight;
02494 
02495     DM_from_template(&ccgdm->dm, dm, DM_TYPE_CCGDM,
02496                      ccgSubSurf_getNumFinalVerts(ss),
02497                      ccgSubSurf_getNumFinalEdges(ss),
02498                      ccgSubSurf_getNumFinalFaces(ss));
02499 
02500     ccgdm->dm.getMinMax = ccgDM_getMinMax;
02501     ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
02502     ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
02503 
02504     ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
02505     ccgdm->dm.getVert = ccgDM_getFinalVert;
02506     ccgdm->dm.getEdge = ccgDM_getFinalEdge;
02507     ccgdm->dm.getFace = ccgDM_getFinalFace;
02508     ccgdm->dm.getVertCo = ccgDM_getFinalVertCo;
02509     ccgdm->dm.getVertNo = ccgDM_getFinalVertNo;
02510     ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
02511     ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
02512     ccgdm->dm.copyFaceArray = ccgDM_copyFinalFaceArray;
02513     ccgdm->dm.getVertData = DM_get_vert_data;
02514     ccgdm->dm.getEdgeData = DM_get_edge_data;
02515     ccgdm->dm.getFaceData = DM_get_face_data;
02516     ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
02517     ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
02518     ccgdm->dm.getFaceDataArray = ccgDM_get_face_data_layer;
02519     ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
02520     ccgdm->dm.getGridSize = ccgDM_getGridSize;
02521     ccgdm->dm.getGridData = ccgDM_getGridData;
02522     ccgdm->dm.getGridAdjacency = ccgDM_getGridAdjacency;
02523     ccgdm->dm.getGridOffset = ccgDM_getGridOffset;
02524     ccgdm->dm.getFaceMap = ccgDM_getFaceMap;
02525     ccgdm->dm.getPBVH = ccgDM_getPBVH;
02526 
02527     ccgdm->dm.getVertCos = ccgdm_getVertCos;
02528     ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
02529     ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
02530     ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
02531     
02532     ccgdm->dm.drawVerts = ccgDM_drawVerts;
02533     ccgdm->dm.drawEdges = ccgDM_drawEdges;
02534     ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
02535     ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
02536     ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored;
02537     ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
02538     ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
02539     ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
02540     ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
02541     ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
02542     ccgdm->dm.drawMappedFacesMat = ccgDM_drawMappedFacesMat;
02543     ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
02544 
02545     ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
02546     ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
02547     
02548     ccgdm->dm.release = ccgDM_release;
02549     
02550     ccgdm->ss = ss;
02551     ccgdm->drawInteriorEdges = drawInteriorEdges;
02552     ccgdm->useSubsurfUv = useSubsurfUv;
02553 
02554     totvert = ccgSubSurf_getNumVerts(ss);
02555     ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
02556     vi = ccgSubSurf_getVertIterator(ss);
02557     for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
02558         CCGVert *v = ccgVertIterator_getCurrent(vi);
02559 
02560         ccgdm->vertMap[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))].vert = v;
02561     }
02562     ccgVertIterator_free(vi);
02563 
02564     totedge = ccgSubSurf_getNumEdges(ss);
02565     ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
02566     ei = ccgSubSurf_getEdgeIterator(ss);
02567     for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
02568         CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
02569 
02570         ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e;
02571     }
02572 
02573     totface = ccgSubSurf_getNumFaces(ss);
02574     ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
02575     fi = ccgSubSurf_getFaceIterator(ss);
02576     for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
02577         CCGFace *f = ccgFaceIterator_getCurrent(fi);
02578 
02579         ccgdm->faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f))].face = f;
02580     }
02581     ccgFaceIterator_free(fi);
02582 
02583     edgeSize = ccgSubSurf_getEdgeSize(ss);
02584     gridSize = ccgSubSurf_getGridSize(ss);
02585     gridFaces = gridSize - 1;
02586     /*gridSideVerts = gridSize - 2;*/ /*UNUSED*/
02587     /*gridInternalVerts = gridSideVerts * gridSideVerts; */ /*UNUSED*/
02588     gridSideEdges = gridSize - 1;
02589     gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2; 
02590 
02591     calc_ss_weights(gridFaces, &qweight, &tweight);
02592 
02593     vertNum = 0;
02594     edgeNum = 0;
02595     faceNum = 0;
02596 
02597     /* mvert = dm->getVertArray(dm); - as yet unused */
02598     medge = dm->getEdgeArray(dm);
02599     mface = dm->getFaceArray(dm);
02600 
02601     faceFlags = ccgdm->faceFlags = MEM_callocN(sizeof(char)*2*totface, "faceFlags");
02602 
02603     orig_indices = (int*)ccgdm->dm.getFaceDataArray(&ccgdm->dm, CD_ORIGINDEX);
02604     for(index = 0; index < totface; ++index) {
02605         CCGFace *f = ccgdm->faceMap[index].face;
02606         int numVerts = ccgSubSurf_getFaceNumVerts(f);
02607         int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
02608         int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f));
02609         FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
02610         int S, x, y;
02611         int vertIdx[4];
02612 
02613         ccgdm->faceMap[index].startVert = vertNum;
02614         ccgdm->faceMap[index].startEdge = edgeNum;
02615         ccgdm->faceMap[index].startFace = faceNum;
02616 
02617         if(orig_indices)
02618             orig_indices[faceNum] = origIndex;
02619 
02620         /* set the face base vert */
02621         *((int*)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
02622 
02623         for(S = 0; S < numVerts; S++) {
02624             CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
02625 
02626             vertIdx[S] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
02627         }
02628 
02629         DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0],
02630                             numVerts, vertNum);
02631         ++vertNum;
02632 
02633         for(S = 0; S < numVerts; S++) {
02634             int prevS = (S - 1 + numVerts) % numVerts;
02635             int nextS = (S + 1) % numVerts;
02636             int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
02637             for(x = 1; x < gridFaces; x++) {
02638                 float w[4];
02639                 w[prevS]  = weight[x][0][0];
02640                 w[S]      = weight[x][0][1];
02641                 w[nextS]  = weight[x][0][2];
02642                 w[otherS] = weight[x][0][3];
02643                 DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
02644                                     numVerts, vertNum);
02645                 ++vertNum;
02646             }
02647         }
02648 
02649         for(S = 0; S < numVerts; S++) {
02650             int prevS = (S - 1 + numVerts) % numVerts;
02651             int nextS = (S + 1) % numVerts;
02652             int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
02653             for(y = 1; y < gridFaces; y++) {
02654                 for(x = 1; x < gridFaces; x++) {
02655                     float w[4];
02656                     w[prevS]  = weight[y * gridFaces + x][0][0];
02657                     w[S]      = weight[y * gridFaces + x][0][1];
02658                     w[nextS]  = weight[y * gridFaces + x][0][2];
02659                     w[otherS] = weight[y * gridFaces + x][0][3];
02660                     DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
02661                                         numVerts, vertNum);
02662                     ++vertNum;
02663                 }
02664             }
02665         }
02666 
02667         for(S = 0; S < numVerts; S++) {
02668             int prevS = (S - 1 + numVerts) % numVerts;
02669             int nextS = (S + 1) % numVerts;
02670             int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
02671 
02672             weight = (numVerts == 4) ? qweight : tweight;
02673 
02674             for(y = 0; y < gridFaces; y++) {
02675                 for(x = 0; x < gridFaces; x++) {
02676                     FaceVertWeight w;
02677                     int j;
02678 
02679                     for(j = 0; j < 4; ++j) {
02680                         w[j][prevS]  = (*weight)[j][0];
02681                         w[j][S]      = (*weight)[j][1];
02682                         w[j][nextS]  = (*weight)[j][2];
02683                         w[j][otherS] = (*weight)[j][3];
02684                     }
02685 
02686                     DM_interp_face_data(dm, &ccgdm->dm, &origIndex, NULL,
02687                                         &w, 1, faceNum);
02688                     weight++;
02689 
02690                     ++faceNum;
02691                 }
02692             }
02693         }
02694 
02695         faceFlags[index*2] = mface[origIndex].flag;
02696         faceFlags[index*2 + 1] = mface[origIndex].mat_nr;
02697 
02698         edgeNum += numFinalEdges;
02699     }
02700 
02701     if(useSubsurfUv) {
02702         CustomData *fdata = &ccgdm->dm.faceData;
02703         CustomData *dmfdata = &dm->faceData;
02704         int numlayer = CustomData_number_of_layers(fdata, CD_MTFACE);
02705         int dmnumlayer = CustomData_number_of_layers(dmfdata, CD_MTFACE);
02706 
02707         for (i=0; i<numlayer && i<dmnumlayer; i++)
02708             set_subsurf_uv(ss, dm, &ccgdm->dm, i);
02709     }
02710 
02711     edgeFlags = ccgdm->edgeFlags = MEM_callocN(sizeof(short)*totedge, "edgeFlags");
02712 
02713     for(index = 0; index < totedge; ++index) {
02714         CCGEdge *e = ccgdm->edgeMap[index].edge;
02715         int numFinalEdges = edgeSize - 1;
02716         int x;
02717         int vertIdx[2];
02718         int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e));
02719 
02720         CCGVert *v;
02721         v = ccgSubSurf_getEdgeVert0(e);
02722         vertIdx[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
02723         v = ccgSubSurf_getEdgeVert1(e);
02724         vertIdx[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
02725 
02726         ccgdm->edgeMap[index].startVert = vertNum;
02727         ccgdm->edgeMap[index].startEdge = edgeNum;
02728 
02729         /* set the edge base vert */
02730         *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
02731 
02732         for(x = 1; x < edgeSize - 1; x++) {
02733             float w[2];
02734             w[1] = (float) x / (edgeSize - 1);
02735             w[0] = 1 - w[1];
02736             DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum);
02737             ++vertNum;
02738         }
02739 
02740         edgeFlags[index]= medge[edgeIdx].flag;
02741 
02742         edgeNum += numFinalEdges;
02743     }
02744 
02745     for(index = 0; index < totvert; ++index) {
02746         CCGVert *v = ccgdm->vertMap[index].vert;
02747         int vertIdx;
02748 
02749         vertIdx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
02750 
02751         ccgdm->vertMap[index].startVert = vertNum;
02752 
02753         /* set the vert base vert */
02754         *((int*) ccgSubSurf_getVertUserData(ss, v)) = vertNum;
02755 
02756         DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1);
02757 
02758         ++vertNum;
02759     }
02760 
02761     MEM_freeN(qweight);
02762     MEM_freeN(tweight);
02763 
02764     return ccgdm;
02765 }
02766 
02767 /***/
02768 
02769 struct DerivedMesh *subsurf_make_derived_from_derived(
02770                         struct DerivedMesh *dm,
02771                         struct SubsurfModifierData *smd,
02772                         int useRenderParams, float (*vertCos)[3],
02773                         int isFinalCalc, int forEditMode, int inEditMode)
02774 {
02775     int useSimple = smd->subdivType == ME_SIMPLE_SUBSURF;
02776     int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
02777     int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
02778     int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
02779     CCGDerivedMesh *result;
02780 
02781     if(forEditMode) {
02782         int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels;
02783 
02784         smd->emCache = _getSubSurf(smd->emCache, levels, useAging, 0,
02785                                    useSimple);
02786         ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
02787 
02788         result = getCCGDerivedMesh(smd->emCache,
02789                                    drawInteriorEdges,
02790                                    useSubsurfUv, dm);
02791     } else if(useRenderParams) {
02792         /* Do not use cache in render mode. */
02793         CCGSubSurf *ss;
02794         int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels): smd->renderLevels;
02795 
02796         if(levels == 0)
02797             return dm;
02798         
02799         ss = _getSubSurf(NULL, levels, 0, 1, useSimple);
02800 
02801         ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
02802 
02803         result = getCCGDerivedMesh(ss,
02804             drawInteriorEdges, useSubsurfUv, dm);
02805 
02806         result->freeSS = 1;
02807     } else {
02808         int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
02809         int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
02810         int levels= (smd->modifier.scene)? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels): smd->levels;
02811         CCGSubSurf *ss;
02812 
02813         /* It is quite possible there is a much better place to do this. It
02814          * depends a bit on how rigourously we expect this function to never
02815          * be called in editmode. In semi-theory we could share a single
02816          * cache, but the handles used inside and outside editmode are not
02817          * the same so we would need some way of converting them. Its probably
02818          * not worth the effort. But then why am I even writing this long
02819          * comment that no one will read? Hmmm. - zr
02820          *
02821          * Addendum: we can't really ensure that this is never called in edit
02822          * mode, so now we have a parameter to verify it. - brecht
02823          */
02824         if(!inEditMode && smd->emCache) {
02825             ccgSubSurf_free(smd->emCache);
02826             smd->emCache = NULL;
02827         }
02828 
02829         if(useIncremental && isFinalCalc) {
02830             smd->mCache = ss = _getSubSurf(smd->mCache, levels,
02831                                            useAging, 0, useSimple);
02832 
02833             ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
02834 
02835             result = getCCGDerivedMesh(smd->mCache,
02836                                        drawInteriorEdges,
02837                                        useSubsurfUv, dm);
02838         } else {
02839             if (smd->mCache && isFinalCalc) {
02840                 ccgSubSurf_free(smd->mCache);
02841                 smd->mCache = NULL;
02842             }
02843 
02844             ss = _getSubSurf(NULL, levels, 0, 1, useSimple);
02845             ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
02846 
02847             result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm);
02848 
02849             if(isFinalCalc)
02850                 smd->mCache = ss;
02851             else
02852                 result->freeSS = 1;
02853         }
02854     }
02855 
02856     return (DerivedMesh*)result;
02857 }
02858 
02859 void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) 
02860 {
02861     /* Finds the subsurf limit positions for the verts in a mesh 
02862      * and puts them in an array of floats. Please note that the 
02863      * calculated vert positions is incorrect for the verts 
02864      * on the boundary of the mesh.
02865      */
02866     CCGSubSurf *ss = _getSubSurf(NULL, 1, 0, 1, 0);
02867     float edge_sum[3], face_sum[3];
02868     CCGVertIterator *vi;
02869     DerivedMesh *dm = CDDM_from_mesh(me, NULL);
02870 
02871     ss_sync_from_derivedmesh(ss, dm, NULL, 0);
02872 
02873     vi = ccgSubSurf_getVertIterator(ss);
02874     for (; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
02875         CCGVert *v = ccgVertIterator_getCurrent(vi);
02876         int idx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v));
02877         int N = ccgSubSurf_getVertNumEdges(v);
02878         int numFaces = ccgSubSurf_getVertNumFaces(v);
02879         float *co;
02880         int i;
02881 
02882         edge_sum[0]= edge_sum[1]= edge_sum[2]= 0.0;
02883         face_sum[0]= face_sum[1]= face_sum[2]= 0.0;
02884 
02885         for (i=0; i<N; i++) {
02886             CCGEdge *e = ccgSubSurf_getVertEdge(v, i);
02887             add_v3_v3v3(edge_sum, edge_sum, ccgSubSurf_getEdgeData(ss, e, 1));
02888         }
02889         for (i=0; i<numFaces; i++) {
02890             CCGFace *f = ccgSubSurf_getVertFace(v, i);
02891             add_v3_v3(face_sum, ccgSubSurf_getFaceCenterData(f));
02892         }
02893 
02894         /* ad-hoc correction for boundary vertices, to at least avoid them
02895            moving completely out of place (brecht) */
02896         if(numFaces && numFaces != N)
02897             mul_v3_fl(face_sum, (float)N/(float)numFaces);
02898 
02899         co = ccgSubSurf_getVertData(ss, v);
02900         positions_r[idx][0] = (co[0]*N*N + edge_sum[0]*4 + face_sum[0])/(N*(N+5));
02901         positions_r[idx][1] = (co[1]*N*N + edge_sum[1]*4 + face_sum[1])/(N*(N+5));
02902         positions_r[idx][2] = (co[2]*N*N + edge_sum[2]*4 + face_sum[2])/(N*(N+5));
02903     }
02904     ccgVertIterator_free(vi);
02905 
02906     ccgSubSurf_free(ss);
02907 
02908     dm->release(dm);
02909 }
02910