//////////////////////////////////////////////////////////////
// //
// 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/sample.obj";
//char* modelfile = "obj/untitled.obj";
//char* modelfile = "obj/teapot.obj";
char* modelfile = "obj/castle.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;
}