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