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) {
491 else if (e->crease - lvl < 0.0)
494 return e->crease - lvl;
497 static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, int levels, int dataSize, CCGSubSurf *ss) {
498 int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
499 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);
503 f->numVerts = numVerts;
507 for (i=0; i<numVerts; i++) {
508 FACE_getVerts(f)[i] = verts[i];
509 FACE_getEdges(f)[i] = edges[i];
510 _vert_addFace(verts[i], f, ss);
511 _edge_addFace(edges[i], f, ss);
514 userData = ccgSubSurf_getFaceUserData(ss, f);
515 memset(userData, 0, ss->meshIFC.faceUserSize);
516 if (ss->useAgeCounts) *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
521 static void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) {
522 int maxGridSize = 1 + (1<<(levels-1));
523 int spacing = 1<<(levels-lvl);
524 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
525 return &gridBase[dataSize*x*spacing];
527 static void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) {
528 int maxGridSize = 1 + (1<<(levels-1));
529 int spacing = 1<<(levels-lvl);
530 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
531 return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)];
533 static float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) {
534 int maxGridSize = 1 + (1<<(levels-1));
535 int spacing = 1<<(levels-lvl);
536 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize));
537 return (float*) &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing) + normalDataOffset];
539 static int _face_getVertIndex(CCGFace *f, CCGVert *v) {
541 for (i=0; i<f->numVerts; i++)
542 if (FACE_getVerts(f)[i]==v)
546 static void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) {
547 int maxGridSize = 1 + (1<<(levels-1));
548 int spacing = 1<<(levels-lvl);
551 for (S=0; S<f->numVerts; S++)
552 if (FACE_getEdges(f)[S]==e)
557 if (e->v0!=FACE_getVerts(f)[S]) {
558 eX = (maxGridSize*2 - 1)-1 - eX;
560 y = maxGridSize - 1 - eX;
561 x = maxGridSize - 1 - eY;
563 S = (S+f->numVerts-1)%f->numVerts;
567 S = (S+1)%f->numVerts;
574 return _face_getIFCo(f, levels, S, cx, cy, levels, dataSize);
576 static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) {
577 return (float*) ((byte*) _face_getIFCoEdge(f, e, lvl, eX, eY, levels, dataSize) + normalDataOffset);
579 void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) {
580 float *a = _face_getIFCo(f, lvl, S, x+0, y+0, levels, dataSize);
581 float *b = _face_getIFCo(f, lvl, S, x+1, y+0, levels, dataSize);
582 float *c = _face_getIFCo(f, lvl, S, x+1, y+1, levels, dataSize);
583 float *d = _face_getIFCo(f, lvl, S, x+0, y+1, levels, dataSize);
584 float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
585 float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
588 no[0] = b_dY*a_cZ - b_dZ*a_cY;
589 no[1] = b_dZ*a_cX - b_dX*a_cZ;
590 no[2] = b_dX*a_cY - b_dY*a_cX;
592 length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
594 if (length>FLT_EPSILON) {
595 float invLength = 1.f/length;
605 static void _face_free(CCGFace *f, CCGSubSurf *ss) {
606 CCGSUBSURF_free(ss, f);
608 static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss) {
610 for (j=0; j<f->numVerts; j++) {
611 _vert_remFace(FACE_getVerts(f)[j], f, ss);
612 _edge_remFace(FACE_getEdges(f)[j], f, ss);
613 FACE_getVerts(f)[j]->flags |= Vert_eEffected;
620 CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) {
622 allocatorIFC = _getStandardAllocatorIFC();
626 if (subdivLevels<1) {
629 CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss));
631 ss->allocatorIFC = *allocatorIFC;
632 ss->allocator = allocator;
634 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
635 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
636 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
640 ss->subdivLevels = subdivLevels;
642 ss->allowEdgeCreation = 0;
643 ss->defaultCreaseValue = 0;
644 ss->defaultEdgeUserData = NULL;
646 ss->useAgeCounts = 0;
647 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
649 ss->calcVertNormals = 0;
650 ss->normalDataOffset = 0;
652 ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
653 ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize);
657 ss->syncState = eSyncState_None;
659 ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL;
660 ss->lenTempArrays = 0;
661 ss->tempVerts = NULL;
662 ss->tempEdges = NULL;
668 void ccgSubSurf_free(CCGSubSurf *ss) {
669 CCGAllocatorIFC allocatorIFC = ss->allocatorIFC;
670 CCGAllocatorHDL allocator = ss->allocator;
673 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_free, ss);
674 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_free, ss);
675 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
677 CCGSUBSURF_free(ss, ss->tempVerts);
678 CCGSUBSURF_free(ss, ss->tempEdges);
681 CCGSUBSURF_free(ss, ss->r);
682 CCGSUBSURF_free(ss, ss->q);
683 if (ss->defaultEdgeUserData) CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
685 _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
686 _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
687 _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
689 CCGSUBSURF_free(ss, ss);
691 if (allocatorIFC.release) {
692 allocatorIFC.release(allocator);
696 CCGError ccgSubSurf_setAllowEdgeCreation(CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData) {
697 if (ss->defaultEdgeUserData) {
698 CCGSUBSURF_free(ss, ss->defaultEdgeUserData);
701 ss->allowEdgeCreation = !!allowEdgeCreation;
702 ss->defaultCreaseValue = defaultCreaseValue;
703 ss->defaultEdgeUserData = CCGSUBSURF_alloc(ss, ss->meshIFC.edgeUserSize);
705 if (defaultUserData) {
706 memcpy(ss->defaultEdgeUserData, defaultUserData, ss->meshIFC.edgeUserSize);
708 memset(ss->defaultEdgeUserData, 0, ss->meshIFC.edgeUserSize);
711 return eCCGError_None;
713 void ccgSubSurf_getAllowEdgeCreation(CCGSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r) {
714 if (allowEdgeCreation_r) *allowEdgeCreation_r = ss->allowEdgeCreation;
715 if (ss->allowEdgeCreation) {
716 if (defaultCreaseValue_r) *defaultCreaseValue_r = ss->defaultCreaseValue;
717 if (defaultUserData_r) memcpy(defaultUserData_r, ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize);
721 CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels) {
722 if (subdivisionLevels<=0) {
723 return eCCGError_InvalidValue;
724 } else if (subdivisionLevels!=ss->subdivLevels) {
726 ss->subdivLevels = subdivisionLevels;
727 _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss);
728 _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss);
729 _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss);
730 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
731 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
732 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
735 return eCCGError_None;
738 void ccgSubSurf_getUseAgeCounts(CCGSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r)
740 *useAgeCounts_r = ss->useAgeCounts;
742 if (vertUserOffset_r) *vertUserOffset_r = ss->vertUserAgeOffset;
743 if (edgeUserOffset_r) *edgeUserOffset_r = ss->edgeUserAgeOffset;
744 if (faceUserOffset_r) *faceUserOffset_r = ss->faceUserAgeOffset;
747 CCGError ccgSubSurf_setUseAgeCounts(CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset) {
749 if ( (vertUserOffset+4>ss->meshIFC.vertUserSize) ||
750 (edgeUserOffset+4>ss->meshIFC.edgeUserSize) ||
751 (faceUserOffset+4>ss->meshIFC.faceUserSize)) {
752 return eCCGError_InvalidValue;
754 ss->useAgeCounts = 1;
755 ss->vertUserAgeOffset = vertUserOffset;
756 ss->edgeUserAgeOffset = edgeUserOffset;
757 ss->faceUserAgeOffset = faceUserOffset;
760 ss->useAgeCounts = 0;
761 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0;
764 return eCCGError_None;
767 CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int normalDataOffset) {
768 if (useVertNormals) {
769 if (normalDataOffset<0 || normalDataOffset+12>ss->meshIFC.vertDataSize) {
770 return eCCGError_InvalidValue;
772 ss->calcVertNormals = 1;
773 ss->normalDataOffset = normalDataOffset;
776 ss->calcVertNormals = 0;
777 ss->normalDataOffset = 0;
780 return eCCGError_None;
785 CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) {
786 if (ss->syncState!=eSyncState_None) {
787 return eCCGError_InvalidSyncState;
792 ss->oldVMap = ss->vMap;
793 ss->oldEMap = ss->eMap;
794 ss->oldFMap = ss->fMap;
796 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
797 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
798 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator);
802 ss->lenTempArrays = 12;
803 ss->tempVerts = CCGSUBSURF_alloc(ss, sizeof(*ss->tempVerts)*ss->lenTempArrays);
804 ss->tempEdges = CCGSUBSURF_alloc(ss, sizeof(*ss->tempEdges)*ss->lenTempArrays);
806 ss->syncState = eSyncState_Vert;
808 return eCCGError_None;
811 CCGError ccgSubSurf_initPartialSync(CCGSubSurf *ss) {
812 if (ss->syncState!=eSyncState_None) {
813 return eCCGError_InvalidSyncState;
818 ss->syncState = eSyncState_Partial;
820 return eCCGError_None;
823 CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL) {
824 if (ss->syncState!=eSyncState_Partial) {
825 return eCCGError_InvalidSyncState;
828 CCGVert *v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
830 if (!v || v->numFaces || v->numEdges) {
831 return eCCGError_InvalidValue;
838 return eCCGError_None;
841 CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL) {
842 if (ss->syncState!=eSyncState_Partial) {
843 return eCCGError_InvalidSyncState;
846 CCGEdge *e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
848 if (!e || e->numFaces) {
849 return eCCGError_InvalidValue;
852 _edge_unlinkMarkAndFree(e, ss);
856 return eCCGError_None;
859 CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) {
860 if (ss->syncState!=eSyncState_Partial) {
861 return eCCGError_InvalidSyncState;
864 CCGFace *f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
867 return eCCGError_InvalidValue;
870 _face_unlinkMarkAndFree(f, ss);
874 return eCCGError_None;
877 CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r) {
880 short seamflag = (seam)? Vert_eSeam: 0;
882 if (ss->syncState==eSyncState_Partial) {
883 v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
885 v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
886 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
887 _ehash_insert(ss->vMap, (EHEntry*) v);
888 v->flags = Vert_eEffected|seamflag;
889 } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
892 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
893 v->flags = Vert_eEffected|seamflag;
895 for (i=0; i<v->numEdges; i++) {
896 CCGEdge *e = v->edges[i];
897 e->v0->flags |= Vert_eEffected;
898 e->v1->flags |= Vert_eEffected;
900 for (i=0; i<v->numFaces; i++) {
901 CCGFace *f = v->faces[i];
902 for (j=0; j<f->numVerts; j++) {
903 FACE_getVerts(f)[j]->flags |= Vert_eEffected;
908 if (ss->syncState!=eSyncState_Vert) {
909 return eCCGError_InvalidSyncState;
912 v = _ehash_lookupWithPrev(ss->oldVMap, vHDL, &prevp);
914 v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
915 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
916 _ehash_insert(ss->vMap, (EHEntry*) v);
917 v->flags = Vert_eEffected|seamflag;
918 } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
920 _ehash_insert(ss->vMap, (EHEntry*) v);
921 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
922 v->flags = Vert_eEffected|Vert_eChanged|seamflag;
925 _ehash_insert(ss->vMap, (EHEntry*) v);
931 return eCCGError_None;
934 CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r) {
936 CCGEdge *e = NULL, *eNew;
938 if (ss->syncState==eSyncState_Partial) {
939 e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp);
940 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1 || crease!=e->crease) {
941 CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
942 CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
944 eNew = _edge_new(eHDL, v0, v1, crease, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
948 eNew->next = e->next;
950 _edge_unlinkMarkAndFree(e, ss);
952 _ehash_insert(ss->eMap, (EHEntry*) eNew);
955 eNew->v0->flags |= Vert_eEffected;
956 eNew->v1->flags |= Vert_eEffected;
959 if (ss->syncState==eSyncState_Vert) {
960 ss->syncState = eSyncState_Edge;
961 } else if (ss->syncState!=eSyncState_Edge) {
962 return eCCGError_InvalidSyncState;
965 e = _ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp);
966 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1|| e->crease!=crease) {
967 CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0);
968 CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1);
969 e = _edge_new(eHDL, v0, v1, crease, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
970 _ehash_insert(ss->eMap, (EHEntry*) e);
971 e->v0->flags |= Vert_eEffected;
972 e->v1->flags |= Vert_eEffected;
975 _ehash_insert(ss->eMap, (EHEntry*) e);
977 if ((e->v0->flags|e->v1->flags)&Vert_eChanged) {
978 e->v0->flags |= Vert_eEffected;
979 e->v1->flags |= Vert_eEffected;
985 return eCCGError_None;
988 CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r) {
990 CCGFace *f = NULL, *fNew;
991 int j, k, topologyChanged = 0;
993 if (numVerts>ss->lenTempArrays) {
994 int oldLen = ss->lenTempArrays;
995 ss->lenTempArrays = (numVerts<ss->lenTempArrays*2)?ss->lenTempArrays*2:numVerts;
996 ss->tempVerts = CCGSUBSURF_realloc(ss, ss->tempVerts, sizeof(*ss->tempVerts)*ss->lenTempArrays, sizeof(*ss->tempVerts)*oldLen);
997 ss->tempEdges = CCGSUBSURF_realloc(ss, ss->tempEdges, sizeof(*ss->tempEdges)*ss->lenTempArrays, sizeof(*ss->tempEdges)*oldLen);
1000 if (ss->syncState==eSyncState_Partial) {
1001 f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp);
1003 for (k=0; k<numVerts; k++) {
1004 ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
1006 for (k=0; k<numVerts; k++) {
1007 ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]);
1011 if ( f->numVerts!=numVerts ||
1012 memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) ||
1013 memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts))
1014 topologyChanged = 1;
1017 if (!f || topologyChanged) {
1018 fNew = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
1021 ss->numGrids += numVerts - f->numVerts;
1024 fNew->next = f->next;
1026 _face_unlinkMarkAndFree(f, ss);
1028 ss->numGrids += numVerts;
1029 _ehash_insert(ss->fMap, (EHEntry*) fNew);
1032 for (k=0; k<numVerts; k++)
1033 FACE_getVerts(fNew)[k]->flags |= Vert_eEffected;
1036 if (ss->syncState==eSyncState_Vert || ss->syncState==eSyncState_Edge) {
1037 ss->syncState = eSyncState_Face;
1038 } else if (ss->syncState!=eSyncState_Face) {
1039 return eCCGError_InvalidSyncState;
1042 f = _ehash_lookupWithPrev(ss->oldFMap, fHDL, &prevp);
1044 for (k=0; k<numVerts; k++) {
1045 ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]);
1047 if (!ss->tempVerts[k])
1048 return eCCGError_InvalidValue;
1050 for (k=0; k<numVerts; k++) {
1051 ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]);
1053 if (!ss->tempEdges[k]) {
1054 if (ss->allowEdgeCreation) {
1055 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);
1056 _ehash_insert(ss->eMap, (EHEntry*) e);
1057 e->v0->flags |= Vert_eEffected;
1058 e->v1->flags |= Vert_eEffected;
1059 if (ss->meshIFC.edgeUserSize) {
1060 memcpy(ccgSubSurf_getEdgeUserData(ss, e), ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize);
1063 return eCCGError_InvalidValue;
1069 if ( f->numVerts!=numVerts ||
1070 memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) ||
1071 memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts))
1072 topologyChanged = 1;
1075 if (!f || topologyChanged) {
1076 f = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
1077 _ehash_insert(ss->fMap, (EHEntry*) f);
1078 ss->numGrids += numVerts;
1080 for (k=0; k<numVerts; k++)
1081 FACE_getVerts(f)[k]->flags |= Vert_eEffected;
1084 _ehash_insert(ss->fMap, (EHEntry*) f);
1086 ss->numGrids += f->numVerts;
1088 for (j=0; j<f->numVerts; j++) {
1089 if (FACE_getVerts(f)[j]->flags&Vert_eChanged) {
1090 for (k=0; k<f->numVerts; k++)
1091 FACE_getVerts(f)[k]->flags |= Vert_eEffected;
1099 return eCCGError_None;
1102 static void ccgSubSurf__sync(CCGSubSurf *ss);
1103 CCGError ccgSubSurf_processSync(CCGSubSurf *ss) {
1104 if (ss->syncState==eSyncState_Partial) {
1105 ss->syncState = eSyncState_None;
1107 ccgSubSurf__sync(ss);
1108 } else if (ss->syncState) {
1109 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_unlinkMarkAndFree, ss);
1110 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_unlinkMarkAndFree, ss);
1111 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss);
1112 CCGSUBSURF_free(ss, ss->tempEdges);
1113 CCGSUBSURF_free(ss, ss->tempVerts);
1115 ss->lenTempArrays = 0;
1117 ss->oldFMap = ss->oldEMap = ss->oldVMap = NULL;
1118 ss->tempVerts = NULL;
1119 ss->tempEdges = NULL;
1121 ss->syncState = eSyncState_None;
1123 ccgSubSurf__sync(ss);
1125 return eCCGError_InvalidSyncState;
1128 return eCCGError_None;
1131 static void ccgSubSurf__sync(CCGSubSurf *ss) {
1132 CCGVert **effectedV;
1133 CCGEdge **effectedE;
1134 CCGFace **effectedF;
1135 int numEffectedV, numEffectedE, numEffectedF;
1136 int subdivLevels = ss->subdivLevels;
1137 int vertDataSize = ss->meshIFC.vertDataSize;
1138 int i,ptrIdx,cornerIdx;
1140 void *q = ss->q, *r = ss->r;
1141 int curLvl, nextLvl;
1144 effectedV = CCGSUBSURF_alloc(ss, sizeof(*effectedV)*ss->vMap->numEntries);
1145 effectedE = CCGSUBSURF_alloc(ss, sizeof(*effectedE)*ss->eMap->numEntries);
1146 effectedF = CCGSUBSURF_alloc(ss, sizeof(*effectedF)*ss->fMap->numEntries);
1147 numEffectedV = numEffectedE = numEffectedF = 0;
1148 for (i=0; i<ss->vMap->curSize; i++) {
1149 CCGVert *v = (CCGVert*) ss->vMap->buckets[i];
1150 for (; v; v = v->next) {
1151 if (v->flags&Vert_eEffected) {
1152 effectedV[numEffectedV++] = v;
1154 for (j=0; j<v->numEdges; j++) {
1155 CCGEdge *e = v->edges[j];
1156 if (!(e->flags&Edge_eEffected)) {
1157 effectedE[numEffectedE++] = e;
1158 e->flags |= Edge_eEffected;
1162 for (j=0; j<v->numFaces; j++) {
1163 CCGFace *f = v->faces[j];
1164 if (!(f->flags&Face_eEffected)) {
1165 effectedF[numEffectedF++] = f;
1166 f->flags |= Face_eEffected;
1173 #define VERT_getCo(v, lvl) _vert_getCo(v, lvl, vertDataSize)
1174 #define EDGE_getCo(e, lvl, x) _edge_getCo(e, lvl, x, vertDataSize)
1175 #define FACE_getIECo(f, lvl, S, x) _face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize)
1176 #define FACE_getIFCo(f, lvl, S, x, y) _face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize)
1180 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1181 CCGFace *f = effectedF[ptrIdx];
1182 void *co = FACE_getCenterData(f);
1184 for (i=0; i<f->numVerts; i++) {
1185 VertDataAdd(co, VERT_getCo(FACE_getVerts(f)[i], curLvl));
1187 VertDataMulN(co, 1.0f/f->numVerts);
1191 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1192 CCGEdge *e = effectedE[ptrIdx];
1193 void *co = EDGE_getCo(e, nextLvl, 1);
1194 float sharpness = EDGE_getSharpness(e, curLvl);
1196 if (_edge_isBoundary(e) || sharpness>=1.0) {
1197 VertDataCopy(co, VERT_getCo(e->v0, curLvl));
1198 VertDataAdd(co, VERT_getCo(e->v1, curLvl));
1199 VertDataMulN(co, 0.5f);
1202 VertDataCopy(q, VERT_getCo(e->v0, curLvl));
1203 VertDataAdd(q, VERT_getCo(e->v1, curLvl));
1204 for (i=0; i<e->numFaces; i++) {
1205 CCGFace *f = e->faces[i];
1206 VertDataAdd(q, FACE_getCenterData(f));
1209 VertDataMulN(q, 1.0f/(2.0f+numFaces));
1211 VertDataCopy(r, VERT_getCo(e->v0, curLvl));
1212 VertDataAdd(r, VERT_getCo(e->v1, curLvl));
1213 VertDataMulN(r, 0.5f);
1215 VertDataCopy(co, q);
1217 VertDataMulN(r, sharpness);
1221 // edge flags cleared later
1223 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
1224 CCGVert *v = effectedV[ptrIdx];
1225 void *co = VERT_getCo(v, curLvl);
1226 void *nCo = VERT_getCo(v, nextLvl);
1227 int sharpCount = 0, allSharp = 1;
1228 float avgSharpness = 0.0;
1229 int seam = VERT_seam(v, ss), seamEdges = 0;
1231 for (i=0; i<v->numEdges; i++) {
1232 CCGEdge *e = v->edges[i];
1233 float sharpness = EDGE_getSharpness(e, curLvl);
1235 if (seam && _edge_isBoundary(e))
1238 if (sharpness!=0.0f) {
1240 avgSharpness += sharpness;
1246 avgSharpness /= sharpCount;
1247 if (avgSharpness>1.0) {
1251 if (seam && seamEdges < 2)
1255 VertDataCopy(nCo, co);
1256 } else if (_vert_isBoundary(v)) {
1257 int numBoundary = 0;
1260 for (i=0; i<v->numEdges; i++) {
1261 CCGEdge *e = v->edges[i];
1262 if (_edge_isBoundary(e)) {
1263 VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
1267 VertDataCopy(nCo, co);
1268 VertDataMulN(nCo, 0.75);
1269 VertDataMulN(r, 0.25f/numBoundary);
1270 VertDataAdd(nCo, r);
1272 int numEdges = 0, numFaces = 0;
1275 for (i=0; i<v->numFaces; i++) {
1276 CCGFace *f = v->faces[i];
1277 VertDataAdd(q, FACE_getCenterData(f));
1280 VertDataMulN(q, 1.0f/numFaces);
1282 for (i=0; i<v->numEdges; i++) {
1283 CCGEdge *e = v->edges[i];
1284 VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
1287 VertDataMulN(r, 1.0f/numEdges);
1289 VertDataCopy(nCo, co);
1290 VertDataMulN(nCo, numEdges-2.0f);
1291 VertDataAdd(nCo, q);
1292 VertDataAdd(nCo, r);
1293 VertDataMulN(nCo, 1.0f/numEdges);
1296 if ((sharpCount>1 && v->numFaces) || seam) {
1300 avgSharpness = 1.0f;
1301 sharpCount = seamEdges;
1305 for (i=0; i<v->numEdges; i++) {
1306 CCGEdge *e = v->edges[i];
1307 float sharpness = EDGE_getSharpness(e, curLvl);
1310 if (_edge_isBoundary(e)) {
1311 CCGVert *oV = _edge_getOtherVert(e, v);
1312 VertDataAdd(q, VERT_getCo(oV, curLvl));
1314 } else if (sharpness != 0.0) {
1315 CCGVert *oV = _edge_getOtherVert(e, v);
1316 VertDataAdd(q, VERT_getCo(oV, curLvl));
1320 VertDataMulN(q, (float) 1/sharpCount);
1322 if (sharpCount!=2 || allSharp) {
1323 // q = q + (co-q)*avgSharpness
1324 VertDataCopy(r, co);
1326 VertDataMulN(r, avgSharpness);
1330 // r = co*.75 + q*.25
1331 VertDataCopy(r, co);
1332 VertDataMulN(r, .75);
1333 VertDataMulN(q, .25);
1336 // nCo = nCo + (r-nCo)*avgSharpness
1337 VertDataSub(r, nCo);
1338 VertDataMulN(r, avgSharpness);
1339 VertDataAdd(nCo, r);
1342 // vert flags cleared later
1345 if (ss->useAgeCounts) {
1346 for (i=0; i<numEffectedV; i++) {
1347 CCGVert *v = effectedV[i];
1348 byte *userData = ccgSubSurf_getVertUserData(ss, v);
1349 *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge;
1352 for (i=0; i<numEffectedE; i++) {
1353 CCGEdge *e = effectedE[i];
1354 byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
1355 *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge;
1358 for (i=0; i<numEffectedF; i++) {
1359 CCGFace *f = effectedF[i];
1360 byte *userData = ccgSubSurf_getFaceUserData(ss, f);
1361 *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge;
1365 for (i=0; i<numEffectedE; i++) {
1366 CCGEdge *e = effectedE[i];
1367 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
1368 VertDataCopy(EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl));
1370 for (i=0; i<numEffectedF; i++) {
1371 CCGFace *f = effectedF[i];
1372 for (S=0; S<f->numVerts; S++) {
1373 CCGEdge *e = FACE_getEdges(f)[S];
1374 CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
1376 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
1377 VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
1378 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
1379 VertDataCopy(FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1));
1381 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 0), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize));
1382 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 1), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize));
1386 for (curLvl=1; curLvl<subdivLevels; curLvl++) {
1387 int edgeSize = 1 + (1<<curLvl);
1388 int gridSize = 1 + (1<<(curLvl-1));
1391 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1392 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1394 /* interior face midpoints
1395 * o old interior face points
1397 for (S=0; S<f->numVerts; S++) {
1398 for (y=0; y<gridSize-1; y++) {
1399 for (x=0; x<gridSize-1; x++) {
1402 void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y+0);
1403 void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y+0);
1404 void *co2 = FACE_getIFCo(f, curLvl, S, x+1, y+1);
1405 void *co3 = FACE_getIFCo(f, curLvl, S, x+0, y+1);
1406 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
1408 VertDataAvg4(co, co0, co1, co2, co3);
1413 /* interior edge midpoints
1414 * o old interior edge points
1415 * o new interior face midpoints
1417 for (S=0; S<f->numVerts; S++) {
1418 for (x=0; x<gridSize-1; x++) {
1420 void *co0 = FACE_getIECo(f, curLvl, S, x+0);
1421 void *co1 = FACE_getIECo(f, curLvl, S, x+1);
1422 void *co2 = FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx);
1423 void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
1424 void *co = FACE_getIECo(f, nextLvl, S, fx);
1426 VertDataAvg4(co, co0, co1, co2, co3);
1429 /* interior face interior edge midpoints
1430 * o old interior face points
1431 * o new interior face midpoints
1435 for (x=1; x<gridSize-1; x++) {
1436 for (y=0; y<gridSize-1; y++) {
1439 void *co0 = FACE_getIFCo(f, curLvl, S, x, y+0);
1440 void *co1 = FACE_getIFCo(f, curLvl, S, x, y+1);
1441 void *co2 = FACE_getIFCo(f, nextLvl, S, fx-1, fy);
1442 void *co3 = FACE_getIFCo(f, nextLvl, S, fx+1, fy);
1443 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
1445 VertDataAvg4(co, co0, co1, co2, co3);
1450 for (y=1; y<gridSize-1; y++) {
1451 for (x=0; x<gridSize-1; x++) {
1454 void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y);
1455 void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y);
1456 void *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy-1);
1457 void *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy+1);
1458 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
1460 VertDataAvg4(co, co0, co1, co2, co3);
1466 /* exterior edge midpoints
1467 * o old exterior edge points
1468 * o new interior face midpoints
1470 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1471 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
1472 float sharpness = EDGE_getSharpness(e, curLvl);
1474 if (_edge_isBoundary(e) || sharpness>1.0) {
1475 for (x=0; x<edgeSize-1; x++) {
1477 void *co0 = EDGE_getCo(e, curLvl, x+0);
1478 void *co1 = EDGE_getCo(e, curLvl, x+1);
1479 void *co = EDGE_getCo(e, nextLvl, fx);
1481 VertDataCopy(co, co0);
1482 VertDataAdd(co, co1);
1483 VertDataMulN(co, 0.5);
1486 for (x=0; x<edgeSize-1; x++) {
1488 void *co0 = EDGE_getCo(e, curLvl, x+0);
1489 void *co1 = EDGE_getCo(e, curLvl, x+1);
1490 void *co = EDGE_getCo(e, nextLvl, fx);
1493 VertDataCopy(q, co0);
1494 VertDataAdd(q, co1);
1496 for (i=0; i<e->numFaces; i++) {
1497 CCGFace *f = e->faces[i];
1498 VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
1502 VertDataMulN(q, 1.0f/(2.0f+numFaces));
1504 VertDataCopy(r, co0);
1505 VertDataAdd(r, co1);
1506 VertDataMulN(r, 0.5);
1508 VertDataCopy(co, q);
1510 VertDataMulN(r, sharpness);
1516 /* exterior vertex shift
1517 * o old vertex points (shifting)
1518 * o old exterior edge points
1519 * o new interior face midpoints
1521 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
1522 CCGVert *v = (CCGVert*) effectedV[ptrIdx];
1523 void *co = VERT_getCo(v, curLvl);
1524 void *nCo = VERT_getCo(v, nextLvl);
1525 int sharpCount = 0, allSharp = 1;
1526 float avgSharpness = 0.0;
1527 int seam = VERT_seam(v, ss), seamEdges = 0;
1529 for (i=0; i<v->numEdges; i++) {
1530 CCGEdge *e = v->edges[i];
1531 float sharpness = EDGE_getSharpness(e, curLvl);
1533 if (seam && _edge_isBoundary(e))
1536 if (sharpness!=0.0f) {
1538 avgSharpness += sharpness;
1544 avgSharpness /= sharpCount;
1545 if (avgSharpness>1.0) {
1549 if (seam && seamEdges < 2)
1553 VertDataCopy(nCo, co);
1554 } else if (_vert_isBoundary(v)) {
1555 int numBoundary = 0;
1558 for (i=0; i<v->numEdges; i++) {
1559 CCGEdge *e = v->edges[i];
1560 if (_edge_isBoundary(e)) {
1561 VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
1566 VertDataCopy(nCo, co);
1567 VertDataMulN(nCo, 0.75);
1568 VertDataMulN(r, 0.25f/numBoundary);
1569 VertDataAdd(nCo, r);
1571 int cornerIdx = (1 + (1<<(curLvl))) - 2;
1572 int numEdges = 0, numFaces = 0;
1575 for (i=0; i<v->numFaces; i++) {
1576 CCGFace *f = v->faces[i];
1577 VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx));
1580 VertDataMulN(q, 1.0f/numFaces);
1582 for (i=0; i<v->numEdges; i++) {
1583 CCGEdge *e = v->edges[i];
1584 VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize));
1587 VertDataMulN(r, 1.0f/numEdges);
1589 VertDataCopy(nCo, co);
1590 VertDataMulN(nCo, numEdges-2.0f);
1591 VertDataAdd(nCo, q);
1592 VertDataAdd(nCo, r);
1593 VertDataMulN(nCo, 1.0f/numEdges);
1596 if ((sharpCount>1 && v->numFaces) || seam) {
1600 avgSharpness = 1.0f;
1601 sharpCount = seamEdges;
1605 for (i=0; i<v->numEdges; i++) {
1606 CCGEdge *e = v->edges[i];
1607 float sharpness = EDGE_getSharpness(e, curLvl);
1610 if (_edge_isBoundary(e))
1611 VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
1612 } else if (sharpness != 0.0) {
1613 VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
1617 VertDataMulN(q, (float) 1/sharpCount);
1619 if (sharpCount!=2 || allSharp) {
1620 // q = q + (co-q)*avgSharpness
1621 VertDataCopy(r, co);
1623 VertDataMulN(r, avgSharpness);
1627 // r = co*.75 + q*.25
1628 VertDataCopy(r, co);
1629 VertDataMulN(r, .75);
1630 VertDataMulN(q, .25);
1633 // nCo = nCo + (r-nCo)*avgSharpness
1634 VertDataSub(r, nCo);
1635 VertDataMulN(r, avgSharpness);
1636 VertDataAdd(nCo, r);
1640 /* exterior edge interior shift
1641 * o old exterior edge midpoints (shifting)
1642 * o old exterior edge midpoints
1643 * o new interior face midpoints
1645 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1646 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
1647 float sharpness = EDGE_getSharpness(e, curLvl);
1649 float avgSharpness = 0.0;
1651 if (sharpness!=0.0f) {
1653 avgSharpness += sharpness;
1655 if (avgSharpness>1.0) {
1663 if (_edge_isBoundary(e) && (!e->numFaces || sharpCount<2)) {
1664 for (x=1; x<edgeSize-1; x++) {
1666 void *co = EDGE_getCo(e, curLvl, x);
1667 void *nCo = EDGE_getCo(e, nextLvl, fx);
1668 VertDataCopy(r, EDGE_getCo(e, curLvl, x-1));
1669 VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
1670 VertDataMulN(r, 0.5);
1671 VertDataCopy(nCo, co);
1672 VertDataMulN(nCo, 0.75);
1673 VertDataMulN(r, 0.25);
1674 VertDataAdd(nCo, r);
1677 for (x=1; x<edgeSize-1; x++) {
1679 void *co = EDGE_getCo(e, curLvl, x);
1680 void *nCo = EDGE_getCo(e, nextLvl, fx);
1685 VertDataAdd(r, EDGE_getCo(e, curLvl, x-1));
1686 VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
1687 for (i=0; i<e->numFaces; i++) {
1688 CCGFace *f = e->faces[i];
1689 VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize));
1690 VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize));
1692 VertDataAdd(r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize));
1695 VertDataMulN(q, 1.0/(numFaces*2.0f));
1696 VertDataMulN(r, 1.0/(2.0f + numFaces));
1698 VertDataCopy(nCo, co);
1699 VertDataMulN(nCo, (float) numFaces);
1700 VertDataAdd(nCo, q);
1701 VertDataAdd(nCo, r);
1702 VertDataMulN(nCo, 1.0f/(2+numFaces));
1704 if (sharpCount==2) {
1705 VertDataCopy(q, co);
1706 VertDataMulN(q, 6.0f);
1707 VertDataAdd(q, EDGE_getCo(e, curLvl, x-1));
1708 VertDataAdd(q, EDGE_getCo(e, curLvl, x+1));
1709 VertDataMulN(q, 1/8.0f);
1711 VertDataSub(q, nCo);
1712 VertDataMulN(q, avgSharpness);
1713 VertDataAdd(nCo, q);
1719 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1720 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1722 /* interior center point shift
1723 * o old face center point (shifting)
1724 * o old interior edge points
1725 * o new interior face midpoints
1728 for (S=0; S<f->numVerts; S++) {
1729 VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1));
1731 VertDataMulN(q, 1.0f/f->numVerts);
1733 for (S=0; S<f->numVerts; S++) {
1734 VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1));
1736 VertDataMulN(r, 1.0f/f->numVerts);
1738 VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f);
1739 VertDataAdd(FACE_getCenterData(f), q);
1740 VertDataAdd(FACE_getCenterData(f), r);
1741 VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
1743 for (S=0; S<f->numVerts; S++) {
1744 /* interior face shift
1745 * o old interior face point (shifting)
1746 * o new interior edge midpoints
1747 * o new interior face midpoints
1749 for (x=1; x<gridSize-1; x++) {
1750 for (y=1; y<gridSize-1; y++) {
1753 void *co = FACE_getIFCo(f, curLvl, S, x, y);
1754 void *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
1756 VertDataAvg4(q, FACE_getIFCo(f, nextLvl, S, fx-1, fy-1),
1757 FACE_getIFCo(f, nextLvl, S, fx+1, fy-1),
1758 FACE_getIFCo(f, nextLvl, S, fx+1, fy+1),
1759 FACE_getIFCo(f, nextLvl, S, fx-1, fy+1));
1761 VertDataAvg4(r, FACE_getIFCo(f, nextLvl, S, fx-1, fy+0),
1762 FACE_getIFCo(f, nextLvl, S, fx+1, fy+0),
1763 FACE_getIFCo(f, nextLvl, S, fx+0, fy-1),
1764 FACE_getIFCo(f, nextLvl, S, fx+0, fy+1));
1766 VertDataCopy(nCo, co);
1767 VertDataSub(nCo, q);
1768 VertDataMulN(nCo, 0.25f);
1769 VertDataAdd(nCo, r);
1773 /* interior edge interior shift
1774 * o old interior edge point (shifting)
1775 * o new interior edge midpoints
1776 * o new interior face midpoints
1778 for (x=1; x<gridSize-1; x++) {
1780 void *co = FACE_getIECo(f, curLvl, S, x);
1781 void *nCo = FACE_getIECo(f, nextLvl, S, fx);
1783 VertDataAvg4(q, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx-1),
1784 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1),
1785 FACE_getIFCo(f, nextLvl, S, fx+1, +1),
1786 FACE_getIFCo(f, nextLvl, S, fx-1, +1));
1788 VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1),
1789 FACE_getIECo(f, nextLvl, S, fx+1),
1790 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx),
1791 FACE_getIFCo(f, nextLvl, S, fx, 1));
1793 VertDataCopy(nCo, co);
1794 VertDataSub(nCo, q);
1795 VertDataMulN(nCo, 0.25f);
1796 VertDataAdd(nCo, r);
1802 edgeSize = 1 + (1<<(nextLvl));
1803 gridSize = 1 + (1<<((nextLvl)-1));
1804 cornerIdx = gridSize-1;
1805 for (i=0; i<numEffectedE; i++) {
1806 CCGEdge *e = effectedE[i];
1807 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
1808 VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl));
1810 for (i=0; i<numEffectedF; i++) {
1811 CCGFace *f = effectedF[i];
1812 for (S=0; S<f->numVerts; S++) {
1813 CCGEdge *e = FACE_getEdges(f)[S];
1814 CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
1816 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
1817 VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
1818 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
1819 VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx));
1820 for (x=1; x<gridSize-1; x++) {
1821 void *co = FACE_getIECo(f, nextLvl, S, x);
1822 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co);
1823 VertDataCopy(FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 0, x), co);
1825 for (x=0; x<gridSize-1; x++) {
1826 int eI = gridSize-1-x;
1827 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
1828 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
1834 #define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
1835 #define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
1836 if (ss->calcVertNormals) {
1837 int lvl = ss->subdivLevels;
1838 int edgeSize = 1 + (1<<lvl);
1839 int gridSize = 1 + (1<<(lvl-1));
1840 int normalDataOffset = ss->normalDataOffset;
1842 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1843 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1846 for (S=0; S<f->numVerts; S++) {
1847 for (y=0; y<gridSize-1; y++)
1848 for (x=0; x<gridSize-1; x++)
1849 NormZero(FACE_getIFNo(f, lvl, S, x, y));
1851 if (FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected)
1852 for (x=0; x<gridSize-1; x++)
1853 NormZero(FACE_getIFNo(f, lvl, S, x, gridSize-1));
1854 if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
1855 for (y=0; y<gridSize-1; y++)
1856 NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, y));
1857 if (FACE_getVerts(f)[S]->flags&Vert_eEffected)
1858 NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1));
1862 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1863 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1867 for (S=0; S<f->numVerts; S++) {
1868 int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected);
1869 int xLimit = !(FACE_getEdges(f)[S]->flags&Edge_eEffected);
1870 int yLimitNext = xLimit;
1871 int xLimitPrev = yLimit;
1873 for (y=0; y<gridSize - 1; y++) {
1874 for (x=0; x<gridSize - 1; x++) {
1875 int xPlusOk = (!xLimit || x<gridSize-2);
1876 int yPlusOk = (!yLimit || y<gridSize-2);
1878 FACE_calcIFNo(f, lvl, S, x, y, no);
1880 NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+0), no);
1882 NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+0), no);
1884 NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+1), no);
1885 if (xPlusOk && yPlusOk) {
1886 if (x<gridSize-2 || y<gridSize-2 || FACE_getVerts(f)[S]->flags&Vert_eEffected) {
1887 NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+1), no);
1894 if (!yLimitNext || 1<gridSize-1)
1895 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, 1), no);
1896 if (!xLimitPrev || 1<gridSize-1)
1897 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no);
1899 for (K=0; K<f->numVerts; K++) {
1901 NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
1905 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no);
1906 if (!yLimitNext || x<gridSize-2)
1907 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x+1), no);
1909 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no);
1910 if (!xLimitPrev || y<gridSize-2)
1911 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y+1, 0), no);
1917 // XXX can I reduce the number of normalisations here?
1918 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
1919 CCGVert *v = (CCGVert*) effectedV[ptrIdx];
1920 float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset);
1924 for (i=0; i<v->numFaces; i++) {
1925 CCGFace *f = v->faces[i];
1926 NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1));
1929 length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
1931 if (length>FLT_EPSILON) {
1932 float invLength = 1.0f/length;
1940 for (i=0; i<v->numFaces; i++) {
1941 CCGFace *f = v->faces[i];
1942 NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no);
1945 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
1946 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
1949 CCGFace *fLast = e->faces[e->numFaces-1];
1952 for (i=0; i<e->numFaces-1; i++) {
1953 CCGFace *f = e->faces[i];
1955 for (x=1; x<edgeSize-1; x++) {
1956 NormAdd(_face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
1957 _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
1961 for (i=0; i<e->numFaces-1; i++) {
1962 CCGFace *f = e->faces[i];
1964 for (x=1; x<edgeSize-1; x++) {
1965 NormCopy(_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
1966 _face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
1971 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1972 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1975 for (S=0; S<f->numVerts; S++) {
1976 NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1),
1977 FACE_getIFNo(f, lvl, S, gridSize-1, 0));
1980 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
1981 CCGFace *f = (CCGFace*) effectedF[ptrIdx];
1984 for (S=0; S<f->numVerts; S++) {
1985 for (y=0; y<gridSize; y++) {
1986 for (x=0; x<gridSize; x++) {
1987 float *no = FACE_getIFNo(f, lvl, S, x, y);
1988 float length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
1990 if (length>FLT_EPSILON) {
1991 float invLength = 1.0f/length;
2005 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
2006 CCGVert *v = effectedV[ptrIdx];
2009 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
2010 CCGEdge *e = effectedE[ptrIdx];
2019 CCGSUBSURF_free(ss, effectedF);
2020 CCGSUBSURF_free(ss, effectedE);
2021 CCGSUBSURF_free(ss, effectedV);
2024 /*** External API accessor functions ***/
2026 int ccgSubSurf_getNumVerts(CCGSubSurf *ss) {
2027 return ss->vMap->numEntries;
2029 int ccgSubSurf_getNumEdges(CCGSubSurf *ss) {
2030 return ss->eMap->numEntries;
2032 int ccgSubSurf_getNumFaces(CCGSubSurf *ss) {
2033 return ss->fMap->numEntries;
2036 CCGVert *ccgSubSurf_getVert(CCGSubSurf *ss, CCGVertHDL v) {
2037 return (CCGVert*) _ehash_lookup(ss->vMap, v);
2039 CCGEdge *ccgSubSurf_getEdge(CCGSubSurf *ss, CCGEdgeHDL e) {
2040 return (CCGEdge*) _ehash_lookup(ss->eMap, e);
2042 CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f) {
2043 return (CCGFace*) _ehash_lookup(ss->fMap, f);
2046 int ccgSubSurf_getSubdivisionLevels(CCGSubSurf *ss) {
2047 return ss->subdivLevels;
2049 int ccgSubSurf_getEdgeSize(CCGSubSurf *ss) {
2050 return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels);
2052 int ccgSubSurf_getEdgeLevelSize(CCGSubSurf *ss, int level) {
2053 if (level<1 || level>ss->subdivLevels) {
2056 return 1 + (1<<level);
2059 int ccgSubSurf_getGridSize(CCGSubSurf *ss) {
2060 return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels);
2062 int ccgSubSurf_getGridLevelSize(CCGSubSurf *ss, int level) {
2063 if (level<1 || level>ss->subdivLevels) {
2066 return 1 + (1<<(level-1));
2070 /* Vert accessors */
2072 CCGVertHDL ccgSubSurf_getVertVertHandle(CCGSubSurf *ss, CCGVert *v) {
2075 int ccgSubSurf_getVertAge(CCGSubSurf *ss, CCGVert *v) {
2076 if (ss->useAgeCounts) {
2077 byte *userData = ccgSubSurf_getVertUserData(ss, v);
2078 return ss->currentAge - *((int*) &userData[ss->vertUserAgeOffset]);
2083 void *ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v) {
2084 return VERT_getLevelData(v) + ss->meshIFC.vertDataSize*(ss->subdivLevels+1);
2086 int ccgSubSurf_getVertNumFaces(CCGSubSurf *ss, CCGVert *v) {
2089 CCGFace *ccgSubSurf_getVertFace(CCGSubSurf *ss, CCGVert *v, int index) {
2090 if (index<0 || index>=v->numFaces) {
2093 return v->faces[index];
2096 int ccgSubSurf_getVertNumEdges(CCGSubSurf *ss, CCGVert *v) {
2099 CCGEdge *ccgSubSurf_getVertEdge(CCGSubSurf *ss, CCGVert *v, int index) {
2100 if (index<0 || index>=v->numEdges) {
2103 return v->edges[index];
2106 void *ccgSubSurf_getVertData(CCGSubSurf *ss, CCGVert *v) {
2107 return ccgSubSurf_getVertLevelData(ss, v, ss->subdivLevels);
2109 void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level) {
2110 if (level<0 || level>ss->subdivLevels) {
2113 return _vert_getCo(v, level, ss->meshIFC.vertDataSize);
2117 /* Edge accessors */
2119 CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle(CCGSubSurf *ss, CCGEdge *e) {
2122 int ccgSubSurf_getEdgeAge(CCGSubSurf *ss, CCGEdge *e) {
2123 if (ss->useAgeCounts) {
2124 byte *userData = ccgSubSurf_getEdgeUserData(ss, e);
2125 return ss->currentAge - *((int*) &userData[ss->edgeUserAgeOffset]);
2130 void *ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e) {
2131 return EDGE_getLevelData(e) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1);
2133 int ccgSubSurf_getEdgeNumFaces(CCGSubSurf *ss, CCGEdge *e) {
2136 CCGFace *ccgSubSurf_getEdgeFace(CCGSubSurf *ss, CCGEdge *e, int index) {
2137 if (index<0 || index>=e->numFaces) {
2140 return e->faces[index];
2143 CCGVert *ccgSubSurf_getEdgeVert0(CCGSubSurf *ss, CCGEdge *e) {
2146 CCGVert *ccgSubSurf_getEdgeVert1(CCGSubSurf *ss, CCGEdge *e) {
2149 void *ccgSubSurf_getEdgeDataArray(CCGSubSurf *ss, CCGEdge *e) {
2150 return ccgSubSurf_getEdgeData(ss, e, 0);
2152 void *ccgSubSurf_getEdgeData(CCGSubSurf *ss, CCGEdge *e, int x) {
2153 return ccgSubSurf_getEdgeLevelData(ss, e, x, ss->subdivLevels);
2155 void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level) {
2156 if (level<0 || level>ss->subdivLevels) {
2159 return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
2162 float ccgSubSurf_getEdgeCrease(CCGSubSurf *ss, CCGEdge *e) {
2166 /* Face accessors */
2168 CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *ss, CCGFace *f) {
2171 int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) {
2172 if (ss->useAgeCounts) {
2173 byte *userData = ccgSubSurf_getFaceUserData(ss, f);
2174 return ss->currentAge - *((int*) &userData[ss->faceUserAgeOffset]);
2179 void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) {
2180 int maxGridSize = 1 + (1<<(ss->subdivLevels-1));
2181 return FACE_getCenterData(f) + ss->meshIFC.vertDataSize *(1 + f->numVerts*maxGridSize + f->numVerts*maxGridSize*maxGridSize);
2183 int ccgSubSurf_getFaceNumVerts(CCGSubSurf *ss, CCGFace *f) {
2186 CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *ss, CCGFace *f, int index) {
2187 if (index<0 || index>=f->numVerts) {
2190 return FACE_getVerts(f)[index];
2193 CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *ss, CCGFace *f, int index) {
2194 if (index<0 || index>=f->numVerts) {
2197 return FACE_getEdges(f)[index];
2200 int ccgSubSurf_getFaceEdgeIndex(CCGSubSurf *ss, CCGFace *f, CCGEdge *e) {
2203 for (i=0; i<f->numVerts; i++)
2204 if (FACE_getEdges(f)[i]==e)
2209 void *ccgSubSurf_getFaceCenterData(CCGSubSurf *ss, CCGFace *f) {
2210 return FACE_getCenterData(f);
2212 void *ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
2213 return ccgSubSurf_getFaceGridEdgeData(ss, f, gridIndex, 0);
2215 void *ccgSubSurf_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x) {
2216 return _face_getIECo(f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize);
2218 void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) {
2219 return ccgSubSurf_getFaceGridData(ss, f, gridIndex, 0, 0);
2221 void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y) {
2222 return _face_getIFCo(f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize);
2225 /*** External API iterator functions ***/
2227 CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss) {
2228 return (CCGVertIterator*) _ehashIterator_new(ss->vMap);
2230 CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss) {
2231 return (CCGEdgeIterator*) _ehashIterator_new(ss->eMap);
2233 CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss) {
2234 return (CCGFaceIterator*) _ehashIterator_new(ss->fMap);
2237 CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi) {
2238 return (CCGVert*) _ehashIterator_getCurrent((EHashIterator*) vi);
2240 int ccgVertIterator_isStopped(CCGVertIterator *vi) {
2241 return _ehashIterator_isStopped((EHashIterator*) vi);
2243 void ccgVertIterator_next(CCGVertIterator *vi) {
2244 _ehashIterator_next((EHashIterator*) vi);
2246 void ccgVertIterator_free(CCGVertIterator *vi) {
2247 _ehashIterator_free((EHashIterator*) vi);
2250 CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi) {
2251 return (CCGEdge*) _ehashIterator_getCurrent((EHashIterator*) vi);
2253 int ccgEdgeIterator_isStopped(CCGEdgeIterator *vi) {
2254 return _ehashIterator_isStopped((EHashIterator*) vi);
2256 void ccgEdgeIterator_next(CCGEdgeIterator *vi) {
2257 _ehashIterator_next((EHashIterator*) vi);
2259 void ccgEdgeIterator_free(CCGEdgeIterator *vi) {
2260 _ehashIterator_free((EHashIterator*) vi);
2263 CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi) {
2264 return (CCGFace*) _ehashIterator_getCurrent((EHashIterator*) vi);
2266 int ccgFaceIterator_isStopped(CCGFaceIterator *vi) {
2267 return _ehashIterator_isStopped((EHashIterator*) vi);
2269 void ccgFaceIterator_next(CCGFaceIterator *vi) {
2270 _ehashIterator_next((EHashIterator*) vi);
2272 void ccgFaceIterator_free(CCGFaceIterator *vi) {
2273 _ehashIterator_free((EHashIterator*) vi);
2276 /*** Extern API final vert/edge/face interface ***/
2278 int ccgSubSurf_getNumFinalVerts(CCGSubSurf *ss) {
2279 int edgeSize = 1 + (1<<ss->subdivLevels);
2280 int gridSize = 1 + (1<<(ss->subdivLevels-1));
2281 int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2)));
2282 return numFinalVerts;
2284 int ccgSubSurf_getNumFinalEdges(CCGSubSurf *ss) {
2285 int edgeSize = 1 + (1<<ss->subdivLevels);
2286 int gridSize = 1 + (1<<(ss->subdivLevels-1));
2287 int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1)));
2288 return numFinalEdges;
2290 int ccgSubSurf_getNumFinalFaces(CCGSubSurf *ss) {
2291 int gridSize = 1 + (1<<(ss->subdivLevels-1));
2292 int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1));
2293 return numFinalFaces;