Newer
Older
cg / sources / main.cpp
@glproj03 glproj03 on 9 Feb 2006 14 KB Added castle
//////////////////////////////////////////////////////////////
//                                                          //
// 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;
}