blob: 9a41a86083a8d3ad7ab7442b6da3780cad836a52 [file] [log] [blame]
jtgafb833d1999-08-19 00:55:39 +00001/*
2 * Demo of a reflective, texture-mapped surface with OpenGL.
3 * Brian Paul August 14, 1995 This file is in the public domain.
4 *
5 * Hardware texture mapping is highly recommended!
6 *
7 * The basic steps are:
8 * 1. Render the reflective object (a polygon) from the normal viewpoint,
9 * setting the stencil planes = 1.
10 * 2. Render the scene from a special viewpoint: the viewpoint which
11 * is on the opposite side of the reflective plane. Only draw where
12 * stencil = 1. This draws the objects in the reflective surface.
13 * 3. Render the scene from the original viewpoint. This draws the
14 * objects in the normal fashion. Use blending when drawing
15 * the reflective, textured surface.
16 *
17 * This is a very crude demo. It could be much better.
18 */
19
20/*
Brian Paul7a6bb1b2000-04-12 01:08:30 +000021 * Authors:
22 * Brian Paul
23 * Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code.
24 * Mark Kilgard (April 1997)
25 * Brian Paul (April 2000 - added keyboard d/s options)
Brian Paul5d7c4862005-08-24 21:32:02 +000026 * Brian Paul (August 2005 - added multi window feature)
jtgafb833d1999-08-19 00:55:39 +000027 */
28
jtgafb833d1999-08-19 00:55:39 +000029
Brian Paul5d7c4862005-08-24 21:32:02 +000030#include <assert.h>
jtgafb833d1999-08-19 00:55:39 +000031#include <math.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include "GL/glut.h"
Brian Paul92eddb02005-01-09 17:37:50 +000035#include "showbuffer.h"
36#include "readtex.h"
jtgafb833d1999-08-19 00:55:39 +000037
38
39#define DEG2RAD (3.14159/180.0)
jtgafb833d1999-08-19 00:55:39 +000040#define TABLE_TEXTURE "../images/tile.rgb"
jtgafb833d1999-08-19 00:55:39 +000041#define MAX_OBJECTS 2
Brian Paul5d7c4862005-08-24 21:32:02 +000042#define INIT_WIDTH 400
43#define INIT_HEIGHT 300
jtgafb833d1999-08-19 00:55:39 +000044
45
Brian Paul5d7c4862005-08-24 21:32:02 +000046struct window {
47 int id; /* returned by glutCreateWindow() */
48 int width, height;
49 GLboolean anim;
50 GLfloat xrot, yrot;
51 GLfloat spin;
52 GLenum showBuffer;
53 GLuint table_list;
54 GLuint objects_list[MAX_OBJECTS];
55 double t0;
56 struct window *next;
57};
58
59
60static struct window *FirstWindow = NULL;
61
62
63static void
64CreateWindow(void);
65
66
67static struct window *
68CurrentWindow(void)
69{
70 int id = glutGetWindow();
71 struct window *w;
72 for (w = FirstWindow; w; w = w->next) {
73 if (w->id == id)
74 return w;
75 }
76 return NULL;
77}
78
79
80static GLboolean
81AnyAnimating(void)
82{
83 struct window *w;
84 for (w = FirstWindow; w; w = w->next) {
85 if (w->anim)
86 return 1;
87 }
88 return 0;
89}
90
91
92static void
93KillWindow(struct window *w)
94{
95 struct window *win, *prev = NULL;
96 for (win = FirstWindow; win; win = win->next) {
97 if (win == w) {
98 if (prev) {
99 prev->next = win->next;
100 }
101 else {
102 FirstWindow = win->next;
103 }
104 glutDestroyWindow(win->id);
105 win->next = NULL;
106 free(win);
107 return;
108 }
109 prev = win;
110 }
111}
112
113
114static void
115KillAllWindows(void)
116{
117 while (FirstWindow)
118 KillWindow(FirstWindow);
119}
120
121
122static GLuint
123MakeTable(void)
jtgafb833d1999-08-19 00:55:39 +0000124{
125 static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
126 static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
Brian Paul5d7c4862005-08-24 21:32:02 +0000127 GLuint table_list;
jtgafb833d1999-08-19 00:55:39 +0000128
129 table_list = glGenLists(1);
130 glNewList( table_list, GL_COMPILE );
131
132 /* load table's texture */
133 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
Brian Paul5d7c4862005-08-24 21:32:02 +0000134 /*glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
jtgafb833d1999-08-19 00:55:39 +0000135 glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
136 glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
137
138 /* draw textured square for the table */
139 glPushMatrix();
140 glScalef( 4.0, 4.0, 4.0 );
141 glBegin( GL_POLYGON );
142 glNormal3f( 0.0, 1.0, 0.0 );
143 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 );
144 glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
145 glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 );
146 glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
147 glEnd();
148 glPopMatrix();
149
150 glDisable( GL_TEXTURE_2D );
151
152 glEndList();
Brian Paul5d7c4862005-08-24 21:32:02 +0000153 return table_list;
jtgafb833d1999-08-19 00:55:39 +0000154}
155
156
Brian Paul5d7c4862005-08-24 21:32:02 +0000157static void
158MakeObjects(GLuint *objects_list)
jtgafb833d1999-08-19 00:55:39 +0000159{
160 GLUquadricObj *q;
161
162 static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
163 static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
164 static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
165
166 q = gluNewQuadric();
167 gluQuadricDrawStyle( q, GLU_FILL );
168 gluQuadricNormals( q, GLU_SMOOTH );
169
170 objects_list[0] = glGenLists(1);
171 glNewList( objects_list[0], GL_COMPILE );
172 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
173 glMaterialfv( GL_FRONT, GL_EMISSION, black );
174 gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
175 glEndList();
176
177 objects_list[1] = glGenLists(1);
178 glNewList( objects_list[1], GL_COMPILE );
179 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
180 glMaterialfv( GL_FRONT, GL_EMISSION, black );
181 gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
182 glEndList();
183}
184
185
Brian Paul5d7c4862005-08-24 21:32:02 +0000186static void
187InitWindow(struct window *w)
jtgafb833d1999-08-19 00:55:39 +0000188{
Brian Paul5d7c4862005-08-24 21:32:02 +0000189 GLint imgWidth, imgHeight;
190 GLenum imgFormat;
191 GLubyte *image = NULL;
jtgafb833d1999-08-19 00:55:39 +0000192
Brian Paul5d7c4862005-08-24 21:32:02 +0000193 w->table_list = MakeTable();
194 MakeObjects(w->objects_list);
195
196 image = LoadRGBImage( TABLE_TEXTURE, &imgWidth, &imgHeight, &imgFormat );
197 if (!image) {
jtgafb833d1999-08-19 00:55:39 +0000198 printf("Couldn't read %s\n", TABLE_TEXTURE);
199 exit(0);
200 }
201
Brian Paul5d7c4862005-08-24 21:32:02 +0000202 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight,
203 imgFormat, GL_UNSIGNED_BYTE, image);
204 free(image);
jtgafb833d1999-08-19 00:55:39 +0000205
206 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
207 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
208 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
209 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
jtgafb833d1999-08-19 00:55:39 +0000210
jtgafb833d1999-08-19 00:55:39 +0000211 glShadeModel( GL_FLAT );
212
213 glEnable( GL_LIGHT0 );
214 glEnable( GL_LIGHTING );
215
Brian Paul73ccfa02001-04-25 15:51:32 +0000216 glClearColor( 0.5, 0.5, 0.9, 0.0 );
jtgafb833d1999-08-19 00:55:39 +0000217
218 glEnable( GL_NORMALIZE );
219}
220
221
Brian Paul5d7c4862005-08-24 21:32:02 +0000222static void
223Reshape(int width, int height)
jtgafb833d1999-08-19 00:55:39 +0000224{
Brian Paul5d7c4862005-08-24 21:32:02 +0000225 struct window *w = CurrentWindow();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000226 GLfloat yAspect = 2.5;
Brian Paul5d7c4862005-08-24 21:32:02 +0000227 GLfloat xAspect = yAspect * (float) width / (float) height;
228 w->width = width;
229 w->height = height;
230 glViewport(0, 0, width, height);
jtgafb833d1999-08-19 00:55:39 +0000231 glMatrixMode(GL_PROJECTION);
232 glLoadIdentity();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000233 glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 );
jtgafb833d1999-08-19 00:55:39 +0000234 glMatrixMode(GL_MODELVIEW);
235 glLoadIdentity();
236}
237
238
Brian Paul5d7c4862005-08-24 21:32:02 +0000239static void
240DrawObjects(struct window *w, GLfloat eyex, GLfloat eyey, GLfloat eyez)
jtgafb833d1999-08-19 00:55:39 +0000241{
242 (void) eyex;
243 (void) eyey;
244 (void) eyez;
245#ifndef USE_ZBUFFER
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000246 if (eyex<0.5) {
jtgafb833d1999-08-19 00:55:39 +0000247#endif
Brian Paul5d7c4862005-08-24 21:32:02 +0000248 glPushMatrix();
249 glTranslatef( 1.0, 1.5, 0.0 );
250 glRotatef( w->spin, 1.0, 0.5, 0.0 );
251 glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
252 glCallList( w->objects_list[0] );
253 glPopMatrix();
254
255 glPushMatrix();
256 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 );
257 glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
258 glRotatef( w->spin, 1.0, 0.5, 0.0 );
259 glScalef( 0.5, 0.5, 0.5 );
260 glCallList( w->objects_list[1] );
261 glPopMatrix();
jtgafb833d1999-08-19 00:55:39 +0000262#ifndef USE_ZBUFFER
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000263 }
264 else {
Brian Paul5d7c4862005-08-24 21:32:02 +0000265 glPushMatrix();
266 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 );
267 glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
268 glRotatef( w->spin, 1.0, 0.5, 0.0 );
269 glScalef( 0.5, 0.5, 0.5 );
270 glCallList( w->objects_list[1] );
271 glPopMatrix();
jtgafb833d1999-08-19 00:55:39 +0000272
Brian Paul5d7c4862005-08-24 21:32:02 +0000273 glPushMatrix();
274 glTranslatef( 1.0, 1.5, 0.0 );
275 glRotatef( w->spin, 1.0, 0.5, 0.0 );
276 glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
277 glCallList( w->objects_list[0] );
278 glPopMatrix();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000279 }
jtgafb833d1999-08-19 00:55:39 +0000280#endif
281}
282
283
Brian Paul5d7c4862005-08-24 21:32:02 +0000284static void
285DrawTable(struct window *w)
jtgafb833d1999-08-19 00:55:39 +0000286{
Brian Paul5d7c4862005-08-24 21:32:02 +0000287 glCallList(w->table_list);
jtgafb833d1999-08-19 00:55:39 +0000288}
289
290
Brian Paul5d7c4862005-08-24 21:32:02 +0000291static void
292DrawWindow(void)
jtgafb833d1999-08-19 00:55:39 +0000293{
Brian Paul5d7c4862005-08-24 21:32:02 +0000294 struct window *w = CurrentWindow();
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000295 static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
jtgafb833d1999-08-19 00:55:39 +0000296 GLfloat dist = 20.0;
297 GLfloat eyex, eyey, eyez;
298
299 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
300
301
Brian Paul5d7c4862005-08-24 21:32:02 +0000302 eyex = dist * cos(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD);
303 eyez = dist * sin(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD);
304 eyey = dist * sin(w->xrot * DEG2RAD);
jtgafb833d1999-08-19 00:55:39 +0000305
306 /* view from top */
307 glPushMatrix();
308 gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
309
310 glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
311
312 /* draw table into stencil planes */
jtgafb833d1999-08-19 00:55:39 +0000313 glDisable( GL_DEPTH_TEST );
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000314 glEnable( GL_STENCIL_TEST );
jtgafb833d1999-08-19 00:55:39 +0000315 glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
316 glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
317 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
Brian Paul5d7c4862005-08-24 21:32:02 +0000318 DrawTable(w);
jtgafb833d1999-08-19 00:55:39 +0000319 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
320
jtgafb833d1999-08-19 00:55:39 +0000321 glEnable( GL_DEPTH_TEST );
jtgafb833d1999-08-19 00:55:39 +0000322
323 /* render view from below (reflected viewport) */
324 /* only draw where stencil==1 */
325 if (eyey>0.0) {
326 glPushMatrix();
327
328 glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
329 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
330 glScalef( 1.0, -1.0, 1.0 );
331
332 /* Reposition light in reflected space. */
333 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
334
Brian Paul5d7c4862005-08-24 21:32:02 +0000335 DrawObjects(w, eyex, eyey, eyez);
jtgafb833d1999-08-19 00:55:39 +0000336 glPopMatrix();
337
338 /* Restore light's original unreflected position. */
339 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
340 }
341
342 glDisable( GL_STENCIL_TEST );
343
344 glEnable( GL_BLEND );
345 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
346
jtgafb833d1999-08-19 00:55:39 +0000347 glEnable( GL_TEXTURE_2D );
Brian Paul5d7c4862005-08-24 21:32:02 +0000348 DrawTable(w);
jtgafb833d1999-08-19 00:55:39 +0000349 glDisable( GL_TEXTURE_2D );
350 glDisable( GL_BLEND );
351
352 /* view from top */
353 glPushMatrix();
354
Brian Paul5d7c4862005-08-24 21:32:02 +0000355 DrawObjects(w, eyex, eyey, eyez);
jtgafb833d1999-08-19 00:55:39 +0000356
357 glPopMatrix();
358
359 glPopMatrix();
360
Brian Paul5d7c4862005-08-24 21:32:02 +0000361 if (w->showBuffer == GL_DEPTH) {
362 ShowDepthBuffer(w->width, w->height, 1.0, 0.0);
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000363 }
Brian Paul5d7c4862005-08-24 21:32:02 +0000364 else if (w->showBuffer == GL_STENCIL) {
365 ShowStencilBuffer(w->width, w->height, 255.0, 0.0);
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000366 }
Brian Paul5d7c4862005-08-24 21:32:02 +0000367 else if (w->showBuffer == GL_ALPHA) {
368 ShowAlphaBuffer(w->width, w->height);
Brian Paul73ccfa02001-04-25 15:51:32 +0000369 }
jtgafb833d1999-08-19 00:55:39 +0000370
371 glutSwapBuffers();
Brian Paulcefc42f2000-09-15 16:43:57 +0000372
Brian Paul5d7c4862005-08-24 21:32:02 +0000373 /* calc/show frame rate */
Brian Paulcefc42f2000-09-15 16:43:57 +0000374 {
Brian Paul5d7c4862005-08-24 21:32:02 +0000375 static GLint t0 = 0;
376 static GLint frames = 0;
Brian Paulcefc42f2000-09-15 16:43:57 +0000377 GLint t = glutGet(GLUT_ELAPSED_TIME);
Brian Paul5d7c4862005-08-24 21:32:02 +0000378 frames++;
379 if (t - t0 >= 5000) {
380 GLfloat seconds = (t - t0) / 1000.0;
381 GLfloat fps = frames / seconds;
382 printf("%d frames in %g seconds = %g FPS\n", frames, seconds, fps);
383 t0 = t;
384 frames = 0;
Brian Paulcefc42f2000-09-15 16:43:57 +0000385 }
386 }
jtgafb833d1999-08-19 00:55:39 +0000387}
jtgafb833d1999-08-19 00:55:39 +0000388
389
Brian Paul5d7c4862005-08-24 21:32:02 +0000390static void
391Idle(void)
Brian Paul2b2e6212001-01-23 23:43:53 +0000392{
Brian Paul5d7c4862005-08-24 21:32:02 +0000393 double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
394 struct window *w;
395 for (w = FirstWindow; w; w = w->next) {
396 if (w->anim) {
397 double dt;
398 if (w->t0 < 0.0)
399 w->t0 = t;
400 dt = t - w->t0;
401 w->t0 = t;
402 w->spin += 60.0 * dt;
403 w->yrot += 90.0 * dt;
404 assert(w->id);
405 glutSetWindow(w->id);
406 glutPostRedisplay();
407 }
408 }
Brian Paul2b2e6212001-01-23 23:43:53 +0000409}
410
411
Brian Paul5d7c4862005-08-24 21:32:02 +0000412static void
413Key(unsigned char key, int x, int y)
jtgafb833d1999-08-19 00:55:39 +0000414{
Brian Paul5d7c4862005-08-24 21:32:02 +0000415 struct window *w = CurrentWindow();
jtgafb833d1999-08-19 00:55:39 +0000416 (void) x;
417 (void) y;
Brian Paul5d7c4862005-08-24 21:32:02 +0000418
419 switch (key) {
420 case 'd':
421 w->showBuffer = GL_DEPTH;
422 glutPostRedisplay();
423 break;
424 case 's':
425 w->showBuffer = GL_STENCIL;
426 glutPostRedisplay();
427 break;
428 case 'a':
429 w->showBuffer = GL_ALPHA;
430 glutPostRedisplay();
431 break;
432 case 'c':
433 w->showBuffer = GL_NONE;
434 glutPostRedisplay();
435 break;
436 case ' ':
437 w->anim = !w->anim;
438 w->t0 = -1;
439 if (AnyAnimating())
440 glutIdleFunc(Idle);
Brian Paul2b2e6212001-01-23 23:43:53 +0000441 else
442 glutIdleFunc(NULL);
Brian Paul5d7c4862005-08-24 21:32:02 +0000443 glutPostRedisplay();
444 break;
445 case 'n':
446 CreateWindow();
447 break;
448 case 'k':
449 KillWindow(w);
450 if (FirstWindow == NULL)
451 exit(0);
452 break;
453 case 27:
454 KillAllWindows();
jtgafb833d1999-08-19 00:55:39 +0000455 exit(0);
Brian Paul5d7c4862005-08-24 21:32:02 +0000456 break;
457 default:
458 ;
Brian Paul7a6bb1b2000-04-12 01:08:30 +0000459 }
jtgafb833d1999-08-19 00:55:39 +0000460}
461
462
Brian Paul5d7c4862005-08-24 21:32:02 +0000463static void
464SpecialKey(int key, int x, int y)
jtgafb833d1999-08-19 00:55:39 +0000465{
Brian Paul5d7c4862005-08-24 21:32:02 +0000466 struct window *w = CurrentWindow();
jtgafb833d1999-08-19 00:55:39 +0000467 (void) x;
468 (void) y;
469 switch (key) {
470 case GLUT_KEY_UP:
Brian Paul5d7c4862005-08-24 21:32:02 +0000471 w->xrot += 3.0;
472 if (w->xrot > 85)
473 w->xrot = 85;
jtgafb833d1999-08-19 00:55:39 +0000474 break;
475 case GLUT_KEY_DOWN:
Brian Paul5d7c4862005-08-24 21:32:02 +0000476 w->xrot -= 3.0;
477 if (w->xrot < 5)
478 w->xrot = 5;
jtgafb833d1999-08-19 00:55:39 +0000479 break;
480 case GLUT_KEY_LEFT:
Brian Paul5d7c4862005-08-24 21:32:02 +0000481 w->yrot += 3.0;
jtgafb833d1999-08-19 00:55:39 +0000482 break;
483 case GLUT_KEY_RIGHT:
Brian Paul5d7c4862005-08-24 21:32:02 +0000484 w->yrot -= 3.0;
jtgafb833d1999-08-19 00:55:39 +0000485 break;
486 }
487 glutPostRedisplay();
488}
489
490
Brian Paul5d7c4862005-08-24 21:32:02 +0000491static void
492CreateWindow(void)
jtgafb833d1999-08-19 00:55:39 +0000493{
Brian Paul5d7c4862005-08-24 21:32:02 +0000494 char title[1000];
495 struct window *w = (struct window *) calloc(1, sizeof(struct window));
496
497 glutInitWindowSize(INIT_WIDTH, INIT_HEIGHT);
498 w->id = glutCreateWindow("foo");
499 sprintf(title, "reflect window %d", w->id);
500 glutSetWindowTitle(title);
501 assert(w->id);
502 w->width = INIT_WIDTH;
503 w->height = INIT_HEIGHT;
504 w->anim = GL_TRUE;
505 w->xrot = 30.0;
506 w->yrot = 50.0;
507 w->spin = 0.0;
508 w->showBuffer = GL_NONE;
509
510 InitWindow(w);
511
512 glutReshapeFunc(Reshape);
513 glutDisplayFunc(DrawWindow);
jtgafb833d1999-08-19 00:55:39 +0000514 glutKeyboardFunc(Key);
515 glutSpecialFunc(SpecialKey);
Brian Paul5d7c4862005-08-24 21:32:02 +0000516
517 /* insert at head of list */
518 w->next = FirstWindow;
519 FirstWindow = w;
520}
521
522
523static void
524Usage(void)
525{
526 printf("Keys:\n");
527 printf(" a - show alpha buffer\n");
528 printf(" d - show depth buffer\n");
529 printf(" s - show stencil buffer\n");
530 printf(" c - show color buffer\n");
531 printf(" n - create new window\n");
532 printf(" k - kill window\n");
533 printf(" SPACE - toggle animation\n");
534 printf(" ARROWS - rotate scene\n");
535}
536
537
538int
539main(int argc, char *argv[])
540{
541 glutInit(&argc, argv);
542 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH |
543 GLUT_STENCIL | GLUT_ALPHA);
544 CreateWindow();
545 glutIdleFunc(Idle);
546 Usage();
jtgafb833d1999-08-19 00:55:39 +0000547 glutMainLoop();
548 return 0;
549}