b22cb7f38edb873503d724934724825f85988b54
[freeglut] / progs / test-shapes-gles1 / test-shapes-gles1.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 #define glRotated glRotatef
56 #define glTranslated glTranslatef
57
58 /*
59  * These global variables control which object is drawn,
60  * and how it is drawn.  No object uses all of these
61  * variables.
62  */
63 static int function_index;
64 static int slices = 16;
65 static int stacks = 16;
66 static double irad = .25;
67 static double orad = 1.0;   /* doubles as size for objects other than Torus */
68 static int depth = 4;
69 static double offset[ 3 ] = { 0, 0, 0 };
70 static GLboolean show_info = GL_TRUE;
71 static float ar;
72 static GLboolean persProject = GL_TRUE;
73
74 /*
75  * These one-liners draw particular objects, fetching appropriate
76  * information from the above globals.  They are just thin wrappers
77  * for the FreeGLUT objects.
78  */
79 static void drawSolidTetrahedron(void)         { glutSolidTetrahedron ();                        }
80 static void drawWireTetrahedron(void)          { glutWireTetrahedron ();                         }
81 static void drawSolidCube(void)                { glutSolidCube(orad);                            }  /* orad doubles as size input */
82 static void drawWireCube(void)                 { glutWireCube(orad);                             }  /* orad doubles as size input */
83 static void drawSolidOctahedron(void)          { glutSolidOctahedron ();                         }
84 static void drawWireOctahedron(void)           { glutWireOctahedron ();                          }
85 static void drawSolidDodecahedron(void)        { glutSolidDodecahedron ();                       }
86 static void drawWireDodecahedron(void)         { glutWireDodecahedron ();                        }
87 static void drawSolidRhombicDodecahedron(void) { glutSolidRhombicDodecahedron ();                }
88 static void drawWireRhombicDodecahedron(void)  { glutWireRhombicDodecahedron ();                 }
89 static void drawSolidIcosahedron(void)         { glutSolidIcosahedron ();                        }
90 static void drawWireIcosahedron(void)          { glutWireIcosahedron ();                         }
91 static void drawSolidSierpinskiSponge(void)    { glutSolidSierpinskiSponge (depth, offset, orad);}  /* orad doubles as size input */
92 static void drawWireSierpinskiSponge(void)     { glutWireSierpinskiSponge (depth, offset, orad); }  /* orad doubles as size input */
93 static void drawSolidSphere(void)              { glutSolidSphere(orad,slices,stacks);            }  /* orad doubles as size input */
94 static void drawWireSphere(void)               { glutWireSphere(orad,slices,stacks);             }  /* orad doubles as size input */
95 #ifndef EGL_VERSION_1_0
96 static void drawSolidTorus(void)               { glutSolidTorus(irad,orad,slices,stacks);        }
97 static void drawWireTorus(void)                { glutWireTorus (irad,orad,slices,stacks);        }
98 static void drawSolidCone(void)                { glutSolidCone(orad,orad,slices,stacks);         }  /* orad doubles as size input */
99 static void drawWireCone(void)                 { glutWireCone(orad,orad,slices,stacks);          }  /* orad doubles as size input */
100 static void drawSolidCylinder(void)            { glutSolidCylinder(orad,orad,slices,stacks);     }  /* orad doubles as size input */
101 static void drawWireCylinder(void)             { glutWireCylinder(orad,orad,slices,stacks);      }  /* orad doubles as size input */
102 #endif
103
104 /*
105  * This structure defines an entry in our function-table.
106  */
107 typedef struct
108 {
109     const char * const name;
110     void (*solid) (void);
111     void (*wire)  (void);
112 } entry;
113
114 #define ENTRY(e) {#e, drawSolid##e, drawWire##e}
115 static const entry table [] =
116 {
117     ENTRY (Cube),
118     ENTRY (Tetrahedron),
119     ENTRY (Octahedron),
120     ENTRY (Dodecahedron),
121     ENTRY (RhombicDodecahedron),
122     ENTRY (Icosahedron),
123     ENTRY (SierpinskiSponge),
124     ENTRY (Sphere),
125 };
126 #undef ENTRY
127
128 /*!
129     Does printf()-like work using freeglut
130     glutBitmapString().  Uses a fixed font.  Prints
131     at the indicated row/column position.
132
133     Limitation: Cannot address pixels.
134     Limitation: Renders in screen coords, not model coords.
135 */
136 static void shapesPrintf (int row, int col, const char *fmt, ...)
137 {
138 }
139
140 /* GLUT callback Handlers */
141
142 static void
143 resize(int width, int height)
144 {
145     ar = (float) width / (float) height;
146
147     glViewport(0, 0, width, height);
148 }
149
150 static void display(void)
151 {
152     const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
153     const double a = t*90.0;
154
155     glMatrixMode(GL_PROJECTION);
156     glLoadIdentity();
157     glFrustumf(-ar, ar, -1.0, 1.0, 2.0, 100.0);
158     glMatrixMode(GL_MODELVIEW);
159     glLoadIdentity();
160
161     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
162
163     glEnable(GL_LIGHTING);
164
165     glColor4f(1,0,0,1);
166
167     glPushMatrix();
168         glTranslated(0,1.2,-6);
169         glRotated(60,1,0,0);
170         glRotated(a,0,0,1);
171         table [function_index].solid ();
172     glPopMatrix();
173
174     glPushMatrix();
175         glTranslated(0,-1.2,-6);
176         glRotated(60,1,0,0);
177         glRotated(a,0,0,1);
178         table [function_index].wire ();
179     glPopMatrix();
180
181     glDisable(GL_LIGHTING);
182     glColor4f(0.1,0.1,0.4,1.0);
183
184     glutSwapBuffers();
185 }
186
187
188 static void
189 key(unsigned char key, int x, int y)
190 {
191     switch (key)
192     {
193     case 27 :
194     case 'Q':
195     case 'q': glutLeaveMainLoop () ;      break;
196
197     case 'I':
198     case 'i': show_info = ( show_info == GL_TRUE ) ? GL_FALSE : GL_TRUE; break;
199
200     case '=':
201     case '+': slices++; printf("%d,%d\n", slices, stacks); break;
202
203     case '-':
204     case '_': if( slices > -1 ) slices--; break;
205
206     case ',':
207     case '<': if( stacks > -1 ) stacks--; break;
208
209     case '.':
210     case '>': stacks++;                   break;
211
212     case '9': 
213     case '(': if( depth > -1 ) depth--;   break;
214
215     case '0': 
216     case ')': ++depth;                    break;
217
218     case 'P':
219     case 'p': persProject=!persProject;   break;
220
221     default:
222         break;
223     }
224
225     glutPostRedisplay();
226 }
227
228 static void special (int key, int x, int y)
229 {
230     switch (key)
231     {
232     case GLUT_KEY_PAGE_UP:    ++function_index; break;
233     case GLUT_KEY_PAGE_DOWN:  --function_index; break;
234     case GLUT_KEY_UP:         orad *= 2;        break;
235     case GLUT_KEY_DOWN:       orad /= 2;        break;
236
237     case GLUT_KEY_RIGHT:      irad *= 2;        break;
238     case GLUT_KEY_LEFT:       irad /= 2;        break;
239
240     default:
241         break;
242     }
243
244     if (0 > function_index)
245         function_index = NUMBEROF (table) - 1;
246
247     if (NUMBEROF (table) <= ( unsigned )function_index)
248         function_index = 0;
249 }
250
251
252 static void
253 idle(void)
254 {
255     glutPostRedisplay();
256 }
257
258 static void
259 onMouseClick(int button, int state, int x, int y) {
260   if (state == GLUT_DOWN)
261     special(GLUT_KEY_PAGE_DOWN, 0, 0);
262 }
263
264 const GLfloat light_ambient[]  = { 0.0f, 0.0f, 0.0f, 1.0f };
265 const GLfloat light_diffuse[]  = { 1.0f, 1.0f, 1.0f, 1.0f };
266 const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
267 const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
268
269 const GLfloat mat_ambient[]    = { 0.7f, 0.7f, 0.7f, 1.0f };
270 const GLfloat mat_diffuse[]    = { 0.8f, 0.8f, 0.8f, 1.0f };
271 const GLfloat mat_specular[]   = { 1.0f, 1.0f, 1.0f, 1.0f };
272 const GLfloat high_shininess[] = { 100.0f };
273
274 /* Program entry point */
275
276 int
277 main(int argc, char *argv[])
278 {
279     glutInitWindowSize(640,480);
280     glutInitWindowPosition(40,40);
281     glutInit(&argc, argv);
282     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
283
284     glutCreateWindow("FreeGLUT Shapes");
285
286     glutReshapeFunc(resize);
287     glutDisplayFunc(display);
288     glutKeyboardFunc(key);
289     glutSpecialFunc(special);
290     glutIdleFunc(idle);
291     glutMouseFunc(onMouseClick);
292
293     glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ;
294
295     glClearColor(1,1,1,1);
296     glEnable(GL_CULL_FACE);
297     glCullFace(GL_BACK);
298
299     glEnable(GL_DEPTH_TEST);
300     glDepthFunc(GL_LESS);
301
302     glEnable(GL_LIGHT0);
303     glEnable(GL_NORMALIZE);
304     glEnable(GL_COLOR_MATERIAL);
305
306     glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ambient);
307     glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse);
308     glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
309     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
310
311     glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient);
312     glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse);
313     glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular);
314     glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
315
316     glutMainLoop();
317
318 #ifdef _MSC_VER
319     /* DUMP MEMORY LEAK INFORMATION */
320     _CrtDumpMemoryLeaks () ;
321 #endif
322
323     return EXIT_SUCCESS;
324 }