📄 glcamera.cpp
字号:
// Code writen by: Vic Hollis 09/07/2003
// I don't mind if you use this class in your own code. All I ask is
// that you give me credit for it if you do. And plug NeHe while your
// at it! :P Thanks go to David Steere, Cameron Tidwell, Bert Sammons,
// and Brannon Martindale for helping me test all the code! Enjoy.
// glCamera.cpp: implementation of the glCamera class.
//
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Some minimal additions by rIO.Spinning Kids
// For testing flares against occluding objects.
// Not using proprietary extensions, this is PURE OpenGL1.1
//
// Just call the IsOccluded function, passing it the glPoint to check
//
//////////////////////////////////////////////////////////////////////
#include "glCamera.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
glCamera::glCamera()
{
// Initalize all our member varibles.
m_MaxPitchRate = 0.0f;
m_MaxHeadingRate = 0.0f;
m_HeadingDegrees = 0.0f;
m_PitchDegrees = 0.0f;
m_MaxForwardVelocity = 0.0f;
m_ForwardVelocity = 0.0f;
m_LightSourcePos.x = 0.0f;
m_LightSourcePos.y = 0.0f;
m_LightSourcePos.z = 0.0f;
m_GlowTexture = 0;
m_HaloTexture = 0;
m_StreakTexture = 0;
m_MaxPointSize = 0.0f;
}
glCamera::~glCamera()
{
if(m_GlowTexture != 0) { // If the glow texture is valid
glDeleteTextures(1, &m_GlowTexture); // delete the glow texture
}
if(m_HaloTexture != 0) { // If the halo texture is valid
glDeleteTextures(1, &m_HaloTexture); // delete the halo texture
}
if(m_BigGlowTexture != 0) { // If the BigGlow texture is valid
glDeleteTextures(1, &m_BigGlowTexture); // delete the BigGlow texture
}
if(m_StreakTexture != 0) { // If the Streak texture is valid
glDeleteTextures(1, &m_StreakTexture); // delete the StreakTexture
}
}
void glCamera::SetPrespective()
{
GLfloat Matrix[16]; // A array to hold the model view matrix.
glVector v; // A vector to hold our cameras direction * the forward velocity
// we don't want to destory the Direction vector by using it instead.
// Going to use glRotate to calculate our direction vector
glRotatef(m_HeadingDegrees, 0.0f, 1.0f, 0.0f);
glRotatef(m_PitchDegrees, 1.0f, 0.0f, 0.0f);
// Get the resulting matrix from OpenGL it will have our
// direction vector in the 3rd row.
glGetFloatv(GL_MODELVIEW_MATRIX, Matrix);
// Get the direction vector from the matrix. Element 10 must
// be inverted!
m_DirectionVector.i = Matrix[8];
m_DirectionVector.j = Matrix[9];
m_DirectionVector.k = -Matrix[10];
// Ok erase the results of the last computation.
glLoadIdentity();
// Rotate the scene to get the right orientation.
glRotatef(m_PitchDegrees, 1.0f, 0.0f, 0.0f);
glRotatef(m_HeadingDegrees, 0.0f, 1.0f, 0.0f);
// Scale the direction by our speed.
v = m_DirectionVector;
v *= m_ForwardVelocity;
// Increment our position by the vector
m_Position.x += v.i;
m_Position.y += v.j;
m_Position.z += v.k;
// Translate to our new position.
glTranslatef(-m_Position.x, -m_Position.y, -m_Position.z);
}
void glCamera::ChangePitch(GLfloat degrees)
{
if(fabs(degrees) < fabs(m_MaxPitchRate))
{
// Our pitch is less than the max pitch rate that we
// defined so lets increment it.
m_PitchDegrees += degrees;
}
else
{
// Our pitch is greater than the max pitch rate that
// we defined so we can only increment our pitch by the
// maximum allowed value.
if(degrees < 0)
{
// We are pitching down so decrement
m_PitchDegrees -= m_MaxPitchRate;
}
else
{
// We are pitching up so increment
m_PitchDegrees += m_MaxPitchRate;
}
}
// We don't want our pitch to run away from us. Although it
// really doesn't matter I prefer to have my pitch degrees
// within the range of -360.0f to 360.0f
if(m_PitchDegrees > 360.0f)
{
m_PitchDegrees -= 360.0f;
}
else if(m_PitchDegrees < -360.0f)
{
m_PitchDegrees += 360.0f;
}
}
void glCamera::ChangeHeading(GLfloat degrees)
{
if(fabs(degrees) < fabs(m_MaxHeadingRate))
{
// Our Heading is less than the max heading rate that we
// defined so lets increment it but first we must check
// to see if we are inverted so that our heading will not
// become inverted.
if(m_PitchDegrees > 90 && m_PitchDegrees < 270 || (m_PitchDegrees < -90 && m_PitchDegrees > -270))
{
m_HeadingDegrees -= degrees;
}
else
{
m_HeadingDegrees += degrees;
}
}
else
{
// Our heading is greater than the max heading rate that
// we defined so we can only increment our heading by the
// maximum allowed value.
if(degrees < 0)
{
// Check to see if we are upside down.
if((m_PitchDegrees > 90 && m_PitchDegrees < 270) || (m_PitchDegrees < -90 && m_PitchDegrees > -270))
{
// Ok we would normally decrement here but since we are upside
// down then we need to increment our heading
m_HeadingDegrees += m_MaxHeadingRate;
}
else
{
// We are not upside down so decrement as usual
m_HeadingDegrees -= m_MaxHeadingRate;
}
}
else
{
// Check to see if we are upside down.
if(m_PitchDegrees > 90 && m_PitchDegrees < 270 || (m_PitchDegrees < -90 && m_PitchDegrees > -270))
{
// Ok we would normally increment here but since we are upside
// down then we need to decrement our heading.
m_HeadingDegrees -= m_MaxHeadingRate;
}
else
{
// We are not upside down so increment as usual.
m_HeadingDegrees += m_MaxHeadingRate;
}
}
}
// We don't want our heading to run away from us either. Although it
// really doesn't matter I prefer to have my heading degrees
// within the range of -360.0f to 360.0f
if(m_HeadingDegrees > 360.0f)
{
m_HeadingDegrees -= 360.0f;
}
else if(m_HeadingDegrees < -360.0f)
{
m_HeadingDegrees += 360.0f;
}
}
void glCamera::ChangeVelocity(GLfloat vel)
{
if(fabs(vel) < fabs(m_MaxForwardVelocity))
{
// Our velocity is less than the max velocity increment that we
// defined so lets increment it.
m_ForwardVelocity += vel;
}
else
{
// Our velocity is greater than the max velocity increment that
// we defined so we can only increment our velocity by the
// maximum allowed value.
if(vel < 0)
{
// We are slowing down so decrement
m_ForwardVelocity -= -m_MaxForwardVelocity;
}
else
{
// We are speeding up so increment
m_ForwardVelocity += m_MaxForwardVelocity;
}
}
}
// I found this code here: http://www.markmorley.com/opengl/frustumculling.html
// and decided to make it part of
// the camera class just in case I might want to rotate
// and translate the projection matrix. This code will
// make sure that the Frustum is updated correctly but
// this member is computational expensive with:
// 82 muliplications, 72 additions, 24 divisions, and
// 12 subtractions for a total of 190 operations. Ouch!
void glCamera::UpdateFrustum()
{
GLfloat clip[16];
GLfloat proj[16];
GLfloat modl[16];
GLfloat t;
/* Get the current PROJECTION matrix from OpenGL */
glGetFloatv( GL_PROJECTION_MATRIX, proj );
/* Get the current MODELVIEW matrix from OpenGL */
glGetFloatv( GL_MODELVIEW_MATRIX, modl );
/* Combine the two matrices (multiply projection by modelview) */
clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];
clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];
clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];
clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
/* Extract the numbers for the RIGHT plane */
m_Frustum[0][0] = clip[ 3] - clip[ 0];
m_Frustum[0][1] = clip[ 7] - clip[ 4];
m_Frustum[0][2] = clip[11] - clip[ 8];
m_Frustum[0][3] = clip[15] - clip[12];
/* Normalize the result */
t = GLfloat(sqrt( m_Frustum[0][0] * m_Frustum[0][0] + m_Frustum[0][1] * m_Frustum[0][1] + m_Frustum[0][2] * m_Frustum[0][2] ));
m_Frustum[0][0] /= t;
m_Frustum[0][1] /= t;
m_Frustum[0][2] /= t;
m_Frustum[0][3] /= t;
/* Extract the numbers for the LEFT plane */
m_Frustum[1][0] = clip[ 3] + clip[ 0];
m_Frustum[1][1] = clip[ 7] + clip[ 4];
m_Frustum[1][2] = clip[11] + clip[ 8];
m_Frustum[1][3] = clip[15] + clip[12];
/* Normalize the result */
t = GLfloat(sqrt( m_Frustum[1][0] * m_Frustum[1][0] + m_Frustum[1][1] * m_Frustum[1][1] + m_Frustum[1][2] * m_Frustum[1][2] ));
m_Frustum[1][0] /= t;
m_Frustum[1][1] /= t;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -