X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffg_teapot.c;h=a378b9bbfb1248acde0f5b399856ae3dbd3c9908;hb=a67edfb64096e4da7f8b7d6cd34de78c7fc72c54;hp=41d0feeee73db72ab871d0a8192d5a7e04c7c95f;hpb=1b5ee849ba61b667aeba474a7e03406196478bee;p=freeglut diff --git a/src/fg_teapot.c b/src/fg_teapot.c index 41d0fee..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. * @@ -25,176 +25,546 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * Original teapot code copyright follows: - */ - -/* - * (c) Copyright 1993, Silicon Graphics, Inc. - * - * ALL RIGHTS RESERVED - * - * Permission to use, copy, modify, and distribute this software - * for any purpose and without fee is hereby granted, provided - * that the above copyright notice appear in all copies and that - * both the copyright notice and this permission notice appear in - * supporting documentation, and that the name of Silicon - * Graphics, Inc. not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. - * - * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU - * "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR - * OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO - * EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE - * ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, - * INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, - * SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR - * NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY - * OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - * US Government Users Restricted Rights - * - * Use, duplication, or disclosure by the Government is subject to - * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph - * (c)(1)(ii) of the Rights in Technical Data and Computer - * Software clause at DFARS 252.227-7013 and/or in similar or - * successor clauses in the FAR or the DOD or NASA FAR - * Supplement. Unpublished-- rights reserved under the copyright - * laws of the United States. Contractor/manufacturer is Silicon - * Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA - * 94039-7311. - * - * OpenGL(TM) is a trademark of Silicon Graphics, Inc. +/* 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 */ #include #include "fg_internal.h" #include "fg_teapot_data.h" +/* -- STATIC VARS: CACHES ---------------------------------------------------- */ + +/* 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. + * 3rd order Bezier surfaces have 4 Bernstein coeffs. + * 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_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 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, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertIdxsPerPart); +extern void fghDrawGeometryWire(GLfloat *vertices, GLfloat *normals, GLsizei numVertices, + GLushort *vertIdxs, GLsizei numParts, GLsizei numVertPerPart, GLenum vertexMode, + GLushort *vertIdxs2, GLsizei numParts2, GLsizei numVertPerPart2); + +/* evaluate 3rd order Bernstein polynomial and its 1st deriv */ +static void bernstein3(int i, GLfloat x, GLfloat *r0, GLfloat *r1) +{ + float invx = 1.f - x; + /* r0: zero order coeff, r1: first deriv coeff */ + switch (i) + { + GLfloat temp; + case 0: + temp = invx*invx; + *r0 = invx * temp; /* invx * invx * invx */ + *r1 = -3 * temp; /* -3 * invx * invx */ + break; + case 1: + temp = invx*invx; + *r0 = 3 * x * temp; /* 3 * x * invx * invx */ + *r1 = 3 * temp - 6 * x * invx; /* 3 * invx * invx - 6 * x * invx */ + break; + case 2: + temp = x*x; + *r0 = 3 * temp * invx; /* 3 * x * x * invx */ + *r1 = 6 * x * invx - 3 * temp; /* 6 * x * invx - 3 * x * x */ + break; + case 3: + temp = x*x; + *r0 = x * temp; /* x * x * x */ + *r1 = 3 * temp; /* 3 * x * x */ + break; + default: + *r0 = *r1 = 0; + } +} -static void fghTeapot( GLint grid, GLdouble scale, GLenum type ) +static void pregenBernstein(int nSubDivs, GLfloat (*bern_0)[4], GLfloat (*bern_1)[4]) { -#if defined(_WIN32_WCE) - int i, numV=sizeof(strip_vertices)/4, numI=sizeof(strip_normals)/4; -#else - double p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3]; - long i, j, k, l; -#endif - - glPushAttrib( GL_ENABLE_BIT | GL_EVAL_BIT ); - glEnable( GL_AUTO_NORMAL ); - glEnable( GL_NORMALIZE ); - glEnable( GL_MAP2_VERTEX_3 ); - glEnable( GL_MAP2_TEXTURE_COORD_2 ); - - glPushMatrix(); - glRotated( 270.0, 1.0, 0.0, 0.0 ); - glScaled( 0.5 * scale, 0.5 * scale, 0.5 * scale ); - glTranslated( 0.0, 0.0, -1.5 ); - -#if defined(_WIN32_WCE) - glRotated( 90.0, 1.0, 0.0, 0.0 ); - glBegin( GL_TRIANGLE_STRIP ); - - for( i = 0; i < numV-1; i++ ) + int s,i; + for (s=0; s 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]-zOffset)*scale/2.f; + cp[i/4][i%4][2] = -cpdata[patchdata[p][i]][1] *scale/2.f; + } + + /* eval bezier patch */ + if (!*inited) /* first time, generate normals as well */ + o += evalBezierWithNorm(cp,nSubDivs,bern_0,bern_1, flag, normalFix, verts+o,norms+o); + else /* only need to regen vertices */ + o += evalBezier(cp,nSubDivs,bern_0, flag, verts+o); + } + *lastScale = scale; + + if (!*inited) + { + int r,c; + /* generate texture coordinates if solid teapot/teacup/teaspoon */ + if (!useWireMode) + { + /* generate for first patch */ + for (r=0,o=0; r