/* TriWorld.cpp * * This file contains the program entry point, main, and initiallizes OpenGL. */ // Choose exactly 1 timing mode! //#define TURING #define WINDOWS //#define SLOW_WINDOWS #include #include #include #include #include "World.h" #include "Tuplex.h" #include "Error.h" #include "Camera.h" #include "Parser.h" #include using namespace std; // Screen size const int SCREEN_SIZE = 400; int height = SCREEN_SIZE; int width = SCREEN_SIZE; // Globals const string DEF_WORLD = "cityscape.wld"; World world; Parser parser; clock_t lastTick; // Enumeration for Menu enum { M_NONE, M_OPEN, M_EXIT }; // Function Prototypes void initOpenGL(); void display(void); void reshape(int w, int h); void idle(); //void menu(int value); void keyboard(unsigned char key, int x, int y); void mouse(int x, int y); /* main * * Program entry point. You know what it does... */ int main(int argc, char **argv) { // Initialize glut glutInit(&argc, argv); glutInitWindowSize(SCREEN_SIZE, SCREEN_SIZE); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutCreateWindow("Triangle World"); // Set up Right-Click Menu // glutCreateMenu(menu); // glutAddMenuEntry("Open File", M_OPEN); // glutAddMenuEntry("-----------------------", M_NONE); // glutAddMenuEntry("Exit", M_EXIT); // glutAttachMenu(GLUT_RIGHT_BUTTON); // Initalize OpenGL parameters initOpenGL(); // Register callback functions glutDisplayFunc(display); glutReshapeFunc(reshape); glutIdleFunc(idle); glutKeyboardFunc(keyboard); glutMotionFunc(mouse); // Initialize the timer lastTick = clock(); // Setup the world. (Has to be after initOpenGL). world.init(); parser.getFile(DEF_WORLD,&world); // Loop until something happens glutMainLoop(); return 0; } /* initOpenGL * * Initializes a few OpenGL parameters. */ void initOpenGL() { // Enable depth buffering glEnable(GL_DEPTH_TEST); // Turn off back face drawing // glCall(GL_BACK); // ***** // Initialize background color to black glClearColor(0.015,0,.25,0); } /* idle * * Called every chance that glut gets. We'll implement a timer in this * function to handle all time-dependant tasks (such as moving the ball). */ void idle() { clock_t tick = clock(); if (!world.gameOver()) { #ifdef TURING world.timeStep(0.01); /* For Turing */ #endif #ifdef WINDOWS world.timeStep(double(tick - lastTick) / 1000.0); /* For Windows */ #endif #ifdef SLOW_WINDOWS world.timeStep(double(tick - lastTick) / 10000.0); /* For Windows */ #endif lastTick = tick; } else { if (double(tick - lastTick) / 1000.0 > 0.02) { Triangle::enlarge(); lastTick = tick; } } glutPostRedisplay(); } /* display * * In charge of drawing the screen by telling the ball and each of the * triangles to draw themselves. */ void display() { // Clear buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset transform matrix glLoadIdentity(); world.draw(); // Swap buffers glutSwapBuffers(); } /* reshape * * Called whenever the user resizes the graphics window. In this function * we'll make sure that the draw image doesn't get deformed and is more or * less centered. */ void reshape(int w, int h) { if (w < h) glViewport((w - h) / 2, 0, h, h); else glViewport(0, (h - w) / 2, w, w); width = w; height = h; lastTick = clock(); // resync timer } ///* menu // * // */ //void menu(int value) //{ // string cmd; // // switch(value) // { // case M_EXIT: // exit(0); // break; // case M_OPEN: // //***** // /* // cout << "Please enter filename of input file.\n-> "; // cin >> cmd; // world.reconfigure(cmd); // */ // parser.loadFile(&world); // break; // default: // cerr << "Invalid Menu argument: " << value << endl; // break; // } // lastTick = clock(); // resync timer //} /* keyboard * * This function will load a input file. If the user presses any key, he is prompted * to type in the filename of an input file. This file is then parsed and, pending * errors encountered while parsing, adds the required vertices, triangles and edges * to the World. * * A later refinement might be to have a load key 'l' that prompts for the filename, * freeing up all the other keys for other functionality. */ void keyboard(unsigned char key, int x, int y) { //printf("Key = %d\n", key); // ***** // surpress unused variable warnings (void)x; (void)y; switch(key) { case ' ': world.swing(); break; case 'I': case 'i': world.lightToggle(); break; case '_': case '-': world.camera.zoomOut(); cout << "Camera: Zooming out\n"; break; case '=': case '+': world.camera.zoomIn(); cout << "Camera: Zooming in\n"; break; case 'W': case 'w': world.camera.moveForward(); cout << "Camera: Forward\n"; break; case 'S': case 's': world.camera.moveBackward(); cout << "Camera: Backward\n"; break; case 'A': case 'a': world.camera.moveLeft(); cout << "Camera: Left\n"; break; case 'D': case 'd': world.camera.moveRight(); cout << "Camera: Right\n"; break; case 'V': case 'v': world.camera.moveUp(); cout << "Camera: Up\n"; break; case 'C': case 'c': world.camera.moveDown(); cout << "Camera: Down\n"; break; case 'X': case 'x': world.camera.axesToggle(); cout << "Axes " << (world.camera.axes() ? "On" : "Off") << endl; break; case 'B': case 'b': (world.camera.tracking()) ? world.camera.track(NULL) : world.camera.track(world.pBallPosition()); break; case 'P': case 'p': parser.cycleVerbosity(); break; case 'O': case 'o': world.rollDebugToggle(); break; case 'n': cout << "Ball At: " << *(world.pBallPosition()) << endl; break; case 'N': world.ballDebugToggle(); break; case 'L': case 'l': parser.loadFile(&world); break; case '\\': Triangle::toggleCrazyTris(); break; case '[': Triangle::enlarge(); break; case ']': Triangle::shrink(); break; default: cout << "i - toggles lights\n" << "b - toggles ball follow\n" << "+/- - zooms in/out\n" << " w v\n" << "asd c - move the view (when not following ball)\n" << "x - toggles axes\n" << "p - cycles parsing verbosity\n" << "o - toggle collision/rolling/stop notifications\n" << "n - output ball's position\n" << "N - toggle constand Ball updates\n" << "l - loads a file\n" << "\"\\\" - toggle triangle resize\n" << "[ / ] - separate/conjoin triangles\n" << endl; break; } lastTick = clock(); // resync timer } void mouse(int x, int y) { world.camera.rotate(x,y,width,height); }