///////////////////////////////////////////////////////////////////////////////
// ModelGL.cpp
// ===========
// Model component of OpenGL
//
// AUTHOR: Song Ho Ahn (song.ahn@gmail.com)
// CREATED: 2008-10-02
// UPDATED: 2013-03-01
///////////////////////////////////////////////////////////////////////////////
#ifdef _WIN32
#include <windows.h> // include windows.h to avoid thousands of compile errors even though this class is not depending on Windows
#endif
#ifdef __APPLE__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#include <cmath>
#include "ModelGL.h"
#include "cameraSimple.h" // 3D mesh of camera
// constants
const float DEG2RAD = 3.141593f / 180;
const float FOV_Y = 60.0f;
const float NEAR_PLANE = 1.0f;
const float FAR_PLANE = 100.0f;
const float CAMERA_ANGLE_X = 45.0f; // pitch in degree
const float CAMERA_ANGLE_Y = -45.0f; // heading in degree
const float CAMERA_DISTANCE = 25.0f; // camera distance
// default projection matrix values
const float DEFAULT_LEFT = -0.5f;
const float DEFAULT_RIGHT = 0.5f;
const float DEFAULT_BOTTOM = -0.5f;
const float DEFAULT_TOP = 0.5f;
const float DEFAULT_NEAR = 1.0f;
const float DEFAULT_FAR = 10.0f;
///////////////////////////////////////////////////////////////////////////////
// default ctor
///////////////////////////////////////////////////////////////////////////////
ModelGL::ModelGL() : windowWidth(0), windowHeight(0), mouseLeftDown(false),
mouseRightDown(false), drawModeChanged(false), drawMode(0),
cameraAngleX(CAMERA_ANGLE_X), cameraAngleY(CAMERA_ANGLE_Y),
cameraDistance(CAMERA_DISTANCE), windowSizeChanged(false),
projectionLeft(DEFAULT_LEFT),
projectionRight(DEFAULT_RIGHT),
projectionBottom(DEFAULT_BOTTOM),
projectionTop(DEFAULT_TOP),
projectionNear(DEFAULT_NEAR),
projectionFar(DEFAULT_FAR),
quadricId(0), projectionMode(0)
{
bgColor[0] = bgColor[1] = bgColor[2] = bgColor[3] = 0;
// init projection matrix
setFrustum(projectionLeft, projectionRight,
projectionBottom, projectionTop,
projectionNear, projectionFar);
// model, view, modelview matrices are fixed in this app
matrixModel.identity();
matrixView.identity();
matrixView.translate(0, 0, -7); // move the camera away from 3D objects
matrixModelView = matrixView * matrixModel;
}
///////////////////////////////////////////////////////////////////////////////
// destructor
///////////////////////////////////////////////////////////////////////////////
ModelGL::~ModelGL()
{
}
///////////////////////////////////////////////////////////////////////////////
// initialize OpenGL states and scene
///////////////////////////////////////////////////////////////////////////////
void ModelGL::init()
{
glShadeModel(GL_SMOOTH); // shading mathod: GL_SMOOTH or GL_FLAT
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
// enable /disable features
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
//glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glEnable(GL_SCISSOR_TEST);
// track material ambient and diffuse from surface color, call it before glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glClearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]); // background color
glClearStencil(0); // clear stencil buffer
glClearDepth(1.0f); // 0 is near, 1 is far
glDepthFunc(GL_LEQUAL);
initLights();
// create a GLU quadric object
quadricId = gluNewQuadric();
gluQuadricDrawStyle(quadricId, GLU_FILL);
}
///////////////////////////////////////////////////////////////////////////////
// clean up OpenGL objects
///////////////////////////////////////////////////////////////////////////////
void ModelGL::quit()
{
gluDeleteQuadric(quadricId);
}
///////////////////////////////////////////////////////////////////////////////
// initialize lights
///////////////////////////////////////////////////////////////////////////////
void ModelGL::initLights()
{
// set up light colors (ambient, diffuse, specular)
GLfloat lightKa[] = {.0f, .0f, .0f, 1.0f}; // ambient light
GLfloat lightKd[] = {.9f, .9f, .9f, 1.0f}; // diffuse light
GLfloat lightKs[] = {1, 1, 1, 1}; // specular light
glLightfv(GL_LIGHT0, GL_AMBIENT, lightKa);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightKd);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightKs);
// position the light in eye space
float lightPos[4] = {0, 0, 1, 0}; // directional light
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_LIGHT0); // MUST enable each light source after configuration
}
///////////////////////////////////////////////////////////////////////////////
// set camera position and lookat direction
///////////////////////////////////////////////////////////////////////////////
void ModelGL::setCamera(float posX, float posY, float posZ, float targetX, float targetY, float targetZ)
{
float forward[4];
float up[4];
float left[4];
float position[4];
float invLength;
// determine forward vector (direction reversed because it is camera)
forward[0] = posX - targetX; // x
forward[1] = posY - targetY; // y
forward[2] = posZ - targetZ; // z
forward[3] = 0.0f; // w
// normalize it without w-component
invLength = 1.0f / sqrtf(forward[0]*forward[0] + forward[1]*forward[1] + forward[2]*forward[2]);
forward[0] *= invLength;
forward[1] *= invLength;
forward[2] *= invLength;
// assume up direction is straight up
up[0] = 0.0f; // x
up[1] = 1.0f; // y
up[2] = 0.0f; // z
up[3] = 0.0f; // w
// compute left vector with cross product
left[0] = up[1]*forward[2] - up[2]*forward[1]; // x
left[1] = up[2]*forward[0] - up[0]*forward[2]; // y
left[2] = up[0]*forward[1] - up[1]*forward[0]; // z
left[3] = 1.0f; // w
// re-compute orthogonal up vector
up[0] = forward[1]*left[2] - forward[2]*left[1]; // x
up[1] = forward[2]*left[0] - forward[0]*left[2]; // y
up[2] = forward[0]*left[1] - forward[1]*left[0]; // z
up[3] = 0.0f; // w
// camera position
position[0] = -posX;
position[1] = -posY;
position[2] = -posZ;
position[3] = 1.0f;
// copy axis vectors to matrix
matrixView.identity();
matrixView.setColumn(0, left);
matrixView.setColumn(1, up);
matrixView.setColumn(2, forward);
matrixView.setColumn(3, position);
}
///////////////////////////////////////////////////////////////////////////////
// set rendering window size
///////////////////////////////////////////////////////////////////////////////
void ModelGL::setWindowSize(int width, int height)
{
// assign the width/height of viewport
windowWidth = width;
windowHeight = height;
windowSizeChanged = true;
}
///////////////////////////////////////////////////////////////////////////////
// configure projection and viewport
///////////////////////////////////////////////////////////////////////////////
void ModelGL::setViewpor
评论1