From: John F. Fay Date: Wed, 4 May 2005 21:02:22 +0000 (+0000) Subject: Replacing the original \"freeglut\" \"shapes\" demo with the much snazzier OpenGLUT... X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;ds=sidebyside;h=32ee0c1e2137eee3f3879c7a246efd0558be71ee;hp=cef996c3fac108d491a7b05c616ccc04c6851cd0;p=freeglut Replacing the original \"freeglut\" \"shapes\" demo with the much snazzier OpenGLUT \"shapes\" demo. Many thanks to the OpenGLUT community for writing it. The copyright notice stays in the program. git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@598 7f0cb862-5218-0410-a997-914c9d46530a --- diff --git a/progs/demos/shapes/shapes.c b/progs/demos/shapes/shapes.c index 2e7e181..4928260 100644 --- a/progs/demos/shapes/shapes.c +++ b/progs/demos/shapes/shapes.c @@ -1,131 +1,322 @@ -/* - * FreeGLUT Shapes Demo - * - * Written by Nigel Stewart November 2003 - * - * This program is test harness for the sphere, cone - * and torus shapes in FreeGLUT. - * - * Spinning wireframe and smooth shaded shapes are - * displayed until the ESC or q key is pressed. The - * number of geometry stacks and slices can be adjusted - * using the + and - keys. - */ +/*! \file shapes.c + \ingroup demos + + This program is a test harness for the various shapes + in OpenGLUT. It may also be useful to see which + parameters control what behavior in the OpenGLUT + objects. + + Spinning wireframe and solid-shaded shapes are + displayed. Some parameters can be adjusted. + + Keys: + - Esc   Quit + - q Q   Quit + - = +   Increase \a slices + - - _   Decreate \a slices + - , <   Decreate \a stacks + - . >   Increase \a stacks + - 9 (   Decreate \a depth (Sierpinski Sponge) + - 0 )   Increase \a depth (Sierpinski Sponge) + - up    Increase "outer radius" + - down  Decrease "outer radius" + - left  Decrease "inner radius" + - right Increase "inner radius" + - PgUp  Next shape-drawing function + - PgDn  Prev shape-drawing function + + \author Written by Nigel Stewart November 2003 + + \author Portions Copyright (C) 2004, the OpenGLUT project contributors.
+ OpenGLUT branched from freeglut in February, 2004. + + \image html openglut_shapes.png OpenGLUT Geometric Shapes Demonstration + \include demos/shapes/shapes.c +*/ #include +#include +#include #include +#ifdef WIN32 +#include // DUMP MEMORY LEAKS +#endif + +/* + * This macro is only intended to be used on arrays, of course. + */ +#define NUMBEROF(x) ((sizeof(x))/(sizeof(x[0]))) + +/* + * These global variables control which object is drawn, + * and how it is drawn. No object uses all of these + * variables. + */ +static int function_index; static int slices = 16; static int stacks = 16; +static double irad = .25; +static double orad = 1.0; +static int depth = 4; +static double offset[ 3 ] = { 0, 0, 0 }; + + +/* + * These one-liners draw particular objects, fetching appropriate + * information from the above globals. They are just thin wrappers + * for the OpenGLUT objects. + */ +static void drawSolidTetrahedron(void) { glutSolidTetrahedron (); } +static void drawWireTetrahedron(void) { glutWireTetrahedron (); } +static void drawSolidCube(void) { glutSolidCube(1); } +static void drawWireCube(void) { glutWireCube(1); } +static void drawSolidOctahedron(void) { glutSolidOctahedron (); } +static void drawWireOctahedron(void) { glutWireOctahedron (); } +static void drawSolidDodecahedron(void) { glutSolidDodecahedron (); } +static void drawWireDodecahedron(void) { glutWireDodecahedron (); } +static void drawSolidRhombicDodecahedron(void) { glutSolidRhombicDodecahedron (); } +static void drawWireRhombicDodecahedron(void) { glutWireRhombicDodecahedron (); } +static void drawSolidIcosahedron(void) { glutSolidIcosahedron (); } +static void drawWireIcosahedron(void) { glutWireIcosahedron (); } +static void drawSolidSierpinskiSponge(void) { glutSolidSierpinskiSponge (depth, offset, 1); } +static void drawWireSierpinskiSponge(void) { glutWireSierpinskiSponge (depth, offset, 1); } +static void drawSolidTeapot(void) { glutSolidTeapot(1); } +static void drawWireTeapot(void) { glutWireTeapot(1); } +static void drawSolidTorus(void) { glutSolidTorus(irad,orad,slices,stacks); } +static void drawWireTorus(void) { glutWireTorus (irad,orad,slices,stacks); } +static void drawSolidSphere(void) { glutSolidSphere(1,slices,stacks); } +static void drawWireSphere(void) { glutWireSphere(1,slices,stacks); } +static void drawSolidCone(void) { glutSolidCone(1,1,slices,stacks); } +static void drawWireCone(void) { glutWireCone(1,1,slices,stacks); } +static void drawSolidCylinder(void) { glutSolidCylinder(1,1,slices,stacks); } +static void drawWireCylinder(void) { glutWireCylinder(1,1,slices,stacks); } +static void drawSolidCuboctahedron(void) +{ +#define RADIUS 1.0f + glBegin( GL_TRIANGLES ); + glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( RADIUS, RADIUS, 0.0 ); glVertex3d( 0.0, RADIUS, RADIUS ); glVertex3d( RADIUS, 0.0, RADIUS ); + glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( RADIUS, RADIUS, 0.0 ); glVertex3d( RADIUS, 0.0,-RADIUS ); glVertex3d( 0.0, RADIUS,-RADIUS ); + glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( RADIUS,-RADIUS, 0.0 ); glVertex3d( RADIUS, 0.0, RADIUS ); glVertex3d( 0.0,-RADIUS, RADIUS ); + glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( RADIUS,-RADIUS, 0.0 ); glVertex3d( 0.0,-RADIUS,-RADIUS ); glVertex3d( RADIUS, 0.0,-RADIUS ); + glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-RADIUS, RADIUS, 0.0 ); glVertex3d(-RADIUS, 0.0, RADIUS ); glVertex3d( 0.0, RADIUS, RADIUS ); + glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-RADIUS, RADIUS, 0.0 ); glVertex3d( 0.0, RADIUS,-RADIUS ); glVertex3d(-RADIUS, 0.0,-RADIUS ); + glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-RADIUS,-RADIUS, 0.0 ); glVertex3d( 0.0,-RADIUS, RADIUS ); glVertex3d(-RADIUS, 0.0, RADIUS ); + glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-RADIUS,-RADIUS, 0.0 ); glVertex3d(-RADIUS, 0.0,-RADIUS ); glVertex3d( 0.0,-RADIUS,-RADIUS ); + glEnd(); + + glBegin( GL_QUADS ); + glNormal3d( 1.0, 0.0, 0.0 ); glVertex3d( RADIUS, RADIUS, 0.0 ); glVertex3d( RADIUS, 0.0, RADIUS ); glVertex3d( RADIUS,-RADIUS, 0.0 ); glVertex3d( RADIUS, 0.0,-RADIUS ); + glNormal3d(-1.0, 0.0, 0.0 ); glVertex3d(-RADIUS, RADIUS, 0.0 ); glVertex3d(-RADIUS, 0.0,-RADIUS ); glVertex3d(-RADIUS,-RADIUS, 0.0 ); glVertex3d(-RADIUS, 0.0, RADIUS ); + glNormal3d( 0.0, 1.0, 0.0 ); glVertex3d( RADIUS, RADIUS, 0.0 ); glVertex3d( 0.0, RADIUS,-RADIUS ); glVertex3d(-RADIUS, RADIUS, 0.0 ); glVertex3d( 0.0, RADIUS, RADIUS ); + glNormal3d( 0.0,-1.0, 0.0 ); glVertex3d(-RADIUS, RADIUS, 0.0 ); glVertex3d( 0.0,-RADIUS, RADIUS ); glVertex3d(-RADIUS,-RADIUS, 0.0 ); glVertex3d( 0.0,-RADIUS,-RADIUS ); + glNormal3d( 0.0, 0.0, 1.0 ); glVertex3d( RADIUS, 0.0, RADIUS ); glVertex3d( 0.0, RADIUS, RADIUS ); glVertex3d(-RADIUS, 0.0, RADIUS ); glVertex3d( 0.0,-RADIUS, RADIUS ); + glNormal3d( 0.0, 0.0,-1.0 ); glVertex3d( RADIUS, 0.0,-RADIUS ); glVertex3d( 0.0,-RADIUS,-RADIUS ); glVertex3d(-RADIUS, 0.0,-RADIUS ); glVertex3d( 0.0, RADIUS,-RADIUS ); + glEnd(); +#undef RADIUS +} +static void drawWireCuboctahedron(void) +{ +} + +/* + * This structure defines an entry in our function-table. + */ +typedef struct +{ + const char * const name; + void (*solid) (void); + void (*wire) (void); +} entry; + +#define ENTRY(e) {#e, drawSolid##e, drawWire##e} +static const entry table [] = +{ + ENTRY (Tetrahedron), + ENTRY (Cube), + ENTRY (Octahedron), + ENTRY (Dodecahedron), + ENTRY (RhombicDodecahedron), + ENTRY (Icosahedron), + ENTRY (SierpinskiSponge), + ENTRY (Teapot), + ENTRY (Torus), + ENTRY (Sphere), + ENTRY (Cone), + ENTRY (Cylinder), + ENTRY (Cuboctahedron) +}; +#undef ENTRY + +/*! + Does printf()-like work using freeglut/OpenGLUT + glutBitmapString(). Uses a fixed font. Prints + at the indicated row/column position. + + Limitation: Cannot address pixels. + Limitation: Renders in screen coords, not model coords. + + \note Uses a fixed, 256-byte array for holding strings. + The best way around this would be to use vasprintf(), + but that is not available on WIN32, I believe. + Another alternative would be to write our own formatter + from scratch and emit the characters one at a time to + the GLUT bitmap single-character drawing routine. + We could also use vsnprintf(), but I'm not sure if + that is standard... +*/ +static void shapesPrintf (int row, int col, const char *fmt, ...) +{ + static char buf[256]; + int viewport[4]; + void *font = GLUT_BITMAP_9_BY_15; + va_list args; + + va_start(args, fmt); + (void) vsprintf (buf, fmt, args); + va_end(args); + + glGetIntegerv(GL_VIEWPORT,viewport); + + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0,viewport[2],0,viewport[3],-1,1); + + glRasterPos2i + ( + glutBitmapWidth(font, ' ') * col, + - glutBitmapHeight(font) * (row+2) + viewport[3] + ); + glutBitmapString (font, buf); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +} /* GLUT callback Handlers */ -static void +static void resize(int width, int height) { const float ar = (float) width / (float) height; - + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0); - + glMatrixMode(GL_MODELVIEW); glLoadIdentity() ; } -static void -display(void) +static void display(void) { const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; const double a = t*90.0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glColor3d(1,0,0); - glPushMatrix(); - glTranslated(-2.4,1.2,-6); - glRotated(60,1,0,0); - glRotated(a,0,0,1); - glutSolidSphere(1,slices,stacks); - glPopMatrix(); + glEnable(GL_LIGHTING); - glPushMatrix(); - glTranslated(0,1.2,-6); - glRotated(60,1,0,0); - glRotated(a,0,0,1); - glutSolidCone(1,1,slices,stacks); - glPopMatrix(); + printf ( "Shape %d slides %d stacks %d\n", function_index, slices, stacks ) ; - glPushMatrix(); - glTranslated(2.4,1.2,-6); - glRotated(60,1,0,0); - glRotated(a,0,0,1); - glutSolidTorus(0.2,0.8,slices,stacks); - glPopMatrix(); + glColor3d(1,0,0); glPushMatrix(); - glTranslated(-2.4,-1.2,-6); + glTranslated(0,1.2,-6); glRotated(60,1,0,0); glRotated(a,0,0,1); - glutWireSphere(1,slices,stacks); + table [function_index].solid (); glPopMatrix(); glPushMatrix(); glTranslated(0,-1.2,-6); glRotated(60,1,0,0); glRotated(a,0,0,1); - glutWireCone(1,1,slices,stacks); + table [function_index].wire (); glPopMatrix(); - glPushMatrix(); - glTranslated(2.4,-1.2,-6); - glRotated(60,1,0,0); - glRotated(a,0,0,1); - glutWireTorus(0.2,0.8,slices,stacks); - glPopMatrix(); + glDisable(GL_LIGHTING); + glColor3d(0.1,0.1,0.4); +/* shapesPrintf (1, 3, "Shape PgUp PgDn: %s", table [function_index].name); + shapesPrintf (2, 3, " Slices +-: %d Stacks <>: %d", slices, stacks); + shapesPrintf (3, 3, " nSides +-: %d nRings <>: %d", slices, stacks); + shapesPrintf (4, 3, " Depth (): %d", depth); + shapesPrintf (5, 3, " Outer radius Up Down : %f", orad); + shapesPrintf (6, 3, " Inner radius Left Right: %f", irad); +*/ glutSwapBuffers(); } -static void +static void key(unsigned char key, int x, int y) { - switch (key) + switch (key) { - case 'n': glDisable ( GL_CULL_FACE ) ; - break ; - case 'f': glEnable ( GL_CULL_FACE ) ; - glCullFace ( GL_FRONT ) ; - break ; - case 'b': glEnable ( GL_CULL_FACE ) ; - glCullFace ( GL_BACK ) ; - break ; - case 27 : - case 'q': - exit(0); - break; - - case '+': - slices++; - stacks++; - break; - - case '-': - if (slices>3 && stacks>3) - { - slices--; - stacks--; - } - break; + case 27 : + case 'Q': + case 'q': glutLeaveMainLoop () ; break; + + case '=': + case '+': slices++; break; + + case '-': + case '_': if( slices > -1 ) slices--; break; + + case ',': + case '<': if( stacks > -1 ) stacks--; break; + + case '.': + case '>': stacks++; break; + + case '9': + case '(': if( depth > -1 ) depth--; break; + + case '0': + case ')': ++depth; break; + + default: + break; } glutPostRedisplay(); } -static void +static void special (int key, int x, int y) +{ + switch (key) + { + case GLUT_KEY_PAGE_UP: ++function_index; break; + case GLUT_KEY_PAGE_DOWN: --function_index; break; + case GLUT_KEY_UP: orad *= 2; break; + case GLUT_KEY_DOWN: orad /= 2; break; + + case GLUT_KEY_RIGHT: irad *= 2; break; + case GLUT_KEY_LEFT: irad /= 2; break; + + default: + break; + } + + if (0 > function_index) + function_index = NUMBEROF (table) - 1; + + if (NUMBEROF (table) <= ( unsigned )function_index) + function_index = 0; +} + + +static void idle(void) { glutPostRedisplay(); @@ -143,31 +334,34 @@ const GLfloat high_shininess[] = { 100.0f }; /* Program entry point */ -int +int main(int argc, char *argv[]) { - glutInit(&argc, argv); glutInitWindowSize(640,480); - glutInitWindowPosition (40,40); + glutInitWindowPosition(40,40); + glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); - glutCreateWindow("FreeGLUT Shapes"); + glutCreateWindow("OpenGLUT Shapes"); glutReshapeFunc(resize); glutDisplayFunc(display); glutKeyboardFunc(key); + glutSpecialFunc(special); glutIdleFunc(idle); + glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ; + glClearColor(1,1,1,1); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); glEnable(GL_LIGHT0); glEnable(GL_NORMALIZE); glEnable(GL_COLOR_MATERIAL); - glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); @@ -181,6 +375,9 @@ main(int argc, char *argv[]) glutMainLoop(); +#ifdef WIN32 + _CrtDumpMemoryLeaks () ; // DUMP MEMORY LEAK INFORMATION +#endif + return EXIT_SUCCESS; } -