8 #include "CCGSubSurf.h"
12 typedef unsigned char byte;
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
22 typedef struct _EHEntry EHEntry;
27 typedef struct _EHash {
29 int numEntries, curSize, curSizeIdx;
31 CCGAllocatorIFC allocatorIFC;
32 CCGAllocatorHDL allocator;
35 #define EHASH_alloc(eh, nb) ((eh)->allocatorIFC.alloc((eh)->allocator, nb))
36 #define EHASH_free(eh, ptr) ((eh)->allocatorIFC.free((eh)->allocator, ptr))
38 #define EHASH_hash(eh, item) (((unsigned long) (item))%((unsigned int) (eh)->curSize))
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;
46 while (kHashSizes[eh->curSizeIdx]<estimatedNumEntries)
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));
54 typedef void (*EHEntryFreeFP)(EHEntry *, void *);
55 static void _ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *userData) {
56 int numBuckets = eh->curSize;
58 while (numBuckets--) {
59 EHEntry *entry = eh->buckets[numBuckets];
62 EHEntry *next = entry->next;
64 freeEntry(entry, userData);
70 EHASH_free(eh, eh->buckets);
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;
81 if (eh->numEntries > (numBuckets*3)) {
82 EHEntry **oldBuckets = eh->buckets;
83 eh->curSize = kHashSizes[++eh->curSizeIdx];
85 eh->buckets = EHASH_alloc(eh, eh->curSize*sizeof(*eh->buckets));
86 memset(eh->buckets, 0, eh->curSize*sizeof(*eh->buckets));
88 while (numBuckets--) {
89 for (entry = oldBuckets[numBuckets]; entry;) {
90 EHEntry *next = entry->next;
92 hash = EHASH_hash(eh, entry->key);
93 entry->next = eh->buckets[hash];
94 eh->buckets[hash] = entry;
100 EHASH_free(eh, oldBuckets);
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];
109 for (; (entry = *prevp); prevp = (void**) &entry->next) {
110 if (entry->key==key) {
111 *prevp_r = (void**) prevp;
119 static void *_ehash_lookup(EHash *eh, void *key) {
120 int hash = EHASH_hash(eh, key);
123 for (entry = eh->buckets[hash]; entry; entry = entry->next)
132 typedef struct _EHashIterator {
138 static EHashIterator *_ehashIterator_new(EHash *eh) {
139 EHashIterator *ehi = EHASH_alloc(eh, sizeof(*ehi));
141 ehi->curEntry = NULL;
143 while (!ehi->curEntry) {
145 if (ehi->curBucket==ehi->eh->curSize)
147 ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
151 static void _ehashIterator_free(EHashIterator *ehi) {
152 EHASH_free(ehi->eh, ehi);
155 static void *_ehashIterator_getCurrent(EHashIterator *ehi) {
156 return ehi->curEntry;
159 static void _ehashIterator_next(EHashIterator *ehi) {
161 ehi->curEntry = ehi->curEntry->next;
162 while (!ehi->curEntry) {
164 if (ehi->curBucket==ehi->eh->curSize)
166 ehi->curEntry = ehi->eh->buckets[ehi->curBucket];
170 static int _ehashIterator_isStopped(EHashIterator *ehi) {
171 return !ehi->curEntry;
176 static void *_stdAllocator_alloc(CCGAllocatorHDL a, int numBytes) {
177 return malloc(numBytes);
179 static void *_stdAllocator_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) {
180 return realloc(ptr, newSize);
182 static void _stdAllocator_free(CCGAllocatorHDL a, void *ptr) {
186 static CCGAllocatorIFC *_getStandardAllocatorIFC(void) {
187 static CCGAllocatorIFC ifc;
189 ifc.alloc = _stdAllocator_alloc;
190 ifc.realloc = _stdAllocator_realloc;
191 ifc.free = _stdAllocator_free;
199 static int VertDataEqual(float *a, float *b) {
200 return a[0]==b[0] && a[1]==b[1] && a[2]==b[2];
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) \
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; \
214 #define NormZero(av) { float *a = (float*) av; a[0] = a[1] = a[2] = 0.0f; }
215 #define NormCopy(av, bv) { float *a = (float*) av, *b = (float*) bv; a[0] =b[0]; a[1] =b[1]; a[2] =b[2]; }
216 #define NormAdd(av, bv) { float *a = (float*) av, *b = (float*) bv; a[0]+=b[0]; a[1]+=b[1]; a[2]+=b[2]; }
219 static int _edge_isBoundary(CCGEdge *e);
224 Vert_eEffected= (1<<0),
225 Vert_eChanged= (1<<1),
229 Edge_eEffected= (1<<0),
232 Face_eEffected= (1<<0),
236 CCGVert *next; /* EHData.next */
237 CCGVertHDL vHDL; /* EHData.key */
239 short numEdges, numFaces, flags, pad;
246 #define VERT_getLevelData(v) ((byte*) &(v)[1])
249 CCGEdge *next; /* EHData.next */
250 CCGEdgeHDL eHDL; /* EHData.key */
252 short numFaces, flags;
261 #define EDGE_getLevelData(e) ((byte*) &(e)[1])
264 CCGFace *next; /* EHData.next */
265 CCGFaceHDL fHDL; /* EHData.key */
267 short numVerts, flags, pad1, pad2;
275 #define FACE_getVerts(f) ((CCGVert**) &(f)[1])
276 #define FACE_getEdges(f) ((CCGEdge**) &(FACE_getVerts(f)[(f)->numVerts]))
277 #define FACE_getCenterData(f) ((byte*) &(FACE_getEdges(f)[(f)->numVerts]))
288 EHash *vMap; /* map of CCGVertHDL -> Vert */
289 EHash *eMap; /* map of CCGEdgeHDL -> Edge */
290 EHash *fMap; /* map of CCGFaceHDL -> Face */
294 CCGAllocatorIFC allocatorIFC;
295 CCGAllocatorHDL allocator;
299 int allowEdgeCreation;
300 float defaultCreaseValue;
301 void *defaultEdgeUserData;
305 // data for calc vert normals
307 int normalDataOffset;
309 // data for age'ing (to debug sync)
312 int vertUserAgeOffset;
313 int edgeUserAgeOffset;
314 int faceUserAgeOffset;
316 // data used during syncing
319 EHash *oldVMap, *oldEMap, *oldFMap;
325 #define CCGSUBSURF_alloc(ss, nb) ((ss)->allocatorIFC.alloc((ss)->allocator, nb))
326 #define CCGSUBSURF_realloc(ss, ptr, nb, ob) ((ss)->allocatorIFC.realloc((ss)->allocator, ptr, nb, ob))
327 #define CCGSUBSURF_free(ss, ptr) ((ss)->allocatorIFC.free((ss)->allocator, ptr))
331 static CCGVert *_vert_new(CCGVertHDL vHDL, int levels, int dataSize, CCGSubSurf *ss) {
332 CCGVert *v = CCGSUBSURF_alloc(ss, sizeof(CCGVert) + ss->meshIFC.vertDataSize * (ss->subdivLevels+1) + ss->meshIFC.vertUserSize);
338 v->numEdges = v->numFaces = 0;
341 userData = ccgSubSurf_getVertUserData(ss, v);
342 memset(userData, 0, ss->meshIFC.vertUserSize);
343 if (ss->useAgeCounts) *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
347 static void _vert_remEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss) {
349 for (i=0; i<v->numEdges; i++) {
350 if (v->edges[i]==e) {
351 v->edges[i] = v->edges[--v->numEdges];
356 static void _vert_remFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) {
358 for (i=0; i<v->numFaces; i++) {
359 if (v->faces[i]==f) {
360 v->faces[i] = v->faces[--v->numFaces];
365 static void _vert_addEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss) {
366 v->edges = CCGSUBSURF_realloc(ss, v->edges, (v->numEdges+1)*sizeof(*v->edges), v->numEdges*sizeof(*v->edges));
367 v->edges[v->numEdges++] = e;
369 static void _vert_addFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) {
370 v->faces = CCGSUBSURF_realloc(ss, v->faces, (v->numFaces+1)*sizeof(*v->faces), v->numFaces*sizeof(*v->faces));
371 v->faces[v->numFaces++] = f;
373 static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) {
375 for (i=0; i<v->numEdges; i++) {
376 CCGEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse
377 if ( (e->v0==v && e->v1==vQ) ||
378 (e->v1==v && e->v0==vQ))
383 static int _vert_isBoundary(CCGVert *v) {
385 for (i=0; i<v->numEdges; i++)
386 if (_edge_isBoundary(v->edges[i]))
391 static void *_vert_getCo(CCGVert *v, int lvl, int dataSize) {
392 return &VERT_getLevelData(v)[lvl*dataSize];
394 static float *_vert_getNo(CCGVert *v, int lvl, int dataSize, int normalDataOffset) {
395 return (float*) &VERT_getLevelData(v)[lvl*dataSize + normalDataOffset];
398 static void _vert_free(CCGVert *v, CCGSubSurf *ss) {
399 CCGSUBSURF_free(ss, v->edges);
400 CCGSUBSURF_free(ss, v->faces);
401 CCGSUBSURF_free(ss, v);
404 static int VERT_seam(CCGVert *v, CCGSubSurf *ss) {
405 return ((v->flags & Vert_eSeam) != 0);
410 static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float crease, int levels, int dataSize, CCGSubSurf *ss) {
411 CCGEdge *e = CCGSUBSURF_alloc(ss, sizeof(CCGEdge) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1) + ss->meshIFC.edgeUserSize);
421 _vert_addEdge(v0, e, ss);
422 _vert_addEdge(v1, e, ss);
424 userData = ccgSubSurf_getEdgeUserData(ss, e);
425 memset(userData, 0, ss->meshIFC.edgeUserSize);
426 if (ss->useAgeCounts) *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
430 static void _edge_remFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) {
432 for (i=0; i<e->numFaces; i++) {
433 if (e->faces[i]==f) {
434 e->faces[i] = e->faces[--e->numFaces];
439 static void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) {
440 e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces+1)*sizeof(*e->faces), e->numFaces*sizeof(*e->faces));
441 e->faces[e->numFaces++] = f;
443 static int _edge_isBoundary(CCGEdge *e) {
444 return e->numFaces<2;
447 static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ) {
455 static void *_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize) {
456 int levelBase = lvl + (1<<lvl) - 1;
457 return &EDGE_getLevelData(e)[dataSize*(levelBase + x)];
460 static float *_edge_getNo(CCGEdge *e, int lvl, int x, int dataSize, int normalDataOffset) {
461 int levelBase = lvl + (1<<lvl) - 1;
462 return (float*) &EDGE_getLevelData(e)[dataSize*(levelBase + x) + normalDataOffset];
465 static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize) {
466 int levelBase = lvl + (1<<lvl) - 1;
468 return &EDGE_getLevelData(e)[dataSize*(levelBase + x)];
470 return &EDGE_getLevelData(e)[dataSize*(levelBase + (1<<lvl) - x)];
474 static void _edge_free(CCGEdge *e, CCGSubSurf *ss) {
475 CCGSUBSURF_free(ss, e->faces);
476 CCGSUBSURF_free(ss, e);
478 static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss) {
479 _vert_remEdge(e->v0, e, ss);
480 _vert_remEdge(e->v1, e, ss);
481 e->v0->flags |= Vert_eEffected;
482 e->v1->flags |= Vert_eEffected;
486 static float EDGE_getSharpness(CCGEdge *e, int lvl, CCGSubSurf *ss) {
487 float sharpness = e->crease;
500 static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, int levels, int dataSize, CCGSubSurf *ss) {
501 int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
502 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);
506 f->numVerts = numVerts;
510 for (i=0; i<numVerts; i++) {
511 FACE_getVerts(f)[i] = verts[i];
512 FACE_getEdges(f)[i] = edges[i];
513 _vert_addFace(verts[i], f, ss);
514 _edge_addFace(edges[i], f, ss);
517 userData = ccgSubSurf_getFaceUserData(ss, f);
518 memset(userData, 0, ss->meshIFC.faceUserSize);
519 if (ss->useAgeCounts) *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
524 static void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) {
525 int maxGridSize = 1 + (1<<(levels-1));
526 int spacing = 1<<(levels-lvl);
527 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
528 return &gridBase[dataSize*x*spacing];
530 static void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) {
531 int maxGridSize = 1 + (1<<(levels-1));
532 int spacing = 1<<(levels-lvl);
533 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
534 return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)];
536 static float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) {
537 int maxGridSize = 1 + (1<<(levels-1));
538 int spacing = 1<<(levels-lvl);
539 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
540 return (float*) &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing) + normalDataOffset];
542 static int _face_getVertIndex(CCGFace *f, CCGVert *v) {
544 for (i=0; i<f->numVerts; i++)
545 if (FACE_getVerts(f)[i]==v)
549 static void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) {
550 int maxGridSize = 1 + (1<<(levels-1));
551 int spacing = 1<<(levels-lvl);
554 for (S=0; S<f->numVerts; S++)
555 if (FACE_getEdges(f)[S]==e)
560 if (e->v0!=FACE_getVerts(f)[S]) {
561 eX = (maxGridSize*2 - 1)-1 - eX;
563 y = maxGridSize - 1 - eX;
564 x = maxGridSize - 1 - eY;
566 S = (S+f->numVerts-1)%f->numVerts;
570 S = (S+1)%f->numVerts;
577 return _face_getIFCo(f, levels, S, cx, cy, levels, dataSize);
579 static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) {
580 return (float*) ((byte*) _face_getIFCoEdge(f, e, lvl, eX, eY, levels, dataSize) + normalDataOffset);
582 void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) {
583 float *a = _face_getIFCo(f, lvl, S, x+0, y+0, levels, dataSize);
584 float *b = _face_getIFCo(f, lvl, S, x+1, y+0, levels, dataSize);
585 float *c = _face_getIFCo(f, lvl, S, x+1, y+1, levels, dataSize);
586 float *d = _face_getIFCo(f, lvl, S, x+0, y+1, levels, dataSize);
587 float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
588 float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
591 no[0] = b_dY*a_cZ - b_dZ*a_cY;
592 no[1] = b_dZ*a_cX - b_dX*a_cZ;
593 no[2] = b_dX*a_cY - b_dY*a_cX;
595 length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
597 if (length>FLT_EPSILON) {
598 float invLength = 1.f/length;
608 static void _face_free(CCGFace *f, CCGSubSurf *ss) {
609 CCGSUBSURF_free(ss, f);
611 static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss) {
613 for (j=0; j<f->numVerts; j++) {
614 _vert_remFace(FACE_getVerts(f)[j], f, ss);
615 _edge_remFace(FACE_getEdges(f)[j], f, ss);
616 FACE_getVerts(f)[j]->flags |= Vert_eEffected;
623 CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) {
625 allocatorIFC = _getStandardAllocatorIFC();
629 if (subdivLevels<1) {
632 CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss));
634 ss->allocatorIFC = *allocatorIFC;
635 ss->allocator = allocator;
637 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
638 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
639 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
643 ss->subdivLevels = subdivLevels;
645 ss->allowEdgeCreation = 0;
646 ss->defaultCreaseValue = 0;
647 ss->defaultEdgeUserData = NULL;
649 ss->useAgeCounts = 0;
650 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
652 ss->calcVertNormals = 0;
653 ss->normalDataOffset = 0;
655 ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
656 ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
660 ss->syncState = eSyncState_None;
662 ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL;
663 ss->lenTempArrays = 0;
664 ss->tempVerts = NULL;
665 ss->tempEdges = NULL;
671 void ccgSubSurf_free(CCGSubSurf *ss) {
672 CCGAllocatorIFC allocatorIFC = ss->allocatorIFC;
673 CCGAllocatorHDL allocator = ss->allocator;
676 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_free, ss);
677 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_free, ss);
678 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
680 CCGSUBSURF_free(ss, ss->tempVerts);
681 CCGSUBSURF_free(ss, ss->tempEdges);
684 CCGSUBSURF_free(ss, ss->r);
685 CCGSUBSURF_free(ss, ss->q);
686 if (ss->defaultEdgeUserData) CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
688 _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
689 _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
690 _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
692 CCGSUBSURF_free(ss, ss);
694 if (allocatorIFC.release) {
695 allocatorIFC.release(allocator);
699 CCGError ccgSubSurf_setAllowEdgeCreation(CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData) {
700 if (ss->defaultEdgeUserData) {
701 CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
704 ss->allowEdgeCreation = !!allowEdgeCreation;
705 ss->defaultCreaseValue = defaultCreaseValue;
706 ss->defaultEdgeUserData = CCGSUBSURF_alloc(ss, ss->meshIFC.edgeUserSize);
708 if (defaultUserData) {
709 memcpy(ss->defaultEdgeUserData, defaultUserData, ss->meshIFC.edgeUserSize);
711 memset(ss->defaultEdgeUserData, 0, ss->meshIFC.edgeUserSize);
714 return eCCGError_None;
716 void ccgSubSurf_getAllowEdgeCreation(CCGSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r) {
717 if (allowEdgeCreation_r) *allowEdgeCreation_r = ss->allowEdgeCreation;
718 if (ss->allowEdgeCreation) {
719 if (defaultCreaseValue_r) *defaultCreaseValue_r = ss->defaultCreaseValue;
720 if (defaultUserData_r) memcpy(defaultUserData_r, ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize);
724 CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels) {
725 if (subdivisionLevels<=0) {
726 return eCCGError_InvalidValue;
727 } else if (subdivisionLevels!=ss->subdivLevels) {
729 ss->subdivLevels = subdivisionLevels;
730 _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
731 _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
732 _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
733 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
734 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
735 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
738 return eCCGError_None;
741 void ccgSubSurf_getUseAgeCounts(CCGSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r)
743 *useAgeCounts_r = ss->useAgeCounts;
745 if (vertUserOffset_r) *vertUserOffset_r = ss->vertUserAgeOffset;
746 if (edgeUserOffset_r) *edgeUserOffset_r = ss->edgeUserAgeOffset;
747 if (faceUserOffset_r) *faceUserOffset_r = ss->faceUserAgeOffset;
750 CCGError ccgSubSurf_setUseAgeCounts(CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset) {
752 if ( (vertUserOffset+4>ss->meshIFC.vertUserSize) ||
753 (edgeUserOffset+4>ss->meshIFC.edgeUserSize) ||
754 (faceUserOffset+4>ss->meshIFC.faceUserSize)) {
755 return eCCGError_InvalidValue;
757 ss->useAgeCounts = 1;
758 ss->vertUserAgeOffset = vertUserOffset;
759 ss->edgeUserAgeOffset = edgeUserOffset;
760 ss->faceUserAgeOffset = faceUserOffset;
763 ss->useAgeCounts = 0;
764 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
767 return eCCGError_None;
770 CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int normalDataOffset) {
771 if (useVertNormals) {
772 if (normalDataOffset<0 || normalDataOffset+12>ss->meshIFC.vertDataSize) {
773 return eCCGError_InvalidValue;
775 ss->calcVertNormals = 1;
776 ss->normalDataOffset = normalDataOffset;
779 ss->calcVertNormals = 0;
780 ss->normalDataOffset = 0;
783 return eCCGError_None;
788 CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) {
789 if (ss->syncState!=eSyncState_None) {
790 return eCCGError_InvalidSyncState;
795 ss->oldVMap = ss->vMap;
796 ss->oldEMap = ss->eMap;
797 ss->oldFMap = ss->fMap;
799 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
800 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
801 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
805 ss->lenTempArrays = 12;
806 ss->tempVerts = CCGSUBSURF_alloc(ss, sizeof(*ss->tempVerts)*ss->lenTempArrays);
807 ss->tempEdges = CCGSUBSURF_alloc(ss, sizeof(*ss->tempEdges)*ss->lenTempArrays);
809 ss->syncState = eSyncState_Vert;
811 return eCCGError_None;
814 CCGError ccgSubSurf_initPartialSync(CCGSubSurf *ss) {
815 if (ss->syncState!=eSyncState_None) {
816 return eCCGError_InvalidSyncState;
821 ss->syncState = eSyncState_Partial;
823 return eCCGError_None;
826 CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL) {
827 if (ss->syncState!=eSyncState_Partial) {
828 return eCCGError_InvalidSyncState;
831 CCGVert *v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
833 if (!v || v->numFaces || v->numEdges) {
834 return eCCGError_InvalidValue;
841 return eCCGError_None;
844 CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL) {
845 if (ss->syncState!=eSyncState_Partial) {
846 return eCCGError_InvalidSyncState;
849 CCGEdge *e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
851 if (!e || e->numFaces) {
852 return eCCGError_InvalidValue;
855 _edge_unlinkMarkAndFree(e, ss);
859 return eCCGError_None;
862 CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) {
863 if (ss->syncState!=eSyncState_Partial) {
864 return eCCGError_InvalidSyncState;
867 CCGFace *f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
870 return eCCGError_InvalidValue;
873 _face_unlinkMarkAndFree(f, ss);
877 return eCCGError_None;
880 CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r) {
883 short seamflag = (seam)? Vert_eSeam: 0;
885 if (ss->syncState==eSyncState_Partial) {
886 v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
888 v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
889 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
890 _ehash_insert(ss->vMap, (EHEntry*) v);
891 v->flags = Vert_eEffected|seamflag;
892 } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
895 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
896 v->flags = Vert_eEffected|seamflag;
898 for (i=0; i<v->numEdges; i++) {
899 CCGEdge *e = v->edges[i];
900 e->v0->flags |= Vert_eEffected;
901 e->v1->flags |= Vert_eEffected;
903 for (i=0; i<v->numFaces; i++) {
904 CCGFace *f = v->faces[i];
905 for (j=0; j<f->numVerts; j++) {
906 FACE_getVerts(f)[j]->flags |= Vert_eEffected;
911 if (ss->syncState!=eSyncState_Vert) {
912 return eCCGError_InvalidSyncState;
915 v = _ehash_lookupWithPrev(ss->oldVMap, vHDL, &prevp);
917 v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
918 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
919 _ehash_insert(ss->vMap, (EHEntry*) v);
920 v->flags = Vert_eEffected|seamflag;
921 } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
923 _ehash_insert(ss->vMap, (EHEntry*) v);
924 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
925 v->flags = Vert_eEffected|Vert_eChanged|seamflag;
928 _ehash_insert(ss->vMap, (EHEntry*) v);
934 return eCCGError_None;
937 CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r) {
939 CCGEdge *e = NULL, *eNew;
941 if (ss->syncState==eSyncState_Partial) {
942 e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
943 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1 || crease!=e->crease) {
944 CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
945 CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
947 eNew = _edge_new(eHDL, v0, v1, crease, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
951 eNew->next = e->next;
953 _edge_unlinkMarkAndFree(e, ss);
955 _ehash_insert(ss->eMap, (EHEntry*) eNew);
958 eNew->v0->flags |= Vert_eEffected;
959 eNew->v1->flags |= Vert_eEffected;
962 if (ss->syncState==eSyncState_Vert) {
963 ss->syncState = eSyncState_Edge;
964 } else if (ss->syncState!=eSyncState_Edge) {
965 return eCCGError_InvalidSyncState;
968 e = _ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp);
969 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1|| e->crease!=crease) {
970 CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
971 CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
972 e = _edge_new(eHDL, v0, v1, crease, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
973 _ehash_insert(ss->eMap, (EHEntry*) e);
974 e->v0->flags |= Vert_eEffected;
975 e->v1->flags |= Vert_eEffected;
978 _ehash_insert(ss->eMap, (EHEntry*) e);
980 if ((e->v0->flags|e->v1->flags)&Vert_eChanged) {
981 e->v0->flags |= Vert_eEffected;
982 e->v1->flags |= Vert_eEffected;
988 return eCCGError_None;
991 CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r) {
993 CCGFace *f = NULL, *fNew;
994 int j, k, topologyChanged = 0;
996 if (numVerts>ss->lenTempArrays) {
997 int oldLen = ss->lenTempArrays;
998 ss->lenTempArrays = (numVerts<ss->lenTempArrays*2)?ss->lenTempArrays*2:numVerts;
999 ss->tempVerts = CCGSUBSURF_realloc(ss, ss->tempVerts, sizeof(*ss->tempVerts)*ss->lenTempArrays, sizeof(*ss->tempVerts)*oldLen);
1000 ss->tempEdges = CCGSUBSURF_realloc(ss, ss->tempEdges, sizeof(*ss->tempEdges)*ss->lenTempArrays, sizeof(*ss->tempEdges)*oldLen);
1003 if (ss->syncState==eSyncState_Partial) {
1004 f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
1006 for (k=0; k<numVerts; k++) {
1007 ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
1009 for (k=0; k<numVerts; k++) {
1010 ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]);
1014 if ( f->numVerts!=numVerts ||
1015 memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) ||
1016 memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts))
1017 topologyChanged = 1;
1020 if (!f || topologyChanged) {
1021 fNew = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
1024 ss->numGrids += numVerts - f->numVerts;
1027 fNew->next = f->next;
1029 _face_unlinkMarkAndFree(f, ss);
1031 ss->numGrids += numVerts;
1032 _ehash_insert(ss->fMap, (EHEntry*) fNew);
1035 for (k=0; k<numVerts; k++)
1036 FACE_getVerts(fNew)[k]->flags |= Vert_eEffected;
1039 if (ss->syncState==eSyncState_Vert || ss->syncState==eSyncState_Edge) {
1040 ss->syncState = eSyncState_Face;
1041 } else if (ss->syncState!=eSyncState_Face) {
1042 return eCCGError_InvalidSyncState;
1045 f = _ehash_lookupWithPrev(ss->oldFMap, fHDL, &prevp);
1047 for (k=0; k<numVerts; k++) {
1048 ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
1050 if (!ss->tempVerts[k])
1051 return eCCGError_InvalidValue;
1053 for (k=0; k<numVerts; k++) {
1054 ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]);
1056 if (!ss->tempEdges[k]) {
1057 if (ss->allowEdgeCreation) {
1058 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);
1059 _ehash_insert(ss->eMap, (EHEntry*) e);
1060 e->v0->flags |= Vert_eEffected;
1061 e->v1->flags |= Vert_eEffected;
1062 if (ss->meshIFC.edgeUserSize) {
1063 memcpy(ccgSubSurf_getEdgeUserData(ss, e), ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize);
1066 return eCCGError_InvalidValue;
1072 if ( f->numVerts!=numVerts ||
1073 memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) ||
1074 memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts))
1075 topologyChanged = 1;
1078 if (!f || topologyChanged) {
1079 f = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
1080 _ehash_insert(ss->fMap, (EHEntry*) f);
1081 ss->numGrids += numVerts;
1083 for (k=0; k<numVerts; k++)
1084 FACE_getVerts(f)[k]->flags |= Vert_eEffected;
1087 _ehash_insert(ss->fMap, (EHEntry*) f);
1089 ss->numGrids += f->numVerts;
1091 for (j=0; j<f->numVerts; j++) {
1092 if (FACE_getVerts(f)[j]->flags&Vert_eChanged) {
1093 for (k=0; k<f->numVerts; k++)
1094 FACE_getVerts(f)[k]->flags |= Vert_eEffected;
1102 return eCCGError_None;
1105 static void ccgSubSurf__sync(CCGSubSurf *ss);
1106 CCGError ccgSubSurf_processSync(CCGSubSurf *ss) {
1107 if (ss->syncState==eSyncState_Partial) {
1108 ss->syncState = eSyncState_None;
1110 ccgSubSurf__sync(ss);
1111 } else if (ss->syncState) {
1112 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_unlinkMarkAndFree, ss);
1113 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_unlinkMarkAndFree, ss);
1114 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
1115 CCGSUBSURF_free(ss, ss->tempEdges);
1116 CCGSUBSURF_free(ss, ss->tempVerts);
1118 ss->lenTempArrays = 0;
1120 ss->oldFMap = ss->oldEMap = ss->oldVMap = NULL;
1121 ss->tempVerts = NULL;
1122 ss->tempEdges = NULL;
1124 ss->syncState = eSyncState_None;
1126 ccgSubSurf__sync(ss);
1128 return eCCGError_InvalidSyncState;
1131 return eCCGError_None;
1134 static void ccgSubSurf__sync(CCGSubSurf *ss) {
1135 CCGVert **effectedV;
1136 CCGEdge **effectedE;
1137 CCGFace **effectedF;
1138 int numEffectedV, numEffectedE, numEffectedF;
1139 int subdivLevels = ss->subdivLevels;
1140 int vertDataSize = ss->meshIFC.vertDataSize;
1141 int i,ptrIdx,cornerIdx;
1143 void *q = ss->q, *r = ss->r;
1144 int curLvl, nextLvl;
1147 effectedV = CCGSUBSURF_alloc(ss, sizeof(*effectedV)*ss->vMap->numEntries);
1148 effectedE = CCGSUBSURF_alloc(ss, sizeof(*effectedE)*ss->eMap->numEntries);
1149 effectedF = CCGSUBSURF_alloc(ss, sizeof(*effectedF)*ss->fMap->numEntries);
1150 numEffectedV = numEffectedE = numEffectedF = 0;
1151 for (i=0; i<ss->vMap->curSize; i++) {
1152 CCGVert *v = (CCGVert*) ss->vMap->buckets[i];
1153 for (; v; v = v->next) {
1154 if (v->flags&Vert_eEffected) {
1155 effectedV[numEffectedV++] = v;
1157 for (j=0; j<v->numEdges; j++) {
1158 CCGEdge *e = v->edges[j];
1159 if (!(e->flags&Edge_eEffected)) {
1160 effectedE[numEffectedE++] = e;
1161 e->flags |= Edge_eEffected;
1165 for (j=0; j<v->numFaces; j++) {
1166 CCGFace *f = v->faces[j];
1167 if (!(f->flags&Face_eEffected)) {
1168 effectedF[numEffectedF++] = f;
1169 f->flags |= Face_eEffected;
1176 #define VERT_getCo(v, lvl) _vert_getCo(v, lvl, vertDataSize)
1177 #define EDGE_getCo(e, lvl, x) _edge_getCo(e, lvl, x, vertDataSize)
1178 #define FACE_getIECo(f, lvl, S, x) _face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize)
1179 #define FACE_getIFCo(f, lvl, S, x, y) _face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize)
1183 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1184 CCGFace *f = effectedF[ptrIdx];
1185 void *co = FACE_getCenterData(f);
1187 for (i=0; i<f->numVerts; i++) {
1188 VertDataAdd(co, VERT_getCo(FACE_getVerts(f)[i], curLvl));
1190 VertDataMulN(co, 1.0f/f->numVerts);
1194 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1195 CCGEdge *e = effectedE[ptrIdx];
1196 void *co = EDGE_getCo(e, nextLvl, 1);
1197 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1199 if (_edge_isBoundary(e) || sharpness>=1.0) {
1200 VertDataCopy(co, VERT_getCo(e->v0, curLvl));
1201 VertDataAdd(co, VERT_getCo(e->v1, curLvl));
1202 VertDataMulN(co, 0.5f);
1205 VertDataCopy(q, VERT_getCo(e->v0, curLvl));
1206 VertDataAdd(q, VERT_getCo(e->v1, curLvl));
1207 for (i=0; i<e->numFaces; i++) {
1208 CCGFace *f = e->faces[i];
1209 VertDataAdd(q, FACE_getCenterData(f));
1212 VertDataMulN(q, 1.0f/(2.0f+numFaces));
1214 VertDataCopy(r, VERT_getCo(e->v0, curLvl));
1215 VertDataAdd(r, VERT_getCo(e->v1, curLvl));
1216 VertDataMulN(r, 0.5f);
1218 VertDataCopy(co, q);
1220 VertDataMulN(r, sharpness);
1224 // edge flags cleared later
1226 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
1227 CCGVert *v = effectedV[ptrIdx];
1228 void *co = VERT_getCo(v, curLvl);
1229 void *nCo = VERT_getCo(v, nextLvl);
1230 int sharpCount = 0, allSharp = 1;
1231 float avgSharpness = 0.0;
1232 int seam = VERT_seam(v, ss), seamEdges = 0;
1234 for (i=0; i<v->numEdges; i++) {
1235 CCGEdge *e = v->edges[i];
1236 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1238 if (seam && _edge_isBoundary(e))
1241 if (sharpness!=0.0f) {
1243 avgSharpness += sharpness;
1249 avgSharpness /= sharpCount;
1250 if (avgSharpness>1.0) {
1254 if (seam && seamEdges < 2)
1258 VertDataCopy(nCo, co);
1259 } else if (_vert_isBoundary(v)) {
1260 int numBoundary = 0;
1263 for (i=0; i<v->numEdges; i++) {
1264 CCGEdge *e = v->edges[i];
1265 if (_edge_isBoundary(e)) {
1266 VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
1270 VertDataCopy(nCo, co);
1271 VertDataMulN(nCo, 0.75);
1272 VertDataMulN(r, 0.25f/numBoundary);
1273 VertDataAdd(nCo, r);
1275 int numEdges = 0, numFaces = 0;
1278 for (i=0; i<v->numFaces; i++) {
1279 CCGFace *f = v->faces[i];
1280 VertDataAdd(q, FACE_getCenterData(f));
1283 VertDataMulN(q, 1.0f/numFaces);
1285 for (i=0; i<v->numEdges; i++) {
1286 CCGEdge *e = v->edges[i];
1287 VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
1290 VertDataMulN(r, 1.0f/numEdges);
1292 VertDataCopy(nCo, co);
1293 VertDataMulN(nCo, numEdges-2.0f);
1294 VertDataAdd(nCo, q);
1295 VertDataAdd(nCo, r);
1296 VertDataMulN(nCo, 1.0f/numEdges);
1299 if ((sharpCount>1 && v->numFaces) || seam) {
1303 avgSharpness = 1.0f;
1304 sharpCount = seamEdges;
1308 for (i=0; i<v->numEdges; i++) {
1309 CCGEdge *e = v->edges[i];
1310 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1313 if (_edge_isBoundary(e)) {
1314 CCGVert *oV = _edge_getOtherVert(e, v);
1315 VertDataAdd(q, VERT_getCo(oV, curLvl));
1317 } else if (sharpness != 0.0) {
1318 CCGVert *oV = _edge_getOtherVert(e, v);
1319 VertDataAdd(q, VERT_getCo(oV, curLvl));
1323 VertDataMulN(q, (float) 1/sharpCount);
1325 if (sharpCount!=2 || allSharp) {
1326 // q = q + (co-q)*avgSharpness
1327 VertDataCopy(r, co);
1329 VertDataMulN(r, avgSharpness);
1333 // r = co*.75 + q*.25
1334 VertDataCopy(r, co);
1335 VertDataMulN(r, .75);
1336 VertDataMulN(q, .25);
1339 // nCo = nCo + (r-nCo)*avgSharpness
1340 VertDataSub(r, nCo);
1341 VertDataMulN(r, avgSharpness);
1342 VertDataAdd(nCo, r);
1345 // vert flags cleared later
1348 if (ss->useAgeCounts) {
1349 for (i=0; i<numEffectedV; i++) {
1350 CCGVert *v = effectedV[i];
1351 byte *userData = ccgSubSurf_getVertUserData(ss, v);
1352 *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
1355 for (i=0; i<numEffectedE; i++) {
1356 CCGEdge *e = effectedE[i];
1357 byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
1358 *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
1361 for (i=0; i<numEffectedF; i++) {
1362 CCGFace *f = effectedF[i];
1363 byte *userData = ccgSubSurf_getFaceUserData(ss, f);
1364 *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
1368 for (i=0; i<numEffectedE; i++) {
1369 CCGEdge *e = effectedE[i];
1370 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
1371 VertDataCopy(EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl));
1373 for (i=0; i<numEffectedF; i++) {
1374 CCGFace *f = effectedF[i];
1375 for (S=0; S<f->numVerts; S++) {
1376 CCGEdge *e = FACE_getEdges(f)[S];
1377 CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
1379 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
1380 VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
1381 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
1382 VertDataCopy(FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1));
1384 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 0), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize));
1385 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 1), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize));
1389 for (curLvl=1; curLvl<subdivLevels; curLvl++) {
1390 int edgeSize = 1 + (1<<curLvl);
1391 int gridSize = 1 + (1<<(curLvl-1));
1394 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1395 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1397 /* interior face midpoints
1398 * o old interior face points
1400 for (S=0; S<f->numVerts; S++) {
1401 for (y=0; y<gridSize-1; y++) {
1402 for (x=0; x<gridSize-1; x++) {
1405 void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y+0);
1406 void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y+0);
1407 void *co2 = FACE_getIFCo(f, curLvl, S, x+1, y+1);
1408 void *co3 = FACE_getIFCo(f, curLvl, S, x+0, y+1);
1409 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
1411 VertDataAvg4(co, co0, co1, co2, co3);
1416 /* interior edge midpoints
1417 * o old interior edge points
1418 * o new interior face midpoints
1420 for (S=0; S<f->numVerts; S++) {
1421 for (x=0; x<gridSize-1; x++) {
1423 void *co0 = FACE_getIECo(f, curLvl, S, x+0);
1424 void *co1 = FACE_getIECo(f, curLvl, S, x+1);
1425 void *co2 = FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx);
1426 void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
1427 void *co = FACE_getIECo(f, nextLvl, S, fx);
1429 VertDataAvg4(co, co0, co1, co2, co3);
1432 /* interior face interior edge midpoints
1433 * o old interior face points
1434 * o new interior face midpoints
1438 for (x=1; x<gridSize-1; x++) {
1439 for (y=0; y<gridSize-1; y++) {
1442 void *co0 = FACE_getIFCo(f, curLvl, S, x, y+0);
1443 void *co1 = FACE_getIFCo(f, curLvl, S, x, y+1);
1444 void *co2 = FACE_getIFCo(f, nextLvl, S, fx-1, fy);
1445 void *co3 = FACE_getIFCo(f, nextLvl, S, fx+1, fy);
1446 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
1448 VertDataAvg4(co, co0, co1, co2, co3);
1453 for (y=1; y<gridSize-1; y++) {
1454 for (x=0; x<gridSize-1; x++) {
1457 void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y);
1458 void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y);
1459 void *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy-1);
1460 void *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy+1);
1461 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
1463 VertDataAvg4(co, co0, co1, co2, co3);
1469 /* exterior edge midpoints
1470 * o old exterior edge points
1471 * o new interior face midpoints
1473 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1474 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
1475 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1477 if (_edge_isBoundary(e) || sharpness>1.0) {
1478 for (x=0; x<edgeSize-1; x++) {
1480 void *co0 = EDGE_getCo(e, curLvl, x+0);
1481 void *co1 = EDGE_getCo(e, curLvl, x+1);
1482 void *co = EDGE_getCo(e, nextLvl, fx);
1484 VertDataCopy(co, co0);
1485 VertDataAdd(co, co1);
1486 VertDataMulN(co, 0.5);
1489 for (x=0; x<edgeSize-1; x++) {
1491 void *co0 = EDGE_getCo(e, curLvl, x+0);
1492 void *co1 = EDGE_getCo(e, curLvl, x+1);
1493 void *co = EDGE_getCo(e, nextLvl, fx);
1496 VertDataCopy(q, co0);
1497 VertDataAdd(q, co1);
1499 for (i=0; i<e->numFaces; i++) {
1500 CCGFace *f = e->faces[i];
1501 VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
1505 VertDataMulN(q, 1.0f/(2.0f+numFaces));
1507 VertDataCopy(r, co0);
1508 VertDataAdd(r, co1);
1509 VertDataMulN(r, 0.5);
1511 VertDataCopy(co, q);
1513 VertDataMulN(r, sharpness);
1519 /* exterior vertex shift
1520 * o old vertex points (shifting)
1521 * o old exterior edge points
1522 * o new interior face midpoints
1524 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
1525 CCGVert *v = (CCGVert*) effectedV[ptrIdx];
1526 void *co = VERT_getCo(v, curLvl);
1527 void *nCo = VERT_getCo(v, nextLvl);
1528 int sharpCount = 0, allSharp = 1;
1529 float avgSharpness = 0.0;
1530 int seam = VERT_seam(v, ss), seamEdges = 0;
1532 for (i=0; i<v->numEdges; i++) {
1533 CCGEdge *e = v->edges[i];
1534 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1536 if (seam && _edge_isBoundary(e))
1539 if (sharpness!=0.0f) {
1541 avgSharpness += sharpness;
1547 avgSharpness /= sharpCount;
1548 if (avgSharpness>1.0) {
1552 if (seam && seamEdges < 2)
1556 VertDataCopy(nCo, co);
1557 } else if (_vert_isBoundary(v)) {
1558 int numBoundary = 0;
1561 for (i=0; i<v->numEdges; i++) {
1562 CCGEdge *e = v->edges[i];
1563 if (_edge_isBoundary(e)) {
1564 VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
1569 VertDataCopy(nCo, co);
1570 VertDataMulN(nCo, 0.75);
1571 VertDataMulN(r, 0.25f/numBoundary);
1572 VertDataAdd(nCo, r);
1574 int cornerIdx = (1 + (1<<(curLvl))) - 2;
1575 int numEdges = 0, numFaces = 0;
1578 for (i=0; i<v->numFaces; i++) {
1579 CCGFace *f = v->faces[i];
1580 VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx));
1583 VertDataMulN(q, 1.0f/numFaces);
1585 for (i=0; i<v->numEdges; i++) {
1586 CCGEdge *e = v->edges[i];
1587 VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize));
1590 VertDataMulN(r, 1.0f/numEdges);
1592 VertDataCopy(nCo, co);
1593 VertDataMulN(nCo, numEdges-2.0f);
1594 VertDataAdd(nCo, q);
1595 VertDataAdd(nCo, r);
1596 VertDataMulN(nCo, 1.0f/numEdges);
1599 if ((sharpCount>1 && v->numFaces) || seam) {
1603 avgSharpness = 1.0f;
1604 sharpCount = seamEdges;
1608 for (i=0; i<v->numEdges; i++) {
1609 CCGEdge *e = v->edges[i];
1610 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1613 if (_edge_isBoundary(e))
1614 VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
1615 } else if (sharpness != 0.0) {
1616 VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
1620 VertDataMulN(q, (float) 1/sharpCount);
1622 if (sharpCount!=2 || allSharp) {
1623 // q = q + (co-q)*avgSharpness
1624 VertDataCopy(r, co);
1626 VertDataMulN(r, avgSharpness);
1630 // r = co*.75 + q*.25
1631 VertDataCopy(r, co);
1632 VertDataMulN(r, .75);
1633 VertDataMulN(q, .25);
1636 // nCo = nCo + (r-nCo)*avgSharpness
1637 VertDataSub(r, nCo);
1638 VertDataMulN(r, avgSharpness);
1639 VertDataAdd(nCo, r);
1643 /* exterior edge interior shift
1644 * o old exterior edge midpoints (shifting)
1645 * o old exterior edge midpoints
1646 * o new interior face midpoints
1648 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1649 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
1650 float sharpness = EDGE_getSharpness(e, curLvl, ss);
1652 float avgSharpness = 0.0;
1654 if (sharpness!=0.0f) {
1656 avgSharpness += sharpness;
1658 if (avgSharpness>1.0) {
1666 if (_edge_isBoundary(e) && (!e->numFaces || sharpCount<2)) {
1667 for (x=1; x<edgeSize-1; x++) {
1669 void *co = EDGE_getCo(e, curLvl, x);
1670 void *nCo = EDGE_getCo(e, nextLvl, fx);
1671 VertDataCopy(r, EDGE_getCo(e, curLvl, x-1));
1672 VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
1673 VertDataMulN(r, 0.5);
1674 VertDataCopy(nCo, co);
1675 VertDataMulN(nCo, 0.75);
1676 VertDataMulN(r, 0.25);
1677 VertDataAdd(nCo, r);
1680 for (x=1; x<edgeSize-1; x++) {
1682 void *co = EDGE_getCo(e, curLvl, x);
1683 void *nCo = EDGE_getCo(e, nextLvl, fx);
1688 VertDataAdd(r, EDGE_getCo(e, curLvl, x-1));
1689 VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
1690 for (i=0; i<e->numFaces; i++) {
1691 CCGFace *f = e->faces[i];
1692 VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize));
1693 VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize));
1695 VertDataAdd(r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize));
1698 VertDataMulN(q, 1.0/(numFaces*2.0f));
1699 VertDataMulN(r, 1.0/(2.0f + numFaces));
1701 VertDataCopy(nCo, co);
1702 VertDataMulN(nCo, (float) numFaces);
1703 VertDataAdd(nCo, q);
1704 VertDataAdd(nCo, r);
1705 VertDataMulN(nCo, 1.0f/(2+numFaces));
1707 if (sharpCount==2) {
1708 VertDataCopy(q, co);
1709 VertDataMulN(q, 6.0f);
1710 VertDataAdd(q, EDGE_getCo(e, curLvl, x-1));
1711 VertDataAdd(q, EDGE_getCo(e, curLvl, x+1));
1712 VertDataMulN(q, 1/8.0f);
1714 VertDataSub(q, nCo);
1715 VertDataMulN(q, avgSharpness);
1716 VertDataAdd(nCo, q);
1722 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1723 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1725 /* interior center point shift
1726 * o old face center point (shifting)
1727 * o old interior edge points
1728 * o new interior face midpoints
1731 for (S=0; S<f->numVerts; S++) {
1732 VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1));
1734 VertDataMulN(q, 1.0f/f->numVerts);
1736 for (S=0; S<f->numVerts; S++) {
1737 VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1));
1739 VertDataMulN(r, 1.0f/f->numVerts);
1741 VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f);
1742 VertDataAdd(FACE_getCenterData(f), q);
1743 VertDataAdd(FACE_getCenterData(f), r);
1744 VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
1746 for (S=0; S<f->numVerts; S++) {
1747 /* interior face shift
1748 * o old interior face point (shifting)
1749 * o new interior edge midpoints
1750 * o new interior face midpoints
1752 for (x=1; x<gridSize-1; x++) {
1753 for (y=1; y<gridSize-1; y++) {
1756 void *co = FACE_getIFCo(f, curLvl, S, x, y);
1757 void *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
1759 VertDataAvg4(q, FACE_getIFCo(f, nextLvl, S, fx-1, fy-1),
1760 FACE_getIFCo(f, nextLvl, S, fx+1, fy-1),
1761 FACE_getIFCo(f, nextLvl, S, fx+1, fy+1),
1762 FACE_getIFCo(f, nextLvl, S, fx-1, fy+1));
1764 VertDataAvg4(r, FACE_getIFCo(f, nextLvl, S, fx-1, fy+0),
1765 FACE_getIFCo(f, nextLvl, S, fx+1, fy+0),
1766 FACE_getIFCo(f, nextLvl, S, fx+0, fy-1),
1767 FACE_getIFCo(f, nextLvl, S, fx+0, fy+1));
1769 VertDataCopy(nCo, co);
1770 VertDataSub(nCo, q);
1771 VertDataMulN(nCo, 0.25f);
1772 VertDataAdd(nCo, r);
1776 /* interior edge interior shift
1777 * o old interior edge point (shifting)
1778 * o new interior edge midpoints
1779 * o new interior face midpoints
1781 for (x=1; x<gridSize-1; x++) {
1783 void *co = FACE_getIECo(f, curLvl, S, x);
1784 void *nCo = FACE_getIECo(f, nextLvl, S, fx);
1786 VertDataAvg4(q, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx-1),
1787 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1),
1788 FACE_getIFCo(f, nextLvl, S, fx+1, +1),
1789 FACE_getIFCo(f, nextLvl, S, fx-1, +1));
1791 VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1),
1792 FACE_getIECo(f, nextLvl, S, fx+1),
1793 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx),
1794 FACE_getIFCo(f, nextLvl, S, fx, 1));
1796 VertDataCopy(nCo, co);
1797 VertDataSub(nCo, q);
1798 VertDataMulN(nCo, 0.25f);
1799 VertDataAdd(nCo, r);
1805 edgeSize = 1 + (1<<(nextLvl));
1806 gridSize = 1 + (1<<((nextLvl)-1));
1807 cornerIdx = gridSize-1;
1808 for (i=0; i<numEffectedE; i++) {
1809 CCGEdge *e = effectedE[i];
1810 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
1811 VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl));
1813 for (i=0; i<numEffectedF; i++) {
1814 CCGFace *f = effectedF[i];
1815 for (S=0; S<f->numVerts; S++) {
1816 CCGEdge *e = FACE_getEdges(f)[S];
1817 CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
1819 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
1820 VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
1821 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
1822 VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx));
1823 for (x=1; x<gridSize-1; x++) {
1824 void *co = FACE_getIECo(f, nextLvl, S, x);
1825 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co);
1826 VertDataCopy(FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 0, x), co);
1828 for (x=0; x<gridSize-1; x++) {
1829 int eI = gridSize-1-x;
1830 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
1831 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
1837 #define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
1838 #define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
1839 if (ss->calcVertNormals) {
1840 int lvl = ss->subdivLevels;
1841 int edgeSize = 1 + (1<<lvl);
1842 int gridSize = 1 + (1<<(lvl-1));
1843 int normalDataOffset = ss->normalDataOffset;
1845 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1846 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1849 for (S=0; S<f->numVerts; S++) {
1850 for (y=0; y<gridSize-1; y++)
1851 for (x=0; x<gridSize-1; x++)
1852 NormZero(FACE_getIFNo(f, lvl, S, x, y));
1854 if (FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected)
1855 for (x=0; x<gridSize-1; x++)
1856 NormZero(FACE_getIFNo(f, lvl, S, x, gridSize-1));
1857 if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
1858 for (y=0; y<gridSize-1; y++)
1859 NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, y));
1860 if (FACE_getVerts(f)[S]->flags&Vert_eEffected)
1861 NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1));
1865 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1866 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1870 for (S=0; S<f->numVerts; S++) {
1871 int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected);
1872 int xLimit = !(FACE_getEdges(f)[S]->flags&Edge_eEffected);
1873 int yLimitNext = xLimit;
1874 int xLimitPrev = yLimit;
1876 for (y=0; y<gridSize - 1; y++) {
1877 for (x=0; x<gridSize - 1; x++) {
1878 int xPlusOk = (!xLimit || x<gridSize-2);
1879 int yPlusOk = (!yLimit || y<gridSize-2);
1881 FACE_calcIFNo(f, lvl, S, x, y, no);
1883 NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+0), no);
1885 NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+0), no);
1887 NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+1), no);
1888 if (xPlusOk && yPlusOk) {
1889 if (x<gridSize-2 || y<gridSize-2 || FACE_getVerts(f)[S]->flags&Vert_eEffected) {
1890 NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+1), no);
1897 if (!yLimitNext || 1<gridSize-1)
1898 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, 1), no);
1899 if (!xLimitPrev || 1<gridSize-1)
1900 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no);
1902 for (K=0; K<f->numVerts; K++) {
1904 NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
1908 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no);
1909 if (!yLimitNext || x<gridSize-2)
1910 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x+1), no);
1912 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no);
1913 if (!xLimitPrev || y<gridSize-2)
1914 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y+1, 0), no);
1920 // XXX can I reduce the number of normalisations here?
1921 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
1922 CCGVert *v = (CCGVert*) effectedV[ptrIdx];
1923 float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset);
1927 for (i=0; i<v->numFaces; i++) {
1928 CCGFace *f = v->faces[i];
1929 NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1));
1932 length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
1934 if (length>FLT_EPSILON) {
1935 float invLength = 1.0f/length;
1943 for (i=0; i<v->numFaces; i++) {
1944 CCGFace *f = v->faces[i];
1945 NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no);
1948 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1949 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
1952 CCGFace *fLast = e->faces[e->numFaces-1];
1955 for (i=0; i<e->numFaces-1; i++) {
1956 CCGFace *f = e->faces[i];
1958 for (x=1; x<edgeSize-1; x++) {
1959 NormAdd(_face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
1960 _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
1964 for (i=0; i<e->numFaces-1; i++) {
1965 CCGFace *f = e->faces[i];
1967 for (x=1; x<edgeSize-1; x++) {
1968 NormCopy(_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
1969 _face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
1974 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1975 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1978 for (S=0; S<f->numVerts; S++) {
1979 NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1),
1980 FACE_getIFNo(f, lvl, S, gridSize-1, 0));
1983 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1984 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1987 for (S=0; S<f->numVerts; S++) {
1988 for (y=0; y<gridSize; y++) {
1989 for (x=0; x<gridSize; x++) {
1990 float *no = FACE_getIFNo(f, lvl, S, x, y);
1991 float length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
1993 if (length>FLT_EPSILON) {
1994 float invLength = 1.0f/length;
2008 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
2009 CCGVert *v = effectedV[ptrIdx];
2012 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
2013 CCGEdge *e = effectedE[ptrIdx];
2022 CCGSUBSURF_free(ss, effectedF);
2023 CCGSUBSURF_free(ss, effectedE);
2024 CCGSUBSURF_free(ss, effectedV);
2027 /*** External API accessor functions ***/
2029 int ccgSubSurf_getNumVerts(CCGSubSurf *ss) {
2030 return ss->vMap->numEntries;
2032 int ccgSubSurf_getNumEdges(CCGSubSurf *ss) {
2033 return ss->eMap->numEntries;
2035 int ccgSubSurf_getNumFaces(CCGSubSurf *ss) {
2036 return ss->fMap->numEntries;
2039 CCGVert *ccgSubSurf_getVert(CCGSubSurf *ss, CCGVertHDL v) {
2040 return (CCGVert*) _ehash_lookup(ss->vMap, v);
2042 CCGEdge *ccgSubSurf_getEdge(CCGSubSurf *ss, CCGEdgeHDL e) {
2043 return (CCGEdge*) _ehash_lookup(ss->eMap, e);
2045 CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f) {
2046 return (CCGFace*) _ehash_lookup(ss->fMap, f);
2049 int ccgSubSurf_getSubdivisionLevels(CCGSubSurf *ss) {
2050 return ss->subdivLevels;
2052 int ccgSubSurf_getEdgeSize(CCGSubSurf *ss) {
2053 return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels);
2055 int ccgSubSurf_getEdgeLevelSize(CCGSubSurf *ss, int level) {
2056 if (level<1 || level>ss->subdivLevels) {
2059 return 1 + (1<<level);
2062 int ccgSubSurf_getGridSize(CCGSubSurf *ss) {
2063 return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels);
2065 int ccgSubSurf_getGridLevelSize(CCGSubSurf *ss, int level) {
2066 if (level<1 || level>ss->subdivLevels) {
2069 return 1 + (1<<(level-1));
2073 /* Vert accessors */
2075 CCGVertHDL ccgSubSurf_getVertVertHandle(CCGSubSurf *ss, CCGVert *v) {
2078 int ccgSubSurf_getVertAge(CCGSubSurf *ss, CCGVert *v) {
2079 if (ss->useAgeCounts) {
2080 byte *userData = ccgSubSurf_getVertUserData(ss, v);
2081 return ss->currentAge - *((int*) &userData[ss->vertUserAgeOffset]);
2086 void *ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v) {
2087 return VERT_getLevelData(v) + ss->meshIFC.vertDataSize*(ss->subdivLevels+1);
2089 int ccgSubSurf_getVertNumFaces(CCGSubSurf *ss, CCGVert *v) {
2092 CCGFace *ccgSubSurf_getVertFace(CCGSubSurf *ss, CCGVert *v, int index) {
2093 if (index<0 || index>=v->numFaces) {
2096 return v->faces[index];
2099 int ccgSubSurf_getVertNumEdges(CCGSubSurf *ss, CCGVert *v) {
2102 CCGEdge *ccgSubSurf_getVertEdge(CCGSubSurf *ss, CCGVert *v, int index) {
2103 if (index<0 || index>=v->numEdges) {
2106 return v->edges[index];
2109 void *ccgSubSurf_getVertData(CCGSubSurf *ss, CCGVert *v) {
2110 return ccgSubSurf_getVertLevelData(ss, v, ss->subdivLevels);
2112 void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level) {
2113 if (level<0 || level>ss->subdivLevels) {
2116 return _vert_getCo(v, level, ss->meshIFC.vertDataSize);
2120 /* Edge accessors */
2122 CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle(CCGSubSurf *ss, CCGEdge *e) {
2125 int ccgSubSurf_getEdgeAge(CCGSubSurf *ss, CCGEdge *e) {
2126 if (ss->useAgeCounts) {
2127 byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
2128 return ss->currentAge - *((int*) &userData[ss->edgeUserAgeOffset]);
2133 void *ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e) {
2134 return EDGE_getLevelData(e) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1);
2136 int ccgSubSurf_getEdgeNumFaces(CCGSubSurf *ss, CCGEdge *e) {
2139 CCGFace *ccgSubSurf_getEdgeFace(CCGSubSurf *ss, CCGEdge *e, int index) {
2140 if (index<0 || index>=e->numFaces) {
2143 return e->faces[index];
2146 CCGVert *ccgSubSurf_getEdgeVert0(CCGSubSurf *ss, CCGEdge *e) {
2149 CCGVert *ccgSubSurf_getEdgeVert1(CCGSubSurf *ss, CCGEdge *e) {
2152 void *ccgSubSurf_getEdgeDataArray(CCGSubSurf *ss, CCGEdge *e) {
2153 return ccgSubSurf_getEdgeData(ss, e, 0);
2155 void *ccgSubSurf_getEdgeData(CCGSubSurf *ss, CCGEdge *e, int x) {
2156 return ccgSubSurf_getEdgeLevelData(ss, e, x, ss->subdivLevels);
2158 void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level) {
2159 if (level<0 || level>ss->subdivLevels) {
2162 return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
2165 float ccgSubSurf_getEdgeCrease(CCGSubSurf *ss, CCGEdge *e) {
2169 /* Face accessors */
2171 CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *ss, CCGFace *f) {
2174 int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) {
2175 if (ss->useAgeCounts) {
2176 byte *userData = ccgSubSurf_getFaceUserData(ss, f);
2177 return ss->currentAge - *((int*) &userData[ss->faceUserAgeOffset]);
2182 void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) {
2183 int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
2184 return FACE_getCenterData(f) + ss->meshIFC.vertDataSize *(1 + f->numVerts*maxGridSize + f->numVerts*maxGridSize*maxGridSize);
2186 int ccgSubSurf_getFaceNumVerts(CCGSubSurf *ss, CCGFace *f) {
2189 CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *ss, CCGFace *f, int index) {
2190 if (index<0 || index>=f->numVerts) {
2193 return FACE_getVerts(f)[index];
2196 CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *ss, CCGFace *f, int index) {
2197 if (index<0 || index>=f->numVerts) {
2200 return FACE_getEdges(f)[index];
2203 int ccgSubSurf_getFaceEdgeIndex(CCGSubSurf *ss, CCGFace *f, CCGEdge *e) {
2206 for (i=0; i<f->numVerts; i++)
2207 if (FACE_getEdges(f)[i]==e)
2212 void *ccgSubSurf_getFaceCenterData(CCGSubSurf *ss, CCGFace *f) {
2213 return FACE_getCenterData(f);
2215 void *ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
2216 return ccgSubSurf_getFaceGridEdgeData(ss, f, gridIndex, 0);
2218 void *ccgSubSurf_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x) {
2219 return _face_getIECo(f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize);
2221 void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
2222 return ccgSubSurf_getFaceGridData(ss, f, gridIndex, 0, 0);
2224 void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y) {
2225 return _face_getIFCo(f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize);
2228 /*** External API iterator functions ***/
2230 CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss) {
2231 return (CCGVertIterator*) _ehashIterator_new(ss->vMap);
2233 CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss) {
2234 return (CCGEdgeIterator*) _ehashIterator_new(ss->eMap);
2236 CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss) {
2237 return (CCGFaceIterator*) _ehashIterator_new(ss->fMap);
2240 CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi) {
2241 return (CCGVert*) _ehashIterator_getCurrent((EHashIterator*) vi);
2243 int ccgVertIterator_isStopped(CCGVertIterator *vi) {
2244 return _ehashIterator_isStopped((EHashIterator*) vi);
2246 void ccgVertIterator_next(CCGVertIterator *vi) {
2247 _ehashIterator_next((EHashIterator*) vi);
2249 void ccgVertIterator_free(CCGVertIterator *vi) {
2250 _ehashIterator_free((EHashIterator*) vi);
2253 CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi) {
2254 return (CCGEdge*) _ehashIterator_getCurrent((EHashIterator*) vi);
2256 int ccgEdgeIterator_isStopped(CCGEdgeIterator *vi) {
2257 return _ehashIterator_isStopped((EHashIterator*) vi);
2259 void ccgEdgeIterator_next(CCGEdgeIterator *vi) {
2260 _ehashIterator_next((EHashIterator*) vi);
2262 void ccgEdgeIterator_free(CCGEdgeIterator *vi) {
2263 _ehashIterator_free((EHashIterator*) vi);
2266 CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi) {
2267 return (CCGFace*) _ehashIterator_getCurrent((EHashIterator*) vi);
2269 int ccgFaceIterator_isStopped(CCGFaceIterator *vi) {
2270 return _ehashIterator_isStopped((EHashIterator*) vi);
2272 void ccgFaceIterator_next(CCGFaceIterator *vi) {
2273 _ehashIterator_next((EHashIterator*) vi);
2275 void ccgFaceIterator_free(CCGFaceIterator *vi) {
2276 _ehashIterator_free((EHashIterator*) vi);
2279 /*** Extern API final vert/edge/face interface ***/
2281 int ccgSubSurf_getNumFinalVerts(CCGSubSurf *ss) {
2282 int edgeSize = 1 + (1<<ss->subdivLevels);
2283 int gridSize = 1 + (1<<(ss->subdivLevels-1));
2284 int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2)));
2285 return numFinalVerts;
2287 int ccgSubSurf_getNumFinalEdges(CCGSubSurf *ss) {
2288 int edgeSize = 1 + (1<<ss->subdivLevels);
2289 int gridSize = 1 + (1<<(ss->subdivLevels-1));
2290 int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1)));
2291 return numFinalEdges;
2293 int ccgSubSurf_getNumFinalFaces(CCGSubSurf *ss) {
2294 int gridSize = 1 + (1<<(ss->subdivLevels-1));
2295 int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1));
2296 return numFinalFaces;