/*************************************************************************** File: main1A.cpp Created: 02/27/2001 Author: Maxim Garber Computer Science Department University of North Carolina - Chapel Hill garber@cs.unc.edu Description: Viewer and test app. for physically based modeling homework 2 ----------------------------------------------------------------------------. Copyright 2002 Maxim Garber UNC Collide Research Group *****************************************************************************/ #include "ODEMidpoint.h" #include "PBMProjectile.h" #include "PBMWall.h" #include "PBMSimScene.h" #include #include #include #include #include "vec3fv.hpp" #include "x_trimodel.hpp" // viewer GLVU glvu; // simulation scene PBMSimScene* scene; unsigned int numObjects = 0; bool runSimulation = 0; // projectile parameters PBMProjectileLaunchParams params; X_TriModel *geometry; PQP_Model *collisionGeometry; float colors[3]; enum IntegratorType{euler, midpoint, numIntergratorTypes}; IntegratorType integrator = euler; // timing bool fixedFrameSimulation = 0; clock_t lastTimeInstant; // used for idle function simulation int frameTime = 30; // in ms, used for fixed frame time simulation // lighting float lightPosition[4] = {10, 10, 10,1}; /***************************************************************************** FUNCTION : userDisplayFunc0 DESCRIPTION: Displays the hockey scene *****************************************************************************/ void userDisplayFunc0() { glvu.BeginFrame(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // draw scene scene->Draw(); glColor3f(1.0f, 1.0f, 1.0f); glvu.DrawFPS(); // print text parameters unsigned int textHeight = 100; Text(5, textHeight, "PARAMETERS:"); Text(5, textHeight-=15, "number of objects: %d", numObjects); Text(5, textHeight-=15, "new object speed: %00.0f m/s ", params.linVelocityMagnitude); if(integrator == euler) Text(5, textHeight-=15, "integrator: euler"); else if(integrator == midpoint) Text(5, textHeight-=15, "integrator: midpoint"); if(fixedFrameSimulation) Text(5, textHeight-=15, "time step: %f s", frameTime/1000.0f); else Text(5, textHeight-=15, "time step: 1 frame"); glvu.EndFrame(); } /***************************************************************************** FUNCTION : userIdleFunc0 DESCRIPTION: Update objects and post redisplay Called as often as possible *****************************************************************************/ void userIdleFunc0() { clock_t timeInstant = clock(); if(runSimulation) { float timeElapsed = (float) (timeInstant - lastTimeInstant) / CLOCKS_PER_SEC; if(timeElapsed > 0.03) timeElapsed = 0.03; scene->Update(timeElapsed); } lastTimeInstant = timeInstant; glutPostRedisplay(); } /***************************************************************************** FUNCTION : userTimerFunc0 DESCRIPTION: Update objects and post redisplay Called every frameTime milliseconds for fixed frame simulation *****************************************************************************/ void userTimerFunc0(int timeElapsed) { if(runSimulation) { scene->Update(frameTime / 1000.0f); } glutPostRedisplay(); if(fixedFrameSimulation) glutTimerFunc(frameTime,userTimerFunc0, timeElapsed+frameTime); } /***************************************************************************** FUNCTION : userKeyboardFunc0 DESCRIPTION: my keyboard handling ruitine *****************************************************************************/ void userKeyboardFunc0(unsigned char Key, int x, int y) { switch(Key) { // launch a projectile case 'f': { // pick some random direction float dir[4]; for(unsigned int i=0; i<4; i++) dir[i] = ((float)rand())/RAND_MAX; Normalize3fv(dir); Copy3fv(params.linVelocityDirection, dir); Copy3fv(params.angVelocity, dir); for(i=0; i<4;i++) params.rotation[i] = dir[i]; PBMProjectile* projectile = new PBMProjectile(geometry, collisionGeometry, params); scene->AddProjectile(projectile); projectile->SetColor(colors); numObjects++; break; } // run simulation case 's': runSimulation = !runSimulation; break; case ' ': // manual simulation time step if(fixedFrameSimulation) { scene->Update(frameTime / 1000.0f); } else { clock_t timeInstant = clock(); scene->Update((float) (timeInstant - lastTimeInstant) / CLOCKS_PER_SEC); lastTimeInstant = timeInstant; glutPostRedisplay(); } break; // change integrator case 'i': integrator = (IntegratorType) ((((int)integrator)+1)% (int) numIntergratorTypes); if(integrator == euler) params.integrator = EulerSolver::InstancePtr(); else if(integrator = midpoint) params.integrator = MidpointSolver::InstancePtr(); break; // print stats case 'p': { CollisionStats *stats = scene->GetCollisionStats(); printf("\nSTATS\n"); printf("Object Collisions: %d\n", stats->numObjectCollisions); printf("Object Collision Tests: %d\n", stats->numObjectCollisionTests); printf("Avg Object Collision Time: %f sec.\n", stats->objectCollisionTimer.GetAvgTime()); printf("Total Object Collision Time: %f sec.\n", stats->objectCollisionTimer.GetTime() ); printf("Wall Collisions: %d\n", stats->numWallCollisions); printf("Wall Collision Tests: %d\n", stats->numWallCollisionTests); printf("Avg Wall Collision Time: %f sec.\n", stats->wallCollisionTimer.GetAvgTime()); printf("Total Wall Collision Time: %f sec.\n", stats->wallCollisionTimer.GetTime() ); break; } // change fixed frame to variable rate simulation case 't': fixedFrameSimulation = !fixedFrameSimulation; if(fixedFrameSimulation) { // for fixed simulation speed glutTimerFunc(frameTime,userTimerFunc0, frameTime); glutIdleFunc(0); } else { // for fastest simulation speed glutIdleFunc(userIdleFunc0); } break; }; // CALL THE DEFAULT GLVU KEYBOARD HANDLER // as long as it doesn't add inertia if(Key != 'i') glvu.Keyboard(Key,x,y); glutPostRedisplay(); } /***************************************************************************** FUNCTION : userSpecialFunc0 DESCRIPTION: my special keyhandling ruitine *****************************************************************************/ void userSpecialFunc0(int Key, int x, int y) { float parameterIncrement = 1.0f; switch(Key) { // object velocity case GLUT_KEY_PAGE_UP: params.linVelocityMagnitude += parameterIncrement; break; case GLUT_KEY_PAGE_DOWN: params.linVelocityMagnitude -= parameterIncrement; break; case GLUT_KEY_F1: scene->EnableStats(!scene->GetEnableStats()); break; case GLUT_KEY_F2: scene->ResetStats(); } } /***************************************************************************** FUNCTION : Initialize DESCRIPTION: Initialize all objects in the scene *****************************************************************************/ void Initialize() { scene = new PBMSimScene(10, 10, 0.5); // set launch params Set3fv(params.position, 0, 0, 0); params.linVelocityMagnitude = 1; // instantiate 2 integrators MidpointSolver::Instantiate(); // set integrator to euler params.integrator = EulerSolver::InstancePtr(); // initialize projectile PBMProjectile* proj = new PBMProjectile("pumpkin_smallest.X", params); geometry = proj->GetGeometry(); collisionGeometry = proj->GetCollisionGeometry(); colors[0] = 0.8f; colors[1] = 0.4; colors[2] = 0.0; } /*********************************************************** ****************** FUNCTION : main DESCRIPTION: Init viewer and start main loop *****************************************************************************/ void main() { // initialize the viewer glvu.Init("Physically Based Modeling: Homework 1", GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA, // buffers 50,50,512,512); // screen position and size // remove inertia from camera model glvu.Keyboard('i',0,0); // initialize objects in scene Initialize(); // set openGL material and lighting state glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); glEnable(GL_COLOR_MATERIAL); glEnable(GL_DEPTH_TEST); glClearColor(0.5,0.6,0.8,0); // register callbacks glutDisplayFunc(userDisplayFunc0); glutKeyboardFunc(userKeyboardFunc0); glutSpecialFunc(userSpecialFunc0); if(fixedFrameSimulation) // for fixed simulation speed glutTimerFunc(frameTime,userTimerFunc0, frameTime); else // for fastest simulation speed glutIdleFunc(userIdleFunc0); // set camera position and projection parameters Vec3f ModelMin(-100,-100,-100), ModelMax(100,100,100), Eye(-10,5,0), LookAtCntr(0,0,0), Up(0,1,0); float Yfov = 45; float Aspect = 1; // width over height float Near = 0.001f; // near plane distance relative to model diagonal length float Far = 10000.0f; // far plane distance (also relative) glvu.SetAllCams(ModelMin,ModelMax, Eye,LookAtCntr,Up, Yfov,Aspect, Near,Far); // frame per second clock glvu.StartFPSClock(); lastTimeInstant = 0; // start event loop glutMainLoop(); // delete collision sphere delete(scene); }