Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2009-11-25 15:27:21 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-11-25 15:27:21 +0300
commit90cc7c8abd7b4c36002031edba8b75207fb98086 (patch)
tree3a0a63b907c87108164ee4562210c915e7c6d640 /source/blender/blenkernel
parent9a31f37d19de8ab6f45ac0622bd620e80cff9abf (diff)
Sculpt: CCGSubsurf new functions to update normals, update subdivision
levels, copy coordinates from face grids, and stitch together face grids.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c1470
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.h5
2 files changed, 903 insertions, 572 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index cee032f364e..86595dea8fb 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -1130,6 +1130,643 @@ CCGError ccgSubSurf_processSync(CCGSubSurf *ss) {
return eCCGError_None;
}
+#define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
+#define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
+static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss,
+ CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
+ int numEffectedV, int numEffectedE, int numEffectedF) {
+ int i,ptrIdx;
+ int subdivLevels = ss->subdivLevels;
+ int lvl = ss->subdivLevels;
+ int edgeSize = 1 + (1<<lvl);
+ int gridSize = 1 + (1<<(lvl-1));
+ int normalDataOffset = ss->normalDataOffset;
+ int vertDataSize = ss->meshIFC.vertDataSize;
+
+ for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ int S, x, y;
+
+ for (S=0; S<f->numVerts; S++) {
+ for (y=0; y<gridSize-1; y++)
+ for (x=0; x<gridSize-1; x++)
+ NormZero(FACE_getIFNo(f, lvl, S, x, y));
+
+ if (FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected)
+ for (x=0; x<gridSize-1; x++)
+ NormZero(FACE_getIFNo(f, lvl, S, x, gridSize-1));
+ if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
+ for (y=0; y<gridSize-1; y++)
+ NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, y));
+ if (FACE_getVerts(f)[S]->flags&Vert_eEffected)
+ NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1));
+ }
+ }
+
+ for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ int S, x, y;
+ float no[3];
+
+ for (S=0; S<f->numVerts; S++) {
+ int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected);
+ int xLimit = !(FACE_getEdges(f)[S]->flags&Edge_eEffected);
+ int yLimitNext = xLimit;
+ int xLimitPrev = yLimit;
+
+ for (y=0; y<gridSize - 1; y++) {
+ for (x=0; x<gridSize - 1; x++) {
+ int xPlusOk = (!xLimit || x<gridSize-2);
+ int yPlusOk = (!yLimit || y<gridSize-2);
+
+ FACE_calcIFNo(f, lvl, S, x, y, no);
+
+ NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+0), no);
+ if (xPlusOk)
+ NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+0), no);
+ if (yPlusOk)
+ NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+1), no);
+ if (xPlusOk && yPlusOk) {
+ if (x<gridSize-2 || y<gridSize-2 || FACE_getVerts(f)[S]->flags&Vert_eEffected) {
+ NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+1), no);
+ }
+ }
+
+ if (x==0 && y==0) {
+ int K;
+
+ if (!yLimitNext || 1<gridSize-1)
+ NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, 1), no);
+ if (!xLimitPrev || 1<gridSize-1)
+ NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no);
+
+ for (K=0; K<f->numVerts; K++) {
+ if (K!=S) {
+ NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
+ }
+ }
+ } else if (y==0) {
+ NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no);
+ if (!yLimitNext || x<gridSize-2)
+ NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x+1), no);
+ } else if (x==0) {
+ NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no);
+ if (!xLimitPrev || y<gridSize-2)
+ NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y+1, 0), no);
+ }
+ }
+ }
+ }
+ }
+ // XXX can I reduce the number of normalisations here?
+ for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
+ CCGVert *v = (CCGVert*) effectedV[ptrIdx];
+ float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset);
+
+ NormZero(no);
+
+ for (i=0; i<v->numFaces; i++) {
+ CCGFace *f = v->faces[i];
+ NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1));
+ }
+
+ length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
+
+ if (length>FLT_EPSILON) {
+ float invLength = 1.0f/length;
+ no[0] *= invLength;
+ no[1] *= invLength;
+ no[2] *= invLength;
+ } else {
+ NormZero(no);
+ }
+
+ for (i=0; i<v->numFaces; i++) {
+ CCGFace *f = v->faces[i];
+ NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no);
+ }
+ }
+ for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
+ CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
+
+ if (e->numFaces) {
+ CCGFace *fLast = e->faces[e->numFaces-1];
+ int x;
+
+ for (i=0; i<e->numFaces-1; i++) {
+ CCGFace *f = e->faces[i];
+
+ for (x=1; x<edgeSize-1; x++) {
+ NormAdd(_face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
+ _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
+ }
+ }
+
+ for (i=0; i<e->numFaces-1; i++) {
+ CCGFace *f = e->faces[i];
+
+ for (x=1; x<edgeSize-1; x++) {
+ NormCopy(_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
+ _face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
+ }
+ }
+ }
+ }
+ for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ int S;
+
+ for (S=0; S<f->numVerts; S++) {
+ NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1),
+ FACE_getIFNo(f, lvl, S, gridSize-1, 0));
+ }
+ }
+ for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ int S, x, y;
+
+ for (S=0; S<f->numVerts; S++) {
+ for (y=0; y<gridSize; y++) {
+ for (x=0; x<gridSize; x++) {
+ float *no = FACE_getIFNo(f, lvl, S, x, y);
+ float length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
+
+ if (length>FLT_EPSILON) {
+ float invLength = 1.0f/length;
+ no[0] *= invLength;
+ no[1] *= invLength;
+ no[2] *= invLength;
+ } else {
+ NormZero(no);
+ }
+ }
+ }
+ }
+ }
+}
+#undef FACE_getIFNo
+
+#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)
+static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss,
+ CCGVert **effectedV, CCGEdge **effectedE, CCGFace **effectedF,
+ int numEffectedV, int numEffectedE, int numEffectedF, int curLvl) {
+ int subdivLevels = ss->subdivLevels;
+ int edgeSize = 1 + (1<<curLvl);
+ int gridSize = 1 + (1<<(curLvl-1));
+ int nextLvl = curLvl+1;
+ int ptrIdx, S, y, x, i, cornerIdx;
+ void *q = ss->q, *r = ss->r;
+ int vertDataSize = ss->meshIFC.vertDataSize;
+
+ for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+
+ /* interior face midpoints
+ * o old interior face points
+ */
+ for (S=0; S<f->numVerts; S++) {
+ for (y=0; y<gridSize-1; y++) {
+ for (x=0; x<gridSize-1; x++) {
+ int fx = 1 + 2*x;
+ int fy = 1 + 2*y;
+ void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y+0);
+ void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y+0);
+ void *co2 = FACE_getIFCo(f, curLvl, S, x+1, y+1);
+ void *co3 = FACE_getIFCo(f, curLvl, S, x+0, y+1);
+ void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+ VertDataAvg4(co, co0, co1, co2, co3);
+ }
+ }
+ }
+
+ /* interior edge midpoints
+ * o old interior edge points
+ * o new interior face midpoints
+ */
+ for (S=0; S<f->numVerts; S++) {
+ for (x=0; x<gridSize-1; x++) {
+ int fx = x*2 + 1;
+ void *co0 = FACE_getIECo(f, curLvl, S, x+0);
+ void *co1 = FACE_getIECo(f, curLvl, S, x+1);
+ void *co2 = FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx);
+ void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
+ void *co = FACE_getIECo(f, nextLvl, S, fx);
+
+ VertDataAvg4(co, co0, co1, co2, co3);
+ }
+
+ /* interior face interior edge midpoints
+ * o old interior face points
+ * o new interior face midpoints
+ */
+
+ /* vertical */
+ for (x=1; x<gridSize-1; x++) {
+ for (y=0; y<gridSize-1; y++) {
+ int fx = x*2;
+ int fy = y*2+1;
+ void *co0 = FACE_getIFCo(f, curLvl, S, x, y+0);
+ void *co1 = FACE_getIFCo(f, curLvl, S, x, y+1);
+ void *co2 = FACE_getIFCo(f, nextLvl, S, fx-1, fy);
+ void *co3 = FACE_getIFCo(f, nextLvl, S, fx+1, fy);
+ void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+ VertDataAvg4(co, co0, co1, co2, co3);
+ }
+ }
+
+ /* horizontal */
+ for (y=1; y<gridSize-1; y++) {
+ for (x=0; x<gridSize-1; x++) {
+ int fx = x*2+1;
+ int fy = y*2;
+ void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y);
+ void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y);
+ void *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy-1);
+ void *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy+1);
+ void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+ VertDataAvg4(co, co0, co1, co2, co3);
+ }
+ }
+ }
+ }
+
+ /* exterior edge midpoints
+ * o old exterior edge points
+ * o new interior face midpoints
+ */
+ for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
+ CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+
+ if (_edge_isBoundary(e) || sharpness>1.0) {
+ for (x=0; x<edgeSize-1; x++) {
+ int fx = x*2 + 1;
+ void *co0 = EDGE_getCo(e, curLvl, x+0);
+ void *co1 = EDGE_getCo(e, curLvl, x+1);
+ void *co = EDGE_getCo(e, nextLvl, fx);
+
+ VertDataCopy(co, co0);
+ VertDataAdd(co, co1);
+ VertDataMulN(co, 0.5);
+ }
+ } else {
+ for (x=0; x<edgeSize-1; x++) {
+ int fx = x*2 + 1;
+ void *co0 = EDGE_getCo(e, curLvl, x+0);
+ void *co1 = EDGE_getCo(e, curLvl, x+1);
+ void *co = EDGE_getCo(e, nextLvl, fx);
+ int numFaces = 0;
+
+ VertDataCopy(q, co0);
+ VertDataAdd(q, co1);
+
+ for (i=0; i<e->numFaces; i++) {
+ CCGFace *f = e->faces[i];
+ VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
+ numFaces++;
+ }
+
+ VertDataMulN(q, 1.0f/(2.0f+numFaces));
+
+ VertDataCopy(r, co0);
+ VertDataAdd(r, co1);
+ VertDataMulN(r, 0.5);
+
+ VertDataCopy(co, q);
+ VertDataSub(r, q);
+ VertDataMulN(r, sharpness);
+ VertDataAdd(co, r);
+ }
+ }
+ }
+
+ /* exterior vertex shift
+ * o old vertex points (shifting)
+ * o old exterior edge points
+ * o new interior face midpoints
+ */
+ for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
+ CCGVert *v = (CCGVert*) effectedV[ptrIdx];
+ void *co = VERT_getCo(v, curLvl);
+ void *nCo = VERT_getCo(v, nextLvl);
+ int sharpCount = 0, allSharp = 1;
+ float avgSharpness = 0.0;
+ int seam = VERT_seam(v), seamEdges = 0;
+
+ for (i=0; i<v->numEdges; i++) {
+ CCGEdge *e = v->edges[i];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+
+ if (seam && _edge_isBoundary(e))
+ seamEdges++;
+
+ if (sharpness!=0.0f) {
+ sharpCount++;
+ avgSharpness += sharpness;
+ } else {
+ allSharp = 0;
+ }
+ }
+
+ if(sharpCount) {
+ avgSharpness /= sharpCount;
+ if (avgSharpness>1.0) {
+ avgSharpness = 1.0;
+ }
+ }
+
+ if (seam && seamEdges < 2)
+ seam = 0;
+
+ if (!v->numEdges) {
+ VertDataCopy(nCo, co);
+ } else if (_vert_isBoundary(v)) {
+ int numBoundary = 0;
+
+ VertDataZero(r);
+ for (i=0; i<v->numEdges; i++) {
+ CCGEdge *e = v->edges[i];
+ if (_edge_isBoundary(e)) {
+ VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
+ numBoundary++;
+ }
+ }
+
+ VertDataCopy(nCo, co);
+ VertDataMulN(nCo, 0.75);
+ VertDataMulN(r, 0.25f/numBoundary);
+ VertDataAdd(nCo, r);
+ } else {
+ int cornerIdx = (1 + (1<<(curLvl))) - 2;
+ int numEdges = 0, numFaces = 0;
+
+ VertDataZero(q);
+ for (i=0; i<v->numFaces; i++) {
+ CCGFace *f = v->faces[i];
+ VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx));
+ numFaces++;
+ }
+ VertDataMulN(q, 1.0f/numFaces);
+ VertDataZero(r);
+ for (i=0; i<v->numEdges; i++) {
+ CCGEdge *e = v->edges[i];
+ VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize));
+ numEdges++;
+ }
+ VertDataMulN(r, 1.0f/numEdges);
+
+ VertDataCopy(nCo, co);
+ VertDataMulN(nCo, numEdges-2.0f);
+ VertDataAdd(nCo, q);
+ VertDataAdd(nCo, r);
+ VertDataMulN(nCo, 1.0f/numEdges);
+ }
+
+ if ((sharpCount>1 && v->numFaces) || seam) {
+ VertDataZero(q);
+
+ if (seam) {
+ avgSharpness = 1.0f;
+ sharpCount = seamEdges;
+ allSharp = 1;
+ }
+
+ for (i=0; i<v->numEdges; i++) {
+ CCGEdge *e = v->edges[i];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+
+ if (seam) {
+ if (_edge_isBoundary(e))
+ VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
+ } else if (sharpness != 0.0) {
+ VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
+ }
+ }
+
+ VertDataMulN(q, (float) 1/sharpCount);
+
+ if (sharpCount!=2 || allSharp) {
+ // q = q + (co-q)*avgSharpness
+ VertDataCopy(r, co);
+ VertDataSub(r, q);
+ VertDataMulN(r, avgSharpness);
+ VertDataAdd(q, r);
+ }
+
+ // r = co*.75 + q*.25
+ VertDataCopy(r, co);
+ VertDataMulN(r, .75);
+ VertDataMulN(q, .25);
+ VertDataAdd(r, q);
+
+ // nCo = nCo + (r-nCo)*avgSharpness
+ VertDataSub(r, nCo);
+ VertDataMulN(r, avgSharpness);
+ VertDataAdd(nCo, r);
+ }
+ }
+
+ /* exterior edge interior shift
+ * o old exterior edge midpoints (shifting)
+ * o old exterior edge midpoints
+ * o new interior face midpoints
+ */
+ for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
+ CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
+ float sharpness = EDGE_getSharpness(e, curLvl);
+ int sharpCount = 0;
+ float avgSharpness = 0.0;
+
+ if (sharpness!=0.0f) {
+ sharpCount = 2;
+ avgSharpness += sharpness;
+
+ if (avgSharpness>1.0) {
+ avgSharpness = 1.0;
+ }
+ } else {
+ sharpCount = 0;
+ avgSharpness = 0;
+ }
+
+ if (_edge_isBoundary(e) && (!e->numFaces || sharpCount<2)) {
+ for (x=1; x<edgeSize-1; x++) {
+ int fx = x*2;
+ void *co = EDGE_getCo(e, curLvl, x);
+ void *nCo = EDGE_getCo(e, nextLvl, fx);
+ VertDataCopy(r, EDGE_getCo(e, curLvl, x-1));
+ VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
+ VertDataMulN(r, 0.5);
+ VertDataCopy(nCo, co);
+ VertDataMulN(nCo, 0.75);
+ VertDataMulN(r, 0.25);
+ VertDataAdd(nCo, r);
+ }
+ } else {
+ for (x=1; x<edgeSize-1; x++) {
+ int fx = x*2;
+ void *co = EDGE_getCo(e, curLvl, x);
+ void *nCo = EDGE_getCo(e, nextLvl, fx);
+ int numFaces = 0;
+
+ VertDataZero(q);
+ VertDataZero(r);
+ VertDataAdd(r, EDGE_getCo(e, curLvl, x-1));
+ VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
+ for (i=0; i<e->numFaces; i++) {
+ CCGFace *f = e->faces[i];
+ VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize));
+ VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize));
+
+ VertDataAdd(r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize));
+ numFaces++;
+ }
+ VertDataMulN(q, 1.0/(numFaces*2.0f));
+ VertDataMulN(r, 1.0/(2.0f + numFaces));
+
+ VertDataCopy(nCo, co);
+ VertDataMulN(nCo, (float) numFaces);
+ VertDataAdd(nCo, q);
+ VertDataAdd(nCo, r);
+ VertDataMulN(nCo, 1.0f/(2+numFaces));
+
+ if (sharpCount==2) {
+ VertDataCopy(q, co);
+ VertDataMulN(q, 6.0f);
+ VertDataAdd(q, EDGE_getCo(e, curLvl, x-1));
+ VertDataAdd(q, EDGE_getCo(e, curLvl, x+1));
+ VertDataMulN(q, 1/8.0f);
+
+ VertDataSub(q, nCo);
+ VertDataMulN(q, avgSharpness);
+ VertDataAdd(nCo, q);
+ }
+ }
+ }
+ }
+
+ for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
+ CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+
+ /* interior center point shift
+ * o old face center point (shifting)
+ * o old interior edge points
+ * o new interior face midpoints
+ */
+ VertDataZero(q);
+ for (S=0; S<f->numVerts; S++) {
+ VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1));
+ }
+ VertDataMulN(q, 1.0f/f->numVerts);
+ VertDataZero(r);
+ for (S=0; S<f->numVerts; S++) {
+ VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1));
+ }
+ VertDataMulN(r, 1.0f/f->numVerts);
+
+ VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f);
+ VertDataAdd(FACE_getCenterData(f), q);
+ VertDataAdd(FACE_getCenterData(f), r);
+ VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
+
+ for (S=0; S<f->numVerts; S++) {
+ /* interior face shift
+ * o old interior face point (shifting)
+ * o new interior edge midpoints
+ * o new interior face midpoints
+ */
+ for (x=1; x<gridSize-1; x++) {
+ for (y=1; y<gridSize-1; y++) {
+ int fx = x*2;
+ int fy = y*2;
+ void *co = FACE_getIFCo(f, curLvl, S, x, y);
+ void *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
+
+ VertDataAvg4(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));
+
+ VertDataAvg4(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));
+
+ VertDataCopy(nCo, co);
+ VertDataSub(nCo, q);
+ VertDataMulN(nCo, 0.25f);
+ VertDataAdd(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; x<gridSize-1; x++) {
+ int fx = x*2;
+ void *co = FACE_getIECo(f, curLvl, S, x);
+ void *nCo = FACE_getIECo(f, nextLvl, S, fx);
+
+ VertDataAvg4(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));
+
+ VertDataAvg4(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));
+
+ VertDataCopy(nCo, co);
+ VertDataSub(nCo, q);
+ VertDataMulN(nCo, 0.25f);
+ VertDataAdd(nCo, r);
+ }
+ }
+ }
+
+ /* copy down */
+ edgeSize = 1 + (1<<(nextLvl));
+ gridSize = 1 + (1<<((nextLvl)-1));
+ cornerIdx = gridSize-1;
+ for (i=0; i<numEffectedE; i++) {
+ CCGEdge *e = effectedE[i];
+ VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
+ VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl));
+ }
+ for (i=0; i<numEffectedF; i++) {
+ CCGFace *f = effectedF[i];
+ for (S=0; S<f->numVerts; S++) {
+ CCGEdge *e = FACE_getEdges(f)[S];
+ CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
+
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
+ VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
+ VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx));
+ for (x=1; x<gridSize-1; x++) {
+ void *co = FACE_getIECo(f, nextLvl, S, x);
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co);
+ VertDataCopy(FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 0, x), co);
+ }
+ for (x=0; x<gridSize-1; x++) {
+ int eI = gridSize-1-x;
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
+ VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
+ }
+ }
+ }
+}
+
+
static void ccgSubSurf__sync(CCGSubSurf *ss) {
CCGVert **effectedV;
CCGEdge **effectedE;
@@ -1137,11 +1774,9 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
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 i, j, ptrIdx, S;
int curLvl, nextLvl;
- int j;
+ void *q = ss->q, *r = ss->r;
effectedV = CCGSUBSURF_alloc(ss, sizeof(*effectedV)*ss->vMap->numEntries);
effectedE = CCGSUBSURF_alloc(ss, sizeof(*effectedE)*ss->eMap->numEntries);
@@ -1172,10 +1807,6 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
}
-#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;
@@ -1388,645 +2019,340 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
}
for (curLvl=1; curLvl<subdivLevels; curLvl++) {
- int edgeSize = 1 + (1<<curLvl);
- int gridSize = 1 + (1<<(curLvl-1));
- nextLvl = curLvl+1;
+ ccgSubSurf__calcSubdivLevel(ss,
+ effectedV, effectedE, effectedF,
+ numEffectedV, numEffectedE, numEffectedF, curLvl);
+ }
- for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ if (ss->calcVertNormals)
+ ccgSubSurf__calcVertNormals(ss,
+ effectedV, effectedE, effectedF,
+ numEffectedV, numEffectedE, numEffectedF);
- /* interior face midpoints
- * o old interior face points
- */
- for (S=0; S<f->numVerts; S++) {
- for (y=0; y<gridSize-1; y++) {
- for (x=0; x<gridSize-1; x++) {
- int fx = 1 + 2*x;
- int fy = 1 + 2*y;
- void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y+0);
- void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y+0);
- void *co2 = FACE_getIFCo(f, curLvl, S, x+1, y+1);
- void *co3 = FACE_getIFCo(f, curLvl, S, x+0, y+1);
- void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
-
- VertDataAvg4(co, co0, co1, co2, co3);
- }
- }
- }
+ for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
+ CCGVert *v = effectedV[ptrIdx];
+ v->flags = 0;
+ }
+ for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
+ CCGEdge *e = effectedE[ptrIdx];
+ e->flags = 0;
+ }
- /* interior edge midpoints
- * o old interior edge points
- * o new interior face midpoints
- */
- for (S=0; S<f->numVerts; S++) {
- for (x=0; x<gridSize-1; x++) {
- int fx = x*2 + 1;
- void *co0 = FACE_getIECo(f, curLvl, S, x+0);
- void *co1 = FACE_getIECo(f, curLvl, S, x+1);
- void *co2 = FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 1, fx);
- void *co3 = FACE_getIFCo(f, nextLvl, S, fx, 1);
- void *co = FACE_getIECo(f, nextLvl, S, fx);
-
- VertDataAvg4(co, co0, co1, co2, co3);
- }
+ CCGSUBSURF_free(ss, effectedF);
+ CCGSUBSURF_free(ss, effectedE);
+ CCGSUBSURF_free(ss, effectedV);
+}
- /* interior face interior edge midpoints
- * o old interior face points
- * o new interior face midpoints
- */
-
- /* vertical */
- for (x=1; x<gridSize-1; x++) {
- for (y=0; y<gridSize-1; y++) {
- int fx = x*2;
- int fy = y*2+1;
- void *co0 = FACE_getIFCo(f, curLvl, S, x, y+0);
- void *co1 = FACE_getIFCo(f, curLvl, S, x, y+1);
- void *co2 = FACE_getIFCo(f, nextLvl, S, fx-1, fy);
- void *co3 = FACE_getIFCo(f, nextLvl, S, fx+1, fy);
- void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
-
- VertDataAvg4(co, co0, co1, co2, co3);
- }
- }
+static void ccgSubSurf__allFaces(CCGSubSurf *ss, CCGFace ***faces, int *numFaces, int *freeFaces)
+{
+ CCGFace **array;
+ int i, num;
- /* horizontal */
- for (y=1; y<gridSize-1; y++) {
- for (x=0; x<gridSize-1; x++) {
- int fx = x*2+1;
- int fy = y*2;
- void *co0 = FACE_getIFCo(f, curLvl, S, x+0, y);
- void *co1 = FACE_getIFCo(f, curLvl, S, x+1, y);
- void *co2 = FACE_getIFCo(f, nextLvl, S, fx, fy-1);
- void *co3 = FACE_getIFCo(f, nextLvl, S, fx, fy+1);
- void *co = FACE_getIFCo(f, nextLvl, S, fx, fy);
-
- VertDataAvg4(co, co0, co1, co2, co3);
- }
- }
- }
+ if(!*faces) {
+ array = CCGSUBSURF_alloc(ss, sizeof(*array)*ss->fMap->numEntries);
+ num = 0;
+ for (i=0; i<ss->fMap->curSize; i++) {
+ CCGFace *f = (CCGFace*) ss->fMap->buckets[i];
+
+ for (; f; f = f->next)
+ array[num++] = f;
}
- /* exterior edge midpoints
- * o old exterior edge points
- * o new interior face midpoints
- */
- for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
- float sharpness = EDGE_getSharpness(e, curLvl);
+ *faces = array;
+ *numFaces = num;
+ *freeFaces= 1;
+ }
+ else
+ *freeFaces= 0;
+}
- if (_edge_isBoundary(e) || sharpness>1.0) {
- for (x=0; x<edgeSize-1; x++) {
- int fx = x*2 + 1;
- void *co0 = EDGE_getCo(e, curLvl, x+0);
- void *co1 = EDGE_getCo(e, curLvl, x+1);
- void *co = EDGE_getCo(e, nextLvl, fx);
+static void ccgSubSurf__effectedFaceNeighbours(CCGSubSurf *ss, CCGFace **faces, int numFaces, CCGVert ***verts, int *numVerts, CCGEdge ***edges, int *numEdges)
+{
+ CCGVert **arrayV;
+ CCGEdge **arrayE;
+ int numV, numE, i, j;
- VertDataCopy(co, co0);
- VertDataAdd(co, co1);
- VertDataMulN(co, 0.5);
- }
- } else {
- for (x=0; x<edgeSize-1; x++) {
- int fx = x*2 + 1;
- void *co0 = EDGE_getCo(e, curLvl, x+0);
- void *co1 = EDGE_getCo(e, curLvl, x+1);
- void *co = EDGE_getCo(e, nextLvl, fx);
- int numFaces = 0;
-
- VertDataCopy(q, co0);
- VertDataAdd(q, co1);
-
- for (i=0; i<e->numFaces; i++) {
- CCGFace *f = e->faces[i];
- VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
- numFaces++;
- }
+ arrayV = CCGSUBSURF_alloc(ss, sizeof(*arrayV)*ss->vMap->numEntries);
+ arrayE = CCGSUBSURF_alloc(ss, sizeof(*arrayE)*ss->eMap->numEntries);
+ numV = numE = 0;
- VertDataMulN(q, 1.0f/(2.0f+numFaces));
+ for (i=0; i<numFaces; i++) {
+ CCGFace *f = faces[i];
+ f->flags |= Face_eEffected;
+ }
- VertDataCopy(r, co0);
- VertDataAdd(r, co1);
- VertDataMulN(r, 0.5);
+ for (i=0; i<ss->vMap->curSize; i++) {
+ CCGVert *v = (CCGVert*) ss->vMap->buckets[i];
- VertDataCopy(co, q);
- VertDataSub(r, q);
- VertDataMulN(r, sharpness);
- VertDataAdd(co, r);
- }
+ for (; v; v = v->next) {
+ for(j=0; j<v->numFaces; j++)
+ if(!(v->faces[j]->flags & Face_eEffected))
+ break;
+
+ if(j == v->numFaces) {
+ arrayV[numV++] = v;
+ v->flags |= Vert_eEffected;
}
}
+ }
- /* exterior vertex shift
- * o old vertex points (shifting)
- * o old exterior edge points
- * o new interior face midpoints
- */
- for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
- CCGVert *v = (CCGVert*) effectedV[ptrIdx];
- void *co = VERT_getCo(v, curLvl);
- void *nCo = VERT_getCo(v, nextLvl);
- int sharpCount = 0, allSharp = 1;
- float avgSharpness = 0.0;
- int seam = VERT_seam(v), seamEdges = 0;
+ for (i=0; i<ss->eMap->curSize; i++) {
+ CCGEdge *e = (CCGEdge*) ss->eMap->buckets[i];
- for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
- float sharpness = EDGE_getSharpness(e, curLvl);
+ for (; e; e = e->next) {
+ for(j=0; j<e->numFaces; j++)
+ if(!(e->faces[j]->flags & Face_eEffected))
+ break;
+
+ if(j == e->numFaces) {
+ e->flags |= Edge_eEffected;
+ arrayE[numE++] = e;
+ }
+ }
+ }
- if (seam && _edge_isBoundary(e))
- seamEdges++;
+ *verts = arrayV;
+ *numVerts = numV;
+ *edges = arrayE;
+ *numEdges = numE;
+}
- if (sharpness!=0.0f) {
- sharpCount++;
- avgSharpness += sharpness;
- } else {
- allSharp = 0;
- }
- }
+/* copy face grid coordinates to other places */
+CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
+{
+ int i, S, x, gridSize, cornerIdx, subdivLevels;
+ int vertDataSize = ss->meshIFC.vertDataSize, freeF;
- if(sharpCount) {
- avgSharpness /= sharpCount;
- if (avgSharpness>1.0) {
- avgSharpness = 1.0;
- }
- }
+ subdivLevels = ss->subdivLevels;
+ lvl = (lvl)? lvl: subdivLevels;
+ gridSize = 1 + (1<<(lvl-1));
+ cornerIdx = gridSize-1;
- if (seam && seamEdges < 2)
- seam = 0;
+ ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
- if (!v->numEdges) {
- VertDataCopy(nCo, co);
- } else if (_vert_isBoundary(v)) {
- int numBoundary = 0;
+ for (i=0; i<numEffectedF; i++) {
+ CCGFace *f = effectedF[i];
- VertDataZero(r);
- for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
- if (_edge_isBoundary(e)) {
- VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
- numBoundary++;
- }
- }
+ for (S=0; S<f->numVerts; S++) {
+ CCGEdge *e = FACE_getEdges(f)[S];
+ CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
- VertDataCopy(nCo, co);
- VertDataMulN(nCo, 0.75);
- VertDataMulN(r, 0.25f/numBoundary);
- VertDataAdd(nCo, r);
- } else {
- int cornerIdx = (1 + (1<<(curLvl))) - 2;
- int numEdges = 0, numFaces = 0;
+ VertDataCopy(FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0));
+ VertDataCopy(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx));
- VertDataZero(q);
- for (i=0; i<v->numFaces; i++) {
- CCGFace *f = v->faces[i];
- VertDataAdd(q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx));
- numFaces++;
- }
- VertDataMulN(q, 1.0f/numFaces);
- VertDataZero(r);
- for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
- VertDataAdd(r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize));
- numEdges++;
- }
- VertDataMulN(r, 1.0f/numEdges);
+ for (x=0; x<gridSize; x++)
+ VertDataCopy(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0));
- VertDataCopy(nCo, co);
- VertDataMulN(nCo, numEdges-2.0f);
- VertDataAdd(nCo, q);
- VertDataAdd(nCo, r);
- VertDataMulN(nCo, 1.0f/numEdges);
+ for (x=0; x<gridSize; x++) {
+ int eI = gridSize-1-x;
+ VertDataCopy(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, cornerIdx, x));
+ VertDataCopy(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, x, cornerIdx));
}
+ }
+ }
- if ((sharpCount>1 && v->numFaces) || seam) {
- VertDataZero(q);
-
- if (seam) {
- avgSharpness = 1.0f;
- sharpCount = seamEdges;
- allSharp = 1;
- }
+ if(freeF) CCGSUBSURF_free(ss, effectedF);
- for (i=0; i<v->numEdges; i++) {
- CCGEdge *e = v->edges[i];
- float sharpness = EDGE_getSharpness(e, curLvl);
+ return eCCGError_None;
+}
- if (seam) {
- if (_edge_isBoundary(e))
- VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
- } else if (sharpness != 0.0) {
- VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
- }
- }
+/* stitch together face grids, averaging coordinates at edges
+ and vertices, for multires displacements */
+CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
+{
+ CCGVert **effectedV;
+ CCGEdge **effectedE;
+ int numEffectedV, numEffectedE, freeF;
+ int i, S, x, gridSize, cornerIdx, subdivLevels, edgeSize;
+ int vertDataSize = ss->meshIFC.vertDataSize;
- VertDataMulN(q, (float) 1/sharpCount);
+ subdivLevels = ss->subdivLevels;
+ lvl = (lvl)? lvl: subdivLevels;
+ gridSize = 1 + (1<<(lvl-1));
+ edgeSize = 1 + (1<<lvl);
+ cornerIdx = gridSize-1;
- if (sharpCount!=2 || allSharp) {
- // q = q + (co-q)*avgSharpness
- VertDataCopy(r, co);
- VertDataSub(r, q);
- VertDataMulN(r, avgSharpness);
- VertDataAdd(q, r);
- }
+ ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
+ ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
+ &effectedV, &numEffectedV, &effectedE, &numEffectedE);
- // r = co*.75 + q*.25
- VertDataCopy(r, co);
- VertDataMulN(r, .75);
- VertDataMulN(q, .25);
- VertDataAdd(r, q);
+ /* zero */
+ for (i=0; i<numEffectedV; i++) {
+ CCGVert *v = effectedV[i];
+ VertDataZero(VERT_getCo(v, lvl));
+ }
- // nCo = nCo + (r-nCo)*avgSharpness
- VertDataSub(r, nCo);
- VertDataMulN(r, avgSharpness);
- VertDataAdd(nCo, r);
- }
- }
+ for (i=0; i<numEffectedE; i++) {
+ CCGEdge *e = effectedE[i];
- /* exterior edge interior shift
- * o old exterior edge midpoints (shifting)
- * o old exterior edge midpoints
- * o new interior face midpoints
- */
- for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
- float sharpness = EDGE_getSharpness(e, curLvl);
- int sharpCount = 0;
- float avgSharpness = 0.0;
+ for (x=0; x<edgeSize; x++)
+ VertDataZero(EDGE_getCo(e, lvl, x));
+ }
- if (sharpness!=0.0f) {
- sharpCount = 2;
- avgSharpness += sharpness;
+ /* add */
+ for (i=0; i<numEffectedF; i++) {
+ CCGFace *f = effectedF[i];
- if (avgSharpness>1.0) {
- avgSharpness = 1.0;
- }
- } else {
- sharpCount = 0;
- avgSharpness = 0;
- }
+ VertDataZero(FACE_getCenterData(f));
- if (_edge_isBoundary(e) && (!e->numFaces || sharpCount<2)) {
- for (x=1; x<edgeSize-1; x++) {
- int fx = x*2;
- void *co = EDGE_getCo(e, curLvl, x);
- void *nCo = EDGE_getCo(e, nextLvl, fx);
- VertDataCopy(r, EDGE_getCo(e, curLvl, x-1));
- VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
- VertDataMulN(r, 0.5);
- VertDataCopy(nCo, co);
- VertDataMulN(nCo, 0.75);
- VertDataMulN(r, 0.25);
- VertDataAdd(nCo, r);
- }
- } else {
- for (x=1; x<edgeSize-1; x++) {
- int fx = x*2;
- void *co = EDGE_getCo(e, curLvl, x);
- void *nCo = EDGE_getCo(e, nextLvl, fx);
- int numFaces = 0;
-
- VertDataZero(q);
- VertDataZero(r);
- VertDataAdd(r, EDGE_getCo(e, curLvl, x-1));
- VertDataAdd(r, EDGE_getCo(e, curLvl, x+1));
- for (i=0; i<e->numFaces; i++) {
- CCGFace *f = e->faces[i];
- VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize));
- VertDataAdd(q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize));
-
- VertDataAdd(r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize));
- numFaces++;
- }
- VertDataMulN(q, 1.0/(numFaces*2.0f));
- VertDataMulN(r, 1.0/(2.0f + numFaces));
+ for (S=0; S<f->numVerts; S++)
+ for (x=0; x<gridSize; x++)
+ VertDataZero(FACE_getIECo(f, lvl, S, x));
- VertDataCopy(nCo, co);
- VertDataMulN(nCo, (float) numFaces);
- VertDataAdd(nCo, q);
- VertDataAdd(nCo, r);
- VertDataMulN(nCo, 1.0f/(2+numFaces));
-
- if (sharpCount==2) {
- VertDataCopy(q, co);
- VertDataMulN(q, 6.0f);
- VertDataAdd(q, EDGE_getCo(e, curLvl, x-1));
- VertDataAdd(q, EDGE_getCo(e, curLvl, x+1));
- VertDataMulN(q, 1/8.0f);
-
- VertDataSub(q, nCo);
- VertDataMulN(q, avgSharpness);
- VertDataAdd(nCo, q);
- }
- }
- }
- }
+ for (S=0; S<f->numVerts; S++) {
+ int prevS = (S+f->numVerts-1)%f->numVerts;
+ CCGEdge *e = FACE_getEdges(f)[S];
+ CCGEdge *prevE = FACE_getEdges(f)[prevS];
- for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
+ VertDataAdd(FACE_getCenterData(f), FACE_getIFCo(f, lvl, S, 0, 0));
+ VertDataAdd(VERT_getCo(FACE_getVerts(f)[S], lvl), FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx));
- /* interior center point shift
- * o old face center point (shifting)
- * o old interior edge points
- * o new interior face midpoints
- */
- VertDataZero(q);
- for (S=0; S<f->numVerts; S++) {
- VertDataAdd(q, FACE_getIFCo(f, nextLvl, S, 1, 1));
+ for (x=1; x<gridSize-1; x++) {
+ VertDataAdd(FACE_getIECo(f, lvl, S, x), FACE_getIFCo(f, lvl, S, x, 0));
+ VertDataAdd(FACE_getIECo(f, lvl, prevS, x), FACE_getIFCo(f, lvl, S, 0, x));
}
- VertDataMulN(q, 1.0f/f->numVerts);
- VertDataZero(r);
- for (S=0; S<f->numVerts; S++) {
- VertDataAdd(r, FACE_getIECo(f, curLvl, S, 1));
- }
- VertDataMulN(r, 1.0f/f->numVerts);
-
- VertDataMulN(FACE_getCenterData(f), f->numVerts-2.0f);
- VertDataAdd(FACE_getCenterData(f), q);
- VertDataAdd(FACE_getCenterData(f), r);
- VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
-
- for (S=0; S<f->numVerts; S++) {
- /* interior face shift
- * o old interior face point (shifting)
- * o new interior edge midpoints
- * o new interior face midpoints
- */
- for (x=1; x<gridSize-1; x++) {
- for (y=1; y<gridSize-1; y++) {
- int fx = x*2;
- int fy = y*2;
- void *co = FACE_getIFCo(f, curLvl, S, x, y);
- void *nCo = FACE_getIFCo(f, nextLvl, S, fx, fy);
-
- VertDataAvg4(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));
-
- VertDataAvg4(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));
-
- VertDataCopy(nCo, co);
- VertDataSub(nCo, q);
- VertDataMulN(nCo, 0.25f);
- VertDataAdd(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; x<gridSize-1; x++) {
- int fx = x*2;
- void *co = FACE_getIECo(f, curLvl, S, x);
- void *nCo = FACE_getIECo(f, nextLvl, S, fx);
-
- VertDataAvg4(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));
-
- VertDataAvg4(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));
-
- VertDataCopy(nCo, co);
- VertDataSub(nCo, q);
- VertDataMulN(nCo, 0.25f);
- VertDataAdd(nCo, r);
- }
+ for (x=0; x<gridSize-1; x++) {
+ int eI = gridSize-1-x;
+ VertDataAdd(_edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, cornerIdx, x));
+ if(x != 0)
+ VertDataAdd(_edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize), FACE_getIFCo(f, lvl, S, x, cornerIdx));
}
}
+ }
- /* copy down */
- edgeSize = 1 + (1<<(nextLvl));
- gridSize = 1 + (1<<((nextLvl)-1));
- cornerIdx = gridSize-1;
- for (i=0; i<numEffectedE; i++) {
- CCGEdge *e = effectedE[i];
- VertDataCopy(EDGE_getCo(e, nextLvl, 0), VERT_getCo(e->v0, nextLvl));
- VertDataCopy(EDGE_getCo(e, nextLvl, edgeSize-1), VERT_getCo(e->v1, nextLvl));
- }
- for (i=0; i<numEffectedF; i++) {
- CCGFace *f = effectedF[i];
- for (S=0; S<f->numVerts; S++) {
- CCGEdge *e = FACE_getEdges(f)[S];
- CCGEdge *prevE = FACE_getEdges(f)[(S+f->numVerts-1)%f->numVerts];
-
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, 0, 0), FACE_getCenterData(f));
- VertDataCopy(FACE_getIECo(f, nextLvl, S, 0), FACE_getCenterData(f));
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], nextLvl));
- VertDataCopy(FACE_getIECo(f, nextLvl, S, cornerIdx), EDGE_getCo(FACE_getEdges(f)[S], nextLvl, cornerIdx));
- for (x=1; x<gridSize-1; x++) {
- void *co = FACE_getIECo(f, nextLvl, S, x);
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, 0), co);
- VertDataCopy(FACE_getIFCo(f, nextLvl, (S+1)%f->numVerts, 0, x), co);
- }
- for (x=0; x<gridSize-1; x++) {
- int eI = gridSize-1-x;
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
- VertDataCopy(FACE_getIFCo(f, nextLvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], nextLvl, eI,vertDataSize));
- }
- }
- }
+ /* average */
+ for (i=0; i<numEffectedV; i++) {
+ CCGVert *v = effectedV[i];
+ VertDataMulN(VERT_getCo(v, lvl), 1.0f/v->numFaces);
}
-#define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset)
-#define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize)
- if (ss->calcVertNormals) {
- int lvl = ss->subdivLevels;
- int edgeSize = 1 + (1<<lvl);
- int gridSize = 1 + (1<<(lvl-1));
- int normalDataOffset = ss->normalDataOffset;
+ for (i=0; i<numEffectedE; i++) {
+ CCGEdge *e = effectedE[i];
- for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
- int S, x, y;
+ VertDataCopy(EDGE_getCo(e, lvl, 0), VERT_getCo(e->v0, lvl));
+ VertDataCopy(EDGE_getCo(e, lvl, edgeSize-1), VERT_getCo(e->v1, lvl));
- for (S=0; S<f->numVerts; S++) {
- for (y=0; y<gridSize-1; y++)
- for (x=0; x<gridSize-1; x++)
- NormZero(FACE_getIFNo(f, lvl, S, x, y));
-
- if (FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected)
- for (x=0; x<gridSize-1; x++)
- NormZero(FACE_getIFNo(f, lvl, S, x, gridSize-1));
- if (FACE_getEdges(f)[S]->flags&Edge_eEffected)
- for (y=0; y<gridSize-1; y++)
- NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, y));
- if (FACE_getVerts(f)[S]->flags&Vert_eEffected)
- NormZero(FACE_getIFNo(f, lvl, S, gridSize-1, gridSize-1));
- }
- }
+ for (x=1; x<edgeSize-1; x++)
+ VertDataMulN(EDGE_getCo(e, lvl, x), 1.0f/e->numFaces);
+ }
- for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
- int S, x, y;
- float no[3];
+ /* copy */
+ for (i=0; i<numEffectedF; i++) {
+ CCGFace *f = effectedF[i];
- for (S=0; S<f->numVerts; S++) {
- int yLimit = !(FACE_getEdges(f)[(S-1+f->numVerts)%f->numVerts]->flags&Edge_eEffected);
- int xLimit = !(FACE_getEdges(f)[S]->flags&Edge_eEffected);
- int yLimitNext = xLimit;
- int xLimitPrev = yLimit;
-
- for (y=0; y<gridSize - 1; y++) {
- for (x=0; x<gridSize - 1; x++) {
- int xPlusOk = (!xLimit || x<gridSize-2);
- int yPlusOk = (!yLimit || y<gridSize-2);
-
- FACE_calcIFNo(f, lvl, S, x, y, no);
-
- NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+0), no);
- if (xPlusOk)
- NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+0), no);
- if (yPlusOk)
- NormAdd(FACE_getIFNo(f, lvl, S, x+0, y+1), no);
- if (xPlusOk && yPlusOk) {
- if (x<gridSize-2 || y<gridSize-2 || FACE_getVerts(f)[S]->flags&Vert_eEffected) {
- NormAdd(FACE_getIFNo(f, lvl, S, x+1, y+1), no);
- }
- }
+ VertDataMulN(FACE_getCenterData(f), 1.0f/f->numVerts);
- if (x==0 && y==0) {
- int K;
+ for (S=0; S<f->numVerts; S++)
+ for (x=1; x<gridSize-1; x++)
+ VertDataMulN(FACE_getIECo(f, lvl, S, x), 0.5f);
- if (!yLimitNext || 1<gridSize-1)
- NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, 1), no);
- if (!xLimitPrev || 1<gridSize-1)
- NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no);
+ for (S=0; S<f->numVerts; S++) {
+ int prevS = (S+f->numVerts-1)%f->numVerts;
+ CCGEdge *e = FACE_getEdges(f)[S];
+ CCGEdge *prevE = FACE_getEdges(f)[prevS];
- for (K=0; K<f->numVerts; K++) {
- if (K!=S) {
- NormAdd(FACE_getIFNo(f, lvl, K, 0, 0), no);
- }
- }
- } else if (y==0) {
- NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no);
- if (!yLimitNext || x<gridSize-2)
- NormAdd(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x+1), no);
- } else if (x==0) {
- NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no);
- if (!xLimitPrev || y<gridSize-2)
- NormAdd(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y+1, 0), no);
- }
- }
- }
+ VertDataCopy(FACE_getIFCo(f, lvl, S, 0, 0), FACE_getCenterData(f));
+ VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, cornerIdx), VERT_getCo(FACE_getVerts(f)[S], lvl));
+
+ for (x=1; x<gridSize-1; x++) {
+ VertDataCopy(FACE_getIFCo(f, lvl, S, x, 0), FACE_getIECo(f, lvl, S, x));
+ VertDataCopy(FACE_getIFCo(f, lvl, S, 0, x), FACE_getIECo(f, lvl, prevS, x));
}
+
+ for (x=0; x<gridSize-1; x++) {
+ int eI = gridSize-1-x;
+ VertDataCopy(FACE_getIFCo(f, lvl, S, cornerIdx, x), _edge_getCoVert(e, FACE_getVerts(f)[S], lvl, eI,vertDataSize));
+ VertDataCopy(FACE_getIFCo(f, lvl, S, x, cornerIdx), _edge_getCoVert(prevE, FACE_getVerts(f)[S], lvl, eI,vertDataSize));
+ }
+
+ VertDataCopy(FACE_getIECo(f, lvl, S, 0), FACE_getCenterData(f));
+ VertDataCopy(FACE_getIECo(f, lvl, S, gridSize-1), FACE_getIFCo(f, lvl, S, gridSize-1, 0));
}
- // XXX can I reduce the number of normalisations here?
- for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
- CCGVert *v = (CCGVert*) effectedV[ptrIdx];
- float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset);
+ }
- NormZero(no);
+ for (i=0; i<numEffectedV; i++)
+ effectedV[i]->flags = 0;
+ for (i=0; i<numEffectedE; i++)
+ effectedE[i]->flags = 0;
+ for (i=0; i<numEffectedF; i++)
+ effectedF[i]->flags = 0;
- for (i=0; i<v->numFaces; i++) {
- CCGFace *f = v->faces[i];
- NormAdd(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1));
- }
+ CCGSUBSURF_free(ss, effectedE);
+ CCGSUBSURF_free(ss, effectedV);
+ if(freeF) CCGSUBSURF_free(ss, effectedF);
- length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
+ return eCCGError_None;
+}
- if (length>FLT_EPSILON) {
- float invLength = 1.0f/length;
- no[0] *= invLength;
- no[1] *= invLength;
- no[2] *= invLength;
- } else {
- NormZero(no);
- }
+/* update normals for specified faces */
+CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **effectedF, int numEffectedF) {
+ CCGVert **effectedV;
+ CCGEdge **effectedE;
+ int i, numEffectedV, numEffectedE, freeF;
- for (i=0; i<v->numFaces; i++) {
- CCGFace *f = v->faces[i];
- NormCopy(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no);
- }
- }
- for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
- CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
+ ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
+ ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
+ &effectedV, &numEffectedV, &effectedE, &numEffectedE);
- if (e->numFaces) {
- CCGFace *fLast = e->faces[e->numFaces-1];
- int x;
+ if (ss->calcVertNormals)
+ ccgSubSurf__calcVertNormals(ss,
+ effectedV, effectedE, effectedF,
+ numEffectedV, numEffectedE, numEffectedF);
- for (i=0; i<e->numFaces-1; i++) {
- CCGFace *f = e->faces[i];
+ for (i=0; i<numEffectedV; i++)
+ effectedV[i]->flags = 0;
+ for (i=0; i<numEffectedE; i++)
+ effectedE[i]->flags = 0;
+ for (i=0; i<numEffectedF; i++)
+ effectedF[i]->flags = 0;
- for (x=1; x<edgeSize-1; x++) {
- NormAdd(_face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
- _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
- }
- }
+ CCGSUBSURF_free(ss, effectedE);
+ CCGSUBSURF_free(ss, effectedV);
+ if(freeF) CCGSUBSURF_free(ss, effectedF);
- for (i=0; i<e->numFaces-1; i++) {
- CCGFace *f = e->faces[i];
+ return eCCGError_None;
+}
- for (x=1; x<edgeSize-1; x++) {
- NormCopy(_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
- _face_getIFNoEdge(fLast, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
- }
- }
- }
- }
- for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
- int S;
+/* compute subdivision levels from a given starting point, used by
+ multires subdivide/propagate, by filling in coordinates at a
+ certain level, and then subdividing that up to the highest level */
+CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, int numEffectedF)
+{
+ CCGVert **effectedV;
+ CCGEdge **effectedE;
+ int numEffectedV, numEffectedE, freeF, i;
+ int curLvl, subdivLevels = ss->subdivLevels;
- for (S=0; S<f->numVerts; S++) {
- NormCopy(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1),
- FACE_getIFNo(f, lvl, S, gridSize-1, 0));
- }
- }
- for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
- CCGFace *f = (CCGFace*) effectedF[ptrIdx];
- int S, x, y;
-
- for (S=0; S<f->numVerts; S++) {
- for (y=0; y<gridSize; y++) {
- for (x=0; x<gridSize; x++) {
- float *no = FACE_getIFNo(f, lvl, S, x, y);
- float length = sqrt(no[0]*no[0] + no[1]*no[1] + no[2]*no[2]);
-
- if (length>FLT_EPSILON) {
- float invLength = 1.0f/length;
- no[0] *= invLength;
- no[1] *= invLength;
- no[2] *= invLength;
- } else {
- NormZero(no);
- }
- }
- }
- }
- }
- }
-#undef FACE_getIFNo
+ ccgSubSurf__allFaces(ss, &effectedF, &numEffectedF, &freeF);
+ ccgSubSurf__effectedFaceNeighbours(ss, effectedF, numEffectedF,
+ &effectedV, &numEffectedV, &effectedE, &numEffectedE);
- for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
- CCGVert *v = effectedV[ptrIdx];
- v->flags = 0;
- }
- for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
- CCGEdge *e = effectedE[ptrIdx];
- e->flags = 0;
+ for (curLvl=lvl; curLvl<subdivLevels; curLvl++) {
+ ccgSubSurf__calcSubdivLevel(ss,
+ effectedV, effectedE, effectedF,
+ numEffectedV, numEffectedE, numEffectedF, curLvl);
}
-#undef VERT_getCo
-#undef EDGE_getCo
-#undef FACE_getIECo
-#undef FACE_getIFCo
+ for (i=0; i<numEffectedV; i++)
+ effectedV[i]->flags = 0;
+ for (i=0; i<numEffectedE; i++)
+ effectedE[i]->flags = 0;
+ for (i=0; i<numEffectedF; i++)
+ effectedF[i]->flags = 0;
- CCGSUBSURF_free(ss, effectedF);
CCGSUBSURF_free(ss, effectedE);
CCGSUBSURF_free(ss, effectedV);
+ if(freeF) CCGSUBSURF_free(ss, effectedF);
+
+ return eCCGError_None;
}
+#undef VERT_getCo
+#undef EDGE_getCo
+#undef FACE_getIECo
+#undef FACE_getIFCo
+
/*** External API accessor functions ***/
int ccgSubSurf_getNumVerts(CCGSubSurf *ss) {
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h
index fbd0aecc0a5..d51cf0128c3 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf.h
@@ -59,6 +59,11 @@ CCGError ccgSubSurf_syncFaceDel (CCGSubSurf *ss, CCGFaceHDL fHDL);
CCGError ccgSubSurf_processSync (CCGSubSurf *ss);
+CCGError ccgSubSurf_updateFromFaces(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces);
+CCGError ccgSubSurf_updateNormals(CCGSubSurf *ss, CCGFace **faces, int numFaces);
+CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces);
+CCGError ccgSubSurf_stitchFaces(CCGSubSurf *ss, int lvl, CCGFace **faces, int numFaces);
+
CCGError ccgSubSurf_setSubdivisionLevels (CCGSubSurf *ss, int subdivisionLevels);
CCGError ccgSubSurf_setAllowEdgeCreation (CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData);