- Hacked in blender style creasing support to new subsurfs.
authorDaniel Dunbar <daniel@zuster.org>
Tue, 22 Mar 2005 06:11:25 +0000 (06:11 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Tue, 22 Mar 2005 06:11:25 +0000 (06:11 +0000)
I would like to have proper creasing (following what appears to be
the informal standard in the subdivision surface literature) but
I do not know when I will get to this or how complicated it will
be. With this patch CCGSubSurfs should now have the same capabilities
as regular subsurfs (barring possible bugs) and so replacing the
old implementation is a reasonable possibility.

source/blender/blenkernel/intern/CCGSubSurf.c
source/blender/blenkernel/intern/CCGSubSurf.h
source/blender/blenkernel/intern/subsurf_ccg.c

index 8c2d0f6e80dbd6b79fbcb38d0d41d494b07133e2..906e390d8fd4603b62cfa60e02dabc89a28895f8 100644 (file)
@@ -4,9 +4,12 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 
 #include "CCGSubSurf.h"
 
+#define USE_CREASING
+
 /***/
 
 typedef unsigned char  byte;
@@ -462,6 +465,15 @@ static void _edge_unlinkMarkAndFree(CCGEdge *e, CCGSubSurf *ss) {
        _edge_free(e, ss);
 }
 
+#ifdef USE_CREASING
+float EDGE_getSharpness(CCGEdge *e, int lvl, CCGSubSurf *ss) {
+       float f,sharpness = f=(((float*) ccgSubSurf_getEdgeUserData(ss, e))[1]);
+       while ((sharpness>1.0) && lvl--)
+               sharpness -= 1.0;
+       return sharpness;
+}
+#endif
+
 /***/
 
 static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int numVerts, int levels, int dataSize, CCGSubSurf *ss) {
@@ -1098,17 +1110,45 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
        for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
                CCGFace *f = effectedF[ptrIdx];
                void *co = FACE_getCenterData(f);
-               f->flags = 0;
                ss->meshIFC.vertDataZero(ss->meshData, co);
                for (i=0; i<f->numVerts; i++) {
                        ss->meshIFC.vertDataAdd(ss->meshData, co, VERT_getCo(FACE_getVerts(f)[i], curLvl));
                }
                ss->meshIFC.vertDataMulN(ss->meshData, co, 1.0f/f->numVerts);
+
+               f->flags = 0;
        }
        for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
                CCGEdge *e = effectedE[ptrIdx];
                void *co = EDGE_getCo(e, nextLvl, 1);
-               e->flags = 0;
+#ifdef USE_CREASING
+               float sharpness = EDGE_getSharpness(e, curLvl, ss);
+
+               if (_edge_isBoundary(e) || sharpness>=1.0) {
+                       ss->meshIFC.vertDataCopy(ss->meshData, co, VERT_getCo(e->v0, curLvl));
+                       ss->meshIFC.vertDataAdd(ss->meshData, co, VERT_getCo(e->v1, curLvl));
+                       ss->meshIFC.vertDataMulN(ss->meshData, co, 0.5f);
+               } else {
+                       int numFaces = 0;
+                       ss->meshIFC.vertDataCopy(ss->meshData, q, VERT_getCo(e->v0, curLvl));
+                       ss->meshIFC.vertDataAdd(ss->meshData, q, VERT_getCo(e->v1, curLvl));
+                       for (i=0; i<e->numFaces; i++) {
+                               CCGFace *f = e->faces[i];
+                               ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getCenterData(f));
+                               numFaces++;
+                       }
+                       ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/(2.0f+numFaces));
+
+                       ss->meshIFC.vertDataCopy(ss->meshData, r, VERT_getCo(e->v0, curLvl));
+                       ss->meshIFC.vertDataAdd(ss->meshData, r, VERT_getCo(e->v1, curLvl));
+                       ss->meshIFC.vertDataMulN(ss->meshData, r, 0.5f);
+
+                       ss->meshIFC.vertDataCopy(ss->meshData, co, q);
+                       ss->meshIFC.vertDataSub(ss->meshData, r, q);
+                       ss->meshIFC.vertDataMulN(ss->meshData, r, sharpness);
+                       ss->meshIFC.vertDataAdd(ss->meshData, co, r);
+               }
+#else
                if (_edge_isBoundary(e)) {
                        ss->meshIFC.vertDataCopy(ss->meshData, co, VERT_getCo(e->v0, curLvl));
                        ss->meshIFC.vertDataAdd(ss->meshData, co, VERT_getCo(e->v1, curLvl));
@@ -1124,13 +1164,95 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
                        }
                        ss->meshIFC.vertDataMulN(ss->meshData, co, 1.0f/(2.0f+numFaces));
                }
