00001 #include <GL/glut.h>
00002 #include <GL/glu.h>
00003
00004 #include <stdio.h>
00005 #include <stdlib.h>
00006 #include <math.h>
00007
00008 #include "config.h"
00009 #include "torus.h"
00010 #include "texture.h"
00011 #include "math.h"
00012 #include "heightfield.h"
00013
00014
00015
00016
00017
00018
00019
00020
00021 enum {
00022 MENU_LIGHTING = 1,
00023 MENU_POLYMODE,
00024 MENU_TEXTURING,
00025 MENU_FRAMERATE,
00026 MENU_EXIT
00027 };
00028
00029
00030 static int g_nLastTime = 0;
00031
00032 static float g_fFPS = 0;
00033
00034
00035 static float g_nearPlane = 1;
00036 static float g_farPlane = 10;
00037
00038 static const double VIEWING_DISTANCE_MIN = 1;
00039 float g_fViewDistance = 5*VIEWING_DISTANCE_MIN;
00040
00041
00042
00043 static int g_Width = 256;
00044 static int g_Height = 256;
00045
00046
00047 static bool g_bFillPolygons = true;
00048
00049
00050
00051 static bool g_bRotateLeft = false;
00052 static bool g_bRotateRight = false;
00053 static bool g_bRotateDown = false;
00054 static bool g_bRotateUp = false;
00055
00056
00057 static bool g_bCameraUp = false;
00058 static bool g_bCameraDown = false;
00059 static bool g_bCameraLeft = false;
00060 static bool g_bCameraRight = false;
00061 static float g_fCameraX = 0;
00062 static float g_fCameraY = 0;
00063
00064
00065 static float g_eyePoint[4];
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 void glutString( char *pstr )
00076 {
00077 while (*pstr!=char(0)) {
00078 glutBitmapCharacter( GLUT_BITMAP_8_BY_13, int( *pstr ));
00079 pstr++;
00080 }
00081 }
00082
00083
00084
00085
00086
00087
00088
00089 void computeCameraPosition( float *eyePoint )
00090 {
00091
00092
00093
00094 float eyeProject[4];
00095 eyeProject[0] = 0;
00096 eyeProject[1] = 0;
00097 eyeProject[2] = - (g_nearPlane * g_farPlane) / (g_farPlane - g_nearPlane);
00098 eyeProject[3] = 0;
00099
00100
00101
00102 float modelviewT[16];
00103 glGetFloatv( GL_TRANSPOSE_MODELVIEW_MATRIX, modelviewT );
00104 float projectionT[16];
00105 glGetFloatv( GL_TRANSPOSE_PROJECTION_MATRIX, projectionT );
00106
00107
00108 float inverse_projection[16];
00109 float inverse_modelview[16];
00110 Invert<float> (projectionT, inverse_projection);
00111 Invert<float> (modelviewT, inverse_modelview);
00112
00113 float eyeCamera[4];
00114 Multiply<float> (inverse_projection, eyeProject, eyeCamera );
00115 Multiply<float> (inverse_modelview, eyeCamera, eyePoint );
00116 }
00117
00118
00119
00120
00121
00122 void computeLightPosition( const float *lightPosWorld, float *lightPosEye )
00123 {
00124
00125
00126
00127 float projection[16];
00128 glGetFloatv( GL_TRANSPOSE_MODELVIEW_MATRIX, projection );
00129 Multiply<float> (projection, lightPosWorld, lightPosEye );
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 void setupCamera()
00141 {
00142
00143 glMatrixMode(GL_PROJECTION);
00144 glLoadIdentity();
00145 gluPerspective(65.0, (float)g_Width / g_Height, g_nearPlane, g_farPlane);
00146
00147
00148 glMatrixMode(GL_MODELVIEW);
00149 glLoadIdentity();
00150
00151
00152 gluLookAt(0, 0, -g_fViewDistance, 0, 0, -1, 0, 1, 0);
00153
00154
00155 glRotatef( g_fCameraX, 1,0,0 );
00156 glRotatef( g_fCameraY, 0,1,0 );
00157
00158
00159 computeLightPosition( g_lightPos, g_lightPosEye );
00160 }
00161
00162
00163
00164 void renderScene()
00165 {
00166 if (g_bLighting) {
00167 glEnable(GL_LIGHTING);
00168 }
00169 else {
00170 glDisable(GL_LIGHTING);
00171 }
00172
00173
00174 glPushMatrix();
00175
00176
00177 drawTorus( g_eyePoint );
00178 glPopMatrix();
00179
00180
00181
00182
00183 glPushMatrix();
00184 glTranslatef( 0,-5,0 );
00185 glRotatef( -90, 1,0,0 );
00186 drawHeightField( 0,0, (int)g_farPlane, (int)g_farPlane );
00187 glPopMatrix();
00188 }
00189
00190
00191 void display()
00192 {
00193
00194 glClearColor( colorSky[0], colorSky[1], colorSky[2], colorSky[3] );
00195 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00196
00197
00198 setupCamera();
00199 glGetFloatv(GL_MODELVIEW_MATRIX, ModelViewMatrix);
00200
00201 glViewport(0, 0, g_Width, g_Height);
00202
00203
00204 glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);
00205 glLightfv(GL_LIGHT0, GL_DIFFUSE, colorWhite );
00206 glLightfv(GL_LIGHT0, GL_AMBIENT, colorDarkGrey );
00207 glLightfv(GL_LIGHT0, GL_SPECULAR, colorWhite );
00208
00209
00210 glFogi( GL_FOG_MODE, GL_LINEAR );
00211 glFogf( GL_FOG_START, g_farPlane * 0.6f );
00212 glFogf( GL_FOG_END, g_farPlane );
00213 glFogfv( GL_FOG_COLOR, colorSky );
00214 glEnable( GL_FOG );
00215
00216
00217 renderScene();
00218
00219
00220
00221 if (g_bFrameRate) {
00222 char buf[100];
00223 sprintf( buf, "%0.2f fps", g_fFPS );
00224 glMatrixMode( GL_PROJECTION );
00225 glLoadIdentity();
00226 glMatrixMode( GL_MODELVIEW );
00227 glLoadIdentity();
00228 glDisable( GL_DEPTH_TEST );
00229 glDisable( GL_LIGHTING );
00230 glColor3f( 1.0f, 1.0f, 1.0f );
00231 glRasterPos2f( -1,-1 );
00232 glutString( buf );
00233 glEnable( GL_DEPTH_TEST );
00234 }
00235
00236
00237 glutSwapBuffers();
00238 }
00239
00240
00241
00242 void reshape(GLint width, GLint height)
00243 {
00244 g_Width = width;
00245 g_Height = height;
00246 }
00247
00248
00249
00250 void initGL()
00251 {
00252 glEnable(GL_DEPTH_TEST);
00253 glDepthFunc(GL_LESS);
00254 glShadeModel(GL_SMOOTH);
00255 glEnable(GL_LIGHTING);
00256 glEnable(GL_LIGHT0);
00257 glEnable( GL_CULL_FACE );
00258 glCullFace( GL_BACK );
00259 glEnable( GL_NORMALIZE );
00260
00261
00262 initTorus();
00263
00264 initTextures();
00265
00266
00267 printf( "Loading height field %s, size %i x %i ... ",
00268 g_strHeightFieldFile, g_hfW, g_hfH );
00269 initHeightField();
00270 printf( "success.\n" );
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 static void timerCallback(int)
00284 {
00285
00286 int nc = glutGet(GLUT_ELAPSED_TIME);
00287 float fSec = float(nc-g_nLastTime) / 1000.0f;
00288
00289 g_fFPS = (19.0f*g_fFPS + 1.0f / fSec) / 20.0f;
00290 g_nLastTime = nc;
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 if (g_bRotateLeft) {
00302 g_fTorusX += fSec * 360.0f / 5.0f;
00303 }
00304 else if (g_bRotateRight) {
00305 g_fTorusX -= fSec * 360.0f / 5.0f;
00306 }
00307 if (g_bRotateUp) {
00308 g_fTorusY += fSec * 360.0f / 5.0f;
00309 }
00310 else if (g_bRotateDown) {
00311 g_fTorusY -= fSec * 360.0f / 5.0f;
00312 }
00313
00314
00315
00316 glutPostRedisplay();
00317 glutTimerFunc( g_nTimerDelay, timerCallback, 0);
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 void selectFromMenu(int idCommand)
00334 {
00335 switch (idCommand) {
00336 case MENU_LIGHTING:
00337 g_bLighting = !g_bLighting;
00338 break;
00339 case MENU_FRAMERATE:
00340 g_bFrameRate = !g_bFrameRate;
00341 break;
00342 case MENU_POLYMODE:
00343 g_bFillPolygons = !g_bFillPolygons;
00344 glPolygonMode (GL_FRONT_AND_BACK, g_bFillPolygons ? GL_FILL : GL_LINE);
00345 break;
00346 case MENU_EXIT:
00347 printf( "Exiting.\n" );
00348 glutSetKeyRepeat( GLUT_KEY_REPEAT_ON );
00349 exit (0);
00350 break;
00351 }
00352
00353
00354 glutPostRedisplay();
00355 }
00356
00357
00358 float sExpFunc( int n )
00359 {
00360 return float(n*n) / 2.0f + 0.01f;
00361 }
00362
00363
00364
00365 void keyboard(unsigned char key, int, int )
00366 {
00367 switch (key) {
00368 case 27:
00369 exit (0);
00370 break;
00371 case 'l':
00372 selectFromMenu(MENU_LIGHTING);
00373 break;
00374 case 'f':
00375 selectFromMenu(MENU_FRAMERATE);
00376 break;
00377 case 'p':
00378 selectFromMenu(MENU_POLYMODE);
00379 break;
00380 case '1':
00381 g_specularExponent = sExpFunc( 1 );
00382 break;
00383 case '2':
00384 g_specularExponent = sExpFunc( 2 );
00385 break;
00386 case '3':
00387 g_specularExponent = sExpFunc( 3 );
00388 break;
00389 case '4':
00390 g_specularExponent = sExpFunc( 4 );
00391 break;
00392 case '5':
00393 g_specularExponent = sExpFunc( 5 );
00394 break;
00395 case '6':
00396 g_specularExponent = sExpFunc( 6 );
00397 break;
00398 case '7':
00399 g_specularExponent = sExpFunc( 7 );
00400 break;
00401 case '8':
00402 g_specularExponent = sExpFunc( 8 );
00403 break;
00404 case '9':
00405 g_specularExponent = sExpFunc( 9 );
00406 break;
00407 case '0':
00408 g_specularExponent = sExpFunc( 0 );
00409 break;
00410 case 'a':
00411 g_bRotateLeft = true;
00412 break;
00413 case 'd':
00414 g_bRotateRight = true;
00415 break;
00416 case 's':
00417 g_bRotateUp = true;
00418 break;
00419 case 'w':
00420 g_bRotateDown = true;
00421 break;
00422 }
00423 }
00424
00425 void keyboardUp(unsigned char key, int,int)
00426 {
00427 switch( key ) {
00428 case 'a':
00429 g_bRotateLeft = false;
00430 break;
00431 case 'd':
00432 g_bRotateRight = false;
00433 break;
00434 case 's':
00435 g_bRotateUp = false;
00436 break;
00437 case 'w':
00438 g_bRotateDown = false;
00439 break;
00440 }
00441 }
00442
00443 void special( int key, int,int )
00444 {
00445 switch( key ) {
00446 case GLUT_KEY_F1:
00447 g_bPerPixelLighting = true;
00448 break;
00449 case GLUT_KEY_F2:
00450 g_bPerPixelLighting = false;
00451 break;
00452 case GLUT_KEY_F3:
00453 g_bBlinnPhong = true;
00454 break;
00455 case GLUT_KEY_F4:
00456 g_bBlinnPhong = false;
00457 break;
00458 case GLUT_KEY_UP:
00459 g_bCameraUp = true;
00460 break;
00461 case GLUT_KEY_DOWN:
00462 g_bCameraDown = true;
00463 break;
00464 case GLUT_KEY_LEFT:
00465 g_bCameraLeft = true;
00466 break;
00467 case GLUT_KEY_RIGHT:
00468 g_bCameraRight = true;
00469 break;
00470 }
00471 }
00472
00473
00474 void specialUp( int key, int,int )
00475 {
00476 switch( key ) {
00477 case GLUT_KEY_UP:
00478 g_bCameraUp = false;
00479 break;
00480 case GLUT_KEY_DOWN:
00481 g_bCameraDown = false;
00482 break;
00483 case GLUT_KEY_LEFT:
00484 g_bCameraLeft = false;
00485 break;
00486 case GLUT_KEY_RIGHT:
00487 g_bCameraRight = false;
00488 break;
00489 }
00490 }
00491
00492
00493
00494
00495
00496
00497 int buildPopupMenu()
00498 {
00499 printf( "Keys:\n" );
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 printf( " p - Toggle polygon fill\n" );
00513 printf( " f - Display frame rate\n" );
00514 printf( " ESC - Exit demo\n" );
00515
00516
00517 int menu = glutCreateMenu (selectFromMenu);
00518 glutAddMenuEntry ("Toggle polygon fill\tp", MENU_POLYMODE);
00519 glutAddMenuEntry ("Display frame rate\tf", MENU_FRAMERATE);
00520 glutAddMenuEntry ("Exit demo\tEsc", MENU_EXIT);
00521 return menu;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 int main(int argc, char** argv)
00535 {
00536
00537 glutInit(&argc, argv);
00538 glutInitWindowSize(g_Width, g_Height);
00539 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
00540 glutCreateWindow("CG-I GLUT example");
00541
00542 glutSetKeyRepeat( GLUT_KEY_REPEAT_ON );
00543 glutIgnoreKeyRepeat(0);
00544
00545
00546 initGL();
00547
00548
00549 glutDisplayFunc(display);
00550 glutReshapeFunc(reshape);
00551 glutKeyboardFunc(keyboard);
00552 glutKeyboardUpFunc(keyboardUp);
00553 glutSpecialFunc(special);
00554 glutSpecialUpFunc(specialUp);
00555
00556
00557
00558 buildPopupMenu();
00559 glutAttachMenu(GLUT_RIGHT_BUTTON);
00560
00561
00562 g_nLastTime = glutGet( GLUT_ELAPSED_TIME );
00563 glutTimerFunc( g_nTimerDelay, timerCallback, 0);
00564
00565
00566 glutMainLoop();
00567 return 0;
00568 }