- added vertex normal calculation functionality to CCG subsurf (CCGSS
[blender.git] / source / blender / blenkernel / intern / CCGSubSurf.c
1 /* $Id$ */
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <math.h>
6 #include <float.h>
7
8 #include "CCGSubSurf.h"
9
10 /***/
11
12 typedef unsigned char   byte;
13
14 /***/
15
16 static int kHashSizes[] = {
17         1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 
18         16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 
19         4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459
20 };
21
22 typedef struct _EHEntry EHEntry;
23 struct _EHEntry {
24         EHEntry *next;
25         void *key;
26 };
27 typedef struct _EHash {
28         EHEntry **buckets;
29         int numEntries, curSize, curSizeIdx;
30
31         CCGAllocatorIFC allocatorIFC;
32         CCGAllocatorHDL allocator;
33 } EHash;
34
35 #define EHASH_alloc(eh, nb)                     ((eh)->allocatorIFC.alloc((eh)->allocator, nb))
36 #define EHASH_free(eh, ptr)                     ((eh)->allocatorIFC.free((eh)->allocator, ptr))
37
38 #define EHASH_hash(eh, item)    (((unsigned long) (item))%((unsigned int) (eh)->curSize))
39
40 static EHash *_ehash_new(int estimatedNumEntries, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) {
41         EHash *eh = allocatorIFC->alloc(allocator, sizeof(*eh));
42         eh->allocatorIFC = *allocatorIFC;
43         eh->allocator = allocator;
44         eh->numEntries = 0;
45         eh->curSizeIdx = 0;
46         while (kHashSizes[eh->curSizeIdx]<estimatedNumEntries)
47                 eh->curSizeIdx++;
48         eh->curSize = kHashSizes[eh->curSizeIdx];
49         eh->buckets = EHASH_alloc(eh, eh->curSize*sizeof(*eh->buckets));
50         memset(eh->buckets, 0, eh->curSize*sizeof(*eh->buckets));
51
52         return eh;
53 }
54 typedef void (*EHEntryFreeFP)(EHEntry *, void *);
55 static void _ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *userData) {
56         int numBuckets = eh->curSize;
57
58         while (numBuckets--) {
59                 EHEntry *entry = eh->buckets[numBuckets];
60
61                 while (entry) {
62                         EHEntry *next = entry->next;
63
64                         freeEntry(entry, userData);
65
66                         entry = next;
67                 }
68         }
69
70         EHASH_free(eh, eh->buckets);
71         EHASH_free(eh, eh);
72 }
73
74 static void _ehash_insert(EHash *eh, EHEntry *entry) {
75         int numBuckets = eh->curSize;
76         int hash = EHASH_hash(eh, entry->key);
77         entry->next = eh->buckets[hash];
78         eh->buckets[hash] = entry;
79         eh->numEntries++;
80
81         if (eh->numEntries > (numBuckets*3)) {
82                 EHEntry **oldBuckets = eh->buckets;
83                 eh->curSize = kHashSizes[++eh->curSizeIdx];
84                 
85                 eh->buckets = EHASH_alloc(eh, eh->curSize*sizeof(*eh->buckets));
86                 memset(eh->buckets, 0, eh->curSize*sizeof(*eh->buckets));
87
88                 while (numBuckets--) {
89                         for (entry = oldBuckets[numBuckets]; entry;) {
90                                 EHEntry *next = entry->next;
91                                 
92                                 hash = EHASH_hash(eh, entry->key);
93                                 entry->next = eh->buckets[hash];
94                                 eh->buckets[hash] = entry;
95                                 
96                                 entry = next;
97                         }
98                 }
99
100                 EHASH_free(eh, oldBuckets);
101         }
102 }
103
104 static void *_ehash_lookupWithPrev(EHash *eh, void *key, void ***prevp_r) {
105         int hash = EHASH_hash(eh, key);
106         void **prevp = (void**) &eh->buckets[hash];
107         EHEntry *entry;
108         
109         for (; (entry = *prevp); prevp = (void**) &entry->next) {
110                 if (entry->key==key) {
111                         *prevp_r = (void**) prevp;
112                         return entry;
113                 }
114         }
115         
116         return NULL;
117 }
118
119 static void *_ehash_lookup(EHash *eh, void *key) {
120         int hash = EHASH_hash(eh, key);
121         EHEntry *entry;
122         
123         for (entry = eh->buckets[hash]; entry; entry = entry->next)
124                 if (entry->key==key)
125                         break;
126         
127         return entry;
128 }
129
130 /**/
131
132 typedef struct _EHashIterator {
133         EHash *eh;
134         int curBucket;
135         EHEntry *curEntry;
136 } EHashIterator;
137
138 static EHashIterator *_ehashIterator_new(EHash *eh) {
139         EHashIterator *ehi = EHASH_alloc(eh, sizeof(*ehi));
140         ehi->eh = eh;
141         ehi->curEntry = NULL;
142         ehi->curBucket = -1;
143         while (!ehi->curEntry) {
144                 ehi->curBucket++;
145                 if (ehi->curBucket==ehi->eh->curSize)
146                         break;
147                 ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
148         }
149         return ehi;
150 }
151 static void _ehashIterator_free(EHashIterator *ehi) {
152         EHASH_free(ehi->eh, ehi);
153 }
154
155 static void *_ehashIterator_getCurrent(EHashIterator *ehi) {
156         return ehi->curEntry;
157 }
158
159 static void _ehashIterator_next(EHashIterator *ehi) {
160         if (ehi->curEntry) {
161         ehi->curEntry = ehi->curEntry->next;
162                 while (!ehi->curEntry) {
163                         ehi->curBucket++;
164                         if (ehi->curBucket==ehi->eh->curSize)
165                                 break;
166                         ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
167                 }
168         }
169 }
170 static int _ehashIterator_isStopped(EHashIterator *ehi) {
171         return !ehi->curEntry;
172 }
173
174 /***/
175
176 static void *_stdAllocator_alloc(CCGAllocatorHDL a, int numBytes) {
177         return malloc(numBytes);
178 }
179 static void *_stdAllocator_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) {
180         return realloc(ptr, newSize);
181 }
182 static void _stdAllocator_free(CCGAllocatorHDL a, void *ptr) {
183         free(ptr);
184 }
185
186 static CCGAllocatorIFC *_getStandardAllocatorIFC(void) {
187         static CCGAllocatorIFC ifc;
188
189         ifc.alloc = _stdAllocator_alloc;
190         ifc.realloc = _stdAllocator_realloc;
191         ifc.free = _stdAllocator_free;
192         ifc.release = NULL;
193
194         return &ifc;
195 }
196
197 /***/
198
199 static int _edge_isBoundary(CCGEdge *e);
200
201 /***/
202
203 enum {
204         Vert_eEffected=         (1<<0),
205         Vert_eChanged=          (1<<1),
206 } VertFlags;
207 enum {
208         Edge_eEffected=         (1<<0),
209 } CCGEdgeFlags;
210 enum {
211         Face_eEffected=         (1<<0),
212 } FaceFlags;
213
214 struct _CCGVert {
215         CCGVert         *next;  /* EHData.next */
216         CCGVertHDL      vHDL;   /* EHData.key */
217
218         short numEdges, numFaces, flags, pad;
219
220         CCGEdge **edges;
221         CCGFace **faces;
222 //      byte *levelData;
223 //      byte *userData;
224 };
225 #define VERT_getLevelData(v)            ((byte*) &(v)[1])
226
227 struct _CCGEdge {
228         CCGEdge         *next;  /* EHData.next */
229         CCGEdgeHDL      eHDL;   /* EHData.key */
230
231         short numFaces, flags;
232         float crease;
233
234         CCGVert *v0,*v1;
235         CCGFace **faces;
236
237 //      byte *levelData;
238 //      byte *userData;
239 };
240 #define EDGE_getLevelData(e)            ((byte*) &(e)[1])
241
242 struct _CCGFace {
243         CCGFace         *next;  /* EHData.next */
244         CCGFaceHDL      fHDL;   /* EHData.key */
245
246         short numVerts, flags, pad1, pad2;
247
248 //      CCGVert **verts;
249 //      CCGEdge **edges;
250 //      byte *centerData;
251 //      byte **gridData;
252 //      byte *userData;
253 };
254 #define FACE_getVerts(f)                ((CCGVert**) &(f)[1])
255 #define FACE_getEdges(f)                ((CCGEdge**) &(FACE_getVerts(f)[(f)->numVerts]))
256 #define FACE_getCenterData(f)   ((byte*) &(FACE_getEdges(f)[(f)->numVerts]))
257
258 typedef enum {
259         eSyncState_None = 0,
260         eSyncState_Vert,
261         eSyncState_Edge,
262         eSyncState_Face,
263         eSyncState_Partial,
264 } SyncState;
265
266 struct _CCGSubSurf {
267         EHash *vMap;    /* map of CCGVertHDL -> Vert */
268         EHash *eMap;    /* map of CCGEdgeHDL -> Edge */
269         EHash *fMap;    /* map of CCGFaceHDL -> Face */
270
271         CCGMeshIFC meshIFC;
272         void *meshData;
273
274         CCGAllocatorIFC allocatorIFC;
275         CCGAllocatorHDL allocator;
276
277         int subdivLevels;
278         int numGrids;
279         int allowEdgeCreation;
280
281         void *q, *r;
282                 
283                 // data for calc vert normals
284         int calcVertNormals;
285         int normalDataOffset;
286
287                 // data for age'ing (to debug sync)
288         int currentAge;
289         int useAgeCounts;
290         int vertUserAgeOffset;
291         int edgeUserAgeOffset;
292         int faceUserAgeOffset;
293
294                 // data used during syncing
295         SyncState syncState;
296
297         EHash *oldVMap, *oldEMap, *oldFMap;
298         int lenTempArrays;
299         CCGVert **tempVerts;
300         CCGEdge **tempEdges;
301 };
302
303 #define CCGSUBSURF_alloc(ss, nb)                        ((ss)->allocatorIFC.alloc((ss)->allocator, nb))
304 #define CCGSUBSURF_realloc(ss, ptr, nb, ob)     ((ss)->allocatorIFC.realloc((ss)->allocator, ptr, nb, ob))
305 #define CCGSUBSURF_free(ss, ptr)                        ((ss)->allocatorIFC.free((ss)->allocator, ptr))
306
307 /***/
308
309 static CCGVert *_vert_new(CCGVertHDL vHDL, int levels, int dataSize, CCGSubSurf *ss) {
310         CCGVert *v = CCGSUBSURF_alloc(ss, sizeof(CCGVert) + ss->meshIFC.vertDataSize * (ss->subdivLevels+1) + ss->meshIFC.vertUserSize);
311         byte *userData;
312
313         v->vHDL = vHDL;
314         v->edges = NULL;
315         v->faces = NULL;
316         v->numEdges = v->numFaces = 0;
317         v->flags = 0;
318
319         userData = ccgSubSurf_getVertUserData(ss, v);
320         memset(userData, 0, ss->meshIFC.vertUserSize);
321         if (ss->useAgeCounts) *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
322
323         return v;
324 }
325 static void _vert_remEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss) {
326         int i;
327         for (i=0; i<v->numEdges; i++) {
328                 if (v->edges[i]==e) {
329                         v->edges[i] = v->edges[--v->numEdges];
330                         break;
331                 }
332         }
333 }
334 static void _vert_remFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) {
335         int i;
336         for (i=0; i<v->numFaces; i++) {
337                 if (v->faces[i]==f) {
338                         v->faces[i] = v->faces[--v->numFaces];
339                         break;
340                 }
341         }
342 }
343 static void _vert_addEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss) {
344         v->edges = CCGSUBSURF_realloc(ss, v->edges, (v->numEdges+1)*sizeof(*v->edges), v->numEdges*sizeof(*v->edges));
345         v->edges[v->numEdges++] = e;
346 }
347 static void _vert_addFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) {
348         v->faces = CCGSUBSURF_realloc(ss, v->faces, (v->numFaces+1)*sizeof(*v->faces), v->numFaces*sizeof(*v->faces));
349         v->faces[v->numFaces++] = f;
350 }
351 static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) {
352         int i;
353         for (i=0; i<v->numEdges; i++) {
354                 CCGEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse
355                 if (    (e->v0==v && e->v1==vQ) ||
356                                 (e->v1==v && e->v0==vQ))
357                         return e;
358         }
359         return 0;
360 }
361 static int _vert_isBoundary(CCGVert *v) {
362         int i;
363         for (i=0; i<v->numEdges; i++)
364                 if (_edge_isBoundary(v->edges[i]))
365                         return 1;
366         return 0;
367 }
368
369 static void *_vert_getCo(CCGVert *v, int lvl, int dataSize) {
370         return &VERT_getLevelData(v)[lvl*dataSize];
371 }
372
373 static void _vert_free(CCGVert *v, CCGSubSurf *ss) {
374         CCGSUBSURF_free(ss, v->edges);
375         CCGSUBSURF_free(ss, v->faces);
376         CCGSUBSURF_free(ss, v);
377 }
378
379 /***/
380
381 static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float crease, int levels, int dataSize, CCGSubSurf *ss) {
382         CCGEdge *e = CCGSUBSURF_alloc(ss, sizeof(CCGEdge) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1) + ss->meshIFC.edgeUserSize);
383         byte *userData;
384
385         e->eHDL = eHDL;
386         e->v0 = v0;
387         e->v1 = v1;
388         e->crease = crease;
389         e->faces = NULL;
390         e->numFaces = 0;
391         e->flags = 0;
392         _vert_addEdge(v0, e, ss);
393         _vert_addEdge(v1, e, ss);
394
395         userData = ccgSubSurf_getEdgeUserData(ss, e);
396         memset(userData, 0, ss->meshIFC.edgeUserSize);
397         if (ss->useAgeCounts) *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
398
399         return e;
400 }
401 static void _edge_remFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) {
402         int i;
403         for (i=0; i<e->numFaces; i++) {
404                 if (e->faces[i]==f) {
405                         e->faces[i] = e->faces[--e->numFaces];
406                         break;
407                 }
408         }
409 }
410 static void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) {
411         e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces+1)*sizeof(*e->faces), e->numFaces*sizeof(*e->faces));
412         e->faces[e->numFaces++] = f;
413 }
414 static int _edge_isBoundary(CCGEdge *e) {
415         return e->numFaces<2;
416 }
417
418 static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ) {
419         if (vQ==e->v0) {
420                 return e->v1;
421         } else {
422                 return e->v0;
423         }
424 }
425
426 static void *_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize) {
427         int levelBase = lvl + (1<<lvl) - 1;
428         return &EDGE_getLevelData(e)[dataSize*(levelBase + x)];
429 }
430 static float *_edge_getNo(CCGEdge *e, int lvl, int x, int dataSize, int normalDataOffset) {
431         int levelBase = lvl + (1<<lvl) - 1;
432         return (float*) &EDGE_getLevelData(e)[dataSize*(levelBase + x) + normalDataOffset];
433 }
434
435 static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize) {
436         int levelBase = lvl + (1<<lvl) - 1;
437         if (v==e->v0) {
438                 return &EDGE_getLevelData(e)[dataSize*(levelBase + x)];
439         } else {
440                 return &EDGE_getLevelData(e)[dataSize*(levelBase + (1<<lvl) - x)];              
441         }
442 }
443
444 static void _edge_free(CCGEdge *e, CCGSubSurf *ss) {
445         CCGSUBSURF_free(ss, e->faces);
446         CCGSUBSURF_free(ss, e);
447 }
448 static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss) {
449         _vert_remEdge(e->v0, e, ss);
450         _vert_remEdge(e->v1, e, ss);
451         e->v0->flags |= Vert_eEffected;
452         e->v1->flags |= Vert_eEffected;
453         _edge_free(e, ss);
454 }
455
456 static float EDGE_getSharpness(CCGEdge *e, int lvl, CCGSubSurf *ss) {
457         float sharpness = e->crease;
458         while (lvl--) {
459                 if (sharpness>1.0) {
460                         sharpness -= 1.0;
461                 } else {
462                         sharpness = 0.0;
463                 }
464         }
465         return sharpness;
466 }
467
468 /***/
469
470 static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, int levels, int dataSize, CCGSubSurf *ss) {
471         int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
472         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);
473         byte *userData;
474         int i;
475
476         f->numVerts = numVerts;
477         f->fHDL = fHDL;
478         f->flags = 0;
479
480         for (i=0; i<numVerts; i++) {
481                 FACE_getVerts(f)[i] = verts[i];
482                 FACE_getEdges(f)[i] = edges[i];
483                 _vert_addFace(verts[i], f, ss);
484                 _edge_addFace(edges[i], f, ss);
485         }
486
487         userData = ccgSubSurf_getFaceUserData(ss, f);
488         memset(userData, 0, ss->meshIFC.faceUserSize);
489         if (ss->useAgeCounts) *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
490
491         return f;
492 }
493
494 static void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) {
495         int maxGridSize = 1 + (1<<(levels-1));
496         int spacing = 1<<(levels-lvl);
497         byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
498         return &gridBase[dataSize*x*spacing];
499 }
500 static void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) {
501         int maxGridSize = 1 + (1<<(levels-1));
502         int spacing = 1<<(levels-lvl);
503         byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
504         return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)];
505 }
506 static float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) {
507         int maxGridSize = 1 + (1<<(levels-1));
508         int spacing = 1<<(levels-lvl);
509         byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
510         return (float*) &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing) + normalDataOffset];
511 }
512 static int _face_getVertIndex(CCGFace *f, CCGVert *v) {
513         int i;
514         for (i=0; i<f->numVerts; i++)
515                 if (FACE_getVerts(f)[i]==v)
516                         return i;
517         return -1;
518 }
519 static void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) {
520         int maxGridSize = 1 + (1<<(levels-1));
521         int spacing = 1<<(levels-lvl);
522         int S, x, y, cx, cy;
523
524         for (S=0; S<f->numVerts; S++)
525                 if (FACE_getEdges(f)[S]==e)
526                         break;
527
528         eX = eX*spacing;
529         eY = eY*spacing;
530         if (e->v0!=FACE_getVerts(f)[S]) {
531                 eX = (maxGridSize*2 - 1)-1 - eX;
532         }
533         y = maxGridSize - 1 - eX;
534         x = maxGridSize - 1 - eY;
535         if (x<0) {
536                 S = (S+f->numVerts-1)%f->numVerts;
537                 cx = y;
538                 cy = -x;
539         } else if (y<0) {
540                 S = (S+1)%f->numVerts;
541                 cx = -y;
542                 cy = x;
543         } else {
544                 cx = x;
545                 cy = y;
546         }
547         return _face_getIFCo(f, levels, S, cx, cy, levels, dataSize);
548 }
549 static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) {
550         return (float*) ((byte*) _face_getIFCoEdge(f, e, lvl, eX, eY, levels, dataSize) + normalDataOffset);
551 }
552
553 static void _face_free(CCGFace *f, CCGSubSurf *ss) {
554         CCGSUBSURF_free(ss, f);
555 }
556 static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss) {
557         int j;
558         for (j=0; j<f->numVerts; j++) {
559                 _vert_remFace(FACE_getVerts(f)[j], f, ss);
560                 _edge_remFace(FACE_getEdges(f)[j], f, ss);
561                 FACE_getVerts(f)[j]->flags |= Vert_eEffected;
562         }
563         _face_free(f, ss);
564 }
565
566 /***/
567
568 CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, CCGMeshHDL meshData, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) {
569         if (!allocatorIFC) {
570                 allocatorIFC = _getStandardAllocatorIFC();
571                 allocator = NULL;
572         }
573
574         if (subdivLevels<1) {
575                 return NULL;
576         } else {
577                 CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss));
578
579                 ss->allocatorIFC = *allocatorIFC;
580                 ss->allocator = allocator;
581
582                 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
583                 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
584                 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
585
586                 ss->meshIFC = *ifc;
587                 ss->meshData = meshData;
588
589                 ss->subdivLevels = subdivLevels;
590                 ss->numGrids = 0;
591                 ss->allowEdgeCreation = 0;
592
593                 ss->useAgeCounts = 0;
594                 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
595
596                 ss->calcVertNormals = 0;
597                 ss->normalDataOffset = 0;
598
599                 ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
600                 ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
601
602                 ss->currentAge = 0;
603
604                 ss->syncState = eSyncState_None;
605
606                 ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL;
607                 ss->lenTempArrays = 0;
608                 ss->tempVerts = NULL;
609                 ss->tempEdges = NULL;   
610
611                 return ss;
612         }
613 }
614
615 void ccgSubSurf_free(CCGSubSurf *ss) {
616         CCGAllocatorIFC allocatorIFC = ss->allocatorIFC;
617         CCGAllocatorHDL allocator = ss->allocator;
618
619         if (ss->syncState) {
620                 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_free, ss);
621                 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_free, ss);
622                 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
623
624                 CCGSUBSURF_free(ss, ss->tempVerts);
625                 CCGSUBSURF_free(ss, ss->tempEdges);
626         }
627
628         CCGSUBSURF_free(ss, ss->r);
629         CCGSUBSURF_free(ss, ss->q);
630
631         _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
632         _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
633         _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
634
635         CCGSUBSURF_free(ss, ss);
636
637         if (allocatorIFC.release) {
638                 allocatorIFC.release(allocator);
639         }
640 }
641
642 CCGError ccgSubSurf_setAllowEdgeCreation(CCGSubSurf *ss, int allowEdgeCreation) {
643         ss->allowEdgeCreation = !!allowEdgeCreation;
644
645         return eCCGError_None;
646 }
647
648 CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels) {
649         if (subdivisionLevels<=0) {
650                 return eCCGError_InvalidValue;
651         } else if (subdivisionLevels!=ss->subdivLevels) {
652                 ss->numGrids = 0;
653                 ss->subdivLevels = subdivisionLevels;
654                 _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
655                 _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
656                 _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
657                 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
658                 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
659                 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
660         }
661
662         return eCCGError_None;
663 }
664
665 CCGError ccgSubSurf_setUseAgeCounts(CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset) {
666         if (useAgeCounts) {
667                 if (    (vertUserOffset+4>ss->meshIFC.vertUserSize) ||
668                                 (edgeUserOffset+4>ss->meshIFC.edgeUserSize) ||
669                                 (faceUserOffset+4>ss->meshIFC.faceUserSize)) {
670                         return eCCGError_InvalidValue;
671                 }  else {
672                         ss->useAgeCounts = 1;
673                         ss->vertUserAgeOffset = vertUserOffset;
674                         ss->edgeUserAgeOffset = edgeUserOffset;
675                         ss->faceUserAgeOffset = faceUserOffset;
676                 }
677         } else {
678                 ss->useAgeCounts = 0;
679                 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
680         }
681
682         return eCCGError_None;
683 }
684
685 CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int normalDataOffset) {
686         if (useVertNormals) {
687                 if (normalDataOffset<0 || normalDataOffset+12>ss->meshIFC.vertDataSize) {
688                         return eCCGError_InvalidValue;
689                 } else {
690                         ss->calcVertNormals = 1;
691                         ss->normalDataOffset = normalDataOffset;
692                 }
693         } else {
694                 ss->calcVertNormals = 0;
695                 ss->normalDataOffset = 0;
696         }
697
698         return eCCGError_None;
699 }
700
701 /***/
702
703 CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) {
704         if (ss->syncState!=eSyncState_None) {
705                 return eCCGError_InvalidSyncState;
706         }
707
708         ss->currentAge++;
709
710         ss->oldVMap = ss->vMap; 
711         ss->oldEMap = ss->eMap; 
712         ss->oldFMap = ss->fMap;
713
714         ss->vMap = _ehash_new(ss->oldVMap->numEntries, &ss->allocatorIFC, ss->allocator);
715         ss->eMap = _ehash_new(ss->oldFMap->numEntries, &ss->allocatorIFC, ss->allocator);
716         ss->fMap = _ehash_new(ss->oldEMap->numEntries, &ss->allocatorIFC, ss->allocator);
717
718         ss->numGrids = 0;
719
720         ss->lenTempArrays = 12;
721         ss->tempVerts = CCGSUBSURF_alloc(ss, sizeof(*ss->tempVerts)*ss->lenTempArrays);
722         ss->tempEdges = CCGSUBSURF_alloc(ss, sizeof(*ss->tempEdges)*ss->lenTempArrays);
723
724         ss->syncState = eSyncState_Vert;
725
726         return eCCGError_None;
727 }
728
729 CCGError ccgSubSurf_initPartialSync(CCGSubSurf *ss) {
730         if (ss->syncState!=eSyncState_None) {
731                 return eCCGError_InvalidSyncState;
732         }
733
734         ss->currentAge++;
735
736         ss->syncState = eSyncState_Partial;
737
738         return eCCGError_None;
739 }
740
741 CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL) {
742         if (ss->syncState!=eSyncState_Partial) {
743                 return eCCGError_InvalidSyncState;
744         } else {
745                 void **prevp;
746                 CCGVert *v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
747
748                 if (!v || v->numFaces || v->numEdges) {
749                         return eCCGError_InvalidValue;
750                 } else {
751                         *prevp = v->next;
752                         _vert_free(v, ss);
753                 }
754         }
755
756         return eCCGError_None;
757 }
758
759 CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL) {
760         if (ss->syncState!=eSyncState_Partial) {
761                 return eCCGError_InvalidSyncState;
762         } else {
763                 void **prevp;
764                 CCGEdge *e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
765
766                 if (!e || e->numFaces) {
767                         return eCCGError_InvalidValue;
768                 } else {
769                         *prevp = e->next;
770                         _edge_unlinkMarkAndFree(e, ss);
771                 }
772         }
773
774         return eCCGError_None;
775 }
776
777 CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) {
778         if (ss->syncState!=eSyncState_Partial) {
779                 return eCCGError_InvalidSyncState;
780         } else {
781                 void **prevp;
782                 CCGFace *f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
783
784                 if (!f) {
785                         return eCCGError_InvalidValue;
786                 } else {
787                         *prevp = f->next;
788                         _face_unlinkMarkAndFree(f, ss);
789                 }
790         }
791
792         return eCCGError_None;
793 }
794
795 CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData) {
796         void **prevp;
797         CCGVert *v;
798         
799         if (ss->syncState==eSyncState_Partial) {
800                 v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
801                 if (!v) {
802                         v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
803                         ss->meshIFC.vertDataCopy(ss->meshData, _vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
804                         _ehash_insert(ss->vMap, (EHEntry*) v);
805                         v->flags = Vert_eEffected;
806                 } else if (!ss->meshIFC.vertDataEqual(ss->meshData, vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize))) {
807                         int i, j;
808
809                         ss->meshIFC.vertDataCopy(ss->meshData, _vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
810                         v->flags = Vert_eEffected;
811
812                         for (i=0; i<v->numEdges; i++) {
813                                 CCGEdge *e = v->edges[i];
814                                 e->v0->flags |= Vert_eEffected;
815                                 e->v1->flags |= Vert_eEffected;
816                         }
817                         for (i=0; i<v->numFaces; i++) {
818                                 CCGFace *f = v->faces[i];
819                                 for (j=0; j<f->numVerts; j++) {
820                                         FACE_getVerts(f)[j]->flags |= Vert_eEffected;
821                                 }
822                         }
823                 }
824         } else {
825                 if (ss->syncState!=eSyncState_Vert) { 
826                         return eCCGError_InvalidSyncState;
827                 }
828
829                 v = _ehash_lookupWithPrev(ss->oldVMap, vHDL, &prevp);
830                 if (!v) {
831                         v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
832                         ss->meshIFC.vertDataCopy(ss->meshData, _vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
833                         _ehash_insert(ss->vMap, (EHEntry*) v);
834                         v->flags = Vert_eEffected;
835                 } else if (!ss->meshIFC.vertDataEqual(ss->meshData, vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize))) {
836                         *prevp = v->next;
837                         _ehash_insert(ss->vMap, (EHEntry*) v);
838                         ss->meshIFC.vertDataCopy(ss->meshData, _vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
839                         v->flags = Vert_eEffected|Vert_eChanged;
840                 } else {
841                         *prevp = v->next;
842                         _ehash_insert(ss->vMap, (EHEntry*) v);
843                         v->flags = 0;
844                 }
845         }
846
847         return eCCGError_None;
848 }
849
850 CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease) {
851         void **prevp;
852         CCGEdge *e, *eNew;
853
854         if (ss->syncState==eSyncState_Partial) {
855                 e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
856                 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1 || crease!=e->crease) {
857                         CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
858                         CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
859
860                         eNew = _edge_new(eHDL, v0, v1, crease, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
861
862                         if (e) {
863                                 *prevp = eNew;
864                                 eNew->next = e->next;
865
866                                 _edge_unlinkMarkAndFree(e, ss);
867                         } else {
868                                 _ehash_insert(ss->eMap, (EHEntry*) eNew);
869                         }
870
871                         eNew->v0->flags |= Vert_eEffected;
872                         eNew->v1->flags |= Vert_eEffected;
873                 }
874         } else {
875                 if (ss->syncState==eSyncState_Vert) {
876                         ss->syncState = eSyncState_Edge;
877                 } else if (ss->syncState!=eSyncState_Edge) {
878                         return eCCGError_InvalidSyncState;
879                 }
880
881                 e = _ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp);
882                 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1|| e->crease!=crease) {
883                         CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
884                         CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
885                         e = _edge_new(eHDL, v0, v1, crease, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
886                         _ehash_insert(ss->eMap, (EHEntry*) e);
887                         e->v0->flags |= Vert_eEffected;
888                         e->v1->flags |= Vert_eEffected;
889                 } else {
890                         *prevp = e->next;
891                         _ehash_insert(ss->eMap, (EHEntry*) e);
892                         e->flags = 0;
893                         if ((e->v0->flags|e->v1->flags)&Vert_eChanged) {
894                                 e->v0->flags |= Vert_eEffected;
895                                 e->v1->flags |= Vert_eEffected;
896                         }
897                 }
898         }
899
900         return eCCGError_None;
901 }
902
903 CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs) {
904         void **prevp;
905         CCGFace *f, *fNew;
906         int j, k, topologyChanged = 0;
907
908         if (numVerts>ss->lenTempArrays) {
909                 int oldLen = ss->lenTempArrays;
910                 ss->lenTempArrays = (numVerts<ss->lenTempArrays*2)?ss->lenTempArrays*2:numVerts;
911                 ss->tempVerts = CCGSUBSURF_realloc(ss, ss->tempVerts, sizeof(*ss->tempVerts)*ss->lenTempArrays, sizeof(*ss->tempVerts)*oldLen);
912                 ss->tempEdges = CCGSUBSURF_realloc(ss, ss->tempEdges, sizeof(*ss->tempEdges)*ss->lenTempArrays, sizeof(*ss->tempEdges)*oldLen);
913         }
914
915         if (ss->syncState==eSyncState_Partial) {
916                 f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
917
918                 for (k=0; k<numVerts; k++) {
919                         ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
920                 }
921                 for (k=0; k<numVerts; k++) {
922                         ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]);
923                 }
924
925                 if (f) {
926                         if (    f->numVerts!=numVerts ||
927                                         memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) ||
928                                         memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts))
929                                 topologyChanged = 1;
930                 }
931
932                 if (!f || topologyChanged) {
933                         fNew = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
934
935                         if (f) {
936                                 ss->numGrids += numVerts - f->numVerts;
937
938                                 *prevp = fNew;
939                                 fNew->next = f->next;
940
941                                 _face_unlinkMarkAndFree(f, ss);
942                         } else {
943                                 ss->numGrids += numVerts;
944                                 _ehash_insert(ss->fMap, (EHEntry*) fNew);
945                         }
946
947                         for (k=0; k<numVerts; k++)
948                                 FACE_getVerts(fNew)[k]->flags |= Vert_eEffected;
949                 }
950         } else {
951                 if (ss->syncState==eSyncState_Vert || ss->syncState==eSyncState_Edge) {
952                         ss->syncState = eSyncState_Face;
953                 } else if (ss->syncState!=eSyncState_Face) {
954                         return eCCGError_InvalidSyncState;
955                 }
956
957                 f = _ehash_lookupWithPrev(ss->oldFMap, fHDL, &prevp);
958
959                 for (k=0; k<numVerts; k++) {
960                         ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
961                 }
962                 for (k=0; k<numVerts; k++) {
963                         ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]);
964
965                         if (ss->allowEdgeCreation && !ss->tempEdges[k]) {
966                                 CCGEdge *e = ss->tempEdges[k] = _edge_new((CCGEdgeHDL) -1, ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts], 0.0, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
967                                 _ehash_insert(ss->eMap, (EHEntry*) e);
968                                 e->v0->flags |= Vert_eEffected;
969                                 e->v1->flags |= Vert_eEffected;
970                         }
971                 }
972
973                 if (f) {
974                         if (    f->numVerts!=numVerts ||
975                                         memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) ||
976                                         memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts))
977                                 topologyChanged = 1;
978                 }
979
980                 if (!f || topologyChanged) {
981                         f = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
982                         _ehash_insert(ss->fMap, (EHEntry*) f);
983                         ss->numGrids += numVerts;
984
985                         for (k=0; k<numVerts; k++)
986                                 FACE_getVerts(f)[k]->flags |= Vert_eEffected;
987                 } else {
988                         *prevp = f->next;
989                         _ehash_insert(ss->fMap, (EHEntry*) f);
990                         f->flags = 0;
991                         ss->numGrids += f->numVerts;
992
993                         for (j=0; j<f->numVerts; j++) {
994                                 if (FACE_getVerts(f)[j]->flags&Vert_eChanged) {
995                                         for (k=0; k<f->numVerts; k++)
996                                                 FACE_getVerts(f)[k]->flags |= Vert_eEffected;
997                                         break;
998                                 }
999                         }
1000                 }
1001         }
1002
1003         return eCCGError_None;
1004 }
1005
1006 static void ccgSubSurf__sync(CCGSubSurf *ss);
1007 CCGError ccgSubSurf_processSync(CCGSubSurf *ss) {
1008         if (ss->syncState==eSyncState_Partial) {
1009                 ss->syncState = eSyncState_None;
1010
1011                 ccgSubSurf__sync(ss);
1012         } else if (ss->syncState) {
1013                 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_unlinkMarkAndFree, ss);
1014                 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_unlinkMarkAndFree, ss);
1015                 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
1016                 CCGSUBSURF_free(ss, ss->tempEdges);
1017                 CCGSUBSURF_free(ss, ss->tempVerts);
1018
1019                 ss->lenTempArrays = 0;
1020
1021                 ss->oldFMap = ss->oldEMap = ss->oldVMap = NULL;
1022                 ss->tempVerts = NULL;
1023                 ss->tempEdges = NULL;
1024
1025                 ss->syncState = eSyncState_None;
1026
1027                 ccgSubSurf__sync(ss);
1028         } else {
1029                 return eCCGError_InvalidSyncState;
1030         }
1031
1032         return eCCGError_None;
1033 }
1034
1035 static void ccgSubSurf__sync(CCGSubSurf *ss) {
1036         CCGVert **effectedV;
1037         CCGEdge **effectedE;
1038         CCGFace **effectedF;
1039         int numEffectedV, numEffectedE, numEffectedF;
1040         int subdivLevels = ss->subdivLevels;
1041         int vertDataSize = ss->meshIFC.vertDataSize;
1042         int i,ptrIdx,cornerIdx;
1043         int S,x,y;
1044         void *q = ss->q, *r = ss->r;
1045         int curLvl, nextLvl;
1046         int j;
1047
1048         effectedV = CCGSUBSURF_alloc(ss, sizeof(*effectedV)*ss->vMap->numEntries);
1049         effectedE = CCGSUBSURF_alloc(ss, sizeof(*effectedE)*ss->eMap->numEntries);
1050         effectedF = CCGSUBSURF_alloc(ss, sizeof(*effectedF)*ss->fMap->numEntries);
1051         numEffectedV = numEffectedE = numEffectedF = 0;
1052         for (i=0; i<ss->vMap->curSize; i++) {
1053                 CCGVert *v = (CCGVert*) ss->vMap->buckets[i];
1054                 for (; v; v = v->next) {
1055                         if (v->flags&Vert_eEffected) {
1056                                 effectedV[numEffectedV++] = v;
1057
1058                                 for (j=0; j<v->numEdges; j++) {
1059                                         CCGEdge *e = v->edges[j];
1060                                         if (!(e->flags&Edge_eEffected)) {
1061                                                 effectedE[numEffectedE++] = e;
1062                                                 e->flags |= Edge_eEffected;
1063                                         }
1064                                 }
1065
1066                                 for (j=0; j<v->numFaces; j++) {
1067                                         CCGFace *f = v->faces[j];
1068                                         if (!(f->flags&Face_eEffected)) {
1069                                                 effectedF[numEffectedF++] = f;
1070                                                 f->flags |= Face_eEffected;
1071                                         }
1072                                 }
1073                         }
1074                 }
1075         }
1076
1077 #define VERT_getCo(v, lvl)                              _vert_getCo(v, lvl, vertDataSize)
1078 #define EDGE_getCo(e, lvl, x)                   _edge_getCo(e, lvl, x, vertDataSize)
1079 #define FACE_getIECo(f, lvl, S, x)              _face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize)
1080 #define FACE_getIFCo(f, lvl, S, x, y)   _face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize)
1081         curLvl = 0;
1082         nextLvl = curLvl+1;
1083
1084         for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1085                 CCGFace *f = effectedF[ptrIdx];
1086                 void *co = FACE_getCenterData(f);
1087                 ss->meshIFC.vertDataZero(ss->meshData, co);
1088                 for (i=0; i<f->numVerts; i++) {
1089                         ss->meshIFC.vertDataAdd(ss->meshData, co, VERT_getCo(FACE_getVerts(f)[i], curLvl));
1090                 }
1091                 ss->meshIFC.vertDataMulN(ss->meshData, co, 1.0f/f->numVerts);
1092
1093                 f->flags = 0;
1094         }
1095         for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1096                 CCGEdge *e = effectedE[ptrIdx];
1097                 void *co = EDGE_getCo(e, nextLvl, 1);
1098                 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1099
1100                 if (_edge_isBoundary(e) || sharpness>=1.0) {
1101                         ss->meshIFC.vertDataCopy(ss->meshData, co, VERT_getCo(e->v0, curLvl));
1102                         ss->meshIFC.vertDataAdd(ss->meshData, co, VERT_getCo(e->v1, curLvl));
1103                         ss->meshIFC.vertDataMulN(ss->meshData, co, 0.5f);
1104                 } else {
1105                         int numFaces = 0;
1106                         ss->meshIFC.vertDataCopy(ss->meshData, q, VERT_getCo(e->v0, curLvl));
1107                         ss->meshIFC.vertDataAdd(ss->meshData, q, VERT_getCo(e->v1, curLvl));
1108                         for (i=0; i<e->numFaces; i++) {
1109                                 CCGFace *f = e->faces[i];
1110                                 ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getCenterData(f));
1111                                 numFaces++;
1112                         }
1113                         ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/(2.0f+numFaces));
1114
1115                         ss->meshIFC.vertDataCopy(ss->meshData, r, VERT_getCo(e->v0, curLvl));
1116                         ss->meshIFC.vertDataAdd(ss->meshData, r, VERT_getCo(e->v1, curLvl));
1117                         ss->meshIFC.vertDataMulN(ss->meshData, r, 0.5f);
1118
1119                         ss->meshIFC.vertDataCopy(ss->meshData, co, q);
1120                         ss->meshIFC.vertDataSub(ss->meshData, r, q);
1121                         ss->meshIFC.vertDataMulN(ss->meshData, r, sharpness);
1122                         ss->meshIFC.vertDataAdd(ss->meshData, co, r);
1123                 }
1124
1125                 e->flags = 0;
1126         }
1127         for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
1128                 CCGVert *v = effectedV[ptrIdx];
1129                 void *co = VERT_getCo(v, curLvl);
1130                 void *nCo = VERT_getCo(v, nextLvl);
1131                 int sharpCount = 0;
1132                 float avgSharpness = 0.0;
1133
1134                 for (i=0; i<v->numEdges; i++) {
1135                         CCGEdge *e = v->edges[i];
1136                         float sharpness = EDGE_getSharpness(e, curLvl, ss);
1137
1138                         if (sharpness!=0.0f) {
1139                                 sharpCount++;
1140                                 avgSharpness += sharpness;
1141                         }
1142                 }
1143
1144                 avgSharpness /= sharpCount;
1145                 if (avgSharpness>1.0) {
1146                         avgSharpness = 1.0;
1147                 }
1148
1149                 if (!v->numEdges) {
1150                         ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1151                 } else if (_vert_isBoundary(v)) {
1152                         int numBoundary = 0;
1153
1154                         ss->meshIFC.vertDataZero(ss->meshData, r);
1155                         for (i=0; i<v->numEdges; i++) {
1156                                 CCGEdge *e = v->edges[i];
1157                                 if (_edge_isBoundary(e)) {
1158                                         ss->meshIFC.vertDataAdd(ss->meshData, r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
1159                                         numBoundary++;
1160                                 }
1161                         }
1162                         ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1163                         ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.75);
1164                         ss->meshIFC.vertDataMulN(ss->meshData, r, 0.25f/numBoundary);
1165                         ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1166                 } else {
1167                         int numEdges = 0, numFaces = 0;
1168
1169                         ss->meshIFC.vertDataZero(ss->meshData, q);
1170                         for (i=0; i<v->numFaces; i++) {
1171                                 CCGFace *f = v->faces[i];
1172                                 ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getCenterData(f));
1173                                 numFaces++;
1174                         }
1175                         ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/numFaces);
1176                         ss->meshIFC.vertDataZero(ss->meshData, r);
1177                         for (i=0; i<v->numEdges; i++) {
1178                                 CCGEdge *e = v->edges[i];
1179                                 ss->meshIFC.vertDataAdd(ss->meshData, r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
1180                                 numEdges++;
1181                         }
1182                         ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0f/numEdges);
1183
1184                         ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1185                         ss->meshIFC.vertDataMulN(ss->meshData, nCo, numEdges-2.0f);
1186                         ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
1187                         ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1188                         ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/numEdges);
1189                 }
1190
1191                 if (sharpCount>1) {
1192                         ss->meshIFC.vertDataZero(ss->meshData, q);
1193
1194                         for (i=0; i<v->numEdges; i++) {
1195                                 CCGEdge *e = v->edges[i];
1196                                 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1197
1198                                 if (sharpness != 0.0) {
1199                                         CCGVert *oV = _edge_getOtherVert(e, v);
1200                                         ss->meshIFC.vertDataAdd(ss->meshData, q, VERT_getCo(oV, curLvl));
1201                                 }
1202                         }
1203
1204                         ss->meshIFC.vertDataMulN(ss->meshData, q, (float) 1/sharpCount);
1205
1206                         if (sharpCount!=2) {
1207                                         // q = q + (co-q)*avgSharpness
1208                                 ss->meshIFC.vertDataCopy(ss->meshData, r, co);
1209                                 ss->meshIFC.vertDataSub(ss->meshData, r, q);
1210                                 ss->meshIFC.vertDataMulN(ss->meshData, r, avgSharpness);
1211                                 ss->meshIFC.vertDataAdd(ss->meshData, q, r);
1212                         }
1213
1214                                 // r = co*.75 + q*.25
1215                         ss->meshIFC.vertDataCopy(ss->meshData, r, co);
1216                         ss->meshIFC.vertDataMulN(ss->meshData, r, .75);
1217                         ss->meshIFC.vertDataMulN(ss->meshData, q, .25);
1218                         ss->meshIFC.vertDataAdd(ss->meshData, r, q);
1219
1220                                 // nCo = nCo  + (r-nCo)*avgSharpness
1221                         ss->meshIFC.vertDataSub(ss->meshData, r, nCo);
1222                         ss->meshIFC.vertDataMulN(ss->meshData, r, avgSharpness);
1223                         ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1224                 }
1225
1226                 v->flags = 0;
1227         }
1228
1229         if (ss->useAgeCounts) {
1230                 for (i=0; i<numEffectedV; i++) {
1231                         CCGVert *v = effectedV[i];
1232                         byte *userData = ccgSubSurf_getVertUserData(ss, v);
1233                         *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
1234                 }
1235
1236                 for (i=0; i<numEffectedE; i++) {
1237                         CCGEdge *e = effectedE[i];
1238                         byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
1239                         *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
1240                 }
1241
1242                 for (i=0; i<numEffectedF; i++) {
1243                         CCGFace *f = effectedF[i];
1244                         byte *userData = ccgSubSurf_getFaceUserData(ss, f);
1245                         *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
1246                 }
1247         }
1248
1249         for (i=0; i<numEffectedE; i++) {
1250                 CCGEdge *e = effectedE[i];
1251                 ss->meshIFC.vertDataCopy(ss->meshData, EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
1252                 ss->meshIFC.vertDataCopy(ss->meshData, EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl));
1253         }
1254         for (i=0; i<numEffectedF; i++) {
1255                 CCGFace *f = effectedF[i];
1256                 for (S=0; S<f->numVerts; S++) {
1257                         CCGEdge *e = FACE_getEdges(f)[S];
1258                         CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
1259
1260                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
1261                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
1262                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
1263                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1));
1264
1265                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 1, 0), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize));
1266                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 0, 1), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize));
1267                 }
1268         }
1269
1270         for (curLvl=1; curLvl<subdivLevels; curLvl++) {
1271                 int edgeSize = 1 + (1<<curLvl);
1272                 int gridSize = 1 + (1<<(curLvl-1));
1273                 nextLvl = curLvl+1;
1274
1275                 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1276                         CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1277
1278                                 /* interior face midpoints
1279                                  *  o old interior face points
1280                                  */
1281                         for (S=0; S<f->numVerts; S++) {
1282                                 for (y=0; y<gridSize-1; y++) {
1283                                         for (x=0; x<gridSize-1; x++) {
1284                                                 int fx = 1 + 2*x;
1285                                                 int fy = 1 + 2*y;
1286                                                 void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y+0);
1287                                                 void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y+0);
1288                                                 void *co2 = FACE_getIFCo(f, curLvl, S, x+1, y+1);
1289                                                 void *co3 = FACE_getIFCo(f, curLvl, S, x+0, y+1);
1290                                                 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
1291
1292                                                 ss->meshIFC.vertDataAvg4(ss->meshData, co, co0, co1, co2, co3);
1293                                         }
1294                                 }
1295                         }
1296
1297                                 /* interior edge midpoints
1298                                  *  o old interior edge points
1299                                  *  o new interior face midpoints
1300                                  */
1301                         for (S=0; S<f->numVerts; S++) {
1302                                 for (x=0; x<gridSize-1; x++) {
1303                                         int fx = x*2 + 1;
1304                                         void *co0 = FACE_getIECo(f, curLvl, S, x+0);
1305                                         void *co1 = FACE_getIECo(f, curLvl, S, x+1);
1306                                         void *co2 = FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx);
1307                                         void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
1308                                         void *co = FACE_getIECo(f, nextLvl, S, fx);
1309                                         
1310                                         ss->meshIFC.vertDataAvg4(ss->meshData, co, co0, co1, co2, co3);
1311                                 }
1312
1313                                                 /* interior face interior edge midpoints
1314                                                  *  o old interior face points
1315                                                  *  o new interior face midpoints
1316                                                  */
1317
1318                                         /* vertical */
1319                                 for (x=1; x<gridSize-1; x++) {
1320                                         for (y=0; y<gridSize-1; y++) {
1321                                                 int fx = x*2;
1322                                                 int fy = y*2+1;
1323                                                 void *co0 = FACE_getIFCo(f, curLvl, S, x, y+0);
1324                                                 void *co1 = FACE_getIFCo(f, curLvl, S, x, y+1);
1325                                                 void *co2 = FACE_getIFCo(f, nextLvl, S, fx-1, fy);
1326                                                 void *co3 = FACE_getIFCo(f, nextLvl, S, fx+1, fy);
1327                                                 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
1328
1329                                                 ss->meshIFC.vertDataAvg4(ss->meshData, co, co0, co1, co2, co3);
1330                                         }
1331                                 }
1332
1333                                         /* horizontal */
1334                                 for (y=1; y<gridSize-1; y++) {
1335                                         for (x=0; x<gridSize-1; x++) {
1336                                                 int fx = x*2+1;
1337                                                 int fy = y*2;
1338                                                 void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y);
1339                                                 void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y);
1340                                                 void *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy-1);
1341                                                 void *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy+1);
1342                                                 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
1343
1344                                                 ss->meshIFC.vertDataAvg4(ss->meshData, co, co0, co1, co2, co3);
1345                                         }
1346                                 }
1347                         }
1348                 }
1349
1350                         /* exterior edge midpoints
1351                          *  o old exterior edge points
1352                          *  o new interior face midpoints
1353                          */
1354                 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1355                         CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
1356                         float sharpness = EDGE_getSharpness(e, curLvl, ss);
1357
1358                         if (_edge_isBoundary(e) || sharpness>1.0) {
1359                                 for (x=0; x<edgeSize-1; x++) {
1360                                         int fx = x*2 + 1;
1361                                         void *co0 = EDGE_getCo(e, curLvl, x+0);
1362                                         void *co1 = EDGE_getCo(e, curLvl, x+1);
1363                                         void *co = EDGE_getCo(e, nextLvl, fx);
1364
1365                                         ss->meshIFC.vertDataCopy(ss->meshData, co, co0);
1366                                         ss->meshIFC.vertDataAdd(ss->meshData, co, co1);
1367                                         ss->meshIFC.vertDataMulN(ss->meshData, co, 0.5);
1368                                 }
1369                         } else {
1370                                 for (x=0; x<edgeSize-1; x++) {
1371                                         int fx = x*2 + 1;
1372                                         void *co0 = EDGE_getCo(e, curLvl, x+0);
1373                                         void *co1 = EDGE_getCo(e, curLvl, x+1);
1374                                         void *co = EDGE_getCo(e, nextLvl, fx);
1375                                         int numFaces = 0;
1376
1377                                         ss->meshIFC.vertDataCopy(ss->meshData, q, co0);
1378                                         ss->meshIFC.vertDataAdd(ss->meshData, q, co1);
1379
1380                                         for (i=0; i<e->numFaces; i++) {
1381                                                 CCGFace *f = e->faces[i];
1382                                                 ss->meshIFC.vertDataAdd(ss->meshData, q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
1383                                                 numFaces++;
1384                                         }
1385
1386                                         ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/(2.0f+numFaces));
1387
1388                                         ss->meshIFC.vertDataCopy(ss->meshData, r, co0);
1389                                         ss->meshIFC.vertDataAdd(ss->meshData, r, co1);
1390                                         ss->meshIFC.vertDataMulN(ss->meshData, r, 0.5);
1391
1392                                         ss->meshIFC.vertDataCopy(ss->meshData, co, q);
1393                                         ss->meshIFC.vertDataSub(ss->meshData, r, q);
1394                                         ss->meshIFC.vertDataMulN(ss->meshData, r, sharpness);
1395                                         ss->meshIFC.vertDataAdd(ss->meshData, co, r);
1396                                 }
1397                         }
1398                 }
1399
1400                         /* exterior vertex shift
1401                          *  o old vertex points (shifting)
1402                          *  o old exterior edge points
1403                          *  o new interior face midpoints
1404                          */
1405                 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
1406                         CCGVert *v = (CCGVert*) effectedV[ptrIdx];
1407                         void *co = VERT_getCo(v, curLvl);
1408                         void *nCo = VERT_getCo(v, nextLvl);
1409                         int sharpCount = 0;
1410                         float avgSharpness = 0.0;
1411
1412                         for (i=0; i<v->numEdges; i++) {
1413                                 CCGEdge *e = v->edges[i];
1414                                 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1415
1416                                 if (sharpness!=0.0f) {
1417                                         sharpCount++;
1418                                         avgSharpness += sharpness;
1419                                 }
1420                         }
1421
1422                         avgSharpness /= sharpCount;
1423                         if (avgSharpness>1.0) {
1424                                 avgSharpness = 1.0;
1425                         }
1426
1427                         if (!v->numEdges) {
1428                                 ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1429                         } else if (_vert_isBoundary(v)) {
1430                                 int numBoundary = 0;
1431
1432                                 ss->meshIFC.vertDataZero(ss->meshData, r);
1433                                 for (i=0; i<v->numEdges; i++) {
1434                                         CCGEdge *e = v->edges[i];
1435                                         if (_edge_isBoundary(e)) {
1436                                                 ss->meshIFC.vertDataAdd(ss->meshData, r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
1437                                                 numBoundary++;
1438                                         }
1439                                 }
1440
1441                                 ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1442                                 ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.75);
1443                                 ss->meshIFC.vertDataMulN(ss->meshData, r, 0.25f/numBoundary);
1444                                 ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1445                         } else {
1446                                 int cornerIdx = (1 + (1<<(curLvl))) - 2;
1447                                 int numEdges = 0, numFaces = 0;
1448
1449                                 ss->meshIFC.vertDataZero(ss->meshData, q);
1450                                 for (i=0; i<v->numFaces; i++) {
1451                                         CCGFace *f = v->faces[i];
1452                                         ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx));
1453                                         numFaces++;
1454                                 }
1455                                 ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/numFaces);
1456                                 ss->meshIFC.vertDataZero(ss->meshData, r);
1457                                 for (i=0; i<v->numEdges; i++) {
1458                                         CCGEdge *e = v->edges[i];
1459                                         ss->meshIFC.vertDataAdd(ss->meshData, r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize));
1460                                         numEdges++;
1461                                 }
1462                                 ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0f/numEdges);
1463
1464                                 ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1465                                 ss->meshIFC.vertDataMulN(ss->meshData, nCo, numEdges-2.0f);
1466                                 ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
1467                                 ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1468                                 ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/numEdges);
1469                         }
1470
1471                         if (sharpCount>1) {
1472                                 ss->meshIFC.vertDataZero(ss->meshData, q);
1473
1474                                 for (i=0; i<v->numEdges; i++) {
1475                                         CCGEdge *e = v->edges[i];
1476                                         float sharpness = EDGE_getSharpness(e, curLvl, ss);
1477
1478                                         if (sharpness != 0.0) {
1479                                                 ss->meshIFC.vertDataAdd(ss->meshData, q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
1480                                         }
1481                                 }
1482
1483                                 ss->meshIFC.vertDataMulN(ss->meshData, q, (float) 1/sharpCount);
1484
1485                                 if (sharpCount!=2) {
1486                                                 // q = q + (co-q)*avgSharpness
1487                                         ss->meshIFC.vertDataCopy(ss->meshData, r, co);
1488                                         ss->meshIFC.vertDataSub(ss->meshData, r, q);
1489                                         ss->meshIFC.vertDataMulN(ss->meshData, r, avgSharpness);
1490                                         ss->meshIFC.vertDataAdd(ss->meshData, q, r);
1491                                 }
1492
1493                                         // r = co*.75 + q*.25
1494                                 ss->meshIFC.vertDataCopy(ss->meshData, r, co);
1495                                 ss->meshIFC.vertDataMulN(ss->meshData, r, .75);
1496                                 ss->meshIFC.vertDataMulN(ss->meshData, q, .25);
1497                                 ss->meshIFC.vertDataAdd(ss->meshData, r, q);
1498
1499                                         // nCo = nCo  + (r-nCo)*avgSharpness
1500                                 ss->meshIFC.vertDataSub(ss->meshData, r, nCo);
1501                                 ss->meshIFC.vertDataMulN(ss->meshData, r, avgSharpness);
1502                                 ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1503                         }
1504                 }
1505
1506                         /* exterior edge interior shift
1507                          *  o old exterior edge midpoints (shifting)
1508                          *  o old exterior edge midpoints
1509                          *  o new interior face midpoints
1510                          */
1511                 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1512                         CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
1513                         float sharpness = EDGE_getSharpness(e, curLvl, ss);
1514                         int sharpCount = 0;
1515                         float avgSharpness = 0.0;
1516
1517                         if (sharpness!=0.0f) {
1518                                 sharpCount = 2;
1519                                 avgSharpness += sharpness;
1520
1521                                 if (avgSharpness>1.0) {
1522                                         avgSharpness = 1.0;
1523                                 }
1524                         } else {
1525                                 sharpCount = 0;
1526                                 avgSharpness = 0;
1527                         }
1528
1529                         if (_edge_isBoundary(e) && sharpCount<2) {
1530                                 for (x=1; x<edgeSize-1; x++) {
1531                                         int fx = x*2;
1532                                         void *co = EDGE_getCo(e, curLvl, x);
1533                                         void *nCo = EDGE_getCo(e, nextLvl, fx);
1534                                         ss->meshIFC.vertDataCopy(ss->meshData, r, EDGE_getCo(e, curLvl, x-1));
1535                                         ss->meshIFC.vertDataAdd(ss->meshData, r, EDGE_getCo(e, curLvl, x+1));
1536                                         ss->meshIFC.vertDataMulN(ss->meshData, r, 0.5);
1537                                         ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1538                                         ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.75);
1539                                         ss->meshIFC.vertDataMulN(ss->meshData, r, 0.25);
1540                                         ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1541                                 }
1542                         } else {
1543                                 for (x=1; x<edgeSize-1; x++) {
1544                                         int fx = x*2;
1545                                         void *co = EDGE_getCo(e, curLvl, x);
1546                                         void *nCo = EDGE_getCo(e, nextLvl, fx);
1547                                         int numFaces = 0;
1548
1549                                         ss->meshIFC.vertDataZero(ss->meshData, q);
1550                                         ss->meshIFC.vertDataZero(ss->meshData, r);
1551                                         ss->meshIFC.vertDataAdd(ss->meshData, r, EDGE_getCo(e, curLvl, x-1));
1552                                         ss->meshIFC.vertDataAdd(ss->meshData, r, EDGE_getCo(e, curLvl, x+1));
1553                                         for (i=0; i<e->numFaces; i++) {
1554                                                 CCGFace *f = e->faces[i];
1555                                                 ss->meshIFC.vertDataAdd(ss->meshData, q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize));
1556                                                 ss->meshIFC.vertDataAdd(ss->meshData, q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize));
1557
1558                                                 ss->meshIFC.vertDataAdd(ss->meshData, r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize));
1559                                                 numFaces++;
1560                                         }
1561                                         ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0/(numFaces*2.0f));
1562                                         ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0/(2.0f + numFaces));
1563
1564                                         ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1565                                         ss->meshIFC.vertDataMulN(ss->meshData, nCo, (float) numFaces);
1566                                         ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
1567                                         ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1568                                         ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/(2+numFaces));
1569
1570                                         if (sharpCount==2) {
1571                                                 ss->meshIFC.vertDataCopy(ss->meshData, q, co);
1572                                                 ss->meshIFC.vertDataMulN(ss->meshData, q, 6.0f);
1573                                                 ss->meshIFC.vertDataAdd(ss->meshData, q, EDGE_getCo(e, curLvl, x-1));
1574                                                 ss->meshIFC.vertDataAdd(ss->meshData, q, EDGE_getCo(e, curLvl, x+1));
1575                                                 ss->meshIFC.vertDataMulN(ss->meshData, q, 1/8.0f);
1576
1577                                                 ss->meshIFC.vertDataSub(ss->meshData, q, nCo);
1578                                                 ss->meshIFC.vertDataMulN(ss->meshData, q, avgSharpness);
1579                                                 ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
1580                                         }
1581                                 }
1582                         }
1583                 }
1584
1585                 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1586                         CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1587
1588                                 /* interior center point shift
1589                                  *  o old face center point (shifting)
1590                                  *  o old interior edge points
1591                                  *  o new interior face midpoints
1592                                  */
1593                         ss->meshIFC.vertDataZero(ss->meshData, q);
1594                         for (S=0; S<f->numVerts; S++) {
1595                                 ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getIFCo(f, nextLvl, S, 1, 1));
1596                         }
1597                         ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/f->numVerts);
1598                         ss->meshIFC.vertDataZero(ss->meshData, r);
1599                         for (S=0; S<f->numVerts; S++) {
1600                                 ss->meshIFC.vertDataAdd(ss->meshData, r, FACE_getIECo(f, curLvl, S, 1));
1601                         }
1602                         ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0f/f->numVerts);
1603
1604                         ss->meshIFC.vertDataMulN(ss->meshData, FACE_getCenterData(f), f->numVerts-2.0f);
1605                         ss->meshIFC.vertDataAdd(ss->meshData, FACE_getCenterData(f), q);
1606                         ss->meshIFC.vertDataAdd(ss->meshData, FACE_getCenterData(f), r);
1607                         ss->meshIFC.vertDataMulN(ss->meshData, FACE_getCenterData(f), 1.0f/f->numVerts);
1608
1609                         for (S=0; S<f->numVerts; S++) {
1610                                         /* interior face shift
1611                                          *  o old interior face point (shifting)
1612                                          *  o new interior edge midpoints
1613                                          *  o new interior face midpoints
1614                                          */
1615                                 for (x=1; x<gridSize-1; x++) {
1616                                         for (y=1; y<gridSize-1; y++) {
1617                                                 int fx = x*2;
1618                                                 int fy = y*2;
1619                                                 void *co = FACE_getIFCo(f, curLvl, S, x, y);
1620                                                 void *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
1621                                                 
1622                                                 ss->meshIFC.vertDataAvg4(ss->meshData, q, FACE_getIFCo(f, nextLvl, S, fx-1, fy-1),
1623                                                         FACE_getIFCo(f, nextLvl, S, fx+1, fy-1),
1624                                                         FACE_getIFCo(f, nextLvl, S, fx+1, fy+1),
1625                                                         FACE_getIFCo(f, nextLvl, S, fx-1, fy+1));
1626
1627                                                 ss->meshIFC.vertDataAvg4(ss->meshData, r, FACE_getIFCo(f, nextLvl, S, fx-1, fy+0),
1628                                                         FACE_getIFCo(f, nextLvl, S, fx+1, fy+0),
1629                                                         FACE_getIFCo(f, nextLvl, S, fx+0, fy-1),
1630                                                         FACE_getIFCo(f, nextLvl, S, fx+0, fy+1));
1631
1632                                                 ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1633                                                 ss->meshIFC.vertDataSub(ss->meshData, nCo, q);
1634                                                 ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.25f);
1635                                                 ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1636                                         }
1637                                 }
1638
1639                                         /* interior edge interior shift
1640                                          *  o old interior edge point (shifting)
1641                                          *  o new interior edge midpoints
1642                                          *  o new interior face midpoints
1643                                          */
1644                                 for (x=1; x<gridSize-1; x++) {
1645                                         int fx = x*2;
1646                                         void *co = FACE_getIECo(f, curLvl, S, x);
1647                                         void *nCo = FACE_getIECo(f, nextLvl, S, fx);
1648                                         
1649                                         ss->meshIFC.vertDataAvg4(ss->meshData, q, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx-1),
1650                                                 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1),
1651                                                 FACE_getIFCo(f, nextLvl, S, fx+1, +1),
1652                                                 FACE_getIFCo(f, nextLvl, S, fx-1, +1));
1653
1654                                         ss->meshIFC.vertDataAvg4(ss->meshData, r, FACE_getIECo(f, nextLvl, S, fx-1),
1655                                                 FACE_getIECo(f, nextLvl, S, fx+1),
1656                                                 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx),
1657                                                 FACE_getIFCo(f, nextLvl, S, fx, 1));
1658
1659                                         ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
1660                                         ss->meshIFC.vertDataSub(ss->meshData, nCo, q);
1661                                         ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.25f);
1662                                         ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
1663                                 }
1664                         }
1665                 }
1666
1667
1668
1669                         /* copy down */
1670                 edgeSize = 1 + (1<<(nextLvl));
1671                 gridSize = 1 + (1<<((nextLvl)-1));
1672                 cornerIdx = gridSize-1;
1673                 for (i=0; i<numEffectedE; i++) {
1674                         CCGEdge *e = effectedE[i];
1675                         ss->meshIFC.vertDataCopy(ss->meshData, EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
1676                         ss->meshIFC.vertDataCopy(ss->meshData, EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl));
1677                 }
1678                 for (i=0; i<numEffectedF; i++) {
1679                         CCGFace *f = effectedF[i];
1680                         for (S=0; S<f->numVerts; S++) {
1681                                 CCGEdge *e = FACE_getEdges(f)[S];
1682                                 CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
1683
1684                                 ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
1685                                 ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
1686                                 ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
1687                                 ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx));
1688                                 for (x=1; x<gridSize-1; x++) {
1689                                         void *co = FACE_getIECo(f, nextLvl, S, x);
1690                                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, x, 0), co);
1691                                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 0, x), co);
1692                                 }
1693                                 for (x=0; x<gridSize-1; x++) {
1694                                         int eI = gridSize-1-x;
1695                                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
1696                                         ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
1697                                 }
1698                         }
1699                 }
1700         }
1701
1702 #define FACE_getIFNo(f, lvl, S, x, y)   _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
1703 #define AddNo(a, b)             {a[0]+= b[0], a[1]+= b[1], a[2] += b[2];}
1704 #define CopyNo(a, b)    {a[0] = b[0], a[1] = b[1], a[2]  = b[2];}
1705         if (ss->calcVertNormals) {
1706                 int lvl = ss->subdivLevels;
1707                 int edgeSize = 1 + (1<<lvl);
1708                 int gridSize = 1 + (1<<(lvl-1));
1709                 int normalDataOffset = ss->normalDataOffset;
1710
1711                 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1712                         CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1713                         int S, x, y;
1714
1715                         for (S=0; S<f->numVerts; S++) {
1716                                 for (y=0; y<gridSize; y++) {
1717                                         for (x=0; x<gridSize; x++) {
1718                                                 float *no = FACE_getIFNo(f, lvl, S, x, y);
1719                                                 no[0] = no[1] = no[2] = 0.0;
1720                                         }
1721                                 }
1722                         }
1723                 }
1724
1725                 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1726                         CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1727                         int S, x, y;
1728
1729                         for (S=0; S<f->numVerts; S++) {
1730                                 for (y=0; y<gridSize-1; y++) {
1731                                         for (x=0; x<gridSize-1; x++) {
1732                                                 float *a = FACE_getIFCo(f, lvl, S, x+0, y+0);
1733                                                 float *b = FACE_getIFCo(f, lvl, S, x+1, y+0);
1734                                                 float *c = FACE_getIFCo(f, lvl, S, x+1, y+1);
1735                                                 float *d = FACE_getIFCo(f, lvl, S, x+0, y+1);
1736                                                 float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
1737                                                 float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
1738                                                 float no[3];
1739
1740                                                 no[0] = b_dY*a_cZ - b_dZ*a_cY;
1741                                                 no[1] = b_dZ*a_cX - b_dX*a_cZ;
1742                                                 no[2] = b_dX*a_cY - b_dY*a_cX;
1743
1744                                                 AddNo(FACE_getIFNo(f, lvl, S, x+0, y+0), no);
1745                                                 AddNo(FACE_getIFNo(f, lvl, S, x+1, y+0), no);
1746                                                 AddNo(FACE_getIFNo(f, lvl, S, x+1, y+1), no);
1747                                                 AddNo(FACE_getIFNo(f, lvl, S, x+0, y+1), no);
1748
1749                                                 if (x==0 && y==0) {
1750                                                         int K;
1751
1752                                                         AddNo(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, 1), no);
1753                                                         AddNo(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no);
1754
1755                                                         for (K=0; K<f->numVerts; K++) {
1756                                                                 if (K!=S) {
1757                                                                         AddNo(FACE_getIFNo(f, lvl, K, 0, 0), no);
1758                                                                 }
1759                                                         }
1760                                                 } else if (y==0) {
1761                                                         AddNo(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no);
1762                                                         AddNo(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x+1), no);
1763                                                 } else if (x==0) {
1764                                                         AddNo(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no);
1765                                                         AddNo(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y+1, 0), no);
1766                                                 }
1767                                         }
1768                                 }
1769                         }
1770                 }
1771                 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
1772                         CCGVert *v = (CCGVert*) effectedV[ptrIdx];
1773                         float no[3] = {0};
1774
1775                         for (i=0; i<v->numFaces; i++) {
1776                                 CCGFace *f = v->faces[i];
1777                                 AddNo(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1));
1778                         }
1779
1780                         for (i=0; i<v->numFaces; i++) {
1781                                 CCGFace *f = v->faces[i];
1782                                 CopyNo(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no);
1783                         }
1784                 }
1785                 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1786                         CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
1787                         int x;
1788
1789                         for (x=0; x<edgeSize; x++) {
1790                                 float *no = _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset);
1791                                 no[0] = no[1] = no[2] = 0.0;
1792                         }
1793
1794                         for (i=0; i<e->numFaces; i++) {
1795                                 CCGFace *f = e->faces[i];
1796
1797                                 for (x=1; x<edgeSize-1; x++) {
1798                                         AddNo(  _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset),
1799                                                         _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
1800                                 }
1801                         }
1802
1803                         for (i=0; i<e->numFaces; i++) {
1804                                 CCGFace *f = e->faces[i];
1805
1806                                 for (x=1; x<edgeSize-1; x++) {
1807                                         CopyNo( _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
1808                                                         _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset));
1809                                 }
1810                         }
1811                 }
1812                 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1813                         CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1814                         int S;
1815
1816                         for (S=0; S<f->numVerts; S++) {
1817                                 CopyNo( FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1),
1818                                                 FACE_getIFNo(f, lvl, S, gridSize-1, 0));
1819                         }
1820                 }
1821                 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1822                         CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1823                         int S, x, y;
1824
1825                         for (S=0; S<f->numVerts; S++) {
1826                                 for (y=0; y<gridSize; y++) {
1827                                         for (x=0; x<gridSize; x++) {
1828                                                 float *no = FACE_getIFNo(f, lvl, S, x, y);
1829                                                 float length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
1830
1831                                                 if (length>FLT_EPSILON) {
1832                                                         float invLength = 1.0f/length;
1833                                                         no[0] *= invLength;
1834                                                         no[1] *= invLength;
1835                                                         no[2] *= invLength;
1836                                                 } else {
1837                                                         no[0] = no[1] = no[2] = 0.0;
1838                                                 }
1839                                         }
1840                                 }
1841                         }
1842                 }
1843         }
1844 #undef CopyNo
1845 #undef AddNo
1846 #undef FACE_getIFNo
1847
1848 #undef VERT_getCo
1849 #undef EDGE_getCo
1850 #undef FACE_getIECo
1851 #undef FACE_getIFCo
1852
1853         CCGSUBSURF_free(ss, effectedF);
1854         CCGSUBSURF_free(ss, effectedE);
1855         CCGSUBSURF_free(ss, effectedV);
1856 }
1857
1858 /*** External API accessor functions ***/
1859
1860 int ccgSubSurf_getNumVerts(CCGSubSurf *ss) {
1861         return ss->vMap->numEntries;
1862 }
1863 int ccgSubSurf_getNumEdges(CCGSubSurf *ss) {
1864         return ss->eMap->numEntries;
1865 }
1866 int ccgSubSurf_getNumFaces(CCGSubSurf *ss) {
1867         return ss->fMap->numEntries;
1868 }
1869
1870 CCGVert *ccgSubSurf_getVert(CCGSubSurf *ss, CCGVertHDL v) {
1871         return (CCGVert*) _ehash_lookup(ss->vMap, v);
1872 }
1873 CCGEdge *ccgSubSurf_getEdge(CCGSubSurf *ss, CCGEdgeHDL e) {
1874         return (CCGEdge*) _ehash_lookup(ss->eMap, e);
1875 }
1876 CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f) {
1877         return (CCGFace*) _ehash_lookup(ss->fMap, f);
1878 }
1879
1880 int ccgSubSurf_getSubdivisionLevels(CCGSubSurf *ss) {
1881         return ss->subdivLevels;
1882 }
1883 int ccgSubSurf_getEdgeSize(CCGSubSurf *ss) {
1884         return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels);
1885 }
1886 int ccgSubSurf_getEdgeLevelSize(CCGSubSurf *ss, int level) {
1887         if (level<1 || level>ss->subdivLevels) {
1888                 return -1;
1889         } else {
1890                 return 1 + (1<<level);
1891         }
1892 }
1893 int ccgSubSurf_getGridSize(CCGSubSurf *ss) {
1894         return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels);
1895 }
1896 int ccgSubSurf_getGridLevelSize(CCGSubSurf *ss, int level) {
1897         if (level<1 || level>ss->subdivLevels) {
1898                 return -1;
1899         } else {
1900                 return 1 + (1<<(level-1));
1901         }
1902 }
1903
1904 /* Vert accessors */
1905
1906 CCGVertHDL ccgSubSurf_getVertVertHandle(CCGSubSurf *ss, CCGVert *v) {
1907         return v->vHDL;
1908 }
1909 int ccgSubSurf_getVertAge(CCGSubSurf *ss, CCGVert *v) {
1910         if (ss->useAgeCounts) {
1911                 byte *userData = ccgSubSurf_getVertUserData(ss, v);
1912                 return ss->currentAge - *((int*) &userData[ss->vertUserAgeOffset]);
1913         } else {
1914                 return 0;
1915         }
1916 }
1917 void *ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v) {
1918         return VERT_getLevelData(v) + ss->meshIFC.vertDataSize*(ss->subdivLevels+1);
1919 }
1920 int ccgSubSurf_getVertNumFaces(CCGSubSurf *ss, CCGVert *v) {
1921         return v->numFaces;
1922 }
1923 CCGFace *ccgSubSurf_getVertFace(CCGSubSurf *ss, CCGVert *v, int index) {
1924         if (index<0 || index>=v->numFaces) {
1925                 return NULL;
1926         } else {
1927                 return v->faces[index];
1928         }
1929 }
1930 int ccgSubSurf_getVertNumEdges(CCGSubSurf *ss, CCGVert *v) {
1931         return v->numEdges;
1932 }
1933 CCGEdge *ccgSubSurf_getVertEdge(CCGSubSurf *ss, CCGVert *v, int index) {
1934         if (index<0 || index>=v->numEdges) {
1935                 return NULL;
1936         } else {
1937                 return v->edges[index];
1938         }
1939 }
1940 void *ccgSubSurf_getVertData(CCGSubSurf *ss, CCGVert *v) {
1941         return ccgSubSurf_getVertLevelData(ss, v, ss->subdivLevels);
1942 }
1943 void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level) {
1944         if (level<0 || level>ss->subdivLevels) {
1945                 return NULL;
1946         } else {
1947                 return _vert_getCo(v, level, ss->meshIFC.vertDataSize);
1948         }
1949 }
1950
1951 /* Edge accessors */
1952
1953 CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle(CCGSubSurf *ss, CCGEdge *e) {
1954         return e->eHDL;
1955 }
1956 int ccgSubSurf_getEdgeAge(CCGSubSurf *ss, CCGEdge *e) {
1957         if (ss->useAgeCounts) {
1958                 byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
1959                 return ss->currentAge - *((int*) &userData[ss->edgeUserAgeOffset]);
1960         } else {
1961                 return 0;
1962         }
1963 }
1964 void *ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e) {
1965         return EDGE_getLevelData(e) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1);
1966 }
1967 int ccgSubSurf_getEdgeNumFaces(CCGSubSurf *ss, CCGEdge *e) {
1968         return e->numFaces;
1969 }
1970 CCGFace *ccgSubSurf_getEdgeFace(CCGSubSurf *ss, CCGEdge *e, int index) {
1971         if (index<0 || index>=e->numFaces) {
1972                 return NULL;
1973         } else {
1974                 return e->faces[index];
1975         }
1976 }
1977 CCGVert *ccgSubSurf_getEdgeVert0(CCGSubSurf *ss, CCGEdge *e) {
1978         return e->v0;
1979 }
1980 CCGVert *ccgSubSurf_getEdgeVert1(CCGSubSurf *ss, CCGEdge *e) {
1981         return e->v1;
1982 }
1983 void *ccgSubSurf_getEdgeDataArray(CCGSubSurf *ss, CCGEdge *e) {
1984         return ccgSubSurf_getEdgeData(ss, e, 0);
1985 }
1986 void *ccgSubSurf_getEdgeData(CCGSubSurf *ss, CCGEdge *e, int x) {
1987         return ccgSubSurf_getEdgeLevelData(ss, e, x, ss->subdivLevels);
1988 }
1989 void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level) {
1990         if (level<0 || level>ss->subdivLevels) {
1991                 return NULL;
1992         } else {
1993                 return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
1994         }
1995 }
1996
1997 /* Face accessors */
1998
1999 CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *ss, CCGFace *f) {
2000         return f->fHDL;
2001 }
2002 int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) {
2003         if (ss->useAgeCounts) {
2004                 byte *userData = ccgSubSurf_getFaceUserData(ss, f);
2005                 return ss->currentAge - *((int*) &userData[ss->faceUserAgeOffset]);
2006         } else {
2007                 return 0;
2008         }
2009 }
2010 void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) {
2011         int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
2012         return FACE_getCenterData(f) + ss->meshIFC.vertDataSize *(1 + f->numVerts*maxGridSize + f->numVerts*maxGridSize*maxGridSize);
2013 }
2014 int ccgSubSurf_getFaceNumVerts(CCGSubSurf *ss, CCGFace *f) {
2015         return f->numVerts;
2016 }
2017 CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *ss, CCGFace *f, int index) {
2018         if (index<0 || index>=f->numVerts) {
2019                 return NULL;
2020         } else {
2021                 return FACE_getVerts(f)[index];
2022         }
2023 }
2024 CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *ss, CCGFace *f, int index) {
2025         if (index<0 || index>=f->numVerts) {
2026                 return NULL;
2027         } else {
2028                 return FACE_getEdges(f)[index];
2029         }
2030 }
2031 void *ccgSubSurf_getFaceCenterData(CCGSubSurf *ss, CCGFace *f) {
2032         return FACE_getCenterData(f);
2033 }
2034 void *ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
2035         return ccgSubSurf_getFaceGridEdgeData(ss, f, gridIndex, 0);
2036 }
2037 void *ccgSubSurf_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x) {
2038         return _face_getIECo(f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize);
2039 }
2040 void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
2041         return ccgSubSurf_getFaceGridData(ss, f, gridIndex, 0, 0);
2042 }
2043 void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y) {
2044         return _face_getIFCo(f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize);
2045 }
2046
2047 /*** External API iterator functions ***/
2048
2049 CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss) {
2050         return (CCGVertIterator*) _ehashIterator_new(ss->vMap);
2051 }
2052 CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss) {
2053         return (CCGEdgeIterator*) _ehashIterator_new(ss->eMap);
2054 }
2055 CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss) {
2056         return (CCGFaceIterator*) _ehashIterator_new(ss->fMap);
2057 }
2058
2059 CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi) {
2060         return (CCGVert*) _ehashIterator_getCurrent((EHashIterator*) vi);
2061 }
2062 int ccgVertIterator_isStopped(CCGVertIterator *vi) {
2063         return _ehashIterator_isStopped((EHashIterator*) vi);
2064 }
2065 void ccgVertIterator_next(CCGVertIterator *vi) {
2066         _ehashIterator_next((EHashIterator*) vi); 
2067 }
2068 void ccgVertIterator_free(CCGVertIterator *vi) {
2069         _ehashIterator_free((EHashIterator*) vi);
2070 }
2071
2072 CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi) {
2073         return (CCGEdge*) _ehashIterator_getCurrent((EHashIterator*) vi);
2074 }
2075 int ccgEdgeIterator_isStopped(CCGEdgeIterator *vi) {
2076         return _ehashIterator_isStopped((EHashIterator*) vi);
2077 }
2078 void ccgEdgeIterator_next(CCGEdgeIterator *vi) {
2079         _ehashIterator_next((EHashIterator*) vi); 
2080 }
2081 void ccgEdgeIterator_free(CCGEdgeIterator *vi) {
2082         _ehashIterator_free((EHashIterator*) vi);
2083 }
2084
2085 CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi) {
2086         return (CCGFace*) _ehashIterator_getCurrent((EHashIterator*) vi);
2087 }
2088 int ccgFaceIterator_isStopped(CCGFaceIterator *vi) {
2089         return _ehashIterator_isStopped((EHashIterator*) vi);
2090 }
2091 void ccgFaceIterator_next(CCGFaceIterator *vi) {
2092         _ehashIterator_next((EHashIterator*) vi); 
2093 }
2094 void ccgFaceIterator_free(CCGFaceIterator *vi) {
2095         _ehashIterator_free((EHashIterator*) vi);
2096 }
2097
2098 /*** Extern API final vert/edge/face interface ***/
2099
2100 int ccgSubSurf_getNumFinalVerts(CCGSubSurf *ss) {
2101         int edgeSize = 1 + (1<<ss->subdivLevels);
2102         int gridSize = 1 + (1<<(ss->subdivLevels-1));
2103         int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2)));
2104         return numFinalVerts;
2105 }
2106 int ccgSubSurf_getNumFinalEdges(CCGSubSurf *ss) {
2107         int edgeSize = 1 + (1<<ss->subdivLevels);
2108         int gridSize = 1 + (1<<(ss->subdivLevels-1));
2109         int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1)));
2110         return numFinalEdges;
2111 }
2112 int ccgSubSurf_getNumFinalFaces(CCGSubSurf *ss) {
2113         int gridSize = 1 + (1<<(ss->subdivLevels-1));
2114         int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1));
2115         return numFinalFaces;
2116 }