+#endif
+
+               e->flags = 0;
        }
        for (ptrIdx=0; ptrIdx<numEffectedV; ptrIdx++) {
                CCGVert *v = effectedV[ptrIdx];
                void *co = VERT_getCo(v, curLvl);
                void *nCo = VERT_getCo(v, nextLvl);
-               v->flags = 0;
 
+#ifdef USE_CREASING
+               int sharpCount = 0;
+               float avgSharpness = 0.0;
+               CCGVert *sharpV0 = NULL, *sharpV1 = NULL;
+
+               for (i=0; i<v->numEdges; i++) {
+                       CCGEdge *e = v->edges[i];
+                       float sharpness = EDGE_getSharpness(e, curLvl, ss);
+
+                       if (sharpness!=0.0f) {
+                               sharpCount++;
+                               avgSharpness += sharpness;
+
+                               if (!sharpV0) {
+                                       sharpV0 = _edge_getOtherVert(e, v);
+                               } else if (!sharpV1) {
+                                       sharpV1 = _edge_getOtherVert(e, v);
+                               }
+                       }
+               }
+
+               avgSharpness /= sharpCount;
+               if (avgSharpness>1.0) {
+                       avgSharpness = 1.0;
+               }
+
+               if (!v->numEdges || sharpCount>2) {
+                       ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
+               } else if (_vert_isBoundary(v) && sharpCount<2) {
+                       int numBoundary = 0;
+
+                       ss->meshIFC.vertDataZero(ss->meshData, r);
+                       for (i=0; i<v->numEdges; i++) {
+                               CCGEdge *e = v->edges[i];
+                               if (_edge_isBoundary(e)) {
+                                       ss->meshIFC.vertDataAdd(ss->meshData, r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
+                                       numBoundary++;
+                               }
+                       }
+                       ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
+                       ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.75);
+                       ss->meshIFC.vertDataMulN(ss->meshData, r, 0.25f/numBoundary);
+                       ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
+               } else {
+                       int numEdges = 0, numFaces = 0;
+
+                       ss->meshIFC.vertDataZero(ss->meshData, q);
+                       for (i=0; i<v->numFaces; i++) {
+                               CCGFace *f = v->faces[i];
+                               ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getCenterData(f));
+                               numFaces++;
+                       }
+                       ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/numFaces);
+                       ss->meshIFC.vertDataZero(ss->meshData, r);
+                       for (i=0; i<v->numEdges; i++) {
+                               CCGEdge *e = v->edges[i];
+                               ss->meshIFC.vertDataAdd(ss->meshData, r, VERT_getCo(_edge_getOtherVert(e, v), curLvl));
+                               numEdges++;
+                       }
+                       ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0f/numEdges);
+
+                       ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
+                       ss->meshIFC.vertDataMulN(ss->meshData, nCo, numEdges-2.0f);
+                       ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
+                       ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
+                       ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/numEdges);
+
+                       if (sharpCount==2) {
+                               ss->meshIFC.vertDataCopy(ss->meshData, q, co);
+                               ss->meshIFC.vertDataMulN(ss->meshData, q, 6.0f);
+                               ss->meshIFC.vertDataAdd(ss->meshData, q, VERT_getCo(sharpV0, curLvl));
+                               ss->meshIFC.vertDataAdd(ss->meshData, q, VERT_getCo(sharpV1, curLvl));
+                               ss->meshIFC.vertDataMulN(ss->meshData, q, 1/8.0f);
+
+                               ss->meshIFC.vertDataSub(ss->meshData, q, nCo);
+                               ss->meshIFC.vertDataMulN(ss->meshData, q, avgSharpness);
+                               ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
+                       }
+               }
+#else
                if (!v->numEdges) {
                        ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
                } else if (_vert_isBoundary(v)) {
@@ -1172,6 +1294,9 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
                        ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
                        ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/numEdges);
                }
