From 887b598d716085cd9aee87fdb19980bfc081da70 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 21 Mar 2005 01:34:27 +0000 Subject: - Initial integration of CCGSubSurf library into blender. The lib is only in one C file and not worth dropping in extern but presumably will be synced with public CCGSubSurf release I hope to be making soon. - Currently the implementation must be enabled by defining USE_CCGSUBSURFLIB somewhere with your build system. The code should be considered highly experimental. --- source/blender/blenkernel/intern/CCGSubSurf.c | 1825 +++++++++++++++++++++++++ source/blender/blenkernel/intern/CCGSubSurf.h | 163 +++ source/blender/blenkernel/intern/subsurf.c | 14 +- source/blender/makesdna/DNA_mesh_types.h | 3 + source/blender/src/buttons_editing.c | 5 +- 5 files changed, 2005 insertions(+), 5 deletions(-) create mode 100644 source/blender/blenkernel/intern/CCGSubSurf.c create mode 100644 source/blender/blenkernel/intern/CCGSubSurf.h diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c new file mode 100644 index 00000000000..78d5d8e1d11 --- /dev/null +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -0,0 +1,1825 @@ +#ifdef USE_CCGSUBSURFLIB + +/* $Id$ */ + +#include +#include + +#include "CCGSubSurf.h" + +/***/ + +typedef unsigned char byte; + +/***/ + +static int kHashSizes[] = { + 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, + 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, + 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459 +}; + +typedef struct _EHEntry EHEntry; +struct _EHEntry { + EHEntry *next; + void *key; +}; +typedef struct _EHash { + EHEntry **buckets; + int numEntries, curSize, curSizeIdx; + + CCGAllocatorIFC allocatorIFC; + CCGAllocatorHDL allocator; +} EHash; + +#define EHASH_alloc(eh, nb) ((eh)->allocatorIFC.alloc((eh)->allocator, nb)) +#define EHASH_free(eh, ptr) ((eh)->allocatorIFC.free((eh)->allocator, ptr)) + +#define EHASH_hash(eh, item) (((unsigned int) (item))%((unsigned int) (eh)->curSize)) + +static EHash *_ehash_new(int estimatedNumEntries, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) { + EHash *eh = allocatorIFC->alloc(allocator, sizeof(*eh)); + eh->allocatorIFC = *allocatorIFC; + eh->allocator = allocator; + eh->numEntries = 0; + eh->curSizeIdx = 0; + while (kHashSizes[eh->curSizeIdx]curSizeIdx++; + eh->curSize = kHashSizes[eh->curSizeIdx]; + eh->buckets = EHASH_alloc(eh, eh->curSize*sizeof(*eh->buckets)); + memset(eh->buckets, 0, eh->curSize*sizeof(*eh->buckets)); + + return eh; +} +typedef void (*EHEntryFreeFP)(EHEntry *, void *); +static void _ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *userData) { + int numBuckets = eh->curSize; + + while (numBuckets--) { + EHEntry *entry = eh->buckets[numBuckets]; + + while (entry) { + EHEntry *next = entry->next; + + freeEntry(entry, userData); + + entry = next; + } + } + + EHASH_free(eh, eh->buckets); + EHASH_free(eh, eh); +} + +static void _ehash_insert(EHash *eh, EHEntry *entry) { + int numBuckets = eh->curSize; + int hash = EHASH_hash(eh, entry->key); + entry->next = eh->buckets[hash]; + eh->buckets[hash] = entry; + eh->numEntries++; + + if (eh->numEntries > (numBuckets*3)) { + EHEntry **oldBuckets = eh->buckets; + eh->curSize = kHashSizes[++eh->curSizeIdx]; + + eh->buckets = EHASH_alloc(eh, eh->curSize*sizeof(*eh->buckets)); + memset(eh->buckets, 0, eh->curSize*sizeof(*eh->buckets)); + + while (numBuckets--) { + for (entry = oldBuckets[numBuckets]; entry;) { + EHEntry *next = entry->next; + + hash = EHASH_hash(eh, entry->key); + entry->next = eh->buckets[hash]; + eh->buckets[hash] = entry; + + entry = next; + } + } + + EHASH_free(eh, oldBuckets); + } +} + +static void *_ehash_lookupWithPrev(EHash *eh, void *key, void ***prevp_r) { + int hash = EHASH_hash(eh, key); + EHEntry *entry, **prevp = &eh->buckets[hash]; + + for (; (entry = *prevp); prevp = &entry->next) { + if (entry->key==key) { + *prevp_r = prevp; + return entry; + } + } + + return NULL; +} + +static void *_ehash_lookup(EHash *eh, void *key) { + int hash = EHASH_hash(eh, key); + EHEntry *entry; + + for (entry = eh->buckets[hash]; entry; entry = entry->next) + if (entry->key==key) + break; + + return entry; +} + +/**/ + +typedef struct _EHashIterator { + EHash *eh; + int curBucket; + EHEntry *curEntry; +} EHashIterator; + +static EHashIterator *_ehashIterator_new(EHash *eh) { + EHashIterator *ehi = EHASH_alloc(eh, sizeof(*ehi)); + ehi->eh = eh; + ehi->curEntry = NULL; + ehi->curBucket = -1; + while (!ehi->curEntry) { + ehi->curBucket++; + if (ehi->curBucket==ehi->eh->curSize) + break; + ehi->curEntry = ehi->eh->buckets[ehi->curBucket]; + } + return ehi; +} +static void _ehashIterator_free(EHashIterator *ehi) { + EHASH_free(ehi->eh, ehi); +} + +static void *_ehashIterator_getCurrent(EHashIterator *ehi) { + return ehi->curEntry; +} + +static void _ehashIterator_next(EHashIterator *ehi) { + if (ehi->curEntry) { + ehi->curEntry = ehi->curEntry->next; + while (!ehi->curEntry) { + ehi->curBucket++; + if (ehi->curBucket==ehi->eh->curSize) + break; + ehi->curEntry = ehi->eh->buckets[ehi->curBucket]; + } + } +} +static int _ehashIterator_isStopped(EHashIterator *ehi) { + return !ehi->curEntry; +} + +/***/ + +static void *_stdAllocator_alloc(CCGAllocatorHDL a, int numBytes) { + return malloc(numBytes); +} +static void *_stdAllocator_realloc(CCGAllocatorHDL a, void *ptr, int newSize, int oldSize) { + return realloc(ptr, newSize); +} +static void _stdAllocator_free(CCGAllocatorHDL a, void *ptr) { + free(ptr); +} + +static CCGAllocatorIFC *_getStandardAllocatorIFC(void) { + static CCGAllocatorIFC ifc; + + ifc.alloc = _stdAllocator_alloc; + ifc.realloc = _stdAllocator_realloc; + ifc.free = _stdAllocator_free; + ifc.release = NULL; + + return &ifc; +} + +/***/ + +static int _edge_isBoundary(CCGEdge *e); + +/***/ + +enum { + Vert_eEffected= (1<<0), + Vert_eChanged= (1<<1), +} VertFlags; +enum { + Edge_eEffected= (1<<0), +} CCGEdgeFlags; +enum { + Face_eEffected= (1<<0), +} FaceFlags; + +struct _CCGVert { + CCGVert *next; /* EHData.next */ + CCGVertHDL vHDL; /* EHData.key */ + + short numEdges, numFaces, flags, pad; + + CCGEdge **edges; + CCGFace **faces; +// byte *levelData; +// byte *userData; +}; +#define VERT_getLevelData(v) ((byte*) &(v)[1]) + +struct _CCGEdge { + CCGEdge *next; /* EHData.next */ + CCGEdgeHDL eHDL; /* EHData.key */ + + short numFaces, flags; + + CCGVert *v0,*v1; + CCGFace **faces; + +// byte *levelData; +// byte *userData; +}; +#define EDGE_getLevelData(e) ((byte*) &(e)[1]) + +struct _CCGFace { + CCGFace *next; /* EHData.next */ + CCGFaceHDL fHDL; /* EHData.key */ + + short numVerts, flags, pad1, pad2; + +// CCGVert **verts; +// CCGEdge **edges; +// byte *centerData; +// byte **gridData; +// byte *userData; +}; +#define FACE_getVerts(f) ((CCGVert**) &(f)[1]) +#define FACE_getEdges(f) ((CCGEdge**) &(FACE_getVerts(f)[(f)->numVerts])) +#define FACE_getCenterData(f) ((byte*) &(FACE_getEdges(f)[(f)->numVerts])) + +typedef enum { + eSyncState_None = 0, + eSyncState_Vert, + eSyncState_Edge, + eSyncState_Face, + eSyncState_Partial, +} SyncState; + +struct _CCGSubSurf { + EHash *vMap; /* map of CCGVertHDL -> Vert */ + EHash *eMap; /* map of CCGEdgeHDL -> Edge */ + EHash *fMap; /* map of CCGFaceHDL -> Face */ + + CCGMeshIFC meshIFC; + void *meshData; + + CCGAllocatorIFC allocatorIFC; + CCGAllocatorHDL allocator; + + int subdivLevels; + int numGrids; + int allowEdgeCreation; + + void *q, *r; + + // data for age'ing (to debug sync) + int currentAge; + int useAgeCounts; + int vertUserAgeOffset; + int edgeUserAgeOffset; + int faceUserAgeOffset; + + // data used during syncing + SyncState syncState; + + EHash *oldVMap, *oldEMap, *oldFMap; + int lenTempArrays; + CCGVert **tempVerts; + CCGEdge **tempEdges; +}; + +#define CCGSUBSURF_alloc(ss, nb) ((ss)->allocatorIFC.alloc((ss)->allocator, nb)) +#define CCGSUBSURF_realloc(ss, ptr, nb, ob) ((ss)->allocatorIFC.realloc((ss)->allocator, ptr, nb, ob)) +#define CCGSUBSURF_free(ss, ptr) ((ss)->allocatorIFC.free((ss)->allocator, ptr)) + +/***/ + +static CCGVert *_vert_new(CCGVertHDL vHDL, int levels, int dataSize, CCGSubSurf *ss) { + CCGVert *v = CCGSUBSURF_alloc(ss, sizeof(CCGVert) + ss->meshIFC.vertDataSize * (ss->subdivLevels+1) + ss->meshIFC.vertUserSize); + byte *userData; + + v->vHDL = vHDL; + v->edges = NULL; + v->faces = NULL; + v->numEdges = v->numFaces = 0; + v->flags = 0; + + userData = ccgSubSurf_getVertUserData(ss, v); + memset(userData, 0, ss->meshIFC.vertUserSize); + if (ss->useAgeCounts) *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge; + + return v; +} +static void _vert_remEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss) { + int i; + for (i=0; inumEdges; i++) { + if (v->edges[i]==e) { + v->edges[i] = v->edges[--v->numEdges]; + break; + } + } +} +static void _vert_remFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) { + int i; + for (i=0; inumFaces; i++) { + if (v->faces[i]==f) { + v->faces[i] = v->faces[--v->numFaces]; + break; + } + } +} +static void _vert_addEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss) { + v->edges = CCGSUBSURF_realloc(ss, v->edges, (v->numEdges+1)*sizeof(*v->edges), v->numEdges*sizeof(*v->edges)); + v->edges[v->numEdges++] = e; +} +static void _vert_addFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) { + v->faces = CCGSUBSURF_realloc(ss, v->faces, (v->numFaces+1)*sizeof(*v->faces), v->numFaces*sizeof(*v->faces)); + v->faces[v->numFaces++] = f; +} +static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) { + int i; + for (i=0; inumEdges; i++) { + CCGEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse + if ( (e->v0==v && e->v1==vQ) || + (e->v1==v && e->v0==vQ)) + return e; + } + return 0; +} +static int _vert_isBoundary(CCGVert *v) { + int i; + for (i=0; inumEdges; i++) + if (_edge_isBoundary(v->edges[i])) + return 1; + return 0; +} +static int _vert_getEdgeIndex(CCGVert *v, CCGEdge *e) { + int i; + for (i=0; v->numEdges; i++) + if (v->edges[i]==e) + return i; + return -1; +} +static int _vert_getFaceIndex(CCGVert *v, CCGFace *f) { + int i; + for (i=0; v->numFaces; i++) + if (v->faces[i]==f) + return i; + return -1; +} + +static void *_vert_getCo(CCGVert *v, int lvl, int dataSize) { + return &VERT_getLevelData(v)[lvl*dataSize]; +} + +static void _vert_free(CCGVert *v, CCGSubSurf *ss) { + CCGSUBSURF_free(ss, v->edges); + CCGSUBSURF_free(ss, v->faces); + CCGSUBSURF_free(ss, v); +} + +/***/ + +static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, int levels, int dataSize, CCGSubSurf *ss) { + CCGEdge *e = CCGSUBSURF_alloc(ss, sizeof(CCGEdge) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1) + ss->meshIFC.edgeUserSize); + byte *userData; + + e->eHDL = eHDL; + e->v0 = v0; + e->v1 = v1; + e->faces = NULL; + e->numFaces = 0; + e->flags = 0; + _vert_addEdge(v0, e, ss); + _vert_addEdge(v1, e, ss); + + userData = ccgSubSurf_getEdgeUserData(ss, e); + memset(userData, 0, ss->meshIFC.edgeUserSize); + if (ss->useAgeCounts) *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge; + + return e; +} +void _edge_remFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) { + int i; + for (i=0; inumFaces; i++) { + if (e->faces[i]==f) { + e->faces[i] = e->faces[--e->numFaces]; + break; + } + } +} +void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) { + e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces+1)*sizeof(*e->faces), e->numFaces*sizeof(*e->faces)); + e->faces[e->numFaces++] = f; +} +static int _edge_getFaceIndex(CCGEdge *e, CCGFace *f) { + int i; + for (i=0; inumFaces; i++) + if (e->faces[i]==f) + return i; + return -1; +} +static int _edge_isBoundary(CCGEdge *e) { + return e->numFaces<2; +} + +static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ) { + if (vQ==e->v0) { + return e->v1; + } else { + return e->v0; + } +} + +static void *_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize) { + int levelBase = lvl + (1<v0) { + return &EDGE_getLevelData(e)[dataSize*(levelBase + x)]; + } else { + return &EDGE_getLevelData(e)[dataSize*(levelBase + (1<faces); + CCGSUBSURF_free(ss, e); +} +static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss) { + _vert_remEdge(e->v0, e, ss); + _vert_remEdge(e->v1, e, ss); + e->v0->flags |= Vert_eEffected; + e->v1->flags |= Vert_eEffected; + _edge_free(e, ss); +} + +/***/ + +static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, int levels, int dataSize, CCGSubSurf *ss) { + int maxGridSize = 1 + (1<<(ss->subdivLevels-1)); + 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); + CCGVert **fVerts = FACE_getVerts(f); + byte *userData; + int i; + + f->numVerts = numVerts; + f->fHDL = fHDL; + f->flags = 0; + + for (i=0; imeshIFC.faceUserSize); + if (ss->useAgeCounts) *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge; + + return f; +} + +static void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) { + int maxGridSize = 1 + (1<<(levels-1)); + int spacing = 1<<(levels-lvl); + byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); + return &gridBase[dataSize*x*spacing]; +} +static void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) { + int maxGridSize = 1 + (1<<(levels-1)); + int spacing = 1<<(levels-lvl); + byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); + return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)]; +} +static int _face_getVertIndex(CCGFace *f, CCGVert *v) { + int i; + for (i=0; inumVerts; i++) + if (FACE_getVerts(f)[i]==v) + return i; + return -1; +} +static int _face_getEdgeIndex(CCGFace *f, CCGEdge *e) { + int i; + for (i=0; inumVerts; i++) + if (FACE_getEdges(f)[i]==e) + return i; + return -1; +} +static void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) { + int maxGridSize = 1 + (1<<(levels-1)); + int spacing = 1<<(levels-lvl); + int S, x, y, cx, cy; + + for (S=0; SnumVerts; S++) + if (FACE_getEdges(f)[S]==e) + break; + + eX = eX*spacing; + eY = eY*spacing; + if (e->v0!=FACE_getVerts(f)[S]) { + eX = (maxGridSize*2 - 1)-1 - eX; + } + y = maxGridSize - 1 - eX; + x = maxGridSize - 1 - eY; + if (x<0) { + S = (S+f->numVerts-1)%f->numVerts; + cx = y; + cy = -x; + } else if (y<0) { + S = (S+1)%f->numVerts; + cx = -y; + cy = x; + } else { + cx = x; + cy = y; + } + return _face_getIFCo(f, levels, S, cx, cy, levels, dataSize); +} + +static void _face_free(CCGFace *f, CCGSubSurf *ss) { + CCGSUBSURF_free(ss, f); +} +static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss) { + int j; + for (j=0; jnumVerts; j++) { + _vert_remFace(FACE_getVerts(f)[j], f, ss); + _edge_remFace(FACE_getEdges(f)[j], f, ss); + FACE_getVerts(f)[j]->flags |= Vert_eEffected; + } + _face_free(f, ss); +} + +/***/ + +CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, CCGMeshHDL meshData, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) { + if (!allocatorIFC) { + allocatorIFC = _getStandardAllocatorIFC(); + allocator = NULL; + } + + if (subdivLevels<1) { + return NULL; + } else { + CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss)); + + ss->allocatorIFC = *allocatorIFC; + ss->allocator = allocator; + + ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); + ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); + ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); + + ss->meshIFC = *ifc; + ss->meshData = meshData; + + ss->subdivLevels = subdivLevels; + ss->numGrids = 0; + ss->allowEdgeCreation = 0; + + ss->useAgeCounts = 0; + ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0; + + ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); + ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); + + ss->currentAge = 0; + + ss->syncState = eSyncState_None; + + ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL; + ss->lenTempArrays = 0; + ss->tempVerts = NULL; + ss->tempEdges = NULL; + + return ss; + } +} + +void ccgSubSurf_free(CCGSubSurf *ss) { + CCGAllocatorIFC allocatorIFC = ss->allocatorIFC; + CCGAllocatorHDL allocator = ss->allocator; + + if (ss->syncState) { + _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_free, ss); + _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_free, ss); + _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss); + + CCGSUBSURF_free(ss, ss->tempVerts); + CCGSUBSURF_free(ss, ss->tempEdges); + } + + CCGSUBSURF_free(ss, ss->r); + CCGSUBSURF_free(ss, ss->q); + + _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss); + _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss); + _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss); + + CCGSUBSURF_free(ss, ss); + + if (allocatorIFC.release) { + allocatorIFC.release(allocator); + } +} + +CCGError ccgSubSurf_setAllowEdgeCreation(CCGSubSurf *ss, int allowEdgeCreation) { + ss->allowEdgeCreation = !!allowEdgeCreation; + + return eCCGError_None; +} + +CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels) { + if (subdivisionLevels<=0) { + return eCCGError_InvalidValue; + } else if (subdivisionLevels!=ss->subdivLevels) { + ss->numGrids = 0; + ss->subdivLevels = subdivisionLevels; + _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss); + _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss); + _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss); + ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); + ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); + ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); + } + + return eCCGError_None; +} + +CCGError ccgSubSurf_setUseAgeCounts(CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset) { + if (useAgeCounts) { + if ( (vertUserOffset+4>ss->meshIFC.vertUserSize) || + (edgeUserOffset+4>ss->meshIFC.edgeUserSize) || + (faceUserOffset+4>ss->meshIFC.faceUserSize)) { + return eCCGError_InvalidValue; + } else { + ss->useAgeCounts = 1; + ss->vertUserAgeOffset = vertUserOffset; + ss->edgeUserAgeOffset = edgeUserOffset; + ss->faceUserAgeOffset = faceUserOffset; + } + } else { + ss->useAgeCounts = 0; + ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0; + } + + return eCCGError_None; +} + +/***/ + +CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) { + if (ss->syncState!=eSyncState_None) { + return eCCGError_InvalidSyncState; + } + + ss->currentAge++; + + ss->oldVMap = ss->vMap; + ss->oldEMap = ss->eMap; + ss->oldFMap = ss->fMap; + + ss->vMap = _ehash_new(ss->oldVMap->numEntries, &ss->allocatorIFC, ss->allocator); + ss->eMap = _ehash_new(ss->oldFMap->numEntries, &ss->allocatorIFC, ss->allocator); + ss->fMap = _ehash_new(ss->oldEMap->numEntries, &ss->allocatorIFC, ss->allocator); + + ss->numGrids = 0; + + ss->lenTempArrays = 12; + ss->tempVerts = CCGSUBSURF_alloc(ss, sizeof(*ss->tempVerts)*ss->lenTempArrays); + ss->tempEdges = CCGSUBSURF_alloc(ss, sizeof(*ss->tempEdges)*ss->lenTempArrays); + + ss->syncState = eSyncState_Vert; + + return eCCGError_None; +} + +CCGError ccgSubSurf_initPartialSync(CCGSubSurf *ss) { + if (ss->syncState!=eSyncState_None) { + return eCCGError_InvalidSyncState; + } + + ss->currentAge++; + + ss->syncState = eSyncState_Partial; + + return eCCGError_None; +} + +CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL) { + if (ss->syncState!=eSyncState_Partial) { + return eCCGError_InvalidSyncState; + } else { + CCGVert **prevp, *v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp); + + if (!v || v->numFaces || v->numEdges) { + return eCCGError_InvalidValue; + } else { + *prevp = v->next; + _vert_free(v, ss); + } + } + + return eCCGError_None; +} + +CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL) { + if (ss->syncState!=eSyncState_Partial) { + return eCCGError_InvalidSyncState; + } else { + CCGEdge **prevp, *e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp); + + if (!e || e->numFaces) { + return eCCGError_InvalidValue; + } else { + *prevp = e->next; + _edge_unlinkMarkAndFree(e, ss); + } + } + + return eCCGError_None; +} + +CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) { + if (ss->syncState!=eSyncState_Partial) { + return eCCGError_InvalidSyncState; + } else { + CCGFace **prevp, *f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp); + + if (!f) { + return eCCGError_InvalidValue; + } else { + *prevp = f->next; + _face_unlinkMarkAndFree(f, ss); + } + } + + return eCCGError_None; +} + +CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData) { + CCGVert **prevp, *v; + + if (ss->syncState==eSyncState_Partial) { + v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp); + if (!v) { + v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss); + ss->meshIFC.vertDataCopy(ss->meshData, _vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData); + _ehash_insert(ss->vMap, (EHEntry*) v); + v->flags = Vert_eEffected; + } else if (!ss->meshIFC.vertDataEqual(ss->meshData, vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize))) { + int i, j; + + ss->meshIFC.vertDataCopy(ss->meshData, _vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData); + v->flags = Vert_eEffected; + + for (i=0; inumEdges; i++) { + CCGEdge *e = v->edges[i]; + e->v0->flags |= Vert_eEffected; + e->v1->flags |= Vert_eEffected; + } + for (i=0; inumFaces; i++) { + CCGFace *f = v->faces[i]; + for (j=0; jnumVerts; j++) { + FACE_getVerts(f)[j]->flags |= Vert_eEffected; + } + } + } + } else { + if (ss->syncState!=eSyncState_Vert) { + return eCCGError_InvalidSyncState; + } + + v = _ehash_lookupWithPrev(ss->oldVMap, vHDL, &prevp); + if (!v) { + v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss); + ss->meshIFC.vertDataCopy(ss->meshData, _vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData); + _ehash_insert(ss->vMap, (EHEntry*) v); + v->flags = Vert_eEffected; + } else if (!ss->meshIFC.vertDataEqual(ss->meshData, vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize))) { + *prevp = v->next; + _ehash_insert(ss->vMap, (EHEntry*) v); + ss->meshIFC.vertDataCopy(ss->meshData, _vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData); + v->flags = Vert_eEffected|Vert_eChanged; + } else { + *prevp = v->next; + _ehash_insert(ss->vMap, (EHEntry*) v); + v->flags = 0; + } + } + + return eCCGError_None; +} + +CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1) { + CCGEdge **prevp, *e, *eNew; + + if (ss->syncState==eSyncState_Partial) { + e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp); + if (!e || ((e->v0->vHDL!=e_vHDL0) || (e->v1->vHDL!=e_vHDL1))) { + CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0); + CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1); + + eNew = _edge_new(eHDL, v0, v1, ss->subdivLevels, ss->meshIFC.vertDataSize, ss); + + if (e) { + *prevp = eNew; + eNew->next = e->next; + + _edge_unlinkMarkAndFree(e, ss); + } else { + _ehash_insert(ss->eMap, (EHEntry*) eNew); + } + + eNew->v0->flags |= Vert_eEffected; + eNew->v1->flags |= Vert_eEffected; + } + } else { + if (ss->syncState==eSyncState_Vert) { + ss->syncState = eSyncState_Edge; + } else if (ss->syncState!=eSyncState_Edge) { + return eCCGError_InvalidSyncState; + } + + e = _ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp); + if (!e || ((e->v0->vHDL!=e_vHDL0) || (e->v1->vHDL!=e_vHDL1))) { + CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0); + CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1); + e = _edge_new(eHDL, v0, v1, ss->subdivLevels, ss->meshIFC.vertDataSize, ss); + _ehash_insert(ss->eMap, (EHEntry*) e); + e->v0->flags |= Vert_eEffected; + e->v1->flags |= Vert_eEffected; + } else { + *prevp = e->next; + _ehash_insert(ss->eMap, (EHEntry*) e); + e->flags = 0; + if ((e->v0->flags|e->v1->flags)&Vert_eChanged) { + e->v0->flags |= Vert_eEffected; + e->v1->flags |= Vert_eEffected; + } + } + } + + return eCCGError_None; +} + +CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs) { + CCGFace **prevp, *f, *fNew; + int j, k, topologyChanged = 0; + + if (numVerts>ss->lenTempArrays) { + int oldLen = ss->lenTempArrays; + ss->lenTempArrays = (numVertslenTempArrays*2)?ss->lenTempArrays*2:numVerts; + ss->tempVerts = CCGSUBSURF_realloc(ss, ss->tempVerts, sizeof(*ss->tempVerts)*ss->lenTempArrays, sizeof(*ss->tempVerts)*oldLen); + ss->tempEdges = CCGSUBSURF_realloc(ss, ss->tempEdges, sizeof(*ss->tempEdges)*ss->lenTempArrays, sizeof(*ss->tempEdges)*oldLen); + } + + if (ss->syncState==eSyncState_Partial) { + f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp); + + for (k=0; ktempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]); + } + for (k=0; ktempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]); + } + + if (f) { + if ( f->numVerts!=numVerts || + memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) || + memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts)) + topologyChanged = 1; + } + + if (!f || topologyChanged) { + fNew = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss->subdivLevels, ss->meshIFC.vertDataSize, ss); + + if (f) { + ss->numGrids += numVerts - f->numVerts; + + *prevp = fNew; + fNew->next = f->next; + + _face_unlinkMarkAndFree(f, ss); + } else { + ss->numGrids += numVerts; + _ehash_insert(ss->fMap, (EHEntry*) fNew); + } + + for (k=0; kflags |= Vert_eEffected; + } + } else { + if (ss->syncState==eSyncState_Vert || ss->syncState==eSyncState_Edge) { + ss->syncState = eSyncState_Face; + } else if (ss->syncState!=eSyncState_Face) { + return eCCGError_InvalidSyncState; + } + + f = _ehash_lookupWithPrev(ss->oldFMap, fHDL, &prevp); + + for (k=0; ktempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]); + } + for (k=0; ktempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]); + + if (ss->allowEdgeCreation && !ss->tempEdges[k]) { + CCGEdge *e = ss->tempEdges[k] = _edge_new((CCGEdgeHDL) -1, ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts], ss->subdivLevels, ss->meshIFC.vertDataSize, ss); + _ehash_insert(ss->eMap, (EHEntry*) e); + e->v0->flags |= Vert_eEffected; + e->v1->flags |= Vert_eEffected; + } + } + + if (f) { + if ( f->numVerts!=numVerts || + memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) || + memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts)) + topologyChanged = 1; + } + + if (!f || topologyChanged) { + f = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss->subdivLevels, ss->meshIFC.vertDataSize, ss); + _ehash_insert(ss->fMap, (EHEntry*) f); + ss->numGrids += numVerts; + + for (k=0; kflags |= Vert_eEffected; + } else { + *prevp = f->next; + _ehash_insert(ss->fMap, (EHEntry*) f); + f->flags = 0; + ss->numGrids += f->numVerts; + + for (j=0; jnumVerts; j++) { + if (FACE_getVerts(f)[j]->flags&Vert_eChanged) { + for (k=0; knumVerts; k++) + FACE_getVerts(f)[k]->flags |= Vert_eEffected; + break; + } + } + } + } + + return eCCGError_None; +} + +static void ccgSubSurf__sync(CCGSubSurf *ss); +CCGError ccgSubSurf_processSync(CCGSubSurf *ss) { + if (ss->syncState==eSyncState_Partial) { + ss->syncState = eSyncState_None; + + ccgSubSurf__sync(ss); + } else if (ss->syncState) { + _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_unlinkMarkAndFree, ss); + _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_unlinkMarkAndFree, ss); + _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss); + CCGSUBSURF_free(ss, ss->tempEdges); + CCGSUBSURF_free(ss, ss->tempVerts); + + ss->lenTempArrays = 0; + + ss->oldFMap = ss->oldEMap = ss->oldVMap = NULL; + ss->tempVerts = NULL; + ss->tempEdges = NULL; + + ss->syncState = eSyncState_None; + + ccgSubSurf__sync(ss); + } else { + return eCCGError_InvalidSyncState; + } + + return eCCGError_None; +} + +CCGError ccgSubSurf_sync2(CCGSubSurf *ss) { + int numVerts = ss->meshIFC.getNumVerts(ss->meshData); + int numEdges = ss->meshIFC.getNumEdges(ss->meshData); + int numFaces = ss->meshIFC.getNumFaces(ss->meshData); + CCGVertHDL *tmpVertHDLs = CCGSUBSURF_alloc(ss, sizeof(*tmpVertHDLs)*20); + void *tempData = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); + int i,j; + + ccgSubSurf_initFullSync(ss); + + for (i=0; imeshIFC.getVert(ss->meshData, i); + + ss->meshIFC.getVertData(ss->meshData, vHDL, tempData); + + ccgSubSurf_syncVert(ss, vHDL, tempData); + } + for (i=0; imeshIFC.getEdge(ss->meshData, i); + CCGVertHDL e_vHDL0 = ss->meshIFC.getEdgeVert0(ss->meshData, eHDL); + CCGVertHDL e_vHDL1 = ss->meshIFC.getEdgeVert1(ss->meshData, eHDL); + + ccgSubSurf_syncEdge(ss, eHDL, e_vHDL0, e_vHDL1); + } + for (i=0; imeshIFC.getFace(ss->meshData, i); + int numVerts = ss->meshIFC.getFaceNumVerts(ss->meshData, fHDL); + + for (j=0; jmeshIFC.getFaceVert(ss->meshData, fHDL, j); + } + + ccgSubSurf_syncFace(ss, fHDL, numVerts, tmpVertHDLs); + } + + ccgSubSurf_processSync(ss); + + CCGSUBSURF_free(ss, tmpVertHDLs); + CCGSUBSURF_free(ss, tempData); + + return eCCGError_None; +} + +static void ccgSubSurf__sync(CCGSubSurf *ss) { + CCGVert **effectedV; + CCGEdge **effectedE; + CCGFace **effectedF; + int numEffectedV, numEffectedE, numEffectedF; + int subdivLevels = ss->subdivLevels; + int vertDataSize = ss->meshIFC.vertDataSize; + int i,ptrIdx,cornerIdx; + int S,x,y; + void *q = ss->q, *r = ss->r; + int curLvl, nextLvl; + int j; + + effectedV = CCGSUBSURF_alloc(ss, sizeof(*effectedV)*ss->vMap->numEntries); + effectedE = CCGSUBSURF_alloc(ss, sizeof(*effectedE)*ss->eMap->numEntries); + effectedF = CCGSUBSURF_alloc(ss, sizeof(*effectedF)*ss->fMap->numEntries); + numEffectedV = numEffectedE = numEffectedF = 0; + for (i=0; ivMap->curSize; i++) { + CCGVert *v = (CCGVert*) ss->vMap->buckets[i]; + for (; v; v = v->next) { + if (v->flags&Vert_eEffected) { + effectedV[numEffectedV++] = v; + + for (j=0; jnumEdges; j++) { + CCGEdge *e = v->edges[j]; + if (!(e->flags&Edge_eEffected)) { + effectedE[numEffectedE++] = e; + e->flags |= Edge_eEffected; + } + } + + for (j=0; jnumFaces; j++) { + CCGFace *f = v->faces[j]; + if (!(f->flags&Face_eEffected)) { + effectedF[numEffectedF++] = f; + f->flags |= Face_eEffected; + } + } + } + } + } + +#define VERT_getCo(v, lvl) _vert_getCo(v, lvl, vertDataSize) +#define EDGE_getCo(e, lvl, x) _edge_getCo(e, lvl, x, vertDataSize) +#define FACE_getIECo(f, lvl, S, x) _face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize) +#define FACE_getIFCo(f, lvl, S, x, y) _face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize) + curLvl = 0; + nextLvl = curLvl+1; + + for (ptrIdx=0; ptrIdxflags = 0; + ss->meshIFC.vertDataZero(ss->meshData, co); + for (i=0; inumVerts; i++) { + ss->meshIFC.vertDataAdd(ss->meshData, co, VERT_getCo(FACE_getVerts(f)[i], curLvl)); + } + ss->meshIFC.vertDataMulN(ss->meshData, co, 1.0f/f->numVerts); + } + for (ptrIdx=0; ptrIdxflags = 0; + if (_edge_isBoundary(e)) { + ss->meshIFC.vertDataCopy(ss->meshData, co, VERT_getCo(e->v0, curLvl)); + ss->meshIFC.vertDataAdd(ss->meshData, co, VERT_getCo(e->v1, curLvl)); + ss->meshIFC.vertDataMulN(ss->meshData, co, 0.5f); + } else { + int numFaces = 0; + ss->meshIFC.vertDataCopy(ss->meshData, co, VERT_getCo(e->v0, curLvl)); + ss->meshIFC.vertDataAdd(ss->meshData, co, VERT_getCo(e->v1, curLvl)); + for (i=0; inumFaces; i++) { + CCGFace *f = e->faces[i]; + ss->meshIFC.vertDataAdd(ss->meshData, co, FACE_getCenterData(f)); + numFaces++; + } + ss->meshIFC.vertDataMulN(ss->meshData, co, 1.0f/(2.0f+numFaces)); + } + } + for (ptrIdx=0; ptrIdxflags = 0; + + if (!v->numEdges) { + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + } else if (_vert_isBoundary(v)) { + int numBoundary = 0; + + ss->meshIFC.vertDataZero(ss->meshData, r); + for (i=0; inumEdges; i++) { + CCGEdge *e = v->edges[i]; + if (_edge_isBoundary(e)) { + ss->meshIFC.vertDataAdd(ss->meshData, r, VERT_getCo(_edge_getOtherVert(e, v), curLvl)); + numBoundary++; + } + } + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.75); + ss->meshIFC.vertDataMulN(ss->meshData, r, 0.25f/numBoundary); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, r); + } else { + int numEdges = 0, numFaces = 0; + + ss->meshIFC.vertDataZero(ss->meshData, q); + for (i=0; inumFaces; i++) { + CCGFace *f = v->faces[i]; + ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getCenterData(f)); + numFaces++; + } + ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/numFaces); + ss->meshIFC.vertDataZero(ss->meshData, r); + for (i=0; inumEdges; i++) { + CCGEdge *e = v->edges[i]; + ss->meshIFC.vertDataAdd(ss->meshData, r, VERT_getCo(_edge_getOtherVert(e, v), curLvl)); + numEdges++; + } + ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0f/numEdges); + + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, numEdges-2.0f); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, q); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, r); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/numEdges); + } + } + + if (ss->useAgeCounts) { + for (i=0; ivertUserAgeOffset]) = ss->currentAge; + } + + for (i=0; iedgeUserAgeOffset]) = ss->currentAge; + } + + for (i=0; ifaceUserAgeOffset]) = ss->currentAge; + } + } + + for (i=0; imeshIFC.vertDataCopy(ss->meshData, EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl)); + ss->meshIFC.vertDataCopy(ss->meshData, EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl)); + } + for (i=0; inumVerts; S++) { + CCGEdge *e = FACE_getEdges(f)[S]; + CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts]; + + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f)); + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f)); + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl)); + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1)); + + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 1, 0), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize)); + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 0, 1), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize)); + } + } + + for (curLvl=1; curLvlnumVerts; S++) { + for (y=0; ymeshIFC.vertDataAvg4(ss->meshData, co, co0, co1, co2, co3); + } + } + } + + /* interior edge midpoints + * o old interior edge points + * o new interior face midpoints + */ + for (S=0; SnumVerts; S++) { + for (x=0; xnumVerts, 1, fx); + void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1); + void *co = FACE_getIECo(f, nextLvl, S, fx); + + ss->meshIFC.vertDataAvg4(ss->meshData, co, co0, co1, co2, co3); + } + + /* interior face interior edge midpoints + * o old interior face points + * o new interior face midpoints + */ + + /* vertical */ + for (x=1; xmeshIFC.vertDataAvg4(ss->meshData, co, co0, co1, co2, co3); + } + } + + /* horizontal */ + for (y=1; ymeshIFC.vertDataAvg4(ss->meshData, co, co0, co1, co2, co3); + } + } + } + } + + /* exterior edge midpoints + * o old exterior edge points + * o new interior face midpoints + */ + for (ptrIdx=0; ptrIdxmeshIFC.vertDataCopy(ss->meshData, co, co0); + ss->meshIFC.vertDataAdd(ss->meshData, co, co1); + ss->meshIFC.vertDataMulN(ss->meshData, co, 0.5); + } + } else { + for (x=0; xmeshIFC.vertDataCopy(ss->meshData, co, co0); + ss->meshIFC.vertDataAdd(ss->meshData, co, co1); + + for (i=0; inumFaces; i++) { + CCGFace *f = e->faces[i]; + ss->meshIFC.vertDataAdd(ss->meshData, co, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize)); + numFaces++; + } + + ss->meshIFC.vertDataMulN(ss->meshData, co, 1.0f/(2.0f+numFaces)); + } + } + } + + /* exterior vertex shift + * o old vertex points (shifting) + * o old exterior edge points + * o new interior face midpoints + */ + for (ptrIdx=0; ptrIdxnumEdges) { + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + } else if (_vert_isBoundary(v)) { + int numBoundary = 0; + + ss->meshIFC.vertDataZero(ss->meshData, r); + for (i=0; inumEdges; i++) { + CCGEdge *e = v->edges[i]; + if (_edge_isBoundary(e)) { + ss->meshIFC.vertDataAdd(ss->meshData, r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); + numBoundary++; + } + } + + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.75); + ss->meshIFC.vertDataMulN(ss->meshData, r, 0.25f/numBoundary); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, r); + } else { + int cornerIdx = (1 + (1<<(curLvl))) - 2; + int numEdges = 0, numFaces = 0; + + ss->meshIFC.vertDataZero(ss->meshData, q); + for (i=0; inumFaces; i++) { + CCGFace *f = v->faces[i]; + ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx)); + numFaces++; + } + ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/numFaces); + ss->meshIFC.vertDataZero(ss->meshData, r); + for (i=0; inumEdges; i++) { + CCGEdge *e = v->edges[i]; + ss->meshIFC.vertDataAdd(ss->meshData, r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize)); + numEdges++; + } + ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0f/numEdges); + + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, numEdges-2.0f); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, q); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, r); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/numEdges); + } + } + + /* exterior edge interior shift + * o old exterior edge midpoints (shifting) + * o old exterior edge midpoints + * o new interior face midpoints + */ + for (ptrIdx=0; ptrIdxmeshIFC.vertDataCopy(ss->meshData, r, EDGE_getCo(e, curLvl, x-1)); + ss->meshIFC.vertDataAdd(ss->meshData, r, EDGE_getCo(e, curLvl, x+1)); + ss->meshIFC.vertDataMulN(ss->meshData, r, 0.5); + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.75); + ss->meshIFC.vertDataMulN(ss->meshData, r, 0.25); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, r); + } + } else { + for (x=1; xmeshIFC.vertDataZero(ss->meshData, q); + ss->meshIFC.vertDataZero(ss->meshData, r); + ss->meshIFC.vertDataAdd(ss->meshData, r, EDGE_getCo(e, curLvl, x-1)); + ss->meshIFC.vertDataAdd(ss->meshData, r, EDGE_getCo(e, curLvl, x+1)); + for (i=0; inumFaces; i++) { + CCGFace *f = e->faces[i]; + ss->meshIFC.vertDataAdd(ss->meshData, q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize)); + ss->meshIFC.vertDataAdd(ss->meshData, q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize)); + + ss->meshIFC.vertDataAdd(ss->meshData, r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize)); + numFaces++; + } + ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0/(numFaces*2.0f)); + ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0/(2.0f + numFaces)); + + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, (float) numFaces); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, q); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, r); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/(2+numFaces)); + } + } + } + + for (ptrIdx=0; ptrIdxmeshIFC.vertDataZero(ss->meshData, q); + for (S=0; SnumVerts; S++) { + ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getIFCo(f, nextLvl, S, 1, 1)); + } + ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/f->numVerts); + ss->meshIFC.vertDataZero(ss->meshData, r); + for (S=0; SnumVerts; S++) { + ss->meshIFC.vertDataAdd(ss->meshData, r, FACE_getIECo(f, curLvl, S, 1)); + } + ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0f/f->numVerts); + + ss->meshIFC.vertDataMulN(ss->meshData, FACE_getCenterData(f), f->numVerts-2.0f); + ss->meshIFC.vertDataAdd(ss->meshData, FACE_getCenterData(f), q); + ss->meshIFC.vertDataAdd(ss->meshData, FACE_getCenterData(f), r); + ss->meshIFC.vertDataMulN(ss->meshData, FACE_getCenterData(f), 1.0f/f->numVerts); + + for (S=0; SnumVerts; S++) { + /* interior face shift + * o old interior face point (shifting) + * o new interior edge midpoints + * o new interior face midpoints + */ + for (x=1; xmeshIFC.vertDataAvg4(ss->meshData, q, FACE_getIFCo(f, nextLvl, S, fx-1, fy-1), + FACE_getIFCo(f, nextLvl, S, fx+1, fy-1), + FACE_getIFCo(f, nextLvl, S, fx+1, fy+1), + FACE_getIFCo(f, nextLvl, S, fx-1, fy+1)); + + ss->meshIFC.vertDataAvg4(ss->meshData, r, FACE_getIFCo(f, nextLvl, S, fx-1, fy+0), + FACE_getIFCo(f, nextLvl, S, fx+1, fy+0), + FACE_getIFCo(f, nextLvl, S, fx+0, fy-1), + FACE_getIFCo(f, nextLvl, S, fx+0, fy+1)); + + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + ss->meshIFC.vertDataSub(ss->meshData, nCo, q); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.25f); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, r); + } + } + + /* interior edge interior shift + * o old interior edge point (shifting) + * o new interior edge midpoints + * o new interior face midpoints + */ + for (x=1; xmeshIFC.vertDataAvg4(ss->meshData, q, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx-1), + FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1), + FACE_getIFCo(f, nextLvl, S, fx+1, +1), + FACE_getIFCo(f, nextLvl, S, fx-1, +1)); + + ss->meshIFC.vertDataAvg4(ss->meshData, r, FACE_getIECo(f, nextLvl, S, fx-1), + FACE_getIECo(f, nextLvl, S, fx+1), + FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx), + FACE_getIFCo(f, nextLvl, S, fx, 1)); + + ss->meshIFC.vertDataCopy(ss->meshData, nCo, co); + ss->meshIFC.vertDataSub(ss->meshData, nCo, q); + ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.25f); + ss->meshIFC.vertDataAdd(ss->meshData, nCo, r); + } + } + } + + + + /* copy down */ + edgeSize = 1 + (1<<(nextLvl)); + gridSize = 1 + (1<<((nextLvl)-1)); + cornerIdx = gridSize-1; + for (i=0; imeshIFC.vertDataCopy(ss->meshData, EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl)); + ss->meshIFC.vertDataCopy(ss->meshData, EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl)); + } + for (i=0; inumVerts; S++) { + CCGEdge *e = FACE_getEdges(f)[S]; + CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts]; + + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f)); + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f)); + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl)); + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx)); + for (x=1; xmeshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, x, 0), co); + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 0, x), co); + } + for (x=0; xmeshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize)); + ss->meshIFC.vertDataCopy(ss->meshData, FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize)); + } + } + } + } +#undef VERT_getCo +#undef EDGE_getCo +#undef FACE_getIECo +#undef FACE_getIFCo + + CCGSUBSURF_free(ss, effectedF); + CCGSUBSURF_free(ss, effectedE); + CCGSUBSURF_free(ss, effectedV); +} + +/*** External API accessor functions ***/ + +int ccgSubSurf_getNumVerts(CCGSubSurf *ss) { + return ss->vMap->numEntries; +} +int ccgSubSurf_getNumEdges(CCGSubSurf *ss) { + return ss->eMap->numEntries; +} +int ccgSubSurf_getNumFaces(CCGSubSurf *ss) { + return ss->fMap->numEntries; +} + +int ccgSubSurf_getSubdivisionLevels(CCGSubSurf *ss) { + return ss->subdivLevels; +} +int ccgSubSurf_getEdgeSize(CCGSubSurf *ss) { + return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels); +} +int ccgSubSurf_getEdgeLevelSize(CCGSubSurf *ss, int level) { + if (level<1 || level>ss->subdivLevels) { + return -1; + } else { + return 1 + (1<subdivLevels); +} +int ccgSubSurf_getGridLevelSize(CCGSubSurf *ss, int level) { + if (level<1 || level>ss->subdivLevels) { + return -1; + } else { + return 1 + (1<<(level-1)); + } +} + +/* Vert accessors */ + +CCGVertHDL ccgSubSurf_getVertVertHandle(CCGSubSurf *ss, CCGVert *v) { + return v->vHDL; +} +int ccgSubSurf_getVertAge(CCGSubSurf *ss, CCGVert *v) { + if (ss->useAgeCounts) { + byte *userData = ccgSubSurf_getVertUserData(ss, v); + return ss->currentAge - *((int*) &userData[ss->vertUserAgeOffset]); + } else { + return 0; + } +} +void *ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v) { + return VERT_getLevelData(v) + ss->meshIFC.vertDataSize*(ss->subdivLevels+1); +} +int ccgSubSurf_getVertNumFaces(CCGSubSurf *ss, CCGVert *v) { + return v->numFaces; +} +CCGFace *ccgSubSurf_getVertFace(CCGSubSurf *ss, CCGVert *v, int index) { + if (index<0 || index>=v->numFaces) { + return NULL; + } else { + return v->faces[index]; + } +} +int ccgSubSurf_getVertNumEdges(CCGSubSurf *ss, CCGVert *v) { + return v->numEdges; +} +CCGEdge *ccgSubSurf_getVertEdge(CCGSubSurf *ss, CCGVert *v, int index) { + if (index<0 || index>=v->numEdges) { + return NULL; + } else { + return v->edges[index]; + } +} +void *ccgSubSurf_getVertData(CCGSubSurf *ss, CCGVert *v) { + return ccgSubSurf_getVertLevelData(ss, v, ss->subdivLevels); +} +void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level) { + if (level<0 || level>ss->subdivLevels) { + return NULL; + } else { + return _vert_getCo(v, level, ss->meshIFC.vertDataSize); + } +} + +/* Edge accessors */ + +CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle(CCGSubSurf *ss, CCGEdge *e) { + return e->eHDL; +} +int ccgSubSurf_getEdgeAge(CCGSubSurf *ss, CCGEdge *e) { + if (ss->useAgeCounts) { + byte *userData = ccgSubSurf_getEdgeUserData(ss, e); + return ss->currentAge - *((int*) &userData[ss->edgeUserAgeOffset]); + } else { + return 0; + } +} +void *ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e) { + return EDGE_getLevelData(e) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1); +} +int ccgSubSurf_getEdgeNumFaces(CCGSubSurf *ss, CCGEdge *e) { + return e->numFaces; +} +CCGFace *ccgSubSurf_getEdgeFace(CCGSubSurf *ss, CCGEdge *e, int index) { + if (index<0 || index>=e->numFaces) { + return NULL; + } else { + return e->faces[index]; + } +} +CCGVert *ccgSubSurf_getEdgeVert0(CCGSubSurf *ss, CCGEdge *e) { + return e->v0; +} +CCGVert *ccgSubSurf_getEdgeVert1(CCGSubSurf *ss, CCGEdge *e) { + return e->v1; +} +void *ccgSubSurf_getEdgeDataArray(CCGSubSurf *ss, CCGEdge *e) { + return ccgSubSurf_getEdgeData(ss, e, 0); +} +void *ccgSubSurf_getEdgeData(CCGSubSurf *ss, CCGEdge *e, int x) { + return ccgSubSurf_getEdgeLevelData(ss, e, x, ss->subdivLevels); +} +void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level) { + if (level<0 || level>ss->subdivLevels) { + return NULL; + } else { + return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize); + } +} + +/* Face accessors */ + +CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *ss, CCGFace *f) { + return f->fHDL; +} +int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) { + if (ss->useAgeCounts) { + byte *userData = ccgSubSurf_getFaceUserData(ss, f); + return ss->currentAge - *((int*) &userData[ss->faceUserAgeOffset]); + } else { + return 0; + } +} +void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) { + int maxGridSize = 1 + (1<<(ss->subdivLevels-1)); + return FACE_getCenterData(f) + ss->meshIFC.vertDataSize *(1 + f->numVerts*maxGridSize + f->numVerts*maxGridSize*maxGridSize); +} +int ccgSubSurf_getFaceNumVerts(CCGSubSurf *ss, CCGFace *f) { + return f->numVerts; +} +CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *ss, CCGFace *f, int index) { + if (index<0 || index>=f->numVerts) { + return NULL; + } else { + return FACE_getVerts(f)[index]; + } +} +CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *ss, CCGFace *f, int index) { + if (index<0 || index>=f->numVerts) { + return NULL; + } else { + return FACE_getEdges(f)[index]; + } +} +void *ccgSubSurf_getFaceCenterData(CCGSubSurf *ss, CCGFace *f) { + return FACE_getCenterData(f); +} +void *ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) { + return ccgSubSurf_getFaceGridEdgeData(ss, f, gridIndex, 0); +} +void *ccgSubSurf_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x) { + return _face_getIECo(f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize); +} +void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) { + return ccgSubSurf_getFaceGridData(ss, f, gridIndex, 0, 0); +} +void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y) { + return _face_getIFCo(f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize); +} + +/*** External API iterator functions ***/ + +typedef struct _CCGVertIterator CCGVertIterator; +typedef struct _CCGEdgeIterator CCGEdgeIterator; +typedef struct _CCGFaceIterator CCGFaceIterator; + +CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss) { + return (CCGVertIterator*) _ehashIterator_new(ss->vMap); +} +CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss) { + return (CCGEdgeIterator*) _ehashIterator_new(ss->eMap); +} +CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss) { + return (CCGFaceIterator*) _ehashIterator_new(ss->fMap); +} + +CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi) { + return (CCGVert*) _ehashIterator_getCurrent((EHashIterator*) vi); +} +int ccgVertIterator_isStopped(CCGVertIterator *vi) { + return _ehashIterator_isStopped((EHashIterator*) vi); +} +void ccgVertIterator_next(CCGVertIterator *vi) { + _ehashIterator_next((EHashIterator*) vi); +} +void ccgVertIterator_free(CCGVertIterator *vi) { + _ehashIterator_free((EHashIterator*) vi); +} + +CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi) { + return (CCGEdge*) _ehashIterator_getCurrent((EHashIterator*) vi); +} +int ccgEdgeIterator_isStopped(CCGEdgeIterator *vi) { + return _ehashIterator_isStopped((EHashIterator*) vi); +} +void ccgEdgeIterator_next(CCGEdgeIterator *vi) { + _ehashIterator_next((EHashIterator*) vi); +} +void ccgEdgeIterator_free(CCGEdgeIterator *vi) { + _ehashIterator_free((EHashIterator*) vi); +} + +CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi) { + return (CCGFace*) _ehashIterator_getCurrent((EHashIterator*) vi); +} +int ccgFaceIterator_isStopped(CCGFaceIterator *vi) { + return _ehashIterator_isStopped((EHashIterator*) vi); +} +void ccgFaceIterator_next(CCGFaceIterator *vi) { + _ehashIterator_next((EHashIterator*) vi); +} +void ccgFaceIterator_free(CCGFaceIterator *vi) { + _ehashIterator_free((EHashIterator*) vi); +} + +/*** Extern API final vert/edge/face interface ***/ + +int ccgSubSurf_getNumFinalVerts(CCGSubSurf *ss) { + int edgeSize = 1 + (1<subdivLevels); + int gridSize = 1 + (1<<(ss->subdivLevels-1)); + int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2))); + return numFinalVerts; +} +int ccgSubSurf_getNumFinalEdges(CCGSubSurf *ss) { + int edgeSize = 1 + (1<subdivLevels); + int gridSize = 1 + (1<<(ss->subdivLevels-1)); + int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1))); + return numFinalEdges; +} +int ccgSubSurf_getNumFinalFaces(CCGSubSurf *ss) { + int gridSize = 1 + (1<<(ss->subdivLevels-1)); + int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1)); + return numFinalFaces; +} + +#endif \ No newline at end of file diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h new file mode 100644 index 00000000000..e1f00ea1048 --- /dev/null +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -0,0 +1,163 @@ +/* $Id$ */ + +typedef void* CCGMeshHDL; +typedef void* CCGVertHDL; +typedef void* CCGEdgeHDL; +typedef void* CCGFaceHDL; + +typedef struct _CCGMeshIFC CCGMeshIFC; +struct _CCGMeshIFC { + int vertUserSize, edgeUserSize, faceUserSize; + + int vertDataSize; + void (*vertDataZero) (CCGMeshHDL m, void *t); + int (*vertDataEqual) (CCGMeshHDL m, void *a, void *b); + void (*vertDataCopy) (CCGMeshHDL m, void *t, void *a); + void (*vertDataAdd) (CCGMeshHDL m, void *ta, void *b); + void (*vertDataSub) (CCGMeshHDL m, void *ta, void *b); + void (*vertDataMulN) (CCGMeshHDL m, void *ta, double n); + void (*vertDataAvg4) (CCGMeshHDL m, void *t, void *a, void *b, void *c, void *d); + + int (*getNumVerts) (CCGMeshHDL m); + int (*getNumEdges) (CCGMeshHDL m); + int (*getNumFaces) (CCGMeshHDL m); + CCGVertHDL (*getVert) (CCGMeshHDL m, int idx); + CCGEdgeHDL (*getEdge) (CCGMeshHDL m, int idx); + CCGFaceHDL (*getFace) (CCGMeshHDL m, int idx); + + void (*getVertData) (CCGMeshHDL m, CCGVertHDL v, void *data_r); + + CCGVertHDL (*getEdgeVert0) (CCGMeshHDL m, CCGEdgeHDL e); + CCGVertHDL (*getEdgeVert1) (CCGMeshHDL m, CCGEdgeHDL e); + + int (*getFaceNumVerts) (CCGMeshHDL m, CCGFaceHDL f); + CCGVertHDL (*getFaceVert) (CCGMeshHDL m, CCGFaceHDL f, int idx); +}; + +/***/ + +typedef void* CCGAllocatorHDL; + +typedef struct _CCGAllocatorIFC CCGAllocatorIFC; +struct _CCGAllocatorIFC { + void* (*alloc) (CCGAllocatorHDL a, int numBytes); + void* (*realloc) (CCGAllocatorHDL a, void *ptr, int newSize, int oldSize); + void (*free) (CCGAllocatorHDL a, void *ptr); + void (*release) (CCGAllocatorHDL a); +}; + +/***/ + +typedef enum { + eCCGError_None = 0, + + eCCGError_InvalidSyncState, + eCCGError_InvalidValue, +} CCGError; + +/***/ + +typedef struct _CCGSubSurf CCGSubSurf; + +CCGSubSurf* ccgSubSurf_new (CCGMeshIFC *ifc, CCGMeshHDL meshData, int subdivisionLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator); +void ccgSubSurf_free (CCGSubSurf *ss); + +CCGError ccgSubSurf_sync (CCGSubSurf *ss); + +CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss); +CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss); + +CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData); +CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1); +CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs); + +CCGError ccgSubSurf_syncVertDel (CCGSubSurf *ss, CCGVertHDL vHDL); +CCGError ccgSubSurf_syncEdgeDel (CCGSubSurf *ss, CCGEdgeHDL eHDL); +CCGError ccgSubSurf_syncFaceDel (CCGSubSurf *ss, CCGFaceHDL fHDL); + +CCGError ccgSubSurf_processSync (CCGSubSurf *ss); + +CCGError ccgSubSurf_setSubdivisionLevels (CCGSubSurf *ss, int subdivisionLevels); +CCGError ccgSubSurf_setAllowEdgeCreation (CCGSubSurf *ss, int allowEdgeCreation); +CCGError ccgSubSurf_setUseAgeCounts (CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset); + +/***/ + +typedef struct _CCGVert CCGVert; +typedef struct _CCGEdge CCGEdge; +typedef struct _CCGFace CCGFace; + +int ccgSubSurf_getNumVerts (CCGSubSurf *ss); +int ccgSubSurf_getNumEdges (CCGSubSurf *ss); +int ccgSubSurf_getNumFaces (CCGSubSurf *ss); + +int ccgSubSurf_getSubdivisionLevels (CCGSubSurf *ss); +int ccgSubSurf_getEdgeSize (CCGSubSurf *ss); +int ccgSubSurf_getEdgeLevelSize (CCGSubSurf *ss, int level); +int ccgSubSurf_getGridSize (CCGSubSurf *ss); +int ccgSubSurf_getGridLevelSize (CCGSubSurf *ss, int level); + +CCGVertHDL ccgSubSurf_getVertVertHandle (CCGSubSurf *ss, CCGVert *v); +int ccgSubSurf_getVertNumFaces (CCGSubSurf *ss, CCGVert *v); +CCGFace* ccgSubSurf_getVertFace (CCGSubSurf *ss, CCGVert *v, int index); +int ccgSubSurf_getVertNumEdges (CCGSubSurf *ss, CCGVert *v); +CCGEdge* ccgSubSurf_getVertEdge (CCGSubSurf *ss, CCGVert *v, int index); + +int ccgSubSurf_getVertAge (CCGSubSurf *ss, CCGVert *v); +void* ccgSubSurf_getVertUserData (CCGSubSurf *ss, CCGVert *v); +void* ccgSubSurf_getVertData (CCGSubSurf *ss, CCGVert *v); +void* ccgSubSurf_getVertLevelData (CCGSubSurf *ss, CCGVert *v, int level); + +CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle (CCGSubSurf *ss, CCGEdge *e); +int ccgSubSurf_getEdgeNumFaces (CCGSubSurf *ss, CCGEdge *e); +CCGFace* ccgSubSurf_getEdgeFace (CCGSubSurf *ss, CCGEdge *e, int index); +CCGVert* ccgSubSurf_getEdgeVert0 (CCGSubSurf *ss, CCGEdge *e); +CCGVert* ccgSubSurf_getEdgeVert1 (CCGSubSurf *ss, CCGEdge *e); + +int ccgSubSurf_getEdgeAge (CCGSubSurf *ss, CCGEdge *e); +void* ccgSubSurf_getEdgeUserData (CCGSubSurf *ss, CCGEdge *e); +void* ccgSubSurf_getEdgeDataArray (CCGSubSurf *ss, CCGEdge *e); +void* ccgSubSurf_getEdgeData (CCGSubSurf *ss, CCGEdge *e, int x); +void* ccgSubSurf_getEdgeLevelData (CCGSubSurf *ss, CCGEdge *e, int x, int level); + +CCGFaceHDL ccgSubSurf_getFaceFaceHandle (CCGSubSurf *ss, CCGFace *f); +int ccgSubSurf_getFaceNumVerts (CCGSubSurf *ss, CCGFace *f); +CCGVert* ccgSubSurf_getFaceVert (CCGSubSurf *ss, CCGFace *f, int index); +CCGEdge* ccgSubSurf_getFaceEdge (CCGSubSurf *ss, CCGFace *f, int index); + +int ccgSubSurf_getFaceAge (CCGSubSurf *ss, CCGFace *f); +void* ccgSubSurf_getFaceUserData (CCGSubSurf *ss, CCGFace *f); +void* ccgSubSurf_getFaceCenterData (CCGSubSurf *ss, CCGFace *f); +void* ccgSubSurf_getFaceGridEdgeDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex); +void* ccgSubSurf_getFaceGridEdgeData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x); +void* ccgSubSurf_getFaceGridDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex); +void* ccgSubSurf_getFaceGridData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y); + +int ccgSubSurf_getNumFinalVerts (CCGSubSurf *ss); +int ccgSubSurf_getNumFinalEdges (CCGSubSurf *ss); +int ccgSubSurf_getNumFinalFaces (CCGSubSurf *ss); + +/***/ + +typedef struct _CCGVertIterator CCGVertIterator; +typedef struct _CCGEdgeIterator CCGEdgeIterator; +typedef struct _CCGFaceIterator CCGFaceIterator; + +CCGVertIterator* ccgSubSurf_getVertIterator (CCGSubSurf *ss); +CCGEdgeIterator* ccgSubSurf_getEdgeIterator (CCGSubSurf *ss); +CCGFaceIterator* ccgSubSurf_getFaceIterator (CCGSubSurf *ss); + +CCGVert* ccgVertIterator_getCurrent (CCGVertIterator *vi); +int ccgVertIterator_isStopped (CCGVertIterator *vi); +void ccgVertIterator_next (CCGVertIterator *vi); +void ccgVertIterator_free (CCGVertIterator *vi); + +CCGEdge* ccgEdgeIterator_getCurrent (CCGEdgeIterator *ei); +int ccgEdgeIterator_isStopped (CCGEdgeIterator *ei); +void ccgEdgeIterator_next (CCGEdgeIterator *ei); +void ccgEdgeIterator_free (CCGEdgeIterator *ei); + +CCGFace* ccgFaceIterator_getCurrent (CCGFaceIterator *fi); +int ccgFaceIterator_isStopped (CCGFaceIterator *fi); +void ccgFaceIterator_next (CCGFaceIterator *fi); +void ccgFaceIterator_free (CCGFaceIterator *fi); diff --git a/source/blender/blenkernel/intern/subsurf.c b/source/blender/blenkernel/intern/subsurf.c index 6e29f1b4add..1619d6e7673 100644 --- a/source/blender/blenkernel/intern/subsurf.c +++ b/source/blender/blenkernel/intern/subsurf.c @@ -39,10 +39,6 @@ #include #endif -#ifdef WIN32 -#include "BLI_winstuff.h" -#endif - #include #include #include @@ -1096,6 +1092,11 @@ static DispListMesh *subsurf_subdivide_to_displistmesh(HyperMesh *hme, short sub DispListMesh *subsurf_make_dispListMesh_from_editmesh(EditMesh *em, int subdivLevels, int flags, short type) { if (subdivLevels<1) { return displistmesh_from_editmesh(em); +#ifdef USE_CCGSUBSURFLIB + } else if (type==ME_CCG_SUBSURF) { + extern DispListMesh *subsurf_ccg_make_dispListMesh_from_editmesh(EditMesh *em, int subdivLevels, int flags); + return subsurf_ccg_make_dispListMesh_from_editmesh(em, subdivLevels, flags); +#endif } else { HyperMesh *hme= hypermesh_from_editmesh(em, subdivLevels); @@ -1106,6 +1107,11 @@ DispListMesh *subsurf_make_dispListMesh_from_editmesh(EditMesh *em, int subdivLe DispListMesh *subsurf_make_dispListMesh_from_mesh(Mesh *me, float *extverts, int subdivLevels, int flags) { if (subdivLevels<1) { return displistmesh_from_mesh(me, extverts); +#ifdef USE_CCGSUBSURFLIB + } else if (me->subsurftype==ME_CCG_SUBSURF) { + extern DispListMesh *subsurf_ccg_make_dispListMesh_from_mesh(Mesh *me, float *extverts, int subdivLevels, int flags); + return subsurf_ccg_make_dispListMesh_from_mesh(me, extverts, subdivLevels, flags); +#endif } else { HyperMesh *hme= hypermesh_from_mesh(me, extverts, subdivLevels); diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index f9cb375572b..79bf76618a6 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -120,6 +120,9 @@ typedef struct Mesh { #define ME_CC_SUBSURF 0 #define ME_SIMPLE_SUBSURF 1 +#ifdef USE_CCGSUBSURFLIB +#define ME_CCG_SUBSURF 2 +#endif #define TF_DYNAMIC 1 /* #define TF_INVISIBLE 2 */ diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index c6f095c7a6d..7829aa467bd 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -40,7 +40,6 @@ #endif #ifdef WIN32 -#include "BLI_winstuff.h" #ifndef snprintf #define snprintf _snprintf #endif @@ -653,7 +652,11 @@ static void editing_panel_mesh_type(Object *ob, Mesh *me) uiBlock *block; float val; /* Hope to support more than two subsurf algorithms */ +#ifdef USE_CCGSUBSURFLIB + char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|CCGSubSurf%x2|Simple Subdiv.%x1"; +#else char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1"; +#endif block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_type", UI_EMBOSS, UI_HELV, curarea->win); if( uiNewPanel(curarea, block, "Mesh", "Editing", 320, 0, 318, 204)==0) return; -- cgit v1.2.3