Demo.cpp

00001 #include "Demo.h"
00002 #include "Textures.h"
00003 
00004 Demo::Demo ()
00005 {
00006         // initialize default state
00007         fullscreen_enabled = false;
00008         culling_mode = C_NONE;
00009         level_of_detail_enabled = false;
00010         is_initialized = false;
00011         demo_time = DEMO_NOT_YET_STARTED;
00012 
00013         // frame rate
00014         frame_rate = 0;
00015         incremental_rate = 0;
00016         last_frame_rate_time = 0;
00017 
00018         // initialize scene list
00019         first_scene = NULL;
00020         current_scene = NULL;
00021 
00022         // set default size
00023         window_width = 640;
00024         window_height = 480;
00025 
00026         // create camera to monitor scenes
00027         monitor_camera = new Camera ();
00028 }
00029 
00030 Demo::~Demo ()
00031 {
00032         // release textures
00033         Textures::Release ();
00034 
00035         // delete all scenes
00036         SceneListElem * current_scene;
00037         SceneListElem * scene_to_be_deleted;
00038 
00039         current_scene = first_scene;
00040         while (current_scene != NULL)
00041         {
00042                 scene_to_be_deleted = current_scene;
00043                 current_scene = current_scene->next;
00044                 delete scene_to_be_deleted;
00045         }
00046 }
00047 
00048 void Demo::Init (int argc, char * argv [])
00049 {
00050         PrintUsage ();
00051 
00052         // activate this demo
00053         Demo::current_demo = this;
00054 
00055         // init display mode and window or fullscreen
00056         glutInitDisplayMode(GLUT_DEPTH | GLUT_RGBA | GLUT_DOUBLE | GLUT_ACCUM);
00057 
00058         if (argc == 3)
00059         {
00060                 int size_x, size_y;
00061                 size_x = atoi (argv[1]);
00062                 size_y = atoi (argv[2]);
00063 
00064                 if (size_x > 0 && size_y > 0)
00065                 {
00066                         window_width = size_x;
00067                         window_height = size_y;
00068                 }
00069         }
00070         if (argc == 2)
00071         {
00072                 glutGameModeString (argv[1]);
00073                 if (glutGameModeGet (GLUT_GAME_MODE_POSSIBLE ))
00074                 {
00075                         fullscreen_enabled = true;
00076                         glutEnterGameMode ();
00077                 }
00078         }
00079 
00080         if (!fullscreen_enabled)
00081         {
00082                 glutInitWindowSize (window_width, window_height);
00083                 glutCreateWindow("Demo");
00084         }
00085 
00086         // Register functions
00087         glutDisplayFunc (Demo::static_display);
00088         glutIdleFunc (Demo::static_idle);
00089         glutReshapeFunc (Demo::static_reshape);
00090         glutKeyboardFunc (Demo::static_keyboard);
00091         glutSpecialFunc (Demo::static_keyboard_special);
00092 
00093         // Init OpenGL states
00094         glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
00095         glEnable (GL_DEPTH_TEST);
00096         glDepthFunc (GL_LEQUAL);
00097         glShadeModel (GL_SMOOTH);
00098         glEnable (GL_COLOR_MATERIAL);
00099         glEnable (GL_LIGHTING);
00100 
00101         // set default values for ambient light and specular behaviour
00102         SetGlobalAmbientPlayback (0.0f, 0.0f, 0.0f, 0.0f);
00103         SetGlobalAmbientMonitor (0.4f, 0.4f, 0.4f, 1.0f);
00104         SetGlobalSpecularReflection (1.0f, 1.0f, 1.0f, 1.0f);
00105         SetGlobalShininess (64);
00106 
00107         glMaterialfv (GL_FRONT, GL_SPECULAR, global_specular_reflection);
00108         glMateriali(GL_FRONT, GL_SHININESS, global_shininess);
00109 
00110         glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
00111 
00112         // Load textures
00113         Textures::Load ();
00114 
00115         // Init all scenes
00116         SceneListElem * current_scene;
00117         current_scene = first_scene;
00118         while (current_scene != NULL)
00119         {
00120                 if (current_scene->scene != NULL)
00121                 {current_scene->scene->Init ();}
00122                 current_scene = current_scene->next;
00123         }
00124 
00125         // Init random number generator
00126         srand (timeGetTime ());
00127 
00128         // set up modes
00129         level_of_detail_enabled = true;
00130         culling_mode = C_BOUNDING_BOX;
00131 
00132         is_initialized = true;
00133 }
00134 
00135 void Demo::Play ()
00136 {
00137         if (!is_initialized)
00138         {printf ("Demo has to be initialized first\n"); return;}
00139 
00140         if (first_scene == NULL)
00141         {printf ("Demo contains no scenes\n");}
00142 
00143         demo_time = 0;
00144         last_measure_time = (int)glutGet (GLUT_ELAPSED_TIME);
00145         monitoring_mode = false;
00146         demo_playing = true;
00147         current_scene = first_scene;
00148 
00149         glLightModelfv (GL_LIGHT_MODEL_AMBIENT, global_ambient_playback);
00150 
00151         glutShowWindow ();
00152         glutMainLoop ();
00153 }
00154 
00155 void Demo::AddScene (Scene * scene, int duration, int blend_in)
00156 {
00157         SceneListElem * current_scene;
00158 
00159         // Add dummy scene if the first scene has to be blended in
00160         if (blend_in > 0 && first_scene == NULL)
00161         {
00162                 first_scene = new SceneList;
00163                 first_scene->next = NULL;
00164                 first_scene->scene = NULL;
00165                 first_scene->start_time = 0;
00166                 first_scene->blend = duration;
00167                 first_scene->end_time = blend_in;
00168         }
00169 
00170         if (first_scene == NULL)
00171         {
00172                 first_scene = new SceneList;
00173                 first_scene->next = NULL;
00174                 first_scene->blend = duration;
00175                 first_scene->start_time = 0;
00176                 first_scene->end_time = duration;
00177                 first_scene->scene = scene;
00178         }
00179         else
00180         {
00181                 current_scene = first_scene;
00182                 while (current_scene->next != NULL) current_scene = current_scene->next;
00183 
00184                 current_scene->next = new SceneListElem;
00185                 current_scene->next->next = NULL;
00186                 current_scene->next->blend = current_scene->end_time + duration - blend_in;
00187                 current_scene->next->start_time = current_scene->end_time - blend_in;
00188                 current_scene->next->end_time = current_scene->next->start_time + duration;
00189                 current_scene->blend = current_scene->next->start_time;
00190                 current_scene->next->scene = scene;
00191         }
00192 }
00193 
00194 void Demo::SwitchMonitor ()
00195 {
00196         monitoring_mode = !monitoring_mode;
00197         if (!monitoring_mode)
00198         {
00199                 // exit mode
00200                 last_measure_time = (int)glutGet (GLUT_ELAPSED_TIME);
00201                 glLightModelfv (GL_LIGHT_MODEL_AMBIENT, global_ambient_playback);
00202                 demo_playing = true;    
00203         }
00204         else
00205         {
00206                 // enter mode, set up the camera
00207                 current_scene->scene->CopyPosition (demo_time - current_scene->start_time, monitor_camera);
00208                 glLightModelfv (GL_LIGHT_MODEL_AMBIENT, global_ambient_monitor);
00209                 demo_playing = false;
00210         }
00211 }
00212 
00213 void Demo::SwitchPlayback ()
00214 {
00215         demo_playing = !demo_playing;
00216         if (demo_playing)
00217         {
00218                 last_measure_time = (int)glutGet (GLUT_ELAPSED_TIME);
00219         }
00220 }
00221 
00222 void Demo::UpdateTime ()
00223 {
00224         int current_measure_time;
00225 
00226         current_measure_time = (int)glutGet (GLUT_ELAPSED_TIME);
00227 
00228         // update demo time only if playback is on
00229         if (demo_playing)
00230         {
00231                 demo_time += current_measure_time - last_measure_time;
00232                 last_measure_time = current_measure_time;
00233         }
00234 
00235         // always update frame rate
00236         if (current_measure_time - last_frame_rate_time > 1000)
00237         {
00238                 frame_rate = incremental_rate;
00239                 incremental_rate = 0;
00240                 last_frame_rate_time += 1000;
00241 
00242                 if (!monitoring_mode)
00243                 {
00244                         sprintf (buffer, "%03d s, fps: %d", demo_time / 1000, frame_rate);
00245                         glutSetWindowTitle (buffer);
00246                 }
00247         }
00248         else incremental_rate ++;
00249 
00250         // update window title
00251         if (monitoring_mode)
00252         {
00253                 Position mon = monitor_camera->position->GetPosition (0);
00254                 sprintf (buffer, "time: %d, fps: %d, pos: {%g, %g, %g, %g, %g, %g}", demo_time, frame_rate, mon.x, mon.y, mon.z, mon.roll, mon.pitch, mon.yaw);
00255                 glutSetWindowTitle (buffer);
00256         }
00257 }
00258 
00259 void Demo::DisplayLoop ()
00260 {
00261         float ratio;
00262 
00263         UpdateTime ();
00264 
00265         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00266 
00267         if (current_scene != NULL)
00268         {
00269                 if (current_scene->end_time <= demo_time)
00270                 {current_scene = current_scene->next;}
00271 
00272                 if (current_scene != NULL)
00273                 {
00274                         if (current_scene->blend > demo_time)
00275                         {ratio = 1.0f;}
00276                         else
00277                         {ratio = 1 - (((float)(demo_time - current_scene->blend)) / ((float)(current_scene->end_time - current_scene->blend)));}
00278 
00279                         // if the ratio equals 1.0, we just have to render the current scene
00280                         if (ratio == 1.0f)
00281                         {
00282                                 if (current_scene->scene != NULL)
00283                                 {
00284                                         if (!monitoring_mode )
00285                                         {current_scene->scene->Render (demo_time - current_scene->start_time, culling_mode, level_of_detail_enabled);}
00286                                         else
00287                                         {current_scene->scene->Monitor (demo_time - current_scene->start_time, monitor_camera, culling_mode, level_of_detail_enabled);}
00288                                 }
00289                         }
00290                         else
00291                         {
00292                                 // if the ratio is below 1.0, we have to render this and the next scene.
00293                                 // We'll do this using the accumulation buffer.
00294                                 if (current_scene->scene != NULL)
00295                                 {
00296                                         if (!monitoring_mode)
00297                                         {current_scene->scene->Render (demo_time - current_scene->start_time, culling_mode, level_of_detail_enabled);}
00298                                         else
00299                                         {current_scene->scene->Monitor (demo_time - current_scene->start_time, monitor_camera, culling_mode, level_of_detail_enabled);}
00300                                 }
00301                                 glAccum (GL_LOAD, ratio);
00302                                 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00303 
00304                                 if (current_scene->next != NULL && current_scene->next->scene != NULL)
00305                                 {
00306                                         if (!monitoring_mode)
00307                                         {current_scene->next->scene->Render (demo_time - current_scene->next->start_time, culling_mode, level_of_detail_enabled);}
00308                                         else
00309                                         {current_scene->next->scene->Monitor (demo_time - current_scene->next->start_time, monitor_camera, culling_mode, level_of_detail_enabled);}
00310                                 }
00311 
00312                                 glAccum (GL_ACCUM, 1 - ratio);
00313                                 glAccum (GL_RETURN, 1.0f);
00314                         }
00315                 }
00316                 else
00317                 {
00318                         // demo is over, stop playback
00319                         demo_time = DEMO_NOT_YET_STARTED;
00320                         demo_playing = false;
00321                         if (fullscreen_enabled) 
00322                         {
00323                                 glutLeaveGameMode ();
00324                                 exit (0);
00325                         }
00326                 }
00327         }
00328 
00329         glutSwapBuffers ();
00330 }
00331 
00332 void Demo::IdleLoop ()
00333 {
00334         // Just post a redisplay
00335         glutPostRedisplay ();
00336 }
00337 
00338 void Demo::Reshape (int w, int h)
00339 {
00340         glViewport (0, 0, w, h);
00341 }
00342 
00343 void Demo::Keyboard (unsigned char key, int x, int y)
00344 {
00345         switch (key)
00346         {
00347                 // switch monitoring mode
00348                 case 'm':               if (demo_time != DEMO_NOT_YET_STARTED)
00349                                                 {SwitchMonitor ();}
00350                                                 printf ("Switched Monitor Mode\n");
00351                                                 break;
00352                 // switch playback on/off
00353                 case 'p':               if (demo_time != DEMO_NOT_YET_STARTED)
00354                                                 {SwitchPlayback ();}
00355                                                 printf ("Switched Playback Mode\n");
00356                                                 break;
00357                 // change view frustum culling mode
00358                 case 'c':               switch (culling_mode)
00359                                                 {
00360                                                         case C_BOUNDING_BOX:    culling_mode = C_SPHERE;
00361                                                                                                         printf ("View frustum culling mode set to: sphere\n");
00362                                                                                                         break;
00363                                                         case C_SPHERE:                  culling_mode = C_MIXED;
00364                                                                                                         printf ("View frustum culling mode set to: mixed\n");
00365                                                                                                         break;  
00366                                                         case C_MIXED:                   culling_mode = C_NONE;
00367                                                                                                         printf ("View frustum culling disabled\n");
00368                                                                                                         break;
00369                                                         case C_NONE:                    culling_mode = C_BOUNDING_BOX;
00370                                                                                                         printf ("View frustum culling mode set to: bounding box\n");
00371                                                                                                         break;
00372                                                 }
00373                                                 break;
00374                 // switch level of detail on/off
00375                 case 'l':               level_of_detail_enabled = !level_of_detail_enabled;
00376                                                 if (level_of_detail_enabled)
00377                                                 {printf ("Level of detail is now ENABLED\n");}
00378                                                 else
00379                                                 {printf ("Level of detail is now DISABLED\n");}
00380                                                 break;
00381                 // DELETE shifts the camera to the left
00382                 case 127:               if (monitoring_mode)
00383                                                 {monitor_camera->MoveRight (DELTA_Y);}
00384                                                 break;
00385                 // ESC key leaves fullscreen mode
00386                 case 27:                if (fullscreen_enabled)
00387                                                 {
00388                                                         glutLeaveGameMode ();
00389                                                         exit (0);
00390                                                 }
00391                                                 break;
00392                 // default behaviour
00393                 default:        printf ("key does nothing\n");
00394         }
00395 }
00396 
00397 void Demo::KeyboardSpecial (int key, int x, int y)
00398 {
00399         Position p;
00400 
00401         switch (key)
00402         {
00403                 // HOME moves the camera forward
00404                 case GLUT_KEY_HOME:                     if (monitoring_mode)
00405                                                                         {monitor_camera->MoveForward (DELTA_X);}
00406                                                                         break;
00407                 // END moves the camera backward
00408                 case GLUT_KEY_END:                      if (monitoring_mode)
00409                                                                         {monitor_camera->MoveForward (-DELTA_X);}
00410                                                                         break;
00411                 // PAGE DOWN shifts the camera to the right
00412                 case GLUT_KEY_PAGE_DOWN:        if (monitoring_mode)
00413                                                                         {monitor_camera->MoveRight (-DELTA_Y);}
00414                                                                         break;
00415                 // INSERT moves the camera up
00416                 case GLUT_KEY_INSERT:           if (monitoring_mode)
00417                                                                         {monitor_camera->MoveUp (DELTA_Z);}
00418                                                                         break;
00419                 // PAGE UP moves the camera down
00420                 case GLUT_KEY_PAGE_UP:          if (monitoring_mode)
00421                                                                         {monitor_camera->MoveUp (-DELTA_Z);}
00422                                                                         break;
00423                 // up increases pitch
00424                 case GLUT_KEY_UP:                       if (monitoring_mode)
00425                                                                         {
00426                                                                                 p = monitor_camera->position->GetPosition (0);
00427                                                                                 monitor_camera->position->SetConstantPosition (p.x, p.y, p.z, p.roll, p.pitch + DELTA_PITCH, p.yaw);
00428                                                                         }
00429                                                                         break;
00430                 // down decreases pitch
00431                 case GLUT_KEY_DOWN:                     if (monitoring_mode)
00432                                                                         {
00433                                                                                 p = monitor_camera->position->GetPosition (0);
00434                                                                                 monitor_camera->position->SetConstantPosition (p.x, p.y, p.z, p.roll, p.pitch - DELTA_PITCH, p.yaw);
00435                                                                         }
00436                                                                         break;
00437                 // left increases yaw
00438                 case GLUT_KEY_LEFT:                     if (monitoring_mode)
00439                                                                         {
00440                                                                                 p = monitor_camera->position->GetPosition (0);
00441                                                                                 monitor_camera->position->SetConstantPosition (p.x, p.y, p.z, p.roll, p.pitch, p.yaw + DELTA_YAW);
00442                                                                         }
00443                                                                         break;
00444                 // right decreases yaw
00445                 case GLUT_KEY_RIGHT:            if (monitoring_mode)
00446                                                                         {
00447                                                                                 p = monitor_camera->position->GetPosition (0);
00448                                                                                 monitor_camera->position->SetConstantPosition (p.x, p.y, p.z, p.roll, p.pitch, p.yaw - DELTA_YAW);
00449                                                                         }
00450                                                                         break;
00451                 // default behaviour
00452                 default:                                        printf ("special key does nothing\n");
00453         }
00454 }
00455 
00456 void Demo::SetGlobalAmbientPlayback (float red, float green, float blue, float alpha)
00457 {
00458         global_ambient_playback[0] = red;
00459         global_ambient_playback[1] = green;
00460         global_ambient_playback[2] = blue;
00461         global_ambient_playback[3] = alpha;
00462 }
00463 
00464 void Demo::SetGlobalAmbientMonitor (float red, float green, float blue, float alpha)
00465 {
00466         global_ambient_monitor[0] = red;
00467         global_ambient_monitor[1] = green;
00468         global_ambient_monitor[2] = blue;
00469         global_ambient_monitor[3] = alpha;
00470 }
00471 
00472 void Demo::SetGlobalSpecularReflection (float red, float green, float blue, float alpha)
00473 {
00474         global_specular_reflection[0] = red;
00475         global_specular_reflection[1] = green;
00476         global_specular_reflection[2] = blue;
00477         global_specular_reflection[3] = alpha;
00478 }
00479 
00480 void Demo::SetGlobalShininess (int shininess_)
00481 {
00482         global_shininess = shininess_;
00483 }
00484 
00485 Demo * Demo::current_demo = NULL;
00486 
00487 void Demo::static_display ()
00488 {
00489         if (Demo::current_demo != NULL) Demo::current_demo->DisplayLoop ();
00490 }
00491 
00492 void Demo::static_idle ()
00493 {
00494         if (Demo::current_demo != NULL) Demo::current_demo->IdleLoop ();
00495 }
00496 
00497 void Demo::static_reshape (int w, int h)
00498 {
00499         if (Demo::current_demo != NULL) Demo::current_demo->Reshape (w, h);
00500 }
00501 
00502 void Demo::static_keyboard (unsigned char key, int x, int y)
00503 {
00504         if (Demo::current_demo != NULL) Demo::current_demo->Keyboard (key, x, y);
00505 }
00506 
00507 void Demo::static_keyboard_special (int key, int x, int y)
00508 {
00509         if (Demo::current_demo != NULL) Demo::current_demo->KeyboardSpecial (key, x, y);
00510 }
00511 
00512 void Demo::PrintUsage ()
00513 {
00514         printf ("\n");
00515         printf ("Usage:\n");
00516         printf ("\n");
00517         printf ("windowed   mode: demo.exe [WIDTH HEIGHT]\n");
00518         printf ("fullscreen mode: demo.exe WIDTHxHEIGHT:BPP@REFRESHRATE\n");
00519         printf ("\n");
00520         printf ("Keys:\n");
00521         printf ("\n");
00522         printf ("[p]:       start/stop playback of the demo.\n");
00523         printf ("[m]:      enter/exit monitoring mode (see explanation below).\n");
00524         printf ("[c]:      switch between different view frustum culling modes.\n");
00525         printf ("              - none: no view frustum culling applied.\n");
00526         printf ("              - sphere: view frustum culling using bounding spheres.\n");
00527         printf ("              - bounding box: view frustum culling using bounding boxes.\n");
00528         printf ("              - mixed: view frustum culling using both bounding spheres\n                       and bounding boxes.\n");
00529         printf ("[l]:      turn level of detail on/off.\n");
00530         printf ("[LEFT]:    turn camera to the left during monitoring mode.\n");
00531         printf ("[RIGHT]:   turn camera to the right during monitoring mode.\n");
00532         printf ("[UP]:      turn camera upwards during monitoring mode.\n");
00533         printf ("[DOWN]:    turn camera downwards during monitoring mode.\n");
00534         printf ("[HOME]:    move camera forward during monitoring mode.\n");
00535         printf ("[END]:     move camera backwards during monitoring mode.\n");
00536         printf ("[DELETE]:  move camera to the left during monitoring mode.\n");
00537         printf ("[PGDN]:    move camera to the right during monitoring mode.\n");
00538         printf ("[INSERT]:  move camera upwards during monitoring mode.\n");
00539         printf ("[PGUP]:    move camera downwards during monitoring mode.\n");
00540         printf ("[ESCAPE]:  exit if in fullscreen mode.\n");
00541         printf ("\n");
00542         printf ("Monitoring mode:\n");
00543         printf ("\n");
00544         printf ("During monitoring mode, the camera may be moved around freely. The camera\n");
00545         printf ("which captures the scene as well as its viewing frustum are displayed along\n");
00546         printf ("with the bounding volumes of the objects. These volumes are colored\n");
00547         printf ("differently depending on the outcome of the view frustum culling test (red:\n");
00548         printf ("fully outside, green: fully inside, brown: partial). Please note that you can\n");
00549         printf ("always pause/resume playback of the scene at your own free will without leaving\n");
00550         printf ("monitoring mode.\n");
00551         printf ("\n");
00552         printf ("Note:\n");
00553         printf ("\n");
00554         printf ("The keys will only work if the DISPLAY WINDOW is activate. If this CONSOLE\n");
00555         printf ("WINDOW is active, nothing will happen.\n");
00556         printf ("\n");
00557 }

Generated on Sun Jul 2 13:20:39 2006 for Demo by  doxygen 1.4.6-NO