From da01fb62acaa15868738b006b2225d896214b955 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Sun, 3 Apr 2005 21:52:10 +0000 Subject: - added vertex normal calculation functionality to CCG subsurf (CCGSS is fast, but can be rather tedious to work with...) - vertex normals for smooth faces draw correctly now... this code also switched to drawing with GL_QUAD_STRIP which can be quite a bit faster (depends how fast graphics card calcs lighting, I get 50% faster here) --- source/blender/blenkernel/intern/CCGSubSurf.c | 185 +++++++++++++++++++++++++ source/blender/blenkernel/intern/CCGSubSurf.h | 1 + source/blender/blenkernel/intern/subsurf_ccg.c | 122 +++++++++------- 3 files changed, 259 insertions(+), 49 deletions(-) (limited to 'source/blender/blenkernel/intern') diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index d28136d4713..0d0283b8cb6 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "CCGSubSurf.h" @@ -278,6 +279,10 @@ struct _CCGSubSurf { int allowEdgeCreation; void *q, *r; + + // data for calc vert normals + int calcVertNormals; + int normalDataOffset; // data for age'ing (to debug sync) int currentAge; @@ -422,6 +427,11 @@ static void *_edge_getCo(CCGEdge *e, int lvl, int x, int dataSize) { int levelBase = lvl + (1<v0) { @@ -493,6 +503,12 @@ static void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); return &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing)]; } +static float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) { + int maxGridSize = 1 + (1<<(levels-1)); + int spacing = 1<<(levels-lvl); + byte *gridBase = FACE_getCenterData(f) + dataSize*(1 + S*(maxGridSize + maxGridSize*maxGridSize)); + return (float*) &gridBase[dataSize*(maxGridSize + (y*maxGridSize + x)*spacing) + normalDataOffset]; +} static int _face_getVertIndex(CCGFace *f, CCGVert *v) { int i; for (i=0; inumVerts; i++) @@ -530,6 +546,9 @@ static void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, } return _face_getIFCo(f, levels, S, cx, cy, levels, dataSize); } +static float *_face_getIFNoEdge(CCGFace *f, CCGEdge *e, int lvl, int eX, int eY, int levels, int dataSize, int normalDataOffset) { + return (float*) ((byte*) _face_getIFCoEdge(f, e, lvl, eX, eY, levels, dataSize) + normalDataOffset); +} static void _face_free(CCGFace *f, CCGSubSurf *ss) { CCGSUBSURF_free(ss, f); @@ -574,6 +593,9 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, CCGMeshHDL meshData, int subdivLevel ss->useAgeCounts = 0; ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0; + ss->calcVertNormals = 0; + ss->normalDataOffset = 0; + ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); @@ -660,6 +682,22 @@ CCGError ccgSubSurf_setUseAgeCounts(CCGSubSurf *ss, int useAgeCounts, int vertUs return eCCGError_None; } +CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int normalDataOffset) { + if (useVertNormals) { + if (normalDataOffset<0 || normalDataOffset+12>ss->meshIFC.vertDataSize) { + return eCCGError_InvalidValue; + } else { + ss->calcVertNormals = 1; + ss->normalDataOffset = normalDataOffset; + } + } else { + ss->calcVertNormals = 0; + ss->normalDataOffset = 0; + } + + return eCCGError_None; +} + /***/ CCGError ccgSubSurf_initFullSync(CCGSubSurf *ss) { @@ -1660,6 +1698,153 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) { } } } + +#define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset) +#define AddNo(a, b) {a[0]+= b[0], a[1]+= b[1], a[2] += b[2];} +#define CopyNo(a, b) {a[0] = b[0], a[1] = b[1], a[2] = b[2];} + if (ss->calcVertNormals) { + int lvl = ss->subdivLevels; + int edgeSize = 1 + (1<normalDataOffset; + + for (ptrIdx=0; ptrIdxnumVerts; S++) { + for (y=0; ynumVerts; S++) { + for (y=0; ynumVerts, 0, 1), no); + AddNo(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no); + + for (K=0; KnumVerts; K++) { + if (K!=S) { + AddNo(FACE_getIFNo(f, lvl, K, 0, 0), no); + } + } + } else if (y==0) { + AddNo(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x), no); + AddNo(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, x+1), no); + } else if (x==0) { + AddNo(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y, 0), no); + AddNo(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, y+1, 0), no); + } + } + } + } + } + for (ptrIdx=0; ptrIdxnumFaces; i++) { + CCGFace *f = v->faces[i]; + AddNo(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1)); + } + + for (i=0; inumFaces; i++) { + CCGFace *f = v->faces[i]; + CopyNo(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no); + } + } + for (ptrIdx=0; ptrIdxnumFaces; i++) { + CCGFace *f = e->faces[i]; + + for (x=1; xnumFaces; i++) { + CCGFace *f = e->faces[i]; + + for (x=1; xnumVerts; S++) { + CopyNo( FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, gridSize-1), + FACE_getIFNo(f, lvl, S, gridSize-1, 0)); + } + } + for (ptrIdx=0; ptrIdxnumVerts; S++) { + for (y=0; yFLT_EPSILON) { + float invLength = 1.0f/length; + no[0] *= invLength; + no[1] *= invLength; + no[2] *= invLength; + } else { + no[0] = no[1] = no[2] = 0.0; + } + } + } + } + } + } +#undef CopyNo +#undef AddNo +#undef FACE_getIFNo + #undef VERT_getCo #undef EDGE_getCo #undef FACE_getIECo diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h index 84e30b431df..7ebce5b569f 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.h +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -65,6 +65,7 @@ CCGError ccgSubSurf_processSync (CCGSubSurf *ss); CCGError ccgSubSurf_setSubdivisionLevels (CCGSubSurf *ss, int subdivisionLevels); CCGError ccgSubSurf_setAllowEdgeCreation (CCGSubSurf *ss, int allowEdgeCreation); CCGError ccgSubSurf_setUseAgeCounts (CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset); +CCGError ccgSubSurf_setCalcVertexNormals (CCGSubSurf *ss, int useVertNormals, int normalDataOffset); /***/ diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 35a5091c9ca..d1323b6e69f 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -72,6 +72,11 @@ typedef struct _SubSurf { Mesh *me; } SubSurf; +typedef struct _VertData { + float co[3]; + float no[3]; +} VertData; + static void _subsurfNew_meshIFC_vertDataCopy(CCGMeshHDL mv, void *tv, void *av) { float *t= tv, *a= av; t[0]= a[0]; @@ -140,7 +145,7 @@ static CCGSubSurf *_getSubSurf(SubSurf *ss, int subdivLevels, int useArena) { } else { ifc.vertUserSize = ifc.edgeUserSize = ifc.faceUserSize = 4; } - ifc.vertDataSize= 12; + ifc.vertDataSize= sizeof(VertData); ifc.vertDataZero= _subsurfNew_meshIFC_vertDataZero; ifc.vertDataEqual= _subsurfNew_meshIFC_vertDataEqual; ifc.vertDataCopy= _subsurfNew_meshIFC_vertDataCopy; @@ -166,6 +171,8 @@ static CCGSubSurf *_getSubSurf(SubSurf *ss, int subdivLevels, int useArena) { ccgSubSurf_setUseAgeCounts(ccgSS, 1, 4, 8, 4); } + ccgSubSurf_setCalcVertexNormals(ccgSS, 1, BLI_STRUCT_OFFSET(VertData, no)); + return ccgSS; } @@ -565,10 +572,10 @@ static void subSurf_sync(SubSurf *ss) { int i; for (i=0; ime->totvert; i++) { - ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, ss->me->mvert[i].co); + ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, subSurf->me->mvert[i].co); } - if (ss->me->medge) { + if (subSurf->me->medge) { for (i=0; ime->totedge; i++) { MEdge *med = &ss->me->medge[i]; float crease = med->crease*creaseFactor/255.0f; @@ -670,7 +677,7 @@ static void ccgDM_drawEdges(DerivedMesh *dm) { for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { CCGEdge *e = ccgEdgeIterator_getCurrent(ei); EditEdge *eed= ccgSubSurf_getEdgeEdgeHandle(ss, e); - float (*edgeData)[3] = ccgSubSurf_getEdgeDataArray(ss, e); + VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); if (eed->h!=0) continue; @@ -682,8 +689,8 @@ static void ccgDM_drawEdges(DerivedMesh *dm) { glBegin(GL_LINE_STRIP); for (i=0; iflag&ME_AUTOSMOOTH) && (efa->flag&ME_SMOOTH); - setMaterial(efa->mat_nr+1); if (efa->h!=0) continue; + setMaterial(efa->mat_nr+1); + glShadeModel(isSmooth?GL_SMOOTH:GL_FLAT); for (S=0; Sno); + glVertex3fv(a->co); + glNormal3fv(b->no); + glVertex3fv(b->co); } + glEnd(); + } + } else { + glBegin(GL_QUADS); + for (y=0; yss->subSurf; CCGEdgeIterator *ei = ccgSubSurf_getEdgeIterator(ss); CCGEdge *e = ccgSubSurf_getEdge(ss, edge); - float (*edgeData)[3] = ccgSubSurf_getEdgeDataArray(ss, e); + VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); int i, edgeSize = ccgSubSurf_getEdgeSize(ss); glBegin(GL_LINE_STRIP); for (i=0; i0?ageCol:0, 0); } - glVertex3fv(edgeData[i]); + glVertex3fv(edgeData[i].co); } } glEnd(); @@ -927,13 +951,13 @@ static void ccgDM_drawMappedFacesEM(DerivedMesh *dm, int (*setDrawOptions)(void int S, x, y, numVerts= ccgSubSurf_getFaceNumVerts(ss, f); for (S=0; S