- 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)
This commit is contained in:
Daniel Dunbar
2005-04-03 21:52:10 +00:00
parent a5e55df5ec
commit da01fb62ac
3 changed files with 259 additions and 49 deletions

View File

@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>
#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<<lvl) - 1;
return &EDGE_getLevelData(e)[dataSize*(levelBase + x)];
}
static float *_edge_getNo(CCGEdge *e, int lvl, int x, int dataSize, int normalDataOffset) {
int levelBase = lvl + (1<<lvl) - 1;
return (float*) &EDGE_getLevelData(e)[dataSize*(levelBase + x) + normalDataOffset];
}
static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSize) {
int levelBase = lvl + (1<<lvl) - 1;
if (v==e->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; i<f->numVerts; 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<<lvl);
int gridSize = 1 + (1<<(lvl-1));
int normalDataOffset = ss->normalDataOffset;
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);
no[0] = no[1] = no[2] = 0.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-1; y++) {
for (x=0; x<gridSize-1; x++) {
float *a = FACE_getIFCo(f, lvl, S, x+0, y+0);
float *b = FACE_getIFCo(f, lvl, S, x+1, y+0);
float *c = FACE_getIFCo(f, lvl, S, x+1, y+1);
float *d = FACE_getIFCo(f, lvl, S, x+0, y+1);
float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
float no[3];
no[0] = b_dY*a_cZ - b_dZ*a_cY;
no[1] = b_dZ*a_cX - b_dX*a_cZ;
no[2] = b_dX*a_cY - b_dY*a_cX;
AddNo(FACE_getIFNo(f, lvl, S, x+0, y+0), no);
AddNo(FACE_getIFNo(f, lvl, S, x+1, y+0), no);
AddNo(FACE_getIFNo(f, lvl, S, x+1, y+1), no);
AddNo(FACE_getIFNo(f, lvl, S, x+0, y+1), no);
if (x==0 && y==0) {
int K;
AddNo(FACE_getIFNo(f, lvl, (S+1)%f->numVerts, 0, 1), no);
AddNo(FACE_getIFNo(f, lvl, (S-1+f->numVerts)%f->numVerts, 1, 0), no);
for (K=0; K<f->numVerts; 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; ptrIdx<numEffectedV; ptrIdx++) {
CCGVert *v = (CCGVert*) effectedV[ptrIdx];
float no[3] = {0};
for (i=0; i<v->numFaces; i++) {
CCGFace *f = v->faces[i];
AddNo(no, FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1));
}
for (i=0; i<v->numFaces; i++) {
CCGFace *f = v->faces[i];
CopyNo(FACE_getIFNo(f, lvl, _face_getVertIndex(f,v), gridSize-1, gridSize-1), no);
}
}
for (ptrIdx=0; ptrIdx<numEffectedE; ptrIdx++) {
CCGEdge *e = (CCGEdge*) effectedE[ptrIdx];
int x;
for (x=0; x<edgeSize; x++) {
float *no = _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset);
no[0] = no[1] = no[2] = 0.0;
}
for (i=0; i<e->numFaces; i++) {
CCGFace *f = e->faces[i];
for (x=1; x<edgeSize-1; x++) {
AddNo( _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset),
_face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset));
}
}
for (i=0; i<e->numFaces; i++) {
CCGFace *f = e->faces[i];
for (x=1; x<edgeSize-1; x++) {
CopyNo( _face_getIFNoEdge(f, e, lvl, x, 0, subdivLevels, vertDataSize, normalDataOffset),
_edge_getNo(e, lvl, x, vertDataSize, normalDataOffset));
}
}
}
for (ptrIdx=0; ptrIdx<numEffectedF; ptrIdx++) {
CCGFace *f = (CCGFace*) effectedF[ptrIdx];
int S;
for (S=0; S<f->numVerts; S++) {
CopyNo( 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 {
no[0] = no[1] = no[2] = 0.0;
}
}
}
}
}
}
#undef CopyNo
#undef AddNo
#undef FACE_getIFNo
#undef VERT_getCo
#undef EDGE_getCo
#undef FACE_getIECo

