You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
5.0 KiB
184 lines
5.0 KiB
// |
|
// Copyright (c) 2010-2011 Matthew Jack and Doug Binks |
|
// |
|
// This software is provided 'as-is', without any express or implied |
|
// warranty. In no event will the authors be held liable for any damages |
|
// arising from the use of this software. |
|
// Permission is granted to anyone to use this software for any purpose, |
|
// including commercial applications, and to alter it and redistribute it |
|
// freely, subject to the following restrictions: |
|
// 1. The origin of this software must not be misrepresented; you must not |
|
// claim that you wrote the original software. If you use this software |
|
// in a product, an acknowledgment in the product documentation would be |
|
// appreciated but is not required. |
|
// 2. Altered source versions must be plainly marked as such, and must not be |
|
// misrepresented as being the original software. |
|
// 3. This notice may not be removed or altered from any source distribution. |
|
|
|
#pragma once |
|
#ifndef AUDORIENTATION3D_DEFINED |
|
#define AUDORIENTATION3D_DEFINED |
|
|
|
#include "AUVec3f.inl" //interface relies on class AUVec3f |
|
#include <limits> //for numerical limits |
|
|
|
|
|
class AUOrientation3D |
|
{ |
|
public: |
|
AUOrientation3D() : |
|
m_v3dForwards( 1.0f, 0.0f, 0.0f ), |
|
m_v3dUp( 0.0f, 1.0f, 0.0f ), |
|
m_v3dRight( 0.0f, 0.0f, 1.0f ) |
|
{ |
|
} |
|
|
|
AUOrientation3D( const AUVec3f& v3dForwards_, const AUVec3f& v3dUp_) : |
|
m_v3dForwards( v3dForwards_ ), |
|
m_v3dUp( v3dUp_ ) |
|
{ |
|
OrthoNormalise(); |
|
} |
|
|
|
//Inspectors |
|
const AUVec3f& GetForwards() const { return m_v3dForwards; } |
|
const AUVec3f& GetUp() const { return m_v3dUp; } |
|
const AUVec3f& GetRight() const { return m_v3dRight; } |
|
|
|
void LoadglViewMatrix( float *const fglMatrix_ ) const |
|
{ |
|
//note: OpenGL camera defaults to looking down -z, thus orient z with Forwards |
|
fglMatrix_[0] = m_v3dRight.x; |
|
fglMatrix_[1] = m_v3dUp.x; |
|
fglMatrix_[2] = -m_v3dForwards.x; |
|
fglMatrix_[3] = 0.0f; |
|
|
|
fglMatrix_[4] = m_v3dRight.y; |
|
fglMatrix_[5] = m_v3dUp.y; |
|
fglMatrix_[6] = -m_v3dForwards.y; |
|
fglMatrix_[7] = 0.0f; |
|
|
|
fglMatrix_[8] = m_v3dRight.z; |
|
fglMatrix_[9] = m_v3dUp.z; |
|
fglMatrix_[10] = -m_v3dForwards.z; |
|
fglMatrix_[11] = 0.0f; |
|
|
|
fglMatrix_[12] = 0.0f; |
|
fglMatrix_[13] = 0.0f; |
|
fglMatrix_[14] = 0.0f; |
|
fglMatrix_[15] = 1.0f; |
|
} |
|
|
|
void LoadglObjectMatrix( float *const fglMatrix_ ) const |
|
{ |
|
//note: OpenGL camera defaults to looking down -z, thus orient z with Forwards |
|
fglMatrix_[0] = m_v3dForwards.x; |
|
fglMatrix_[1] = m_v3dForwards.y; |
|
fglMatrix_[2] = m_v3dForwards.z; |
|
fglMatrix_[3] = 0.0f; |
|
|
|
fglMatrix_[4] = m_v3dUp.x; |
|
fglMatrix_[5] = m_v3dUp.y; |
|
fglMatrix_[6] = m_v3dUp.z; |
|
fglMatrix_[7] = 0.0f; |
|
|
|
fglMatrix_[8] = m_v3dRight.x; |
|
fglMatrix_[9] = m_v3dRight.y; |
|
fglMatrix_[10] = m_v3dRight.z; |
|
fglMatrix_[11] = 0.0f; |
|
|
|
fglMatrix_[12] = 0.0f; |
|
fglMatrix_[13] = 0.0f; |
|
fglMatrix_[14] = 0.0f; |
|
fglMatrix_[15] = 1.0f; |
|
} |
|
|
|
//Mutators |
|
AUVec3f& GetForwards() { return m_v3dForwards; } |
|
AUVec3f& GetUp() { return m_v3dUp; } |
|
AUVec3f& GetRight() { return m_v3dRight; } |
|
|
|
void Set( const AUVec3f& v3dForwards_, const AUVec3f& v3dUp_) |
|
{ |
|
m_v3dForwards = v3dForwards_; |
|
m_v3dUp = v3dUp_; |
|
OrthoNormalise(); |
|
} |
|
|
|
void Rotate( const AUVec3f& v3dAxis_, float fTheta_) |
|
{ |
|
float fCosTheta = static_cast<float>( cos(fTheta_ ) ); |
|
float fSinTheta = static_cast<float>( sin(fTheta_ ) ); |
|
|
|
AUVec3f v3dtemp = v3dAxis_.Cross( m_v3dForwards ); |
|
m_v3dForwards += fSinTheta * v3dtemp + |
|
( fCosTheta - 1.0f ) * v3dAxis_.Cross( v3dtemp ); |
|
v3dtemp = v3dAxis_.Cross( m_v3dUp ); |
|
m_v3dUp += fSinTheta * v3dtemp + |
|
( fCosTheta - 1.0f ) * v3dAxis_.Cross( v3dtemp ); |
|
|
|
//orthonormalise coordinate system |
|
OrthoNormalise(); |
|
} |
|
|
|
protected: |
|
void OrthoNormalise() |
|
{ |
|
if( true == m_v3dForwards.Normalise() ) |
|
{ |
|
//have a normalised forwards vector |
|
m_v3dRight = m_v3dForwards.Cross( m_v3dUp ); |
|
if( true == m_v3dRight.Normalise() ) |
|
{ |
|
//and now have a normalised right vector so safe to generate cross. |
|
m_v3dUp = m_v3dRight.Cross( m_v3dForwards ); |
|
} |
|
else |
|
{ |
|
//have a forwards vector only, so generate an arbitary `up'. |
|
m_v3dUp.SetX( m_v3dForwards.z ); |
|
m_v3dUp.SetY( m_v3dForwards.x ); |
|
m_v3dUp.SetZ( m_v3dForwards.y ); |
|
|
|
//will now get a 'guaranteed' right from this |
|
m_v3dRight = m_v3dForwards.Cross( m_v3dUp ); |
|
|
|
//and so can generate a true up |
|
m_v3dUp = m_v3dRight.Cross( m_v3dForwards ); |
|
} |
|
} |
|
else |
|
{ |
|
//can't use forwards as our main vector, so try up |
|
if( true == m_v3dUp.Normalise() ) |
|
{ |
|
//have a up vector only, so generate an arbitary `up'. |
|
m_v3dForwards.SetX( m_v3dUp.z ); |
|
m_v3dForwards.SetY( m_v3dUp.x ); |
|
m_v3dForwards.SetZ( m_v3dUp.y ); |
|
|
|
//will now get a 'guaranteed' right from this |
|
m_v3dRight = m_v3dForwards.Cross( m_v3dUp ); |
|
|
|
//and so can generate a true forwards |
|
m_v3dForwards = m_v3dUp.Cross( m_v3dRight ); |
|
} |
|
else |
|
{ |
|
//have no appropriate starting vectors, so fake it. |
|
m_v3dForwards.Set( 1.0f, 0.0f, 0.0f ); |
|
m_v3dUp.Set( 0.0f, 1.0f, 0.0f ); |
|
m_v3dRight.Set( 0.0f, 0.0f, 1.0f ); |
|
} |
|
|
|
} |
|
} |
|
|
|
private: |
|
AUVec3f m_v3dForwards; |
|
AUVec3f m_v3dUp; |
|
AUVec3f m_v3dRight; |
|
|
|
}; |
|
|
|
#endif //AUDORIENTATION3D_DEFINED
|