X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffg_teapot.c;h=a378b9bbfb1248acde0f5b399856ae3dbd3c9908;hb=af47c3f93c7834b4006c49ec9df6a6ffdd3025de;hp=d2a2dd3405da5fd162cff7ba3d33c5fe52e7a998;hpb=7e0a8e93d578a3609fc84a68a2c57201e58f8ecc;p=freeglut diff --git a/src/fg_teapot.c b/src/fg_teapot.c index d2a2dd3..a378b9b 100644 --- a/src/fg_teapot.c +++ b/src/fg_teapot.c @@ -1,5 +1,5 @@ /* - * freeglut_teapot.c + * fg_teapot.c * * Teapot(tm) rendering code. * @@ -28,7 +28,6 @@ /* notes: * the (very little) required math is found here: http://www.gamasutra.com/view/feature/131848/tessellation_of_4x4_bezier_patches_.php?print=1 * a much more optimized version is here, didn't bother to implement that: http://www.gamasutra.com/view/feature/131794/an_indepth_look_at_bicubic_bezier_.php?print=1 - * teacup and teaspoon data: ftp://ftp.funet.fi/pub/sci/graphics/packages/objects/teaset.tar.Z (figure out this sampling scheme) */ #include @@ -37,14 +36,9 @@ /* -- STATIC VARS: CACHES ---------------------------------------------------- */ -/* Teapot defs */ -#define GLUT_TEAPOT_N_PATCHES (6*4 + 4*2) /* 6 patches are reproduced (rotated) 4 times, 4 patches (flipped) 2 times */ -#define GLUT_SOLID_TEAPOT_N_SUBDIV 10 -#define GLUT_SOLID_TEAPOT_N_VERT GLUT_SOLID_TEAPOT_N_SUBDIV*GLUT_SOLID_TEAPOT_N_SUBDIV * GLUT_TEAPOT_N_PATCHES /* N_SUBDIV^2 vertices per patch */ -#define GLUT_SOLID_TEAPOT_N_TRI (GLUT_SOLID_TEAPOT_N_SUBDIV-1)*(GLUT_SOLID_TEAPOT_N_SUBDIV-1) * GLUT_TEAPOT_N_PATCHES * 2 /* if e.g. 7x7 vertices for each patch, there are 6*6 squares for each patch. Each square is decomposed into 2 triangles */ - -#define GLUT_WIRE_TEAPOT_N_SUBDIV 7 -#define GLUT_WIRE_TEAPOT_N_VERT GLUT_WIRE_TEAPOT_N_SUBDIV*GLUT_WIRE_TEAPOT_N_SUBDIV * GLUT_TEAPOT_N_PATCHES /* N_SUBDIV^2 vertices per patch */ +/* General defs */ +#define GLUT_SOLID_N_SUBDIV 8 +#define GLUT_WIRE_N_SUBDIV 10 /* Bernstein coefficients only have to be precomputed once (number of patch subdivisions is fixed) * Can thus define arrays for them here, they will be filled upon first use. @@ -52,28 +46,89 @@ * Have separate caches for solid and wire as they use a different number of subdivisions * _0 is for Bernstein polynomials, _1 for their first derivative (which we need for normals) */ -static GLfloat bernWire_0 [GLUT_WIRE_TEAPOT_N_SUBDIV] [4]; -static GLfloat bernWire_1 [GLUT_WIRE_TEAPOT_N_SUBDIV] [4]; -static GLfloat bernSolid_0[GLUT_SOLID_TEAPOT_N_SUBDIV][4]; -static GLfloat bernSolid_1[GLUT_SOLID_TEAPOT_N_SUBDIV][4]; +static GLfloat bernWire_0 [GLUT_WIRE_N_SUBDIV] [4]; +static GLfloat bernWire_1 [GLUT_WIRE_N_SUBDIV] [4]; +static GLfloat bernSolid_0[GLUT_SOLID_N_SUBDIV][4]; +static GLfloat bernSolid_1[GLUT_SOLID_N_SUBDIV][4]; + +/* Teapot defs */ +#define GLUT_TEAPOT_N_PATCHES (6*4 + 4*2) /* 6 patches are reproduced (rotated) 4 times, 4 patches (flipped) 2 times */ +#define GLUT_SOLID_TEAPOT_N_VERT GLUT_SOLID_N_SUBDIV*GLUT_SOLID_N_SUBDIV * GLUT_TEAPOT_N_PATCHES /* N_SUBDIV^2 vertices per patch */ +#define GLUT_SOLID_TEAPOT_N_TRI (GLUT_SOLID_N_SUBDIV-1)*(GLUT_SOLID_N_SUBDIV-1) * GLUT_TEAPOT_N_PATCHES * 2 /* if e.g. 7x7 vertices for each patch, there are 6*6 squares for each patch. Each square is decomposed into 2 triangles */ + +#define GLUT_WIRE_TEAPOT_N_VERT GLUT_WIRE_N_SUBDIV*GLUT_WIRE_N_SUBDIV * GLUT_TEAPOT_N_PATCHES /* N_SUBDIV^2 vertices per patch */ + +/* Bit of caching: + * vertex indices and normals only need to be generated once for + * a given number of subdivisions as they don't change with scale. + * Vertices can be cached and reused if scale didn't change. + */ +static GLushort vertIdxsTeapotS[GLUT_SOLID_TEAPOT_N_TRI*3]; +static GLfloat normsTeapotS [GLUT_SOLID_TEAPOT_N_VERT*3]; +static GLfloat vertsTeapotS [GLUT_SOLID_TEAPOT_N_VERT*3]; +static GLfloat texcsTeapotS [GLUT_SOLID_TEAPOT_N_VERT*2]; +static GLfloat lastScaleTeapotS = 0.f; +static GLboolean initedTeapotS = GL_FALSE; + +static GLushort vertIdxsTeapotW[GLUT_WIRE_TEAPOT_N_VERT*2]; +static GLfloat normsTeapotW [GLUT_WIRE_TEAPOT_N_VERT*3]; +static GLfloat vertsTeapotW [GLUT_WIRE_TEAPOT_N_VERT*3]; +static GLfloat lastScaleTeapotW = 0.f; +static GLboolean initedTeapotW = GL_FALSE; + + +/* Teacup defs */ +#define GLUT_TEACUP_N_PATCHES (6*4 + 1*2) /* 6 patches are reproduced (rotated) 4 times, 1 patch (flipped) 2 times */ +#define GLUT_SOLID_TEACUP_N_VERT GLUT_SOLID_N_SUBDIV*GLUT_SOLID_N_SUBDIV * GLUT_TEACUP_N_PATCHES /* N_SUBDIV^2 vertices per patch */ +#define GLUT_SOLID_TEACUP_N_TRI (GLUT_SOLID_N_SUBDIV-1)*(GLUT_SOLID_N_SUBDIV-1) * GLUT_TEACUP_N_PATCHES * 2 /* if e.g. 7x7 vertices for each patch, there are 6*6 squares for each patch. Each square is decomposed into 2 triangles */ + +#define GLUT_WIRE_TEACUP_N_VERT GLUT_WIRE_N_SUBDIV*GLUT_WIRE_N_SUBDIV * GLUT_TEACUP_N_PATCHES /* N_SUBDIV^2 vertices per patch */ /* Bit of caching: * vertex indices and normals only need to be generated once for * a given number of subdivisions as they don't change with scale. * Vertices can be cached and reused if scale didn't change. */ -static GLushort vertIdxsSolid[GLUT_SOLID_TEAPOT_N_TRI*3]; -static GLfloat normsSolid [GLUT_SOLID_TEAPOT_N_VERT*3]; -static GLfloat vertsSolid [GLUT_SOLID_TEAPOT_N_VERT*3]; -static GLfloat texcsSolid [GLUT_SOLID_TEAPOT_N_VERT*2]; -static GLfloat lastScaleSolid = 0.f; -static GLboolean initedSolid = GL_FALSE; - -static GLushort vertIdxsWire [GLUT_WIRE_TEAPOT_N_VERT*2]; -static GLfloat normsWire [GLUT_WIRE_TEAPOT_N_VERT*3]; -static GLfloat vertsWire [GLUT_WIRE_TEAPOT_N_VERT*3]; -static GLfloat lastScaleWire = 0.f; -static GLboolean initedWire = GL_FALSE; +static GLushort vertIdxsTeacupS[GLUT_SOLID_TEACUP_N_TRI*3]; +static GLfloat normsTeacupS [GLUT_SOLID_TEACUP_N_VERT*3]; +static GLfloat vertsTeacupS [GLUT_SOLID_TEACUP_N_VERT*3]; +static GLfloat texcsTeacupS [GLUT_SOLID_TEACUP_N_VERT*2]; +static GLfloat lastScaleTeacupS = 0.f; +static GLboolean initedTeacupS = GL_FALSE; + +static GLushort vertIdxsTeacupW[GLUT_WIRE_TEACUP_N_VERT*2]; +static GLfloat normsTeacupW [GLUT_WIRE_TEACUP_N_VERT*3]; +static GLfloat vertsTeacupW [GLUT_WIRE_TEACUP_N_VERT*3]; +static GLfloat lastScaleTeacupW = 0.f; +static GLboolean initedTeacupW = GL_FALSE; + + +/* Teaspoon defs */ +#define GLUT_TEASPOON_N_PATCHES GLUT_TEASPOON_N_INPUT_PATCHES +#define GLUT_SOLID_TEASPOON_N_VERT GLUT_SOLID_N_SUBDIV*GLUT_SOLID_N_SUBDIV * GLUT_TEASPOON_N_PATCHES /* N_SUBDIV^2 vertices per patch */ +#define GLUT_SOLID_TEASPOON_N_TRI (GLUT_SOLID_N_SUBDIV-1)*(GLUT_SOLID_N_SUBDIV-1) * GLUT_TEASPOON_N_PATCHES * 2 /* if e.g. 7x7 vertices for each patch, there are 6*6 squares for each patch. Each square is decomposed into 2 triangles */ + +#define GLUT_WIRE_TEASPOON_N_VERT GLUT_WIRE_N_SUBDIV*GLUT_WIRE_N_SUBDIV * GLUT_TEASPOON_N_PATCHES /* N_SUBDIV^2 vertices per patch */ + +/* Bit of caching: + * vertex indices and normals only need to be generated once for + * a given number of subdivisions as they don't change with scale. + * Vertices can be cached and reused if scale didn't change. + */ +static GLushort vertIdxsTeaspoonS[GLUT_SOLID_TEASPOON_N_TRI*3]; +static GLfloat normsTeaspoonS [GLUT_SOLID_TEASPOON_N_VERT*3]; +static GLfloat vertsTeaspoonS [GLUT_SOLID_TEASPOON_N_VERT*3]; +static GLfloat texcsTeaspoonS [GLUT_SOLID_TEASPOON_N_VERT*2]; +static GLfloat lastScaleTeaspoonS = 0.f; +static GLboolean initedTeaspoonS = GL_FALSE; + +static GLushort vertIdxsTeaspoonW[GLUT_WIRE_TEASPOON_N_VERT*2]; +static GLfloat normsTeaspoonW [GLUT_WIRE_TEASPOON_N_VERT*3]; +static GLfloat vertsTeaspoonW [GLUT_WIRE_TEASPOON_N_VERT*3]; +static GLfloat lastScaleTeaspoonW = 0.f; +static GLboolean initedTeaspoonW = GL_FALSE; + + /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ extern void fghDrawGeometrySolid(GLfloat *vertices, GLfloat *normals, GLfloat *textcs, GLsizei numVertices, @@ -271,33 +326,29 @@ static int evalBezier(GLfloat cp[4][4][3], int nSubDivs, float (*bern_0)[4], int return nVertVals*flag; } -static void fghTeapot( GLfloat scale, GLboolean useWireMode ) +static void fghTeaset( GLfloat scale, GLboolean useWireMode, + GLfloat (*cpdata)[3], int (*patchdata)[16], + GLushort *vertIdxs, + GLfloat *verts, GLfloat *norms, GLfloat *texcs, + GLfloat *lastScale, GLboolean *inited, + GLboolean needNormalFix, GLboolean rotFlip, GLfloat zOffset, + int nVerts, int nInputPatches, int nPatches, int nTriangles ) { /* for internal use */ int p,o; GLfloat cp[4][4][3]; /* to hold pointers to static vars/arrays */ GLfloat (*bern_0)[4], (*bern_1)[4]; - GLfloat *verts, *norms, *lastScale; - GLushort *vertIdxs; - GLboolean * inited; - int nSubDivs, nVerts; + int nSubDivs; /* Get relevant static arrays and variables */ bern_0 = useWireMode ? bernWire_0 : bernSolid_0; bern_1 = useWireMode ? bernWire_1 : bernSolid_1; - verts = useWireMode ? vertsWire : vertsSolid; - norms = useWireMode ? normsWire : normsSolid; - lastScale = useWireMode ? &lastScaleWire : &lastScaleSolid; - vertIdxs = useWireMode ? vertIdxsWire : vertIdxsSolid; - inited = useWireMode ? &initedWire : &initedSolid; - nSubDivs = useWireMode ? GLUT_WIRE_TEAPOT_N_SUBDIV : GLUT_SOLID_TEAPOT_N_SUBDIV; - nVerts = useWireMode ? GLUT_WIRE_TEAPOT_N_VERT : GLUT_SOLID_TEAPOT_N_VERT; + nSubDivs = useWireMode ? GLUT_WIRE_N_SUBDIV : GLUT_SOLID_N_SUBDIV; /* check if need to generate vertices */ if (!*inited || scale != *lastScale) { - printf("regen\n"); /* set vertex array to all 0 (not necessary for normals and vertex indices) */ memset(verts,0,nVerts*3*sizeof(GLfloat)); @@ -306,26 +357,26 @@ static void fghTeapot( GLfloat scale, GLboolean useWireMode ) pregenBernstein(nSubDivs,bern_0,bern_1); /* generate vertices and normals */ - for (p=0, o=0; p was 1.5 for teapot, but should be 1.575 to center it on the Z axis. Teacup and teaspoon have different offsets */ - cp[i/4][i%4][0] = cpdata[patchdata[p][i]][0] *scale/2.f; - cp[i/4][i%4][1] = (cpdata[patchdata[p][i]][2]-1.5f)*scale/2.f; - cp[i/4][i%4][2] = -cpdata[patchdata[p][i]][1] *scale/2.f; + cp[i/4][i%4][0] = cpdata[patchdata[p][i]][0] *scale/2.f; + cp[i/4][i%4][1] = (cpdata[patchdata[p][i]][2]-zOffset)*scale/2.f; + cp[i/4][i%4][2] = -cpdata[patchdata[p][i]][1] *scale/2.f; } /* eval bezier patch */ @@ -339,7 +390,7 @@ static void fghTeapot( GLfloat scale, GLboolean useWireMode ) if (!*inited) { int r,c; - /* generate texture coordinates if solid teapot */ + /* generate texture coordinates if solid teapot/teacup/teaspoon */ if (!useWireMode) { /* generate for first patch */ @@ -349,21 +400,21 @@ static void fghTeapot( GLfloat scale, GLboolean useWireMode ) for (c=0; c