+#endif
+
+               v->flags = 0;
        }
 
        if (ss->useAgeCounts) {
@@ -1302,6 +1427,50 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
                for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
                        CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
 
+#ifdef USE_CREASING
+                       float sharpness = EDGE_getSharpness(e, curLvl, ss);
+
+                       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);
+
+                                       ss->meshIFC.vertDataCopy(ss->meshData, co, co0);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, co, co1);
+                                       ss->meshIFC.vertDataMulN(ss->meshData, 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;
+
+                                       ss->meshIFC.vertDataCopy(ss->meshData, q, co0);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, q, co1);
+
+                                       for (i=0; i<e->numFaces; i++) {
+                                               CCGFace *f = e->faces[i];
+                                               ss->meshIFC.vertDataAdd(ss->meshData, q, _face_getIFCoEdge(f, e, nextLvl, fx, 1, subdivLevels, vertDataSize));
+                                               numFaces++;
+                                       }
+
+                                       ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/(2.0f+numFaces));
+
+                                       ss->meshIFC.vertDataCopy(ss->meshData, r, co0);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, r, co1);
+                                       ss->meshIFC.vertDataMulN(ss->meshData, r, 0.5);
+
+                                       ss->meshIFC.vertDataCopy(ss->meshData, co, q);
+                                       ss->meshIFC.vertDataSub(ss->meshData, r, q);
+                                       ss->meshIFC.vertDataMulN(ss->meshData, r, sharpness);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, co, r);
+                               }
+                       }
+#else
                        if (_edge_isBoundary(e)) {
                                for (x=0; x<edgeSize-1; x++) {
                                        int fx = x*2 + 1;
@@ -1333,6 +1502,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
                                        ss->meshIFC.vertDataMulN(ss->meshData, co, 1.0f/(2.0f+numFaces));
                                }
                        }
