corrected data type (its a demo after all, better be precise)
[freeglut] / progs / demos / shapes / shapes.c
1 /*! \file    shapes.c
2     \ingroup demos
3
4     This program is a test harness for the various shapes
5     in OpenGLUT.  It may also be useful to see which
6     parameters control what behavior in the OpenGLUT
7     objects.
8  
9     Spinning wireframe and solid-shaded shapes are
10     displayed.  Some parameters can be adjusted.
11  
12    Keys:
13       -    <tt>Esc &nbsp;</tt> Quit
14       -    <tt>q Q &nbsp;</tt> Quit
15       -    <tt>i I &nbsp;</tt> Show info
16       -    <tt>p P &nbsp;</tt> Toggle perspective or orthographic projection
17       -    <tt>= + &nbsp;</tt> Increase \a slices
18       -    <tt>- _ &nbsp;</tt> Decreate \a slices
19       -    <tt>, < &nbsp;</tt> Decreate \a stacks
20       -    <tt>. > &nbsp;</tt> Increase \a stacks
21       -    <tt>9 ( &nbsp;</tt> Decreate \a depth  (Sierpinski Sponge)
22       -    <tt>0 ) &nbsp;</tt> Increase \a depth  (Sierpinski Sponge)
23       -    <tt>up&nbsp; &nbsp;</tt> Increase "outer radius"
24       -    <tt>down&nbsp;</tt> Decrease "outer radius"
25       -    <tt>left&nbsp;</tt> Decrease "inner radius"
26       -    <tt>right</tt> Increase "inner radius"
27       -    <tt>PgUp&nbsp;</tt> Next shape-drawing function
28       -    <tt>PgDn&nbsp;</tt> Prev shape-drawing function
29
30     \author  Written by Nigel Stewart November 2003
31
32     \author  Portions Copyright (C) 2004, the OpenGLUT project contributors. <br>
33              OpenGLUT branched from freeglut in February, 2004.
34  
35     \image   html openglut_shapes.png OpenGLUT Geometric Shapes Demonstration
36     \include demos/shapes/shapes.c
37 */
38
39 #include <GL/freeglut.h>
40
41 #include <stdarg.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44
45 #ifdef _MSC_VER
46 /* DUMP MEMORY LEAKS */
47 #include <crtdbg.h>
48 #endif
49
50 /*
51  * This macro is only intended to be used on arrays, of course.
52  */
53 #define NUMBEROF(x) ((sizeof(x))/(sizeof(x[0])))
54
55 /*
56  * These global variables control which object is drawn,
57  * and how it is drawn.  No object uses all of these
58  * variables.
59  */
60 static int function_index;
61 static int slices = 16;
62 static int stacks = 16;
63 static double irad = .25;
64 static double orad = 1.0;   /* doubles as size for objects other than Torus */
65 static int depth = 4;
66 static double offset[ 3 ] = { 0, 0, 0 };
67 static GLboolean show_info = GL_TRUE;
68 static float ar;
69 static GLboolean persProject = GL_TRUE;
70
71 /*
72  * These one-liners draw particular objects, fetching appropriate
73  * information from the above globals.  They are just thin wrappers
74  * for the FreeGLUT objects.
75  */
76 static void drawSolidTetrahedron(void)         { glutSolidTetrahedron ();                        }
77 static void drawWireTetrahedron(void)          { glutWireTetrahedron ();                         }
78 static void drawSolidCube(void)                { glutSolidCube(orad);                            }  /* orad doubles as size input */
79 static void drawWireCube(void)                 { glutWireCube(orad);                             }  /* orad doubles as size input */
80 static void drawSolidOctahedron(void)          { glutSolidOctahedron ();                         }
81 static void drawWireOctahedron(void)           { glutWireOctahedron ();                          }
82 static void drawSolidDodecahedron(void)        { glutSolidDodecahedron ();                       }
83 static void drawWireDodecahedron(void)         { glutWireDodecahedron ();                        }
84 static void drawSolidRhombicDodecahedron(void) { glutSolidRhombicDodecahedron ();                }
85 static void drawWireRhombicDodecahedron(void)  { glutWireRhombicDodecahedron ();                 }
86 static void drawSolidIcosahedron(void)         { glutSolidIcosahedron ();                        }
87 static void drawWireIcosahedron(void)          { glutWireIcosahedron ();                         }
88 static void drawSolidSierpinskiSponge(void)    { glutSolidSierpinskiSponge (depth, offset, orad);}  /* orad doubles as size input */
89 static void drawWireSierpinskiSponge(void)     { glutWireSierpinskiSponge (depth, offset, orad); }  /* orad doubles as size input */
90 static void drawSolidTeapot(void)              { glutSolidTeapot(orad);                          }  /* orad doubles as size input */
91 static void drawWireTeapot(void)               { glutWireTeapot(orad);                           }  /* orad doubles as size input */
92 static void drawSolidTorus(void)               { glutSolidTorus(irad,orad,slices,stacks);        }
93 static void drawWireTorus(void)                { glutWireTorus (irad,orad,slices,stacks);        }
94 static void drawSolidSphere(void)              { glutSolidSphere(orad,slices,stacks);            }  /* orad doubles as size input */
95 static void drawWireSphere(void)               { glutWireSphere(orad,slices,stacks);             }  /* orad doubles as size input */
96 static void drawSolidCone(void)                { glutSolidCone(orad,orad,slices,stacks);         }  /* orad doubles as size input */
97 static void drawWireCone(void)                 { glutWireCone(orad,orad,slices,stacks);          }  /* orad doubles as size input */
98 static void drawSolidCylinder(void)            { glutSolidCylinder(orad,orad,slices,stacks);     }  /* orad doubles as size input */
99 static void drawWireCylinder(void)             { glutWireCylinder(orad,orad,slices,stacks);      }  /* orad doubles as size input */
100
101 #define RADIUS    1.0f
102
103 static void drawSolidCuboctahedron(void)
104 {
105   glBegin( GL_TRIANGLES );
106     glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( RADIUS, RADIUS, 0.0 ); glVertex3d( 0.0, RADIUS, RADIUS ); glVertex3d( RADIUS, 0.0, RADIUS );
107     glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( RADIUS, RADIUS, 0.0 ); glVertex3d( RADIUS, 0.0,-RADIUS ); glVertex3d( 0.0, RADIUS,-RADIUS );
108     glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( RADIUS,-RADIUS, 0.0 ); glVertex3d( RADIUS, 0.0, RADIUS ); glVertex3d( 0.0,-RADIUS, RADIUS );
109     glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( RADIUS,-RADIUS, 0.0 ); glVertex3d( 0.0,-RADIUS,-RADIUS ); glVertex3d( RADIUS, 0.0,-RADIUS );
110     glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-RADIUS, RADIUS, 0.0 ); glVertex3d(-RADIUS, 0.0, RADIUS ); glVertex3d( 0.0, RADIUS, RADIUS );
111     glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-RADIUS, RADIUS, 0.0 ); glVertex3d( 0.0, RADIUS,-RADIUS ); glVertex3d(-RADIUS, 0.0,-RADIUS );
112     glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-RADIUS,-RADIUS, 0.0 ); glVertex3d( 0.0,-RADIUS, RADIUS ); glVertex3d(-RADIUS, 0.0, RADIUS );
113     glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-RADIUS,-RADIUS, 0.0 ); glVertex3d(-RADIUS, 0.0,-RADIUS ); glVertex3d( 0.0,-RADIUS,-RADIUS );
114   glEnd();
115
116   glBegin( GL_QUADS );
117     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 );
118     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 );
119     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 );
120     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 );
121     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 );
122     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 );
123   glEnd();
124 }
125
126 static void drawWireCuboctahedron(void)
127 {
128   glBegin( GL_LINE_LOOP );
129     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 );
130   glEnd();
131   glBegin( GL_LINE_LOOP );
132     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 );
133   glEnd();
134   glBegin( GL_LINE_LOOP );
135     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 );
136   glEnd();
137   glBegin( GL_LINE_LOOP );
138     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 );
139   glEnd();
140   glBegin( GL_LINE_LOOP );
141     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 );
142   glEnd();
143   glBegin( GL_LINE_LOOP );
144     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 );
145   glEnd();
146 }
147
148 #undef RADIUS
149
150 /*
151  * This structure defines an entry in our function-table.
152  */
153 typedef struct
154 {
155     const char * const name;
156     void (*solid) (void);
157     void (*wire)  (void);
158 } entry;
159
160 #define ENTRY(e) {#e, drawSolid##e, drawWire##e}
161 static const entry table [] =
162 {
163     ENTRY (Tetrahedron),
164     ENTRY (Cube),
165     ENTRY (Octahedron),
166     ENTRY (Dodecahedron),
167     ENTRY (RhombicDodecahedron),
168     ENTRY (Icosahedron),
169     ENTRY (SierpinskiSponge),
170     ENTRY (Teapot),
171     ENTRY (Torus),
172     ENTRY (Sphere),
173     ENTRY (Cone),
174     ENTRY (Cylinder),
175     ENTRY (Cuboctahedron)
176 };
177 #undef ENTRY
178
179 /*!
180     Does printf()-like work using freeglut
181     glutBitmapString().  Uses a fixed font.  Prints
182     at the indicated row/column position.
183
184     Limitation: Cannot address pixels.
185     Limitation: Renders in screen coords, not model coords.
186 */
187 static void shapesPrintf (int row, int col, const char *fmt, ...)
188 {
189     static char buf[256];
190     int viewport[4];
191     void *font = GLUT_BITMAP_9_BY_15;
192     va_list args;
193
194     va_start(args, fmt);
195 #if defined(WIN32) && !defined(__CYGWIN__)
196     (void) _vsnprintf (buf, sizeof(buf), fmt, args);
197 #else
198     (void) vsnprintf (buf, sizeof(buf), fmt, args);
199 #endif
200     va_end(args);
201
202     glGetIntegerv(GL_VIEWPORT,viewport);
203
204     glPushMatrix();
205     glLoadIdentity();
206
207     glMatrixMode(GL_PROJECTION);
208     glPushMatrix();
209     glLoadIdentity();
210
211         glOrtho(0,viewport[2],0,viewport[3],-1,1);
212
213         glRasterPos2i
214         (
215               glutBitmapWidth(font, ' ') * col,
216             - glutBitmapHeight(font) * row + viewport[3]
217         );
218         glutBitmapString (font, (unsigned char*)buf);
219
220     glPopMatrix();
221     glMatrixMode(GL_MODELVIEW);
222     glPopMatrix();
223 }
224
225 /* GLUT callback Handlers */
226
227 static void
228 resize(int width, int height)
229 {
230     ar = (float) width / (float) height;
231
232     glViewport(0, 0, width, height);
233 }
234
235 static void display(void)
236 {
237     const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
238     const double a = t*90.0;
239
240     glMatrixMode(GL_PROJECTION);
241     glLoadIdentity();
242     if (persProject)
243         glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
244     else
245         glOrtho(-ar*3, ar*3, -3.0, 3.0, 2.0, 100.0);
246     glMatrixMode(GL_MODELVIEW);
247     glLoadIdentity();
248
249     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
250
251     glEnable(GL_LIGHTING);
252
253     glColor3d(1,0,0);
254
255     glPushMatrix();
256         glTranslated(0,1.2,-6);
257         glRotated(60,1,0,0);
258         glRotated(a,0,0,1);
259         table [function_index].solid ();
260     glPopMatrix();
261
262     glPushMatrix();
263         glTranslated(0,-1.2,-6);
264         glRotated(60,1,0,0);
265         glRotated(a,0,0,1);
266         table [function_index].wire ();
267     glPopMatrix();
268
269     glDisable(GL_LIGHTING);
270     glColor3d(0.1,0.1,0.4);
271
272     if( show_info ) {
273         shapesPrintf (1, 1, "Shape PgUp PgDn: %s", table [function_index].name);
274         shapesPrintf (2, 1, "Slices +-: %d   Stacks <>: %d", slices, stacks);
275         shapesPrintf (3, 1, "nSides +-: %d   nRings <>: %d", slices, stacks);
276         shapesPrintf (4, 1, "Depth  (): %d", depth);
277         shapesPrintf (5, 1, "Outer radius  Up  Down : %f", orad);
278         shapesPrintf (6, 1, "Inner radius Left Right: %f", irad);
279     } else {
280         printf ( "Shape %d slides %d stacks %d\n", function_index, slices, stacks ) ;
281     }
282
283     glutSwapBuffers();
284 }
285
286
287 static void
288 key(unsigned char key, int x, int y)
289 {
290     switch (key)
291     {
292     case 27 :
293     case 'Q':
294     case 'q': glutLeaveMainLoop () ;      break;
295
296     case 'I':
297     case 'i': show_info = ( show_info == GL_TRUE ) ? GL_FALSE : GL_TRUE; break;
298
299     case '=':
300     case '+': slices++;                   break;
301
302     case '-':
303     case '_': if( slices > -1 ) slices--; break;
304
305     case ',':
306     case '<': if( stacks > -1 ) stacks--; break;
307
308     case '.':
309     case '>': stacks++;                   break;
310
311     case '9': 
312     case '(': if( depth > -1 ) depth--;   break;
313
314     case '0': 
315     case ')': ++depth;                    break;
316
317     case 'P':
318     case 'p': persProject=!persProject;   break;
319
320     default:
321         break;
322     }
323
324     glutPostRedisplay();
325 }
326
327 static void special (int key, int x, int y)
328 {
329     switch (key)
330     {
331     case GLUT_KEY_PAGE_UP:    ++function_index; break;
332     case GLUT_KEY_PAGE_DOWN:  --function_index; break;
333     case GLUT_KEY_UP:         orad *= 2;        break;
334     case GLUT_KEY_DOWN:       orad /= 2;        break;
335
336     case GLUT_KEY_RIGHT:      irad *= 2;        break;
337     case GLUT_KEY_LEFT:       irad /= 2;        break;
338
339     default:
340         break;
341     }
342
343     if (0 > function_index)
344         function_index = NUMBEROF (table) - 1;
345
346     if (NUMBEROF (table) <= ( unsigned )function_index)
347         function_index = 0;
348 }
349
350
351 static void
352 idle(void)
353 {
354     glutPostRedisplay();
355 }
356
357 const GLfloat light_ambient[]  = { 0.0f, 0.0f, 0.0f, 1.0f };
358 const GLfloat light_diffuse[]  = { 1.0f, 1.0f, 1.0f, 1.0f };
359 const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
360 const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
361
362 const GLfloat mat_ambient[]    = { 0.7f, 0.7f, 0.7f, 1.0f };
363 const GLfloat mat_diffuse[]    = { 0.8f, 0.8f, 0.8f, 1.0f };
364 const GLfloat mat_specular[]   = { 1.0f, 1.0f, 1.0f, 1.0f };
365 const GLfloat high_shininess[] = { 100.0f };
366
367 /* Program entry point */
368
369 int
370 main(int argc, char *argv[])
371 {
372     glutInitWindowSize(640,480);
373     glutInitWindowPosition(40,40);
374     glutInit(&argc, argv);
375     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
376
377     glutCreateWindow("FreeGLUT Shapes");
378
379     glutReshapeFunc(resize);
380     glutDisplayFunc(display);
381     glutKeyboardFunc(key);
382     glutSpecialFunc(special);
383     glutIdleFunc(idle);
384
385     glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ;
386
387     glClearColor(1,1,1,1);
388     glEnable(GL_CULL_FACE);
389     glCullFace(GL_BACK);
390
391     glEnable(GL_DEPTH_TEST);
392     glDepthFunc(GL_LESS);
393
394     glEnable(GL_LIGHT0);
395     glEnable(GL_NORMALIZE);
396     glEnable(GL_COLOR_MATERIAL);
397
398     glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ambient);
399     glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse);
400     glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
401     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
402
403     glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient);
404     glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse);
405     glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular);
406     glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
407
408     glutMainLoop();
409
410 #ifdef _MSC_VER
411     /* DUMP MEMORY LEAK INFORMATION */
412     _CrtDumpMemoryLeaks () ;
413 #endif
414
415     return EXIT_SUCCESS;
416 }