Blender  V2.59
CCGSubSurf.c
Go to the documentation of this file.
00001 
00004 /* $Id: CCGSubSurf.c 35888 2011-03-30 02:05:10Z campbellbarton $ */
00005 
00006 #include <stdlib.h>
00007 #include <string.h>
00008 #include <math.h>
00009 
00010 #include "CCGSubSurf.h"
00011 
00012 #include "MEM_guardedalloc.h"
00013 #include "BLO_sys_types.h" // for intptr_t support
00014 
00015 #ifdef _MSC_VER
00016 #define CCG_INLINE __inline
00017 #else
00018 #define CCG_INLINE inline
00019 #endif
00020 
00021 /* copied from BKE_utildefines.h ugh */
00022 #ifdef __GNUC__
00023 #  define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
00024 #else
00025 #  define UNUSED(x) x
00026 #endif
00027 
00028 /* used for normalize_v3 in BLI_math_vector
00029  * float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */
00030 #define EPSILON (1.0e-35f)
00031 
00032 /***/
00033 
00034 typedef unsigned char   byte;
00035 
00036 /***/
00037 
00038 static int kHashSizes[] = {
00039         1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 
00040         16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 
00041         4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459
00042 };
00043 
00044 typedef struct _EHEntry EHEntry;
00045 struct _EHEntry {
00046         EHEntry *next;
00047         void *key;
00048 };
00049 typedef struct _EHash {
00050         EHEntry **buckets;
00051         int numEntries, curSize, curSizeIdx;
00052 
00053         CCGAllocatorIFC allocatorIFC;
00054         CCGAllocatorHDL allocator;
00055 } EHash;
00056 
00057 #define EHASH_alloc(eh, nb)                     ((eh)->allocatorIFC.alloc((eh)->allocator, nb))
00058 #define EHASH_free(eh, ptr)                     ((eh)->allocatorIFC.free((eh)->allocator, ptr))
00059 
00060 #define EHASH_hash(eh, item)    (((uintptr_t) (item))%((unsigned int) (eh)->curSize))
00061 
00062 static EHash *_ehash_new(int estimatedNumEntries, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) {
00063         EHash *eh = allocatorIFC->alloc(allocator, sizeof(*eh));
00064         eh->allocatorIFC = *allocatorIFC;
00065         eh->allocator = allocator;
00066         eh->numEntries = 0;
00067         eh->curSizeIdx = 0;
00068         while (kHashSizes[eh->curSizeIdx]<estimatedNumEntries)
00069                 eh->curSizeIdx++;
00070         eh->curSize = kHashSizes[eh->curSizeIdx];
00071         eh->buckets = EHASH_alloc(eh, eh->curSize*sizeof(*eh->buckets));
00072         memset(eh->buckets, 0, eh->curSize*sizeof(*eh->buckets));
00073 
00074         return eh;
00075 }
00076 typedef void (*EHEntryFreeFP)(EHEntry *, void *);
00077 static void _ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *userData) {
00078         int numBuckets = eh->curSize;
00079 
00080         while (numBuckets--) {
00081                 EHEntry *entry = eh->buckets[numBuckets];
00082 
00083                 while (entry) {
00084                         EHEntry *next = entry->next;
00085 
00086                         freeEntry(entry, userData);
00087 
00088                         entry = next;
00089                 }
00090         }
00091 
00092         EHASH_free(eh, eh->buckets);
00093         EHASH_free(eh, eh);
00094 }
00095 
00096 static void _ehash_insert(EHash *eh, EHEntry *entry) {
00097         int numBuckets = eh->curSize;
00098         int hash = EHASH_hash(eh, entry->key);
00099         entry->next = eh->buckets[hash];
00100         eh->buckets[hash] = entry;
00101         eh->numEntries++;
00102 
00103         if (eh->numEntries > (numBuckets*3)) {
00104                 EHEntry **oldBuckets = eh->buckets;
00105                 eh->curSize = kHashSizes[++eh->curSizeIdx];
00106                 
00107                 eh->buckets = EHASH_alloc(eh, eh->curSize*sizeof(*eh->buckets));
00108                 memset(eh->buckets, 0, eh->curSize*sizeof(*eh->buckets));
00109 
00110                 while (numBuckets--) {
00111                         for (entry = oldBuckets[numBuckets]; entry;) {
00112                                 EHEntry *next = entry->next;
00113                                 
00114                                 hash = EHASH_hash(eh, entry->key);
00115                                 entry->next = eh->buckets[hash];
00116                                 eh->buckets[hash] = entry;
00117                                 
00118                                 entry = next;
00119                         }
00120                 }
00121 
00122                 EHASH_free(eh, oldBuckets);
00123         }
00124 }
00125 
00126 static void *_ehash_lookupWithPrev(EHash *eh, void *key, void ***prevp_r) {
00127         int hash = EHASH_hash(eh, key);
00128         void **prevp = (void**) &eh->buckets[hash];
00129         EHEntry *entry;
00130         
00131         for (; (entry = *prevp); prevp = (void**) &entry->next) {
00132                 if (entry->key==key) {
00133                         *prevp_r = (void**) prevp;
00134                         return entry;
00135                 }
00136         }
00137         
00138         return NULL;
00139 }
00140 
00141 static void *_ehash_lookup(EHash *eh, void *key) {
00142         int hash = EHASH_hash(eh, key);
00143         EHEntry *entry;
00144         
00145         for (entry = eh->buckets[hash]; entry; entry = entry->next)
00146                 if (entry->key==key)
00147                         break;
00148         
00149         return entry;
00150 }
00151 
00152 
00153 
00154 typedef struct _EHashIterator {
00155         EHash *eh;
00156         int curBucket;
00157         EHEntry *curEntry;
00158 } EHashIterator;
00159 
00160 static EHashIterator *_ehashIterator_new(EHash *eh) {
00161         EHashIterator *ehi = EHASH_alloc(eh, sizeof(*ehi));
00162         ehi->eh = eh;
00163         ehi->curEntry = NULL;
00164         ehi->curBucket = -1;
00165         while (!ehi->curEntry) {
00166                 ehi->curBucket++;
00167                 if (ehi->curBucket==ehi->eh->curSize)
00168                         break;
00169                 ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
00170         }
00171         return ehi;
00172 }
00173 static void _ehashIterator_free(EHashIterator *ehi) {
00174         EHASH_free(ehi->eh, ehi);
00175 }
00176 
00177 static void *_ehashIterator_getCurrent(EHashIterator *ehi) {
00178         return ehi->curEntry;
00179 }
00180 
00181 static void _ehashIterator_next(EHashIterator *ehi) {
00182         if (ehi->curEntry) {
00183                 ehi->curEntry = ehi->curEntry->next;
00184                 while (!ehi->curEntry) {
00185                         ehi->curBucket++;
00186                         if (ehi->curBucket==ehi->eh->curSize)
00187                                 break;
00188                         ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
00189                 }
00190         }
00191 }
00192 static int _ehashIterator_isStopped(EHashIterator *ehi) {
00193         return !ehi->curEntry;
00194 }
00195 
00196 /***/
00197 
00198 static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes) {
00199         return malloc(numBytes);
00200 }
00201 static void *_stdAllocator_realloc(CCGAllocatorHDL UNUSED(a), void *ptr, int newSize, int UNUSED(oldSize)) {
00202         return realloc(ptr, newSize);
00203 }
00204 static void _stdAllocator_free(CCGAllocatorHDL UNUSED(a), void *ptr) {
00205         free(ptr);
00206 }
00207 
00208 static CCGAllocatorIFC *_getStandardAllocatorIFC(void) {
00209         static CCGAllocatorIFC ifc;
00210 
00211         ifc.alloc = _stdAllocator_alloc;
00212         ifc.realloc = _stdAllocator_realloc;
00213         ifc.free = _stdAllocator_free;
00214         ifc.release = NULL;
00215 
00216         return &ifc;
00217 }
00218 
00219 /***/
00220 
00221 static int VertDataEqual(float *a, float *b) {
00222         return a[0]==b[0] && a[1]==b[1] && a[2]==b[2];
00223 }
00224 #define VertDataZero(av)                                { float *_a = (float*) av; _a[0] = _a[1] = _a[2] = 0.0f; }
00225 #define VertDataCopy(av, bv)                    { float *_a = (float*) av, *_b = (float*) bv; _a[0] =_b[0]; _a[1] =_b[1]; _a[2] =_b[2]; }
00226 #define VertDataAdd(av, bv)                             { float *_a = (float*) av, *_b = (float*) bv; _a[0]+=_b[0]; _a[1]+=_b[1]; _a[2]+=_b[2]; }
00227 #define VertDataSub(av, bv)                             { float *_a = (float*) av, *_b = (float*) bv; _a[0]-=_b[0]; _a[1]-=_b[1]; _a[2]-=_b[2]; }
00228 #define VertDataMulN(av, n)                             { float *_a = (float*) av; _a[0]*=n; _a[1]*=n; _a[2]*=n; }
00229 #define VertDataAvg4(tv, av, bv, cv, dv) \
00230         { \
00231                 float *_t = (float*) tv, *_a = (float*) av, *_b = (float*) bv, *_c = (float*) cv, *_d = (float*) dv; \
00232                 _t[0] = (_a[0]+_b[0]+_c[0]+_d[0])*.25f; \
00233                 _t[1] = (_a[1]+_b[1]+_c[1]+_d[1])*.25f; \
00234                 _t[2] = (_a[2]+_b[2]+_c[2]+_d[2])*.25f; \
00235         }
00236 #define NormZero(av)                                    { float *_a = (float*) av; _a[0] = _a[1] = _a[2] = 0.0f; }
00237 #define NormCopy(av, bv)                                { float *_a = (float*) av, *_b = (float*) bv; _a[0] =_b[0]; _a[1] =_b[1]; _a[2] =_b[2]; }
00238 #define NormAdd(av, bv)                                 { float *_a = (float*) av, *_b = (float*) bv; _a[0]+=_b[0]; _a[1]+=_b[1]; _a[2]+=_b[2]; }
00239 
00240 
00241 static int _edge_isBoundary(CCGEdge *e);
00242 
00243 /***/
00244 
00245 enum {
00246         Vert_eEffected=         (1<<0),
00247         Vert_eChanged=          (1<<1),
00248         Vert_eSeam=                     (1<<2),
00249 } /*VertFlags*/;
00250 enum {
00251         Edge_eEffected=         (1<<0),
00252 } /*CCGEdgeFlags*/;
00253 enum {
00254         Face_eEffected=         (1<<0),
00255 } /*FaceFlags*/;
00256 
00257 struct _CCGVert {
00258         CCGVert         *next;  /* EHData.next */
00259         CCGVertHDL      vHDL;   /* EHData.key */
00260 
00261         short numEdges, numFaces, flags, pad;
00262 
00263         CCGEdge **edges;
00264         CCGFace **faces;
00265 //      byte *levelData;
00266 //      byte *userData;
00267 };
00268 #define VERT_getLevelData(v)            ((byte*) &(v)[1])
00269 
00270 struct _CCGEdge {
00271         CCGEdge         *next;  /* EHData.next */
00272         CCGEdgeHDL      eHDL;   /* EHData.key */
00273 
00274         short numFaces, flags;
00275         float crease;
00276 
00277         CCGVert *v0,*v1;
00278         CCGFace **faces;
00279 
00280 //      byte *levelData;
00281 //      byte *userData;
00282 };
00283 #define EDGE_getLevelData(e)            ((byte*) &(e)[1])
00284 
00285 struct _CCGFace {
00286         CCGFace         *next;  /* EHData.next */
00287         CCGFaceHDL      fHDL;   /* EHData.key */
00288 
00289         short numVerts, flags, pad1, pad2;
00290 
00291 //      CCGVert **verts;
00292 //      CCGEdge **edges;
00293 //      byte *centerData;
00294 //      byte **gridData;
00295 //      byte *userData;
00296 };
00297 #define FACE_getVerts(f)                ((CCGVert**) &(f)[1])
00298 #define FACE_getEdges(f)                ((CCGEdge**) &(FACE_getVerts(f)[(f)->numVerts]))
00299 #define FACE_getCenterData(f)   ((byte*) &(FACE_getEdges(f)[(f)->numVerts]))
00300 
00301 typedef enum {
00302         eSyncState_None = 0,
00303         eSyncState_Vert,
00304         eSyncState_Edge,
00305         eSyncState_Face,
00306         eSyncState_Partial,
00307 } SyncState;
00308 
00309 struct _CCGSubSurf {
00310         EHash *vMap;    /* map of CCGVertHDL -> Vert */
00311         EHash *eMap;    /* map of CCGEdgeHDL -> Edge */
00312         EHash *fMap;    /* map of CCGFaceHDL -> Face */
00313 
00314         CCGMeshIFC meshIFC;
00315         
00316         CCGAllocatorIFC allocatorIFC;
00317         CCGAllocatorHDL allocator;
00318 
00319         int subdivLevels;
00320         int numGrids;
00321         int allowEdgeCreation;
00322         float defaultCreaseValue;
00323         void *defaultEdgeUserData;
00324 
00325         void *q, *r;
00326                 
00327                 // data for calc vert normals
00328         int calcVertNormals;
00329         int normalDataOffset;
00330 
00331                 // data for age'ing (to debug sync)
00332         int currentAge;
00333         int useAgeCounts;
00334         int vertUserAgeOffset;
00335         int edgeUserAgeOffset;
00336         int faceUserAgeOffset;
00337 
00338                 // data used during syncing
00339         SyncState syncState;
00340 
00341         EHash *oldVMap, *oldEMap, *oldFMap;
00342         int lenTempArrays;
00343         CCGVert **tempVerts;
00344         CCGEdge **tempEdges;
00345 };
00346 
00347 #define CCGSUBSURF_alloc(ss, nb)                        ((ss)->allocatorIFC.alloc((ss)->allocator, nb))
00348 #define CCGSUBSURF_realloc(ss, ptr, nb, ob)     ((ss)->allocatorIFC.realloc((ss)->allocator, ptr, nb, ob))
00349 #define CCGSUBSURF_free(ss, ptr)                        ((ss)->allocatorIFC.free((ss)->allocator, ptr))
00350 
00351 /***/
00352 
00353 static CCGVert *_vert_new(CCGVertHDL vHDL, CCGSubSurf *ss) {
00354         CCGVert *v = CCGSUBSURF_alloc(ss, sizeof(CCGVert) + ss->meshIFC.vertDataSize * (ss->subdivLevels+1) + ss->meshIFC.vertUserSize);
00355         byte *userData;
00356 
00357         v->vHDL = vHDL;
00358         v->edges = NULL;
00359         v->faces = NULL;
00360         v->numEdges = v->numFaces = 0;
00361         v->flags = 0;
00362 
00363         userData = ccgSubSurf_getVertUserData(ss, v);
00364         memset(userData, 0, ss->meshIFC.vertUserSize);
00365         if (ss->useAgeCounts) *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
00366 
00367         return v;
00368 }
00369 static void _vert_remEdge(CCGVert *v, CCGEdge *e) {
00370         int i;
00371         for (i=0; i<v->numEdges; i++) {
00372                 if (v->edges[i]==e) {
00373                         v->edges[i] = v->edges[--v->numEdges];
00374                         break;
00375                 }
00376         }
00377 }
00378 static void _vert_remFace(CCGVert *v, CCGFace *f) {
00379         int i;
00380         for (i=0; i<v->numFaces; i++) {
00381                 if (v->faces[i]==f) {
00382                         v->faces[i] = v->faces[--v->numFaces];
00383                         break;
00384                 }
00385         }
00386 }
00387 static void _vert_addEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss) {
00388         v->edges = CCGSUBSURF_realloc(ss, v->edges, (v->numEdges+1)*sizeof(*v->edges), v->numEdges*sizeof(*v->edges));
00389         v->edges[v->numEdges++] = e;
00390 }
00391 static void _vert_addFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) {
00392         v->faces = CCGSUBSURF_realloc(ss, v->faces, (v->numFaces+1)*sizeof(*v->faces), v->numFaces*sizeof(*v->faces));
00393         v->faces[v->numFaces++] = f;
00394 }
00395 static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) {
00396         int i;
00397         for (i=0; i<v->numEdges; i++) {
00398                 CCGEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse
00399                 if (    (e->v0==v && e->v1==vQ) ||
00400                                 (e->v1==v && e->v0==vQ))
00401                         return e;
00402         }
00403         return NULL;
00404 }
00405 static int _vert_isBoundary(CCGVert *v) {
00406         int i;
00407         for (i=0; i<v->numEdges; i++)
00408                 if (_edge_isBoundary(v->edges[i]))
00409                         return 1;
00410         return 0;
00411 }
00412 
00413 static void *_vert_getCo(CCGVert *v, int lvl, int dataSize) {
00414         return &VERT_getLevelData(v)[lvl*dataSize];
00415 }
00416 static float *_vert_getNo(CCGVert *v, int lvl, int dataSize, int normalDataOffset) {
00417         return (float*) &VERT_getLevelData(v)[lvl*dataSize + normalDataOffset];
00418 }
00419 
00420 static void _vert_free(CCGVert *v, CCGSubSurf *ss) {
00421         CCGSUBSURF_free(ss, v->edges);
00422         CCGSUBSURF_free(ss, v->faces);
00423         CCGSUBSURF_free(ss, v);
00424 }
00425 
00426 static int VERT_seam(CCGVert *v) {
00427         return ((v->flags & Vert_eSeam) != 0);
00428 }
00429 
00430 /***/
00431 
00432 static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float crease, CCGSubSurf *ss) {
00433         CCGEdge *e = CCGSUBSURF_alloc(ss, sizeof(CCGEdge) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1) + ss->meshIFC.edgeUserSize);
00434         byte *userData;
00435 
00436         e->eHDL = eHDL;
00437         e->v0 = v0;
00438         e->v1 = v1;
00439         e->crease = crease;
00440         e->faces = NULL;
00441         e->numFaces = 0;
00442         e->flags = 0;
00443         _vert_addEdge(v0, e, ss);
00444         _vert_addEdge(v1, e, ss);
00445 
00446         userData = ccgSubSurf_getEdgeUserData(ss, e);
00447         memset(userData, 0, ss->meshIFC.edgeUserSize);
00448         if (ss->useAgeCounts) *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
00449 
00450         return e;
00451 }
00452 static void _edge_remFace(CCGEdge *e, CCGFace *f) {
00453         int i;
00454         for (i=0; i<e->numFaces; i++) {
00455                 if (e->faces[i]==f) {
00456                         e->faces[i] = e->faces[--e->numFaces];
00457                         break;
00458                 }
00459         }
00460 }
00461 static void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) {
00462         e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces+1)*sizeof(*e->faces), e->numFaces*sizeof(*e->faces));
00463         e->faces[e->numFaces++] = f;
00464 }
00465 static int _edge_isBoundary(CCGEdge *e) {
00466         return e->numFaces<2;
00467 }
00468 
00469 static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ) {
00470         if (vQ==e->v0) {
00471                 return e->v1;
00472         } else {
00473                 return e->v0;
00474         }
00475 }
00476 
00477 static void *_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize) {
00478         int levelBase = lvl + (1<<lvl) - 1;
00479         return &EDGE_getLevelData(e)[dataSize*(levelBase + x)];
00480 }
00481 static float *_edge_getNo(CCGEdge *e, int lvl, int x, int dataSize, int normalDataOffset) {
00482         int levelBase = lvl + (1<<lvl) - 1;
00483         return (float*) &EDGE_getLevelData(e)[dataSize*(levelBase + x) + normalDataOffset];
00484 }
00485 static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize) {
00486         int levelBase = lvl + (1<<lvl) - 1;
00487         if (v==e->v0) {
00488                 return &EDGE_getLevelData(e)[dataSize*(levelBase + x)];
00489         } else {
00490                 return &EDGE_getLevelData(e)[dataSize*(levelBase + (1<<lvl) - x)];              
00491         }
00492 }
00493 
00494 static void _edge_free(CCGEdge *e, CCGSubSurf *ss) {
00495         CCGSUBSURF_free(ss, e->faces);
00496         CCGSUBSURF_free(ss, e);
00497 }
00498 static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss) {
00499         _vert_remEdge(e->v0, e);
00500         _vert_remEdge(e->v1, e);
00501         e->v0->flags |= Vert_eEffected;
00502         e->v1->flags |= Vert_eEffected;
00503         _edge_free(e, ss);
00504 }
00505 
00506 static float EDGE_getSharpness(CCGEdge *e, int lvl) {
00507         if (!lvl)
00508                 return e->crease;
00509         else if (!e->crease)
00510                 return 0.0f;
00511         else if (e->crease - lvl < 0.0f)
00512                 return 0.0f;
00513         else
00514                 return e->crease - lvl;
00515 }
00516 
00517 static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, CCGSubSurf *ss) {
00518         int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
00519         CCGFace *f = CCGSUBSURF_alloc(ss, sizeof(CCGFace) + sizeof(CCGVert*)*numVerts + sizeof(CCGEdge*)*numVerts + ss->meshIFC.vertDataSize *(1 + numVerts*maxGridSize + numVerts*maxGridSize*maxGridSize) + ss->meshIFC.faceUserSize);
00520         byte *userData;
00521         int i;
00522 
00523         f->numVerts = numVerts;
00524         f->fHDL = fHDL;
00525         f->flags = 0;
00526 
00527         for (i=0; i<numVerts; i++) {
00528                 FACE_getVerts(f)[i] = verts[i];
00529                 FACE_getEdges(f)[i] = edges[i];
00530                 _vert_addFace(verts[i], f, ss);
00531                 _edge_addFace(edges[i], f, ss);
00532         }
00533 
00534         userData = ccgSubSurf_getFaceUserData(ss, f);
00535         memset(userData, 0, ss->meshIFC.faceUserSize);
00536         if (ss->useAgeCounts) *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
00537 
00538         return f;
00539 }
00540 
00541 static CCG_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) {
00542         int maxGridSize = 1 + (1<<(levels-1));
00543         int spacing = 1<<(levels-lvl);
00544         byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
00545         return &gridBase[dataSize*x*spacing];
00546 }
00547 static CCG_INLINE void *_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset) {
00548         int maxGridSize = 1 + (1<<(levels-1));
00549         int spacing = 1<<(levels-lvl);
00550         byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
00551         return &gridBase[dataSize*x*spacing + normalDataOffset];
00552 }
00553 static CCG_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) {
00554         int maxGridSize = 1 + (1<<(levels-1));
00555         int spacing = 1<<(levels-lvl);
00556         byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
00557         return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)];
00558 }
00559 static CCG_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) {
00560         int maxGridSize = 1 + (1<<(levels-1));
00561         int spacing = 1<<(levels-lvl);
00562         byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
00563         return (float*) &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing) + normalDataOffset];
00564 }
00565 static int _face_getVertIndex(CCGFace *f, CCGVert *v) {
00566         int i;
00567         for (i=0; i<f->numVerts; i++)
00568                 if (FACE_getVerts(f)[i]==v)
00569                         return i;
00570         return -1;
00571 }
00572 static CCG_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) {
00573         int maxGridSize = 1 + (1<<(levels-1));
00574         int spacing = 1<<(levels-lvl);
00575         int S, x, y, cx, cy;
00576 
00577         for (S=0; S<f->numVerts; S++)
00578                 if (FACE_getEdges(f)[S]==e)
00579                         break;
00580 
00581         eX = eX*spacing;
00582         eY = eY*spacing;
00583         if (e->v0!=FACE_getVerts(f)[S]) {
00584                 eX = (maxGridSize*2 - 1)-1 - eX;
00585         }
00586         y = maxGridSize - 1 - eX;
00587         x = maxGridSize - 1 - eY;
00588         if (x<0) {
00589                 S = (S+f->numVerts-1)%f->numVerts;
00590                 cx = y;
00591                 cy = -x;
00592         } else if (y<0) {
00593                 S = (S+1)%f->numVerts;
00594                 cx = -y;
00595                 cy = x;
00596         } else {
00597                 cx = x;
00598                 cy = y;
00599         }
00600         return _face_getIFCo(f, levels, S, cx, cy, levels, dataSize);
00601 }
00602 static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) {
00603         return (float*) ((byte*) _face_getIFCoEdge(f, e, lvl, eX, eY, levels, dataSize) + normalDataOffset);
00604 }
00605 static void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) {
00606         float *a = _face_getIFCo(f, lvl, S, x+0, y+0, levels, dataSize);
00607         float *b = _face_getIFCo(f, lvl, S, x+1, y+0, levels, dataSize);
00608         float *c = _face_getIFCo(f, lvl, S, x+1, y+1, levels, dataSize);
00609         float *d = _face_getIFCo(f, lvl, S, x+0, y+1, levels, dataSize);
00610         float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
00611         float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
00612         float length;
00613 
00614         no[0] = b_dY*a_cZ - b_dZ*a_cY;
00615         no[1] = b_dZ*a_cX - b_dX*a_cZ;
00616         no[2] = b_dX*a_cY - b_dY*a_cX;
00617 
00618         length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
00619 
00620         if (length>EPSILON) {
00621                 float invLength = 1.f/length;
00622 
00623                 no[0] *= invLength;
00624                 no[1] *= invLength;
00625                 no[2] *= invLength;
00626         } else {
00627                 NormZero(no);
00628         }
00629 }
00630 
00631 static void _face_free(CCGFace *f, CCGSubSurf *ss) {
00632         CCGSUBSURF_free(ss, f);
00633 }
00634 static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss) {
00635         int j;
00636         for (j=0; j<f->numVerts; j++) {
00637                 _vert_remFace(FACE_getVerts(f)[j], f);
00638                 _edge_remFace(FACE_getEdges(f)[j], f);
00639                 FACE_getVerts(f)[j]->flags |= Vert_eEffected;
00640         }
00641         _face_free(f, ss);
00642 }
00643 
00644 /***/
00645 
00646 CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) {
00647         if (!allocatorIFC) {
00648                 allocatorIFC = _getStandardAllocatorIFC();
00649                 allocator = NULL;
00650         }
00651 
00652         if (subdivLevels<1) {
00653                 return NULL;
00654         } else {
00655                 CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss));
00656 
00657                 ss->allocatorIFC = *allocatorIFC;
00658                 ss->allocator = allocator;
00659 
00660                 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
00661                 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
00662                 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
00663 
00664                 ss->meshIFC = *ifc;
00665                 
00666                 ss->subdivLevels = subdivLevels;
00667                 ss->numGrids = 0;
00668                 ss->allowEdgeCreation = 0;
00669                 ss->defaultCreaseValue = 0;
00670                 ss->defaultEdgeUserData = NULL;
00671 
00672                 ss->useAgeCounts = 0;
00673                 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
00674 
00675                 ss->calcVertNormals = 0;
00676                 ss->normalDataOffset = 0;
00677 
00678                 ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
00679                 ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
00680 
00681                 ss->currentAge = 0;
00682 
00683                 ss->syncState = eSyncState_None;
00684 
00685                 ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL;
00686                 ss->lenTempArrays = 0;
00687                 ss->tempVerts = NULL;
00688                 ss->tempEdges = NULL;   
00689 
00690                 return ss;
00691         }
00692 }
00693 
00694 void ccgSubSurf_free(CCGSubSurf *ss) {
00695         CCGAllocatorIFC allocatorIFC = ss->allocatorIFC;
00696         CCGAllocatorHDL allocator = ss->allocator;
00697 
00698         if (ss->syncState) {
00699                 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_free, ss);
00700                 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_free, ss);
00701                 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
00702 
00703                 MEM_freeN(ss->tempVerts);
00704                 MEM_freeN(ss->tempEdges);
00705         }
00706 
00707         CCGSUBSURF_free(ss, ss->r);
00708         CCGSUBSURF_free(ss, ss->q);
00709         if (ss->defaultEdgeUserData) CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
00710 
00711         _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
00712         _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
00713         _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
00714 
00715         CCGSUBSURF_free(ss, ss);
00716 
00717         if (allocatorIFC.release) {
00718                 allocatorIFC.release(allocator);
00719         }
00720 }
00721 
00722 CCGError ccgSubSurf_setAllowEdgeCreation(CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData) {
00723         if (ss->defaultEdgeUserData) {
00724                 CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
00725         }
00726 
00727         ss->allowEdgeCreation = !!allowEdgeCreation;
00728         ss->defaultCreaseValue = defaultCreaseValue;
00729         ss->defaultEdgeUserData = CCGSUBSURF_alloc(ss, ss->meshIFC.edgeUserSize);
00730 
00731         if (defaultUserData) {
00732                 memcpy(ss->defaultEdgeUserData, defaultUserData, ss->meshIFC.edgeUserSize);
00733         } else {
00734                 memset(ss->defaultEdgeUserData, 0, ss->meshIFC.edgeUserSize);
00735         }
00736 
00737         return eCCGError_None;
00738 }
00739 void ccgSubSurf_getAllowEdgeCreation(CCGSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r) {
00740         if (allowEdgeCreation_r) *allowEdgeCreation_r = ss->allowEdgeCreation;
00741         if (ss->allowEdgeCreation) {
00742                 if (defaultCreaseValue_r) *defaultCreaseValue_r = ss->defaultCreaseValue;
00743                 if (defaultUserData_r) memcpy(defaultUserData_r, ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize);
00744         }
00745 }
00746 
00747 CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels) {
00748         if (subdivisionLevels<=0) {
00749                 return eCCGError_InvalidValue;
00750         } else if (subdivisionLevels!=ss->subdivLevels) {
00751                 ss->numGrids = 0;
00752                 ss->subdivLevels = subdivisionLevels;
00753                 _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
00754                 _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
00755                 _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
00756                 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
00757                 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
00758                 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
00759         }
00760 
00761         return eCCGError_None;
00762 }
00763 
00764 void ccgSubSurf_getUseAgeCounts(CCGSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r)
00765 {
00766         *useAgeCounts_r = ss->useAgeCounts;
00767 
00768         if (vertUserOffset_r) *vertUserOffset_r = ss->vertUserAgeOffset;
00769         if (edgeUserOffset_r) *edgeUserOffset_r = ss->edgeUserAgeOffset;
00770         if (faceUserOffset_r) *faceUserOffset_r = ss->faceUserAgeOffset;
00771 }
00772 
00773 CCGError ccgSubSurf_setUseAgeCounts(CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset) {
00774         if (useAgeCounts) {
00775                 if (    (vertUserOffset+4>ss->meshIFC.vertUserSize) ||
00776                                 (edgeUserOffset+4>ss->meshIFC.edgeUserSize) ||
00777                                 (faceUserOffset+4>ss->meshIFC.faceUserSize)) {
00778                         return eCCGError_InvalidValue;
00779                 }  else {
00780                         ss->useAgeCounts = 1;
00781                         ss->vertUserAgeOffset = vertUserOffset;
00782                         ss->edgeUserAgeOffset = edgeUserOffset;
00783                         ss->faceUserAgeOffset = faceUserOffset;
00784                 }
00785         } else {
00786                 ss->useAgeCounts = 0;
00787                 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
00788         }
00789 
00790         return eCCGError_None;
00791 }
00792 
00793 CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int normalDataOffset) {
00794         if (useVertNormals) {
00795                 if (normalDataOffset<0 || normalDataOffset+12>ss->meshIFC.vertDataSize) {
00796                         return eCCGError_InvalidValue;
00797                 } else {
00798                         ss->calcVertNormals = 1;
00799                         ss->normalDataOffset = normalDataOffset;
00800                 }
00801         } else {
00802                 ss->calcVertNormals = 0;
00803                 ss->normalDataOffset = 0;
00804         }
00805 
00806         return eCCGError_None;
00807 }
00808 
00809 /***/
00810 
00811 CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) {
00812         if (ss->syncState!=eSyncState_None) {
00813                 return eCCGError_InvalidSyncState;
00814         }
00815 
00816         ss->currentAge++;
00817 
00818         ss->oldVMap = ss->vMap; 
00819         ss->oldEMap = ss->eMap; 
00820         ss->oldFMap = ss->fMap;
00821 
00822         ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
00823         ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
00824         ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
00825 
00826         ss->numGrids = 0;
00827 
00828         ss->lenTempArrays = 12;
00829         ss->tempVerts = MEM_mallocN(sizeof(*ss->tempVerts)*ss->lenTempArrays, "CCGSubsurf tempVerts");
00830         ss->tempEdges = MEM_mallocN(sizeof(*ss->tempEdges)*ss->lenTempArrays, "CCGSubsurf tempEdges");
00831 
00832         ss->syncState = eSyncState_Vert;
00833 
00834         return eCCGError_None;
00835 }
00836 
00837 CCGError ccgSubSurf_initPartialSync(CCGSubSurf *ss) {
00838         if (ss->syncState!=eSyncState_None) {
00839                 return eCCGError_InvalidSyncState;
00840         }
00841 
00842         ss->currentAge++;
00843 
00844         ss->syncState = eSyncState_Partial;
00845 
00846         return eCCGError_None;
00847 }
00848 
00849 CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL) {
00850         if (ss->syncState!=eSyncState_Partial) {
00851                 return eCCGError_InvalidSyncState;
00852         } else {
00853                 void **prevp;
00854                 CCGVert *v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
00855 
00856                 if (!v || v->numFaces || v->numEdges) {
00857                         return eCCGError_InvalidValue;
00858                 } else {
00859                         *prevp = v->next;
00860                         _vert_free(v, ss);
00861                 }
00862         }
00863 
00864         return eCCGError_None;
00865 }
00866 
00867 CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL) {
00868         if (ss->syncState!=eSyncState_Partial) {
00869                 return eCCGError_InvalidSyncState;
00870         } else {
00871                 void **prevp;
00872                 CCGEdge *e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
00873 
00874                 if (!e || e->numFaces) {
00875                         return eCCGError_InvalidValue;
00876                 } else {
00877                         *prevp = e->next;
00878                         _edge_unlinkMarkAndFree(e, ss);
00879                 }
00880         }
00881 
00882         return eCCGError_None;
00883 }
00884 
00885 CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) {
00886         if (ss->syncState!=eSyncState_Partial) {
00887                 return eCCGError_InvalidSyncState;
00888         } else {
00889                 void **prevp;
00890                 CCGFace *f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
00891 
00892                 if (!f) {
00893                         return eCCGError_InvalidValue;
00894                 } else {
00895                         *prevp = f->next;
00896                         _face_unlinkMarkAndFree(f, ss);
00897                 }
00898         }
00899 
00900         return eCCGError_None;
00901 }
00902 
00903 CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r) {
00904         void **prevp;
00905         CCGVert *v = NULL;
00906         short seamflag = (seam)? Vert_eSeam: 0;
00907         
00908         if (ss->syncState==eSyncState_Partial) {
00909                 v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
00910                 if (!v) {
00911                         v = _vert_new(vHDL, ss);
00912                         VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
00913                         _ehash_insert(ss->vMap, (EHEntry*) v);
00914                         v->flags = Vert_eEffected|seamflag;
00915                 } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
00916                         int i, j;
00917 
00918                         VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
00919                         v->flags = Vert_eEffected|seamflag;
00920 
00921                         for (i=0; i<v->numEdges; i++) {
00922                                 CCGEdge *e = v->edges[i];
00923                                 e->v0->flags |= Vert_eEffected;
00924                                 e->v1->flags |= Vert_eEffected;
00925                         }
00926                         for (i=0; i<v->numFaces; i++) {
00927                                 CCGFace *f = v->faces[i];
00928                                 for (j=0; j<f->numVerts; j++) {
00929                                         FACE_getVerts(f)[j]->flags |= Vert_eEffected;
00930                                 }
00931                         }
00932                 }
00933         } else {
00934                 if (ss->syncState!=eSyncState_Vert) { 
00935                         return eCCGError_InvalidSyncState;
00936                 }
00937 
00938                 v = _ehash_lookupWithPrev(ss->oldVMap, vHDL, &prevp);
00939                 if (!v) {
00940                         v = _vert_new(vHDL, ss);
00941                         VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
00942                         _ehash_insert(ss->vMap, (EHEntry*) v);
00943                         v->flags = Vert_eEffected|seamflag;
00944                 } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
00945                         *prevp = v->next;
00946                         _ehash_insert(ss->vMap, (EHEntry*) v);
00947                         VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
00948                         v->flags = Vert_eEffected|Vert_eChanged|seamflag;
00949                 } else {
00950                         *prevp = v->next;
00951                         _ehash_insert(ss->vMap, (EHEntry*) v);
00952                         v->flags = 0;
00953                 }
00954         }
00955 
00956         if (v_r) *v_r = v;
00957         return eCCGError_None;
00958 }
00959 
00960 CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r) {
00961         void **prevp;
00962         CCGEdge *e = NULL, *eNew;
00963 
00964         if (ss->syncState==eSyncState_Partial) {
00965                 e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
00966                 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1 || crease!=e->crease) {
00967                         CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
00968                         CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
00969 
00970                         eNew = _edge_new(eHDL, v0, v1, crease, ss);
00971 
00972                         if (e) {
00973                                 *prevp = eNew;
00974                                 eNew->next = e->next;
00975 
00976                                 _edge_unlinkMarkAndFree(e, ss);
00977                         } else {
00978                                 _ehash_insert(ss->eMap, (EHEntry*) eNew);
00979                         }
00980 
00981                         eNew->v0->flags |= Vert_eEffected;
00982                         eNew->v1->flags |= Vert_eEffected;
00983                 }
00984         } else {
00985                 if (ss->syncState==eSyncState_Vert) {
00986                         ss->syncState = eSyncState_Edge;
00987                 } else if (ss->syncState!=eSyncState_Edge) {
00988                         return eCCGError_InvalidSyncState;
00989                 }
00990 
00991                 e = _ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp);
00992                 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1|| e->crease!=crease) {
00993                         CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
00994                         CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
00995                         e = _edge_new(eHDL, v0, v1, crease, ss);
00996                         _ehash_insert(ss->eMap, (EHEntry*) e);
00997                         e->v0->flags |= Vert_eEffected;
00998                         e->v1->flags |= Vert_eEffected;
00999                 } else {
01000                         *prevp = e->next;
01001                         _ehash_insert(ss->eMap, (EHEntry*) e);
01002                         e->flags = 0;
01003                         if ((e->v0->flags|e->v1->flags)&Vert_eChanged) {
01004                                 e->v0->flags |= Vert_eEffected;
01005                                 e->v1->flags |= Vert_eEffected;
01006                         }
01007                 }
01008         }
01009 
01010         if (e_r) *e_r = e;
01011         return eCCGError_None;
01012 }
01013 
01014 CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r) {
01015         void **prevp;
01016         CCGFace *f = NULL, *fNew;
01017         int j, k, topologyChanged = 0;
01018 
01019         if (numVerts>ss->lenTempArrays) {
01020                 ss->lenTempArrays = (numVerts<ss->lenTempArrays*2)?ss->lenTempArrays*2:numVerts;
01021                 ss->tempVerts = MEM_reallocN(ss->tempVerts, sizeof(*ss->tempVerts)*ss->lenTempArrays);
01022                 ss->tempEdges = MEM_reallocN(ss->tempEdges, sizeof(*ss->tempEdges)*ss->lenTempArrays);
01023         }
01024 
01025         if (ss->syncState==eSyncState_Partial) {
01026                 f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
01027 
01028                 for (k=0; k<numVerts; k++) {
01029                         ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
01030                 }
01031                 for (k=0; k<numVerts; k++) {
01032                         ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]);
01033                 }
01034 
01035                 if (f) {
01036                         if (    f->numVerts!=numVerts ||
01037                                         memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) ||
01038                                         memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts))
01039                                 topologyChanged = 1;
01040                 }
01041 
01042                 if (!f || topologyChanged) {
01043                         fNew = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss);
01044 
01045                         if (f) {
01046                                 ss->numGrids += numVerts - f->numVerts;
01047 
01048                                 *prevp = fNew;
01049                                 fNew->next = f->next;
01050 
01051                                 _face_unlinkMarkAndFree(f, ss);
01052                         } else {
01053                                 ss->numGrids += numVerts;
01054                                 _ehash_insert(ss->fMap, (EHEntry*) fNew);
01055                         }
01056 
01057                         for (k=0; k<numVerts; k++)
01058                                 FACE_getVerts(fNew)[k]->flags |= Vert_eEffected;
01059                 }
01060         } else {
01061                 if (ss->syncState==eSyncState_Vert || ss->syncState==eSyncState_Edge) {
01062                         ss->syncState = eSyncState_Face;
01063                 } else if (ss->syncState!=eSyncState_Face) {
01064                         return eCCGError_InvalidSyncState;
01065                 }
01066 
01067                 f = _ehash_lookupWithPrev(ss->oldFMap, fHDL, &prevp);
01068 
01069                 for (k=0; k<numVerts; k++) {
01070                         ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
01071 
01072                         if (!ss->tempVerts[k])
01073                                 return eCCGError_InvalidValue;
01074                 }
01075                 for (k=0; k<numVerts; k++) {
01076                         ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]);
01077 
01078                         if (!ss->tempEdges[k]) {
01079                                 if (ss->allowEdgeCreation) {
01080                                         CCGEdge *e = ss->tempEdges[k] = _edge_new((CCGEdgeHDL) -1, ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts], ss->defaultCreaseValue, ss);
01081                                         _ehash_insert(ss->eMap, (EHEntry*) e);
01082                                         e->v0->flags |= Vert_eEffected;
01083                                         e->v1->flags |= Vert_eEffected;
01084                                         if (ss->meshIFC.edgeUserSize) {
01085                                                 memcpy(ccgSubSurf_getEdgeUserData(ss, e), ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize);
01086                                         }
01087                                 } else {
01088                                         return eCCGError_InvalidValue;
01089                                 }
01090                         }
01091                 }
01092 
01093                 if (f) {
01094                         if (    f->numVerts!=numVerts ||
01095                                         memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) ||
01096                                         memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts))
01097                                 topologyChanged = 1;
01098                 }
01099 
01100                 if (!f || topologyChanged) {
01101                         f = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss);
01102                         _ehash_insert(ss->fMap, (EHEntry*) f);
01103                         ss->numGrids += numVerts;
01104 
01105                         for (k=0; k<numVerts; k++)
01106                                 FACE_getVerts(f)[k]->flags |= Vert_eEffected;
01107                 } else {
01108                         *prevp = f->next;
01109                         _ehash_insert(ss->fMap, (EHEntry*) f);
01110                         f->flags = 0;
01111                         ss->numGrids += f->numVerts;
01112 
01113                         for (j=0; j<f->numVerts; j++) {
01114                                 if (FACE_getVerts(f)[j]->flags&Vert_eChanged) {
01115                                         for (k=0; k<f->numVerts; k++)
01116                                                 FACE_getVerts(f)[k]->flags |= Vert_eEffected;
01117                                         break;
01118                                 }
01119                         }
01120                 }
01121         }
01122 
01123         if (f_r) *f_r = f;
01124         return eCCGError_None;
01125 }
01126 
01127 static void ccgSubSurf__sync(CCGSubSurf *ss);
01128 CCGError ccgSubSurf_processSync(CCGSubSurf *ss) {
01129         if (ss->syncState==eSyncState_Partial) {
01130                 ss->syncState = eSyncState_None;
01131 
01132                 ccgSubSurf__sync(ss);
01133         } else if (ss->syncState) {
01134                 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_unlinkMarkAndFree, ss);
01135                 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_unlinkMarkAndFree, ss);
01136                 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
01137                 MEM_freeN(ss->tempEdges);
01138                 MEM_freeN(ss->tempVerts);
01139 
01140                 ss->lenTempArrays = 0;
01141 
01142                 ss->oldFMap = ss->oldEMap = ss->oldVMap = NULL;
01143                 ss->tempVerts = NULL;
01144                 ss->tempEdges = NULL;
01145 
01146                 ss->syncState = eSyncState_None;
01147 
01148                 ccgSubSurf__sync(ss);
01149         } else {
01150                 return eCCGError_InvalidSyncState;
01151         }
01152 
01153         return eCCGError_None;
01154 }
01155 
01156 #define VERT_getNo(e, lvl)                                      _vert_getNo(e, lvl, vertDataSize, normalDataOffset)
01157 #define EDGE_getNo(e, lvl, x)                           _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset)
01158 #define FACE_getIFNo(f, lvl, S, x, y)           _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
01159 #define FACE_calcIFNo(f, lvl, S, x, y, no)      _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
01160 #define FACE_getIENo(f, lvl, S, x)                      _face_getIENo(f, lvl, S, x, subdivLevels, vertDataSize, normalDataOffset)
01161 static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
01162         CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
01163         int numEffectedV, int numEffectedE, int numEffectedF) {
01164         int i,ptrIdx;
01165         int subdivLevels = ss->subdivLevels;
01166         int lvl = ss->subdivLevels;
01167         int edgeSize = 1 + (1<<lvl);
01168         int gridSize = 1 + (1<<(lvl-1));
01169         int normalDataOffset = ss->normalDataOffset;
01170         int vertDataSize = ss->meshIFC.vertDataSize;
01171 
01172         #pragma omp parallel for private(ptrIdx) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT)
01173         for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
01174                 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
01175                 int S, x, y;
01176                 float no[3];
01177 
01178                 for (S=0; S<f->numVerts; S++) {
01179                         for (y=0; y<gridSize-1; y++)
01180                                 for (x=0; x<gridSize-1; x++)
01181                                         NormZero(FACE_getIFNo(f, lvl, S, x, y));
01182 
01183                         if (FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected)
01184                                 for (x=0; x<gridSize-1; x++)
01185                                         NormZero(FACE_getIFNo(f, lvl, S, x, gridSize-1));
01186                         if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
01187                                 for (y=0; y<gridSize-1; y++)
01188                                         NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, y));
01189                         if (FACE_getVerts(f)[S]->flags&Vert_eEffected)
01190                                 NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1));
01191                 }
01192 
01193                 for (S=0; S<f->numVerts; S++) {
01194                         int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected);
01195                         int xLimit = !(FACE_getEdges(f)[S]->flags&Edge_eEffected);
01196                         int yLimitNext = xLimit;
01197                         int xLimitPrev = yLimit;
01198                         
01199                         for (y=0; y<gridSize - 1; y++) {
01200                                 for (x=0; x<gridSize - 1; x++) {
01201                                         int xPlusOk = (!xLimit || x<gridSize-2);
01202                                         int yPlusOk = (!yLimit || y<gridSize-2);
01203 
01204                                         FACE_calcIFNo(f, lvl, S, x, y, no);
01205 
01206                                         NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+0), no);
01207                                         if (xPlusOk)
01208                                                 NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+0), no);
01209                                         if (yPlusOk)
01210                                                 NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+1), no);
01211                                         if (xPlusOk && yPlusOk) {
01212                                                 if (x<gridSize-2 || y<gridSize-2 || FACE_getVerts(f)[S]->flags&Vert_eEffected) {
01213                                                         NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+1), no);
01214                                                 }
01215                                         }
01216 
01217                                         if (x==0 && y==0) {
01218                                                 int K;
01219 
01220                                                 if (!yLimitNext || 1<gridSize-1)
01221                                                         NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, 1), no);
01222                                                 if (!xLimitPrev || 1<gridSize-1)
01223                                                         NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no);
01224 
01225                                                 for (K=0; K<f->numVerts; K++) {
01226                                                         if (K!=S) {
01227                                                                 NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
01228                                                         }
01229                                                 }
01230                                         } else if (y==0) {
01231                                                 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no);
01232                                                 if (!yLimitNext || x<gridSize-2)
01233                                                         NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x+1), no);
01234                                         } else if (x==0) {
01235                                                 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no);
01236                                                 if (!xLimitPrev || y<gridSize-2)
01237                                                         NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y+1, 0), no);
01238                                         }
01239                                 }
01240                         }
01241                 }
01242         }
01243                 // XXX can I reduce the number of normalisations here?
01244         for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
01245                 CCGVert *v = (CCGVert*) effectedV[ptrIdx];
01246                 float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset);
01247 
01248                 NormZero(no);
01249 
01250                 for (i=0; i<v->numFaces; i++) {
01251                         CCGFace *f = v->faces[i];
01252                         NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1));
01253                 }
01254 
01255                 length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
01256 
01257                 if (length>EPSILON) {
01258                         float invLength = 1.0f/length;
01259                         no[0] *= invLength;
01260                         no[1] *= invLength;
01261                         no[2] *= invLength;
01262                 } else {
01263                         NormZero(no);
01264                 }
01265 
01266                 for (i=0; i<v->numFaces; i++) {
01267                         CCGFace *f = v->faces[i];
01268                         NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no);
01269                 }
01270         }
01271         for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
01272                 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
01273 
01274                 if (e->numFaces) {
01275                         CCGFace *fLast = e->faces[e->numFaces-1];
01276                         int x;
01277 
01278                         for (i=0; i<e->numFaces-1; i++) {
01279                                 CCGFace *f = e->faces[i];
01280 
01281                                 for (x=1; x<edgeSize-1; x++) {
01282                                         NormAdd(_face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
01283                                                         _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
01284                                 }
01285                         }
01286 
01287                         for (i=0; i<e->numFaces-1; i++) {
01288                                 CCGFace *f = e->faces[i];
01289 
01290                                 for (x=1; x<edgeSize-1; x++) {
01291                                         NormCopy(_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
01292                                                         _face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
01293                                 }
01294                         }
01295                 }
01296         }
01297 
01298         #pragma omp parallel for private(ptrIdx) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT)
01299         for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
01300                 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
01301                 int S, x, y;
01302 
01303                 for (S=0; S<f->numVerts; S++) {
01304                         NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1),
01305                                          FACE_getIFNo(f, lvl, S, gridSize-1, 0));
01306                 }
01307 
01308                 for (S=0; S<f->numVerts; S++) {
01309                         for (y=0; y<gridSize; y++) {
01310                                 for (x=0; x<gridSize; x++) {
01311                                         float *no = FACE_getIFNo(f, lvl, S, x, y);
01312                                         float length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
01313 
01314                                         if (length>EPSILON) {
01315                                                 float invLength = 1.0f/length;
01316                                                 no[0] *= invLength;
01317                                                 no[1] *= invLength;
01318                                                 no[2] *= invLength;
01319                                         } else {
01320                                                 NormZero(no);
01321                                         }
01322                                 }
01323                         }
01324 
01325                         VertDataCopy((float*)((byte*)FACE_getCenterData(f) + normalDataOffset),
01326                                 FACE_getIFNo(f, lvl, S, 0, 0));
01327 
01328                         for (x=1; x<gridSize-1; x++)
01329                                 NormCopy(FACE_getIENo(f, lvl, S, x),
01330                                         FACE_getIFNo(f, lvl, S, x, 0));
01331                 }
01332         }
01333 
01334         for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
01335                 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
01336 
01337                 if (e->numFaces) {
01338                         CCGFace *f = e->faces[0];
01339                         int x;
01340 
01341                         for (x=0; x<edgeSize; x++)
01342                                 NormCopy(EDGE_getNo(e, lvl, x),
01343                                         _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
01344                 }
01345                 else {
01346                         /* set to zero here otherwise the normals are uninitialized memory
01347                          * render: tests/animation/knight.blend with valgrind.
01348                          * we could be more clever and interpolate vertex normals but these are
01349                          * most likely not used so just zero out. */
01350                         int x;
01351 
01352                         for (x=0; x<edgeSize; x++) {
01353                                 NormZero(EDGE_getNo(e, lvl, x));
01354                         }
01355                 }
01356         }
01357 }
01358 #undef FACE_getIFNo
01359 
01360 #define VERT_getCo(v, lvl)                              _vert_getCo(v, lvl, vertDataSize)
01361 #define EDGE_getCo(e, lvl, x)                   _edge_getCo(e, lvl, x, vertDataSize)
01362 #define FACE_getIECo(f, lvl, S, x)              _face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize)
01363 #define FACE_getIFCo(f, lvl, S, x, y)   _face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize)
01364 static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
01365         CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
01366         int numEffectedV, int numEffectedE, int numEffectedF, int curLvl) {
01367         int subdivLevels = ss->subdivLevels;
01368         int edgeSize = 1 + (1<<curLvl);
01369         int gridSize = 1 + (1<<(curLvl-1));
01370         int nextLvl = curLvl+1;
01371         int ptrIdx, cornerIdx, i;
01372         int vertDataSize = ss->meshIFC.vertDataSize;
01373         void *q = ss->q, *r = ss->r;
01374 
01375         #pragma omp parallel for private(ptrIdx) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT)
01376         for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
01377                 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
01378                 int S, x, y;
01379 
01380                         /* interior face midpoints
01381                          *  o old interior face points
01382                          */
01383                 for (S=0; S<f->numVerts; S++) {
01384                         for (y=0; y<gridSize-1; y++) {
01385                                 for (x=0; x<gridSize-1; x++) {
01386                                         int fx = 1 + 2*x;
01387                                         int fy = 1 + 2*y;
01388                                         void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y+0);
01389                                         void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y+0);
01390                                         void *co2 = FACE_getIFCo(f, curLvl, S, x+1, y+1);
01391                                         void *co3 = FACE_getIFCo(f, curLvl, S, x+0, y+1);
01392                                         void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
01393 
01394                                         VertDataAvg4(co, co0, co1, co2, co3);
01395                                 }
01396                         }
01397                 }
01398 
01399                         /* interior edge midpoints
01400                          *  o old interior edge points
01401                          *  o new interior face midpoints
01402                          */
01403                 for (S=0; S<f->numVerts; S++) {
01404                         for (x=0; x<gridSize-1; x++) {
01405                                 int fx = x*2 + 1;
01406                                 void *co0 = FACE_getIECo(f, curLvl, S, x+0);
01407                                 void *co1 = FACE_getIECo(f, curLvl, S, x+1);
01408                                 void *co2 = FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx);
01409                                 void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
01410                                 void *co = FACE_getIECo(f, nextLvl, S, fx);
01411                                 
01412                                 VertDataAvg4(co, co0, co1, co2, co3);
01413                         }
01414 
01415                                         /* interior face interior edge midpoints
01416                                          *  o old interior face points
01417                                          *  o new interior face midpoints
01418                                          */
01419 
01420                                 /* vertical */
01421                         for (x=1; x<gridSize-1; x++) {
01422                                 for (y=0; y<gridSize-1; y++) {
01423                                         int fx = x*2;
01424                                         int fy = y*2+1;
01425                                         void *co0 = FACE_getIFCo(f, curLvl, S, x, y+0);
01426                                         void *co1 = FACE_getIFCo(f, curLvl, S, x, y+1);
01427                                         void *co2 = FACE_getIFCo(f, nextLvl, S, fx-1, fy);
01428                                         void *co3 = FACE_getIFCo(f, nextLvl, S, fx+1, fy);
01429                                         void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
01430 
01431                                         VertDataAvg4(co, co0, co1, co2, co3);
01432                                 }
01433                         }
01434 
01435                                 /* horizontal */
01436                         for (y=1; y<gridSize-1; y++) {
01437                                 for (x=0; x<gridSize-1; x++) {
01438                                         int fx = x*2+1;
01439                                         int fy = y*2;
01440                                         void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y);
01441                                         void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y);
01442                                         void *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy-1);
01443                                         void *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy+1);
01444                                         void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
01445 
01446                                         VertDataAvg4(co, co0, co1, co2, co3);
01447                                 }
01448                         }
01449                 }
01450         }
01451 
01452                 /* exterior edge midpoints
01453                  *  o old exterior edge points
01454                  *  o new interior face midpoints
01455                  */
01456         for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
01457                 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
01458                 float sharpness = EDGE_getSharpness(e, curLvl);
01459                 int x, j;
01460 
01461                 if (_edge_isBoundary(e) || sharpness > 1.0f) {
01462                         for (x=0; x<edgeSize-1; x++) {
01463                                 int fx = x*2 + 1;
01464                                 void *co0 = EDGE_getCo(e, curLvl, x+0);
01465                                 void *co1 = EDGE_getCo(e, curLvl, x+1);
01466                                 void *co = EDGE_getCo(e, nextLvl, fx);
01467 
01468                                 VertDataCopy(co, co0);
01469                                 VertDataAdd(co, co1);
01470                                 VertDataMulN(co, 0.5f);
01471                         }
01472                 } else {
01473                         for (x=0; x<edgeSize-1; x++) {
01474                                 int fx = x*2 + 1;
01475                                 void *co0 = EDGE_getCo(e, curLvl, x+0);
01476                                 void *co1 = EDGE_getCo(e, curLvl, x+1);
01477                                 void *co = EDGE_getCo(e, nextLvl, fx);
01478                                 int numFaces = 0;
01479 
01480                                 VertDataCopy(q, co0);
01481                                 VertDataAdd(q, co1);
01482 
01483                                 for (j=0; j<e->numFaces; j++) {
01484                                         CCGFace *f = e->faces[j];
01485                                         VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
01486                                         numFaces++;
01487                                 }
01488 
01489                                 VertDataMulN(q, 1.0f/(2.0f+numFaces));
01490 
01491                                 VertDataCopy(r, co0);
01492                                 VertDataAdd(r, co1);
01493                                 VertDataMulN(r, 0.5f);
01494 
01495                                 VertDataCopy(co, q);
01496                                 VertDataSub(r, q);
01497                                 VertDataMulN(r, sharpness);
01498                                 VertDataAdd(co, r);
01499                         }
01500                 }
01501         }
01502 
01503                 /* exterior vertex shift
01504                  *  o old vertex points (shifting)
01505                  *  o old exterior edge points
01506                  *  o new interior face midpoints
01507                  */
01508         for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
01509                 CCGVert *v = (CCGVert*) effectedV[ptrIdx];
01510                 void *co = VERT_getCo(v, curLvl);
01511                 void *nCo = VERT_getCo(v, nextLvl);
01512                 int sharpCount = 0, allSharp = 1;
01513                 float avgSharpness = 0.0;
01514                 int j, seam = VERT_seam(v), seamEdges = 0;
01515 
01516                 for (j=0; j<v->numEdges; j++) {
01517                         CCGEdge *e = v->edges[j];
01518                         float sharpness = EDGE_getSharpness(e, curLvl);
01519 
01520                         if (seam && _edge_isBoundary(e))
01521                                 seamEdges++;
01522 
01523                         if (sharpness!=0.0f) {
01524                                 sharpCount++;
01525                                 avgSharpness += sharpness;
01526                         } else {
01527                                 allSharp = 0;
01528                         }
01529                 }
01530 
01531                 if(sharpCount) {
01532                         avgSharpness /= sharpCount;
01533                         if (avgSharpness > 1.0f) {
01534                                 avgSharpness = 1.0f;
01535                         }
01536                 }
01537 
01538                 if (seamEdges < 2 || seamEdges != v->numEdges)
01539                         seam = 0;
01540 
01541                 if (!v->numEdges) {
01542                         VertDataCopy(nCo, co);
01543                 } else if (_vert_isBoundary(v)) {
01544                         int numBoundary = 0;
01545 
01546                         VertDataZero(r);
01547                         for (j=0; j<v->numEdges; j++) {
01548                                 CCGEdge *e = v->edges[j];
01549                                 if (_edge_isBoundary(e)) {
01550                                         VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
01551                                         numBoundary++;
01552                                 }
01553                         }
01554 
01555                         VertDataCopy(nCo, co);
01556                         VertDataMulN(nCo, 0.75f);
01557                         VertDataMulN(r, 0.25f/numBoundary);
01558                         VertDataAdd(nCo, r);
01559                 } else {
01560                         int cornerIdx = (1 + (1<<(curLvl))) - 2;
01561                         int numEdges = 0, numFaces = 0;
01562 
01563                         VertDataZero(q);
01564                         for (j=0; j<v->numFaces; j++) {
01565                                 CCGFace *f = v->faces[j];
01566                                 VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx));
01567                                 numFaces++;
01568                         }
01569                         VertDataMulN(q, 1.0f/numFaces);
01570                         VertDataZero(r);
01571                         for (j=0; j<v->numEdges; j++) {
01572                                 CCGEdge *e = v->edges[j];
01573                                 VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize));
01574                                 numEdges++;
01575                         }
01576                         VertDataMulN(r, 1.0f/numEdges);
01577 
01578                         VertDataCopy(nCo, co);
01579                         VertDataMulN(nCo, numEdges-2.0f);
01580                         VertDataAdd(nCo, q);
01581                         VertDataAdd(nCo, r);
01582                         VertDataMulN(nCo, 1.0f/numEdges);
01583                 }
01584 
01585                 if ((sharpCount>1 && v->numFaces) || seam) {
01586                         VertDataZero(q);
01587 
01588                         if (seam) {
01589                                 avgSharpness = 1.0f;
01590                                 sharpCount = seamEdges;
01591                                 allSharp = 1;
01592                         }
01593 
01594                         for (j=0; j<v->numEdges; j++) {
01595                                 CCGEdge *e = v->edges[j];
01596                                 float sharpness = EDGE_getSharpness(e, curLvl);
01597 
01598                                 if (seam) {
01599                                         if (_edge_isBoundary(e))
01600                                                 VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
01601                                 } else if (sharpness != 0.0f) {
01602                                         VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
01603                                 }
01604                         }
01605 
01606                         VertDataMulN(q, (float) 1/sharpCount);
01607 
01608                         if (sharpCount!=2 || allSharp) {
01609                                         // q = q + (co-q)*avgSharpness
01610                                 VertDataCopy(r, co);
01611                                 VertDataSub(r, q);
01612                                 VertDataMulN(r, avgSharpness);
01613                                 VertDataAdd(q, r);
01614                         }
01615 
01616                                 // r = co*.75 + q*.25
01617                         VertDataCopy(r, co);
01618                         VertDataMulN(r, .75f);
01619                         VertDataMulN(q, .25f);
01620                         VertDataAdd(r, q);
01621 
01622                                 // nCo = nCo  + (r-nCo)*avgSharpness
01623                         VertDataSub(r, nCo);
01624                         VertDataMulN(r, avgSharpness);
01625                         VertDataAdd(nCo, r);
01626                 }
01627         }
01628 
01629                 /* exterior edge interior shift
01630                  *  o old exterior edge midpoints (shifting)
01631                  *  o old exterior edge midpoints
01632                  *  o new interior face midpoints
01633                  */
01634         for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
01635                 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
01636                 float sharpness = EDGE_getSharpness(e, curLvl);
01637                 int sharpCount = 0;
01638                 float avgSharpness = 0.0;
01639                 int x, j;
01640 
01641                 if (sharpness!=0.0f) {
01642                         sharpCount = 2;
01643                         avgSharpness += sharpness;
01644 
01645                         if (avgSharpness > 1.0f) {
01646                                 avgSharpness = 1.0f;
01647                         }
01648                 } else {
01649                         sharpCount = 0;
01650                         avgSharpness = 0;
01651                 }
01652 
01653                 if (_edge_isBoundary(e) && (!e->numFaces || sharpCount<2)) {
01654                         for (x=1; x<edgeSize-1; x++) {
01655                                 int fx = x*2;
01656                                 void *co = EDGE_getCo(e, curLvl, x);
01657                                 void *nCo = EDGE_getCo(e, nextLvl, fx);
01658                                 VertDataCopy(r, EDGE_getCo(e, curLvl, x-1));
01659                                 VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
01660                                 VertDataMulN(r, 0.5f);
01661                                 VertDataCopy(nCo, co);
01662                                 VertDataMulN(nCo, 0.75f);
01663                                 VertDataMulN(r, 0.25f);
01664                                 VertDataAdd(nCo, r);
01665                         }
01666                 } else {
01667                         for (x=1; x<edgeSize-1; x++) {
01668                                 int fx = x*2;
01669                                 void *co = EDGE_getCo(e, curLvl, x);
01670                                 void *nCo = EDGE_getCo(e, nextLvl, fx);
01671                                 int numFaces = 0;
01672 
01673                                 VertDataZero(q);
01674                                 VertDataZero(r);
01675                                 VertDataAdd(r, EDGE_getCo(e, curLvl, x-1));
01676                                 VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
01677                                 for (j=0; j<e->numFaces; j++) {
01678                                         CCGFace *f = e->faces[j];
01679                                         VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize));
01680                                         VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize));
01681 
01682                                         VertDataAdd(r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize));
01683                                         numFaces++;
01684                                 }
01685                                 VertDataMulN(q, 1.0f/(numFaces*2.0f));
01686                                 VertDataMulN(r, 1.0f/(2.0f + numFaces));
01687 
01688                                 VertDataCopy(nCo, co);
01689                                 VertDataMulN(nCo, (float) numFaces);
01690                                 VertDataAdd(nCo, q);
01691                                 VertDataAdd(nCo, r);
01692                                 VertDataMulN(nCo, 1.0f/(2+numFaces));
01693 
01694                                 if (sharpCount==2) {
01695                                         VertDataCopy(q, co);
01696                                         VertDataMulN(q, 6.0f);
01697                                         VertDataAdd(q, EDGE_getCo(e, curLvl, x-1));
01698                                         VertDataAdd(q, EDGE_getCo(e, curLvl, x+1));
01699                                         VertDataMulN(q, 1/8.0f);
01700 
01701                                         VertDataSub(q, nCo);
01702                                         VertDataMulN(q, avgSharpness);
01703                                         VertDataAdd(nCo, q);
01704                                 }
01705                         }
01706                 }
01707         }
01708 
01709         #pragma omp parallel private(ptrIdx) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT)
01710         {
01711                 void *q, *r;
01712 
01713                 #pragma omp critical
01714                 {
01715                         q = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf q");
01716                         r = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf r");
01717                 }
01718 
01719                 #pragma omp for schedule(static)
01720                 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
01721                         CCGFace *f = (CCGFace*) effectedF[ptrIdx];
01722                         int S, x, y;
01723 
01724                                 /* interior center point shift
01725                                  *  o old face center point (shifting)
01726                                  *  o old interior edge points
01727                                  *  o new interior face midpoints
01728                                  */
01729                         VertDataZero(q);
01730                         for (S=0; S<f->numVerts; S++) {
01731                                 VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1));
01732                         }
01733                         VertDataMulN(q, 1.0f/f->numVerts);
01734                         VertDataZero(r);
01735                         for (S=0; S<f->numVerts; S++) {
01736                                 VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1));
01737                         }
01738                         VertDataMulN(r, 1.0f/f->numVerts);
01739 
01740                         VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f);
01741                         VertDataAdd(FACE_getCenterData(f), q);
01742                         VertDataAdd(FACE_getCenterData(f), r);
01743                         VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
01744 
01745                         for (S=0; S<f->numVerts; S++) {
01746                                         /* interior face shift
01747                                          *  o old interior face point (shifting)
01748                                          *  o new interior edge midpoints
01749                                          *  o new interior face midpoints
01750                                          */
01751                                 for (x=1; x<gridSize-1; x++) {
01752                                         for (y=1; y<gridSize-1; y++) {
01753                                                 int fx = x*2;
01754                                                 int fy = y*2;
01755                                                 void *co = FACE_getIFCo(f, curLvl, S, x, y);
01756                                                 void *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
01757                                                 
01758                                                 VertDataAvg4(q, FACE_getIFCo(f, nextLvl, S, fx-1, fy-1),
01759                                                         FACE_getIFCo(f, nextLvl, S, fx+1, fy-1),
01760                                                         FACE_getIFCo(f, nextLvl, S, fx+1, fy+1),
01761                                                         FACE_getIFCo(f, nextLvl, S, fx-1, fy+1));
01762 
01763                                                 VertDataAvg4(r, FACE_getIFCo(f, nextLvl, S, fx-1, fy+0),
01764                                                         FACE_getIFCo(f, nextLvl, S, fx+1, fy+0),
01765                                                         FACE_getIFCo(f, nextLvl, S, fx+0, fy-1),
01766                                                         FACE_getIFCo(f, nextLvl, S, fx+0, fy+1));
01767 
01768                                                 VertDataCopy(nCo, co);
01769                                                 VertDataSub(nCo, q);
01770                                                 VertDataMulN(nCo, 0.25f);
01771                                                 VertDataAdd(nCo, r);
01772                                         }
01773                                 }
01774 
01775                                         /* interior edge interior shift
01776                                          *  o old interior edge point (shifting)
01777                                          *  o new interior edge midpoints
01778                                          *  o new interior face midpoints
01779                                          */
01780                                 for (x=1; x<gridSize-1; x++) {
01781                                         int fx = x*2;
01782                                         void *co = FACE_getIECo(f, curLvl, S, x);
01783                                         void *nCo = FACE_getIECo(f, nextLvl, S, fx);
01784                                         
01785                                         VertDataAvg4(q, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx-1),
01786                                                 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1),
01787                                                 FACE_getIFCo(f, nextLvl, S, fx+1, +1),
01788                                                 FACE_getIFCo(f, nextLvl, S, fx-1, +1));
01789 
01790                                         VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1),
01791                                                 FACE_getIECo(f, nextLvl, S, fx+1),
01792                                                 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx),
01793                                                 FACE_getIFCo(f, nextLvl, S, fx, 1));
01794 
01795                                         VertDataCopy(nCo, co);
01796                                         VertDataSub(nCo, q);
01797                                         VertDataMulN(nCo, 0.25f);
01798                                         VertDataAdd(nCo, r);
01799                                 }
01800                         }
01801                 }
01802 
01803                 #pragma omp critical
01804                 {
01805                         MEM_freeN(q);
01806                         MEM_freeN(r);
01807                 }
01808         }
01809 
01810                 /* copy down */
01811         edgeSize = 1 + (1<<(nextLvl));
01812         gridSize = 1 + (1<<((nextLvl)-1));
01813         cornerIdx = gridSize-1;
01814 
01815         #pragma omp parallel for private(i) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT)
01816         for (i=0; i<numEffectedE; i++) {
01817                 CCGEdge *e = effectedE[i];
01818                 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
01819                 VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl));
01820         }
01821 
01822         #pragma omp parallel for private(i) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT)
01823         for (i=0; i<numEffectedF; i++) {
01824                 CCGFace *f = effectedF[i];
01825                 int S, x;
01826 
01827                 for (S=0; S<f->numVerts; S++) {
01828                         CCGEdge *e = FACE_getEdges(f)[S];
01829                         CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
01830 
01831                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
01832                         VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
01833                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
01834                         VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx));
01835                         for (x=1; x<gridSize-1; x++) {
01836                                 void *co = FACE_getIECo(f, nextLvl, S, x);
01837                                 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co);
01838                                 VertDataCopy(FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 0, x), co);
01839                         }
01840                         for (x=0; x<gridSize-1; x++) {
01841                                 int eI = gridSize-1-x;
01842                                 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
01843                                 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
01844                         }
01845                 }
01846         }
01847 }
01848 
01849 
01850 static void ccgSubSurf__sync(CCGSubSurf *ss) {
01851         CCGVert **effectedV;
01852         CCGEdge **effectedE;
01853         CCGFace **effectedF;
01854         int numEffectedV, numEffectedE, numEffectedF;
01855         int subdivLevels = ss->subdivLevels;
01856         int vertDataSize = ss->meshIFC.vertDataSize;
01857         int i, j, ptrIdx, S;
01858         int curLvl, nextLvl;
01859         void *q = ss->q, *r = ss->r;
01860 
01861         effectedV = MEM_mallocN(sizeof(*effectedV)*ss->vMap->numEntries, "CCGSubsurf effectedV");
01862         effectedE = MEM_mallocN(sizeof(*effectedE)*ss->eMap->numEntries, "CCGSubsurf effectedE");
01863         effectedF = MEM_mallocN(sizeof(*effectedF)*ss->fMap->numEntries, "CCGSubsurf effectedF");
01864         numEffectedV = numEffectedE = numEffectedF = 0;
01865         for (i=0; i<ss->vMap->curSize; i++) {
01866                 CCGVert *v = (CCGVert*) ss->vMap->buckets[i];
01867                 for (; v; v = v->next) {
01868                         if (v->flags&Vert_eEffected) {
01869                                 effectedV[numEffectedV++] = v;
01870 
01871                                 for (j=0; j<v->numEdges; j++) {
01872                                         CCGEdge *e = v->edges[j];
01873                                         if (!(e->flags&Edge_eEffected)) {
01874                                                 effectedE[numEffectedE++] = e;
01875                                                 e->flags |= Edge_eEffected;
01876                                         }
01877                                 }
01878 
01879                                 for (j=0; j<v->numFaces; j++) {
01880                                         CCGFace *f = v->faces[j];
01881                                         if (!(f->flags&Face_eEffected)) {
01882                                                 effectedF[numEffectedF++] = f;
01883                                                 f->flags |= Face_eEffected;
01884                                         }
01885                                 }
01886                         }
01887                 }
01888         }
01889 
01890         curLvl = 0;
01891         nextLvl = curLvl+1;
01892 
01893         for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
01894                 CCGFace *f = effectedF[ptrIdx];
01895                 void *co = FACE_getCenterData(f);
01896                 VertDataZero(co);
01897                 for (i=0; i<f->numVerts; i++) {
01898                         VertDataAdd(co, VERT_getCo(FACE_getVerts(f)[i], curLvl));
01899                 }
01900                 VertDataMulN(co, 1.0f/f->numVerts);
01901 
01902                 f->flags = 0;
01903         }
01904         for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
01905                 CCGEdge *e = effectedE[ptrIdx];
01906                 void *co = EDGE_getCo(e, nextLvl, 1);
01907                 float sharpness = EDGE_getSharpness(e, curLvl);
01908 
01909                 if (_edge_isBoundary(e) || sharpness >= 1.0f) {
01910                         VertDataCopy(co, VERT_getCo(e->v0, curLvl));
01911                         VertDataAdd(co, VERT_getCo(e->v1, curLvl));
01912                         VertDataMulN(co, 0.5f);
01913                 } else {
01914                         int numFaces = 0;
01915                         VertDataCopy(q, VERT_getCo(e->v0, curLvl));
01916                         VertDataAdd(q, VERT_getCo(e->v1, curLvl));
01917                         for (i=0; i<e->numFaces; i++) {
01918                                 CCGFace *f = e->faces[i];
01919                                 VertDataAdd(q, FACE_getCenterData(f));
01920                                 numFaces++;
01921                         }
01922                         VertDataMulN(q, 1.0f/(2.0f+numFaces));
01923 
01924                         VertDataCopy(r, VERT_getCo(e->v0, curLvl));
01925                         VertDataAdd(r, VERT_getCo(e->v1, curLvl));
01926                         VertDataMulN(r, 0.5f);
01927 
01928                         VertDataCopy(co, q);
01929                         VertDataSub(r, q);
01930                         VertDataMulN(r, sharpness);
01931                         VertDataAdd(co, r);
01932                 }
01933 
01934                 // edge flags cleared later
01935         }
01936         for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
01937                 CCGVert *v = effectedV[ptrIdx];
01938                 void *co = VERT_getCo(v, curLvl);
01939                 void *nCo = VERT_getCo(v, nextLvl);
01940                 int sharpCount = 0, allSharp = 1;
01941                 float avgSharpness = 0.0;
01942                 int seam = VERT_seam(v), seamEdges = 0;
01943 
01944                 for (i=0; i<v->numEdges; i++) {
01945                         CCGEdge *e = v->edges[i];
01946                         float sharpness = EDGE_getSharpness(e, curLvl);
01947 
01948                         if (seam && _edge_isBoundary(e))
01949                                 seamEdges++;
01950 
01951                         if (sharpness!=0.0f) {
01952                                 sharpCount++;
01953                                 avgSharpness += sharpness;
01954                         } else {
01955                                 allSharp = 0;
01956                         }
01957                 }
01958 
01959                 if(sharpCount) {
01960                         avgSharpness /= sharpCount;
01961                         if (avgSharpness > 1.0f) {
01962                                 avgSharpness = 1.0f;
01963                         }
01964                 }
01965 
01966                 if (seamEdges < 2 || seamEdges != v->numEdges)
01967                         seam = 0;
01968 
01969                 if (!v->numEdges) {
01970                         VertDataCopy(nCo, co);
01971                 } else if (_vert_isBoundary(v)) {
01972                         int numBoundary = 0;
01973 
01974                         VertDataZero(r);
01975                         for (i=0; i<v->numEdges; i++) {
01976                                 CCGEdge *e = v->edges[i];
01977                                 if (_edge_isBoundary(e)) {
01978                                         VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
01979                                         numBoundary++;
01980                                 }
01981                         }
01982                         VertDataCopy(nCo, co);
01983                         VertDataMulN(nCo, 0.75f);
01984                         VertDataMulN(r, 0.25f/numBoundary);
01985                         VertDataAdd(nCo, r);
01986                 } else {
01987                         int numEdges = 0, numFaces = 0;
01988 
01989                         VertDataZero(q);
01990                         for (i=0; i<v->numFaces; i++) {
01991                                 CCGFace *f = v->faces[i];
01992                                 VertDataAdd(q, FACE_getCenterData(f));
01993                                 numFaces++;
01994                         }
01995                         VertDataMulN(q, 1.0f/numFaces);
01996                         VertDataZero(r);
01997                         for (i=0; i<v->numEdges; i++) {
01998                                 CCGEdge *e = v->edges[i];
01999                                 VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
02000                                 numEdges++;
02001                         }
02002                         VertDataMulN(r, 1.0f/numEdges);
02003 
02004                         VertDataCopy(nCo, co);
02005                         VertDataMulN(nCo, numEdges-2.0f);
02006                         VertDataAdd(nCo, q);
02007                         VertDataAdd(nCo, r);
02008                         VertDataMulN(nCo, 1.0f/numEdges);
02009                 }
02010 
02011                 if (sharpCount>1 || seam) {
02012                         VertDataZero(q);
02013 
02014                         if (seam) {
02015                                 avgSharpness = 1.0f;
02016                                 sharpCount = seamEdges;
02017                                 allSharp = 1;
02018                         }
02019 
02020                         for (i=0; i<v->numEdges; i++) {
02021                                 CCGEdge *e = v->edges[i];
02022                                 float sharpness = EDGE_getSharpness(e, curLvl);
02023 
02024                                 if (seam) {
02025                                         if (_edge_isBoundary(e)) {
02026                                                 CCGVert *oV = _edge_getOtherVert(e, v);
02027                                                 VertDataAdd(q, VERT_getCo(oV, curLvl));
02028                                         }
02029                                 } else if (sharpness != 0.0f) {
02030                                         CCGVert *oV = _edge_getOtherVert(e, v);
02031                                         VertDataAdd(q, VERT_getCo(oV, curLvl));
02032                                 }
02033                         }
02034 
02035                         VertDataMulN(q, (float) 1/sharpCount);
02036 
02037                         if (sharpCount!=2 || allSharp) {
02038                                         // q = q + (co-q)*avgSharpness
02039                                 VertDataCopy(r, co);
02040                                 VertDataSub(r, q);
02041                                 VertDataMulN(r, avgSharpness);
02042                                 VertDataAdd(q, r);
02043                         }
02044 
02045                                 // r = co*.75 + q*.25
02046                         VertDataCopy(r, co);
02047                         VertDataMulN(r, 0.75f);
02048                         VertDataMulN(q, 0.25f);
02049                         VertDataAdd(r, q);
02050 
02051                                 // nCo = nCo  + (r-nCo)*avgSharpness
02052                         VertDataSub(r, nCo);
02053                         VertDataMulN(r, avgSharpness);
02054                         VertDataAdd(nCo, r);
02055                 }
02056 
02057                 // vert flags cleared later
02058         }
02059 
02060         if (ss->useAgeCounts) {
02061                 for (i=0; i<numEffectedV; i++) {
02062                         CCGVert *v = effectedV[i];
02063                         byte *userData = ccgSubSurf_getVertUserData(ss, v);
02064                         *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
02065                 }
02066 
02067                 for (i=0; i<numEffectedE; i++) {
02068                         CCGEdge *e = effectedE[i];
02069                         byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
02070                         *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
02071                 }
02072 
02073                 for (i=0; i<numEffectedF; i++) {
02074                         CCGFace *f = effectedF[i];
02075                         byte *userData = ccgSubSurf_getFaceUserData(ss, f);
02076                         *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
02077                 }
02078         }
02079 
02080         for (i=0; i<numEffectedE; i++) {
02081                 CCGEdge *e = effectedE[i];
02082                 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
02083                 VertDataCopy(EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl));
02084         }
02085         for (i=0; i<numEffectedF; i++) {
02086                 CCGFace *f = effectedF[i];
02087                 for (S=0; S<f->numVerts; S++) {
02088                         CCGEdge *e = FACE_getEdges(f)[S];
02089                         CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
02090 
02091                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
02092                         VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
02093                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
02094                         VertDataCopy(FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1));
02095 
02096                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 0), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize));
02097                         VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 1), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize));
02098                 }
02099         }
02100 
02101         for (curLvl=1; curLvl<subdivLevels; curLvl++) {
02102                 ccgSubSurf__calcSubdivLevel(ss,
02103                         effectedV, effectedE, effectedF,
02104                         numEffectedV, numEffectedE, numEffectedF, curLvl);
02105         }
02106 
02107         if (ss->calcVertNormals)
02108                 ccgSubSurf__calcVertNormals(ss,
02109                         effectedV, effectedE, effectedF,
02110                         numEffectedV, numEffectedE, numEffectedF);
02111 
02112         for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
02113                 CCGVert *v = effectedV[ptrIdx];
02114                 v->flags = 0;
02115         }
02116         for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
02117                 CCGEdge *e = effectedE[ptrIdx];
02118                 e->flags = 0;
02119         }
02120 
02121         MEM_freeN(effectedF);
02122         MEM_freeN(effectedE);
02123         MEM_freeN(effectedV);
02124 }
02125 
02126 static void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces)
02127 {
02128         CCGFace **array;
02129         int i, num;
02130 
02131         if(!*faces) {
02132                 array = MEM_mallocN(sizeof(*array)*ss->fMap->numEntries, "CCGSubsurf allFaces");
02133                 num = 0;
02134                 for (i=0; i<ss->fMap->curSize; i++) {
02135                         CCGFace *f = (CCGFace*) ss->fMap->buckets[i];
02136 
02137                         for (; f; f = f->next)
02138                                 array[num++] = f;
02139                 }
02140 
02141                 *faces = array;
02142                 *numFaces = num;
02143                 *freeFaces= 1;
02144         }
02145         else
02146                 *freeFaces= 0;
02147 }
02148 
02149 static void ccgSubSurf__effectedFaceNeighbours(CCGSubSurf *ss, CCGFace **faces, int numFaces, CCGVert ***verts, int *numVerts, CCGEdge ***edges, int *numEdges)
02150 {
02151         CCGVert **arrayV;
02152         CCGEdge **arrayE;
02153         int numV, numE, i, j;
02154 
02155         arrayV = MEM_mallocN(sizeof(*arrayV)*ss->vMap->numEntries, "CCGSubsurf arrayV");
02156         arrayE = MEM_mallocN(sizeof(*arrayE)*ss->eMap->numEntries, "CCGSubsurf arrayV");
02157         numV = numE = 0;
02158 
02159         for (i=0; i<numFaces; i++) {
02160                 CCGFace *f = faces[i];
02161                 f->flags |= Face_eEffected;
02162         }
02163 
02164         for (i=0; i<ss->vMap->curSize; i++) {
02165                 CCGVert *v = (CCGVert*) ss->vMap->buckets[i];
02166 
02167                 for (; v; v = v->next) {
02168                         for(j=0; j<v->numFaces; j++)
02169                                 if(!(v->faces[j]->flags & Face_eEffected))
02170                                         break;
02171                         
02172                         if(j == v->numFaces) {
02173                                 arrayV[numV++] = v;
02174                                 v->flags |= Vert_eEffected;
02175                         }
02176                 }
02177         }
02178 
02179         for (i=0; i<ss->eMap->curSize; i++) {
02180                 CCGEdge *e = (CCGEdge*) ss->eMap->buckets[i];
02181 
02182                 for (; e; e = e->next) {
02183                         for(j=0; j<e->numFaces; j++)
02184                                 if(!(e->faces[j]->flags & Face_eEffected))
02185                                         break;
02186                         
02187                         if(j == e->numFaces) {
02188                                 e->flags |= Edge_eEffected;
02189                                 arrayE[numE++] = e;
02190                         }
02191                 }
02192         }
02193 
02194         *verts = arrayV;
02195         *numVerts = numV;
02196         *edges = arrayE;
02197         *numEdges = numE;
02198 }
02199 
02200 /* copy face grid coordinates to other places */
02201 CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
02202 {
02203         int i, S, x, gridSize, cornerIdx, subdivLevels;
02204         int vertDataSize = ss->meshIFC.vertDataSize, freeF;
02205 
02206         subdivLevels = ss->subdivLevels;
02207         lvl = (lvl)? lvl: subdivLevels;
02208         gridSize = 1 + (1<<(lvl-1));
02209         cornerIdx = gridSize-1;
02210 
02211         ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
02212 
02213         for (i=0; i<numEffectedF; i++) {
02214                 CCGFace *f = effectedF[i];
02215 
02216                 for (S=0; S<f->numVerts; S++) {
02217                         CCGEdge *e = FACE_getEdges(f)[S];
02218                         CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
02219 
02220                         VertDataCopy(FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0));
02221                         VertDataCopy(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx));
02222 
02223                         for (x=0; x<gridSize; x++)
02224                                 VertDataCopy(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0));
02225 
02226                         for (x=0; x<gridSize; x++) {
02227                                 int eI = gridSize-1-x;
02228                                 VertDataCopy(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, cornerIdx, x));
02229                                 VertDataCopy(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, x, cornerIdx));
02230                         }
02231                 }
02232         }
02233 
02234         if(freeF) MEM_freeN(effectedF);
02235 
02236         return eCCGError_None;
02237 }
02238 
02239 /* copy other places to face grid coordinates */
02240 CCGError ccgSubSurf_updateToFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
02241 {
02242         int i, S, x, gridSize, cornerIdx, subdivLevels;
02243         int vertDataSize = ss->meshIFC.vertDataSize, freeF;
02244 
02245         subdivLevels = ss->subdivLevels;
02246         lvl = (lvl)? lvl: subdivLevels;
02247         gridSize = 1 + (1<<(lvl-1));
02248         cornerIdx = gridSize-1;
02249 
02250         ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
02251 
02252         for (i=0; i<numEffectedF; i++) {
02253                 CCGFace *f = effectedF[i];
02254 
02255                 for (S=0; S<f->numVerts; S++) {
02256                         int prevS = (S+f->numVerts-1)%f->numVerts;
02257                         CCGEdge *e = FACE_getEdges(f)[S];
02258                         CCGEdge *prevE = FACE_getEdges(f)[prevS];
02259 
02260                         for (x=0; x<gridSize; x++) {
02261                                 int eI = gridSize-1-x;
02262                                 VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize));
02263                                 VertDataCopy(FACE_getIFCo(f, lvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize));
02264                         }
02265 
02266                         for (x=1; x<gridSize-1; x++) {
02267                                 VertDataCopy(FACE_getIFCo(f, lvl, S, 0, x), FACE_getIECo(f, lvl, prevS, x));
02268                                 VertDataCopy(FACE_getIFCo(f, lvl, S, x, 0), FACE_getIECo(f, lvl, S, x));
02269                         }
02270 
02271                         VertDataCopy(FACE_getIFCo(f, lvl, S, 0, 0), FACE_getCenterData(f));
02272                         VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], lvl));
02273                 }
02274         }
02275 
02276         if(freeF) MEM_freeN(effectedF);
02277 
02278         return eCCGError_None;
02279 }
02280 
02281 /* stitch together face grids, averaging coordinates at edges
02282    and vertices, for multires displacements */
02283 CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
02284 {
02285         CCGVert **effectedV;
02286         CCGEdge **effectedE;
02287         int numEffectedV, numEffectedE, freeF;
02288         int i, S, x, gridSize, cornerIdx, subdivLevels, edgeSize;
02289         int vertDataSize = ss->meshIFC.vertDataSize;
02290 
02291         subdivLevels = ss->subdivLevels;
02292         lvl = (lvl)? lvl: subdivLevels;
02293         gridSize = 1 + (1<<(lvl-1));
02294         edgeSize = 1 + (1<<lvl);
02295         cornerIdx = gridSize-1;
02296 
02297         ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
02298         ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
02299                 &effectedV, &numEffectedV, &effectedE, &numEffectedE);
02300 
02301         /* zero */
02302         for (i=0; i<numEffectedV; i++) {
02303                 CCGVert *v = effectedV[i];
02304                 VertDataZero(VERT_getCo(v, lvl));
02305         }
02306 
02307         for (i=0; i<numEffectedE; i++) {
02308                 CCGEdge *e = effectedE[i];
02309 
02310                 for (x=0; x<edgeSize; x++)
02311                         VertDataZero(EDGE_getCo(e, lvl, x));
02312         }
02313 
02314         /* add */
02315         for (i=0; i<numEffectedF; i++) {
02316                 CCGFace *f = effectedF[i];
02317 
02318                 VertDataZero(FACE_getCenterData(f));
02319 
02320                 for (S=0; S<f->numVerts; S++)
02321                         for (x=0; x<gridSize; x++)
02322                                 VertDataZero(FACE_getIECo(f, lvl, S, x));
02323 
02324                 for (S=0; S<f->numVerts; S++) {
02325                         int prevS = (S+f->numVerts-1)%f->numVerts;
02326                         CCGEdge *e = FACE_getEdges(f)[S];
02327                         CCGEdge *prevE = FACE_getEdges(f)[prevS];
02328 
02329                         VertDataAdd(FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0));
02330                         if (FACE_getVerts(f)[S]->flags&Vert_eEffected)
02331                                 VertDataAdd(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx));
02332 
02333                         for (x=1; x<gridSize-1; x++) {
02334                                 VertDataAdd(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0));
02335                                 VertDataAdd(FACE_getIECo(f, lvl, prevS, x), FACE_getIFCo(f, lvl, S, 0, x));
02336                         }
02337 
02338                         for (x=0; x<gridSize-1; x++) {
02339                                 int eI = gridSize-1-x;
02340                                 if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
02341                                         VertDataAdd(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, cornerIdx, x));
02342                                 if (FACE_getEdges(f)[prevS]->flags&Edge_eEffected)
02343                                         if(x != 0)
02344                                                 VertDataAdd(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, x, cornerIdx));
02345                         }
02346                 }
02347         }
02348 
02349         /* average */
02350         for (i=0; i<numEffectedV; i++) {
02351                 CCGVert *v = effectedV[i];
02352                 VertDataMulN(VERT_getCo(v, lvl), 1.0f/v->numFaces);
02353         }
02354 
02355         for (i=0; i<numEffectedE; i++) {
02356                 CCGEdge *e = effectedE[i];
02357 
02358                 VertDataCopy(EDGE_getCo(e, lvl, 0), VERT_getCo(e->v0, lvl));
02359                 VertDataCopy(EDGE_getCo(e, lvl, edgeSize-1), VERT_getCo(e->v1, lvl));
02360 
02361                 for (x=1; x<edgeSize-1; x++)
02362                         VertDataMulN(EDGE_getCo(e, lvl, x), 1.0f/e->numFaces);
02363         }
02364 
02365         /* copy */
02366         for (i=0; i<numEffectedF; i++) {
02367                 CCGFace *f = effectedF[i];
02368 
02369                 VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
02370 
02371                 for (S=0; S<f->numVerts; S++)
02372                         for (x=1; x<gridSize-1; x++)
02373                                 VertDataMulN(FACE_getIECo(f, lvl, S, x), 0.5f);
02374 
02375                 for (S=0; S<f->numVerts; S++) {
02376                         int prevS = (S+f->numVerts-1)%f->numVerts;
02377                         CCGEdge *e = FACE_getEdges(f)[S];
02378                         CCGEdge *prevE = FACE_getEdges(f)[prevS];
02379 
02380                         VertDataCopy(FACE_getIFCo(f, lvl, S, 0, 0), FACE_getCenterData(f));
02381                         VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], lvl));
02382 
02383                         for (x=1; x<gridSize-1; x++) {
02384                                 VertDataCopy(FACE_getIFCo(f, lvl, S, x, 0), FACE_getIECo(f, lvl, S, x));
02385                                 VertDataCopy(FACE_getIFCo(f, lvl, S, 0, x), FACE_getIECo(f, lvl, prevS, x));
02386                         }
02387 
02388                         for (x=0; x<gridSize-1; x++) {
02389                                 int eI = gridSize-1-x;
02390                                 VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize));
02391                                 VertDataCopy(FACE_getIFCo(f, lvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize));
02392                         }
02393 
02394                         VertDataCopy(FACE_getIECo(f, lvl, S, 0), FACE_getCenterData(f));
02395                         VertDataCopy(FACE_getIECo(f, lvl, S, gridSize-1), FACE_getIFCo(f, lvl, S, gridSize-1, 0));
02396                 }
02397         }
02398 
02399         for (i=0; i<numEffectedV; i++)
02400                 effectedV[i]->flags = 0;
02401         for (i=0; i<numEffectedE; i++)
02402                 effectedE[i]->flags = 0;
02403         for (i=0; i<numEffectedF; i++)
02404                 effectedF[i]->flags = 0;
02405 
02406         MEM_freeN(effectedE);
02407         MEM_freeN(effectedV);
02408         if(freeF) MEM_freeN(effectedF);
02409 
02410         return eCCGError_None;
02411 }
02412 
02413 /* update normals for specified faces */
02414 CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF) {
02415         CCGVert **effectedV;
02416         CCGEdge **effectedE;
02417         int i, numEffectedV, numEffectedE, freeF;
02418 
02419         ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
02420         ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
02421                 &effectedV, &numEffectedV, &effectedE, &numEffectedE);
02422 
02423         if (ss->calcVertNormals)
02424                 ccgSubSurf__calcVertNormals(ss,
02425                         effectedV, effectedE, effectedF,
02426                         numEffectedV, numEffectedE, numEffectedF);
02427 
02428         for (i=0; i<numEffectedV; i++)
02429                 effectedV[i]->flags = 0;
02430         for (i=0; i<numEffectedE; i++)
02431                 effectedE[i]->flags = 0;
02432         for (i=0; i<numEffectedF; i++)
02433                 effectedF[i]->flags = 0;
02434 
02435         MEM_freeN(effectedE);
02436         MEM_freeN(effectedV);
02437         if(freeF) MEM_freeN(effectedF);
02438 
02439         return eCCGError_None;
02440 }
02441 
02442 /* compute subdivision levels from a given starting point, used by
02443    multires subdivide/propagate, by filling in coordinates at a
02444    certain level, and then subdividing that up to the highest level */
02445 CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
02446 {
02447         CCGVert **effectedV;
02448         CCGEdge **effectedE;
02449         int numEffectedV, numEffectedE, freeF, i;
02450         int curLvl, subdivLevels = ss->subdivLevels;
02451 
02452         ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
02453         ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
02454                 &effectedV, &numEffectedV, &effectedE, &numEffectedE);
02455 
02456         for (curLvl=lvl; curLvl<subdivLevels; curLvl++) {
02457                 ccgSubSurf__calcSubdivLevel(ss,
02458                         effectedV, effectedE, effectedF,
02459                         numEffectedV, numEffectedE, numEffectedF, curLvl);
02460         }
02461 
02462         for (i=0; i<numEffectedV; i++)
02463                 effectedV[i]->flags = 0;
02464         for (i=0; i<numEffectedE; i++)
02465                 effectedE[i]->flags = 0;
02466         for (i=0; i<numEffectedF; i++)
02467                 effectedF[i]->flags = 0;
02468 
02469         MEM_freeN(effectedE);
02470         MEM_freeN(effectedV);
02471         if(freeF) MEM_freeN(effectedF);
02472 
02473         return eCCGError_None;
02474 }
02475 
02476 #undef VERT_getCo
02477 #undef EDGE_getCo
02478 #undef FACE_getIECo
02479 #undef FACE_getIFCo
02480 
02481 /*** External API accessor functions ***/
02482 
02483 int ccgSubSurf_getNumVerts(CCGSubSurf *ss) {
02484         return ss->vMap->numEntries;
02485 }
02486 int ccgSubSurf_getNumEdges(CCGSubSurf *ss) {
02487         return ss->eMap->numEntries;
02488 }
02489 int ccgSubSurf_getNumFaces(CCGSubSurf *ss) {
02490         return ss->fMap->numEntries;
02491 }
02492 
02493 CCGVert *ccgSubSurf_getVert(CCGSubSurf *ss, CCGVertHDL v) {
02494         return (CCGVert*) _ehash_lookup(ss->vMap, v);
02495 }
02496 CCGEdge *ccgSubSurf_getEdge(CCGSubSurf *ss, CCGEdgeHDL e) {
02497         return (CCGEdge*) _ehash_lookup(ss->eMap, e);
02498 }
02499 CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f) {
02500         return (CCGFace*) _ehash_lookup(ss->fMap, f);
02501 }
02502 
02503 int ccgSubSurf_getSubdivisionLevels(CCGSubSurf *ss) {
02504         return ss->subdivLevels;
02505 }
02506 int ccgSubSurf_getEdgeSize(CCGSubSurf *ss) {
02507         return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels);
02508 }
02509 int ccgSubSurf_getEdgeLevelSize(CCGSubSurf *ss, int level) {
02510         if (level<1 || level>ss->subdivLevels) {
02511                 return -1;
02512         } else {
02513                 return 1 + (1<<level);
02514         }
02515 }
02516 int ccgSubSurf_getGridSize(CCGSubSurf *ss) {
02517         return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels);
02518 }
02519 int ccgSubSurf_getGridLevelSize(CCGSubSurf *ss, int level) {
02520         if (level<1 || level>ss->subdivLevels) {
02521                 return -1;
02522         } else {
02523                 return 1 + (1<<(level-1));
02524         }
02525 }
02526 
02527 /* Vert accessors */
02528 
02529 CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v) {
02530         return v->vHDL;
02531 }
02532 int ccgSubSurf_getVertAge(CCGSubSurf *ss, CCGVert *v) {
02533         if (ss->useAgeCounts) {
02534                 byte *userData = ccgSubSurf_getVertUserData(ss, v);
02535                 return ss->currentAge - *((int*) &userData[ss->vertUserAgeOffset]);
02536         } else {
02537                 return 0;
02538         }
02539 }
02540 void *ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v) {
02541         return VERT_getLevelData(v) + ss->meshIFC.vertDataSize*(ss->subdivLevels+1);
02542 }
02543 int ccgSubSurf_getVertNumFaces(CCGVert *v) {
02544         return v->numFaces;
02545 }
02546 CCGFace *ccgSubSurf_getVertFace(CCGVert *v, int index) {
02547         if (index<0 || index>=v->numFaces) {
02548                 return NULL;
02549         } else {
02550                 return v->faces[index];
02551         }
02552 }
02553 int ccgSubSurf_getVertNumEdges(CCGVert *v) {
02554         return v->numEdges;
02555 }
02556 CCGEdge *ccgSubSurf_getVertEdge(CCGVert *v, int index) {
02557         if (index<0 || index>=v->numEdges) {
02558                 return NULL;
02559         } else {
02560                 return v->edges[index];
02561         }
02562 }
02563 void *ccgSubSurf_getVertData(CCGSubSurf *ss, CCGVert *v) {
02564         return ccgSubSurf_getVertLevelData(ss, v, ss->subdivLevels);
02565 }
02566 void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level) {
02567         if (level<0 || level>ss->subdivLevels) {
02568                 return NULL;
02569         } else {
02570                 return _vert_getCo(v, level, ss->meshIFC.vertDataSize);
02571         }
02572 }
02573 
02574 /* Edge accessors */
02575 
02576 CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle(CCGEdge *e) {
02577         return e->eHDL;
02578 }
02579 int ccgSubSurf_getEdgeAge(CCGSubSurf *ss, CCGEdge *e) {
02580         if (ss->useAgeCounts) {
02581                 byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
02582                 return ss->currentAge - *((int*) &userData[ss->edgeUserAgeOffset]);
02583         } else {
02584                 return 0;
02585         }
02586 }
02587 void *ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e) {
02588         return EDGE_getLevelData(e) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1);
02589 }
02590 int ccgSubSurf_getEdgeNumFaces(CCGEdge *e) {
02591         return e->numFaces;
02592 }
02593 CCGFace *ccgSubSurf_getEdgeFace(CCGEdge *e, int index) {
02594         if (index<0 || index>=e->numFaces) {
02595                 return NULL;
02596         } else {
02597                 return e->faces[index];
02598         }
02599 }
02600 CCGVert *ccgSubSurf_getEdgeVert0(CCGEdge *e) {
02601         return e->v0;
02602 }
02603 CCGVert *ccgSubSurf_getEdgeVert1(CCGEdge *e) {
02604         return e->v1;
02605 }
02606 void *ccgSubSurf_getEdgeDataArray(CCGSubSurf *ss, CCGEdge *e) {
02607         return ccgSubSurf_getEdgeData(ss, e, 0);
02608 }
02609 void *ccgSubSurf_getEdgeData(CCGSubSurf *ss, CCGEdge *e, int x) {
02610         return ccgSubSurf_getEdgeLevelData(ss, e, x, ss->subdivLevels);
02611 }
02612 void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level) {
02613         if (level<0 || level>ss->subdivLevels) {
02614                 return NULL;
02615         } else {
02616                 return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
02617         }
02618 }
02619 float ccgSubSurf_getEdgeCrease(CCGEdge *e) {
02620         return e->crease;
02621 }
02622 
02623 /* Face accessors */
02624 
02625 CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *UNUSED(ss), CCGFace *f) {
02626         return f->fHDL;
02627 }
02628 int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) {
02629         if (ss->useAgeCounts) {
02630                 byte *userData = ccgSubSurf_getFaceUserData(ss, f);
02631                 return ss->currentAge - *((int*) &userData[ss->faceUserAgeOffset]);
02632         } else {
02633                 return 0;
02634         }
02635 }
02636 void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) {
02637         int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
02638         return FACE_getCenterData(f) + ss->meshIFC.vertDataSize *(1 + f->numVerts*maxGridSize + f->numVerts*maxGridSize*maxGridSize);
02639 }
02640 int ccgSubSurf_getFaceNumVerts(CCGFace *f) {
02641         return f->numVerts;
02642 }
02643 CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *UNUSED(ss), CCGFace *f, int index) {
02644         if (index<0 || index>=f->numVerts) {
02645                 return NULL;
02646         } else {
02647                 return FACE_getVerts(f)[index];
02648         }
02649 }
02650 CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *UNUSED(ss), CCGFace *f, int index) {
02651         if (index<0 || index>=f->numVerts) {
02652                 return NULL;
02653         } else {
02654                 return FACE_getEdges(f)[index];
02655         }
02656 }
02657 int ccgSubSurf_getFaceEdgeIndex(CCGFace *f, CCGEdge *e) {
02658         int i;
02659 
02660         for (i=0; i<f->numVerts; i++)
02661                 if (FACE_getEdges(f)[i]==e)
02662                         return i;
02663 
02664         return -1;
02665 }
02666 void *ccgSubSurf_getFaceCenterData(CCGFace *f) {
02667         return FACE_getCenterData(f);
02668 }
02669 void *ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
02670         return ccgSubSurf_getFaceGridEdgeData(ss, f, gridIndex, 0);
02671 }
02672 void *ccgSubSurf_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x) {
02673         return _face_getIECo(f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize);
02674 }
02675 void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
02676         return ccgSubSurf_getFaceGridData(ss, f, gridIndex, 0, 0);
02677 }
02678 void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y) {
02679         return _face_getIFCo(f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize);
02680 }
02681 
02682 /*** External API iterator functions ***/
02683 
02684 CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss) {
02685         return (CCGVertIterator*) _ehashIterator_new(ss->vMap);
02686 }
02687 CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss) {
02688         return (CCGEdgeIterator*) _ehashIterator_new(ss->eMap);
02689 }
02690 CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss) {
02691         return (CCGFaceIterator*) _ehashIterator_new(ss->fMap);
02692 }
02693 
02694 CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi) {
02695         return (CCGVert*) _ehashIterator_getCurrent((EHashIterator*) vi);
02696 }
02697 int ccgVertIterator_isStopped(CCGVertIterator *vi) {
02698         return _ehashIterator_isStopped((EHashIterator*) vi);
02699 }
02700 void ccgVertIterator_next(CCGVertIterator *vi) {
02701         _ehashIterator_next((EHashIterator*) vi); 
02702 }
02703 void ccgVertIterator_free(CCGVertIterator *vi) {
02704         _ehashIterator_free((EHashIterator*) vi);
02705 }
02706 
02707 CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi) {
02708         return (CCGEdge*) _ehashIterator_getCurrent((EHashIterator*) vi);
02709 }
02710 int ccgEdgeIterator_isStopped(CCGEdgeIterator *vi) {
02711         return _ehashIterator_isStopped((EHashIterator*) vi);
02712 }
02713 void ccgEdgeIterator_next(CCGEdgeIterator *vi) {
02714         _ehashIterator_next((EHashIterator*) vi); 
02715 }
02716 void ccgEdgeIterator_free(CCGEdgeIterator *vi) {
02717         _ehashIterator_free((EHashIterator*) vi);
02718 }
02719 
02720 CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi) {
02721         return (CCGFace*) _ehashIterator_getCurrent((EHashIterator*) vi);
02722 }
02723 int ccgFaceIterator_isStopped(CCGFaceIterator *vi) {
02724         return _ehashIterator_isStopped((EHashIterator*) vi);
02725 }
02726 void ccgFaceIterator_next(CCGFaceIterator *vi) {
02727         _ehashIterator_next((EHashIterator*) vi); 
02728 }
02729 void ccgFaceIterator_free(CCGFaceIterator *vi) {
02730         _ehashIterator_free((EHashIterator*) vi);
02731 }
02732 
02733 /*** Extern API final vert/edge/face interface ***/
02734 
02735 int ccgSubSurf_getNumFinalVerts(CCGSubSurf *ss) {
02736         int edgeSize = 1 + (1<<ss->subdivLevels);
02737         int gridSize = 1 + (1<<(ss->subdivLevels-1));
02738         int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2)));
02739         return numFinalVerts;
02740 }
02741 int ccgSubSurf_getNumFinalEdges(CCGSubSurf *ss) {
02742         int edgeSize = 1 + (1<<ss->subdivLevels);
02743         int gridSize = 1 + (1<<(ss->subdivLevels-1));
02744         int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1)));
02745         return numFinalEdges;
02746 }
02747 int ccgSubSurf_getNumFinalFaces(CCGSubSurf *ss) {
02748         int gridSize = 1 + (1<<(ss->subdivLevels-1));
02749         int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1));
02750         return numFinalFaces;
02751 }