forgotten commit. disabled until egl is adapted.
[AROS-Contrib.git] / Demo / Mesa / reflect.c
blob3d0409abd3eb2758d06f22ff3904ff4c23793f8d
1 /*
2 * Demo of a reflective, texture-mapped surface with OpenGL.
3 * Brian Paul August 14, 1995 This file is in the public domain.
5 * Hardware texture mapping is highly recommended!
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.
17 * This is a very crude demo. It could be much better.
21 * 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)
26 * Brian Paul (August 2005 - added multi window feature)
30 #include <assert.h>
31 #include <math.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include "GL/glut.h"
35 #include "showbuffer.h"
36 #include "readtex.h"
39 #define DEG2RAD (3.14159/180.0)
40 #define TABLE_TEXTURE "PROGDIR:images/tile.rgb"
41 #define MAX_OBJECTS 2
42 #define INIT_WIDTH 400
43 #define INIT_HEIGHT 300
45 #ifdef _WIN32
46 #undef CreateWindowA
47 #endif
49 struct window {
50 int id; /* returned by glutCreateWindow() */
51 int width, height;
52 GLboolean anim;
53 GLfloat xrot, yrot;
54 GLfloat spin;
55 GLenum showBuffer;
56 GLenum drawBuffer;
57 GLuint table_list;
58 GLuint objects_list[MAX_OBJECTS];
59 double t0;
60 struct window *next;
64 static struct window *FirstWindow = NULL;
67 static void
68 CreateWindow(void);
71 static struct window *
72 CurrentWindow(void)
74 int id = glutGetWindow();
75 struct window *w;
76 for (w = FirstWindow; w; w = w->next) {
77 if (w->id == id)
78 return w;
80 return NULL;
84 static GLboolean
85 AnyAnimating(void)
87 struct window *w;
88 for (w = FirstWindow; w; w = w->next) {
89 if (w->anim)
90 return 1;
92 return 0;
96 static void
97 KillWindow(struct window *w)
99 struct window *win, *prev = NULL;
100 for (win = FirstWindow; win; win = win->next) {
101 if (win == w) {
102 if (prev) {
103 prev->next = win->next;
105 else {
106 FirstWindow = win->next;
108 glutDestroyWindow(win->id);
109 win->next = NULL;
110 free(win);
111 return;
113 prev = win;
118 static void
119 KillAllWindows(void)
121 while (FirstWindow)
122 KillWindow(FirstWindow);
126 static GLuint
127 MakeTable(void)
129 static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
130 static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
131 GLuint table_list;
133 table_list = glGenLists(1);
134 glNewList( table_list, GL_COMPILE );
136 /* load table's texture */
137 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
138 /*glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
139 glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
140 glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
142 /* draw textured square for the table */
143 glPushMatrix();
144 glScalef( 4.0, 4.0, 4.0 );
145 glBegin( GL_POLYGON );
146 glNormal3f( 0.0, 1.0, 0.0 );
147 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 );
148 glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
149 glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 );
150 glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
151 glEnd();
152 glPopMatrix();
154 glDisable( GL_TEXTURE_2D );
156 glEndList();
157 return table_list;
161 static void
162 MakeObjects(GLuint *objects_list)
164 GLUquadricObj *q;
166 static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
167 static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
168 static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
170 q = gluNewQuadric();
171 gluQuadricDrawStyle( q, GLU_FILL );
172 gluQuadricNormals( q, GLU_SMOOTH );
174 objects_list[0] = glGenLists(1);
175 glNewList( objects_list[0], GL_COMPILE );
176 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
177 glMaterialfv( GL_FRONT, GL_EMISSION, black );
178 gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
179 glEndList();
181 objects_list[1] = glGenLists(1);
182 glNewList( objects_list[1], GL_COMPILE );
183 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
184 glMaterialfv( GL_FRONT, GL_EMISSION, black );
185 gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
186 glEndList();
188 gluDeleteQuadric(q);
192 static void
193 InitWindow(struct window *w)
195 GLint imgWidth, imgHeight;
196 GLenum imgFormat;
197 GLubyte *image = NULL;
199 w->table_list = MakeTable();
200 MakeObjects(w->objects_list);
202 image = LoadRGBImage( TABLE_TEXTURE, &imgWidth, &imgHeight, &imgFormat );
203 if (!image) {
204 printf("Couldn't read %s\n", TABLE_TEXTURE);
205 exit(0);
208 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight,
209 imgFormat, GL_UNSIGNED_BYTE, image);
210 free(image);
212 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
213 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
214 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
215 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
217 glShadeModel( GL_FLAT );
219 glEnable( GL_LIGHT0 );
220 glEnable( GL_LIGHTING );
222 glClearColor( 0.5, 0.5, 0.9, 0.0 );
224 glEnable( GL_NORMALIZE );
228 static void
229 Reshape(int width, int height)
231 struct window *w = CurrentWindow();
232 GLfloat yAspect = 2.5;
233 GLfloat xAspect = yAspect * (float) width / (float) height;
234 w->width = width;
235 w->height = height;
236 glViewport(0, 0, width, height);
237 glMatrixMode(GL_PROJECTION);
238 glLoadIdentity();
239 glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 );
240 glMatrixMode(GL_MODELVIEW);
241 glLoadIdentity();
245 static void
246 DrawObjects(struct window *w, GLfloat eyex, GLfloat eyey, GLfloat eyez)
248 (void) eyex;
249 (void) eyey;
250 (void) eyez;
251 #ifndef USE_ZBUFFER
252 if (eyex<0.5) {
253 #endif
254 glPushMatrix();
255 glTranslatef( 1.0, 1.5, 0.0 );
256 glRotatef( w->spin, 1.0, 0.5, 0.0 );
257 glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
258 glCallList( w->objects_list[0] );
259 glPopMatrix();
261 glPushMatrix();
262 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 );
263 glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
264 glRotatef( w->spin, 1.0, 0.5, 0.0 );
265 glScalef( 0.5, 0.5, 0.5 );
266 glCallList( w->objects_list[1] );
267 glPopMatrix();
268 #ifndef USE_ZBUFFER
270 else {
271 glPushMatrix();
272 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 );
273 glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
274 glRotatef( w->spin, 1.0, 0.5, 0.0 );
275 glScalef( 0.5, 0.5, 0.5 );
276 glCallList( w->objects_list[1] );
277 glPopMatrix();
279 glPushMatrix();
280 glTranslatef( 1.0, 1.5, 0.0 );
281 glRotatef( w->spin, 1.0, 0.5, 0.0 );
282 glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 );
283 glCallList( w->objects_list[0] );
284 glPopMatrix();
286 #endif
290 static void
291 DrawTable(struct window *w)
293 glCallList(w->table_list);
297 static void
298 DrawWindow(void)
300 struct window *w = CurrentWindow();
301 static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
302 GLfloat dist = 20.0;
303 GLfloat eyex, eyey, eyez;
305 if (w->drawBuffer == GL_NONE) {
306 glDrawBuffer(GL_BACK);
307 glReadBuffer(GL_BACK);
309 else {
310 glDrawBuffer(w->drawBuffer);
311 glReadBuffer(w->drawBuffer);
314 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
316 if (w->drawBuffer == GL_NONE) {
317 glDrawBuffer(GL_NONE);
320 eyex = dist * cos(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD);
321 eyez = dist * sin(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD);
322 eyey = dist * sin(w->xrot * DEG2RAD);
324 /* view from top */
325 glPushMatrix();
326 gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
328 glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
330 /* draw table into stencil planes */
331 glDisable( GL_DEPTH_TEST );
332 glEnable( GL_STENCIL_TEST );
333 glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
334 glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
335 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
336 DrawTable(w);
337 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
339 glEnable( GL_DEPTH_TEST );
341 /* render view from below (reflected viewport) */
342 /* only draw where stencil==1 */
343 if (eyey>0.0) {
344 glPushMatrix();
346 glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
347 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
348 glScalef( 1.0, -1.0, 1.0 );
350 /* Reposition light in reflected space. */
351 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
353 DrawObjects(w, eyex, eyey, eyez);
354 glPopMatrix();
356 /* Restore light's original unreflected position. */
357 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
360 glDisable( GL_STENCIL_TEST );
362 glEnable( GL_BLEND );
363 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
365 glEnable( GL_TEXTURE_2D );
366 DrawTable(w);
367 glDisable( GL_TEXTURE_2D );
368 glDisable( GL_BLEND );
370 /* view from top */
371 glPushMatrix();
373 DrawObjects(w, eyex, eyey, eyez);
375 glPopMatrix();
377 glPopMatrix();
379 if (w->showBuffer == GL_DEPTH) {
380 ShowDepthBuffer(w->width, w->height, 1.0, 0.0);
382 else if (w->showBuffer == GL_STENCIL) {
383 ShowStencilBuffer(w->width, w->height, 255.0, 0.0);
385 else if (w->showBuffer == GL_ALPHA) {
386 ShowAlphaBuffer(w->width, w->height);
389 if (w->drawBuffer == GL_FRONT)
390 glFinish();
391 else
392 glutSwapBuffers();
394 /* calc/show frame rate */
396 static GLint t0 = 0;
397 static GLint frames = 0;
398 GLint t = glutGet(GLUT_ELAPSED_TIME);
399 frames++;
400 if (t - t0 >= 5000) {
401 GLfloat seconds = (t - t0) / 1000.0;
402 GLfloat fps = frames / seconds;
403 printf("%d frames in %g seconds = %g FPS\n", frames, seconds, fps);
404 fflush(stdout);
405 t0 = t;
406 frames = 0;
412 static void
413 Idle(void)
415 double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
416 struct window *w;
417 for (w = FirstWindow; w; w = w->next) {
418 if (w->anim) {
419 double dt;
420 if (w->t0 < 0.0)
421 w->t0 = t;
422 dt = t - w->t0;
423 w->t0 = t;
424 w->spin += 60.0 * dt;
425 w->yrot += 90.0 * dt;
426 assert(w->id);
427 glutSetWindow(w->id);
428 glutPostRedisplay();
434 static void
435 UpdateIdleFunc(void)
437 if (AnyAnimating())
438 glutIdleFunc(Idle);
439 else
440 glutIdleFunc(NULL);
443 static void
444 Key(unsigned char key, int x, int y)
446 struct window *w = CurrentWindow();
447 (void) x;
448 (void) y;
450 switch (key) {
451 case 'd':
452 w->showBuffer = GL_DEPTH;
453 glutPostRedisplay();
454 break;
455 case 's':
456 w->showBuffer = GL_STENCIL;
457 glutPostRedisplay();
458 break;
459 case 'a':
460 w->showBuffer = GL_ALPHA;
461 glutPostRedisplay();
462 break;
463 case 'c':
464 w->showBuffer = GL_NONE;
465 glutPostRedisplay();
466 break;
467 case 'f':
468 if (w->drawBuffer == GL_FRONT)
469 w->drawBuffer = GL_BACK;
470 else
471 w->drawBuffer = GL_FRONT;
472 glutPostRedisplay();
473 break;
474 case '0':
475 w->drawBuffer = GL_NONE;
476 glutPostRedisplay();
477 break;
478 case ' ':
479 w->anim = !w->anim;
480 w->t0 = -1;
481 UpdateIdleFunc();
482 glutPostRedisplay();
483 break;
484 #ifndef __AROS__
485 case 'n':
486 CreateWindow();
487 UpdateIdleFunc();
488 break;
489 #endif
490 case 'k':
491 KillWindow(w);
492 if (FirstWindow == NULL)
493 exit(0);
494 break;
495 case 27:
496 KillAllWindows();
497 exit(0);
498 break;
499 default:
505 static void
506 SpecialKey(int key, int x, int y)
508 struct window *w = CurrentWindow();
509 (void) x;
510 (void) y;
511 switch (key) {
512 case GLUT_KEY_UP:
513 w->xrot += 3.0;
514 if (w->xrot > 85)
515 w->xrot = 85;
516 break;
517 case GLUT_KEY_DOWN:
518 w->xrot -= 3.0;
519 if (w->xrot < 5)
520 w->xrot = 5;
521 break;
522 case GLUT_KEY_LEFT:
523 w->yrot += 3.0;
524 break;
525 case GLUT_KEY_RIGHT:
526 w->yrot -= 3.0;
527 break;
529 glutPostRedisplay();
535 static void
536 Usage(void)
538 printf("Keys:\n");
539 printf(" a - show alpha buffer\n");
540 printf(" d - show depth buffer\n");
541 printf(" s - show stencil buffer\n");
542 printf(" c - show color buffer\n");
543 printf(" f - toggle rendering to front/back color buffer\n");
544 #ifndef __AROS__
545 printf(" n - create new window\n");
546 #endif
547 printf(" k - kill window\n");
548 printf(" SPACE - toggle animation\n");
549 printf(" ARROWS - rotate scene\n");
552 #include <proto/exec.h>
553 #include <proto/dos.h>
555 #define ARG_TEMPLATE "WINPOSX=X/N/K,WINPOSY=Y/N/K"
556 #define ARG_X 0
557 #define ARG_Y 1
558 #define NUM_ARGS 2
560 static IPTR args[NUM_ARGS];
561 WORD winx = -1, winy = -1;
562 #define W 320
563 #define H 200
565 static void correctpos(void)
567 if (winx == -1) winx = 100;
568 if (winy == -1) winy = 100;
571 static void getarguments(void)
573 struct RDArgs *myargs;
575 if ((myargs = ReadArgs(ARG_TEMPLATE, args, NULL)))
578 if (args[ARG_X]) winx = *(IPTR *)args[ARG_X];
579 if (args[ARG_Y]) winy = *(IPTR *)args[ARG_Y];
581 FreeArgs(myargs);
585 TEXT title[128];
587 static void
588 CreateWindow(void)
590 struct window *w = (struct window *) calloc(1, sizeof(struct window));
592 glutInitWindowPosition(winx, winy);
593 glutInitWindowSize(W, H);
594 w->id = glutCreateWindow("Reflect");
595 sprintf(title, "Reflect %d", w->id);
596 glutSetWindowTitle(title);
597 assert(w->id);
598 w->width = INIT_WIDTH;
599 w->height = INIT_HEIGHT;
600 w->anim = GL_TRUE;
601 w->xrot = 30.0;
602 w->yrot = 50.0;
603 w->spin = 0.0;
604 w->showBuffer = GL_NONE;
605 w->drawBuffer = GL_BACK;
607 InitWindow(w);
609 glutReshapeFunc(Reshape);
610 glutDisplayFunc(DrawWindow);
611 glutKeyboardFunc(Key);
612 glutSpecialFunc(SpecialKey);
614 /* insert at head of list */
615 w->next = FirstWindow;
616 FirstWindow = w;
620 main(int argc, char *argv[])
622 getarguments();
623 correctpos();
625 glutInit(&argc, argv);
626 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH |
627 GLUT_STENCIL | GLUT_ALPHA);
628 CreateWindow();
629 glutIdleFunc(Idle);
630 Usage();
631 glutMainLoop();
632 return 0;