rts_glTrueEyes.h 6.84 KB
#include <iostream>
#include <string>

#include "rtsCamera.h"
#include "rtsSourceCode.h"
#include "rts_glShaderProgram.h"
using namespace std;

#include <gl/glut.h>

class rts_glTrueEyes
{
	static int glut_window;

	static rts_glShaderProgram shader;
	static string source_file;
	static rtsCamera camera;
	static int mouse_x;
	static int mouse_y;
	static float camera_pos[3];
	static float volume_size[3];
	static rts_glTextureMap volume;

	static bool zooming;

	static void DrawCube()
	{
		float sx = volume_size[0]/2;
		float sy = volume_size[1]/2;
		float sz = volume_size[2]/2;
		float tx = volume_size[0]/2;
		float ty = volume_size[1]/2;
		float tz = volume_size[2]/2;

		glBegin(GL_QUADS);
			glTexCoord3f(-tx, -ty, -tz);
			glVertex3f(-sx, -sy, -sz);
			glTexCoord3f(-tx, ty, -tz);
			glVertex3f(-sx, sy, -sz);
			glTexCoord3f(tx, ty, -tz);
			glVertex3f(sx, sy, -sz);
			glTexCoord3f(tx, -ty, -tz);
			glVertex3f(sx, -sy, -sz);
			
			glTexCoord3f(-tx, -ty, tz);
			glVertex3f(-sx, -sy, sz);
			glTexCoord3f(-tx, ty, tz);
			glVertex3f(-sx, sy, sz);
			glTexCoord3f(tx, ty, tz);
			glVertex3f(sx, sy, sz);
			glTexCoord3f(tx, -ty, tz);
			glVertex3f(sx, -sy, sz);

			glTexCoord3f(-tx, -ty, -tz);
			glVertex3f(-sx, -sy, -sz);
			glTexCoord3f(-tx, -ty, tz);
			glVertex3f(-sx, -sy, sz);
			glTexCoord3f(tx, -ty, tz);
			glVertex3f(sx, -sy, sz);
			glTexCoord3f(tx, -ty, -tz);
			glVertex3f(sx, -sy, -sz);

			glTexCoord3f(-tx, ty, -tz);
			glVertex3f(-sx, sy, -sz);
			glTexCoord3f(-tx, ty, tz);
			glVertex3f(-sx, sy, sz);
			glTexCoord3f(tx, ty, tz);
			glVertex3f(sx, sy, sz);
			glTexCoord3f(tx, ty, -tz);
			glVertex3f(sx, sy, -sz);

			glTexCoord3f(-tx, -ty, -tz);
			glVertex3f(-sx, -sy, -sz);
			glTexCoord3f(-tx, -ty, tz);
			glVertex3f(-sx, -sy, sz);
			glTexCoord3f(-tx, ty, tz);
			glVertex3f(-sx, sy, sz);
			glTexCoord3f(-tx, ty, -tz);
			glVertex3f(-sx, sy, -sz);

			glTexCoord3f(tx, -ty, -tz);
			glVertex3f(sx, -sy, -sz);
			glTexCoord3f(tx, -ty, tz);
			glVertex3f(sx, -sy, sz);
			glTexCoord3f(tx, ty, tz);
			glVertex3f(sx, sy, sz);
			glTexCoord3f(tx, ty, -tz);
			glVertex3f(sx, sy, -sz);
		glEnd();
	}

	static void DisplayFunction()
	{


		//set up the viewport and projection
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
		float aspect_ratio = (float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT);
		gluPerspective(camera.getFOV(), aspect_ratio, 0.01, 10);

		//clear the screen
		glClear(GL_COLOR_BUFFER_BIT);
		glClear(GL_DEPTH_BUFFER_BIT);	
		

		//set up the camera
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		point3D<float> pos = camera.getPosition();
		vector3D<float> up = camera.getUp();
		gluLookAt(pos.x, pos.y, pos.z, 0, 0, 0, up.x, up.y, up.z);

		//draw a cube
		glColor3f(1.0, 0.0, 0.0);
		shader.UpdateGlobalUniforms();
		shader.BeginProgram();
		DrawCube();
		shader.EndProgram();

		glutSwapBuffers();
	}
	static void IdleFunction()
	{
		glutPostRedisplay();
	}

