Main Page | Class List | File List | Class Members | File Members

mirror.cpp

Go to the documentation of this file.
00001  
00002 #include <GL/glut.h>
00003 #include <GL/glu.h>
00004 #include <stdlib.h>
00005 #include <math.h>
00006 
00007 #ifdef WIN32
00008 #define near zNear
00009 #define far zFar
00010 #endif
00011 
00012 #define PI_ 3.14159265358979323846
00013 
00014 
00015 // The arbitrary mirror is made using Stencil buffer.
00016 //  Approach is based on those proposed in "Improving Shadows
00017 //  and Reflections via the Stencil buffer".
00018 // 
00019 
00020 #include <stdio.h>
00021 #include "math.h"
00022 
00023 typedef struct Point3Struct {
00024         double x, y, z;
00025 } Point3;
00026 
00027 
00028 bool normalize ( double[3]);
00029 void add ( double[3], double[3]);
00030 
00031 void renderMirrorSurfacePolygons(void);
00032 void draw_scene(void);
00033 void renderMirrorSurfacePolygons(void);
00034 void mirrorMatrix(GLfloat [4][4], 
00035     GLfloat [3],
00036     GLfloat [3]);
00037 void computeReflectionMatrixForMirror(GLfloat [4][4]);
00038 void computeMirrorClipPlane(GLdouble [4]);
00039 void drawBorder(void);
00040 
00041 
00042 //focus
00043 float z = 15.0;
00044 
00045 bool changed = false;
00046 
00047 bool FillPolygons = true;
00048 
00049   GLfloat colorWhite[4] = {1,1,1,1};
00050   GLfloat colorDarkGrey[4]    = { 0.2, 0.2, 0.2, 0.0 };
00051    
00052    GLfloat ambient[] = { 0.1, 0.1, 0.1, 1.0 };
00053    GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
00054    GLfloat no_specular[] = { .0, .0, .0, 1.0 };
00055 
00056 bool Specular = false;
00057 bool Lighting = true;
00058 
00059 GLfloat LightPos[4]  = {5.00, 5.0, 5.0, 1.0};
00060 GLfloat LightPos2[4] = {-10, -10, -10, 1};
00061 
00062 GLfloat mirror_vertices[4][3] = { {-2, -2, -7}, {-2, 2, -7}, {2, 2, -7}, {2, -2, -7} };
00063 GLfloat mirror_center[3] = {0, 0, -7};
00064 GLfloat mirror_normal[3];
00065 
00066 GLfloat border_vertices[4][3] = { {-2.5, -2.5, -7}, {-2.5, 2.5, -7}, {2.5, 2.5, -7}, {2.5, -2.5, -7} };
00067 
00068 bool RotateMirrorUp = false, RotateMirrorDown = false, RotateMirrorLeft = false, RotateMirrorRight = false;
00069 bool MoveMirrorForward = false, MoveMirrorBackward = false;
00070 
00071 //rotation variables
00072 float AngleX=0, AngleY=0;
00073 bool RotateUp = false, RotateDown = false, RotateLeft = false, RotateRight = false;
00074 
00075 float CameraX = 0, CameraY = 0, CameraZ = 5.0f;
00076 
00077 int LastTime = 0;
00078 int TimerDelay = 50;
00079 float FPS = 0;
00080 
00081 void computeMirrorClipPlane(GLdouble plane[4])
00082 {
00083 Point3 vertex[3];
00084 Point3Struct * vertex_ptr;
00085 Point3 normal;
00086 Point3Struct * normal_ptr;
00087 double A, B, C, D;
00088 
00089 vertex[0].x = mirror_vertices[0][0];
00090 vertex[0].y = mirror_vertices[0][1];
00091 vertex[0].z = mirror_vertices[0][2];
00092 
00093 vertex[1].x = mirror_vertices[1][0];
00094 vertex[1].y = mirror_vertices[1][1];
00095 vertex[1].z = mirror_vertices[1][2];
00096 
00097 vertex[2].x = mirror_vertices[2][0];
00098 vertex[2].y = mirror_vertices[2][1];
00099 vertex[2].z = mirror_vertices[2][2];
00100 
00101 
00102 
00103 //determining the coefficients in plane's equation
00104 A = ( (vertex[1].y - vertex[0].y)*(vertex[2].z - vertex[0].z) ) - ( (vertex[1].z - vertex[0].z)*(vertex[2].y - vertex[0].y) );
00105 B = ( (vertex[1].z - vertex[0].z)*(vertex[2].x - vertex[0].x) ) - ( (vertex[2].z - vertex[0].z)*(vertex[1].x - vertex[0].x) );
00106 C = ( (vertex[1].x - vertex[0].x)*(vertex[2].y - vertex[0].y) ) - ( (vertex[1].y - vertex[0].y)*(vertex[2].x - vertex[0].x) );
00107 D = - ( vertex[0].x*A + vertex[0].y*B + vertex[0].z*C );
00108 /*
00109 if (D < 0)
00110     {
00111     //normalizing
00112     D = -D;
00113     A = -A;
00114     B = -B;
00115     C = -C;
00116     }
00117 */      
00118 plane[0] = A;
00119 plane[1] = B;
00120 plane[2] = C;
00121 plane[3] = D;
00122 
00123 //now computing the normal for the mirror
00124         Point3 vertexa, vertexb, vertexc;
00125         double vector[3], vector2[3];
00126                 //load three points of triangle
00127     vertexa.x = mirror_vertices[0][0];
00128     vertexa.y = mirror_vertices[0][1];
00129     vertexa.z = mirror_vertices[0][2];
00130     vertexb.x = mirror_center[0];
00131     vertexb.y = mirror_center[1];
00132     vertexb.z = mirror_center[2];
00133     vertexc.x = mirror_vertices[1][0];
00134     vertexc.y = mirror_vertices[1][1];
00135         vertexc.z = mirror_vertices[1][2];    
00136         
00137         //first vector a-b
00138         vector[0] = vertexb.x - vertexa.x;
00139         vector[1] = vertexb.y - vertexa.y;
00140         vector[2] = vertexb.z - vertexa.z;
00141         
00142         //second vector b-c
00143         vector2[0] = vertexc.x - vertexb.x;
00144         vector2[1] = vertexc.y - vertexb.y;
00145         vector2[2] = vertexc.z - vertexb.z;
00146         
00147         //normal is a cross product between v1 and v2
00148     normal.x =  (vector[1]*vector2[2] - vector[2]*vector2[1]);
00149     normal.y =  (vector[2]*vector2[0] - vector[0]*vector2[2]);
00150     normal.z =  (vector[0]*vector2[1] - vector[1]*vector2[0]);
00151         
00152         //rewriting vector
00153     vector[0] = normal.x;
00154     vector[1] = normal.y;
00155     vector[2] = normal.z;
00156     
00157         //normalizing the normal
00158 if ( normalize ( vector ) )
00159     {
00160     printf(" normal is zero!\n");
00161     }
00162 mirror_normal[0] = vector[0];
00163 mirror_normal[1] = vector[1];
00164 mirror_normal[2] = vector[2];
00165 
00166 //compute the position of the second light source
00167 float k;
00168 
00169 k = (A*LightPos[0] + B*LightPos[1] + C*LightPos[2] + D) / ( -(A*A + B*B + C*C) );
00170 
00171 LightPos2[0] = LightPos[0] + 2*k*A;
00172 LightPos2[1] = LightPos[1] + 2*k*B;
00173 LightPos2[2] = LightPos[2] + 2*k*C;
00174 /*
00175 LightPos2[0] -= mirror_center[0];
00176 LightPos2[1] -= mirror_center[1];
00177 LightPos2[2] -= mirror_center[2];
00178 */
00179 
00180 /*
00181 printf(" lightsource 1: %f, %f, %f lightsource 2: %f, %f, %f \n", 
00182     LightPos[0], LightPos[1], LightPos[2],
00183     LightPos2[0], LightPos2[1], LightPos2[2]);
00184 */
00185 
00186  //printf(" normal: %f, %f, %f \n", mirror_normal[0], mirror_normal[1], mirror_normal[2] );
00187 }
00188 
00189 void add ( double v[3], double v2[3])
00190 {
00191 
00192 v[0] += v2[0];
00193 v[1] += v2[1];
00194 v[2] += v2[2];
00195 
00196 }
00197 
00198 bool normalize ( double v[3])
00199 {
00200 double d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00201 if (d != 0.0) 
00202     {
00203     v[0] /= d;
00204     v[1] /= d;
00205     v[2] /= d;
00206     return (false);
00207     }
00208 else
00209     printf(" zero normal?! hmm, strange... %f \n", d);
00210 
00211 return (true);
00212 //printf(" len of normal is %f \n", sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ) );
00213 }
00214 
00215 
00216 //helper function from Bastian
00217 void glutString( char *pstr )
00218 {
00219   while (*pstr!=char(0)) {
00220     glutBitmapCharacter( GLUT_BITMAP_8_BY_13, int( *pstr ));
00221     pstr++;
00222   }
00223 }
00224 
00225 GLuint teapotList;
00226 
00227 /* accFrustum()
00228  * The first 6 arguments are identical to the glFrustum() call.
00229  *  
00230  * pixdx and pixdy are anti-alias jitter in pixels. 
00231  * Set both equal to 0.0 for no anti-alias jitter.
00232  * eyedx and eyedy are depth-of field jitter in pixels. 
00233  * Set both equal to 0.0 for no depth of field effects.
00234  *
00235  * focus is distance from eye to plane in focus. 
00236  * focus must be greater than, but not equal to 0.0.
00237  *
00238  * Note that accFrustum() calls glTranslatef().  You will 
00239  * probably want to insure that your ModelView matrix has been 
00240  * initialized to identity before calling accFrustum().
00241  */
00242 void accFrustum(GLdouble left, GLdouble right, GLdouble bottom, 
00243    GLdouble top, GLdouble near, GLdouble far, GLdouble pixdx, 
00244    GLdouble pixdy, GLdouble eyedx, GLdouble eyedy, GLdouble focus)
00245 {
00246    GLdouble xwsize, ywsize; 
00247    GLdouble dx, dy;
00248    GLint viewport[4];
00249 
00250    glGetIntegerv (GL_VIEWPORT, viewport);
00251         
00252    xwsize = right - left;
00253    ywsize = top - bottom;
00254         
00255    dx = -(pixdx*xwsize/(GLdouble) viewport[2] + eyedx*near/focus);
00256    dy = -(pixdy*ywsize/(GLdouble) viewport[3] + eyedy*near/focus);
00257         
00258    glMatrixMode(GL_PROJECTION);
00259    glLoadIdentity();
00260    glFrustum (left + dx, right + dx, bottom + dy, top + dy, near, far);
00261 glTranslatef(-0.5, -0.5, -5);
00262 glRotatef( AngleY, 0, 1, 0);
00263 glRotatef( AngleX, 1, 0, 0);
00264 glTranslatef(0.5, 0.5, 5);
00265    glMatrixMode(GL_MODELVIEW);
00266    glLoadIdentity();
00267    glTranslatef (-eyedx, -eyedy, 0.0);
00268 }
00269 
00270 /*  accPerspective()
00271  * 
00272  *  The first 4 arguments are identical to the gluPerspective() call.
00273  *  pixdx and pixdy are anti-alias jitter in pixels. 
00274  *  Set both equal to 0.0 for no anti-alias jitter.
00275  *  eyedx and eyedy are depth-of field jitter in pixels. 
00276  *  Set both equal to 0.0 for no depth of field effects.
00277  *
00278  *  focus is distance from eye to plane in focus. 
00279  *  focus must be greater than, but not equal to 0.0.
00280  *
00281  *  Note that accPerspective() calls accFrustum().
00282  */
00283 void accPerspective(GLdouble fovy, GLdouble aspect, 
00284    GLdouble near, GLdouble far, GLdouble pixdx, GLdouble pixdy, 
00285    GLdouble eyedx, GLdouble eyedy, GLdouble focus)
00286 {
00287    GLdouble fov2,left,right,bottom,top;
00288 
00289    fov2 = ((fovy*PI_) / 180.0) / 2.0;
00290 
00291    top = near / (cos(fov2) / sin(fov2));
00292    bottom = -top;
00293 
00294    right = top * aspect;
00295    left = -right;
00296 
00297    accFrustum (left, right, bottom, top, near, far,
00298                pixdx, pixdy, eyedx, eyedy, focus);
00299 }
00300 
00301 void initGL(void)
00302 {
00303 GLenum performance = GL_NICEST; //GL_NICEST
00304 glHint(GL_POINT_SMOOTH_HINT, performance );
00305 glHint(GL_LINE_SMOOTH_HINT, performance );
00306 glHint(GL_POLYGON_SMOOTH_HINT, performance );
00307 glHint(GL_FOG_HINT, performance );
00308 glHint(GL_PERSPECTIVE_CORRECTION_HINT, performance );
00309 
00310 //  glEnable(GL_DEPTH_TEST);
00311 //  glDepthFunc(GL_LESS);
00312   glShadeModel(GL_SMOOTH);
00313 if (Lighting)  glEnable(GL_LIGHTING);
00314 //  glDisable( GL_CULL_FACE );
00315   glEnable( GL_NORMALIZE );
00316 glDisable(GL_CULL_FACE);  
00317 
00318   glLightfv(GL_LIGHT0, GL_DIFFUSE, colorWhite );
00319     glLightfv(GL_LIGHT0, GL_AMBIENT, colorDarkGrey );
00320       glLightfv(GL_LIGHT0, GL_SPECULAR, no_specular);//colorWhite );    
00321    
00322   glLightfv(GL_LIGHT1, GL_DIFFUSE, colorWhite );
00323     glLightfv(GL_LIGHT1, GL_AMBIENT, colorDarkGrey );
00324       glLightfv(GL_LIGHT1, GL_SPECULAR, no_specular);//colorWhite );    
00325    
00326    //define the linear attenuation factor in order
00327    // to make point light source
00328    glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, .001);
00329    glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, .001);
00330 
00331    GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
00332    GLfloat local_view[] = { 0.0 };
00333 
00334 //   glLightfv(GL_LIGHT0, GL_POSITION, LightPos); 
00335   // glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
00336   // glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
00337 
00338    //glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
00339    //glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
00340     
00341 //   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
00342 //   glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
00343 
00344    glFrontFace (GL_CW);
00345 if (Lighting)   glEnable(GL_LIGHTING);
00346 //   glEnable(GL_LIGHT0);
00347 //   glEnable(GL_AUTO_NORMAL);
00348    glEnable(GL_NORMALIZE);
00349    glEnable(GL_DEPTH_TEST);
00350 
00351    glClearColor(0.0, 0.0, 0.0, 0.0);
00352    glClearAccum(0.0, 0.0, 0.0, 0.0); 
00353 /*  make teapot display list */
00354    teapotList = glGenLists(1);
00355    glNewList (teapotList, GL_COMPILE);
00356    glutSolidTeapot (0.5);
00357    glEndList ();
00358 }
00359 
00360 void renderTeapot (GLfloat x, GLfloat y, GLfloat z, 
00361    GLfloat ambr, GLfloat ambg, GLfloat ambb, 
00362    GLfloat difr, GLfloat difg, GLfloat difb, 
00363    GLfloat specr, GLfloat specg, GLfloat specb, GLfloat shine)
00364 {
00365    GLfloat mat[4];
00366 
00367    glPushMatrix();
00368    glTranslatef (x, y, z);
00369    mat[0] = ambr; mat[1] = ambg; mat[2] = ambb; mat[3] = 1.0;   
00370    glMaterialfv (GL_FRONT, GL_AMBIENT, mat);
00371    mat[0] = difr; mat[1] = difg; mat[2] = difb; 
00372    glMaterialfv (GL_FRONT, GL_DIFFUSE, mat);
00373    mat[0] = specr; mat[1] = specg; mat[2] = specb;
00374    glMaterialfv (GL_FRONT, GL_SPECULAR, mat);
00375    glMaterialf (GL_FRONT, GL_SHININESS, shine*128.0);
00376    glCallList(teapotList);
00377    glPopMatrix();
00378 }
00379 
00380 void draw_scene(void)
00381 {
00382       renderTeapot (-1.1, -0.5, -4.5, 0.1745, 0.01175, 
00383                     0.01175, 0.61424, 0.04136, 0.04136, 
00384                     0.727811, 0.626959, 0.626959, 0.6);
00385       renderTeapot (-0.5, -0.5, -5.0, 0.24725, 0.1995, 
00386                     0.0745, 0.75164, 0.60648, 0.22648, 
00387                     0.628281, 0.555802, 0.366065, 0.4);
00388       renderTeapot (0.2, -0.5, -5.5, 0.19225, 0.19225, 
00389                     0.19225, 0.50754, 0.50754, 0.50754, 
00390                     0.508273, 0.508273, 0.508273, 0.4);
00391       renderTeapot (1.0, -0.5, -6.0, 0.0215, 0.1745, 0.0215, 
00392                     0.07568, 0.61424, 0.07568, 0.633, 
00393                     0.727811, 0.633, 0.6);
00394       renderTeapot (1.8, -0.5, -6.5, 0.0, 0.1, 0.06, 0.0, 
00395                     0.50980392, 0.50980392, 0.50196078, 
00396                     0.50196078, 0.50196078, .25);
00397 }
00398 
00399 void renderMirrorSurfacePolygons(void)
00400 {
00401 //glColor3f( 1,1,1);
00402 glBegin(GL_TRIANGLES);
00403     glVertex3fv(mirror_vertices[0]);
00404     glVertex3fv(mirror_center);
00405     glVertex3fv(mirror_vertices[1]);
00406     
00407     glVertex3fv(mirror_vertices[1]);
00408     glVertex3fv(mirror_center);
00409     glVertex3fv(mirror_vertices[2]);
00410     
00411     glVertex3fv(mirror_vertices[2]);
00412     glVertex3fv(mirror_center);
00413     glVertex3fv(mirror_vertices[3]);
00414     
00415     glVertex3fv(mirror_vertices[3]);
00416     glVertex3fv(mirror_center);
00417     glVertex3fv(mirror_vertices[0]);
00418 glEnd();
00419 }
00420 
00421 void drawBorder(void)
00422 {
00423 glColor4f(.5,.5,.5, 0.5);
00424 /*glBegin(GL_TRIANGLES);
00425     glVertex3fv(border_vertices[0]);
00426     glVertex3fv(mirror_center);
00427     glVertex3fv(border_vertices[1]);
00428     
00429     glVertex3fv(border_vertices[1]);
00430     glVertex3fv(mirror_center);
00431     glVertex3fv(border_vertices[2]);
00432     
00433     glVertex3fv(border_vertices[2]);
00434     glVertex3fv(mirror_center);
00435     glVertex3fv(border_vertices[3]);
00436     
00437     glVertex3fv(border_vertices[3]);
00438     glVertex3fv(mirror_center);
00439     glVertex3fv(border_vertices[0]);
00440 glEnd();
00441 */
00442 glBegin(GL_QUADS);
00443     glVertex3fv(border_vertices[0]);
00444     glVertex3fv(mirror_vertices[0]);
00445     glVertex3fv(mirror_vertices[1]);
00446     glVertex3fv(border_vertices[1]);
00447 
00448     glVertex3fv(border_vertices[1]);
00449     glVertex3fv(mirror_vertices[1]);
00450     glVertex3fv(mirror_vertices[2]);
00451     glVertex3fv(border_vertices[2]);
00452 
00453     glVertex3fv(border_vertices[2]);
00454     glVertex3fv(mirror_vertices[2]);
00455     glVertex3fv(mirror_vertices[3]);
00456     glVertex3fv(border_vertices[3]);
00457 
00458     glVertex3fv(border_vertices[3]);
00459     glVertex3fv(mirror_vertices[3]);
00460     glVertex3fv(mirror_vertices[0]);
00461     glVertex3fv(border_vertices[0]);
00462 
00463 glEnd();
00464 }
00465 
00466 void mirrorMatrix(GLfloat m[4][4], 
00467     GLfloat p[3],
00468     GLfloat v[3])
00469 {
00470 
00471 GLfloat dot = p[0]*v[0] + p[1]*v[1] + p[2]*v[2];
00472 
00473 m[0][0] = 1 - 2*v[0]*v[0];
00474 m[1][0] =   - 2*v[0]*v[1];
00475 m[2][0] =   - 2*v[0]*v[2];
00476 m[3][0] = 2*dot*v[0];
00477 
00478 m[0][1] =   - 2*v[1]*v[0];
00479 m[1][1] = 1 - 2*v[1]*v[1];
00480 m[2][1] =   - 2*v[1]*v[2];
00481 m[3][1] = 2*dot*v[1];
00482 
00483 m[0][2] =   - 2*v[2]*v[0];
00484 m[1][2] =   - 2*v[2]*v[1];
00485 m[2][2] = 1 - 2*v[2]*v[2];
00486 m[3][2] = 2*dot*v[2];
00487 
00488 m[0][3] = 0;
00489 m[1][3] = 0;
00490 m[2][3] = 0;
00491 m[3][3] = 1;
00492 
00493 }
00494 
00495 void computeReflectionMatrixForMirror(GLfloat matrix[4][4])
00496 {
00497 
00498 mirrorMatrix((GLfloat (*)[4])&matrix[0][0], 
00499     &mirror_vertices[0][0],
00500     &mirror_normal[0]);
00501 }
00502 
00503 void display(void)
00504 {
00505    GLint viewport[4];
00506 if (Lighting) glEnable(GL_LIGHTING);
00507 //    glColor3f( 1.0f, 1.0f, 1.0f );
00508 //glDisable(GL_DEPTH_TEST);
00509 
00510    glClearColor(0.0, 0.0, 0.0, 0.0);
00511    //glClearAccum(0.0, 0.0, 0.0, 0.0); 
00512 
00513    glGetIntegerv (GL_VIEWPORT, viewport);
00514   // glClear(GL_ACCUM_BUFFER_BIT);
00515 //glClear(GL_COLOR_BUFFER_BIT);
00516       accPerspective (45.0, 
00517          (GLdouble) viewport[2]/(GLdouble) viewport[3], 
00518          1.0, 15.0, 0.0, 0.0,
00519          0, 0, z);
00520 
00521 
00522     glClearStencil(0);
00523       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
00524 
00525 glEnable(GL_STENCIL_BUFFER_BIT);
00526     glEnable(GL_DEPTH_BUFFER_BIT);
00527     glEnable(GL_DEPTH_TEST);
00528     glDisable(GL_STENCIL_TEST);
00529 
00530 
00531 //blend mirror and reflected scene
00532 /*glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR );
00533 glDepthFunc(GL_LESS);
00534 glEnable(GL_BLEND);
00535 */
00536 GLfloat matrix[4][4];
00537 GLdouble clipPlane[4];
00538 
00539 
00540     computeMirrorClipPlane(&clipPlane[0]);
00541 
00542 glLightfv(GL_LIGHT1, GL_POSITION, LightPos2); 
00543 glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
00544 glEnable(GL_LIGHT1);
00545 glDisable(GL_LIGHT0);
00546 //glEnable(GL_LIGHT0);
00547 
00548 //glDepthFunc(GL_LESS);
00549 //mirror is only one
00550 // 1)
00551     glEnable(GL_STENCIL_TEST);
00552     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
00553     glStencilFunc(GL_ALWAYS, 1, ~0);
00554     glColorMask(0, 0, 0, 0);
00555     renderMirrorSurfacePolygons();       
00556        
00557 // 2)
00558     glDepthRange(1,1);
00559     glDepthFunc(GL_ALWAYS);
00560     glStencilFunc(GL_EQUAL, 1, ~0);
00561     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00562     renderMirrorSurfacePolygons();
00563 
00564 // 3)
00565     glDepthFunc(GL_LESS);
00566     glColorMask(1,1,1,1);
00567     glDepthRange(0,1);
00568 
00569 // 4)
00570 
00571 glPushMatrix();
00572     //returns world-space plane equation for mirror plane to use as clip plane 
00573 //    computeMirrorClipPlane(&clipPlane[0]);
00574     
00575     //set clip plane equation
00576     glClipPlane(GL_CLIP_PLANE0, &clipPlane[0]);
00577 glEnable(GL_CLIP_PLANE0);
00578     //returns mirrorMatrix for given mirror
00579     computeReflectionMatrixForMirror(
00580                 (GLfloat (*) [4])&matrix[0][0]);
00581     //concatenae reflection transform into modelview matrix
00582     glMultMatrixf(&matrix[0][0]);
00583 
00584  glCullFace(GL_FRONT);
00585         //glMatrixMode(GL_MODELVIEW);
00586         //glPushMatrix();
00587         //glLoadIdentity();
00588 //      glEnable(GL_CLIP_PLANE0);
00589         //glPopMatrix();
00590         draw_scene();
00591 drawBorder();
00592     
00593     glCullFace(GL_BACK);
00594     glDisable(GL_CLIP_PLANE0);
00595 glPopMatrix();
00596 
00597 // 5)
00598 
00599 glColorMask(0, 0, 0, 0);
00600 glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
00601 glDepthFunc(GL_ALWAYS);
00602 renderMirrorSurfacePolygons();
00603 glDepthFunc(GL_LESS);
00604 glColorMask(1,1,1,1);
00605 
00606 glCullFace(GL_FRONT);
00607 glDepthFunc(GL_LESS);
00608 glDisable(GL_STENCIL_TEST);
00609 
00610    glLightfv(GL_LIGHT0, GL_POSITION, LightPos); 
00611 glEnable(GL_LIGHT0);
00612 glDisable(GL_LIGHT1);
00613 
00614     draw_scene(); //draw everything except mirror
00615     drawBorder(); // <-- here is the difference with approach in "Improving ..."
00616                 // because we first drawing all the reflections and only then the
00617                 // actual scene, which passes the depth test for GL_LESS. 
00618                 // This removes all not reflected pixels from the mirror. 
00619                 // When using other way round, on the mirror would be teapots which
00620                 // are behind the mirror, since they are drawn at first and never
00621                 // deleted (or pass some depth tests).
00622 glDepthFunc(GL_LESS);
00623 
00624 
00625 
00626 
00627 glDisable(GL_BLEND);
00628 
00629          // Display framerate
00630 glPushMatrix();
00631     char buf[100];
00632     sprintf( buf, " %0.2f fps,  X=%f, Y=%f, Z=%f, alpha=%f, beta=%f ", FPS, CameraX, CameraY, CameraZ, 
00633         AngleX, AngleY );
00634     glMatrixMode( GL_PROJECTION );
00635     glLoadIdentity();
00636     glMatrixMode( GL_MODELVIEW );
00637     glLoadIdentity();
00638     glDisable( GL_DEPTH_TEST );
00639     glDisable( GL_LIGHTING );
00640     glColor3f( 1.0f, 1.0f, 1.0f );
00641     glRasterPos2f( -1,-1 );
00642     glutString( buf );
00643     glEnable( GL_DEPTH_TEST );
00644 if (Lighting)    glEnable(GL_LIGHTING);
00645 glPopMatrix();
00646    
00647    glutSwapBuffers();
00648 }
00649 
00650 void reshape(int w, int h)
00651 {
00652 changed = true;
00653    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
00654    glutPostRedisplay();
00655 }
00656 
00657 void keyboard(unsigned char key, int x, int y)
00658 {
00659    switch (key) {
00660       case 27:
00661       case 'q':
00662          exit(0);
00663          break;
00664           case ' ':
00665                  glutPostRedisplay();
00666                  break;
00667           case 'a':
00668                 RotateLeft = true;
00669                 RotateRight = false;
00670                 break;
00671           case 'd':
00672                 RotateRight = true;
00673                 RotateLeft = false;
00674                 break;
00675           case 'w':
00676                 RotateUp = true;
00677                 RotateDown = false;
00678                 break;
00679           case 's':
00680                 RotateDown = true;
00681                 RotateUp = false;
00682                 break;
00683           case 't':
00684                 RotateMirrorUp = true;
00685                 RotateMirrorDown = false;
00686                 break;
00687           case 'g':
00688                 RotateMirrorDown = true;
00689                 RotateMirrorUp = false;
00690                 break;
00691           case 'f':
00692                 RotateMirrorLeft = true;
00693                 RotateMirrorRight = false;
00694                 break;
00695           case 'h':
00696                 RotateMirrorRight = true;
00697                 RotateMirrorLeft = false;
00698                 break;
00699           case 'v':
00700                 MoveMirrorForward = true;
00701                 MoveMirrorBackward = false;
00702                 break;
00703           case 'b':
00704                 MoveMirrorForward = false;
00705                 MoveMirrorBackward = true;
00706                 break;
00707           case 'o': 
00708                 Specular = !Specular;
00709                 if (!Specular)
00710                     {
00711                     glLightfv(GL_LIGHT0, GL_SPECULAR, no_specular);//colorWhite );    
00712                     glLightfv(GL_LIGHT1, GL_SPECULAR, no_specular);//colorWhite );    
00713                     }
00714                 else
00715                     {
00716                     glLightfv(GL_LIGHT0, GL_SPECULAR, colorWhite );    
00717                     glLightfv(GL_LIGHT1, GL_SPECULAR, colorWhite );    
00718                     };
00719                 break;
00720           case 'l': Lighting = !Lighting;
00721                 if (Lighting)
00722                     glEnable(GL_LIGHTING);
00723                 else
00724                     glDisable(GL_LIGHTING);
00725                 break;
00726           
00727           case 'p': FillPolygons = !FillPolygons;
00728                 glPolygonMode( GL_FRONT_AND_BACK, (FillPolygons ? GL_FILL : GL_LINE) );
00729                 break;
00730    }
00731 }
00732 
00733 
00734 static void timerCallback(int)
00735 {
00736 
00737 int nc = glutGet(GLUT_ELAPSED_TIME);
00738 float fSec = float(nc-LastTime) / 1000.0f;
00739   // Compute average frame rate from the last twenty frames
00740   FPS = (19.0f*FPS + 1.0f / fSec) / 20.0f;
00741   LastTime = nc;
00742   
00743   float fCamArc = fSec * 180.0f;
00744   if (RotateLeft) AngleY -= fCamArc/4;
00745   if (RotateRight) AngleY += fCamArc/4;
00746   if (RotateUp) AngleX += fCamArc/4;
00747   if (RotateDown) AngleX -= fCamArc/4;
00748   
00749   GLfloat angle = fCamArc/4;
00750   GLfloat rotatematrix[16]; 
00751   GLfloat translatematrix[16];
00752   
00753   if ((RotateMirrorLeft) || (RotateMirrorRight) )
00754     {
00755     //specify the rotation angle
00756     if (RotateMirrorLeft) angle = -angle;
00757     //convert from degrees to rad
00758 //printf(" angle = %f deg, ", angle);
00759     angle = angle * M_PI/180.0f;
00760 //printf(" %f rad \n", angle);
00761     //construct the rotation matrix
00762 /*    rotatematrix[0] = 1; rotatematrix[1] = 0; rotatematrix[2] = 0;                  rotatematrix[3] = 0;
00763     rotatematrix[4] = 0; rotatematrix[5] = cos(angle); rotatematrix[6] = -sin(angle); rotatematrix[7] = 0;
00764     rotatematrix[8] = 0; rotatematrix[9] = sin(angle); rotatematrix[10] = cos(angle); rotatematrix[11] = 0;
00765     rotatematrix[12] = 0; rotatematrix[13] = 0; rotatematrix[14] = 0;                 rotatematrix[15] = 1;
00766 */
00767 
00768     rotatematrix[0] = cos(angle); rotatematrix[1] = 0; rotatematrix[2] = sin(angle); rotatematrix[3] = 0;
00769     rotatematrix[4] = 0;        rotatematrix[5] = 1; rotatematrix[6] = 0; rotatematrix[7] = 0;
00770     rotatematrix[8] = -sin(angle); rotatematrix[9] = 0; rotatematrix[10] = cos(angle); rotatematrix[11] = 0;
00771     rotatematrix[12] = 0; rotatematrix[13] = 0; rotatematrix[14] = 0;                 rotatematrix[15] = 1;
00772     
00773     translatematrix[0] = 1; translatematrix[1] = 0; translatematrix[2] = 0; translatematrix[3]  = -mirror_center[0];
00774     translatematrix[4] = 0; translatematrix[5] = 1; translatematrix[6] = 0; translatematrix[7]  = -mirror_center[1];
00775     translatematrix[8] = 0; translatematrix[9] = 0; translatematrix[10] = 1; translatematrix[11] = -mirror_center[2];
00776     translatematrix[12] = 0; translatematrix[13] = 0; translatematrix[14] = 0; translatematrix[15] = 1;
00777 
00778 GLfloat vector[4];
00779     //now modify the coordinates
00780     for (int i=0; i<4; i++)
00781         {
00782         //first, translate the vertices 
00783         mirror_vertices[i][0] -= mirror_center[0];
00784         mirror_vertices[i][1] -= mirror_center[1];
00785         mirror_vertices[i][2] -= mirror_center[2];
00786     
00787         border_vertices[i][0] -= mirror_center[0];
00788         border_vertices[i][1] -= mirror_center[1];
00789         border_vertices[i][2] -= mirror_center[2];
00790         
00791         //then rotate  
00792         Multiply<GLfloat> (rotatematrix, mirror_vertices[i], vector);
00793                 mirror_vertices[i][0] = vector[0];
00794                 mirror_vertices[i][1] = vector[1];
00795                 mirror_vertices[i][2] = vector[2];
00796                 mirror_vertices[i][3] = vector[3];
00797         Multiply<GLfloat> (rotatematrix, border_vertices[i], vector);
00798                 border_vertices[i][0] = vector[0];
00799                 border_vertices[i][1] = vector[1];
00800                 border_vertices[i][2] = vector[2];
00801                 border_vertices[i][3] = vector[3];
00802 
00803         //and return back
00804         mirror_vertices[i][0] += mirror_center[0];
00805         mirror_vertices[i][1] += mirror_center[1];
00806         mirror_vertices[i][2] += mirror_center[2];
00807     
00808         border_vertices[i][0] += mirror_center[0];
00809         border_vertices[i][1] += mirror_center[1];
00810         border_vertices[i][2] += mirror_center[2];
00811         }//end for
00812     }//end if
00813 
00814 //UP and DOWN rotations
00815   if ((RotateMirrorUp) || (RotateMirrorDown) )
00816     {
00817     //specify the rotation angle
00818     if (RotateMirrorDown) angle = -angle;
00819     //convert from degrees to rad
00820 //printf(" angle = %f deg, ", angle);
00821     angle = angle * M_PI/180.0f;
00822 //printf(" %f rad \n", angle);
00823     //construct the rotation matrix
00824     rotatematrix[0] = 1; rotatematrix[1] = 0; rotatematrix[2] = 0;                    rotatematrix[3] = 0;
00825     rotatematrix[4] = 0; rotatematrix[5] = cos(angle); rotatematrix[6] = -sin(angle); rotatematrix[7] = 0;
00826     rotatematrix[8] = 0; rotatematrix[9] = sin(angle); rotatematrix[10] = cos(angle); rotatematrix[11] = 0;
00827     rotatematrix[12] = 0; rotatematrix[13] = 0; rotatematrix[14] = 0;                 rotatematrix[15] = 1;
00828 
00829 /*
00830     rotatematrix[0] = cos(angle); rotatematrix[1] = 0; rotatematrix[2] = sin(angle); rotatematrix[3] = 0;
00831     rotatematrix[4] = 0;        rotatematrix[5] = 1; rotatematrix[6] = 0; rotatematrix[7] = 0;
00832     rotatematrix[8] = -sin(angle); rotatematrix[9] = 0; rotatematrix[10] = cos(angle); rotatematrix[11] = 0;
00833     rotatematrix[12] = 0; rotatematrix[13] = 0; rotatematrix[14] = 0;                 rotatematrix[15] = 1;
00834 */        
00835     translatematrix[0] = 1; translatematrix[1] = 0; translatematrix[2] = 0; translatematrix[3]  = -mirror_center[0];
00836     translatematrix[4] = 0; translatematrix[5] = 1; translatematrix[6] = 0; translatematrix[7]  = -mirror_center[1];
00837     translatematrix[8] = 0; translatematrix[9] = 0; translatematrix[10] = 1; translatematrix[11] = -mirror_center[2];
00838     translatematrix[12] = 0; translatematrix[13] = 0; translatematrix[14] = 0; translatematrix[15] = 1;
00839 
00840 GLfloat vector[4];
00841     //now modify the coordinates
00842     for (int i=0; i<4; i++)
00843         {
00844         //first, translate the vertices 
00845         mirror_vertices[i][0] -= mirror_center[0];
00846         mirror_vertices[i][1] -= mirror_center[1];
00847         mirror_vertices[i][2] -= mirror_center[2];
00848     
00849         border_vertices[i][0] -= mirror_center[0];
00850         border_vertices[i][1] -= mirror_center[1];
00851         border_vertices[i][2] -= mirror_center[2];
00852         
00853         //then rotate  
00854         Multiply<GLfloat> (rotatematrix, mirror_vertices[i], vector);
00855                 mirror_vertices[i][0] = vector[0];
00856                 mirror_vertices[i][1] = vector[1];
00857                 mirror_vertices[i][2] = vector[2];
00858                 mirror_vertices[i][3] = vector[3];
00859         Multiply<GLfloat> (rotatematrix, border_vertices[i], vector);
00860                 border_vertices[i][0] = vector[0];
00861                 border_vertices[i][1] = vector[1];
00862                 border_vertices[i][2] = vector[2];
00863                 border_vertices[i][3] = vector[3];
00864 
00865         //and return back
00866         mirror_vertices[i][0] += mirror_center[0];
00867         mirror_vertices[i][1] += mirror_center[1];
00868         mirror_vertices[i][2] += mirror_center[2];
00869     
00870         border_vertices[i][0] += mirror_center[0];
00871         border_vertices[i][1] += mirror_center[1];
00872         border_vertices[i][2] += mirror_center[2];
00873         }//end for
00874     }//end if
00875 
00876 float distance = .10f;
00877 if ((MoveMirrorForward) || (MoveMirrorBackward))
00878     {
00879         distance = (MoveMirrorForward ? distance : -distance );
00880     //modify the coordinates
00881     for (int i=0; i<4; i++)
00882         {
00883         //mirror 
00884         mirror_vertices[i][0] += mirror_normal[0] * distance;
00885         mirror_vertices[i][1] += mirror_normal[1] * distance;
00886         mirror_vertices[i][2] += mirror_normal[2] * distance;
00887         
00888         //border
00889         border_vertices[i][0] += mirror_normal[0] * distance;
00890         border_vertices[i][1] += mirror_normal[1] * distance;
00891         border_vertices[i][2] += mirror_normal[2] * distance;
00892         }//end for
00893 
00894     //and the center!
00895     mirror_center[0] += mirror_normal[0] * distance;
00896     mirror_center[1] += mirror_normal[1] * distance;
00897     mirror_center[2] += mirror_normal[2] * distance;
00898 
00899     }//end if
00900   
00901   glutPostRedisplay();
00902   glutTimerFunc(TimerDelay, timerCallback, 0);
00903 
00904 }
00905 
00906 
00907 
00908 /*  Main Loop
00909  *  Be certain you request an accumulation buffer.
00910  */
00911 
00912 void keyboardUp(unsigned char key, int, int)
00913 {
00914 switch (key)
00915         {
00916         case 'a': RotateLeft = false;  break;
00917         case 'd': RotateRight = false; break;
00918         case 'w': RotateUp = false;  break;
00919         case 's': RotateDown = false; break;
00920         case 't': RotateMirrorUp = false; break;
00921         case 'g': RotateMirrorDown = false; break;
00922         case 'f': RotateMirrorLeft = false; break;
00923         case 'h': RotateMirrorRight = false; break;
00924         case 'v': MoveMirrorForward = false; break;
00925         case 'b': MoveMirrorBackward = false; break;
00926         }
00927 
00928 }
00929  
00930 int main(int argc, char** argv)
00931 {
00932 
00933 printf(" Keys: \n");
00934 printf("\ta,d,w,s    -- to rotate about gold teapot.\n");
00935 printf("\tf,h,t,g    -- to rotate mirror.\n");
00936 printf("\tv,b        -- to move mirro back and force.\n");
00937 printf("\tp          -- to toggle polygon fill mode.\n");
00938 printf("\tl          -- to toggle lighting.\n");
00939 printf("\to          -- to toggle specular lighting.\n");
00940 printf("\tq    -- to Quit.\n");
00941 
00942    glutInit(&argc, argv);
00943    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB
00944                         | GLUT_STENCIL | GLUT_DEPTH); 
00945    glutInitWindowSize (400, 400);
00946    glutInitWindowPosition (100, 100);
00947    glutCreateWindow (argv[0]);
00948    initGL();
00949    glutReshapeFunc(reshape);
00950    glutDisplayFunc(display);
00951    glutKeyboardFunc(keyboard);
00952    glutKeyboardUpFunc(keyboardUp);
00953    LastTime = glutGet (GLUT_ELAPSED_TIME );
00954    glutTimerFunc ( TimerDelay, timerCallback, 0);
00955    glutMainLoop();
00956    return 0;
00957 }
00958 

Generated on Thu Jan 20 02:47:27 2005 for Arbitrary_Mirror_Effect_Demo by doxygen 1.3.6