Lab 13

GLScene.h:

#ifndef GLSCENE_H
#define GLSCENE_H

#include <qgl.h>
#include <qdatetime.h>
#include <math.h>

/**
* GLScene inherits from QGLWidget (http://doc.trolltech.com/3.3/qglwidget.html) <BR>
* QGLWidget basically allows you to control OpenGL through method calls
*/

class GLScene : public QGLWidget
{
	Q_OBJECT
public:
	GLScene( QWidget* parent, const char* name );
	~GLScene();

protected:
	void initializeGL();
	void paintGL();
	void resizeGL( int w, int h );

	void mouseMoveEvent(QMouseEvent *);
	void mousePressEvent(QMouseEvent *);
	void mouseReleaseEvent(QMouseEvent *);
	void wheelEvent(QWheelEvent *);

private:
	float yAngleForXAngle( float xAngle, float a);
	void camera();
	void unproject(const QPoint& p, float& x, float& y, float& z);

private:
	double zoomFactor;
	double cameraZ, cameraY, cameraX;
	double centerX, centerY, centerZ;

	bool mousePressed;
	float lastX, lastY, lastZ;

	GLfloat objectTransform[16];
};

#endif  

GLScene.cpp

#include "GLScene.h"
#include "GL/glut.h"

#include <iostream>
using namespace std;

/**
* Constructor that creates a GLFractal widget
*/
GLScene::GLScene( QWidget* parent, const char* name ) : QGLWidget( parent, name )
{
	cameraZ = 2.5;
	cameraX = cameraY = 0.0;
	zoomFactor = 0.5;
	centerX = centerY = centerZ = 0.0;
	mousePressed = false;
}

GLScene::~GLScene()
{
} // end destructor

/*--------------------------------------------------------------------------*/
/**
* Do your rendering here
*/
void GLScene::paintGL()
{
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//place a camera in the scene
	camera();

	glMatrixMode( GL_MODELVIEW );
	glPushMatrix();
	glMultMatrixf( objectTransform );

	glColor3f(0.0,0.0,0.0);
	glutSolidCube(.5);

	glPopMatrix();
}

//Set up the camer to look at the scene
void GLScene::camera()
{
	//set up the camera
	glMatrixMode( GL_MODELVIEW); 
	glLoadIdentity();
	gluLookAt( cameraX, cameraY, cameraZ, /* camera position */
	centerX, centerY, centerZ,  /* look-at */
	0.0, 1.0, 0.0); /* up-vector */
}

/*--------------------------------------------------------------------------*/
/**
* Set up the OpenGL rendering state, and define display list
*/

void GLScene::initializeGL()
{
	//The background will be black
	glClearColor (0.0, 0.0, 0.0, 0.0);

	glEnable( GL_DEPTH_TEST ); 
	/* This ensures that we're not drawing faces that we can't see*/
	glEnable( GL_CULL_FACE);


	glShadeModel (GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);

	//let there be light
	GLfloat light0_pos[]={0.0, 5.0,0.0, 1.0}; /*Pos. of the point lightsource*/
	glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);

	//set ambient lighting parameters
	GLfloat ambient[]={0.1,0.1,0.1,1.0};
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);

	//set diffuse and specular lighting
	GLfloat white[]={1.0,1.0,1.0,1.0};
	GLfloat black[]={0.0,0.0,0.0,1.0};

	glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
	glLightfv(GL_LIGHT0,GL_SPECULAR,white);

	//turn on the light
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);


	//place a camera in the scene
	camera();

	glMatrixMode( GL_MODELVIEW );
	glPushMatrix();
	glLoadIdentity();
	glGetFloatv( GL_MODELVIEW_MATRIX, objectTransform );
	glPopMatrix();
}


/*--------------------------------------------------------------------------*/
/**
* Set up the OpenGL view port, matrix mode, etc.
*/
void GLScene::resizeGL( int w, int h )
{
	float sv = ( float) w / h;

	glViewport( 0,0, w,h); /* take the whole window*/
	glMatrixMode( GL_PROJECTION); 
	glLoadIdentity();
	/* now we want perspective! */
	if ( sv > 1.0 )  /* test the aspect ratio */
		gluPerspective( 45, sv, 0.2, 500); /* set up the perspective*/
	else
		gluPerspective( yAngleForXAngle( 45, sv), sv, 0.2, 500);
}

/* makes sure the aspect ratio stays the same when calling gluPerspective */
float GLScene::yAngleForXAngle( float xAngle, float a)
{
	float yAngle;

	xAngle *= M_PI / 180.0;     /* transform to radians */
	yAngle = 2 * atan( tan( xAngle / 2) / a);  /* math is fun */
	yAngle /= M_PI / 180.0;     /* transform to degrees */

	return yAngle;
}

void GLScene::mouseMoveEvent(QMouseEvent *e)
{
	float x,y,z;
	unproject( e->pos(), x, y, z );

	glMatrixMode( GL_MODELVIEW );
	glPushMatrix();
	glLoadMatrixf( objectTransform );
	glTranslatef( x - lastX, y - lastY, 0 );
	glGetFloatv( GL_MODELVIEW_MATRIX, objectTransform );
	glPopMatrix();

	lastX = x;
	lastY = y;
	lastZ = z;

	updateGL();
}

void GLScene::mousePressEvent(QMouseEvent *e)
{
	mousePressed = true;
	unproject( e->pos(), lastX, lastY, lastZ );
}

void GLScene::mouseReleaseEvent(QMouseEvent *e)
{
	mousePressed = false;
}

void GLScene::wheelEvent(QWheelEvent *e)
{
	int numRotations = e->delta() / 120;
	cameraZ += numRotations;
	updateGL();
}

void GLScene::unproject(const QPoint& p, float &x, float &y, float &z)
{
	// We'll need the matrices that define the projection
	GLdouble modelview[16];
	GLdouble projection[16];
	GLint viewport[4];

	glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
	glGetDoublev(GL_PROJECTION_MATRIX, projection);
	glGetIntegerv(GL_VIEWPORT, viewport);

	// First get the z-coordinate from the depth buffer
	GLfloat depth;
	glReadPixels(p.x(), viewport[3] - p.y(), 1, 1,
		GL_DEPTH_COMPONENT, GL_FLOAT, &depth);

	// Calculate the 3D point in world coordinates
	GLdouble x1, y1, z1;
	gluUnProject(p.x(), viewport[3] - p.y(), depth,
		modelview, projection, viewport, &x1, &y1, &z1);

	x = (float)x1;
	y = (float)y1;
	z = (float)z1;
}