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