132001f49Smrg/* 232001f49Smrg * Demo of a reflective, texture-mapped surface with OpenGL. 332001f49Smrg * Brian Paul August 14, 1995 This file is in the public domain. 432001f49Smrg * 532001f49Smrg * Hardware texture mapping is highly recommended! 632001f49Smrg * 732001f49Smrg * The basic steps are: 832001f49Smrg * 1. Render the reflective object (a polygon) from the normal viewpoint, 932001f49Smrg * setting the stencil planes = 1. 1032001f49Smrg * 2. Render the scene from a special viewpoint: the viewpoint which 1132001f49Smrg * is on the opposite side of the reflective plane. Only draw where 1232001f49Smrg * stencil = 1. This draws the objects in the reflective surface. 1332001f49Smrg * 3. Render the scene from the original viewpoint. This draws the 1432001f49Smrg * objects in the normal fashion. Use blending when drawing 1532001f49Smrg * the reflective, textured surface. 1632001f49Smrg * 1732001f49Smrg * This is a very crude demo. It could be much better. 1832001f49Smrg */ 1932001f49Smrg 2032001f49Smrg/* 2132001f49Smrg * Authors: 2232001f49Smrg * Brian Paul 2332001f49Smrg * Dirk Reiners (reiners@igd.fhg.de) made some modifications to this code. 2432001f49Smrg * Mark Kilgard (April 1997) 2532001f49Smrg * Brian Paul (April 2000 - added keyboard d/s options) 2632001f49Smrg * Brian Paul (August 2005 - added multi window feature) 2732001f49Smrg */ 2832001f49Smrg 2932001f49Smrg 3032001f49Smrg#include <assert.h> 3132001f49Smrg#include <math.h> 3232001f49Smrg#include <stdio.h> 3332001f49Smrg#include <stdlib.h> 3432001f49Smrg#include "glut_wrap.h" 3532001f49Smrg#include "showbuffer.h" 3632001f49Smrg#include "readtex.h" 3732001f49Smrg 3832001f49Smrg 3932001f49Smrg#define DEG2RAD (3.14159/180.0) 4032001f49Smrg#define TABLE_TEXTURE DEMOS_DATA_DIR "tile.rgb" 4132001f49Smrg#define MAX_OBJECTS 2 4232001f49Smrg#define INIT_WIDTH 400 4332001f49Smrg#define INIT_HEIGHT 300 4432001f49Smrg 4532001f49Smrg#ifdef _WIN32 4632001f49Smrg#undef CreateWindowA 4732001f49Smrg#endif 4832001f49Smrg 4932001f49Smrgstruct window { 5032001f49Smrg int id; /* returned by glutCreateWindow() */ 5132001f49Smrg int width, height; 5232001f49Smrg GLboolean anim; 5332001f49Smrg GLfloat xrot, yrot; 5432001f49Smrg GLfloat spin; 5532001f49Smrg GLenum showBuffer; 5632001f49Smrg GLenum drawBuffer; 5732001f49Smrg GLuint table_list; 5832001f49Smrg GLuint objects_list[MAX_OBJECTS]; 5932001f49Smrg double t0; 6032001f49Smrg struct window *next; 6132001f49Smrg}; 6232001f49Smrg 6332001f49Smrg 6432001f49Smrgstatic struct window *FirstWindow = NULL; 6532001f49Smrg 6632001f49Smrg 6732001f49Smrgstatic void 6832001f49SmrgCreateWindow(void); 6932001f49Smrg 7032001f49Smrg 7132001f49Smrgstatic struct window * 7232001f49SmrgCurrentWindow(void) 7332001f49Smrg{ 7432001f49Smrg int id = glutGetWindow(); 7532001f49Smrg struct window *w; 7632001f49Smrg for (w = FirstWindow; w; w = w->next) { 7732001f49Smrg if (w->id == id) 7832001f49Smrg return w; 7932001f49Smrg } 8032001f49Smrg return NULL; 8132001f49Smrg} 8232001f49Smrg 8332001f49Smrg 8432001f49Smrgstatic GLboolean 8532001f49SmrgAnyAnimating(void) 8632001f49Smrg{ 8732001f49Smrg struct window *w; 8832001f49Smrg for (w = FirstWindow; w; w = w->next) { 8932001f49Smrg if (w->anim) 9032001f49Smrg return 1; 9132001f49Smrg } 9232001f49Smrg return 0; 9332001f49Smrg} 9432001f49Smrg 9532001f49Smrg 9632001f49Smrgstatic void 9732001f49SmrgKillWindow(struct window *w) 9832001f49Smrg{ 9932001f49Smrg struct window *win, *prev = NULL; 10032001f49Smrg for (win = FirstWindow; win; win = win->next) { 10132001f49Smrg if (win == w) { 10232001f49Smrg if (prev) { 10332001f49Smrg prev->next = win->next; 10432001f49Smrg } 10532001f49Smrg else { 10632001f49Smrg FirstWindow = win->next; 10732001f49Smrg } 10832001f49Smrg glutDestroyWindow(win->id); 10932001f49Smrg win->next = NULL; 11032001f49Smrg free(win); 11132001f49Smrg return; 11232001f49Smrg } 11332001f49Smrg prev = win; 11432001f49Smrg } 11532001f49Smrg} 11632001f49Smrg 11732001f49Smrg 11832001f49Smrgstatic void 11932001f49SmrgKillAllWindows(void) 12032001f49Smrg{ 12132001f49Smrg while (FirstWindow) 12232001f49Smrg KillWindow(FirstWindow); 12332001f49Smrg} 12432001f49Smrg 12532001f49Smrg 12632001f49Smrgstatic GLuint 12732001f49SmrgMakeTable(void) 12832001f49Smrg{ 12932001f49Smrg static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 }; 13032001f49Smrg static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 }; 13132001f49Smrg GLuint table_list; 13232001f49Smrg 13332001f49Smrg table_list = glGenLists(1); 13432001f49Smrg glNewList( table_list, GL_COMPILE ); 13532001f49Smrg 13632001f49Smrg /* load table's texture */ 13732001f49Smrg glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat ); 13832001f49Smrg /*glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/ 13932001f49Smrg glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat ); 14032001f49Smrg glMaterialfv( GL_FRONT, GL_AMBIENT, gray ); 14132001f49Smrg 14232001f49Smrg /* draw textured square for the table */ 14332001f49Smrg glPushMatrix(); 14432001f49Smrg glScalef( 4.0, 4.0, 4.0 ); 14532001f49Smrg glBegin( GL_POLYGON ); 14632001f49Smrg glNormal3f( 0.0, 1.0, 0.0 ); 14732001f49Smrg glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 0.0, 1.0 ); 14832001f49Smrg glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 ); 14932001f49Smrg glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, -1.0 ); 15032001f49Smrg glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 0.0, -1.0 ); 15132001f49Smrg glEnd(); 15232001f49Smrg glPopMatrix(); 15332001f49Smrg 15432001f49Smrg glDisable( GL_TEXTURE_2D ); 15532001f49Smrg 15632001f49Smrg glEndList(); 15732001f49Smrg return table_list; 15832001f49Smrg} 15932001f49Smrg 16032001f49Smrg 16132001f49Smrgstatic void 16232001f49SmrgMakeObjects(GLuint *objects_list) 16332001f49Smrg{ 16432001f49Smrg GLUquadricObj *q; 16532001f49Smrg 16632001f49Smrg static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 }; 16732001f49Smrg static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 }; 16832001f49Smrg static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 }; 16932001f49Smrg 17032001f49Smrg q = gluNewQuadric(); 17132001f49Smrg gluQuadricDrawStyle( q, GLU_FILL ); 17232001f49Smrg gluQuadricNormals( q, GLU_SMOOTH ); 17332001f49Smrg 17432001f49Smrg objects_list[0] = glGenLists(1); 17532001f49Smrg glNewList( objects_list[0], GL_COMPILE ); 17632001f49Smrg glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan ); 17732001f49Smrg glMaterialfv( GL_FRONT, GL_EMISSION, black ); 17832001f49Smrg gluCylinder( q, 0.5, 0.5, 1.0, 15, 1 ); 17932001f49Smrg glEndList(); 18032001f49Smrg 18132001f49Smrg objects_list[1] = glGenLists(1); 18232001f49Smrg glNewList( objects_list[1], GL_COMPILE ); 18332001f49Smrg glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green ); 18432001f49Smrg glMaterialfv( GL_FRONT, GL_EMISSION, black ); 18532001f49Smrg gluCylinder( q, 1.5, 0.0, 2.5, 15, 1 ); 18632001f49Smrg glEndList(); 18732001f49Smrg 18832001f49Smrg gluDeleteQuadric(q); 18932001f49Smrg} 19032001f49Smrg 19132001f49Smrg 19232001f49Smrgstatic void 19332001f49SmrgInitWindow(struct window *w) 19432001f49Smrg{ 19532001f49Smrg GLint imgWidth, imgHeight; 19632001f49Smrg GLenum imgFormat; 19732001f49Smrg GLubyte *image = NULL; 19832001f49Smrg 19932001f49Smrg w->table_list = MakeTable(); 20032001f49Smrg MakeObjects(w->objects_list); 20132001f49Smrg 20232001f49Smrg image = LoadRGBImage( TABLE_TEXTURE, &imgWidth, &imgHeight, &imgFormat ); 20332001f49Smrg if (!image) { 20432001f49Smrg printf("Couldn't read %s\n", TABLE_TEXTURE); 20532001f49Smrg exit(0); 20632001f49Smrg } 20732001f49Smrg 20832001f49Smrg gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight, 20932001f49Smrg imgFormat, GL_UNSIGNED_BYTE, image); 21032001f49Smrg free(image); 21132001f49Smrg 21232001f49Smrg glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); 21332001f49Smrg glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); 21432001f49Smrg glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); 21532001f49Smrg glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); 21632001f49Smrg 21732001f49Smrg glShadeModel( GL_FLAT ); 21832001f49Smrg 21932001f49Smrg glEnable( GL_LIGHT0 ); 22032001f49Smrg glEnable( GL_LIGHTING ); 22132001f49Smrg 22232001f49Smrg glClearColor( 0.5, 0.5, 0.9, 0.0 ); 22332001f49Smrg 22432001f49Smrg glEnable( GL_NORMALIZE ); 22532001f49Smrg} 22632001f49Smrg 22732001f49Smrg 22832001f49Smrgstatic void 22932001f49SmrgReshape(int width, int height) 23032001f49Smrg{ 23132001f49Smrg struct window *w = CurrentWindow(); 23232001f49Smrg GLfloat yAspect = 2.5; 23332001f49Smrg GLfloat xAspect = yAspect * (float) width / (float) height; 23432001f49Smrg w->width = width; 23532001f49Smrg w->height = height; 23632001f49Smrg glViewport(0, 0, width, height); 23732001f49Smrg glMatrixMode(GL_PROJECTION); 23832001f49Smrg glLoadIdentity(); 23932001f49Smrg glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 ); 24032001f49Smrg glMatrixMode(GL_MODELVIEW); 24132001f49Smrg glLoadIdentity(); 24232001f49Smrg} 24332001f49Smrg 24432001f49Smrg 24532001f49Smrgstatic void 24632001f49SmrgDrawObjects(struct window *w, GLfloat eyex, GLfloat eyey, GLfloat eyez) 24732001f49Smrg{ 24832001f49Smrg (void) eyex; 24932001f49Smrg (void) eyey; 25032001f49Smrg (void) eyez; 25132001f49Smrg#ifndef USE_ZBUFFER 25232001f49Smrg if (eyex<0.5) { 25332001f49Smrg#endif 25432001f49Smrg glPushMatrix(); 25532001f49Smrg glTranslatef( 1.0, 1.5, 0.0 ); 25632001f49Smrg glRotatef( w->spin, 1.0, 0.5, 0.0 ); 25732001f49Smrg glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 ); 25832001f49Smrg glCallList( w->objects_list[0] ); 25932001f49Smrg glPopMatrix(); 26032001f49Smrg 26132001f49Smrg glPushMatrix(); 26232001f49Smrg glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 ); 26332001f49Smrg glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 ); 26432001f49Smrg glRotatef( w->spin, 1.0, 0.5, 0.0 ); 26532001f49Smrg glScalef( 0.5, 0.5, 0.5 ); 26632001f49Smrg glCallList( w->objects_list[1] ); 26732001f49Smrg glPopMatrix(); 26832001f49Smrg#ifndef USE_ZBUFFER 26932001f49Smrg } 27032001f49Smrg else { 27132001f49Smrg glPushMatrix(); 27232001f49Smrg glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*w->spin) ), 0.0 ); 27332001f49Smrg glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 ); 27432001f49Smrg glRotatef( w->spin, 1.0, 0.5, 0.0 ); 27532001f49Smrg glScalef( 0.5, 0.5, 0.5 ); 27632001f49Smrg glCallList( w->objects_list[1] ); 27732001f49Smrg glPopMatrix(); 27832001f49Smrg 27932001f49Smrg glPushMatrix(); 28032001f49Smrg glTranslatef( 1.0, 1.5, 0.0 ); 28132001f49Smrg glRotatef( w->spin, 1.0, 0.5, 0.0 ); 28232001f49Smrg glRotatef( 0.5*w->spin, 0.0, 0.5, 1.0 ); 28332001f49Smrg glCallList( w->objects_list[0] ); 28432001f49Smrg glPopMatrix(); 28532001f49Smrg } 28632001f49Smrg#endif 28732001f49Smrg} 28832001f49Smrg 28932001f49Smrg 29032001f49Smrgstatic void 29132001f49SmrgDrawTable(struct window *w) 29232001f49Smrg{ 29332001f49Smrg glCallList(w->table_list); 29432001f49Smrg} 29532001f49Smrg 29632001f49Smrg 29732001f49Smrgstatic void 29832001f49SmrgDrawWindow(void) 29932001f49Smrg{ 30032001f49Smrg struct window *w = CurrentWindow(); 30132001f49Smrg static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 }; 30232001f49Smrg GLfloat dist = 20.0; 30332001f49Smrg GLfloat eyex, eyey, eyez; 30432001f49Smrg 30532001f49Smrg if (w->drawBuffer == GL_NONE) { 30632001f49Smrg glDrawBuffer(GL_BACK); 30732001f49Smrg glReadBuffer(GL_BACK); 30832001f49Smrg } 30932001f49Smrg else { 31032001f49Smrg glDrawBuffer(w->drawBuffer); 31132001f49Smrg glReadBuffer(w->drawBuffer); 31232001f49Smrg } 31332001f49Smrg 31432001f49Smrg glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 31532001f49Smrg 31632001f49Smrg if (w->drawBuffer == GL_NONE) { 31732001f49Smrg glDrawBuffer(GL_NONE); 31832001f49Smrg } 31932001f49Smrg 32032001f49Smrg eyex = dist * cos(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD); 32132001f49Smrg eyez = dist * sin(w->yrot * DEG2RAD) * cos(w->xrot * DEG2RAD); 32232001f49Smrg eyey = dist * sin(w->xrot * DEG2RAD); 32332001f49Smrg 32432001f49Smrg /* view from top */ 32532001f49Smrg glPushMatrix(); 32632001f49Smrg gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 ); 32732001f49Smrg 32832001f49Smrg glLightfv( GL_LIGHT0, GL_POSITION, light_pos ); 32932001f49Smrg 33032001f49Smrg /* draw table into stencil planes */ 33132001f49Smrg glDisable( GL_DEPTH_TEST ); 33232001f49Smrg glEnable( GL_STENCIL_TEST ); 33332001f49Smrg glStencilFunc( GL_ALWAYS, 1, 0xffffffff ); 33432001f49Smrg glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE ); 33532001f49Smrg glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); 33632001f49Smrg DrawTable(w); 33732001f49Smrg glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); 33832001f49Smrg 33932001f49Smrg glEnable( GL_DEPTH_TEST ); 34032001f49Smrg 34132001f49Smrg /* render view from below (reflected viewport) */ 34232001f49Smrg /* only draw where stencil==1 */ 34332001f49Smrg if (eyey>0.0) { 34432001f49Smrg glPushMatrix(); 34532001f49Smrg 34632001f49Smrg glStencilFunc( GL_EQUAL, 1, 0xffffffff ); /* draw if ==1 */ 34732001f49Smrg glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); 34832001f49Smrg glScalef( 1.0, -1.0, 1.0 ); 34932001f49Smrg 35032001f49Smrg /* Reposition light in reflected space. */ 35132001f49Smrg glLightfv(GL_LIGHT0, GL_POSITION, light_pos); 35232001f49Smrg 35332001f49Smrg DrawObjects(w, eyex, eyey, eyez); 35432001f49Smrg glPopMatrix(); 35532001f49Smrg 35632001f49Smrg /* Restore light's original unreflected position. */ 35732001f49Smrg glLightfv(GL_LIGHT0, GL_POSITION, light_pos); 35832001f49Smrg } 35932001f49Smrg 36032001f49Smrg glDisable( GL_STENCIL_TEST ); 36132001f49Smrg 36232001f49Smrg glEnable( GL_BLEND ); 36332001f49Smrg glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 36432001f49Smrg 36532001f49Smrg glEnable( GL_TEXTURE_2D ); 36632001f49Smrg DrawTable(w); 36732001f49Smrg glDisable( GL_TEXTURE_2D ); 36832001f49Smrg glDisable( GL_BLEND ); 36932001f49Smrg 37032001f49Smrg /* view from top */ 37132001f49Smrg glPushMatrix(); 37232001f49Smrg 37332001f49Smrg DrawObjects(w, eyex, eyey, eyez); 37432001f49Smrg 37532001f49Smrg glPopMatrix(); 37632001f49Smrg 37732001f49Smrg glPopMatrix(); 37832001f49Smrg 37932001f49Smrg if (w->showBuffer == GL_DEPTH) { 38032001f49Smrg ShowDepthBuffer(w->width, w->height, 1.0, 0.0); 38132001f49Smrg } 38232001f49Smrg else if (w->showBuffer == GL_STENCIL) { 38332001f49Smrg ShowStencilBuffer(w->width, w->height, 255.0, 0.0); 38432001f49Smrg } 38532001f49Smrg else if (w->showBuffer == GL_ALPHA) { 38632001f49Smrg ShowAlphaBuffer(w->width, w->height); 38732001f49Smrg } 38832001f49Smrg 38932001f49Smrg if (w->drawBuffer == GL_FRONT) 39032001f49Smrg glFinish(); 39132001f49Smrg else 39232001f49Smrg glutSwapBuffers(); 39332001f49Smrg 39432001f49Smrg /* calc/show frame rate */ 39532001f49Smrg { 39632001f49Smrg static GLint t0 = 0; 39732001f49Smrg static GLint frames = 0; 39832001f49Smrg GLint t = glutGet(GLUT_ELAPSED_TIME); 39932001f49Smrg frames++; 40032001f49Smrg if (t - t0 >= 5000) { 40132001f49Smrg GLfloat seconds = (t - t0) / 1000.0; 40232001f49Smrg GLfloat fps = frames / seconds; 40332001f49Smrg printf("%d frames in %g seconds = %g FPS\n", frames, seconds, fps); 40432001f49Smrg fflush(stdout); 40532001f49Smrg t0 = t; 40632001f49Smrg frames = 0; 40732001f49Smrg } 40832001f49Smrg } 40932001f49Smrg} 41032001f49Smrg 41132001f49Smrg 41232001f49Smrgstatic void 41332001f49SmrgIdle(void) 41432001f49Smrg{ 41532001f49Smrg double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; 41632001f49Smrg struct window *w; 41732001f49Smrg for (w = FirstWindow; w; w = w->next) { 41832001f49Smrg if (w->anim) { 41932001f49Smrg double dt; 42032001f49Smrg if (w->t0 < 0.0) 42132001f49Smrg w->t0 = t; 42232001f49Smrg dt = t - w->t0; 42332001f49Smrg w->t0 = t; 42432001f49Smrg w->spin += 60.0 * dt; 42532001f49Smrg w->yrot += 90.0 * dt; 42632001f49Smrg assert(w->id); 42732001f49Smrg glutSetWindow(w->id); 42832001f49Smrg glutPostRedisplay(); 42932001f49Smrg } 43032001f49Smrg } 43132001f49Smrg} 43232001f49Smrg 43332001f49Smrg 43432001f49Smrgstatic void 43532001f49SmrgUpdateIdleFunc(void) 43632001f49Smrg{ 43732001f49Smrg if (AnyAnimating()) 43832001f49Smrg glutIdleFunc(Idle); 43932001f49Smrg else 44032001f49Smrg glutIdleFunc(NULL); 44132001f49Smrg} 44232001f49Smrg 44332001f49Smrgstatic void 44432001f49SmrgKey(unsigned char key, int x, int y) 44532001f49Smrg{ 44632001f49Smrg struct window *w = CurrentWindow(); 44732001f49Smrg (void) x; 44832001f49Smrg (void) y; 44932001f49Smrg 45032001f49Smrg switch (key) { 45132001f49Smrg case 'd': 45232001f49Smrg w->showBuffer = GL_DEPTH; 45332001f49Smrg glutPostRedisplay(); 45432001f49Smrg break; 45532001f49Smrg case 's': 45632001f49Smrg w->showBuffer = GL_STENCIL; 45732001f49Smrg glutPostRedisplay(); 45832001f49Smrg break; 45932001f49Smrg case 'a': 46032001f49Smrg w->showBuffer = GL_ALPHA; 46132001f49Smrg glutPostRedisplay(); 46232001f49Smrg break; 46332001f49Smrg case 'c': 46432001f49Smrg w->showBuffer = GL_NONE; 46532001f49Smrg glutPostRedisplay(); 46632001f49Smrg break; 46732001f49Smrg case 'f': 46832001f49Smrg if (w->drawBuffer == GL_FRONT) 46932001f49Smrg w->drawBuffer = GL_BACK; 47032001f49Smrg else 47132001f49Smrg w->drawBuffer = GL_FRONT; 47232001f49Smrg glutPostRedisplay(); 47332001f49Smrg break; 47432001f49Smrg case '0': 47532001f49Smrg w->drawBuffer = GL_NONE; 47632001f49Smrg glutPostRedisplay(); 47732001f49Smrg break; 47832001f49Smrg case ' ': 47932001f49Smrg w->anim = !w->anim; 48032001f49Smrg w->t0 = -1; 48132001f49Smrg UpdateIdleFunc(); 48232001f49Smrg glutPostRedisplay(); 48332001f49Smrg break; 48432001f49Smrg case 'n': 48532001f49Smrg CreateWindow(); 48632001f49Smrg UpdateIdleFunc(); 48732001f49Smrg break; 48832001f49Smrg case 'k': 48932001f49Smrg KillWindow(w); 49032001f49Smrg if (FirstWindow == NULL) 49132001f49Smrg exit(0); 49232001f49Smrg break; 49332001f49Smrg case 27: 49432001f49Smrg KillAllWindows(); 49532001f49Smrg exit(0); 49632001f49Smrg break; 49732001f49Smrg default: 49832001f49Smrg ; 49932001f49Smrg } 50032001f49Smrg} 50132001f49Smrg 50232001f49Smrg 50332001f49Smrgstatic void 50432001f49SmrgSpecialKey(int key, int x, int y) 50532001f49Smrg{ 50632001f49Smrg struct window *w = CurrentWindow(); 50732001f49Smrg (void) x; 50832001f49Smrg (void) y; 50932001f49Smrg switch (key) { 51032001f49Smrg case GLUT_KEY_UP: 51132001f49Smrg w->xrot += 3.0; 51232001f49Smrg if (w->xrot > 85) 51332001f49Smrg w->xrot = 85; 51432001f49Smrg break; 51532001f49Smrg case GLUT_KEY_DOWN: 51632001f49Smrg w->xrot -= 3.0; 51732001f49Smrg if (w->xrot < 5) 51832001f49Smrg w->xrot = 5; 51932001f49Smrg break; 52032001f49Smrg case GLUT_KEY_LEFT: 52132001f49Smrg w->yrot += 3.0; 52232001f49Smrg break; 52332001f49Smrg case GLUT_KEY_RIGHT: 52432001f49Smrg w->yrot -= 3.0; 52532001f49Smrg break; 52632001f49Smrg } 52732001f49Smrg glutPostRedisplay(); 52832001f49Smrg} 52932001f49Smrg 53032001f49Smrg 53132001f49Smrgstatic void 53232001f49SmrgCreateWindow(void) 53332001f49Smrg{ 53432001f49Smrg char title[1000]; 53532001f49Smrg struct window *w = (struct window *) calloc(1, sizeof(struct window)); 53632001f49Smrg 53732001f49Smrg glutInitWindowSize(INIT_WIDTH, INIT_HEIGHT); 53832001f49Smrg w->id = glutCreateWindow("foo"); 53932001f49Smrg sprintf(title, "reflect window %d", w->id); 54032001f49Smrg glutSetWindowTitle(title); 54132001f49Smrg assert(w->id); 54232001f49Smrg w->width = INIT_WIDTH; 54332001f49Smrg w->height = INIT_HEIGHT; 54432001f49Smrg w->anim = GL_TRUE; 54532001f49Smrg w->xrot = 30.0; 54632001f49Smrg w->yrot = 50.0; 54732001f49Smrg w->spin = 0.0; 54832001f49Smrg w->showBuffer = GL_NONE; 54932001f49Smrg w->drawBuffer = GL_BACK; 55032001f49Smrg 55132001f49Smrg InitWindow(w); 55232001f49Smrg 55332001f49Smrg glutReshapeFunc(Reshape); 55432001f49Smrg glutDisplayFunc(DrawWindow); 55532001f49Smrg glutKeyboardFunc(Key); 55632001f49Smrg glutSpecialFunc(SpecialKey); 55732001f49Smrg 55832001f49Smrg /* insert at head of list */ 55932001f49Smrg w->next = FirstWindow; 56032001f49Smrg FirstWindow = w; 56132001f49Smrg} 56232001f49Smrg 56332001f49Smrg 56432001f49Smrgstatic void 56532001f49SmrgUsage(void) 56632001f49Smrg{ 56732001f49Smrg printf("Keys:\n"); 56832001f49Smrg printf(" a - show alpha buffer\n"); 56932001f49Smrg printf(" d - show depth buffer\n"); 57032001f49Smrg printf(" s - show stencil buffer\n"); 57132001f49Smrg printf(" c - show color buffer\n"); 57232001f49Smrg printf(" f - toggle rendering to front/back color buffer\n"); 57332001f49Smrg printf(" n - create new window\n"); 57432001f49Smrg printf(" k - kill window\n"); 57532001f49Smrg printf(" SPACE - toggle animation\n"); 57632001f49Smrg printf(" ARROWS - rotate scene\n"); 57732001f49Smrg} 57832001f49Smrg 57932001f49Smrg 58032001f49Smrgint 58132001f49Smrgmain(int argc, char *argv[]) 58232001f49Smrg{ 58332001f49Smrg glutInit(&argc, argv); 58432001f49Smrg glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | 58532001f49Smrg GLUT_STENCIL | GLUT_ALPHA); 58632001f49Smrg CreateWindow(); 58732001f49Smrg glutIdleFunc(Idle); 58832001f49Smrg Usage(); 58932001f49Smrg glutMainLoop(); 59032001f49Smrg return 0; 59132001f49Smrg} 592