Newer
Older
cg / sources / main.cpp
@glproj03 glproj03 on 1 Feb 2006 13 KB added material
//////////////////////////////////////////////////////////////
//                                                          //
// 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 "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;
	}

	// current viewport position
	Vec viewer_pos = Vec(0.0f, 0.0f, -50.0f);

	// viewport movement delta
	Vec viewer_zmove_pos = Vec(0.0f, 0.0f, -0.3f);
	Vec viewer_zmove_neg = Vec(0.0f, 0.0f, 0.5f);
	Vec viewer_xmove_pos = Vec(0.3f, 0.0f, 0.0f);
	Vec viewer_xmove_neg = Vec(-0.3f, 0.0f, 0.0f);

	// current viewport rotation
	Vec viewer_rot = Vec(0.0f, 0.0f, 0.0f);

	// viewport rotation delta
	Vec viewer_zrot = Vec (0.0f, 0.0f, 2.0f);
	Vec viewer_yrot = Vec (0.0f, 2.0f, 0.0f);
	Vec viewer_xrot = Vec (2.0f, 0.0f, 0.0f);

	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);
	Color grey   (0.5f,0.5f,0.5f);

	Vec initPos = Vec(30.0f, -30.0f, -30.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<Model*> models;

	std::vector<Animation*> anims;

	anims.push_back((Animation*)userAnim);

	bool wireframe = false;

	int fog = 3;

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

	//cube->showNormals();
	
	/* end cube */

	//models.push_back(cube);

	/* begin import */
	char* modelfile = "obj/sample2.obj";
	//char* modelfile = "obj/sample.obj";
	//char* modelfile = "obj/untitled.obj";
	//char* modelfile = "obj/teapot.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 */
	
	//models.push_back(myModel);
	
	// 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);
	
	GLfloat global_ambient[] = { 0.1f, 0.1f, 0.1f, 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);
	//Color l0_col(0.3f, 0.3f, 0.3f);
	//Vec l0_pos(0.0f, 10.0f, 10.0f);
	//SpecularLight light0(l0_pos, l0_col, GL_LIGHT0);

	//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);

	glShadeModel(GL_SMOOTH);
  
	///////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////////////////////////
	// Mainloop:
	float deltacolor = 0.0f;
	int react_keyevent = 0;

	float viewerMovingSpeed = 1.0f;

	std::vector<Model*>::size_type modelCounter = 0;

	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);
		models.push_back(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);
		models.push_back(t);
	}

	cube->showNormals();
	
	while (!done) {
		/////////////////////
		// Do some rendering:
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		if ( wireframe ) {
			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		} else {
			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		}
	
		// 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
		


		glMatrixMode(GL_MODELVIEW);

		//initial viewer position
		glLoadIdentity();

		// move viewer
		myView->draw();
		
		/* do animations */
		for ( std::vector<Animation*>::size_type anim_ct = 0; anim_ct < anims.size(); anim_ct++ ) {
			((UserAnimation*)anims.at(anim_ct))->tick();
		}

		/* draw some models */
		for ( modelCounter = 0; modelCounter < models.size(); modelCounter++ ) {
			models.at(modelCounter)->draw();
			models.at(modelCounter)->rotate(Vec(1.5f, 0.0f, 0.0f));
		}

		cube->draw();
		myModel->draw();

		//draw cube
		//cube->draw();
		//cube->rotate(Vec(0.1f, 0.5f, 1.0f));
		//myModel->draw();
		//myModel->rotate(Vec(0.2f, 0.3f, 1.2f));
		

		////////////////
		// 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;

		  // lights
		  if (keystate[SDLK_1]) {
			//light0.flip();
		  }
		  else if (keystate[SDLK_2]) {
			//light1.flip();
		  }
		  else {
			react_keyevent = 0;
		  }

			if ( keystate[SDLK_g] ) {
				wireframe = !wireframe;
			}

		} 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;
		}

		// rotate viewer
		if (keystate[SDLK_LEFT]) viewer_rot.add(viewer_yrot*viewerMovingSpeed);
		if (keystate[SDLK_RIGHT]) viewer_rot.sub(viewer_yrot*viewerMovingSpeed);
		if (keystate[SDLK_UP]) viewer_rot.add(viewer_xrot*viewerMovingSpeed);
		if (keystate[SDLK_DOWN]) viewer_rot.sub(viewer_xrot*viewerMovingSpeed);
		
		// move viewer
		if (keystate[SDLK_w]) viewer_pos.add(viewer_zmove_neg*viewerMovingSpeed);
		if (keystate[SDLK_s]) viewer_pos.add(viewer_zmove_pos*viewerMovingSpeed);
		if (keystate[SDLK_a]) viewer_pos.add(viewer_xmove_pos*viewerMovingSpeed);
		if (keystate[SDLK_d]) viewer_pos.add(viewer_xmove_neg*viewerMovingSpeed);

		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;
}