#include #include #include #include #include GLboolean doubleBuffer = GL_TRUE, iconic = GL_FALSE, keepAspect = GL_FALSE; int moving, startx, starty; int useStencil = 1, useClippingPlane = 1; GLdouble bodyWidth = 3.0; float jump = 0.0; GLuint floor_texture; // The coordinates (A,B,C,D) for the plane with equation Ax + By + Cz + D = 0 GLdouble mirror_plane[4] = { 0, 1, 0, 0 }; void mouse(int button, int state, int x, int y); void motion(int x, int y); void controlLights(int value); void idle(void); void visible(int vis); GLuint loadTheTexture( void ); void makeDisplayLists(void); void drawBouncingTeapot(void); void drawFloor(void); void InitializeViewingAndLighting( void ); void SetupEyeViewBasedOnUserInput( void ); void SetLightPostionInCurrentCoordinateFrame( void ); void DrawMirrorIntoStencilBuffer( void ); void SetStencilToRenderOnlyWhenEqualToOne( void ); void MultiplyReflectionMatrixOntoStack( void ); void DrawMirrorBlendedWithReflectedScene( void ); void DrawReflectedScene( void ) { glPushMatrix(); /* figure out new viewing matrix */ MultiplyReflectionMatrixOntoStack(); /* if objects (instead of the viewer) are being reflected, you need to move */ /* the light to compensate */ SetLightPostionInCurrentCoordinateFrame(); /* Deal with flipped facings & scaled normals */ glEnable(GL_NORMALIZE); glCullFace( GL_FRONT ); /* make sure to clip to the floor */ glClipPlane( GL_CLIP_PLANE0, mirror_plane ); if (useClippingPlane) glEnable( GL_CLIP_PLANE0 ); /* draw the reflected scene. */ drawBouncingTeapot(); /* Reset the GL state. */ glDisable( GL_CLIP_PLANE0 ); glDisable(GL_NORMALIZE); glCullFace( GL_BACK ); glPopMatrix(); } void redraw(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glPushMatrix(); /* Do standard per-frame OpenGL setup (for view and lights) */ SetupEyeViewBasedOnUserInput(); SetLightPostionInCurrentCoordinateFrame(); // simply calls glLightfv() with a position /* draw the mirror into the stencil buffer */ DrawMirrorIntoStencilBuffer(); SetStencilToRenderOnlyWhenEqualToOne(); // Note: this enables GL_STENCIL_TEST /* Draw the scene reflected around the mirror */ DrawReflectedScene(); /* Restore light positions to their locations in the non-reflected scene. */ /* Note: Only necessary if lights were moved in DrawReflectedScene() */ SetLightPostionInCurrentCoordinateFrame(); /* If you want the mirror to have color (only reflect part of the light) */ /* then you need to draw it to partially occlude stuff (i.e., with */ /* alpha-blending enabled) */ DrawMirrorBlendedWithReflectedScene(); /* time to draw the actual scene, so disable the stencil test */ glDisable(GL_STENCIL_TEST); /* Draw "actual" scene, not its reflection. */ drawBouncingTeapot(); glPopMatrix(); glutSwapBuffers(); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); glutInitWindowSize( 512, 512 ); glutCreateWindow("Basic Planar Reflection Demo"); glutDisplayFunc(redraw); glutMouseFunc(mouse); glutMotionFunc(motion); glutVisibilityFunc(visible); glutCreateMenu(controlLights); glutAddMenuEntry("Toggle right light", 1); glutAddMenuEntry("Toggle left light", 2); glutAddMenuEntry("Toggle artifact elimination", 3); glutAddMenuEntry("Toggle mirror shape", 4 ); glutAttachMenu(GLUT_RIGHT_BUTTON); makeDisplayLists(); floor_texture = loadTheTexture(); InitializeViewingAndLighting(); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glutMainLoop(); return 0; }