	static void MouseDrag(int x, int y)
	{
		int dx = x - mouse_x;
		int dy = y - mouse_y;

		if(zooming)
		{
			camera.Zoom(dy);
		}
		else
		{

			camera.OrbitFocus(-dx*0.01, dy*0.01);
			point3D<float> pos = camera.getPosition();
			camera_pos[0] = pos.x;
			camera_pos[1] = pos.y;
			camera_pos[2] = pos.z;
		}

		mouse_x = x;
		mouse_y = y;

		glutPostRedisplay();
		
	}

	static void MouseMove(int x, int y)
	{
		mouse_x = x;
		mouse_y = y;

	}
	static void KeyPress(unsigned char key, int x, int y)
	{
		//reload the shader
		if(key == 'r' || key == 'R')
		{
			UpdateShader();


		}

	}

	static void MousePress(int button, int state, int x, int y)
	{
		if(state == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON)
			zooming = true;
		else
			zooming = false;
	}
	
	static void UpdateShader()
	{
		//load the source code
		shader.Clean();
		shader.AttachShader(GL_FRAGMENT_SHADER, source_file.c_str());

		//compile the shader
		shader.Compile();
		shader.PrintLog();
		shader.Link();
		shader.PrintLog();

		if(!shader.linked)
		{
			cout<<"Error linking shader."<<endl;
			std::puts("Press any key to continue...");
			std::getchar();
			UpdateShader();
		}


		shader.PrintUniforms();
		shader.AttachGlobalUniform("camera", &camera_pos);
		shader.AttachGlobalUniform("volume_size", &volume_size);
		shader.AttachTextureMap("volume", volume);


	}
public:
	void Begin();
	void SetShader(string filename);
	void SetVolume(unsigned char* bits, int sx, int sy, int sz, int channels);
	void SetVolumeSize(float x, float y, float z);
	void Initialize();

};

//static variables
rtsCamera rts_glTrueEyes::camera;
rts_glShaderProgram rts_glTrueEyes::shader;
int rts_glTrueEyes::glut_window;
int rts_glTrueEyes::mouse_x;
int rts_glTrueEyes::mouse_y;
float rts_glTrueEyes::camera_pos[3];
float rts_glTrueEyes::volume_size[3];
string rts_glTrueEyes::source_file;
rts_glTextureMap rts_glTrueEyes::volume;
bool rts_glTrueEyes::zooming;


void rts_glTrueEyes::Initialize()
{
	//initialize OpenGL
	glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);

	//create the GLUT window
	glut_window = glutCreateWindow("True Eyes");

	//initialize GLEW
	GLenum err = glewInit();
	if(err != GLEW_OK)
		fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
	if (glewIsSupported("GL_VERSION_2_0"))
		printf("Ready for OpenGL 2.0\n");
	else {
		printf("OpenGL 2.0 not supported\n");
		//exit(1);
	}

	//set the function pointers
	glutDisplayFunc(&rts_glTrueEyes::DisplayFunction);
	glutIdleFunc(&rts_glTrueEyes::IdleFunction);
	glutMotionFunc(&rts_glTrueEyes::MouseDrag);
	glutMouseFunc(&rts_glTrueEyes::MousePress);
	glutPassiveMotionFunc(&rts_glTrueEyes::MouseMove);
	glutKeyboardFunc(&rts_glTrueEyes::KeyPress);

	//set rendering parameters
	glEnable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);

	//set up the camera
	camera.setPosition(0, 0, -1.6);
	camera_pos[0] = 0;
	camera_pos[1] = 0;
	camera_pos[2] = -1.6;
	camera.LookAt(0.0, 0.0, 0.0);
	camera.setFOV(60);

	zooming = false;


}
void rts_glTrueEyes::Begin()
{
	//start rendering
	glutMainLoop();
}

void rts_glTrueEyes::SetShader(string filename)
{
	source_file = filename;
	UpdateShader();
}

void rts_glTrueEyes::SetVolumeSize(float x, float y, float z)
{
	float max_edge = max(x, max(y, z));
	volume_size[0] = x/max_edge;
	volume_size[1] = y/max_edge;
	volume_size[2] = z/max_edge;
}

void rts_glTrueEyes::SetVolume(unsigned char* bits, int sx, int sy, int sz, int channels)
{
	if(channels == 1)
		volume.Init(bits, GL_TEXTURE_3D, sx, sy, sz, 1, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_NEAREST);
	else if(channels == 3)
		volume.Init(bits, GL_TEXTURE_3D, sx, sy, sz, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, GL_NEAREST);
	CHECK_OPENGL_ERROR



}