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