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