////////////////////////////////////////////////////////////// // // // Project: SDL/OpenGL template // // Goal : just open a window with a valid OpenGL context // // Author : Achille Peternier, VRLab - EPFL, 2005 // // // ////////////////////////////////////////////////////////////// ////////////// // #INCLUDE // ////////////// #ifdef WIN32 #include <windows.h> // Only required under Windows :-D #endif #include <SDL.h> // This file import the SDL inteface #include <SDL/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 <string.h> #include <stdlib.h> #include <unistd.h> #include <string> #include <iostream> #include <fstream> #include <math.h> #ifdef WIN32 ///////////// // #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 "array.cpp" using namespace std; ///////////// // #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 #define DEBUG int debugct = 0; int firstprint = 1; #define DD() do { printf("DD:%d\n", debugct); debugct++;} while(0); #define DD1(x) while(firstprint) { printf("DD1: %d\n", x); firstprint = 0;}; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // CLASSES class Color { public: float r; float g; float b; Color(float _r, float _g, float _b) { r = _r; g = _g; b = _b; } void drawColor() { glColor4f(r, g, b, 1.0f); } Color* clone() { return new Color(r,g,b); } }; class Vec { public: float c[3]; Vec(float vx, float vy, float vz) { c[0] = vx; c[1] = vy; c[2] = vz; } Vec(Vec* v) { Vec(v->x(), v->y(), v->z()); } float x() { return c[0]; } float y() { return c[1]; } float z() { return c[2]; } float* getCoords() { return c; } Vec operator+(Vec* v) { return Vec(x() + v->x(), y() + v->y(), z() + v->z()); } Vec operator+(Vec v) { return Vec(x() + v.x(), y() + v.y(), z() + v.z()); } void add(Vec& a) { c[0] += a.x(); c[1] += a.y(); c[2] += a.z(); } Vec operator-(Vec& v) { return Vec(x() - v.x(), y() - v.y(), z() - v.z()); } Vec operator*(float s) { Vec r = Vec(x()*s, y()*s, z()*s); return r; } Vec operator*(Vec& s) { return Vec(x()*s.x(), y()*s.y(), z()*s.z()); } Vec operator/(float s) { return Vec(x()/s, y()/s, z()/s); } Vec cross(Vec* v) { return Vec(y() * v->z() - z() * v->y(), z() * v->x() - x() * v->z(), x() * v->y() - y() * v->x()); } Vec normalize() { return *this * (1 / length()); } float length() { return sqrt(x()*x()+y()*y()+z()*z()); } void print() { printf (" vektor: %f, %f, %f\n", x(), y(), z()); } Vec* clone() { return new Vec(x(), y(), z()); } }; class Poly { private: Array* initpoints; int size; Vec* position; Vec* rotation; Color* color; public: Poly(Array* _points) { Poly(_points, Color(1,1,1)); } Poly(Array* _points, Color _color) { size = _points->length(); position = new Vec(0,0,0); rotation = new Vec(0,0,0); color = _color.clone(); #ifdef DEBUG printf("new Poly(%d)\n", size); #endif initpoints = new Array(_points); setCenter(calcCenter()); } ~Poly() { delete position; delete rotation; delete color; delete initpoints; } /* * 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) { return Vec(atan2(v.y(), v.z()), atan2(v.x(), v.z()), atan2(v.y(), v.x())); } /* * calculate the center relative to all vertices. */ Vec calcCenter() { Vec s (0,0,0); Vec* t; initpoints->reset(); while ( t = (Vec*)initpoints->next() ) { s = s+*t; } return s / ((float)size); } /* * 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(); Vec* t; initpoints->reset(); while ( t = (Vec*)initpoints->next() ) { t->add(diff); } } //additional rotation in arcs void rotate(Vec rot) { rotation->add(rot); } Vec rotate_x(Vec& c) { Vec initrot = getInitRotation(c); Vec rot = initrot + *rotation; float r = Vec(0, c.y(), c.z()).length(); return Vec (c.x(), r*cos(rot.x()), r*sin(rot.x())); } Vec rotate_y(Vec& c) { Vec initrot = getInitRotation(c); Vec rot = initrot + *rotation; float r = Vec(c.x(), 0, c.z()).length(); return Vec (r*sin(rot.y()), c.y(), r*cos(rot.y())); } Vec rotate_z(Vec& c) { Vec initrot = getInitRotation(c); Vec rot = initrot + *rotation; float r = Vec(c.x(), c.y(), 0).length(); return Vec (r*cos(rot.z()), r*sin(rot.z()), c.z()); } void draw() { glBegin (GL_POLYGON); //Vec v1 = *((Vec*)initpoints->get(2)) - *((Vec*)initpoints->get(0)); //Vec v2 = *((Vec*)initpoints->get(1)) - *((Vec*)initpoints->get(0)); //glNormal3fv( v1.cross(v2)+ *(Vec*)((*initpoints)[0]).c ); //glNormal3fv( v1.cross(v2) + ((Vec*)initpoints->get(0))->c ); Vec* t; Vec* mv; initpoints->reset(); while ( (t = (Vec*)initpoints->next()) ) { color->drawColor(); Vec out = (*t - *position); out = rotate_x(out); out = rotate_y(out); out = rotate_z(out); mv = (*position + out).clone(); glVertex3fv(mv->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: Array* faces; Vec* position; Vec* rotation; public: Model(Array* _faces) { faces = new Array(*_faces); Vec c = calcCenter(); setCenter(c); rotation = new Vec(0,0,0); } ~Model() { delete position; delete rotation; delete faces; } void setCenter(Vec& c) { delete position; position = c.clone(); } Vec calcCenter() { Vec s(0,0,0); Poly* t; faces->reset(); while ( t = (Poly*)faces->next() ) { s = s + t->calcCenter(); } return s/((float)faces->length()); } void rotate(Vec rot) { rotation->add(rot); faces->reset(); Poly* t; while ( t = (Poly*)faces->next() ) { t->rotate(rot); } } void draw() { faces->reset(); Poly* t; while ( t = (Poly*)faces->next() ) { t->draw(); } } void addFace(Poly* face) { faces->push(face); } int numberOfFaces() { return faces->length(); } }; /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // GLOBAL VARS int MouseX, MouseY, OldMouseX, OldMouseY; bool MouseButtonRight, MouseButtonLeft; bool done = false; // Quit application when true const char* getNextToken(string& line) { if ( line.length() < 1 ) { return NULL; } 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.c_str(); } int getNextPoint(string& line) { const char* tch; tch = getNextToken(line); if ( tch == NULL ) { return -1; } return (int)atoi(tch); } float getNextCoord(string& line) { const char* tch; tch = getNextToken(line); if ( tch == NULL ) { return -1; } return (float)atof(tch); } Model* importModel(char* fname) { string line; ifstream fp; Array* points = new Array(); Array* tpoints = new Array(); Model* mm = new Model(new Array()); 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(new Vec(getNextCoord(line), getNextCoord(line), getNextCoord(line))); } if ( line[0] == 'f' ) { line.erase(0,1); tpoints->clear(); while ( (tp = getNextPoint(line)) > -1 ) { tpoints->push(points->get(tp-1)); } mm->addFace(new Poly(tpoints)); } } fp.close(); delete points; delete tpoints; 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 black (0,0,0); Color blue (0,0,1); 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); Vec* p0 = new Vec(0 ,0 ,0 ); Vec* p1 = new Vec(10,0 ,0 ); Vec* p2 = new Vec(10,10,0 ); Vec* p3 = new Vec(0 ,10,0 ); Vec* p4 = new Vec(0 ,0 ,10); Vec* p5 = new Vec(10,0 ,10); Vec* p6 = new Vec(10,10,10); Vec* p7 = new Vec(0 ,10,10); Vec cen (5,5,5); /* 4---7 |pp5| 4---0---3---7---4 |pp2|pp0|pp3|pp1| 5---1---2---6---5 |pp4| 5---6 */ Array* pp0 = new Array(); pp0->push(p0); pp0->push(p3); pp0->push(p2); pp0->push(p1); Array* pp1 = new Array(); pp1->push(p4); pp1->push(p5); pp1->push(p6); pp1->push(p7); Array* pp2 = new Array(); pp2->push(p4); pp2->push(p0); pp2->push(p1); pp2->push(p5); Array* pp3 = new Array(); pp3->push(p2); pp3->push(p3); pp3->push(p7); pp3->push(p6); Array* pp4 = new Array(); pp4->push(p1); pp4->push(p2); pp4->push(p6); pp4->push(p5); Array* pp5 = new Array(); pp5->push(p3); pp5->push(p0); pp5->push(p4); pp5->push(p7); Array* polys = new Array(); polys->push(new Poly(pp0, red)); polys->push(new Poly(pp1, green)); polys->push(new Poly(pp2, cyan)); polys->push(new Poly(pp3, blue)); polys->push(new Poly(pp4, yellow)); polys->push(new Poly(pp5, violet)); //Model* myModel = importModel("teapot.obj"); // printf("imported teapot.obj : %d faces\n", myModel->numberOfFaces()); Poly* t; polys->reset(); while ( t = (Poly*)polys->next() ) { //printf("polys %d setCenter\n", polys->pos()-1); t->setCenter(cen); } //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); polys->reset(); while ( t = (Poly*)polys->next() ) { t->draw(); t->rotate(Vec(0.0f, 0.01f, 0.01f)); } 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: usleep(2000); // 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; }