+static double irad = .25;
+static double orad = 1.0; /* doubles as size for objects other than Torus */
+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 FreeGLUT objects.
+ */
+static void drawSolidTetrahedron(void) { glutSolidTetrahedron (); }
+static void drawWireTetrahedron(void) { glutWireTetrahedron (); }
+static void drawSolidCube(void) { glutSolidCube(orad); } /* orad doubles as size input */
+static void drawWireCube(void) { glutWireCube(orad); } /* orad doubles as size input */
+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, orad);} /* orad doubles as size input */
+static void drawWireSierpinskiSponge(void) { glutWireSierpinskiSponge (depth, offset, orad); } /* orad doubles as size input */
+static void drawSolidTeapot(void) { glutSolidTeapot(orad); } /* orad doubles as size input */
+static void drawWireTeapot(void) { glutWireTeapot(orad); } /* orad doubles as size input */
+static void drawSolidTorus(void) { glutSolidTorus(irad,orad,slices,stacks); }
+static void drawWireTorus(void) { glutWireTorus (irad,orad,slices,stacks); }
+static void drawSolidSphere(void) { glutSolidSphere(orad,slices,stacks); } /* orad doubles as size input */
+static void drawWireSphere(void) { glutWireSphere(orad,slices,stacks); } /* orad doubles as size input */
+static void drawSolidCone(void) { glutSolidCone(orad,orad,slices,stacks); } /* orad doubles as size input */
+static void drawWireCone(void) { glutWireCone(orad,orad,slices,stacks); } /* orad doubles as size input */
+static void drawSolidCylinder(void) { glutSolidCylinder(orad,orad,slices,stacks); } /* orad doubles as size input */
+static void drawWireCylinder(void) { glutWireCylinder(orad,orad,slices,stacks); } /* orad doubles as size input */
+
+#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
+ glutBitmapString(). Uses a fixed font. Prints
+ at the indicated row/column position.
+
+ Limitation: Cannot address pixels.
+ Limitation: Renders in screen coords, not model coords.
+*/
+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);
+#if defined(WIN32) && !defined(__CYGWIN__)
+ (void) _vsnprintf (buf, sizeof(buf), fmt, args);
+#else
+ (void) vsnprintf (buf, sizeof(buf), fmt, args);
+#endif
+ 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 + viewport[3]
+ );
+ glutBitmapString (font, (unsigned char*)buf);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+}