| /* $Id: reflect.c,v 1.1 1999/08/19 00:55:40 jtg Exp $ */ |
| |
| /* |
| * Demo of a reflective, texture-mapped surface with OpenGL. |
| * Brian Paul August 14, 1995 This file is in the public domain. |
| * |
| * Hardware texture mapping is highly recommended! |
| * |
| * The basic steps are: |
| * 1. Render the reflective object (a polygon) from the normal viewpoint, |
| * setting the stencil planes = 1. |
| * 2. Render the scene from a special viewpoint: the viewpoint which |
| * is on the opposite side of the reflective plane. Only draw where |
| * stencil = 1. This draws the objects in the reflective surface. |
| * 3. Render the scene from the original viewpoint. This draws the |
| * objects in the normal fashion. Use blending when drawing |
| * the reflective, textured surface. |
| * |
| * This is a very crude demo. It could be much better. |
| */ |
| |
| /* |
| * Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code. |
| * |
| * August 1996 - A few optimizations by Brian |
| */ |
| |
| /* |
| * April, 1997 - Added Mark Kilgard's changes. |
| */ |
| |
| /* |
| * $Log: reflect.c,v $ |
| * Revision 1.1 1999/08/19 00:55:40 jtg |
| * Initial revision |
| * |
| * Revision 3.4 1999/03/28 18:22:05 brianp |
| * minor clean-up |
| * |
| * Revision 3.3 1998/11/22 02:54:29 brianp |
| * only draw one stack for gluCylinders |
| * |
| * Revision 3.2 1998/11/19 02:53:48 brianp |
| * changed texture image and background color |
| * |
| * Revision 3.1 1998/11/05 04:34:04 brianp |
| * moved image files to ../images/ directory |
| * |
| * Revision 3.0 1998/02/14 18:42:29 brianp |
| * initial rev |
| * |
| */ |
| |
| |
| #define USE_ZBUFFER |
| |
| |
| /* OK, without hardware support this is overkill. */ |
| #define USE_TEXTURE |
| |
| #include <math.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "GL/glut.h" |
| |
| #include "../util/readtex.c" /* a hack, I know */ |
| |
| |
| #define DEG2RAD (3.14159/180.0) |
| |
| |
| #define TABLE_TEXTURE "../images/tile.rgb" |
| |
| static int ImgWidth, ImgHeight; |
| static GLenum ImgFormat; |
| static GLubyte *Image = NULL; |
| |
| #define MAX_OBJECTS 2 |
| |
| static GLint table_list; |
| static GLint objects_list[MAX_OBJECTS]; |
| |
| |
| static GLfloat xrot, yrot; |
| static GLfloat spin; |
| |
| |
| |
| static void make_table( void ) |
| { |
| static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 }; |
| static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 }; |
| |
| table_list = glGenLists(1); |
| glNewList( table_list, GL_COMPILE ); |
| |
| /* load table's texture */ |
| glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat ); |
| /* glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/ |
| glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat ); |
| glMaterialfv( GL_FRONT, GL_AMBIENT, gray ); |
| |
| /* draw textured square for the table */ |
| glPushMatrix(); |
| glScalef( 4.0, 4.0, 4.0 ); |
| glBegin( GL_POLYGON ); |
| glNormal3f( 0.0, 1.0, 0.0 ); |
| glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 ); |
| glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 ); |
| glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 ); |
| glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 ); |
| glEnd(); |
| glPopMatrix(); |
| |
| glDisable( GL_TEXTURE_2D ); |
| |
| glEndList(); |
| } |
| |
| |
| static void make_objects( void ) |
| { |
| GLUquadricObj *q; |
| |
| static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 }; |
| static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 }; |
| static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 }; |
| |
| q = gluNewQuadric(); |
| gluQuadricDrawStyle( q, GLU_FILL ); |
| gluQuadricNormals( q, GLU_SMOOTH ); |
| |
| objects_list[0] = glGenLists(1); |
| glNewList( objects_list[0], GL_COMPILE ); |
| glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan ); |
| glMaterialfv( GL_FRONT, GL_EMISSION, black ); |
| gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 ); |
| glEndList(); |
| |
| objects_list[1] = glGenLists(1); |
| glNewList( objects_list[1], GL_COMPILE ); |
| glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green ); |
| glMaterialfv( GL_FRONT, GL_EMISSION, black ); |
| gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 ); |
| glEndList(); |
| } |
| |
| |
| static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 }; |
| |
| static void init( void ) |
| { |
| make_table(); |
| make_objects(); |
| |
| /* Setup texture */ |
| #ifdef USE_TEXTURE |
| |
| Image = LoadRGBImage( TABLE_TEXTURE, &ImgWidth, &ImgHeight, &ImgFormat ); |
| if (!Image) { |
| printf("Couldn't read %s\n", TABLE_TEXTURE); |
| exit(0); |
| } |
| |
| gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ImgWidth, ImgHeight, |
| ImgFormat, GL_UNSIGNED_BYTE, Image); |
| |
| glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); |
| glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); |
| glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); |
| glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); |
| #endif |
| |
| |
| xrot = 30.0; |
| yrot = 50.0; |
| spin = 0.0; |
| |
| #ifndef USE_ZBUFFER |
| glEnable( GL_CULL_FACE ); |
| #endif |
| |
| glShadeModel( GL_FLAT ); |
| |
| glEnable( GL_LIGHT0 ); |
| glEnable( GL_LIGHTING ); |
| |
| glClearColor( 0.5, 0.5, 0.9, 1.0 ); |
| |
| glEnable( GL_NORMALIZE ); |
| } |
| |
| |
| |
| static void reshape(int w, int h) |
| { |
| GLfloat aspect = (float) w / (float) h; |
| |
| glViewport(0, 0, w, h); |
| glMatrixMode(GL_PROJECTION); |
| glLoadIdentity(); |
| glFrustum( -aspect, aspect, -1.0, 1.0, 4.0, 300.0 ); |
| glMatrixMode(GL_MODELVIEW); |
| glLoadIdentity(); |
| } |
| |
| |
| |
| static void draw_objects( GLfloat eyex, GLfloat eyey, GLfloat eyez ) |
| { |
| (void) eyex; |
| (void) eyey; |
| (void) eyez; |
| #ifndef USE_ZBUFFER |
| if (eyex<0.5) |
| { |
| #endif |
| glPushMatrix(); |
| glTranslatef( 1.0, 1.5, 0.0 ); |
| glRotatef( spin, 1.0, 0.5, 0.0 ); |
| glRotatef( 0.5*spin, 0.0, 0.5, 1.0 ); |
| glCallList( objects_list[0] ); |
| glPopMatrix(); |
| |
| glPushMatrix(); |
| glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 ); |
| glRotatef( 0.5*spin, 0.0, 0.5, 1.0 ); |
| glRotatef( spin, 1.0, 0.5, 0.0 ); |
| glScalef( 0.5, 0.5, 0.5 ); |
| glCallList( objects_list[1] ); |
| glPopMatrix(); |
| #ifndef USE_ZBUFFER |
| } |
| else |
| { |
| glPushMatrix(); |
| glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 ); |
| glRotatef( 0.5*spin, 0.0, 0.5, 1.0 ); |
| glRotatef( spin, 1.0, 0.5, 0.0 ); |
| glScalef( 0.5, 0.5, 0.5 ); |
| glCallList( objects_list[1] ); |
| glPopMatrix(); |
| |
| glPushMatrix(); |
| glTranslatef( 1.0, 1.5, 0.0 ); |
| glRotatef( spin, 1.0, 0.5, 0.0 ); |
| glRotatef( 0.5*spin, 0.0, 0.5, 1.0 ); |
| glCallList( objects_list[0] ); |
| glPopMatrix(); |
| } |
| #endif |
| } |
| |
| |
| |
| static void draw_table( void ) |
| { |
| glCallList( table_list ); |
| } |
| |
| |
| |
| static void draw_scene( void ) |
| { |
| GLfloat dist = 20.0; |
| GLfloat eyex, eyey, eyez; |
| |
| glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
| |
| |
| eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD); |
| eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD); |
| eyey = dist * sin(xrot*DEG2RAD); |
| |
| /* view from top */ |
| glPushMatrix(); |
| gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 ); |
| |
| glLightfv( GL_LIGHT0, GL_POSITION, light_pos ); |
| |
| /* draw table into stencil planes */ |
| glEnable( GL_STENCIL_TEST ); |
| #ifdef USE_ZBUFFER |
| glDisable( GL_DEPTH_TEST ); |
| #endif |
| glStencilFunc( GL_ALWAYS, 1, 0xffffffff ); |
| glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE ); |
| glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); |
| draw_table(); |
| glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); |
| |
| #ifdef USE_ZBUFFER |
| glEnable( GL_DEPTH_TEST ); |
| #endif |
| |
| |
| /* render view from below (reflected viewport) */ |
| /* only draw where stencil==1 */ |
| if (eyey>0.0) { |
| glPushMatrix(); |
| |
| glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */ |
| glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); |
| glScalef( 1.0, -1.0, 1.0 ); |
| |
| /* Reposition light in reflected space. */ |
| glLightfv(GL_LIGHT0, GL_POSITION, light_pos); |
| |
| draw_objects(eyex, eyey, eyez); |
| glPopMatrix(); |
| |
| /* Restore light's original unreflected position. */ |
| glLightfv(GL_LIGHT0, GL_POSITION, light_pos); |
| } |
| |
| glDisable( GL_STENCIL_TEST ); |
| |
| glEnable( GL_BLEND ); |
| glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); |
| |
| #ifdef USE_TEXTURE |
| glEnable( GL_TEXTURE_2D ); |
| #endif |
| draw_table(); |
| glDisable( GL_TEXTURE_2D ); |
| glDisable( GL_BLEND ); |
| |
| /* view from top */ |
| glPushMatrix(); |
| |
| draw_objects(eyex, eyey, eyez); |
| |
| glPopMatrix(); |
| |
| glPopMatrix(); |
| |
| glutSwapBuffers(); |
| } |
| |
| |
| |
| #if 0 |
| void draw_scene(void) |
| { |
| GLfloat dist = 20.0; |
| GLfloat eyex, eyey, eyez; |
| |
| glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
| |
| |
| eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD); |
| eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD); |
| eyey = dist * sin(xrot*DEG2RAD); |
| |
| /* view from top */ |
| glPushMatrix(); |
| gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 ); |
| |
| draw_table(); |
| |
| glPopMatrix(); |
| |
| glutSwapBuffers(); |
| } |
| #endif |
| |
| |
| static void Key( unsigned char key, int x, int y ) |
| { |
| (void) x; |
| (void) y; |
| if (key==27) |
| exit(0); |
| } |
| |
| |
| static void SpecialKey( int key, int x, int y ) |
| { |
| (void) x; |
| (void) y; |
| switch (key) { |
| case GLUT_KEY_UP: |
| xrot += 3.0; |
| #ifndef USE_ZBUFFER |
| if ( xrot > 180 ) xrot = 180; |
| #endif |
| break; |
| case GLUT_KEY_DOWN: |
| xrot -= 3.0; |
| #ifndef USE_ZBUFFER |
| if ( xrot < 0 ) xrot = 0; |
| #endif |
| break; |
| case GLUT_KEY_LEFT: |
| yrot += 3.0; |
| break; |
| case GLUT_KEY_RIGHT: |
| yrot -= 3.0; |
| break; |
| } |
| glutPostRedisplay(); |
| } |
| |
| |
| |
| static void idle( void ) |
| { |
| spin += 2.0; |
| yrot += 3.0; |
| glutPostRedisplay(); |
| } |
| |
| |
| |
| int main( int argc, char *argv[] ) |
| { |
| glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB |
| #ifdef USE_ZBUFFER |
| | GLUT_DEPTH |
| #endif |
| | GLUT_STENCIL); |
| glutInitWindowPosition( 0, 0 ); |
| glutInitWindowSize(400, 300 ); |
| glutCreateWindow(argv[0]); |
| glutReshapeFunc(reshape); |
| glutDisplayFunc(draw_scene); |
| glutKeyboardFunc(Key); |
| glutSpecialFunc(SpecialKey); |
| glutIdleFunc(idle); |
| |
| init(); |
| |
| glutMainLoop(); |
| return 0; |
| } |