View File

@@ -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);
/***/

View File

@@ -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; i<ss->me->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; i<ss->me->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; i<edgeSize-1; i++) {
glVertex3fv(edgeData[i]);
glVertex3fv(edgeData[i+1]);
glVertex3fv(edgeData[i].co);
glVertex3fv(edgeData[i+1].co);
}
glEnd();
}
@@ -701,22 +708,22 @@ static void ccgDM_drawEdges(DerivedMesh *dm) {
continue;
for (S=0; S<numVerts; S++) {
float (*faceGridData)[3] = ccgSubSurf_getFaceGridDataArray(ss, f, S);
VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
glBegin(GL_LINE_STRIP);
for (x=0; x<gridSize; x++)
glVertex3fv(faceGridData[x]);
glVertex3fv(faceGridData[x].co);
glEnd();
for (y=1; y<gridSize-1; y++) {
glBegin(GL_LINE_STRIP);
for (x=0; x<gridSize; x++)
glVertex3fv(faceGridData[y*gridSize + x]);
glVertex3fv(faceGridData[y*gridSize + x].co);
glEnd();
}
for (x=1; x<gridSize-1; x++) {
glBegin(GL_LINE_STRIP);
for (y=0; y<gridSize; y++)
glVertex3fv(faceGridData[y*gridSize + x]);
glVertex3fv(faceGridData[y*gridSize + x].co);
glEnd();
}
}
@@ -733,12 +740,12 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm) {
for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
float (*edgeData)[3] = ccgSubSurf_getEdgeDataArray(ss, e);
VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
glBegin(GL_LINE_STRIP);
for (i=0; i<edgeSize-1; i++) {
glVertex3fv(edgeData[i]);
glVertex3fv(edgeData[i+1]);
glVertex3fv(edgeData[i].co);
glVertex3fv(edgeData[i+1].co);
}
glEnd();
}
@@ -755,12 +762,12 @@ static void ccgDM_drawLooseEdges(DerivedMesh *dm) {
CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
if (!ccgSubSurf_getEdgeNumFaces(ss, e)) {
float (*edgeData)[3] = ccgSubSurf_getEdgeDataArray(ss, e);
VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
glBegin(GL_LINE_STRIP);
for (i=0; i<edgeSize-1; i++) {
glVertex3fv(edgeData[i]);
glVertex3fv(edgeData[i+1]);
glVertex3fv(edgeData[i].co);
glVertex3fv(edgeData[i+1].co);
}
glEnd();
}
@@ -779,38 +786,55 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, void (*setMaterial)(int)) {
CCGFace *f= ccgFaceIterator_getCurrent(fi);
EditFace *efa= ccgSubSurf_getFaceFaceHandle(ss, f);
int S, x, y, numVerts= ccgSubSurf_getFaceNumVerts(ss, f);
int isSmooth = !(me->flag&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; S<numVerts; S++) {
float (*faceGridData)[3] = ccgSubSurf_getFaceGridDataArray(ss, f, S);
VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
for (y=0; y<gridSize-1; y++) {
if (isSmooth) {
for (y=0; y<gridSize-1; y++) {
glBegin(GL_QUAD_STRIP);
for (x=0; x<gridSize; x++) {
VertData *a = &faceGridData[(y+0)*gridSize + x];
VertData *b = &faceGridData[(y+1)*gridSize + x];
glBegin(GL_QUADS);
for (x=0; x<gridSize-1; x++) {
float *a = faceGridData[(y+0)*gridSize + x];
float *b = faceGridData[(y+0)*gridSize + x + 1];
float *c = faceGridData[(y+1)*gridSize + x + 1];
float *d = faceGridData[(y+1)*gridSize + x];
if (x<gridSize-1) {
float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
float no[3];
no[0] = b_dY*a_cZ - b_dZ*a_cY;
no[1] = b_dZ*a_cX - b_dX*a_cZ;
no[2] = b_dX*a_cY - b_dY*a_cX;
glNormal3fv(no);
glNormal3fv(a->no);
glVertex3fv(a->co);
glNormal3fv(b->no);
glVertex3fv(b->co);
}
glEnd();
}
} else {
glBegin(GL_QUADS);
for (y=0; y<gridSize-1; y++) {
for (x=0; x<gridSize-1; x++) {
float *a = faceGridData[(y+0)*gridSize + x].co;
float *b = faceGridData[(y+0)*gridSize + x + 1].co;
float *c = faceGridData[(y+1)*gridSize + x + 1].co;
float *d = faceGridData[(y+1)*gridSize + x].co;
glVertex3fv(d);
glVertex3fv(c);
glVertex3fv(b);
glVertex3fv(a);
if (x<gridSize-1) {
float a_cX = c[0]-a[0], a_cY = c[1]-a[1], a_cZ = c[2]-a[2];
float b_dX = d[0]-b[0], b_dY = d[1]-b[1], b_dZ = d[2]-b[2];
float no[3];
no[0] = b_dY*a_cZ - b_dZ*a_cY;
no[1] = b_dZ*a_cX - b_dX*a_cZ;
no[2] = b_dX*a_cY - b_dY*a_cX;
glNormal3fv(no);
}
glVertex3fv(d);
glVertex3fv(c);
glVertex3fv(b);
glVertex3fv(a);
}
}
glEnd();
}
@@ -849,12 +873,12 @@ static void ccgDM_drawMappedEdgeEM(DerivedMesh *dm, void *edge) {
CCGSubSurf *ss = ccgdm->ss->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; i<edgeSize; i++)
glVertex3fv(edgeData[i]);
glVertex3fv(edgeData[i].co);
glEnd();
ccgEdgeIterator_free(ei);
@@ -868,7 +892,7 @@ static void ccgDM_drawMappedEdgesEM(DerivedMesh *dm, int (*setDrawOptions)(void
for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
EditEdge *edge = ccgSubSurf_getEdgeEdgeHandle(ss, e);
float (*edgeData)[3] = ccgSubSurf_getEdgeDataArray(ss, e);
VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
glBegin(GL_LINE_STRIP);
if (!setDrawOptions || setDrawOptions(userData, edge)) {
@@ -878,8 +902,8 @@ static void ccgDM_drawMappedEdgesEM(DerivedMesh *dm, int (*setDrawOptions)(void
}
for (i=0; i<edgeSize-1; i++) {
glVertex3fv(edgeData[i]);
glVertex3fv(edgeData[i+1]);
glVertex3fv(edgeData[i].co);
glVertex3fv(edgeData[i+1].co);
}
}
glEnd();
@@ -896,7 +920,7 @@ static void ccgDM_drawMappedEdgesInterpEM(DerivedMesh *dm, int (*setDrawOptions)
for (; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
EditEdge *edge = ccgSubSurf_getEdgeEdgeHandle(ss, e);
float (*edgeData)[3] = ccgSubSurf_getEdgeDataArray(ss, e);
VertData *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
glBegin(GL_LINE_STRIP);
if (!setDrawOptions || setDrawOptions(userData, edge)) {
@@ -908,7 +932,7 @@ static void ccgDM_drawMappedEdgesInterpEM(DerivedMesh *dm, int (*setDrawOptions)
glColor3ub(0, ageCol>0?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<numVerts; S++) {
float (*faceGridData)[3] = ccgSubSurf_getFaceGridDataArray(ss, f, S);
VertData *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
for (y=0; y<gridSize-1; y++) {
glBegin(GL_QUAD_STRIP);
for (x=0; x<gridSize; x++) {
glVertex3fv(faceGridData[(y+0)*gridSize + x]);
glVertex3fv(faceGridData[(y+1)*gridSize + x]);
glVertex3fv(faceGridData[(y+0)*gridSize + x].co);
glVertex3fv(faceGridData[(y+1)*gridSize + x].co);
}
glEnd();
}