////////////////////////////////////////////////////////////// // // // Project: SDL/OpenGL template // // Goal : just open a window with a valid OpenGL context // // Author : Achille Peternier, VRLab - EPFL, 2005 // // // ////////////////////////////////////////////////////////////// ////////////// // #INCLUDE // ////////////// #include <windows.h> // Only required under Windows :-D #include <SDL.h> // This file import the SDL inteface #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 <math.h> ///////////// // #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") ///////////// // #DEFINE // ///////////// // 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 /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // CLASSES class Color { public: float r; float g; float b; Color(float _r, float _g, float _b) { r = _r; g = _g; b = _b; } void setColor() { printf("color: %f, %f, %f\n", r, g, b); glColor4f (r, g, b, 1.0f); } }; class Vec { public: float c[3]; Vec(float vx, float vy, float vz) { c[0] = vx; c[1] = vy; c[2] = vz; } float x() { return c[0]; } float y() { return c[1]; } float z() { return c[2]; } float* getCoords() { return c; } Vec(Vec* v) { Vec (v->c[0], v->c[1], v->c[2]); } Vec operator+(Vec v) { Vec r = Vec(c[0] + v.c[0], c[1] + v.c[1], c[2] + v.c[2]); return r; } void add(Vec a) { c[0] += a.c[0]; c[1] += a.c[1]; c[2] += a.c[2]; } Vec operator-(Vec v) { Vec r = Vec(c[0] - v.c[0], c[1] - v.c[1], c[2] - v.c[2]); return r; } Vec operator*(float s) { Vec r = Vec(c[0]*s, c[1]*s, c[2]*s); return r; } Vec operator*(Vec s) { Vec r = Vec(x()*s.x(), y()*s.y(), z()*s.z()); } Vec operator/(float s) { Vec r = Vec(c[0]/s, c[1]/s, c[2]/s); return r; } Vec* cross(Vec v) { Vec* r = new Vec(c[1] * v.c[2] - c[2] * v.c[1], c[2] * v.c[0] - c[0] * v.c[2], c[0] * v.c[1] - c[1] * v.c[0]); return r; } Vec normalize() { return *this * (1 / this->length()); } float length() { return sqrt(c[0]*c[0]+c[1]*c[1]+c[2]*c[2]); } void print() { printf (" vektor: %f, %f, %f\n", c[0], c[1], c[2]); }; Vec* clone() { return new Vec(c[0], c[1], c[2]); } }; class Poly { private: Vec** initpoints; //Vec* initrotation; int size; Vec* position; Vec* rotation; public: Poly(Vec** _points, int _size) { size = _size; initpoints = _points; //points = new Vec* [size]; //for (int v = 0; v < size; v++) { //create a copy of every point //points[v] = _points[v]->clone(); //} this->setCenter(this->calcCenter()); rotation = new Vec(0,0,0); } ~Poly() { delete position; delete rotation; } /* * set the position where the (rotation-)center of * the polygon is located */ void setCenter(Vec* c) { delete position; position = c->clone(); } /* * initial rotation relative to rotation center */ /* Vec getInitRotation(Vec* v) { Vec dir = (*position - *v); return Vec(atan2(dir.y(), dir.z()), atan2(dir.x(), dir.z()), atan2(dir.y(), dir.x())); }*/ Vec getSphereCoords(Vec* v) { Vec dir = (*position - *v); float bl = sqrt(dir.x()*dir.x()+dir.y()*dir.y()); return Vec(dir.length(), acos(dir.z()/dir.length()), atan2(dir.y(), dir.x())); } /* * calculate the center relative to all vertices. */ Vec* calcCenter() { Vec s (0,0,0); for (int i = 0; i < size; i++) { s = s+*initpoints[i]; } Vec* r = (s / ((float)size)).clone(); return r; } /* * reset the position of all vertices (ie. translate your * polygon to an absolute position) */ void setPosition(Vec* newcenter) { Vec diff = (*newcenter) - (*position); delete position; position = newcenter->clone(); for (int i = 0; i < size; i++) { initpoints[i]->add(diff); } } //additional rotation in arcs void rotate(Vec rot) { this->rotation->add(rot); } void draw() { glBegin (GL_POLYGON); //this->setNormal(); //col->setColor(); //printf("polygon: \n"); for (int v = 0; v < size; v++) { //initpoints[v]->print(); //glVertex3fv(initpoints[v]->c); } glEnd(); glBegin (GL_POLYGON); printf("polygonrotated: \n"); for (int v = 0; v < size; v++) { Vec dir = (*initpoints[v] - *position); Vec initrot = getSphereCoords(initpoints[v]); initrot.print(); Vec rot = initrot + *rotation; //initpoints[v]->print(); //printf("%f", initpoints[v]->z()); //TODO: WARNING: POLAR COORDINATES Vec out (rot.x() * sin(rot.y()) * cos(rot.z()), rot.x() * sin(rot.y()) * sin(rot.z()), rot.x() * cos(rot.y())); glVertex3fv((*position + out).c); } glEnd(); } }; /* * lightsource */ class Light { public: Vec* pos; Vec* dir; Light(Vec* _pos, Vec* _dir) { pos = _pos; dir = _dir; } void trace() { glBegin (GL_LINES); glVertex3fv(pos->getCoords()); glVertex3fv(dir->getCoords()); glEnd(); } void draw() { //printf(GL_LIGHT0); glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180.0f); float p [4] = {pos->x(), pos->y(), pos->z(), 1.0f}; float d [4] = {dir->x(), dir->y(), dir->z(), 1.0f}; glLightfv(GL_LIGHT0, GL_POSITION, p); glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, d); } }; class Model { private: Poly** faces; int size; Vec* position; Vec* rotation; public: Model(Poly** _faces, int _size) { size = _size; faces = _faces; this->setCenter(this->calcCenter()); rotation = new Vec(0,0,0); } ~Model() { delete position; delete rotation; } void setCenter(Vec* c) { delete position; position = c->clone(); } Vec* calcCenter() { Vec s(0,0,0); for ( int i = 0; i < size; i++ ) { s = s+*faces[i]->calcCenter(); } Vec* r = (s/((float)size)).clone(); return r; } void rotate(Vec rot) { this->rotation->add(rot); for ( int i = 0; i < size; i++ ) { faces[i]->rotate(rot); } } void draw() { for ( int i = 0; i <size; i++ ) { faces[i]->draw(); } } void addFace(Poly* face) { Poly** t = faces; size++; for ( int i = 0; i < size-1; i++ ) { faces[i] = t[i]; } faces[size-1] = face; } }; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // GLOBAL VARS int MouseX, MouseY, OldMouseX, OldMouseY; bool MouseButtonRight, MouseButtonLeft; bool done = false; // Quit application when true Model* importModel(char* fname) { FILE *fp; char lbuf[200]; char* buf2; int numpoints = 0; float tpf[3] = {0.0f, 0.0f, 0.0f}; int* tp = NULL; int tps = 0; int cp = 0; Vec** points; Vec** tpoints; Model* mm = new Model(NULL, 0); Poly* tpp; fp = fopen(fname, "r"); if ( fp == NULL ) { printf("Error reading file %s\n", fname); return NULL; } while( fgets(lbuf, sizeof(lbuf), fp) != NULL ) { buf2 = strtok(lbuf, " "); if ( buf2 == "v" ) { numpoints++; tpf[0] = (float)atof(strtok(lbuf, NULL)); tpf[1] = (float)atof(strtok(lbuf, NULL)); tpf[2] = (float)atof(strtok(lbuf, NULL)); points[numpoints-1] = new Vec(tpf[0], tpf[1], tpf[2]); } if ( buf2 == "f" ) { tps = 0; while ( (buf2 = strtok(lbuf, NULL)) != NULL ) { cp = atoi(buf2); tpoints[tps] = points[cp]->clone(); tps++; } tpp = new Poly(tpoints, tps); mm->addFace(tpp); } } fclose(fp); return mm; } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // 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 white (1,1,1); Color black (0,0,0); Color red (1,0,0); Color blue (0,0,1); Color green (0,1,0); Color yellow (1,1,0); Vec p0 (0 ,0 ,0 ); Vec p1 (10,0 ,0 ); Vec p2 (10,10,0 ); Vec p3 (0 ,10,0 ); Vec p4 (0 ,0 ,10); Vec p5 (10,0 ,10); Vec p6 (10,10,10); Vec p7 (0 ,10,10); /*Rect surf [SURFACE_COUNT] = { Rect (&p0, &p3, &p2, &p1, &red), Rect (&p4, &p5, &p6, &p7, &blue), Rect (&p4, &p0, &p1, &p5, &green), Rect (&p2, &p3, &p7, &p6, &yellow), Rect (&p1, &p2, &p6, &p5, &black), Rect (&p3, &p0, &p4, &p7, &white) };*/ Vec* pp0[4] = {&p0, &p3, &p2, &p1}; Vec* pp1[4] = {&p4, &p5, &p6, &p7}; Vec* pp2[4] = {&p4, &p0, &p1, &p5}; Vec* pp3[4] = {&p2, &p3, &p7, &p6}; Vec* pp4[4] = {&p1, &p2, &p6, &p5}; Vec* pp5[4] = {&p3, &p0, &p4, &p7}; Poly* polys [SURFACE_COUNT] = { new Poly(pp0, 4), new Poly(pp1, 4), new Poly(pp2, 4), new Poly(pp3, 4), new Poly(pp4, 4), new Poly(pp5, 4), }; Model* myModel = importModel("teapot.obj"); //Vec* pp [4] = {&p0, &p3, &p2, &p1}; //Poly poly0 (pp,4); //light info Vec pos0(10.0f, 12.0f, 15.0f); Vec dir0(5.0f, 5.0f, 5.0f); Light light0(&pos0, &dir0); // 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.5f, 1.0f); // correct clipping glEnable (GL_DEPTH_TEST); //enable light glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Mainloop: float deltay = 0.0f; float deltaz = 0.0f; float deltacolor = 0.0f; while (!done) { ///////////////////// // Do some rendering: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 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 // Place the viewer 50 units backward: glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0f, 0.0f, -50.0f); // Draw a rotating triangle: glRotatef(deltay, 0.0f, 1.0f, 0.0f); // Rotation around the Y axis glRotatef(deltaz, 1.0f, 0.0f, 0.0f); /* for (int i = 0; i < SURFACE_COUNT; i++) { polys[i]->draw(); polys[i]->rotate(Vec(0.0f, 0.01f, 0.01f)); }*/ //poly0.draw(); //poly0.rotate(Vec(0.0, 0.01, 0.01)); light0.draw(); light0.trace(); myModel->draw(); //////////////// // Check events: SDL_Event event; while (SDL_PollEvent(&event)) { // Quit by click on X: if (event.type == SDL_QUIT) done = true; } // Update mouse: OldMouseX = MouseX; OldMouseY = MouseY; unsigned buttons = SDL_GetMouseState(&MouseX, &MouseY); if (buttons&SDL_BUTTON(1)) MouseButtonLeft = true; else MouseButtonLeft = false; if (buttons&SDL_BUTTON(3)) // <-- Beware: may be 2 on mouses // without the middle button! MouseButtonRight = true; else MouseButtonRight = false; //if (MouseButtonLeft) // delta += 1.0f; // Update keyboard (used like a joypad): Uint8 *keystate = SDL_GetKeyState(NULL); if (keystate[SDLK_ESCAPE]) done = true; //background color if (keystate[SDLK_1]) glClearColor(0.5f, 0.0f, 0.0f, 1.0f); if (keystate[SDLK_2]) glClearColor(0.0f, 0.5f, 0.0f, 1.0f); if (keystate[SDLK_3]) glClearColor(0.0f, 0.0f, 0.5f, 1.0f); //scene rotation if (keystate[SDLK_LEFT]) deltay -= 2.0f; if (keystate[SDLK_RIGHT]) deltay += 2.0f; if (keystate[SDLK_UP]) deltaz -= 2.0f; if (keystate[SDLK_DOWN]) deltaz += 2.0f; //light rotation /* if (keystate[SDLK_a]) lightpos[0]+=lightdelta; if (keystate[SDLK_d]) lightpos[0]-=lightdelta; if (keystate[SDLK_w]) lightpos[1]+=lightdelta; if (keystate[SDLK_s]) lightpos[1]-=lightdelta; if (keystate[SDLK_q]) lightpos[2]+=lightdelta; if (keystate[SDLK_e]) lightpos[2]-=lightdelta; */ if (keystate[SDLK_SPACE]) { deltacolor += 0.01f; if (deltacolor > 1.0f) { deltacolor = 0.0f; } } //////////////// // Swap buffers: _sleep(20); // Just don't kill computer resources ;) SDL_GL_SwapBuffers(); // Plain stupid log, just to show values: //printf("X: %d, Y: %d, but1: %d, but2: %d\n", // MouseX, MouseY, MouseButtonLeft, MouseButtonRight); } // Ok, release everything and byebye: SDL_Quit(); return 0; } /* //DEPRECATED class Tri{ public: Vec *p[3]; Color *col; Vec *normal; Tri(Vec* p0, Vec* p1, Vec* p2, Color* c) { p[0] = p0; p[1] = p1; p[2] = p2; col = c; Vec v1 = (*p[1] - *p[0]); Vec v2 = (*p[2] - *p[0]); normal = (v1).cross(v2); } ~Tri() { delete normal; } void draw() { glBegin (GL_TRIANGLES); this->setNormal(); col->setColor(); for (int v = 0; v < 3; v++) { glVertex3f(p[v]->c[0], p[v]->c[1], p[v]->c[2]); } glEnd(); this->drawNormals(); this->print(); } void drawNormals() { for (int v = 0; v < 3; v++) { glBegin (GL_LINES); glVertex3f(p[v]->x(), p[v]->y(), p[v]->z()); //glVertex3fv(((*p[v])*scale).getCoords()); glVertex3f(p[v]->x() + this->normal->x(), p[v]->y() + this->normal->y(), p[v]->z() + this->normal->z()); //glVertex3fv(((*p[v])*scale + this->normal).getCoords()); glEnd(); } } void setNormal() { glNormal3fv(this->normal->getCoords()); } void print() { printf("triangle: \n"); for (int v = 0; v < 3; v++) { p[v]->print(); } printf("normal: "); normal->print(); printf("\n"); } }; //DEPRECATED class Rect { public: Tri* t1; Tri* t2; Rect(Vec* p1, Vec* p2, Vec* p3, Vec* p4, Color* c) { t1 = new Tri (p1, p2, p3, c); t2 = new Tri (p1, p3, p4, c); } ~Rect() { delete t1; delete t2; } void draw() { t1->draw(); t2->draw(); } }; */