+#endif
                }
 
                        /* exterior vertex shift
@@ -1345,6 +1515,88 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
                        void *co = VERT_getCo(v, curLvl);
                        void *nCo = VERT_getCo(v, nextLvl);
 
+#ifdef USE_CREASING
+                       int sharpCount = 0;
+                       float avgSharpness = 0.0;
+                       CCGEdge *sharpE0 = NULL, *sharpE1 = NULL;
+
+                       for (i=0; i<v->numEdges; i++) {
+                               CCGEdge *e = v->edges[i];
+                               float sharpness = EDGE_getSharpness(e, curLvl, ss);
+
+                               if (sharpness!=0.0f) {
+                                       sharpCount++;
+                                       avgSharpness += sharpness;
+
+                                       if (!sharpE0) {
+                                               sharpE0 = e;
+                                       } else if (!sharpE1) {
+                                               sharpE1 = e;
+                                       }
+                               }
+                       }
+
+                       avgSharpness /= sharpCount;
+                       if (avgSharpness>1.0) {
+                               avgSharpness = 1.0;
+                       }
+
+                       if (!v->numEdges || sharpCount>2) {
+                               ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
+                       } else if (_vert_isBoundary(v) && sharpCount<2) {
+                               int numBoundary = 0;
+
+                               ss->meshIFC.vertDataZero(ss->meshData, r);
+                               for (i=0; i<v->numEdges; i++) {
+                                       CCGEdge *e = v->edges[i];
+                                       if (_edge_isBoundary(e)) {
+                                               ss->meshIFC.vertDataAdd(ss->meshData, r, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
+                                               numBoundary++;
+                                       }
+                               }
+
+                               ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
+                               ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.75);
+                               ss->meshIFC.vertDataMulN(ss->meshData, r, 0.25f/numBoundary);
+                               ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
+                       } else {
+                               int cornerIdx = (1 + (1<<(curLvl))) - 2;
+                               int numEdges = 0, numFaces = 0;
+
+                               ss->meshIFC.vertDataZero(ss->meshData, q);
+                               for (i=0; i<v->numFaces; i++) {
+                                       CCGFace *f = v->faces[i];
+                                       ss->meshIFC.vertDataAdd(ss->meshData, q, FACE_getIFCo(f, nextLvl, _face_getVertIndex(f,v), cornerIdx, cornerIdx));
+                                       numFaces++;
+                               }
+                               ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0f/numFaces);
+                               ss->meshIFC.vertDataZero(ss->meshData, r);
+                               for (i=0; i<v->numEdges; i++) {
+                                       CCGEdge *e = v->edges[i];
+                                       ss->meshIFC.vertDataAdd(ss->meshData, r, _edge_getCoVert(e, v, curLvl, 1,vertDataSize));
+                                       numEdges++;
+                               }
+                               ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0f/numEdges);
+
+                               ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
+                               ss->meshIFC.vertDataMulN(ss->meshData, nCo, numEdges-2.0f);
+                               ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
+                               ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
+                               ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/numEdges);
+
+                               if (sharpCount==2) {
+                                       ss->meshIFC.vertDataCopy(ss->meshData, q, co);
+                                       ss->meshIFC.vertDataMulN(ss->meshData, q, 6.0f);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, q, _edge_getCoVert(sharpE0, v, curLvl, 1, vertDataSize));
+                                       ss->meshIFC.vertDataAdd(ss->meshData, q, _edge_getCoVert(sharpE1, v, curLvl, 1, vertDataSize));
+                                       ss->meshIFC.vertDataMulN(ss->meshData, q, 1/8.0f);
+
+                                       ss->meshIFC.vertDataSub(ss->meshData, q, nCo);
+                                       ss->meshIFC.vertDataMulN(ss->meshData, q, avgSharpness);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
+                               }
+                       }
+#else
                        if (!v->numEdges) {
                                ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
                        } else if (_vert_isBoundary(v)) {
@@ -1388,6 +1640,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
                                ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
                                ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/numEdges);
                        }
+#endif
                }
 
                        /* exterior edge interior shift
@@ -1398,6 +1651,80 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
                for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
                        CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
 
+#ifdef USE_CREASING
+                       float sharpness = EDGE_getSharpness(e, curLvl, ss);
+                       int sharpCount = 0;
+                       float avgSharpness = 0.0;
+                       CCGVert *sharpV0 = NULL, *sharpV1 = NULL;
+
+                       if (sharpness!=0.0f) {
+                               sharpCount = 2;
+                               avgSharpness += 2*sharpness;
+                       } else {
+                               sharpCount = 0;
+                               avgSharpness = 0;
+                       }
+
+                       avgSharpness /= sharpCount;
+                       if (avgSharpness>1.0) {
+                               avgSharpness = 1.0;
+                       }
+
+                       if (_edge_isBoundary(e) && 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);
+                                       ss->meshIFC.vertDataCopy(ss->meshData, r, EDGE_getCo(e, curLvl, x-1));
+                                       ss->meshIFC.vertDataAdd(ss->meshData, r, EDGE_getCo(e, curLvl, x+1));
+                                       ss->meshIFC.vertDataMulN(ss->meshData, r, 0.5);
+                                       ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
+                                       ss->meshIFC.vertDataMulN(ss->meshData, nCo, 0.75);
+                                       ss->meshIFC.vertDataMulN(ss->meshData, r, 0.25);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
+                               }
+                       } else {
+                               for (x=1; 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;
+
+                                       ss->meshIFC.vertDataZero(ss->meshData, q);
+                                       ss->meshIFC.vertDataZero(ss->meshData, r);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, r, EDGE_getCo(e, curLvl, x-1));
+                                       ss->meshIFC.vertDataAdd(ss->meshData, r, EDGE_getCo(e, curLvl, x+1));
+                                       for (i=0; i<e->numFaces; i++) {
+                                               CCGFace *f = e->faces[i];
+                                               ss->meshIFC.vertDataAdd(ss->meshData, q, _face_getIFCoEdge(f, e, nextLvl, fx-1, 1, subdivLevels, vertDataSize));
+                                               ss->meshIFC.vertDataAdd(ss->meshData, q, _face_getIFCoEdge(f, e, nextLvl, fx+1, 1, subdivLevels, vertDataSize));
+
+                                               ss->meshIFC.vertDataAdd(ss->meshData, r, _face_getIFCoEdge(f, e, curLvl, x, 1, subdivLevels, vertDataSize));
+                                               numFaces++;
+                                       }
+                                       ss->meshIFC.vertDataMulN(ss->meshData, q, 1.0/(numFaces*2.0f));
+                                       ss->meshIFC.vertDataMulN(ss->meshData, r, 1.0/(2.0f + numFaces));
+
+                                       ss->meshIFC.vertDataCopy(ss->meshData, nCo, co);
+                                       ss->meshIFC.vertDataMulN(ss->meshData, nCo, (float) numFaces);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
+                                       ss->meshIFC.vertDataAdd(ss->meshData, nCo, r);
+                                       ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/(2+numFaces));
+
+                                       if (sharpCount==2) {
+                                               ss->meshIFC.vertDataCopy(ss->meshData, q, co);
+                                               ss->meshIFC.vertDataMulN(ss->meshData, q, 6.0f);
+                                               ss->meshIFC.vertDataAdd(ss->meshData, q, EDGE_getCo(e, curLvl, x-1));
+                                               ss->meshIFC.vertDataAdd(ss->meshData, q, EDGE_getCo(e, curLvl, x+1));
+                                               ss->meshIFC.vertDataMulN(ss->meshData, q, 1/8.0f);
+
+                                               ss->meshIFC.vertDataSub(ss->meshData, q, nCo);
+                                               ss->meshIFC.vertDataMulN(ss->meshData, q, avgSharpness);
+                                               ss->meshIFC.vertDataAdd(ss->meshData, nCo, q);
+                                       }
+                               }
+                       }
+#else
                        if (_edge_isBoundary(e)) {
                                for (x=1; x<edgeSize-1; x++) {
                                        int fx = x*2;
@@ -1440,6 +1767,7 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
                                        ss->meshIFC.vertDataMulN(ss->meshData, nCo, 1.0f/(2+numFaces));
                                }
                        }
+#endif
                }
 
                for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
@@ -1580,6 +1908,16 @@ int ccgSubSurf_getNumFaces(CCGSubSurf *ss) {
        return ss->fMap->numEntries;
 }
 
+CCGVert *ccgSubSurf_getVert(CCGSubSurf *ss, CCGVertHDL v) {
+       return (CCGVert*) _ehash_lookup(ss->vMap, v);
+}
+CCGEdge *ccgSubSurf_getEdge(CCGSubSurf *ss, CCGEdgeHDL e) {
+       return (CCGEdge*) _ehash_lookup(ss->eMap, e);
+}
+CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f) {
+       return (CCGFace*) _ehash_lookup(ss->fMap, f);
+}
+
 int ccgSubSurf_getSubdivisionLevels(CCGSubSurf *ss) {
        return ss->subdivLevels;
 }
index e1f00ea1048449a388235c263ce7138e0c179bb8..f9d8da6bf363eed7c3fb97babda72d09e1057fd2 100644 (file)
@@ -97,6 +97,7 @@ int                   ccgSubSurf_getEdgeLevelSize                     (CCGSubSurf *ss, int level);
 int                    ccgSubSurf_getGridSize                          (CCGSubSurf *ss);
 int                    ccgSubSurf_getGridLevelSize                     (CCGSubSurf *ss, int level);
 
+CCGVert*       ccgSubSurf_getVert                                      (CCGSubSurf *ss, CCGVertHDL v);
 CCGVertHDL     ccgSubSurf_getVertVertHandle            (CCGSubSurf *ss, CCGVert *v);
 int                    ccgSubSurf_getVertNumFaces                      (CCGSubSurf *ss, CCGVert *v);
 CCGFace*       ccgSubSurf_getVertFace                          (CCGSubSurf *ss, CCGVert *v, int index);
@@ -108,6 +109,7 @@ void*               ccgSubSurf_getVertUserData                      (CCGSubSurf *ss, CCGVert *v);
 void*          ccgSubSurf_getVertData                          (CCGSubSurf *ss, CCGVert *v);
 void*          ccgSubSurf_getVertLevelData                     (CCGSubSurf *ss, CCGVert *v, int level);
 
+CCGEdge*       ccgSubSurf_getEdge                                      (CCGSubSurf *ss, CCGEdgeHDL e);
 CCGEdgeHDL     ccgSubSurf_getEdgeEdgeHandle            (CCGSubSurf *ss, CCGEdge *e);
 int                    ccgSubSurf_getEdgeNumFaces                      (CCGSubSurf *ss, CCGEdge *e);
 CCGFace*       ccgSubSurf_getEdgeFace                          (CCGSubSurf *ss, CCGEdge *e, int index);
@@ -120,6 +122,7 @@ void*               ccgSubSurf_getEdgeDataArray                     (CCGSubSurf *ss, CCGEdge *e);
 void*          ccgSubSurf_getEdgeData                          (CCGSubSurf *ss, CCGEdge *e, int x);
 void*          ccgSubSurf_getEdgeLevelData                     (CCGSubSurf *ss, CCGEdge *e, int x, int level);
 
+CCGFace*       ccgSubSurf_getFace                                      (CCGSubSurf *ss, CCGFaceHDL f);
 CCGFaceHDL     ccgSubSurf_getFaceFaceHandle            (CCGSubSurf *ss, CCGFace *f);
 int                    ccgSubSurf_getFaceNumVerts                      (CCGSubSurf *ss, CCGFace *f);
 CCGVert*       ccgSubSurf_getFaceVert                          (CCGSubSurf *ss, CCGFace *f, int index);
index 1fe71c747917111c38f805f96ced992ba3d21fd8..8a4c0c2064e52e215ea799963264470d8f5b800c 100644 (file)
@@ -24,6 +24,8 @@
 
 #include "CCGSubSurf.h"
 
+#define USE_CREASING
+
 typedef struct _SubSurf {
        CCGSubSurf *subSurf;
 
@@ -102,7 +104,7 @@ static CCGSubSurf *_getSubSurf(SubSurf *ss, int subdivLevels) {
        CCGAllocatorHDL allocator;
 
        ifc.vertUserSize = 4;
-       ifc.edgeUserSize = 4;
+       ifc.edgeUserSize = 8;
        ifc.faceUserSize = 4;
        ifc.vertDataSize= 12;
        ifc.vertDataZero= _subsurfNew_meshIFC_vertDataZero;
@@ -525,6 +527,8 @@ static DispListMesh *subSurf_createDispListMesh(SubSurf *ssm, int doOptEdges) {
 }
 
 static void subSurf_sync(SubSurf *ss) {
+       float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss->subSurf);
+
        ccgSubSurf_initFullSync(ss->subSurf);
 
        if (ss->controlType==SUBSURF_CONTROLTYPE_MESH) {
@@ -543,6 +547,15 @@ static void subSurf_sync(SubSurf *ss) {
                                MEdge *med = &ss->me->medge[i];
 
                                ccgSubSurf_syncEdge(ss->subSurf, (CCGEdgeHDL) i, (CCGVertHDL) med->v1, (CCGVertHDL) med->v2);
+
+#ifdef USE_CREASING
+                               {
+                                       CCGEdge *e = ccgSubSurf_getEdge(ss->subSurf, (CCGEdgeHDL) i);
+                                       float *userData = ccgSubSurf_getEdgeUserData(ss->subSurf, e);
+
+                                       userData[1] = med->crease*creaseFactor/255.0f;
+                               }
+#endif
                        }
                } else {
                        for (i=0; i<ss->me->totface; i++) {
@@ -567,25 +580,34 @@ static void subSurf_sync(SubSurf *ss) {
                        }
                }
        } else {
-               EditVert *v, *fVerts[4];
-               EditEdge *e;
-               EditFace *f;
+               EditVert *ev, *fVerts[4];
+               EditEdge *ee;
+               EditFace *ef;
 
-               for (v=ss->em->verts.first; v; v=v->next) {
-                       ccgSubSurf_syncVert(ss->subSurf, v, v->co);
+               for (ev=ss->em->verts.first; ev; ev=ev->next) {
+                       ccgSubSurf_syncVert(ss->subSurf, ev, ev->co);
                }
 
-               for (e=ss->em->edges.first; e; e=e->next) {
-                       ccgSubSurf_syncEdge(ss->subSurf, e, e->v1, e->v2);
+               for (ee=ss->em->edges.first; ee; ee=ee->next) {
+                       ccgSubSurf_syncEdge(ss->subSurf, ee, ee->v1, ee->v2);
+
+#ifdef USE_CREASING
+                       {
+                               CCGEdge *e = ccgSubSurf_getEdge(ss->subSurf, ee);
+                               float *userData = ccgSubSurf_getEdgeUserData(ss->subSurf, e);
+
+                               userData[1] = ee->crease*creaseFactor;
+                       }
+#endif
                }
 
-               for (f=ss->em->faces.first; f; f=f->next) {
-                       fVerts[0] = f->v1;
-                       fVerts[1] = f->v2;
-                       fVerts[2] = f->v3;
-                       fVerts[3] = f->v4;
+               for (ef=ss->em->faces.first; ef; ef=ef->next) {
+                       fVerts[0] = ef->v1;
+                       fVerts[1] = ef->v2;
+                       fVerts[2] = ef->v3;
+                       fVerts[3] = ef->v4;
 
-                       ccgSubSurf_syncFace(ss->subSurf, f, f->v4?4:3, fVerts);
+                       ccgSubSurf_syncFace(ss->subSurf, ef, ef->v4?4:3, fVerts);
                }
        }