Blender V2.61 - r43446
|
00001 00006 #include <stdlib.h> 00007 #include <string.h> 00008 #include <math.h> 00009 00010 #include "CCGSubSurf.h" 00011 00012 #include "MEM_guardedalloc.h" 00013 #include "BLO_sys_types.h" // for intptr_t support 00014 00015 #ifdef _MSC_VER 00016 #define CCG_INLINE __inline 00017 #else 00018 #define CCG_INLINE inline 00019 #endif 00020 00021 /* copied from BKE_utildefines.h ugh */ 00022 #ifdef __GNUC__ 00023 # define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) 00024 #else 00025 # define UNUSED(x) x 00026 #endif 00027 00028 /* used for normalize_v3 in BLI_math_vector 00029 * float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */ 00030 #define EPSILON (1.0e-35f) 00031 00032 /***/ 00033 00034 typedef unsigned char byte; 00035 00036 /***/ 00037 00038 static int kHashSizes[] = { 00039 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 00040 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 00041 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 268435459 00042 }; 00043 00044 typedef struct _EHEntry EHEntry; 00045 struct _EHEntry { 00046 EHEntry *next; 00047 void *key; 00048 }; 00049 typedef struct _EHash { 00050 EHEntry **buckets; 00051 int numEntries, curSize, curSizeIdx; 00052 00053 CCGAllocatorIFC allocatorIFC; 00054 CCGAllocatorHDL allocator; 00055 } EHash; 00056 00057 #define EHASH_alloc(eh, nb) ((eh)->allocatorIFC.alloc((eh)->allocator, nb)) 00058 #define EHASH_free(eh, ptr) ((eh)->allocatorIFC.free((eh)->allocator, ptr)) 00059 00060 #define EHASH_hash(eh, item) (((uintptr_t) (item))%((unsigned int) (eh)->curSize)) 00061 00062 static EHash *_ehash_new(int estimatedNumEntries, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) { 00063 EHash *eh = allocatorIFC->alloc(allocator, sizeof(*eh)); 00064 eh->allocatorIFC = *allocatorIFC; 00065 eh->allocator = allocator; 00066 eh->numEntries = 0; 00067 eh->curSizeIdx = 0; 00068 while (kHashSizes[eh->curSizeIdx]<estimatedNumEntries) 00069 eh->curSizeIdx++; 00070 eh->curSize = kHashSizes[eh->curSizeIdx]; 00071 eh->buckets = EHASH_alloc(eh, eh->curSize*sizeof(*eh->buckets)); 00072 memset(eh->buckets, 0, eh->curSize*sizeof(*eh->buckets)); 00073 00074 return eh; 00075 } 00076 typedef void (*EHEntryFreeFP)(EHEntry *, void *); 00077 static void _ehash_free(EHash *eh, EHEntryFreeFP freeEntry, void *userData) { 00078 int numBuckets = eh->curSize; 00079 00080 while (numBuckets--) { 00081 EHEntry *entry = eh->buckets[numBuckets]; 00082 00083 while (entry) { 00084 EHEntry *next = entry->next; 00085 00086 freeEntry(entry, userData); 00087 00088 entry = next; 00089 } 00090 } 00091 00092 EHASH_free(eh, eh->buckets); 00093 EHASH_free(eh, eh); 00094 } 00095 00096 static void _ehash_insert(EHash *eh, EHEntry *entry) { 00097 int numBuckets = eh->curSize; 00098 int hash = EHASH_hash(eh, entry->key); 00099 entry->next = eh->buckets[hash]; 00100 eh->buckets[hash] = entry; 00101 eh->numEntries++; 00102 00103 if (eh->numEntries > (numBuckets*3)) { 00104 EHEntry **oldBuckets = eh->buckets; 00105 eh->curSize = kHashSizes[++eh->curSizeIdx]; 00106 00107 eh->buckets = EHASH_alloc(eh, eh->curSize*sizeof(*eh->buckets)); 00108 memset(eh->buckets, 0, eh->curSize*sizeof(*eh->buckets)); 00109 00110 while (numBuckets--) { 00111 for (entry = oldBuckets[numBuckets]; entry;) { 00112 EHEntry *next = entry->next; 00113 00114 hash = EHASH_hash(eh, entry->key); 00115 entry->next = eh->buckets[hash]; 00116 eh->buckets[hash] = entry; 00117 00118 entry = next; 00119 } 00120 } 00121 00122 EHASH_free(eh, oldBuckets); 00123 } 00124 } 00125 00126 static void *_ehash_lookupWithPrev(EHash *eh, void *key, void ***prevp_r) { 00127 int hash = EHASH_hash(eh, key); 00128 void **prevp = (void**) &eh->buckets[hash]; 00129 EHEntry *entry; 00130 00131 for (; (entry = *prevp); prevp = (void**) &entry->next) { 00132 if (entry->key==key) { 00133 *prevp_r = (void**) prevp; 00134 return entry; 00135 } 00136 } 00137 00138 return NULL; 00139 } 00140 00141 static void *_ehash_lookup(EHash *eh, void *key) { 00142 int hash = EHASH_hash(eh, key); 00143 EHEntry *entry; 00144 00145 for (entry = eh->buckets[hash]; entry; entry = entry->next) 00146 if (entry->key==key) 00147 break; 00148 00149 return entry; 00150 } 00151 00152 00153 00154 typedef struct _EHashIterator { 00155 EHash *eh; 00156 int curBucket; 00157 EHEntry *curEntry; 00158 } EHashIterator; 00159 00160 static EHashIterator *_ehashIterator_new(EHash *eh) { 00161 EHashIterator *ehi = EHASH_alloc(eh, sizeof(*ehi)); 00162 ehi->eh = eh; 00163 ehi->curEntry = NULL; 00164 ehi->curBucket = -1; 00165 while (!ehi->curEntry) { 00166 ehi->curBucket++; 00167 if (ehi->curBucket==ehi->eh->curSize) 00168 break; 00169 ehi->curEntry = ehi->eh->buckets[ehi->curBucket]; 00170 } 00171 return ehi; 00172 } 00173 static void _ehashIterator_free(EHashIterator *ehi) { 00174 EHASH_free(ehi->eh, ehi); 00175 } 00176 00177 static void *_ehashIterator_getCurrent(EHashIterator *ehi) { 00178 return ehi->curEntry; 00179 } 00180 00181 static void _ehashIterator_next(EHashIterator *ehi) { 00182 if (ehi->curEntry) { 00183 ehi->curEntry = ehi->curEntry->next; 00184 while (!ehi->curEntry) { 00185 ehi->curBucket++; 00186 if (ehi->curBucket==ehi->eh->curSize) 00187 break; 00188 ehi->curEntry = ehi->eh->buckets[ehi->curBucket]; 00189 } 00190 } 00191 } 00192 static int _ehashIterator_isStopped(EHashIterator *ehi) { 00193 return !ehi->curEntry; 00194 } 00195 00196 /***/ 00197 00198 static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes) { 00199 return malloc(numBytes); 00200 } 00201 static void *_stdAllocator_realloc(CCGAllocatorHDL UNUSED(a), void *ptr, int newSize, int UNUSED(oldSize)) { 00202 return realloc(ptr, newSize); 00203 } 00204 static void _stdAllocator_free(CCGAllocatorHDL UNUSED(a), void *ptr) { 00205 free(ptr); 00206 } 00207 00208 static CCGAllocatorIFC *_getStandardAllocatorIFC(void) { 00209 static CCGAllocatorIFC ifc; 00210 00211 ifc.alloc = _stdAllocator_alloc; 00212 ifc.realloc = _stdAllocator_realloc; 00213 ifc.free = _stdAllocator_free; 00214 ifc.release = NULL; 00215 00216 return &ifc; 00217 } 00218 00219 /***/ 00220 00221 static int VertDataEqual(const float *a, const float *b) { 00222 return a[0]==b[0] && a[1]==b[1] && a[2]==b[2]; 00223 } 00224 #define VertDataZero(av) { float *_a = (float*) av; _a[0] = _a[1] = _a[2] = 0.0f; } 00225 #define VertDataCopy(av, bv) { float *_a = (float*) av, *_b = (float*) bv; _a[0] =_b[0]; _a[1] =_b[1]; _a[2] =_b[2]; } 00226 #define VertDataAdd(av, bv) { float *_a = (float*) av, *_b = (float*) bv; _a[0]+=_b[0]; _a[1]+=_b[1]; _a[2]+=_b[2]; } 00227 #define VertDataSub(av, bv) { float *_a = (float*) av, *_b = (float*) bv; _a[0]-=_b[0]; _a[1]-=_b[1]; _a[2]-=_b[2]; } 00228 #define VertDataMulN(av, n) { float *_a = (float*) av; _a[0]*=n; _a[1]*=n; _a[2]*=n; } 00229 #define VertDataAvg4(tv, av, bv, cv, dv) \ 00230 { \ 00231 float *_t = (float*) tv, *_a = (float*) av, *_b = (float*) bv, *_c = (float*) cv, *_d = (float*) dv; \ 00232 _t[0] = (_a[0]+_b[0]+_c[0]+_d[0])*.25f; \ 00233 _t[1] = (_a[1]+_b[1]+_c[1]+_d[1])*.25f; \ 00234 _t[2] = (_a[2]+_b[2]+_c[2]+_d[2])*.25f; \ 00235 } 00236 #define NormZero(av) { float *_a = (float*) av; _a[0] = _a[1] = _a[2] = 0.0f; } 00237 #define NormCopy(av, bv) { float *_a = (float*) av, *_b = (float*) bv; _a[0] =_b[0]; _a[1] =_b[1]; _a[2] =_b[2]; } 00238 #define NormAdd(av, bv) { float *_a = (float*) av, *_b = (float*) bv; _a[0]+=_b[0]; _a[1]+=_b[1]; _a[2]+=_b[2]; } 00239 00240 00241 static int _edge_isBoundary(const CCGEdge *e); 00242 00243 /***/ 00244 00245 enum { 00246 Vert_eEffected= (1<<0), 00247 Vert_eChanged= (1<<1), 00248 Vert_eSeam= (1<<2), 00249 } /*VertFlags*/; 00250 enum { 00251 Edge_eEffected= (1<<0), 00252 } /*CCGEdgeFlags*/; 00253 enum { 00254 Face_eEffected= (1<<0), 00255 } /*FaceFlags*/; 00256 00257 struct _CCGVert { 00258 CCGVert *next; /* EHData.next */ 00259 CCGVertHDL vHDL; /* EHData.key */ 00260 00261 short numEdges, numFaces, flags, pad; 00262 00263 CCGEdge **edges; 00264 CCGFace **faces; 00265 // byte *levelData; 00266 // byte *userData; 00267 }; 00268 #define VERT_getLevelData(v) ((byte*) &(v)[1]) 00269 00270 struct _CCGEdge { 00271 CCGEdge *next; /* EHData.next */ 00272 CCGEdgeHDL eHDL; /* EHData.key */ 00273 00274 short numFaces, flags; 00275 float crease; 00276 00277 CCGVert *v0,*v1; 00278 CCGFace **faces; 00279 00280 // byte *levelData; 00281 // byte *userData; 00282 }; 00283 #define EDGE_getLevelData(e) ((byte*) &(e)[1]) 00284 00285 struct _CCGFace { 00286 CCGFace *next; /* EHData.next */ 00287 CCGFaceHDL fHDL; /* EHData.key */ 00288 00289 short numVerts, flags, pad1, pad2; 00290 00291 // CCGVert **verts; 00292 // CCGEdge **edges; 00293 // byte *centerData; 00294 // byte **gridData; 00295 // byte *userData; 00296 }; 00297 #define FACE_getVerts(f) ((CCGVert**) &(f)[1]) 00298 #define FACE_getEdges(f) ((CCGEdge**) &(FACE_getVerts(f)[(f)->numVerts])) 00299 #define FACE_getCenterData(f) ((byte*) &(FACE_getEdges(f)[(f)->numVerts])) 00300 00301 typedef enum { 00302 eSyncState_None = 0, 00303 eSyncState_Vert, 00304 eSyncState_Edge, 00305 eSyncState_Face, 00306 eSyncState_Partial, 00307 } SyncState; 00308 00309 struct _CCGSubSurf { 00310 EHash *vMap; /* map of CCGVertHDL -> Vert */ 00311 EHash *eMap; /* map of CCGEdgeHDL -> Edge */ 00312 EHash *fMap; /* map of CCGFaceHDL -> Face */ 00313 00314 CCGMeshIFC meshIFC; 00315 00316 CCGAllocatorIFC allocatorIFC; 00317 CCGAllocatorHDL allocator; 00318 00319 int subdivLevels; 00320 int numGrids; 00321 int allowEdgeCreation; 00322 float defaultCreaseValue; 00323 void *defaultEdgeUserData; 00324 00325 void *q, *r; 00326 00327 // data for calc vert normals 00328 int calcVertNormals; 00329 int normalDataOffset; 00330 00331 // data for age'ing (to debug sync) 00332 int currentAge; 00333 int useAgeCounts; 00334 int vertUserAgeOffset; 00335 int edgeUserAgeOffset; 00336 int faceUserAgeOffset; 00337 00338 // data used during syncing 00339 SyncState syncState; 00340 00341 EHash *oldVMap, *oldEMap, *oldFMap; 00342 int lenTempArrays; 00343 CCGVert **tempVerts; 00344 CCGEdge **tempEdges; 00345 }; 00346 00347 #define CCGSUBSURF_alloc(ss, nb) ((ss)->allocatorIFC.alloc((ss)->allocator, nb)) 00348 #define CCGSUBSURF_realloc(ss, ptr, nb, ob) ((ss)->allocatorIFC.realloc((ss)->allocator, ptr, nb, ob)) 00349 #define CCGSUBSURF_free(ss, ptr) ((ss)->allocatorIFC.free((ss)->allocator, ptr)) 00350 00351 /***/ 00352 00353 static CCGVert *_vert_new(CCGVertHDL vHDL, CCGSubSurf *ss) { 00354 CCGVert *v = CCGSUBSURF_alloc(ss, sizeof(CCGVert) + ss->meshIFC.vertDataSize * (ss->subdivLevels+1) + ss->meshIFC.vertUserSize); 00355 byte *userData; 00356 00357 v->vHDL = vHDL; 00358 v->edges = NULL; 00359 v->faces = NULL; 00360 v->numEdges = v->numFaces = 0; 00361 v->flags = 0; 00362 00363 userData = ccgSubSurf_getVertUserData(ss, v); 00364 memset(userData, 0, ss->meshIFC.vertUserSize); 00365 if (ss->useAgeCounts) *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge; 00366 00367 return v; 00368 } 00369 static void _vert_remEdge(CCGVert *v, CCGEdge *e) { 00370 int i; 00371 for (i=0; i<v->numEdges; i++) { 00372 if (v->edges[i]==e) { 00373 v->edges[i] = v->edges[--v->numEdges]; 00374 break; 00375 } 00376 } 00377 } 00378 static void _vert_remFace(CCGVert *v, CCGFace *f) { 00379 int i; 00380 for (i=0; i<v->numFaces; i++) { 00381 if (v->faces[i]==f) { 00382 v->faces[i] = v->faces[--v->numFaces]; 00383 break; 00384 } 00385 } 00386 } 00387 static void _vert_addEdge(CCGVert *v, CCGEdge *e, CCGSubSurf *ss) { 00388 v->edges = CCGSUBSURF_realloc(ss, v->edges, (v->numEdges+1)*sizeof(*v->edges), v->numEdges*sizeof(*v->edges)); 00389 v->edges[v->numEdges++] = e; 00390 } 00391 static void _vert_addFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) { 00392 v->faces = CCGSUBSURF_realloc(ss, v->faces, (v->numFaces+1)*sizeof(*v->faces), v->numFaces*sizeof(*v->faces)); 00393 v->faces[v->numFaces++] = f; 00394 } 00395 static CCGEdge *_vert_findEdgeTo(const CCGVert *v, const CCGVert *vQ) { 00396 int i; 00397 for (i=0; i<v->numEdges; i++) { 00398 CCGEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse 00399 if ( (e->v0==v && e->v1==vQ) || 00400 (e->v1==v && e->v0==vQ)) 00401 return e; 00402 } 00403 return NULL; 00404 } 00405 static int _vert_isBoundary(const CCGVert *v) { 00406 int i; 00407 for (i=0; i<v->numEdges; i++) 00408 if (_edge_isBoundary(v->edges[i])) 00409 return 1; 00410 return 0; 00411 } 00412 00413 static void *_vert_getCo(CCGVert *v, int lvl, int dataSize) { 00414 return &VERT_getLevelData(v)[lvl*dataSize]; 00415 } 00416 static float *_vert_getNo(CCGVert *v, int lvl, int dataSize, int normalDataOffset) { 00417 return (float*) &VERT_getLevelData(v)[lvl*dataSize + normalDataOffset]; 00418 } 00419 00420 static void _vert_free(CCGVert *v, CCGSubSurf *ss) { 00421 CCGSUBSURF_free(ss, v->edges); 00422 CCGSUBSURF_free(ss, v->faces); 00423 CCGSUBSURF_free(ss, v); 00424 } 00425 00426 static int VERT_seam(const CCGVert *v) { 00427 return ((v->flags & Vert_eSeam) != 0); 00428 } 00429 00430 /***/ 00431 00432 static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float crease, CCGSubSurf *ss) { 00433 CCGEdge *e = CCGSUBSURF_alloc(ss, sizeof(CCGEdge) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1) + ss->meshIFC.edgeUserSize); 00434 byte *userData; 00435 00436 e->eHDL = eHDL; 00437 e->v0 = v0; 00438 e->v1 = v1; 00439 e->crease = crease; 00440 e->faces = NULL; 00441 e->numFaces = 0; 00442 e->flags = 0; 00443 _vert_addEdge(v0, e, ss); 00444 _vert_addEdge(v1, e, ss); 00445 00446 userData = ccgSubSurf_getEdgeUserData(ss, e); 00447 memset(userData, 0, ss->meshIFC.edgeUserSize); 00448 if (ss->useAgeCounts) *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge; 00449 00450 return e; 00451 } 00452 static void _edge_remFace(CCGEdge *e, CCGFace *f) { 00453 int i; 00454 for (i=0; i<e->numFaces; i++) { 00455 if (e->faces[i]==f) { 00456 e->faces[i] = e->faces[--e->numFaces]; 00457 break; 00458 } 00459 } 00460 } 00461 static void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) { 00462 e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces+1)*sizeof(*e->faces), e->numFaces*sizeof(*e->faces)); 00463 e->faces[e->numFaces++] = f; 00464 } 00465 static int _edge_isBoundary(const CCGEdge *e) { 00466 return e->numFaces<2; 00467 } 00468 00469 static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ) { 00470 if (vQ==e->v0) { 00471 return e->v1; 00472 } else { 00473 return e->v0; 00474 } 00475 } 00476 00477 static void *_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize) { 00478 int levelBase = lvl + (1<<lvl) - 1; 00479 return &EDGE_getLevelData(e)[dataSize*(levelBase + x)]; 00480 } 00481 static float *_edge_getNo(CCGEdge *e, int lvl, int x, int dataSize, int normalDataOffset) { 00482 int levelBase = lvl + (1<<lvl) - 1; 00483 return (float*) &EDGE_getLevelData(e)[dataSize*(levelBase + x) + normalDataOffset]; 00484 } 00485 static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize) { 00486 int levelBase = lvl + (1<<lvl) - 1; 00487 if (v==e->v0) { 00488 return &EDGE_getLevelData(e)[dataSize*(levelBase + x)]; 00489 } else { 00490 return &EDGE_getLevelData(e)[dataSize*(levelBase + (1<<lvl) - x)]; 00491 } 00492 } 00493 00494 static void _edge_free(CCGEdge *e, CCGSubSurf *ss) { 00495 CCGSUBSURF_free(ss, e->faces); 00496 CCGSUBSURF_free(ss, e); 00497 } 00498 static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss) { 00499 _vert_remEdge(e->v0, e); 00500 _vert_remEdge(e->v1, e); 00501 e->v0->flags |= Vert_eEffected; 00502 e->v1->flags |= Vert_eEffected; 00503 _edge_free(e, ss); 00504 } 00505 00506 static float EDGE_getSharpness(CCGEdge *e, int lvl) { 00507 if (!lvl) 00508 return e->crease; 00509 else if (!e->crease) 00510 return 0.0f; 00511 else if (e->crease - lvl < 0.0f) 00512 return 0.0f; 00513 else 00514 return e->crease - lvl; 00515 } 00516 00517 static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, CCGSubSurf *ss) { 00518 int maxGridSize = 1 + (1<<(ss->subdivLevels-1)); 00519 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); 00520 byte *userData; 00521 int i; 00522 00523 f->numVerts = numVerts; 00524 f->fHDL = fHDL; 00525 f->flags = 0; 00526 00527 for (i=0; i<numVerts; i++) { 00528 FACE_getVerts(f)[i] = verts[i]; 00529 FACE_getEdges(f)[i] = edges[i]; 00530 _vert_addFace(verts[i], f, ss); 00531 _edge_addFace(edges[i], f, ss); 00532 } 00533 00534 userData = ccgSubSurf_getFaceUserData(ss, f); 00535 memset(userData, 0, ss->meshIFC.faceUserSize); 00536 if (ss->useAgeCounts) *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge; 00537 00538 return f; 00539 } 00540 00541 static CCG_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) { 00542 int maxGridSize = 1 + (1<<(levels-1)); 00543 int spacing = 1<<(levels-lvl); 00544 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); 00545 return &gridBase[dataSize*x*spacing]; 00546 } 00547 static CCG_INLINE void *_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset) { 00548 int maxGridSize = 1 + (1<<(levels-1)); 00549 int spacing = 1<<(levels-lvl); 00550 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); 00551 return &gridBase[dataSize*x*spacing + normalDataOffset]; 00552 } 00553 static CCG_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) { 00554 int maxGridSize = 1 + (1<<(levels-1)); 00555 int spacing = 1<<(levels-lvl); 00556 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); 00557 return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)]; 00558 } 00559 static CCG_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) { 00560 int maxGridSize = 1 + (1<<(levels-1)); 00561 int spacing = 1<<(levels-lvl); 00562 byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); 00563 return (float*) &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing) + normalDataOffset]; 00564 } 00565 static int _face_getVertIndex(CCGFace *f, CCGVert *v) { 00566 int i; 00567 for (i=0; i<f->numVerts; i++) 00568 if (FACE_getVerts(f)[i]==v) 00569 return i; 00570 return -1; 00571 } 00572 static CCG_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize) { 00573 int maxGridSize = 1 + (1<<(levels-1)); 00574 int spacing = 1<<(levels-lvl); 00575 int S, x, y, cx, cy; 00576 00577 for (S=0; S<f->numVerts; S++) 00578 if (FACE_getEdges(f)[S]==e) 00579 break; 00580 00581 eX = eX*spacing; 00582 eY = eY*spacing; 00583 if (e->v0!=FACE_getVerts(f)[S]) { 00584 eX = (maxGridSize*2 - 1)-1 - eX; 00585 } 00586 y = maxGridSize - 1 - eX; 00587 x = maxGridSize - 1 - eY; 00588 if (x<0) { 00589 S = (S+f->numVerts-1)%f->numVerts; 00590 cx = y; 00591 cy = -x; 00592 } else if (y<0) { 00593 S = (S+1)%f->numVerts; 00594 cx = -y; 00595 cy = x; 00596 } else { 00597 cx = x; 00598 cy = y; 00599 } 00600 return _face_getIFCo(f, levels, S, cx, cy, levels, dataSize); 00601 } 00602 static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) { 00603 return (float*) ((byte*) _face_getIFCoEdge(f, e, lvl, eX, eY, levels, dataSize) + normalDataOffset); 00604 } 00605 static void _face_calcIFNo(CCGFace *f, int lvl, int S, int x, int y, float *no, int levels, int dataSize) { 00606 float *a = _face_getIFCo(f, lvl, S, x+0, y+0, levels, dataSize); 00607 float *b = _face_getIFCo(f, lvl, S, x+1, y+0, levels, dataSize); 00608 float *c = _face_getIFCo(f, lvl, S, x+1, y+1, levels, dataSize); 00609 float *d = _face_getIFCo(f, lvl, S, x+0, y+1, levels, dataSize); 00610 float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2]; 00611 float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2]; 00612 float length; 00613 00614 no[0] = b_dY*a_cZ - b_dZ*a_cY; 00615 no[1] = b_dZ*a_cX - b_dX*a_cZ; 00616 no[2] = b_dX*a_cY - b_dY*a_cX; 00617 00618 length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]); 00619 00620 if (length>EPSILON) { 00621 float invLength = 1.f/length; 00622 00623 no[0] *= invLength; 00624 no[1] *= invLength; 00625 no[2] *= invLength; 00626 } else { 00627 NormZero(no); 00628 } 00629 } 00630 00631 static void _face_free(CCGFace *f, CCGSubSurf *ss) { 00632 CCGSUBSURF_free(ss, f); 00633 } 00634 static void _face_unlinkMarkAndFree(CCGFace *f, CCGSubSurf *ss) { 00635 int j; 00636 for (j=0; j<f->numVerts; j++) { 00637 _vert_remFace(FACE_getVerts(f)[j], f); 00638 _edge_remFace(FACE_getEdges(f)[j], f); 00639 FACE_getVerts(f)[j]->flags |= Vert_eEffected; 00640 } 00641 _face_free(f, ss); 00642 } 00643 00644 /***/ 00645 00646 CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator) { 00647 if (!allocatorIFC) { 00648 allocatorIFC = _getStandardAllocatorIFC(); 00649 allocator = NULL; 00650 } 00651 00652 if (subdivLevels<1) { 00653 return NULL; 00654 } else { 00655 CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss)); 00656 00657 ss->allocatorIFC = *allocatorIFC; 00658 ss->allocator = allocator; 00659 00660 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); 00661 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); 00662 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); 00663 00664 ss->meshIFC = *ifc; 00665 00666 ss->subdivLevels = subdivLevels; 00667 ss->numGrids = 0; 00668 ss->allowEdgeCreation = 0; 00669 ss->defaultCreaseValue = 0; 00670 ss->defaultEdgeUserData = NULL; 00671 00672 ss->useAgeCounts = 0; 00673 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0; 00674 00675 ss->calcVertNormals = 0; 00676 ss->normalDataOffset = 0; 00677 00678 ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); 00679 ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); 00680 00681 ss->currentAge = 0; 00682 00683 ss->syncState = eSyncState_None; 00684 00685 ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL; 00686 ss->lenTempArrays = 0; 00687 ss->tempVerts = NULL; 00688 ss->tempEdges = NULL; 00689 00690 return ss; 00691 } 00692 } 00693 00694 void ccgSubSurf_free(CCGSubSurf *ss) { 00695 CCGAllocatorIFC allocatorIFC = ss->allocatorIFC; 00696 CCGAllocatorHDL allocator = ss->allocator; 00697 00698 if (ss->syncState) { 00699 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_free, ss); 00700 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_free, ss); 00701 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss); 00702 00703 MEM_freeN(ss->tempVerts); 00704 MEM_freeN(ss->tempEdges); 00705 } 00706 00707 CCGSUBSURF_free(ss, ss->r); 00708 CCGSUBSURF_free(ss, ss->q); 00709 if (ss->defaultEdgeUserData) CCGSUBSURF_free(ss, ss->defaultEdgeUserData); 00710 00711 _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss); 00712 _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss); 00713 _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss); 00714 00715 CCGSUBSURF_free(ss, ss); 00716 00717 if (allocatorIFC.release) { 00718 allocatorIFC.release(allocator); 00719 } 00720 } 00721 00722 CCGError ccgSubSurf_setAllowEdgeCreation(CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData) { 00723 if (ss->defaultEdgeUserData) { 00724 CCGSUBSURF_free(ss, ss->defaultEdgeUserData); 00725 } 00726 00727 ss->allowEdgeCreation = !!allowEdgeCreation; 00728 ss->defaultCreaseValue = defaultCreaseValue; 00729 ss->defaultEdgeUserData = CCGSUBSURF_alloc(ss, ss->meshIFC.edgeUserSize); 00730 00731 if (defaultUserData) { 00732 memcpy(ss->defaultEdgeUserData, defaultUserData, ss->meshIFC.edgeUserSize); 00733 } else { 00734 memset(ss->defaultEdgeUserData, 0, ss->meshIFC.edgeUserSize); 00735 } 00736 00737 return eCCGError_None; 00738 } 00739 void ccgSubSurf_getAllowEdgeCreation(CCGSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r) { 00740 if (allowEdgeCreation_r) *allowEdgeCreation_r = ss->allowEdgeCreation; 00741 if (ss->allowEdgeCreation) { 00742 if (defaultCreaseValue_r) *defaultCreaseValue_r = ss->defaultCreaseValue; 00743 if (defaultUserData_r) memcpy(defaultUserData_r, ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize); 00744 } 00745 } 00746 00747 CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels) { 00748 if (subdivisionLevels<=0) { 00749 return eCCGError_InvalidValue; 00750 } else if (subdivisionLevels!=ss->subdivLevels) { 00751 ss->numGrids = 0; 00752 ss->subdivLevels = subdivisionLevels; 00753 _ehash_free(ss->vMap, (EHEntryFreeFP) _vert_free, ss); 00754 _ehash_free(ss->eMap, (EHEntryFreeFP) _edge_free, ss); 00755 _ehash_free(ss->fMap, (EHEntryFreeFP) _face_free, ss); 00756 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); 00757 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); 00758 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); 00759 } 00760 00761 return eCCGError_None; 00762 } 00763 00764 void ccgSubSurf_getUseAgeCounts(CCGSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r) 00765 { 00766 *useAgeCounts_r = ss->useAgeCounts; 00767 00768 if (vertUserOffset_r) *vertUserOffset_r = ss->vertUserAgeOffset; 00769 if (edgeUserOffset_r) *edgeUserOffset_r = ss->edgeUserAgeOffset; 00770 if (faceUserOffset_r) *faceUserOffset_r = ss->faceUserAgeOffset; 00771 } 00772 00773 CCGError ccgSubSurf_setUseAgeCounts(CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset) { 00774 if (useAgeCounts) { 00775 if ( (vertUserOffset+4>ss->meshIFC.vertUserSize) || 00776 (edgeUserOffset+4>ss->meshIFC.edgeUserSize) || 00777 (faceUserOffset+4>ss->meshIFC.faceUserSize)) { 00778 return eCCGError_InvalidValue; 00779 } else { 00780 ss->useAgeCounts = 1; 00781 ss->vertUserAgeOffset = vertUserOffset; 00782 ss->edgeUserAgeOffset = edgeUserOffset; 00783 ss->faceUserAgeOffset = faceUserOffset; 00784 } 00785 } else { 00786 ss->useAgeCounts = 0; 00787 ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0; 00788 } 00789 00790 return eCCGError_None; 00791 } 00792 00793 CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int normalDataOffset) { 00794 if (useVertNormals) { 00795 if (normalDataOffset<0 || normalDataOffset+12>ss->meshIFC.vertDataSize) { 00796 return eCCGError_InvalidValue; 00797 } else { 00798 ss->calcVertNormals = 1; 00799 ss->normalDataOffset = normalDataOffset; 00800 } 00801 } else { 00802 ss->calcVertNormals = 0; 00803 ss->normalDataOffset = 0; 00804 } 00805 00806 return eCCGError_None; 00807 } 00808 00809 /***/ 00810 00811 CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) { 00812 if (ss->syncState!=eSyncState_None) { 00813 return eCCGError_InvalidSyncState; 00814 } 00815 00816 ss->currentAge++; 00817 00818 ss->oldVMap = ss->vMap; 00819 ss->oldEMap = ss->eMap; 00820 ss->oldFMap = ss->fMap; 00821 00822 ss->vMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); 00823 ss->eMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); 00824 ss->fMap = _ehash_new(0, &ss->allocatorIFC, ss->allocator); 00825 00826 ss->numGrids = 0; 00827 00828 ss->lenTempArrays = 12; 00829 ss->tempVerts = MEM_mallocN(sizeof(*ss->tempVerts)*ss->lenTempArrays, "CCGSubsurf tempVerts"); 00830 ss->tempEdges = MEM_mallocN(sizeof(*ss->tempEdges)*ss->lenTempArrays, "CCGSubsurf tempEdges"); 00831 00832 ss->syncState = eSyncState_Vert; 00833 00834 return eCCGError_None; 00835 } 00836 00837 CCGError ccgSubSurf_initPartialSync(CCGSubSurf *ss) { 00838 if (ss->syncState!=eSyncState_None) { 00839 return eCCGError_InvalidSyncState; 00840 } 00841 00842 ss->currentAge++; 00843 00844 ss->syncState = eSyncState_Partial; 00845 00846 return eCCGError_None; 00847 } 00848 00849 CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL) { 00850 if (ss->syncState!=eSyncState_Partial) { 00851 return eCCGError_InvalidSyncState; 00852 } else { 00853 void **prevp; 00854 CCGVert *v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp); 00855 00856 if (!v || v->numFaces || v->numEdges) { 00857 return eCCGError_InvalidValue; 00858 } else { 00859 *prevp = v->next; 00860 _vert_free(v, ss); 00861 } 00862 } 00863 00864 return eCCGError_None; 00865 } 00866 00867 CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL) { 00868 if (ss->syncState!=eSyncState_Partial) { 00869 return eCCGError_InvalidSyncState; 00870 } else { 00871 void **prevp; 00872 CCGEdge *e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp); 00873 00874 if (!e || e->numFaces) { 00875 return eCCGError_InvalidValue; 00876 } else { 00877 *prevp = e->next; 00878 _edge_unlinkMarkAndFree(e, ss); 00879 } 00880 } 00881 00882 return eCCGError_None; 00883 } 00884 00885 CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) { 00886 if (ss->syncState!=eSyncState_Partial) { 00887 return eCCGError_InvalidSyncState; 00888 } else { 00889 void **prevp; 00890 CCGFace *f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp); 00891 00892 if (!f) { 00893 return eCCGError_InvalidValue; 00894 } else { 00895 *prevp = f->next; 00896 _face_unlinkMarkAndFree(f, ss); 00897 } 00898 } 00899 00900 return eCCGError_None; 00901 } 00902 00903 CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertData, int seam, CCGVert **v_r) { 00904 void **prevp; 00905 CCGVert *v = NULL; 00906 short seamflag = (seam)? Vert_eSeam: 0; 00907 00908 if (ss->syncState==eSyncState_Partial) { 00909 v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp); 00910 if (!v) { 00911 v = _vert_new(vHDL, ss); 00912 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData); 00913 _ehash_insert(ss->vMap, (EHEntry*) v); 00914 v->flags = Vert_eEffected|seamflag; 00915 } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) { 00916 int i, j; 00917 00918 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData); 00919 v->flags = Vert_eEffected|seamflag; 00920 00921 for (i=0; i<v->numEdges; i++) { 00922 CCGEdge *e = v->edges[i]; 00923 e->v0->flags |= Vert_eEffected; 00924 e->v1->flags |= Vert_eEffected; 00925 } 00926 for (i=0; i<v->numFaces; i++) { 00927 CCGFace *f = v->faces[i]; 00928 for (j=0; j<f->numVerts; j++) { 00929 FACE_getVerts(f)[j]->flags |= Vert_eEffected; 00930 } 00931 } 00932 } 00933 } else { 00934 if (ss->syncState!=eSyncState_Vert) { 00935 return eCCGError_InvalidSyncState; 00936 } 00937 00938 v = _ehash_lookupWithPrev(ss->oldVMap, vHDL, &prevp); 00939 if (!v) { 00940 v = _vert_new(vHDL, ss); 00941 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData); 00942 _ehash_insert(ss->vMap, (EHEntry*) v); 00943 v->flags = Vert_eEffected|seamflag; 00944 } else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) { 00945 *prevp = v->next; 00946 _ehash_insert(ss->vMap, (EHEntry*) v); 00947 VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData); 00948 v->flags = Vert_eEffected|Vert_eChanged|seamflag; 00949 } else { 00950 *prevp = v->next; 00951 _ehash_insert(ss->vMap, (EHEntry*) v); 00952 v->flags = 0; 00953 } 00954 } 00955 00956 if (v_r) *v_r = v; 00957 return eCCGError_None; 00958 } 00959 00960 CCGError ccgSubSurf_syncEdge(CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r) { 00961 void **prevp; 00962 CCGEdge *e = NULL, *eNew; 00963 00964 if (ss->syncState==eSyncState_Partial) { 00965 e = _ehash_lookupWithPrev(ss->eMap, eHDL, &prevp); 00966 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1 || crease!=e->crease) { 00967 CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0); 00968 CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1); 00969 00970 eNew = _edge_new(eHDL, v0, v1, crease, ss); 00971 00972 if (e) { 00973 *prevp = eNew; 00974 eNew->next = e->next; 00975 00976 _edge_unlinkMarkAndFree(e, ss); 00977 } else { 00978 _ehash_insert(ss->eMap, (EHEntry*) eNew); 00979 } 00980 00981 eNew->v0->flags |= Vert_eEffected; 00982 eNew->v1->flags |= Vert_eEffected; 00983 } 00984 } else { 00985 if (ss->syncState==eSyncState_Vert) { 00986 ss->syncState = eSyncState_Edge; 00987 } else if (ss->syncState!=eSyncState_Edge) { 00988 return eCCGError_InvalidSyncState; 00989 } 00990 00991 e = _ehash_lookupWithPrev(ss->oldEMap, eHDL, &prevp); 00992 if (!e || e->v0->vHDL!=e_vHDL0 || e->v1->vHDL!=e_vHDL1|| e->crease!=crease) { 00993 CCGVert *v0 = _ehash_lookup(ss->vMap, e_vHDL0); 00994 CCGVert *v1 = _ehash_lookup(ss->vMap, e_vHDL1); 00995 e = _edge_new(eHDL, v0, v1, crease, ss); 00996 _ehash_insert(ss->eMap, (EHEntry*) e); 00997 e->v0->flags |= Vert_eEffected; 00998 e->v1->flags |= Vert_eEffected; 00999 } else { 01000 *prevp = e->next; 01001 _ehash_insert(ss->eMap, (EHEntry*) e); 01002 e->flags = 0; 01003 if ((e->v0->flags|e->v1->flags)&Vert_eChanged) { 01004 e->v0->flags |= Vert_eEffected; 01005 e->v1->flags |= Vert_eEffected; 01006 } 01007 } 01008 } 01009 01010 if (e_r) *e_r = e; 01011 return eCCGError_None; 01012 } 01013 01014 CCGError ccgSubSurf_syncFace(CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r) { 01015 void **prevp; 01016 CCGFace *f = NULL, *fNew; 01017 int j, k, topologyChanged = 0; 01018 01019 if (numVerts>ss->lenTempArrays) { 01020 ss->lenTempArrays = (numVerts<ss->lenTempArrays*2)?ss->lenTempArrays*2:numVerts; 01021 ss->tempVerts = MEM_reallocN(ss->tempVerts, sizeof(*ss->tempVerts)*ss->lenTempArrays); 01022 ss->tempEdges = MEM_reallocN(ss->tempEdges, sizeof(*ss->tempEdges)*ss->lenTempArrays); 01023 } 01024 01025 if (ss->syncState==eSyncState_Partial) { 01026 f = _ehash_lookupWithPrev(ss->fMap, fHDL, &prevp); 01027 01028 for (k=0; k<numVerts; k++) { 01029 ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]); 01030 } 01031 for (k=0; k<numVerts; k++) { 01032 ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]); 01033 } 01034 01035 if (f) { 01036 if ( f->numVerts!=numVerts || 01037 memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) || 01038 memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts)) 01039 topologyChanged = 1; 01040 } 01041 01042 if (!f || topologyChanged) { 01043 fNew = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss); 01044 01045 if (f) { 01046 ss->numGrids += numVerts - f->numVerts; 01047 01048 *prevp = fNew; 01049 fNew->next = f->next; 01050 01051 _face_unlinkMarkAndFree(f, ss); 01052 } else { 01053 ss->numGrids += numVerts; 01054 _ehash_insert(ss->fMap, (EHEntry*) fNew); 01055 } 01056 01057 for (k=0; k<numVerts; k++) 01058 FACE_getVerts(fNew)[k]->flags |= Vert_eEffected; 01059 } 01060 } else { 01061 if (ss->syncState==eSyncState_Vert || ss->syncState==eSyncState_Edge) { 01062 ss->syncState = eSyncState_Face; 01063 } else if (ss->syncState!=eSyncState_Face) { 01064 return eCCGError_InvalidSyncState; 01065 } 01066 01067 f = _ehash_lookupWithPrev(ss->oldFMap, fHDL, &prevp); 01068 01069 for (k=0; k<numVerts; k++) { 01070 ss->tempVerts[k] = _ehash_lookup(ss->vMap, vHDLs[k]); 01071 01072 if (!ss->tempVerts[k]) 01073 return eCCGError_InvalidValue; 01074 } 01075 for (k=0; k<numVerts; k++) { 01076 ss->tempEdges[k] = _vert_findEdgeTo(ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts]); 01077 01078 if (!ss->tempEdges[k]) { 01079 if (ss->allowEdgeCreation) { 01080 CCGEdge *e = ss->tempEdges[k] = _edge_new((CCGEdgeHDL) -1, ss->tempVerts[k], ss->tempVerts[(k+1)%numVerts], ss->defaultCreaseValue, ss); 01081 _ehash_insert(ss->eMap, (EHEntry*) e); 01082 e->v0->flags |= Vert_eEffected; 01083 e->v1->flags |= Vert_eEffected; 01084 if (ss->meshIFC.edgeUserSize) { 01085 memcpy(ccgSubSurf_getEdgeUserData(ss, e), ss->defaultEdgeUserData, ss->meshIFC.edgeUserSize); 01086 } 01087 } else { 01088 return eCCGError_InvalidValue; 01089 } 01090 } 01091 } 01092 01093 if (f) { 01094 if ( f->numVerts!=numVerts || 01095 memcmp(FACE_getVerts(f), ss->tempVerts, sizeof(*ss->tempVerts)*numVerts) || 01096 memcmp(FACE_getEdges(f), ss->tempEdges, sizeof(*ss->tempEdges)*numVerts)) 01097 topologyChanged = 1; 01098 } 01099 01100 if (!f || topologyChanged) { 01101 f = _face_new(fHDL, ss->tempVerts, ss->tempEdges, numVerts, ss); 01102 _ehash_insert(ss->fMap, (EHEntry*) f); 01103 ss->numGrids += numVerts; 01104 01105 for (k=0; k<numVerts; k++) 01106 FACE_getVerts(f)[k]->flags |= Vert_eEffected; 01107 } else { 01108 *prevp = f->next; 01109 _ehash_insert(ss->fMap, (EHEntry*) f); 01110 f->flags = 0; 01111 ss->numGrids += f->numVerts; 01112 01113 for (j=0; j<f->numVerts; j++) { 01114 if (FACE_getVerts(f)[j]->flags&Vert_eChanged) { 01115 for (k=0; k<f->numVerts; k++) 01116 FACE_getVerts(f)[k]->flags |= Vert_eEffected; 01117 break; 01118 } 01119 } 01120 } 01121 } 01122 01123 if (f_r) *f_r = f; 01124 return eCCGError_None; 01125 } 01126 01127 static void ccgSubSurf__sync(CCGSubSurf *ss); 01128 CCGError ccgSubSurf_processSync(CCGSubSurf *ss) { 01129 if (ss->syncState==eSyncState_Partial) { 01130 ss->syncState = eSyncState_None; 01131 01132 ccgSubSurf__sync(ss); 01133 } else if (ss->syncState) { 01134 _ehash_free(ss->oldFMap, (EHEntryFreeFP) _face_unlinkMarkAndFree, ss); 01135 _ehash_free(ss->oldEMap, (EHEntryFreeFP) _edge_unlinkMarkAndFree, ss); 01136 _ehash_free(ss->oldVMap, (EHEntryFreeFP) _vert_free, ss); 01137 MEM_freeN(ss->tempEdges); 01138 MEM_freeN(ss->tempVerts); 01139 01140 ss->lenTempArrays = 0; 01141 01142 ss->oldFMap = ss->oldEMap = ss->oldVMap = NULL; 01143 ss->tempVerts = NULL; 01144 ss->tempEdges = NULL; 01145 01146 ss->syncState = eSyncState_None; 01147 01148 ccgSubSurf__sync(ss); 01149 } else { 01150 return eCCGError_InvalidSyncState; 01151 } 01152 01153 return eCCGError_None; 01154 } 01155 01156 #define VERT_getNo(e, lvl) _vert_getNo(e, lvl, vertDataSize, normalDataOffset) 01157 #define EDGE_getNo(e, lvl, x) _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset) 01158 #define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset) 01159 #define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize) 01160 #define FACE_getIENo(f, lvl, S, x) _face_getIENo(f, lvl, S, x, subdivLevels, vertDataSize, normalDataOffset) 01161 static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, 01162 CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF, 01163 int numEffectedV, int numEffectedE, int numEffectedF) { 01164 int i,ptrIdx; 01165 int subdivLevels = ss->subdivLevels; 01166 int lvl = ss->subdivLevels; 01167 int edgeSize = 1 + (1<<lvl); 01168 int gridSize = 1 + (1<<(lvl-1)); 01169 int normalDataOffset = ss->normalDataOffset; 01170 int vertDataSize = ss->meshIFC.vertDataSize; 01171 01172 #pragma omp parallel for private(ptrIdx) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT) 01173 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) { 01174 CCGFace *f = (CCGFace*) effectedF[ptrIdx]; 01175 int S, x, y; 01176 float no[3]; 01177 01178 for (S=0; S<f->numVerts; S++) { 01179 for (y=0; y<gridSize-1; y++) 01180 for (x=0; x<gridSize-1; x++) 01181 NormZero(FACE_getIFNo(f, lvl, S, x, y)); 01182 01183 if (FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected) 01184 for (x=0; x<gridSize-1; x++) 01185 NormZero(FACE_getIFNo(f, lvl, S, x, gridSize-1)); 01186 if (FACE_getEdges(f)[S]->flags&Edge_eEffected) 01187 for (y=0; y<gridSize-1; y++) 01188 NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, y)); 01189 if (FACE_getVerts(f)[S]->flags&Vert_eEffected) 01190 NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1)); 01191 } 01192 01193 for (S=0; S<f->numVerts; S++) { 01194 int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected); 01195 int xLimit = !(FACE_getEdges(f)[S]->flags&Edge_eEffected); 01196 int yLimitNext = xLimit; 01197 int xLimitPrev = yLimit; 01198 01199 for (y=0; y<gridSize - 1; y++) { 01200 for (x=0; x<gridSize - 1; x++) { 01201 int xPlusOk = (!xLimit || x<gridSize-2); 01202 int yPlusOk = (!yLimit || y<gridSize-2); 01203 01204 FACE_calcIFNo(f, lvl, S, x, y, no); 01205 01206 NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+0), no); 01207 if (xPlusOk) 01208 NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+0), no); 01209 if (yPlusOk) 01210 NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+1), no); 01211 if (xPlusOk && yPlusOk) { 01212 if (x<gridSize-2 || y<gridSize-2 || FACE_getVerts(f)[S]->flags&Vert_eEffected) { 01213 NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+1), no); 01214 } 01215 } 01216 01217 if (x==0 && y==0) { 01218 int K; 01219 01220 if (!yLimitNext || 1<gridSize-1) 01221 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, 1), no); 01222 if (!xLimitPrev || 1<gridSize-1) 01223 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no); 01224 01225 for (K=0; K<f->numVerts; K++) { 01226 if (K!=S) { 01227 NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no); 01228 } 01229 } 01230 } else if (y==0) { 01231 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no); 01232 if (!yLimitNext || x<gridSize-2) 01233 NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x+1), no); 01234 } else if (x==0) { 01235 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no); 01236 if (!xLimitPrev || y<gridSize-2) 01237 NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y+1, 0), no); 01238 } 01239 } 01240 } 01241 } 01242 } 01243 // XXX can I reduce the number of normalisations here? 01244 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) { 01245 CCGVert *v = (CCGVert*) effectedV[ptrIdx]; 01246 float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset); 01247 01248 NormZero(no); 01249 01250 for (i=0; i<v->numFaces; i++) { 01251 CCGFace *f = v->faces[i]; 01252 NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1)); 01253 } 01254 01255 length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]); 01256 01257 if (length>EPSILON) { 01258 float invLength = 1.0f/length; 01259 no[0] *= invLength; 01260 no[1] *= invLength; 01261 no[2] *= invLength; 01262 } else { 01263 NormZero(no); 01264 } 01265 01266 for (i=0; i<v->numFaces; i++) { 01267 CCGFace *f = v->faces[i]; 01268 NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no); 01269 } 01270 } 01271 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) { 01272 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx]; 01273 01274 if (e->numFaces) { 01275 CCGFace *fLast = e->faces[e->numFaces-1]; 01276 int x; 01277 01278 for (i=0; i<e->numFaces-1; i++) { 01279 CCGFace *f = e->faces[i]; 01280 01281 for (x=1; x<edgeSize-1; x++) { 01282 NormAdd(_face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset), 01283 _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset)); 01284 } 01285 } 01286 01287 for (i=0; i<e->numFaces-1; i++) { 01288 CCGFace *f = e->faces[i]; 01289 01290 for (x=1; x<edgeSize-1; x++) { 01291 NormCopy(_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset), 01292 _face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset)); 01293 } 01294 } 01295 } 01296 } 01297 01298 #pragma omp parallel for private(ptrIdx) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT) 01299 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) { 01300 CCGFace *f = (CCGFace*) effectedF[ptrIdx]; 01301 int S, x, y; 01302 01303 for (S=0; S<f->numVerts; S++) { 01304 NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1), 01305 FACE_getIFNo(f, lvl, S, gridSize-1, 0)); 01306 } 01307 01308 for (S=0; S<f->numVerts; S++) { 01309 for (y=0; y<gridSize; y++) { 01310 for (x=0; x<gridSize; x++) { 01311 float *no = FACE_getIFNo(f, lvl, S, x, y); 01312 float length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]); 01313 01314 if (length>EPSILON) { 01315 float invLength = 1.0f/length; 01316 no[0] *= invLength; 01317 no[1] *= invLength; 01318 no[2] *= invLength; 01319 } else { 01320 NormZero(no); 01321 } 01322 } 01323 } 01324 01325 VertDataCopy((float*)((byte*)FACE_getCenterData(f) + normalDataOffset), 01326 FACE_getIFNo(f, lvl, S, 0, 0)); 01327 01328 for (x=1; x<gridSize-1; x++) 01329 NormCopy(FACE_getIENo(f, lvl, S, x), 01330 FACE_getIFNo(f, lvl, S, x, 0)); 01331 } 01332 } 01333 01334 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) { 01335 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx]; 01336 01337 if (e->numFaces) { 01338 CCGFace *f = e->faces[0]; 01339 int x; 01340 01341 for (x=0; x<edgeSize; x++) 01342 NormCopy(EDGE_getNo(e, lvl, x), 01343 _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset)); 01344 } 01345 else { 01346 /* set to zero here otherwise the normals are uninitialized memory 01347 * render: tests/animation/knight.blend with valgrind. 01348 * we could be more clever and interpolate vertex normals but these are 01349 * most likely not used so just zero out. */ 01350 int x; 01351 01352 for (x=0; x<edgeSize; x++) { 01353 NormZero(EDGE_getNo(e, lvl, x)); 01354 } 01355 } 01356 } 01357 } 01358 #undef FACE_getIFNo 01359 01360 #define VERT_getCo(v, lvl) _vert_getCo(v, lvl, vertDataSize) 01361 #define EDGE_getCo(e, lvl, x) _edge_getCo(e, lvl, x, vertDataSize) 01362 #define FACE_getIECo(f, lvl, S, x) _face_getIECo(f, lvl, S, x, subdivLevels, vertDataSize) 01363 #define FACE_getIFCo(f, lvl, S, x, y) _face_getIFCo(f, lvl, S, x, y, subdivLevels, vertDataSize) 01364 static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, 01365 CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF, 01366 int numEffectedV, int numEffectedE, int numEffectedF, int curLvl) { 01367 int subdivLevels = ss->subdivLevels; 01368 int edgeSize = 1 + (1<<curLvl); 01369 int gridSize = 1 + (1<<(curLvl-1)); 01370 int nextLvl = curLvl+1; 01371 int ptrIdx, cornerIdx, i; 01372 int vertDataSize = ss->meshIFC.vertDataSize; 01373 void *q = ss->q, *r = ss->r; 01374 01375 #pragma omp parallel for private(ptrIdx) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT) 01376 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) { 01377 CCGFace *f = (CCGFace*) effectedF[ptrIdx]; 01378 int S, x, y; 01379 01380 /* interior face midpoints 01381 * o old interior face points 01382 */ 01383 for (S=0; S<f->numVerts; S++) { 01384 for (y=0; y<gridSize-1; y++) { 01385 for (x=0; x<gridSize-1; x++) { 01386 int fx = 1 + 2*x; 01387 int fy = 1 + 2*y; 01388 void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y+0); 01389 void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y+0); 01390 void *co2 = FACE_getIFCo(f, curLvl, S, x+1, y+1); 01391 void *co3 = FACE_getIFCo(f, curLvl, S, x+0, y+1); 01392 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy); 01393 01394 VertDataAvg4(co, co0, co1, co2, co3); 01395 } 01396 } 01397 } 01398 01399 /* interior edge midpoints 01400 * o old interior edge points 01401 * o new interior face midpoints 01402 */ 01403 for (S=0; S<f->numVerts; S++) { 01404 for (x=0; x<gridSize-1; x++) { 01405 int fx = x*2 + 1; 01406 void *co0 = FACE_getIECo(f, curLvl, S, x+0); 01407 void *co1 = FACE_getIECo(f, curLvl, S, x+1); 01408 void *co2 = FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx); 01409 void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1); 01410 void *co = FACE_getIECo(f, nextLvl, S, fx); 01411 01412 VertDataAvg4(co, co0, co1, co2, co3); 01413 } 01414 01415 /* interior face interior edge midpoints 01416 * o old interior face points 01417 * o new interior face midpoints 01418 */ 01419 01420 /* vertical */ 01421 for (x=1; x<gridSize-1; x++) { 01422 for (y=0; y<gridSize-1; y++) { 01423 int fx = x*2; 01424 int fy = y*2+1; 01425 void *co0 = FACE_getIFCo(f, curLvl, S, x, y+0); 01426 void *co1 = FACE_getIFCo(f, curLvl, S, x, y+1); 01427 void *co2 = FACE_getIFCo(f, nextLvl, S, fx-1, fy); 01428 void *co3 = FACE_getIFCo(f, nextLvl, S, fx+1, fy); 01429 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy); 01430 01431 VertDataAvg4(co, co0, co1, co2, co3); 01432 } 01433 } 01434 01435 /* horizontal */ 01436 for (y=1; y<gridSize-1; y++) { 01437 for (x=0; x<gridSize-1; x++) { 01438 int fx = x*2+1; 01439 int fy = y*2; 01440 void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y); 01441 void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y); 01442 void *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy-1); 01443 void *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy+1); 01444 void *co = FACE_getIFCo(f, nextLvl, S, fx, fy); 01445 01446 VertDataAvg4(co, co0, co1, co2, co3); 01447 } 01448 } 01449 } 01450 } 01451 01452 /* exterior edge midpoints 01453 * o old exterior edge points 01454 * o new interior face midpoints 01455 */ 01456 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) { 01457 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx]; 01458 float sharpness = EDGE_getSharpness(e, curLvl); 01459 int x, j; 01460 01461 if (_edge_isBoundary(e) || sharpness > 1.0f) { 01462 for (x=0; x<edgeSize-1; x++) { 01463 int fx = x*2 + 1; 01464 void *co0 = EDGE_getCo(e, curLvl, x+0); 01465 void *co1 = EDGE_getCo(e, curLvl, x+1); 01466 void *co = EDGE_getCo(e, nextLvl, fx); 01467 01468 VertDataCopy(co, co0); 01469 VertDataAdd(co, co1); 01470 VertDataMulN(co, 0.5f); 01471 } 01472 } else { 01473 for (x=0; x<edgeSize-1; x++) { 01474 int fx = x*2 + 1; 01475 void *co0 = EDGE_getCo(e, curLvl, x+0); 01476 void *co1 = EDGE_getCo(e, curLvl, x+1); 01477 void *co = EDGE_getCo(e, nextLvl, fx); 01478 int numFaces = 0; 01479 01480 VertDataCopy(q, co0); 01481 VertDataAdd(q, co1); 01482 01483 for (j=0; j<e->numFaces; j++) { 01484 CCGFace *f = e->faces[j]; 01485 VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize)); 01486 numFaces++; 01487 } 01488 01489 VertDataMulN(q, 1.0f/(2.0f+numFaces)); 01490 01491 VertDataCopy(r, co0); 01492 VertDataAdd(r, co1); 01493 VertDataMulN(r, 0.5f); 01494 01495 VertDataCopy(co, q); 01496 VertDataSub(r, q); 01497 VertDataMulN(r, sharpness); 01498 VertDataAdd(co, r); 01499 } 01500 } 01501 } 01502 01503 /* exterior vertex shift 01504 * o old vertex points (shifting) 01505 * o old exterior edge points 01506 * o new interior face midpoints 01507 */ 01508 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) { 01509 CCGVert *v = (CCGVert*) effectedV[ptrIdx]; 01510 void *co = VERT_getCo(v, curLvl); 01511 void *nCo = VERT_getCo(v, nextLvl); 01512 int sharpCount = 0, allSharp = 1; 01513 float avgSharpness = 0.0; 01514 int j, seam = VERT_seam(v), seamEdges = 0; 01515 01516 for (j=0; j<v->numEdges; j++) { 01517 CCGEdge *e = v->edges[j]; 01518 float sharpness = EDGE_getSharpness(e, curLvl); 01519 01520 if (seam && _edge_isBoundary(e)) 01521 seamEdges++; 01522 01523 if (sharpness!=0.0f) { 01524 sharpCount++; 01525 avgSharpness += sharpness; 01526 } else { 01527 allSharp = 0; 01528 } 01529 } 01530 01531 if(sharpCount) { 01532 avgSharpness /= sharpCount; 01533 if (avgSharpness > 1.0f) { 01534 avgSharpness = 1.0f; 01535 } 01536 } 01537 01538 if (seamEdges < 2 || seamEdges != v->numEdges) 01539 seam = 0; 01540 01541 if (!v->numEdges) { 01542 VertDataCopy(nCo, co); 01543 } else if (_vert_isBoundary(v)) { 01544 int numBoundary = 0; 01545 01546 VertDataZero(r); 01547 for (j=0; j<v->numEdges; j++) { 01548 CCGEdge *e = v->edges[j]; 01549 if (_edge_isBoundary(e)) { 01550 VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); 01551 numBoundary++; 01552 } 01553 } 01554 01555 VertDataCopy(nCo, co); 01556 VertDataMulN(nCo, 0.75f); 01557 VertDataMulN(r, 0.25f/numBoundary); 01558 VertDataAdd(nCo, r); 01559 } else { 01560 int cornerIdx = (1 + (1<<(curLvl))) - 2; 01561 int numEdges = 0, numFaces = 0; 01562 01563 VertDataZero(q); 01564 for (j=0; j<v->numFaces; j++) { 01565 CCGFace *f = v->faces[j]; 01566 VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx)); 01567 numFaces++; 01568 } 01569 VertDataMulN(q, 1.0f/numFaces); 01570 VertDataZero(r); 01571 for (j=0; j<v->numEdges; j++) { 01572 CCGEdge *e = v->edges[j]; 01573 VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize)); 01574 numEdges++; 01575 } 01576 VertDataMulN(r, 1.0f/numEdges); 01577 01578 VertDataCopy(nCo, co); 01579 VertDataMulN(nCo, numEdges-2.0f); 01580 VertDataAdd(nCo, q); 01581 VertDataAdd(nCo, r); 01582 VertDataMulN(nCo, 1.0f/numEdges); 01583 } 01584 01585 if ((sharpCount>1 && v->numFaces) || seam) { 01586 VertDataZero(q); 01587 01588 if (seam) { 01589 avgSharpness = 1.0f; 01590 sharpCount = seamEdges; 01591 allSharp = 1; 01592 } 01593 01594 for (j=0; j<v->numEdges; j++) { 01595 CCGEdge *e = v->edges[j]; 01596 float sharpness = EDGE_getSharpness(e, curLvl); 01597 01598 if (seam) { 01599 if (_edge_isBoundary(e)) 01600 VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); 01601 } else if (sharpness != 0.0f) { 01602 VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize)); 01603 } 01604 } 01605 01606 VertDataMulN(q, (float) 1/sharpCount); 01607 01608 if (sharpCount!=2 || allSharp) { 01609 // q = q + (co-q)*avgSharpness 01610 VertDataCopy(r, co); 01611 VertDataSub(r, q); 01612 VertDataMulN(r, avgSharpness); 01613 VertDataAdd(q, r); 01614 } 01615 01616 // r = co*.75 + q*.25 01617 VertDataCopy(r, co); 01618 VertDataMulN(r, .75f); 01619 VertDataMulN(q, .25f); 01620 VertDataAdd(r, q); 01621 01622 // nCo = nCo + (r-nCo)*avgSharpness 01623 VertDataSub(r, nCo); 01624 VertDataMulN(r, avgSharpness); 01625 VertDataAdd(nCo, r); 01626 } 01627 } 01628 01629 /* exterior edge interior shift 01630 * o old exterior edge midpoints (shifting) 01631 * o old exterior edge midpoints 01632 * o new interior face midpoints 01633 */ 01634 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) { 01635 CCGEdge *e = (CCGEdge*) effectedE[ptrIdx]; 01636 float sharpness = EDGE_getSharpness(e, curLvl); 01637 int sharpCount = 0; 01638 float avgSharpness = 0.0; 01639 int x, j; 01640 01641 if (sharpness!=0.0f) { 01642 sharpCount = 2; 01643 avgSharpness += sharpness; 01644 01645 if (avgSharpness > 1.0f) { 01646 avgSharpness = 1.0f; 01647 } 01648 } else { 01649 sharpCount = 0; 01650 avgSharpness = 0; 01651 } 01652 01653 if (_edge_isBoundary(e) && (!e->numFaces || sharpCount<2)) { 01654 for (x=1; x<edgeSize-1; x++) { 01655 int fx = x*2; 01656 void *co = EDGE_getCo(e, curLvl, x); 01657 void *nCo = EDGE_getCo(e, nextLvl, fx); 01658 VertDataCopy(r, EDGE_getCo(e, curLvl, x-1)); 01659 VertDataAdd(r, EDGE_getCo(e, curLvl, x+1)); 01660 VertDataMulN(r, 0.5f); 01661 VertDataCopy(nCo, co); 01662 VertDataMulN(nCo, 0.75f); 01663 VertDataMulN(r, 0.25f); 01664 VertDataAdd(nCo, r); 01665 } 01666 } else { 01667 for (x=1; x<edgeSize-1; x++) { 01668 int fx = x*2; 01669 void *co = EDGE_getCo(e, curLvl, x); 01670 void *nCo = EDGE_getCo(e, nextLvl, fx); 01671 int numFaces = 0; 01672 01673 VertDataZero(q); 01674 VertDataZero(r); 01675 VertDataAdd(r, EDGE_getCo(e, curLvl, x-1)); 01676 VertDataAdd(r, EDGE_getCo(e, curLvl, x+1)); 01677 for (j=0; j<e->numFaces; j++) { 01678 CCGFace *f = e->faces[j]; 01679 VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize)); 01680 VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize)); 01681 01682 VertDataAdd(r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize)); 01683 numFaces++; 01684 } 01685 VertDataMulN(q, 1.0f/(numFaces*2.0f)); 01686 VertDataMulN(r, 1.0f/(2.0f + numFaces)); 01687 01688 VertDataCopy(nCo, co); 01689 VertDataMulN(nCo, (float) numFaces); 01690 VertDataAdd(nCo, q); 01691 VertDataAdd(nCo, r); 01692 VertDataMulN(nCo, 1.0f/(2+numFaces)); 01693 01694 if (sharpCount==2) { 01695 VertDataCopy(q, co); 01696 VertDataMulN(q, 6.0f); 01697 VertDataAdd(q, EDGE_getCo(e, curLvl, x-1)); 01698 VertDataAdd(q, EDGE_getCo(e, curLvl, x+1)); 01699 VertDataMulN(q, 1/8.0f); 01700 01701 VertDataSub(q, nCo); 01702 VertDataMulN(q, avgSharpness); 01703 VertDataAdd(nCo, q); 01704 } 01705 } 01706 } 01707 } 01708 01709 #pragma omp parallel private(ptrIdx) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT) 01710 { 01711 void *q, *r; 01712 01713 #pragma omp critical 01714 { 01715 q = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf q"); 01716 r = MEM_mallocN(ss->meshIFC.vertDataSize, "CCGSubsurf r"); 01717 } 01718 01719 #pragma omp for schedule(static) 01720 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) { 01721 CCGFace *f = (CCGFace*) effectedF[ptrIdx]; 01722 int S, x, y; 01723 01724 /* interior center point shift 01725 * o old face center point (shifting) 01726 * o old interior edge points 01727 * o new interior face midpoints 01728 */ 01729 VertDataZero(q); 01730 for (S=0; S<f->numVerts; S++) { 01731 VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1)); 01732 } 01733 VertDataMulN(q, 1.0f/f->numVerts); 01734 VertDataZero(r); 01735 for (S=0; S<f->numVerts; S++) { 01736 VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1)); 01737 } 01738 VertDataMulN(r, 1.0f/f->numVerts); 01739 01740 VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f); 01741 VertDataAdd(FACE_getCenterData(f), q); 01742 VertDataAdd(FACE_getCenterData(f), r); 01743 VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts); 01744 01745 for (S=0; S<f->numVerts; S++) { 01746 /* interior face shift 01747 * o old interior face point (shifting) 01748 * o new interior edge midpoints 01749 * o new interior face midpoints 01750 */ 01751 for (x=1; x<gridSize-1; x++) { 01752 for (y=1; y<gridSize-1; y++) { 01753 int fx = x*2; 01754 int fy = y*2; 01755 void *co = FACE_getIFCo(f, curLvl, S, x, y); 01756 void *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy); 01757 01758 VertDataAvg4(q, FACE_getIFCo(f, nextLvl, S, fx-1, fy-1), 01759 FACE_getIFCo(f, nextLvl, S, fx+1, fy-1), 01760 FACE_getIFCo(f, nextLvl, S, fx+1, fy+1), 01761 FACE_getIFCo(f, nextLvl, S, fx-1, fy+1)); 01762 01763 VertDataAvg4(r, FACE_getIFCo(f, nextLvl, S, fx-1, fy+0), 01764 FACE_getIFCo(f, nextLvl, S, fx+1, fy+0), 01765 FACE_getIFCo(f, nextLvl, S, fx+0, fy-1), 01766 FACE_getIFCo(f, nextLvl, S, fx+0, fy+1)); 01767 01768 VertDataCopy(nCo, co); 01769 VertDataSub(nCo, q); 01770 VertDataMulN(nCo, 0.25f); 01771 VertDataAdd(nCo, r); 01772 } 01773 } 01774 01775 /* interior edge interior shift 01776 * o old interior edge point (shifting) 01777 * o new interior edge midpoints 01778 * o new interior face midpoints 01779 */ 01780 for (x=1; x<gridSize-1; x++) { 01781 int fx = x*2; 01782 void *co = FACE_getIECo(f, curLvl, S, x); 01783 void *nCo = FACE_getIECo(f, nextLvl, S, fx); 01784 01785 VertDataAvg4(q, FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx-1), 01786 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx+1), 01787 FACE_getIFCo(f, nextLvl, S, fx+1, +1), 01788 FACE_getIFCo(f, nextLvl, S, fx-1, +1)); 01789 01790 VertDataAvg4(r, FACE_getIECo(f, nextLvl, S, fx-1), 01791 FACE_getIECo(f, nextLvl, S, fx+1), 01792 FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx), 01793 FACE_getIFCo(f, nextLvl, S, fx, 1)); 01794 01795 VertDataCopy(nCo, co); 01796 VertDataSub(nCo, q); 01797 VertDataMulN(nCo, 0.25f); 01798 VertDataAdd(nCo, r); 01799 } 01800 } 01801 } 01802 01803 #pragma omp critical 01804 { 01805 MEM_freeN(q); 01806 MEM_freeN(r); 01807 } 01808 } 01809 01810 /* copy down */ 01811 edgeSize = 1 + (1<<(nextLvl)); 01812 gridSize = 1 + (1<<((nextLvl)-1)); 01813 cornerIdx = gridSize-1; 01814 01815 #pragma omp parallel for private(i) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT) 01816 for (i=0; i<numEffectedE; i++) { 01817 CCGEdge *e = effectedE[i]; 01818 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl)); 01819 VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl)); 01820 } 01821 01822 #pragma omp parallel for private(i) if(numEffectedF*edgeSize*edgeSize*4 >= CCG_OMP_LIMIT) 01823 for (i=0; i<numEffectedF; i++) { 01824 CCGFace *f = effectedF[i]; 01825 int S, x; 01826 01827 for (S=0; S<f->numVerts; S++) { 01828 CCGEdge *e = FACE_getEdges(f)[S]; 01829 CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts]; 01830 01831 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f)); 01832 VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f)); 01833 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl)); 01834 VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx)); 01835 for (x=1; x<gridSize-1; x++) { 01836 void *co = FACE_getIECo(f, nextLvl, S, x); 01837 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co); 01838 VertDataCopy(FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 0, x), co); 01839 } 01840 for (x=0; x<gridSize-1; x++) { 01841 int eI = gridSize-1-x; 01842 VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize)); 01843 VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize)); 01844 } 01845 } 01846 } 01847 } 01848 01849 01850 static void ccgSubSurf__sync(CCGSubSurf *ss) { 01851 CCGVert **effectedV; 01852 CCGEdge **effectedE; 01853 CCGFace **effectedF; 01854 int numEffectedV, numEffectedE, numEffectedF; 01855 int subdivLevels = ss->subdivLevels; 01856 int vertDataSize = ss->meshIFC.vertDataSize; 01857 int i, j, ptrIdx, S; 01858 int curLvl, nextLvl; 01859 void *q = ss->q, *r = ss->r; 01860 01861 effectedV = MEM_mallocN(sizeof(*effectedV)*ss->vMap->numEntries, "CCGSubsurf effectedV"); 01862 effectedE = MEM_mallocN(sizeof(*effectedE)*ss->eMap->numEntries, "CCGSubsurf effectedE"); 01863 effectedF = MEM_mallocN(sizeof(*effectedF)*ss->fMap->numEntries, "CCGSubsurf effectedF"); 01864 numEffectedV = numEffectedE = numEffectedF = 0; 01865 for (i=0; i<ss->vMap->curSize; i++) { 01866 CCGVert *v = (CCGVert*) ss->vMap->buckets[i]; 01867 for (; v; v = v->next) { 01868 if (v->flags&Vert_eEffected) { 01869 effectedV[numEffectedV++] = v; 01870 01871 for (j=0; j<v->numEdges; j++) { 01872 CCGEdge *e = v->edges[j]; 01873 if (!(e->flags&Edge_eEffected)) { 01874 effectedE[numEffectedE++] = e; 01875 e->flags |= Edge_eEffected; 01876 } 01877 } 01878 01879 for (j=0; j<v->numFaces; j++) { 01880 CCGFace *f = v->faces[j]; 01881 if (!(f->flags&Face_eEffected)) { 01882 effectedF[numEffectedF++] = f; 01883 f->flags |= Face_eEffected; 01884 } 01885 } 01886 } 01887 } 01888 } 01889 01890 curLvl = 0; 01891 nextLvl = curLvl+1; 01892 01893 for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) { 01894 CCGFace *f = effectedF[ptrIdx]; 01895 void *co = FACE_getCenterData(f); 01896 VertDataZero(co); 01897 for (i=0; i<f->numVerts; i++) { 01898 VertDataAdd(co, VERT_getCo(FACE_getVerts(f)[i], curLvl)); 01899 } 01900 VertDataMulN(co, 1.0f/f->numVerts); 01901 01902 f->flags = 0; 01903 } 01904 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) { 01905 CCGEdge *e = effectedE[ptrIdx]; 01906 void *co = EDGE_getCo(e, nextLvl, 1); 01907 float sharpness = EDGE_getSharpness(e, curLvl); 01908 01909 if (_edge_isBoundary(e) || sharpness >= 1.0f) { 01910 VertDataCopy(co, VERT_getCo(e->v0, curLvl)); 01911 VertDataAdd(co, VERT_getCo(e->v1, curLvl)); 01912 VertDataMulN(co, 0.5f); 01913 } else { 01914 int numFaces = 0; 01915 VertDataCopy(q, VERT_getCo(e->v0, curLvl)); 01916 VertDataAdd(q, VERT_getCo(e->v1, curLvl)); 01917 for (i=0; i<e->numFaces; i++) { 01918 CCGFace *f = e->faces[i]; 01919 VertDataAdd(q, FACE_getCenterData(f)); 01920 numFaces++; 01921 } 01922 VertDataMulN(q, 1.0f/(2.0f+numFaces)); 01923 01924 VertDataCopy(r, VERT_getCo(e->v0, curLvl)); 01925 VertDataAdd(r, VERT_getCo(e->v1, curLvl)); 01926 VertDataMulN(r, 0.5f); 01927 01928 VertDataCopy(co, q); 01929 VertDataSub(r, q); 01930 VertDataMulN(r, sharpness); 01931 VertDataAdd(co, r); 01932 } 01933 01934 // edge flags cleared later 01935 } 01936 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) { 01937 CCGVert *v = effectedV[ptrIdx]; 01938 void *co = VERT_getCo(v, curLvl); 01939 void *nCo = VERT_getCo(v, nextLvl); 01940 int sharpCount = 0, allSharp = 1; 01941 float avgSharpness = 0.0; 01942 int seam = VERT_seam(v), seamEdges = 0; 01943 01944 for (i=0; i<v->numEdges; i++) { 01945 CCGEdge *e = v->edges[i]; 01946 float sharpness = EDGE_getSharpness(e, curLvl); 01947 01948 if (seam && _edge_isBoundary(e)) 01949 seamEdges++; 01950 01951 if (sharpness!=0.0f) { 01952 sharpCount++; 01953 avgSharpness += sharpness; 01954 } else { 01955 allSharp = 0; 01956 } 01957 } 01958 01959 if(sharpCount) { 01960 avgSharpness /= sharpCount; 01961 if (avgSharpness > 1.0f) { 01962 avgSharpness = 1.0f; 01963 } 01964 } 01965 01966 if (seamEdges < 2 || seamEdges != v->numEdges) 01967 seam = 0; 01968 01969 if (!v->numEdges) { 01970 VertDataCopy(nCo, co); 01971 } else if (_vert_isBoundary(v)) { 01972 int numBoundary = 0; 01973 01974 VertDataZero(r); 01975 for (i=0; i<v->numEdges; i++) { 01976 CCGEdge *e = v->edges[i]; 01977 if (_edge_isBoundary(e)) { 01978 VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl)); 01979 numBoundary++; 01980 } 01981 } 01982 VertDataCopy(nCo, co); 01983 VertDataMulN(nCo, 0.75f); 01984 VertDataMulN(r, 0.25f/numBoundary); 01985 VertDataAdd(nCo, r); 01986 } else { 01987 int numEdges = 0, numFaces = 0; 01988 01989 VertDataZero(q); 01990 for (i=0; i<v->numFaces; i++) { 01991 CCGFace *f = v->faces[i]; 01992 VertDataAdd(q, FACE_getCenterData(f)); 01993 numFaces++; 01994 } 01995 VertDataMulN(q, 1.0f/numFaces); 01996 VertDataZero(r); 01997 for (i=0; i<v->numEdges; i++) { 01998 CCGEdge *e = v->edges[i]; 01999 VertDataAdd(r, VERT_getCo(_edge_getOtherVert(e, v), curLvl)); 02000 numEdges++; 02001 } 02002 VertDataMulN(r, 1.0f/numEdges); 02003 02004 VertDataCopy(nCo, co); 02005 VertDataMulN(nCo, numEdges-2.0f); 02006 VertDataAdd(nCo, q); 02007 VertDataAdd(nCo, r); 02008 VertDataMulN(nCo, 1.0f/numEdges); 02009 } 02010 02011 if (sharpCount>1 || seam) { 02012 VertDataZero(q); 02013 02014 if (seam) { 02015 avgSharpness = 1.0f; 02016 sharpCount = seamEdges; 02017 allSharp = 1; 02018 } 02019 02020 for (i=0; i<v->numEdges; i++) { 02021 CCGEdge *e = v->edges[i]; 02022 float sharpness = EDGE_getSharpness(e, curLvl); 02023 02024 if (seam) { 02025 if (_edge_isBoundary(e)) { 02026 CCGVert *oV = _edge_getOtherVert(e, v); 02027 VertDataAdd(q, VERT_getCo(oV, curLvl)); 02028 } 02029 } else if (sharpness != 0.0f) { 02030 CCGVert *oV = _edge_getOtherVert(e, v); 02031 VertDataAdd(q, VERT_getCo(oV, curLvl)); 02032 } 02033 } 02034 02035 VertDataMulN(q, (float) 1/sharpCount); 02036 02037 if (sharpCount!=2 || allSharp) { 02038 // q = q + (co-q)*avgSharpness 02039 VertDataCopy(r, co); 02040 VertDataSub(r, q); 02041 VertDataMulN(r, avgSharpness); 02042 VertDataAdd(q, r); 02043 } 02044 02045 // r = co*.75 + q*.25 02046 VertDataCopy(r, co); 02047 VertDataMulN(r, 0.75f); 02048 VertDataMulN(q, 0.25f); 02049 VertDataAdd(r, q); 02050 02051 // nCo = nCo + (r-nCo)*avgSharpness 02052 VertDataSub(r, nCo); 02053 VertDataMulN(r, avgSharpness); 02054 VertDataAdd(nCo, r); 02055 } 02056 02057 // vert flags cleared later 02058 } 02059 02060 if (ss->useAgeCounts) { 02061 for (i=0; i<numEffectedV; i++) { 02062 CCGVert *v = effectedV[i]; 02063 byte *userData = ccgSubSurf_getVertUserData(ss, v); 02064 *((int*) &userData[ss->vertUserAgeOffset]) = ss->currentAge; 02065 } 02066 02067 for (i=0; i<numEffectedE; i++) { 02068 CCGEdge *e = effectedE[i]; 02069 byte *userData = ccgSubSurf_getEdgeUserData(ss, e); 02070 *((int*) &userData[ss->edgeUserAgeOffset]) = ss->currentAge; 02071 } 02072 02073 for (i=0; i<numEffectedF; i++) { 02074 CCGFace *f = effectedF[i]; 02075 byte *userData = ccgSubSurf_getFaceUserData(ss, f); 02076 *((int*) &userData[ss->faceUserAgeOffset]) = ss->currentAge; 02077 } 02078 } 02079 02080 for (i=0; i<numEffectedE; i++) { 02081 CCGEdge *e = effectedE[i]; 02082 VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl)); 02083 VertDataCopy(EDGE_getCo(e, nextLvl, 2), VERT_getCo(e->v1, nextLvl)); 02084 } 02085 for (i=0; i<numEffectedF; i++) { 02086 CCGFace *f = effectedF[i]; 02087 for (S=0; S<f->numVerts; S++) { 02088 CCGEdge *e = FACE_getEdges(f)[S]; 02089 CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts]; 02090 02091 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f)); 02092 VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f)); 02093 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 1), VERT_getCo(FACE_getVerts(f)[S], nextLvl)); 02094 VertDataCopy(FACE_getIECo(f, nextLvl, S, 1), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, 1)); 02095 02096 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 1, 0), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize)); 02097 VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 1), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, 1, vertDataSize)); 02098 } 02099 } 02100 02101 for (curLvl=1; curLvl<subdivLevels; curLvl++) { 02102 ccgSubSurf__calcSubdivLevel(ss, 02103 effectedV, effectedE, effectedF, 02104 numEffectedV, numEffectedE, numEffectedF, curLvl); 02105 } 02106 02107 if (ss->calcVertNormals) 02108 ccgSubSurf__calcVertNormals(ss, 02109 effectedV, effectedE, effectedF, 02110 numEffectedV, numEffectedE, numEffectedF); 02111 02112 for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) { 02113 CCGVert *v = effectedV[ptrIdx]; 02114 v->flags = 0; 02115 } 02116 for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) { 02117 CCGEdge *e = effectedE[ptrIdx]; 02118 e->flags = 0; 02119 } 02120 02121 MEM_freeN(effectedF); 02122 MEM_freeN(effectedE); 02123 MEM_freeN(effectedV); 02124 } 02125 02126 static void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces) 02127 { 02128 CCGFace **array; 02129 int i, num; 02130 02131 if(!*faces) { 02132 array = MEM_mallocN(sizeof(*array)*ss->fMap->numEntries, "CCGSubsurf allFaces"); 02133 num = 0; 02134 for (i=0; i<ss->fMap->curSize; i++) { 02135 CCGFace *f = (CCGFace*) ss->fMap->buckets[i]; 02136 02137 for (; f; f = f->next) 02138 array[num++] = f; 02139 } 02140 02141 *faces = array; 02142 *numFaces = num; 02143 *freeFaces= 1; 02144 } 02145 else 02146 *freeFaces= 0; 02147 } 02148 02149 static void ccgSubSurf__effectedFaceNeighbours(CCGSubSurf *ss, CCGFace **faces, int numFaces, CCGVert ***verts, int *numVerts, CCGEdge ***edges, int *numEdges) 02150 { 02151 CCGVert **arrayV; 02152 CCGEdge **arrayE; 02153 int numV, numE, i, j; 02154 02155 arrayV = MEM_mallocN(sizeof(*arrayV)*ss->vMap->numEntries, "CCGSubsurf arrayV"); 02156 arrayE = MEM_mallocN(sizeof(*arrayE)*ss->eMap->numEntries, "CCGSubsurf arrayV"); 02157 numV = numE = 0; 02158 02159 for (i=0; i<numFaces; i++) { 02160 CCGFace *f = faces[i]; 02161 f->flags |= Face_eEffected; 02162 } 02163 02164 for (i=0; i<ss->vMap->curSize; i++) { 02165 CCGVert *v = (CCGVert*) ss->vMap->buckets[i]; 02166 02167 for (; v; v = v->next) { 02168 for(j=0; j<v->numFaces; j++) 02169 if(!(v->faces[j]->flags & Face_eEffected)) 02170 break; 02171 02172 if(j == v->numFaces) { 02173 arrayV[numV++] = v; 02174 v->flags |= Vert_eEffected; 02175 } 02176 } 02177 } 02178 02179 for (i=0; i<ss->eMap->curSize; i++) { 02180 CCGEdge *e = (CCGEdge*) ss->eMap->buckets[i]; 02181 02182 for (; e; e = e->next) { 02183 for(j=0; j<e->numFaces; j++) 02184 if(!(e->faces[j]->flags & Face_eEffected)) 02185 break; 02186 02187 if(j == e->numFaces) { 02188 e->flags |= Edge_eEffected; 02189 arrayE[numE++] = e; 02190 } 02191 } 02192 } 02193 02194 *verts = arrayV; 02195 *numVerts = numV; 02196 *edges = arrayE; 02197 *numEdges = numE; 02198 } 02199 02200 /* copy face grid coordinates to other places */ 02201 CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF) 02202 { 02203 int i, S, x, gridSize, cornerIdx, subdivLevels; 02204 int vertDataSize = ss->meshIFC.vertDataSize, freeF; 02205 02206 subdivLevels = ss->subdivLevels; 02207 lvl = (lvl)? lvl: subdivLevels; 02208 gridSize = 1 + (1<<(lvl-1)); 02209 cornerIdx = gridSize-1; 02210 02211 ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF); 02212 02213 for (i=0; i<numEffectedF; i++) { 02214 CCGFace *f = effectedF[i]; 02215 02216 for (S=0; S<f->numVerts; S++) { 02217 CCGEdge *e = FACE_getEdges(f)[S]; 02218 CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts]; 02219 02220 VertDataCopy(FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0)); 02221 VertDataCopy(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx)); 02222 02223 for (x=0; x<gridSize; x++) 02224 VertDataCopy(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0)); 02225 02226 for (x=0; x<gridSize; x++) { 02227 int eI = gridSize-1-x; 02228 VertDataCopy(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, cornerIdx, x)); 02229 VertDataCopy(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, x, cornerIdx)); 02230 } 02231 } 02232 } 02233 02234 if(freeF) MEM_freeN(effectedF); 02235 02236 return eCCGError_None; 02237 } 02238 02239 /* copy other places to face grid coordinates */ 02240 CCGError ccgSubSurf_updateToFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF) 02241 { 02242 int i, S, x, gridSize, cornerIdx, subdivLevels; 02243 int vertDataSize = ss->meshIFC.vertDataSize, freeF; 02244 02245 subdivLevels = ss->subdivLevels; 02246 lvl = (lvl)? lvl: subdivLevels; 02247 gridSize = 1 + (1<<(lvl-1)); 02248 cornerIdx = gridSize-1; 02249 02250 ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF); 02251 02252 for (i=0; i<numEffectedF; i++) { 02253 CCGFace *f = effectedF[i]; 02254 02255 for (S=0; S<f->numVerts; S++) { 02256 int prevS = (S+f->numVerts-1)%f->numVerts; 02257 CCGEdge *e = FACE_getEdges(f)[S]; 02258 CCGEdge *prevE = FACE_getEdges(f)[prevS]; 02259 02260 for (x=0; x<gridSize; x++) { 02261 int eI = gridSize-1-x; 02262 VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize)); 02263 VertDataCopy(FACE_getIFCo(f, lvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize)); 02264 } 02265 02266 for (x=1; x<gridSize-1; x++) { 02267 VertDataCopy(FACE_getIFCo(f, lvl, S, 0, x), FACE_getIECo(f, lvl, prevS, x)); 02268 VertDataCopy(FACE_getIFCo(f, lvl, S, x, 0), FACE_getIECo(f, lvl, S, x)); 02269 } 02270 02271 VertDataCopy(FACE_getIFCo(f, lvl, S, 0, 0), FACE_getCenterData(f)); 02272 VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], lvl)); 02273 } 02274 } 02275 02276 if(freeF) MEM_freeN(effectedF); 02277 02278 return eCCGError_None; 02279 } 02280 02281 /* stitch together face grids, averaging coordinates at edges 02282 and vertices, for multires displacements */ 02283 CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF) 02284 { 02285 CCGVert **effectedV; 02286 CCGEdge **effectedE; 02287 int numEffectedV, numEffectedE, freeF; 02288 int i, S, x, gridSize, cornerIdx, subdivLevels, edgeSize; 02289 int vertDataSize = ss->meshIFC.vertDataSize; 02290 02291 subdivLevels = ss->subdivLevels; 02292 lvl = (lvl)? lvl: subdivLevels; 02293 gridSize = 1 + (1<<(lvl-1)); 02294 edgeSize = 1 + (1<<lvl); 02295 cornerIdx = gridSize-1; 02296 02297 ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF); 02298 ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF, 02299 &effectedV, &numEffectedV, &effectedE, &numEffectedE); 02300 02301 /* zero */ 02302 for (i=0; i<numEffectedV; i++) { 02303 CCGVert *v = effectedV[i]; 02304 if(v->numFaces) 02305 VertDataZero(VERT_getCo(v, lvl)); 02306 } 02307 02308 for (i=0; i<numEffectedE; i++) { 02309 CCGEdge *e = effectedE[i]; 02310 02311 if(e->numFaces) 02312 for (x=0; x<edgeSize; x++) 02313 VertDataZero(EDGE_getCo(e, lvl, x)); 02314 } 02315 02316 /* add */ 02317 for (i=0; i<numEffectedF; i++) { 02318 CCGFace *f = effectedF[i]; 02319 02320 VertDataZero(FACE_getCenterData(f)); 02321 02322 for (S=0; S<f->numVerts; S++) 02323 for (x=0; x<gridSize; x++) 02324 VertDataZero(FACE_getIECo(f, lvl, S, x)); 02325 02326 for (S=0; S<f->numVerts; S++) { 02327 int prevS = (S+f->numVerts-1)%f->numVerts; 02328 CCGEdge *e = FACE_getEdges(f)[S]; 02329 CCGEdge *prevE = FACE_getEdges(f)[prevS]; 02330 02331 VertDataAdd(FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0)); 02332 if (FACE_getVerts(f)[S]->flags&Vert_eEffected) 02333 VertDataAdd(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx)); 02334 02335 for (x=1; x<gridSize-1; x++) { 02336 VertDataAdd(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0)); 02337 VertDataAdd(FACE_getIECo(f, lvl, prevS, x), FACE_getIFCo(f, lvl, S, 0, x)); 02338 } 02339 02340 for (x=0; x<gridSize-1; x++) { 02341 int eI = gridSize-1-x; 02342 if (FACE_getEdges(f)[S]->flags&Edge_eEffected) 02343 VertDataAdd(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, cornerIdx, x)); 02344 if (FACE_getEdges(f)[prevS]->flags&Edge_eEffected) 02345 if(x != 0) 02346 VertDataAdd(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, x, cornerIdx)); 02347 } 02348 } 02349 } 02350 02351 /* average */ 02352 for (i=0; i<numEffectedV; i++) { 02353 CCGVert *v = effectedV[i]; 02354 if(v->numFaces) 02355 VertDataMulN(VERT_getCo(v, lvl), 1.0f/v->numFaces); 02356 } 02357 02358 for (i=0; i<numEffectedE; i++) { 02359 CCGEdge *e = effectedE[i]; 02360 02361 VertDataCopy(EDGE_getCo(e, lvl, 0), VERT_getCo(e->v0, lvl)); 02362 VertDataCopy(EDGE_getCo(e, lvl, edgeSize-1), VERT_getCo(e->v1, lvl)); 02363 02364 if(e->numFaces) 02365 for (x=1; x<edgeSize-1; x++) 02366 VertDataMulN(EDGE_getCo(e, lvl, x), 1.0f/e->numFaces); 02367 } 02368 02369 /* copy */ 02370 for (i=0; i<numEffectedF; i++) { 02371 CCGFace *f = effectedF[i]; 02372 02373 VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts); 02374 02375 for (S=0; S<f->numVerts; S++) 02376 for (x=1; x<gridSize-1; x++) 02377 VertDataMulN(FACE_getIECo(f, lvl, S, x), 0.5f); 02378 02379 for (S=0; S<f->numVerts; S++) { 02380 int prevS = (S+f->numVerts-1)%f->numVerts; 02381 CCGEdge *e = FACE_getEdges(f)[S]; 02382 CCGEdge *prevE = FACE_getEdges(f)[prevS]; 02383 02384 VertDataCopy(FACE_getIFCo(f, lvl, S, 0, 0), FACE_getCenterData(f)); 02385 VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], lvl)); 02386 02387 for (x=1; x<gridSize-1; x++) { 02388 VertDataCopy(FACE_getIFCo(f, lvl, S, x, 0), FACE_getIECo(f, lvl, S, x)); 02389 VertDataCopy(FACE_getIFCo(f, lvl, S, 0, x), FACE_getIECo(f, lvl, prevS, x)); 02390 } 02391 02392 for (x=0; x<gridSize-1; x++) { 02393 int eI = gridSize-1-x; 02394 VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize)); 02395 VertDataCopy(FACE_getIFCo(f, lvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize)); 02396 } 02397 02398 VertDataCopy(FACE_getIECo(f, lvl, S, 0), FACE_getCenterData(f)); 02399 VertDataCopy(FACE_getIECo(f, lvl, S, gridSize-1), FACE_getIFCo(f, lvl, S, gridSize-1, 0)); 02400 } 02401 } 02402 02403 for (i=0; i<numEffectedV; i++) 02404 effectedV[i]->flags = 0; 02405 for (i=0; i<numEffectedE; i++) 02406 effectedE[i]->flags = 0; 02407 for (i=0; i<numEffectedF; i++) 02408 effectedF[i]->flags = 0; 02409 02410 MEM_freeN(effectedE); 02411 MEM_freeN(effectedV); 02412 if(freeF) MEM_freeN(effectedF); 02413 02414 return eCCGError_None; 02415 } 02416 02417 /* update normals for specified faces */ 02418 CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF) { 02419 CCGVert **effectedV; 02420 CCGEdge **effectedE; 02421 int i, numEffectedV, numEffectedE, freeF; 02422 02423 ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF); 02424 ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF, 02425 &effectedV, &numEffectedV, &effectedE, &numEffectedE); 02426 02427 if (ss->calcVertNormals) 02428 ccgSubSurf__calcVertNormals(ss, 02429 effectedV, effectedE, effectedF, 02430 numEffectedV, numEffectedE, numEffectedF); 02431 02432 for (i=0; i<numEffectedV; i++) 02433 effectedV[i]->flags = 0; 02434 for (i=0; i<numEffectedE; i++) 02435 effectedE[i]->flags = 0; 02436 for (i=0; i<numEffectedF; i++) 02437 effectedF[i]->flags = 0; 02438 02439 MEM_freeN(effectedE); 02440 MEM_freeN(effectedV); 02441 if(freeF) MEM_freeN(effectedF); 02442 02443 return eCCGError_None; 02444 } 02445 02446 /* compute subdivision levels from a given starting point, used by 02447 multires subdivide/propagate, by filling in coordinates at a 02448 certain level, and then subdividing that up to the highest level */ 02449 CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF) 02450 { 02451 CCGVert **effectedV; 02452 CCGEdge **effectedE; 02453 int numEffectedV, numEffectedE, freeF, i; 02454 int curLvl, subdivLevels = ss->subdivLevels; 02455 02456 ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF); 02457 ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF, 02458 &effectedV, &numEffectedV, &effectedE, &numEffectedE); 02459 02460 for (curLvl=lvl; curLvl<subdivLevels; curLvl++) { 02461 ccgSubSurf__calcSubdivLevel(ss, 02462 effectedV, effectedE, effectedF, 02463 numEffectedV, numEffectedE, numEffectedF, curLvl); 02464 } 02465 02466 for (i=0; i<numEffectedV; i++) 02467 effectedV[i]->flags = 0; 02468 for (i=0; i<numEffectedE; i++) 02469 effectedE[i]->flags = 0; 02470 for (i=0; i<numEffectedF; i++) 02471 effectedF[i]->flags = 0; 02472 02473 MEM_freeN(effectedE); 02474 MEM_freeN(effectedV); 02475 if(freeF) MEM_freeN(effectedF); 02476 02477 return eCCGError_None; 02478 } 02479 02480 #undef VERT_getCo 02481 #undef EDGE_getCo 02482 #undef FACE_getIECo 02483 #undef FACE_getIFCo 02484 02485 /*** External API accessor functions ***/ 02486 02487 int ccgSubSurf_getNumVerts(const CCGSubSurf *ss) { 02488 return ss->vMap->numEntries; 02489 } 02490 int ccgSubSurf_getNumEdges(const CCGSubSurf *ss) { 02491 return ss->eMap->numEntries; 02492 } 02493 int ccgSubSurf_getNumFaces(const CCGSubSurf *ss) { 02494 return ss->fMap->numEntries; 02495 } 02496 02497 CCGVert *ccgSubSurf_getVert(CCGSubSurf *ss, CCGVertHDL v) { 02498 return (CCGVert*) _ehash_lookup(ss->vMap, v); 02499 } 02500 CCGEdge *ccgSubSurf_getEdge(CCGSubSurf *ss, CCGEdgeHDL e) { 02501 return (CCGEdge*) _ehash_lookup(ss->eMap, e); 02502 } 02503 CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f) { 02504 return (CCGFace*) _ehash_lookup(ss->fMap, f); 02505 } 02506 02507 int ccgSubSurf_getSubdivisionLevels(const CCGSubSurf *ss) { 02508 return ss->subdivLevels; 02509 } 02510 int ccgSubSurf_getEdgeSize(const CCGSubSurf *ss) { 02511 return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels); 02512 } 02513 int ccgSubSurf_getEdgeLevelSize(const CCGSubSurf *ss, int level) { 02514 if (level<1 || level>ss->subdivLevels) { 02515 return -1; 02516 } else { 02517 return 1 + (1<<level); 02518 } 02519 } 02520 int ccgSubSurf_getGridSize(const CCGSubSurf *ss) { 02521 return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels); 02522 } 02523 int ccgSubSurf_getGridLevelSize(const CCGSubSurf *ss, int level) { 02524 if (level<1 || level>ss->subdivLevels) { 02525 return -1; 02526 } else { 02527 return 1 + (1<<(level-1)); 02528 } 02529 } 02530 02531 /* Vert accessors */ 02532 02533 CCGVertHDL ccgSubSurf_getVertVertHandle(CCGVert *v) { 02534 return v->vHDL; 02535 } 02536 int ccgSubSurf_getVertAge(CCGSubSurf *ss, CCGVert *v) { 02537 if (ss->useAgeCounts) { 02538 byte *userData = ccgSubSurf_getVertUserData(ss, v); 02539 return ss->currentAge - *((int*) &userData[ss->vertUserAgeOffset]); 02540 } else { 02541 return 0; 02542 } 02543 } 02544 void *ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v) { 02545 return VERT_getLevelData(v) + ss->meshIFC.vertDataSize*(ss->subdivLevels+1); 02546 } 02547 int ccgSubSurf_getVertNumFaces(CCGVert *v) { 02548 return v->numFaces; 02549 } 02550 CCGFace *ccgSubSurf_getVertFace(CCGVert *v, int index) { 02551 if (index<0 || index>=v->numFaces) { 02552 return NULL; 02553 } else { 02554 return v->faces[index]; 02555 } 02556 } 02557 int ccgSubSurf_getVertNumEdges(CCGVert *v) { 02558 return v->numEdges; 02559 } 02560 CCGEdge *ccgSubSurf_getVertEdge(CCGVert *v, int index) { 02561 if (index<0 || index>=v->numEdges) { 02562 return NULL; 02563 } else { 02564 return v->edges[index]; 02565 } 02566 } 02567 void *ccgSubSurf_getVertData(CCGSubSurf *ss, CCGVert *v) { 02568 return ccgSubSurf_getVertLevelData(ss, v, ss->subdivLevels); 02569 } 02570 void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level) { 02571 if (level<0 || level>ss->subdivLevels) { 02572 return NULL; 02573 } else { 02574 return _vert_getCo(v, level, ss->meshIFC.vertDataSize); 02575 } 02576 } 02577 02578 /* Edge accessors */ 02579 02580 CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle(CCGEdge *e) { 02581 return e->eHDL; 02582 } 02583 int ccgSubSurf_getEdgeAge(CCGSubSurf *ss, CCGEdge *e) { 02584 if (ss->useAgeCounts) { 02585 byte *userData = ccgSubSurf_getEdgeUserData(ss, e); 02586 return ss->currentAge - *((int*) &userData[ss->edgeUserAgeOffset]); 02587 } else { 02588 return 0; 02589 } 02590 } 02591 void *ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e) { 02592 return EDGE_getLevelData(e) + ss->meshIFC.vertDataSize *((ss->subdivLevels+1) + (1<<(ss->subdivLevels+1))-1); 02593 } 02594 int ccgSubSurf_getEdgeNumFaces(CCGEdge *e) { 02595 return e->numFaces; 02596 } 02597 CCGFace *ccgSubSurf_getEdgeFace(CCGEdge *e, int index) { 02598 if (index<0 || index>=e->numFaces) { 02599 return NULL; 02600 } else { 02601 return e->faces[index]; 02602 } 02603 } 02604 CCGVert *ccgSubSurf_getEdgeVert0(CCGEdge *e) { 02605 return e->v0; 02606 } 02607 CCGVert *ccgSubSurf_getEdgeVert1(CCGEdge *e) { 02608 return e->v1; 02609 } 02610 void *ccgSubSurf_getEdgeDataArray(CCGSubSurf *ss, CCGEdge *e) { 02611 return ccgSubSurf_getEdgeData(ss, e, 0); 02612 } 02613 void *ccgSubSurf_getEdgeData(CCGSubSurf *ss, CCGEdge *e, int x) { 02614 return ccgSubSurf_getEdgeLevelData(ss, e, x, ss->subdivLevels); 02615 } 02616 void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level) { 02617 if (level<0 || level>ss->subdivLevels) { 02618 return NULL; 02619 } else { 02620 return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize); 02621 } 02622 } 02623 float ccgSubSurf_getEdgeCrease(CCGEdge *e) { 02624 return e->crease; 02625 } 02626 02627 /* Face accessors */ 02628 02629 CCGFaceHDL ccgSubSurf_getFaceFaceHandle(CCGSubSurf *UNUSED(ss), CCGFace *f) { 02630 return f->fHDL; 02631 } 02632 int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) { 02633 if (ss->useAgeCounts) { 02634 byte *userData = ccgSubSurf_getFaceUserData(ss, f); 02635 return ss->currentAge - *((int*) &userData[ss->faceUserAgeOffset]); 02636 } else { 02637 return 0; 02638 } 02639 } 02640 void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) { 02641 int maxGridSize = 1 + (1<<(ss->subdivLevels-1)); 02642 return FACE_getCenterData(f) + ss->meshIFC.vertDataSize *(1 + f->numVerts*maxGridSize + f->numVerts*maxGridSize*maxGridSize); 02643 } 02644 int ccgSubSurf_getFaceNumVerts(CCGFace *f) { 02645 return f->numVerts; 02646 } 02647 CCGVert *ccgSubSurf_getFaceVert(CCGSubSurf *UNUSED(ss), CCGFace *f, int index) { 02648 if (index<0 || index>=f->numVerts) { 02649 return NULL; 02650 } else { 02651 return FACE_getVerts(f)[index]; 02652 } 02653 } 02654 CCGEdge *ccgSubSurf_getFaceEdge(CCGSubSurf *UNUSED(ss), CCGFace *f, int index) { 02655 if (index<0 || index>=f->numVerts) { 02656 return NULL; 02657 } else { 02658 return FACE_getEdges(f)[index]; 02659 } 02660 } 02661 int ccgSubSurf_getFaceEdgeIndex(CCGFace *f, CCGEdge *e) { 02662 int i; 02663 02664 for (i=0; i<f->numVerts; i++) 02665 if (FACE_getEdges(f)[i]==e) 02666 return i; 02667 02668 return -1; 02669 } 02670 void *ccgSubSurf_getFaceCenterData(CCGFace *f) { 02671 return FACE_getCenterData(f); 02672 } 02673 void *ccgSubSurf_getFaceGridEdgeDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) { 02674 return ccgSubSurf_getFaceGridEdgeData(ss, f, gridIndex, 0); 02675 } 02676 void *ccgSubSurf_getFaceGridEdgeData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x) { 02677 return _face_getIECo(f, ss->subdivLevels, gridIndex, x, ss->subdivLevels, ss->meshIFC.vertDataSize); 02678 } 02679 void *ccgSubSurf_getFaceGridDataArray(CCGSubSurf *ss, CCGFace *f, int gridIndex) { 02680 return ccgSubSurf_getFaceGridData(ss, f, gridIndex, 0, 0); 02681 } 02682 void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y) { 02683 return _face_getIFCo(f, ss->subdivLevels, gridIndex, x, y, ss->subdivLevels, ss->meshIFC.vertDataSize); 02684 } 02685 02686 /*** External API iterator functions ***/ 02687 02688 CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss) { 02689 return (CCGVertIterator*) _ehashIterator_new(ss->vMap); 02690 } 02691 CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss) { 02692 return (CCGEdgeIterator*) _ehashIterator_new(ss->eMap); 02693 } 02694 CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss) { 02695 return (CCGFaceIterator*) _ehashIterator_new(ss->fMap); 02696 } 02697 02698 CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi) { 02699 return (CCGVert*) _ehashIterator_getCurrent((EHashIterator*) vi); 02700 } 02701 int ccgVertIterator_isStopped(CCGVertIterator *vi) { 02702 return _ehashIterator_isStopped((EHashIterator*) vi); 02703 } 02704 void ccgVertIterator_next(CCGVertIterator *vi) { 02705 _ehashIterator_next((EHashIterator*) vi); 02706 } 02707 void ccgVertIterator_free(CCGVertIterator *vi) { 02708 _ehashIterator_free((EHashIterator*) vi); 02709 } 02710 02711 CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi) { 02712 return (CCGEdge*) _ehashIterator_getCurrent((EHashIterator*) vi); 02713 } 02714 int ccgEdgeIterator_isStopped(CCGEdgeIterator *vi) { 02715 return _ehashIterator_isStopped((EHashIterator*) vi); 02716 } 02717 void ccgEdgeIterator_next(CCGEdgeIterator *vi) { 02718 _ehashIterator_next((EHashIterator*) vi); 02719 } 02720 void ccgEdgeIterator_free(CCGEdgeIterator *vi) { 02721 _ehashIterator_free((EHashIterator*) vi); 02722 } 02723 02724 CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi) { 02725 return (CCGFace*) _ehashIterator_getCurrent((EHashIterator*) vi); 02726 } 02727 int ccgFaceIterator_isStopped(CCGFaceIterator *vi) { 02728 return _ehashIterator_isStopped((EHashIterator*) vi); 02729 } 02730 void ccgFaceIterator_next(CCGFaceIterator *vi) { 02731 _ehashIterator_next((EHashIterator*) vi); 02732 } 02733 void ccgFaceIterator_free(CCGFaceIterator *vi) { 02734 _ehashIterator_free((EHashIterator*) vi); 02735 } 02736 02737 /*** Extern API final vert/edge/face interface ***/ 02738 02739 int ccgSubSurf_getNumFinalVerts(const CCGSubSurf *ss) { 02740 int edgeSize = 1 + (1<<ss->subdivLevels); 02741 int gridSize = 1 + (1<<(ss->subdivLevels-1)); 02742 int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2))); 02743 return numFinalVerts; 02744 } 02745 int ccgSubSurf_getNumFinalEdges(const CCGSubSurf *ss) { 02746 int edgeSize = 1 + (1<<ss->subdivLevels); 02747 int gridSize = 1 + (1<<(ss->subdivLevels-1)); 02748 int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1))); 02749 return numFinalEdges; 02750 } 02751 int ccgSubSurf_getNumFinalFaces(const CCGSubSurf *ss) { 02752 int gridSize = 1 + (1<<(ss->subdivLevels-1)); 02753 int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1)); 02754 return numFinalFaces; 02755 }