glut_template.cpp 5.33 KB
/* Don't change this file. Make a copy in your project and change parameters as necessary.
	
	In order to use this template, specify the following signature in your main.cpp file:
	void glut_init(int argc, char* argv[]);

*/

#ifndef GLUT_TEMPLATE_H
#define GLUT_TEMPLATE_H

#include <stim/visualization/camera.h>
#include <GL/glut.h>

void render_scene();

void draw_colorcube() {
	glBegin(GL_LINES);								//start a line series
	glColor3f(0, 0, 0);
	glVertex3f(-0.5, -0.5, -0.5);
	glColor3f(1, 0, 0);
	glVertex3f(0.5, -0.5, -0.5);

	glColor3f(0, 0, 0);
	glVertex3f(-0.5, -0.5, -0.5);
	glColor3f(0, 1, 0);
	glVertex3f(-0.5, 0.5, -0.5);

	glColor3f(0, 0, 0);
	glVertex3f(-0.5, -0.5, -0.5);
	glColor3f(0, 0, 1);
	glVertex3f(-0.5, -0.5, 0.5);

	glColor3f(1, 1, 1);
	glVertex3f(0.5, 0.5, 0.5);
	glColor3f(1, 1, 0);
	glVertex3f(0.5, 0.5, -0.5);

	glColor3f(1, 1, 1);
	glVertex3f(0.5, 0.5, 0.5);
	glColor3f(1, 0, 1);
	glVertex3f(0.5, -0.5, 0.5);

	glColor3f(1, 1, 1);
	glVertex3f(0.5, 0.5, 0.5);
	glColor3f(0, 1, 1);
	glVertex3f(-0.5, 0.5, 0.5);

	glColor3f(1, 0, 0);
	glVertex3f(0.5, -0.5, -0.5);
	glColor3f(1, 1, 0);
	glVertex3f(0.5, 0.5, -0.5);

	glColor3f(1, 0, 0);
	glVertex3f(0.5, -0.5, -0.5);
	glColor3f(1, 0, 1);
	glVertex3f(0.5, -0.5, 0.5);

	glColor3f(0, 1, 0);
	glVertex3f(-0.5, 0.5, -0.5);
	glColor3f(1, 1, 0);
	glVertex3f(0.5, 0.5, -0.5);

	glColor3f(0, 1, 0);
	glVertex3f(-0.5, 0.5, -0.5);
	glColor3f(0, 1, 1);
	glVertex3f(-0.5, 0.5, 0.5);

	glColor3f(0, 0, 1);
	glVertex3f(-0.5, -0.5, 0.5);
	glColor3f(1, 0, 1);
	glVertex3f(0.5, -0.5, 0.5);

	glColor3f(0, 0, 1);
	glVertex3f(-0.5, -0.5, 0.5);
	glColor3f(0, 1, 1);
	glVertex3f(-0.5, 0.5, 0.5);
	glEnd();
}}

struct glut_template_struct {
	float theta_scale = 0.01f;
	float phi_scale = 0.01f;
	float zoom_scale = 0.1f;
	stim::camera cam;									//create a camera object
	int mx, my;											//mouse coordinates in the window space
	float d = 1.5;										//initial distance between the camera and the sphere
	bool rotate_zoom = true;							//sets the current camera mode (rotation = true, zoom = false)

	bool axis = false;									//render the z-axis (set via a command line flag)
} gt;

//render the XYZ axes
void render_axes() {
	glDisable(GL_TEXTURE_2D);							//turn off texture mapping		
	glBegin(GL_LINES);
	glColor3f(1.0f, 0.0f, 0.0f);					//set the color to RED and render X
	glVertex3f(0.0, 0.0, 0.0);
	glVertex3f(100.0, 0.0, 0.0);

	glColor3f(0.0f, 1.0f, 0.0f);					//set the color to RED and render X
	glVertex3f(0.0, 0.0, 0.0);
	glVertex3f(0.0, 100.0, 0.0);

	glColor3f(0.0f, 0.0f, 1.0f);					//set the color to RED and render X
	glVertex3f(0.0, 0.0, 0.0);
	glVertex3f(0.0, 0.0, 100.0);
	glEnd();
}

//display function executed to update every frame
void glut_display() {

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

	glMatrixMode(GL_PROJECTION);							//put the projection matrix on the stack
	glLoadIdentity();										//set it to the identity matrix
	gluPerspective(gt.cam.getFOV(), 1, 0.001, 1000000);		//set up a perspective projection
	glMatrixMode(GL_MODELVIEW);								//load the model view matrix to the stack
	glLoadIdentity();										//set it to the identity matrix															
	stim::vec3<float> p = gt.cam.getPosition();				//get the camera parameters
	stim::vec3<float> u = gt.cam.getUp();
	stim::vec3<float> c = gt.cam.getLookAt();
	gluLookAt(p[0], p[1], p[2], c[0], c[1], c[2], u[0], u[1], u[2]);	//specify the camera parameters to OpenGL

	render_axes();											//render the axes if the user requests them
	draw_colorcube();
	glutSwapBuffers();										//swap in the back buffer (double-buffering is used to prevent tearing)
}

//process mouse press events
void glut_mouse_press(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON)						//set the camera motion mode based on the mouse button pressed
		gt.rotate_zoom = true;
	else if (button == GLUT_RIGHT_BUTTON)
		gt.rotate_zoom = false;
	if (state == GLUT_DOWN) {							//if the mouse is pressed
		gt.mx = x;		gt.my = y;								//set the current mouse position
	}
}

//process mouse drags to update the camera
void glut_mouse_drag(int x, int y) {
	if (gt.rotate_zoom == true) {						//if the camera is in rotation mode, rotate
		float theta = gt.theta_scale * (gt.mx - x);
		float phi = -gt.phi_scale * (gt.my - y);
		gt.cam.OrbitFocus(theta, phi);					//if the mouse is dragged
	}
	else {											//otherwize zoom
		gt.cam.Push(gt.zoom_scale*(gt.my - y));
	}
	gt.mx = x;		gt.my = y;								//update the mouse position
	glutPostRedisplay();
}

void glut_init(int argc, char* argv[]) {
	glutInit(&argc, argv);							//initialize GLUT		
	glutInitWindowSize(500, 500);					//set the size of the GLUT window
	glutInitDisplayMode(GLUT_DEPTH | GLUT_RGBA | GLUT_DOUBLE);
	glutCreateWindow("3D Tensor Visualization");	//create the GLUT window (and an OpenGL context)	
	glutDisplayFunc(glut_display);					//set the display function (which will be called repeatedly by glutMainLoop)	
	glutMouseFunc(glut_mouse_press);				//set the mouse press function (called when a mouse button is pressed)	
	glutMotionFunc(glut_mouse_drag);				//set the mouse motion function (which will be called any time the mouse is dragged)
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);			//set the clear color to white
	gt.cam.setPosition(gt.d, gt.d, gt.d);						//initialize the camera
	gt.cam.LookAt(0, 0, 0, 0, 1, 1);
	gt.cam.setFOV(40);
	glutMainLoop();									//enter the main loop
}

#endif