lots of changes
[mesa.git] / progs / demos / reflect.c
1 /* $Id: reflect.c,v 1.1 1999/08/19 00:55:40 jtg Exp $ */
2
3 /*
4 * Demo of a reflective, texture-mapped surface with OpenGL.
5 * Brian Paul August 14, 1995 This file is in the public domain.
6 *
7 * Hardware texture mapping is highly recommended!
8 *
9 * The basic steps are:
10 * 1. Render the reflective object (a polygon) from the normal viewpoint,
11 * setting the stencil planes = 1.
12 * 2. Render the scene from a special viewpoint: the viewpoint which
13 * is on the opposite side of the reflective plane. Only draw where
14 * stencil = 1. This draws the objects in the reflective surface.
15 * 3. Render the scene from the original viewpoint. This draws the
16 * objects in the normal fashion. Use blending when drawing
17 * the reflective, textured surface.
18 *
19 * This is a very crude demo. It could be much better.
20 */
21
22 /*
23 * Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code.
24 *
25 * August 1996 - A few optimizations by Brian
26 */
27
28 /*
29 * April, 1997 - Added Mark Kilgard's changes.
30 */
31
32 /*
33 * $Log: reflect.c,v $
34 * Revision 1.1 1999/08/19 00:55:40 jtg
35 * Initial revision
36 *
37 * Revision 3.4 1999/03/28 18:22:05 brianp
38 * minor clean-up
39 *
40 * Revision 3.3 1998/11/22 02:54:29 brianp
41 * only draw one stack for gluCylinders
42 *
43 * Revision 3.2 1998/11/19 02:53:48 brianp
44 * changed texture image and background color
45 *
46 * Revision 3.1 1998/11/05 04:34:04 brianp
47 * moved image files to ../images/ directory
48 *
49 * Revision 3.0 1998/02/14 18:42:29 brianp
50 * initial rev
51 *
52 */
53
54
55 #define USE_ZBUFFER
56
57
58 /* OK, without hardware support this is overkill. */
59 #define USE_TEXTURE
60
61 #include <math.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include "GL/glut.h"
65
66 #include "../util/readtex.c" /* a hack, I know */
67
68
69 #define DEG2RAD (3.14159/180.0)
70
71
72 #define TABLE_TEXTURE "../images/tile.rgb"
73
74 static int ImgWidth, ImgHeight;
75 static GLenum ImgFormat;
76 static GLubyte *Image = NULL;
77
78 #define MAX_OBJECTS 2
79
80 static GLint table_list;
81 static GLint objects_list[MAX_OBJECTS];
82
83
84 static GLfloat xrot, yrot;
85 static GLfloat spin;
86
87
88
89 static void make_table( void )
90 {
91 static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
92 static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
93
94 table_list = glGenLists(1);
95 glNewList( table_list, GL_COMPILE );
96
97 /* load table's texture */
98 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
99 /* glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
100 glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
101 glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
102
103 /* draw textured square for the table */
104 glPushMatrix();
105 glScalef( 4.0, 4.0, 4.0 );
106 glBegin( GL_POLYGON );
107 glNormal3f( 0.0, 1.0, 0.0 );
108 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 );
109 glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
110 glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 );
111 glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 );
112 glEnd();
113 glPopMatrix();
114
115 glDisable( GL_TEXTURE_2D );
116
117 glEndList();
118 }
119
120
121 static void make_objects( void )
122 {
123 GLUquadricObj *q;
124
125 static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
126 static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
127 static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
128
129 q = gluNewQuadric();
130 gluQuadricDrawStyle( q, GLU_FILL );
131 gluQuadricNormals( q, GLU_SMOOTH );
132
133 objects_list[0] = glGenLists(1);
134 glNewList( objects_list[0], GL_COMPILE );
135 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
136 glMaterialfv( GL_FRONT, GL_EMISSION, black );
137 gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 );
138 glEndList();
139
140 objects_list[1] = glGenLists(1);
141 glNewList( objects_list[1], GL_COMPILE );
142 glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
143 glMaterialfv( GL_FRONT, GL_EMISSION, black );
144 gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 );
145 glEndList();
146 }
147
148
149 static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
150
151 static void init( void )
152 {
153 make_table();
154 make_objects();
155
156 /* Setup texture */
157 #ifdef USE_TEXTURE
158
159 Image = LoadRGBImage( TABLE_TEXTURE, &ImgWidth, &ImgHeight, &ImgFormat );
160 if (!Image) {
161 printf("Couldn't read %s\n", TABLE_TEXTURE);
162 exit(0);
163 }
164
165 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ImgWidth, ImgHeight,
166 ImgFormat, GL_UNSIGNED_BYTE, Image);
167
168 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
169 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
170 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
171 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
172 #endif
173
174
175 xrot = 30.0;
176 yrot = 50.0;
177 spin = 0.0;
178
179 #ifndef USE_ZBUFFER
180 glEnable( GL_CULL_FACE );
181 #endif
182
183 glShadeModel( GL_FLAT );
184
185 glEnable( GL_LIGHT0 );
186 glEnable( GL_LIGHTING );
187
188 glClearColor( 0.5, 0.5, 0.9, 1.0 );
189
190 glEnable( GL_NORMALIZE );
191 }
192
193
194
195 static void reshape(int w, int h)
196 {
197 GLfloat aspect = (float) w / (float) h;
198
199 glViewport(0, 0, w, h);
200 glMatrixMode(GL_PROJECTION);
201 glLoadIdentity();
202 glFrustum( -aspect, aspect, -1.0, 1.0, 4.0, 300.0 );
203 glMatrixMode(GL_MODELVIEW);
204 glLoadIdentity();
205 }
206
207
208
209 static void draw_objects( GLfloat eyex, GLfloat eyey, GLfloat eyez )
210 {
211 (void) eyex;
212 (void) eyey;
213 (void) eyez;
214 #ifndef USE_ZBUFFER
215 if (eyex<0.5)
216 {
217 #endif
218 glPushMatrix();
219 glTranslatef( 1.0, 1.5, 0.0 );
220 glRotatef( spin, 1.0, 0.5, 0.0 );
221 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
222 glCallList( objects_list[0] );
223 glPopMatrix();
224
225 glPushMatrix();
226 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
227 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
228 glRotatef( spin, 1.0, 0.5, 0.0 );
229 glScalef( 0.5, 0.5, 0.5 );
230 glCallList( objects_list[1] );
231 glPopMatrix();
232 #ifndef USE_ZBUFFER
233 }
234 else
235 {
236 glPushMatrix();
237 glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
238 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
239 glRotatef( spin, 1.0, 0.5, 0.0 );
240 glScalef( 0.5, 0.5, 0.5 );
241 glCallList( objects_list[1] );
242 glPopMatrix();
243
244 glPushMatrix();
245 glTranslatef( 1.0, 1.5, 0.0 );
246 glRotatef( spin, 1.0, 0.5, 0.0 );
247 glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
248 glCallList( objects_list[0] );
249 glPopMatrix();
250 }
251 #endif
252 }
253
254
255
256 static void draw_table( void )
257 {
258 glCallList( table_list );
259 }
260
261
262
263 static void draw_scene( void )
264 {
265 GLfloat dist = 20.0;
266 GLfloat eyex, eyey, eyez;
267
268 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
269
270
271 eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
272 eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
273 eyey = dist * sin(xrot*DEG2RAD);
274
275 /* view from top */
276 glPushMatrix();
277 gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
278
279 glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
280
281 /* draw table into stencil planes */
282 glEnable( GL_STENCIL_TEST );
283 #ifdef USE_ZBUFFER
284 glDisable( GL_DEPTH_TEST );
285 #endif
286 glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
287 glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
288 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
289 draw_table();
290 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
291
292 #ifdef USE_ZBUFFER
293 glEnable( GL_DEPTH_TEST );
294 #endif
295
296
297 /* render view from below (reflected viewport) */
298 /* only draw where stencil==1 */
299 if (eyey>0.0) {
300 glPushMatrix();
301
302 glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */
303 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
304 glScalef( 1.0, -1.0, 1.0 );
305
306 /* Reposition light in reflected space. */
307 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
308
309 draw_objects(eyex, eyey, eyez);
310 glPopMatrix();
311
312 /* Restore light's original unreflected position. */
313 glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
314 }
315
316 glDisable( GL_STENCIL_TEST );
317
318 glEnable( GL_BLEND );
319 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
320
321 #ifdef USE_TEXTURE
322 glEnable( GL_TEXTURE_2D );
323 #endif
324 draw_table();
325 glDisable( GL_TEXTURE_2D );
326 glDisable( GL_BLEND );
327
328 /* view from top */
329 glPushMatrix();
330
331 draw_objects(eyex, eyey, eyez);
332
333 glPopMatrix();
334
335 glPopMatrix();
336
337 glutSwapBuffers();
338 }
339
340
341
342 #if 0
343 void draw_scene(void)
344 {
345 GLfloat dist = 20.0;
346 GLfloat eyex, eyey, eyez;
347
348 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
349
350
351 eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
352 eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
353 eyey = dist * sin(xrot*DEG2RAD);
354
355 /* view from top */
356 glPushMatrix();
357 gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
358
359 draw_table();
360
361 glPopMatrix();
362
363 glutSwapBuffers();
364 }
365 #endif
366
367
368 static void Key( unsigned char key, int x, int y )
369 {
370 (void) x;
371 (void) y;
372 if (key==27)
373 exit(0);
374 }
375
376
377 static void SpecialKey( int key, int x, int y )
378 {
379 (void) x;
380 (void) y;
381 switch (key) {
382 case GLUT_KEY_UP:
383 xrot += 3.0;
384 #ifndef USE_ZBUFFER
385 if ( xrot > 180 ) xrot = 180;
386 #endif
387 break;
388 case GLUT_KEY_DOWN:
389 xrot -= 3.0;
390 #ifndef USE_ZBUFFER
391 if ( xrot < 0 ) xrot = 0;
392 #endif
393 break;
394 case GLUT_KEY_LEFT:
395 yrot += 3.0;
396 break;
397 case GLUT_KEY_RIGHT:
398 yrot -= 3.0;
399 break;
400 }
401 glutPostRedisplay();
402 }
403
404
405
406 static void idle( void )
407 {
408 spin += 2.0;
409 yrot += 3.0;
410 glutPostRedisplay();
411 }
412
413
414
415 int main( int argc, char *argv[] )
416 {
417 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB
418 #ifdef USE_ZBUFFER
419 | GLUT_DEPTH
420 #endif
421 | GLUT_STENCIL);
422 glutInitWindowPosition( 0, 0 );
423 glutInitWindowSize(400, 300 );
424 glutCreateWindow(argv[0]);
425 glutReshapeFunc(reshape);
426 glutDisplayFunc(draw_scene);
427 glutKeyboardFunc(Key);
428 glutSpecialFunc(SpecialKey);
429 glutIdleFunc(idle);
430
431 init();
432
433 glutMainLoop();
434 return 0;
435 }