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