////////////////////////////////////////////////////////////// // // // Project: SDL/OpenGL template // // Goal : just open a window with a valid OpenGL context // // Author : Achille Peternier, VRLab - EPFL, 2005 // // // ////////////////////////////////////////////////////////////// ////////////// // #INCLUDE // ////////////// #ifndef UNIX #include <windows.h> // Only required under Windows :-D #endif #ifndef UNIX #include <SDL.h> // This file import the SDL inteface #else #include <SDL/SDL.h> // This file import the SDL inteface #endif #include <GL/gl.h> // This file import the OpenGL interface #include <GL/glu.h> // This file offers some OpenGL-related utilities #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <string> #include <iostream> #include <fstream> #include <math.h> #ifndef UNIX ///////////// // #PRAGMA // ///////////// // Visual Studio specific: you can import libraries directly by // specifing them through a #pragma. On other compilters/platforms add // the required .lib to the makefile or project proprieties #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glu32.lib") #pragma comment(lib, "sdl.lib") #pragma comment(lib, "sdlmain.lib") #endif #include "vec.h" #include "material.h" #include "color.h" #include "thing.h" #include "poly.h" #include "model.h" #include "glumodel.h" #include "animation.h" #include "light.h" using namespace std; // Constants hardcoded during compilation #define WINDOW_TITLE "the cube" #define WINDOW_X 800 // Window width #define WINDOW_Y 600 // Window height #define WINDOW_COLORDEPTH 32 // Color depth (in bits) #define WINDOW_ZETADEPTH 24 // z-buffer depth (in bits) #define SURFACE_COUNT 6 #define PI 3.14159265f int debugct = 0; #define DD() do { printf("DD:%d\n", debugct); debugct++;} while(0); #ifndef UNIX #define mysleep(x) do {Sleep(x/100);} while (0); #else #define mysleep(x) do {usleep(x);} while (0); #endif /////////////////////////////////////////////////////////////////////////// // GLOBAL VARS int MouseX, MouseY, OldMouseX, OldMouseY; bool MouseButtonRight, MouseButtonLeft; bool done = false; // Quit application when true string getNextToken(string& line) { if ( line.length() < 1 ) { return ""; } string mp; while ( line[0] == ' ' ) { line.erase(0, 1); } int np = line.find(" ", 0); if ( (unsigned int)np == string::npos ) { np = line.length(); } mp = line.substr(0, np); line.erase(0, np); return mp; } int getNextPoint(string& line) { string tch; int sp; tch = getNextToken(line); if ( tch == "" ) { return -1; } if ( (unsigned int)(sp = tch.find("/", 0)) != string::npos ) { tch.erase(sp); } return (int)atoi(tch.c_str()); } float getNextCoord(string& line) { const char* tch; tch = getNextToken(line).c_str(); if ( tch == "" ) { return -1; } return (float)atof(tch); } Model* importModel(char* fname) { string line; ifstream fp; std::vector<Vec*> points; Model* mm = new Model(); Poly* tpoly; int tp = -1; fp.open(fname); if ( ! fp.is_open()) { printf("Error reading file %s\n", fname); return mm; } while ( !fp.eof() ) { getline(fp, line); if ( line[0] == 'v' ) { line.erase(0,1); points.push_back(new Vec(getNextCoord(line), getNextCoord(line), getNextCoord(line))); } if ( line[0] == 'f' ) { line.erase(0,1); tpoly = new Poly(); while ( (tp = getNextPoint(line)) > -1 ) { tpoly->addPoint(points.at(tp-1)); } mm->addFace(tpoly); } } fp.close(); return mm; } void drawFog(GLuint filter) { GLuint fogMode[]= { GL_EXP, GL_EXP2, GL_LINEAR }; // Storage For Three Types Of Fog GLfloat fogColor[4]= {0.8f, 0.3f, 0.6f, 1.0f}; // Fog Color glFogi(GL_FOG_MODE, fogMode[filter]); // Fog Mode glFogfv(GL_FOG_COLOR, fogColor); // Set Fog Color glFogf(GL_FOG_DENSITY, 0.35f); // How Dense Will The Fog Be glHint(GL_FOG_HINT, GL_DONT_CARE); // Fog Hint Value glFogf(GL_FOG_START, 1.0f); // Fog Start Depth glFogf(GL_FOG_END, 5.0f); // Fog End Depth glEnable(GL_FOG); // Enables GL_FOG } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // MAIN // int main( int argc, char **argv ) { // Initialize SDL: if (SDL_Init(SDL_INIT_VIDEO) == -1) { printf("ERROR: unable to init SDL!\n"); return 1; } Color blue (0,0,1); Color black (0,0,0); Color red (1,0,0); Color violet (1,0,1); Color yellow (1,1,0); Color white (1,1,1); Color green (0,1,0); Color cyan (0,1,1); Color grey (0.5f,0.5f,0.5f); Vec initPos = Vec(0.0f, 0.0f, 0.0f); Vec initRot = Vec(0.0f, 0.0f, 0.0f); View* myView = new View(initPos, initRot); UserAnimation* userAnim = new UserAnimation(); userAnim->init(); userAnim->addThing((Thing*)myView); userAnim->addColor(&black); userAnim->addColor(&blue); userAnim->addColor(&red); userAnim->addColor(&violet); userAnim->addColor(&yellow); userAnim->addColor(&white); userAnim->addColor(&green); userAnim->addColor(&cyan); userAnim->addColor(&grey); std::vector<Animation*> anims; anims.push_back((Animation*)userAnim); int renderMode = 0; int fog = 3; GluSphere mysphere (Vec(0,-50,0), Material(Color(1,1,0)), 50); KochFractal* kochfrac = new KochFractal(Vec(0,0,0), 3, 30); userAnim->addThing((Thing*)kochfrac); SierpinskiPyramid* myfrac = new SierpinskiPyramid(Vec(-7,10,-7), 4, 15); userAnim->addThing((Thing*)myfrac); /* begin cube */ Vec* ulh = new Vec(0 ,0 ,0 ); Vec* ulv = new Vec(0 ,0 ,10); Vec* urv = new Vec(10,0 ,10); Vec* urh = new Vec(10,0 ,0 ); Vec* olh = new Vec(0 ,10,0 ); Vec* olv = new Vec(0 ,10,10); Vec* orv = new Vec(10,10,10); Vec* orh = new Vec(10,10,0 ); Vec cubePos (5,0,5); Vec cubeCen (5,5,5); Model* cube = new Model(); std::vector<Vec*> bottom; std::vector<Vec*> left; std::vector<Vec*> right; std::vector<Vec*> top; std::vector<Vec*> rear; std::vector<Vec*> front; bottom.push_back(ulh); bottom.push_back(urh); bottom.push_back(urv); bottom.push_back(ulv); left.push_back(ulh); left.push_back(ulv); left.push_back(olv); left.push_back(olh); right.push_back(urh); right.push_back(orh); right.push_back(orv); right.push_back(urv); top.push_back(olh); top.push_back(olv); top.push_back(orv); top.push_back(orh); rear.push_back(ulh); rear.push_back(olh); rear.push_back(orh); rear.push_back(urh); front.push_back(ulv); front.push_back(urv); front.push_back(orv); front.push_back(olv); cube->addFace(new Poly(bottom, red)); cube->addFace(new Poly(left, green)); cube->addFace(new Poly(right, cyan)); cube->addFace(new Poly(top, blue)); cube->addFace(new Poly(rear, yellow)); cube->addFace(new Poly(front, white)); printf("cube ok\n"); cube->setPosition(cubePos); //cube->setCenter(cubeCen); userAnim->addThing((Thing*)cube); cube->setDelta(PI/2.0); /* end cube */ /* begin import */ //char* modelfile = "obj/sample2.obj"; char* modelfile = "obj/shuttle.obj"; //char* modelfile = "obj/sample2.obj"; //char* modelfile = "obj/sample.obj"; //char* modelfile = "obj/untitled.obj"; //char* modelfile = "obj/teapot.obj"; //char* modelfile = "obj/castle.obj"; //char* modelfile = "obj/chaiselongue.obj"; Model* myModel = importModel(modelfile); printf("imported %s : %d faces\n", modelfile, myModel->numFaces()); Vec myCen = Vec(5,-10,5); myModel->setCenter(myCen); myModel->setMaterial(Color(1,0,1), Color(1,0,1)); myModel->setPosition(myCen); //myModel->showNormals(); myModel->setDelta(PI/2.0); userAnim->addThing((Thing*)myModel); //myModel->vardump(""); /* end import */ // Prepare configuration: int bitsPerColor = 8; if (WINDOW_COLORDEPTH == 16) { bitsPerColor = 5; } SDL_GL_SetAttribute(SDL_GL_RED_SIZE, bitsPerColor); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, bitsPerColor); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, bitsPerColor); SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0); SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0); SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0); SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0); if (WINDOW_COLORDEPTH == 32) { SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); } else { SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); } SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, WINDOW_ZETADEPTH); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Create surface: unsigned flags = SDL_OPENGL; SDL_WM_SetCaption(WINDOW_TITLE, NULL); if (SDL_SetVideoMode(WINDOW_X, WINDOW_Y, WINDOW_COLORDEPTH, flags) == NULL ) { printf("ERROR: unsupported video configuration!\n"); return 1; } // Ok, SDL up with a valid OpenGL context! // Now setup some OpenGL parameter: // Clear background with a darkblue color glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // correct clipping glEnable (GL_DEPTH_TEST); //enable light glEnable(GL_LIGHTING); glFrontFace(GL_CCW); GLfloat global_ambient[] = { 0.3f, 0.3f, 0.3f, 1.0f }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient); //light info //Color l0_col(0.1f, 0.1f, 0.1f); //AmbientLight light0(l0_col, GL_LIGHT0); SpotLight light0(GL_LIGHT0, Vec (0, 50, 0), Material(Color(0.5,0.5,0.5), //Color(0.5,0.5,0.5), Color(1,1,1)), 90); Light light1(GL_LIGHT1, Vec (20, 20, 20), Material(Color(0.5,0.5,0.5), Color(0,0,0))); userAnim->addThing((Thing*)(&light0)); userAnim->addThing((Thing*)(&light1)); StaticAnimation* l0Anim = new StaticAnimation(); l0Anim->init(); anims.push_back((Animation*)l0Anim); l0Anim->addThing((Thing*)(&light0)); l0Anim->setRot(Vec(1,0,0)); //Vec l1_pos(-10.0f, -10.0f, -10.0f); //Color l1_col(0.0f, 0.5f, 1.0f); //DiffuseLight light1(l1_pos, l1_col, GL_LIGHT1); //glEnable(GL_COLOR_MATERIAL); /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Mainloop: float deltacolor = 0.0f; int react_keyevent = 0; float viewerMovingSpeed = 1.0f; ThingGroup* rotatingCubes = new ThingGroup(); Model* t; Color* tc; for ( int i = 0; i < 50; i++ ) { t = cube->clone(); t->rotate(Vec(i*5.0f, 0.0f, 0.0f)); t->setPosition(new Vec(200.0f*cos(((float)i)*PI/50.0f), 0.0f, 200.0f*sin(((float)i)*PI/50.0f))); t->scale(pow(1.02f, i)); tc = new Color(i*0.02f, 1.0f, 1.0f-i*0.02f); t->setColor(tc); rotatingCubes->addThing((Thing*)t); } for ( int i = 0; i < 50; i++ ) { t = cube->clone(); t->rotate(Vec(i*-5.0f, 0.0f, 0.0f)); t->scale(pow(0.98f, i)); t->setPosition(new Vec(200.0f*cos(((float)-i)*PI/50.0f), 0.0f, 200.0f*sin(((float)-i)*PI/50.0f))); tc = new Color(i*0.02f, 1.0f-i*0.02f, 1.0f-i*0.02f); t->setColor(tc); rotatingCubes->addThing((Thing*)t); } userAnim->addThing((Thing*)rotatingCubes); StaticAnimation* l1Anim = new StaticAnimation(); l1Anim->init(); anims.push_back((Animation*)l1Anim); l1Anim->addThing((Thing*)rotatingCubes); l1Anim->setRot(Vec(1.5f,0,0)); //Vec l1_pos(-10.0f, -10.0f, -10.0f); cube->showNormals(); float delta = 0; while (!done) { delta += 1; ///////////////////// // Do some rendering: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); switch ( renderMode ) { case 0: /* smooth */ glShadeModel(GL_SMOOTH); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break; case 1: /* linear */ glShadeModel(GL_LINEAR); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break; case 2: /* flat */ glShadeModel(GL_FLAT); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break; case 3: /* wireframe */ glShadeModel(GL_SMOOTH); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break; } // Setup a perspective view: glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, // Field of view WINDOW_X/WINDOW_Y, // width/height ratio 1.0f, // near clipping plane 1000.0f); // far clipping plane // move viewer myView->draw(); glMatrixMode(GL_MODELVIEW); //initial viewer position glLoadIdentity(); //draw lights light0.draw(); light1.draw(); //glTranslatef(0,0,-50); /* do animations */ for ( std::vector<Animation*>::size_type anim_ct = 0; anim_ct < anims.size(); anim_ct++ ) { ((Animation*)anims.at(anim_ct))->tick(); } rotatingCubes->draw(); // //xy plane // glBegin(GL_TRIANGLES); // glNormal3f(0,0,1); // glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue.v()); // glVertex3f(0,0,0); // //glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue.v()); // glVertex3f(10,0,0); // //glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red.v()); // glVertex3f(0,10,0); // glEnd(); // //xz plane // glBegin(GL_TRIANGLES); // glNormal3f(0,1,0); // glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue.v()); // glVertex3f(0,0,0); // //glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue.v()); // glVertex3f(30,0,0); // //glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green.v()); // glVertex3f(0,0,30); // glEnd(); //draw sphere //mysphere.draw(); myfrac->draw(); kochfrac->draw(); //draw cube //cube->draw(); //draw imported model myModel->draw(); //////////////// // Check events: SDL_Event event; while (SDL_PollEvent(&event)) { // Quit by click on X: if (event.type == SDL_QUIT) { done = true; } } // Update keyboard (used like a joypad): Uint8 *keystate = SDL_GetKeyState(NULL); if (keystate[SDLK_ESCAPE]) { done = true; } //allow to hit keys only every few frames. if (react_keyevent == 0) { react_keyevent = 10; if ( keystate[SDLK_g] ) { renderMode++; renderMode = renderMode % 4; printf("Changed render mode to %d.\n", renderMode); } else { react_keyevent = 0; } } else { react_keyevent -= 1; } if ( keystate[SDLK_z] ) { fog++; fog = fog % 4; printf("fog %d\n", fog); } if ( fog < 3 ) { drawFog(fog); } // speed if ( keystate[SDLK_LSHIFT] || keystate[SDLK_RSHIFT] ) { viewerMovingSpeed = 10.0f; } else { viewerMovingSpeed = 1.0f; } if (keystate[SDLK_SPACE]) { deltacolor += 0.01f; if (deltacolor > 1.0f) { deltacolor = 0.0f; } } glFlush(); //////////////// // Swap buffers: mysleep(2000); // Just don't kill computer resources ;) SDL_GL_SwapBuffers(); } // Ok, release everything and byebye: SDL_Quit(); return 0; }