+static double irad = .25;
+static double orad = 1.0;
+static int depth = 4;
+static double offset[ 3 ] = { 0, 0, 0 };
+static GLboolean show_info = GL_TRUE;
+
+/*
+ * 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); }
+
+#define RADIUS 1.0f
+
+static void drawSolidCuboctahedron(void)
+{
+ 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();
+}
+
+static void drawWireCuboctahedron(void)
+{
+ glBegin( GL_LINE_LOOP );
+ 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 );
+ glEnd();
+ glBegin( GL_LINE_LOOP );
+ 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 );
+ glEnd();
+ glBegin( GL_LINE_LOOP );
+ 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 );
+ glEnd();
+ glBegin( GL_LINE_LOOP );
+ 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 );
+ glEnd();
+ glBegin( GL_LINE_LOOP );
+ 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();
+ glBegin( GL_LINE_LOOP );
+ 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
+
+/*
+ * 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, (unsigned char*)buf);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+}