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