//////////////////////////////////////////////////////////////
// //
// 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();
}
};
*/