English
 |
Descent, first person a spectate kamera.
|
 |
21.06.2006
Program načte ze souboru map000.lua základní pozici a rotaci kamery, zda se bude pohybovat pomocí myši, typ a rychlost kamery.
camera0=
{
pos_x=0,
pos_y=0,
pos_z=60,
rot_x=0,
rot_y=0,
rot_z=0,
mousemove=true,
descent=false,
firstperson=true,
spectate=false,
speed=150
}
Pohyb kamery prostorem se provádí změnou modelové matice
///\brief Look at the scene by camera
void CCamera::Look()
{
// Load OpenGL model matrix from camera matrix
glLoadMatrixf(m_kMatrix.GetMatrix());
}
Matice se mění podle aktuální pozice a rotace kamery, definované jako trojrozměrný vektor CVector3
CVector3 m_kPosition; ///< Camera position
CVector3 m_kAngle; ///< Rotation angle
Budeme potřebovat následující funkce třídy CQuaternion a CMatrix:
FromAxisAngle(...) převede rotační vektor kamery na quaternion
float m_afTuple[4];
///\brief Translate axis angle to quaternion
void CQuaternion::FromAxisAngle( CVector3 _kAngle )
{
float fAngle;
CVector3 kSin, kCos;
fAngle = _kAngle[0] * 0.5f;
kSin[0] = sin( fAngle );
kCos[0] = cos( fAngle );
fAngle = _kAngle[1] * 0.5f;
kSin[1] = sin( fAngle );
kCos[1] = cos( fAngle );
fAngle = _kAngle[2] * 0.5f;
kSin[2] = sin( fAngle );
kCos[2] = cos( fAngle );
float fSqrCos = kCos[0] * kCos[1];
float fSqrSin = kSin[0] * kSin[1];
m_afTuple[0] = ( float )( kSin[0] * kCos[1] * kCos[2] - kCos[0] * kSin[1] * kSin[2] );
m_afTuple[1] = ( float )( kCos[0] * kSin[1] * kCos[2] + kSin[0] * kCos[1] * kSin[2] );
m_afTuple[2] = ( float )( fSqrCos * kSin[2] - fSqrSin * kCos[2] );
m_afTuple[3] = ( float )( fSqrCos * kCos[2] + fSqrSin * kSin[2] );
}
Funkce ToRotationMatrix (...) převede quaternion na rotační matici.
///\brief Translate quternion to rotation matrix
void CQuaternion::ToRotationMatrix (CMatrix& _rkRot)
{
_rkRot[0] = ( 1.0f - 2.0f * m_afTuple[1] * m_afTuple[1] - 2.0f * m_afTuple[2] * m_afTuple[2] );
_rkRot[1] = ( 2.0f * m_afTuple[0] * m_afTuple[1] + 2.0f * m_afTuple[3] * m_afTuple[2] );
_rkRot[2] = ( 2.0f * m_afTuple[0] * m_afTuple[2] - 2.0f * m_afTuple[3] * m_afTuple[1] );
_rkRot[4] = ( 2.0f * m_afTuple[0] * m_afTuple[1] - 2.0f * m_afTuple[3] * m_afTuple[2] );
_rkRot[5] = ( 1.0f - 2.0f * m_afTuple[0] * m_afTuple[0] - 2.0f * m_afTuple[2] * m_afTuple[2] );
_rkRot[6] = ( 2.0f * m_afTuple[1] * m_afTuple[2] + 2.0f * m_afTuple[3] * m_afTuple[0] );
_rkRot[8] = ( 2.0f * m_afTuple[0] * m_afTuple[2] + 2.0f * m_afTuple[3] * m_afTuple[1] );
_rkRot[9] = ( 2.0f * m_afTuple[1] * m_afTuple[2] - 2.0f * m_afTuple[3] * m_afTuple[0] );
_rkRot[10] = ( 1.0f - 2.0f * m_afTuple[0] * m_afTuple[0] - 2.0f * m_afTuple[1] * m_afTuple[1] );
}
Funkce SetMatrix(...) Nastaví matici 4x4
// 4x4 matrix array
// Standard matrix:
// |0, 1, 2 ,3|
// |4, 5, 6 ,7|
// |8, 9, 10 ,11|
// |12, 13, 14 ,15|
// OpenGL matrix:
// |0, 4, 8 ,12|
// |1, 5, 9 ,13|
// |2, 6, 10 ,14|
// |3, 7, 11 ,15|
float m_afMatrix[16];
///\brief Set matrix from float array
///\param *_pfMatrix Float array
///\param _iSize Size of float array, default 16
void CMatrix::SetMatrix( const float *_pfMatrix, const int _iSize )
{
for(int i=0; i<_iSize; i++)
{
m_afMatrix[i] = _pfMatrix[i];
}
}
Funkce Inverse() invertuje aktuální matici
///\brief Create inverse matrix
void CMatrix::Inverse()
{
float fA0 = m_afMatrix[ 0]*m_afMatrix[ 5] - m_afMatrix[ 1]*m_afMatrix[ 4];
float fA1 = m_afMatrix[ 0]*m_afMatrix[ 6] - m_afMatrix[ 2]*m_afMatrix[ 4];
float fA2 = m_afMatrix[ 0]*m_afMatrix[ 7] - m_afMatrix[ 3]*m_afMatrix[ 4];
float fA3 = m_afMatrix[ 1]*m_afMatrix[ 6] - m_afMatrix[ 2]*m_afMatrix[ 5];
float fA4 = m_afMatrix[ 1]*m_afMatrix[ 7] - m_afMatrix[ 3]*m_afMatrix[ 5];
float fA5 = m_afMatrix[ 2]*m_afMatrix[ 7] - m_afMatrix[ 3]*m_afMatrix[ 6];
float fB0 = m_afMatrix[ 8]*m_afMatrix[13] - m_afMatrix[ 9]*m_afMatrix[12];
float fB1 = m_afMatrix[ 8]*m_afMatrix[14] - m_afMatrix[10]*m_afMatrix[12];
float fB2 = m_afMatrix[ 8]*m_afMatrix[15] - m_afMatrix[11]*m_afMatrix[12];
float fB3 = m_afMatrix[ 9]*m_afMatrix[14] - m_afMatrix[10]*m_afMatrix[13];
float fB4 = m_afMatrix[ 9]*m_afMatrix[15] - m_afMatrix[11]*m_afMatrix[13];
float fB5 = m_afMatrix[10]*m_afMatrix[15] - m_afMatrix[11]*m_afMatrix[14];
float fDet = fA0*fB5-fA1*fB4+fA2*fB3+fA3*fB2-fA4*fB1+fA5*fB0;
float kInv[16];
kInv[0] = + m_afMatrix[ 5]*fB5 - m_afMatrix[ 6]*fB4 + m_afMatrix[ 7]*fB3;
kInv[1] = - m_afMatrix[ 1]*fB5 + m_afMatrix[ 2]*fB4 - m_afMatrix[ 3]*fB3;
kInv[2] = + m_afMatrix[13]*fA5 - m_afMatrix[14]*fA4 + m_afMatrix[15]*fA3;
kInv[3] = - m_afMatrix[ 9]*fA5 + m_afMatrix[10]*fA4 - m_afMatrix[11]*fA3;
kInv[4] = - m_afMatrix[ 4]*fB5 + m_afMatrix[ 6]*fB2 - m_afMatrix[ 7]*fB1;
kInv[5] = + m_afMatrix[ 0]*fB5 - m_afMatrix[ 2]*fB2 + m_afMatrix[ 3]*fB1;
kInv[6] = - m_afMatrix[12]*fA5 + m_afMatrix[14]*fA2 - m_afMatrix[15]*fA1;
kInv[7] = + m_afMatrix[ 8]*fA5 - m_afMatrix[10]*fA2 + m_afMatrix[11]*fA1;
kInv[8] = + m_afMatrix[ 4]*fB4 - m_afMatrix[ 5]*fB2 + m_afMatrix[ 7]*fB0;
kInv[9] = - m_afMatrix[ 0]*fB4 + m_afMatrix[ 1]*fB2 - m_afMatrix[ 3]*fB0;
kInv[10] = + m_afMatrix[12]*fA4 - m_afMatrix[13]*fA2 + m_afMatrix[15]*fA0;
kInv[11] = - m_afMatrix[ 8]*fA4 + m_afMatrix[ 9]*fA2 - m_afMatrix[11]*fA0;
kInv[12] = - m_afMatrix[ 4]*fB3 + m_afMatrix[ 5]*fB1 - m_afMatrix[ 6]*fB0;
kInv[13] = + m_afMatrix[ 0]*fB3 - m_afMatrix[ 1]*fB1 + m_afMatrix[ 2]*fB0;
kInv[14] = - m_afMatrix[12]*fA3 + m_afMatrix[13]*fA1 - m_afMatrix[14]*fA0;
kInv[15] = + m_afMatrix[ 8]*fA3 - m_afMatrix[ 9]*fA1 + m_afMatrix[10]*fA0;
float fInvDet = ((float)1.0)/fDet;
for(int i=0 ; i<16; i++)
{
kInv[i] *= fInvDet;
m_afMatrix[i] = kInv[i];
}
}
Funkce ChangeVectorGL(...) změní 3D vektor podle OpenGL matice.
///\brief Change OpenGL vector by matrix
inline void CMatrix::ChangeVectorGL( CVector3& _rkVec )
{
CVector3 kResult;
kResult[0] = (_rkVec[0] * m_afMatrix[0]) + (_rkVec[1] * m_afMatrix[4]) + (_rkVec[2] * m_afMatrix[8]);
kResult[1] = (_rkVec[0] * m_afMatrix[1]) + (_rkVec[1] * m_afMatrix[5]) + (_rkVec[2] * m_afMatrix[9]);
kResult[2] = (_rkVec[0] * m_afMatrix[2]) + (_rkVec[1] * m_afMatrix[6]) + (_rkVec[2] * m_afMatrix[10]);
_rkVec = kResult;
}
Funkce InverseTranslation(...) nastaví inverzní posunutí v matici z 3D vektoru.
///\brief Set matrix inverse translation from 3D vector
void CMatrix::InverseTranslation( CVector3 &_rkVector)
{
m_afMatrix[12] = -_rkVector[0];
m_afMatrix[13] = -_rkVector[1];
m_afMatrix[14] = -_rkVector[2];
}
Funkce Multiply(...) vynásobí aktuální matici kamery maticí v parametru funkce. Výsledek uloží do aktuální modelové matice kamery.
///\brief Multiply two matrices. Multiply current matrix with param matrix. Result is in changed current matrix.
void CMatrix::Multiply(CMatrix& _rkMat)
{
float afMatrix[16];
const float *m1 = m_afMatrix, *m2 = _rkMat.m_afMatrix;
afMatrix[0] = ( float ) (m1[0] * m2[0]) + (m1[4] * m2[1]) + (m1[8] * m2[2]);
afMatrix[1] = ( float ) (m1[1] * m2[0]) + (m1[5] * m2[1]) + (m1[9] * m2[2]);
afMatrix[2] = ( float ) (m1[2] * m2[0]) + (m1[6] * m2[1]) + (m1[10] * m2[2]);
afMatrix[3] = 0;
afMatrix[4] = ( float ) (m1[0] * m2[4]) + (m1[4] * m2[5]) + (m1[8] * m2[6]);
afMatrix[5] = ( float ) (m1[1] * m2[4]) + (m1[5] * m2[5]) + (m1[9] * m2[6]);
afMatrix[6] = ( float ) (m1[2] * m2[4]) + (m1[6] * m2[5]) + (m1[10] * m2[6]);
afMatrix[7] = 0;
afMatrix[8] = ( float ) (m1[0] * m2[8]) + (m1[4] * m2[9]) + (m1[8] * m2[10]);
afMatrix[9] = ( float ) (m1[1] * m2[8]) + (m1[5] * m2[9]) + (m1[9] * m2[10]);
afMatrix[10] = ( float )(m1[2] * m2[8]) + (m1[6] * m2[9]) + (m1[10] * m2[10]);
afMatrix[11] = 0;
afMatrix[12] = ( float )(m1[0] * m2[12]) + (m1[4] * m2[13]) + (m1[8] * m2[14]) + m1[12];
afMatrix[13] = ( float )(m1[1] * m2[12]) + (m1[5] * m2[13]) + (m1[9] * m2[14]) + m1[13];
afMatrix[14] = ( float )(m1[2] * m2[12]) + (m1[6] * m2[13]) + (m1[10] * m2[14]) + m1[14];
afMatrix[15] = 1;
SetMatrix( afMatrix );
}
Funkce MultiplyTranspose(...) transponovaně vynásobí aktuální matici kamery maticí v parametru funkce. Výsledek uloží do aktuální modelové matice kamery.
///\brief Multiply transpose two matrices (OpenGL matrices)
void CMatrix::MultiplyTranspose( CMatrix& _rkMat )
{
float afMatrix[16];
const float *m1 = m_afMatrix, *m2 = _rkMat.m_afMatrix;
afMatrix[0] = ( float )(m1[0] * m2[0]) + (m1[1] * m2[4]) + (m1[2] * m2[8]);
afMatrix[1] = ( float )(m1[0] * m2[1]) + (m1[1] * m2[5]) + (m1[2] * m2[9]);
afMatrix[2] = ( float )(m1[0] * m2[2]) + (m1[1] * m2[6]) + (m1[2] * m2[10]);
afMatrix[3] = 0;
afMatrix[4] = ( float )(m1[4] * m2[0]) + (m1[5] * m2[4]) + (m1[6] * m2[8]);
afMatrix[5] = ( float )(m1[4] * m2[1]) + (m1[5] * m2[5]) + (m1[6] * m2[9]);
afMatrix[6] = ( float )(m1[4] * m2[2]) + (m1[5] * m2[6]) + (m1[6] * m2[10]);
afMatrix[7] = 0;
afMatrix[8] = ( float )(m1[8] * m2[0]) + (m1[9] * m2[4]) + (m1[10] * m2[8]);
afMatrix[9] = ( float )(m1[8] * m2[1]) + (m1[9] * m2[5]) + (m1[10] * m2[9]);
afMatrix[10] = ( float )(m1[8] * m2[2]) + (m1[9] * m2[6]) + (m1[10] * m2[10]);
afMatrix[11] = 0;
afMatrix[12] = ( float )(m1[12] * m2[0]) + (m1[13] * m2[4]) + (m1[14] * m2[8]) + m1[12];
afMatrix[13] = ( float )(m1[12] * m2[1]) + (m1[13] * m2[5]) + (m1[14] * m2[9]) + m1[13];
afMatrix[14] = ( float )(m1[12] * m2[2]) + (m1[13] * m2[6]) + (m1[14] * m2[10]) + m1[14];
afMatrix[15] = 1;
SetMatrix( afMatrix );
}
Funkce
RotationXGL(...)
RotationYGL(...)
RotationZGL(...)
nastaví rotační matice XYZ podle rotačního vektoru.
///\brief Calculate OpenGL X rotation matrix
///\param _fAnlge Rotation vector
void CMatrix::RotationXGL( const float _fAngle )
{
const float fS = sin(_fAngle);
const float fC = cos(_fAngle);
m_afMatrix[5] = ( float )fC;
m_afMatrix[9] = ( float )-fS;
m_afMatrix[6] = ( float )fS;
m_afMatrix[10] = ( float )fC;
}
///\brief Calculate OpenGL Y rotation matrix
///\param _fAnlge Rotation vector
void CMatrix::RotationYGL( const float _fAngle )
{
const float fS = sin(_fAngle);
const float fC = cos(_fAngle);
m_afMatrix[0] = ( float )fC;
m_afMatrix[8] = ( float )fS;
m_afMatrix[2] = ( float )-fS;
m_afMatrix[10] = ( float )fC;
}
///\brief Calculate OpenGL Z rotation matrix
///\param _fAnlge Rotation vector
void CMatrix::RotationZGL( const float _fAngle )
{
const float fS = sin(_fAngle);
const float fC = cos(_fAngle);
m_afMatrix[0] = ( float )fC;
m_afMatrix[4] = ( float )-fS;
m_afMatrix[1] = ( float )fS;
m_afMatrix[5] = ( float )fC;
}
Funkce
ChangeVectorXGL(...)
ChangeVectorYGL(...)
ChangeVectorZGL(...)
změní XYZ koordinace vstupního vektoru podle OpenGL matice.
///\brief Change X vector coordination by OpenGL matrix
///\param _rkVec Vector to which change X coordination
void CMatrix::ChangeVectorXGL( CVector3& _rkVec )
{
float fVec = (_rkVec[0] * m_afMatrix[0]) + (_rkVec[1] * m_afMatrix[4]) + (_rkVec[2] * m_afMatrix[8]);
_rkVec[0] = fVec;
}
///\brief Change Y vector coordination by OpenGL matrix
///\param _rkVec Vector to which change Y coordination
void CMatrix::ChangeVectorYGL( CVector3& _rkVec )
{
float fVec = _rkVec[0] * m_afMatrix[1] + _rkVec[1] * m_afMatrix[5] + _rkVec[2] * m_afMatrix[9];
_rkVec[1] = fVec;
}
///\brief Change X vector coordination by OpenGL matrix
///\param _rkVec Vector to which change X coordination
inline void CMatrix::ChangeVectorZGL( CVector3& _rkVec )
{
float fVec = _rkVec[0] * m_afMatrix[2] + _rkVec[1] * m_afMatrix[6] + _rkVec[2] * m_afMatrix[10];
_rkVec[2] = fVec;
}
Změna modelové matice pro descent, first person a spectate kameru.
Změnu modelové matice provádí funkce ChangeMatrix()
///\brief Change camera matrix
void CCamera::ChangeMatrix()
{
// If descent view
if(m_eCamView == K_CAM_DESCENT)
{
// Slave matrices (reset)
CMatrix kT;
CMatrix kR;
// Set quaternion from angle
CQuaternion kQuat;
kQuat.FromAxisAngle(m_kAngle);
// Set rotation matrix from quaternion
kQuat.ToRotationMatrix(kR);
// Copy rotation to camera matrix
m_kMatrix = kR;
// Multiply previous matrix by new matrix
m_kMatrix.Multiply(m_kPrevMatrix);
// Set rotation matrix from current matrix
m_kRotMatrix = m_kMatrix;
// Inverse rotation matrix
m_kRotMatrix.Inverse();
// Set direction vector
m_kForward.Set(0,0,-1);
// Change direction vector by rotation matrix
m_kRotMatrix.ChangeVectorGL(m_kForward);
// Set up vector
m_kUp.Set(0,1,0);
// Change up vector by rotation matrix
m_kRotMatrix.ChangeVectorGL(m_kUp);
// Set right vector
m_kRight.Set(1,0,0);
// Change right vector by rotation matrix
m_kRotMatrix.ChangeVectorGL(m_kRight);
// Store current matrix to previous matrix
m_kPrevMatrix = m_kMatrix;
// Set inverse matrix from current position
kT.InverseTranslation(m_kPosition);
// Multiply inverse matrix and current position matrix
m_kMatrix.Multiply(kT);
// Reset angles
m_kAngle.Reset();
return;
}
// If spectator or first person view
if((m_eCamView == K_CAM_SPECTATE)||(m_eCamView == K_CAM_FIRST_PERSON))
{
// Slave direction vector
CVector3 kDirection;
// Slave matrices (reset)
CMatrix kMX;
CMatrix kMY;
CMatrix kMT;
// Set X rotation matrix
kMX.RotationXGL(m_kAngle[0]);
// Set Y rotation matrix
kMY.RotationYGL(m_kAngle[1]);
// Set inverse translation matrix
kMT.InverseTranslation(m_kPosition);
/////////////////////
// Set Z direction
//////////////////////
// Reset direction vector
kDirection.Set(0,0,-1);
kMY.ChangeVectorZGL(kDirection);
// Set Z coord to my direction
m_kForward.SetZ(kDirection[2]);
// Only if spectate view
if(m_eCamView == K_CAM_SPECTATE)
{
/////////////////////
// Set Y direction
//////////////////////
// Reset direction vector
kDirection.Set(0,0,-1);
kMX.ChangeVectorYGL(kDirection);
// Set Z coord to my direction
m_kForward.SetY(kDirection[1]);
}
////////////////////////////
// Calculate camera matrix
/////////////////////////////
// Copy slave matrix Y to camera matrix
m_kMatrix = kMY;
// Multiply by slave matrix X
m_kMatrix.MultiplyTranspose(kMX);
// Multiply by slave transform matrix Y
m_kMatrix.Multiply(kMT);
///////////////////
// Set X direction
///////////////////
// Reset direction vector
kDirection.Set(0,0,-1);
// Change coordination X in direction vector
m_kMatrix.ChangeVectorXGL(kDirection);
// Set X coord to my direction
m_kForward.SetX(kDirection[0]);
return;
}
}
Změna modelové matice pro descent kameru
Vytvoříme transformační a rotační matici
CMatrix kT;
CMatrix kR;
Získáme quaternion z rotačního vektoru.
CQuaternion kQuat;
kQuat.FromAxisAngle(m_kAngle);
Získáme rotační matici z quaternionu
kQuat.ToRotationMatrix(kR);
Zkopírujeme rotační matici do modelové matice kamery
m_kMatrix = kR;
Vynásobíme modelovou matici kamery maticí kamery předešlého snímku.
m_kMatrix.Multiply(m_kPrevMatrix);
Kopírujeme modelovou matici do rotační matice
m_kRotMatrix = m_kMatrix;
Invertujeme rotační matici
m_kRotMatrix.Inverse();
Nastavíme direction vektor. Rotační matice změní tento vektor.
m_kForward.Set(0,0,-1);
m_kRotMatrix.ChangeVectorGL(m_kForward);
Nastavíme up vektor. Rotační matice změní tento vektor.
m_kUp.Set(0,1,0);
m_kRotMatrix.ChangeVectorGL(m_kUp);
Nastavíme right vektor. Rotační matice změní tento vektor.
m_kRight.Set(1,0,0);
m_kRotMatrix.ChangeVectorGL(m_kRight);
Uložíme aktuální matici jako matici předešlého snímku.
m_kPrevMatrix = m_kMatrix;
Nastavíme inverzní transformační matici podle vektoru pozice kamery.
kT.InverseTranslation(m_kPosition);
Vynásobíme aktuální matici inverzní transformační maticí.
m_kMatrix.Multiply(kT);
Resetujem rotaci kamery.
m_kAngle.Reset();
Změna modelové matice pro first person kameru
Vytvoříme direction vektor, rotační matice X, Y a tranformační matici.
CVector3 kDirection;
CMatrix kMX;
CMatrix kMY;
CMatrix kMT;
Nastavíme rotační matici X,Y podle vektoru rotace. Inverzní transformační matici podle vektoru pozice kamery.
kMX.RotationXGL(m_kAngle[0]);
kMY.RotationYGL(m_kAngle[1]);
kMT.InverseTranslation(m_kPosition);
Nastavíme Z osu direction vektoru podle rotační matice Y.
kDirection.Set(0,0,-1);
kMY.ChangeVectorZGL(kDirection);
m_kForward.SetZ(kDirection[2]);
Zkopírujem rotační matici Y do modelové matice kamery.
m_kMatrix = kMY;
Transponovaně vynásobíme aktuální modelovou matici kamery rotační maticí X.
m_kMatrix.MultiplyTranspose(kMX);
Vynásobíme aktuální modelovou matici transformační maticí.
m_kMatrix.Multiply(kMT);
Nastavíme X osu direction vektoru podle aktuální modelové matice.
kDirection.Set(0,0,-1);
m_kMatrix.ChangeVectorXGL(kDirection);
m_kForward.SetX(kDirection[0]);
Změna modelové matice pro spectate kameru
Vytvoříme direction vektor, rotační matice X, Y a tranformační matici.
CVector3 kDirection;
CMatrix kMX;
CMatrix kMY;
CMatrix kMT;
Nastavíme rotační matici X,Y podle vektoru rotace. Inverzní transformační matici podle vektoru pozice kamery.
kMX.RotationXGL(m_kAngle[0]);
kMY.RotationYGL(m_kAngle[1]);
kMT.InverseTranslation(m_kPosition);
Nastavíme Z osu direction vektoru podle rotační matice Y.
kDirection.Set(0,0,-1);
kMY.ChangeVectorZGL(kDirection);
m_kForward.SetZ(kDirection[2]);
Nastavíme Y osu direction vektoru podle rotační matice X.
kDirection.Set(0,0,-1);
kMX.ChangeVectorYGL(kDirection);
m_kForward.SetY(kDirection[1]);
Zkopírujem rotační matici Y do modelové matice kamery.
m_kMatrix = kMY;
Transponovaně vynásobíme aktuální modelovou matici kamery rotační maticí X.
m_kMatrix.MultiplyTranspose(kMX);
Vynásobíme aktuální modelovou matici transformační maticí.
m_kMatrix.Multiply(kMT);
Nastavíme X osu direction vektoru podle aktuální modelové matice.
kDirection.Set(0,0,-1);
m_kMatrix.ChangeVectorXGL(kDirection);
m_kForward.SetX(kDirection[0]);
Změna pozičního m_kPosition a rotačního m_kAngle vektoru.
Změnu pozičního a rotačního vektoru provádí funkce:
GoForward()
GoBackward()
TurnLeft()
TurnRight()
StrafeRight()
StrafeLeft()
GoUp()
GoDown()
LurchLeft()
LurchRight()
TurnUp()
TurnDown()
které jsou volány po zmáčknutí určité klávesy definované v keymapě.
///\brief Go forward by camera
void CCamera::GoForward()
{
// If descent camera
if(m_eCamView == K_CAM_DESCENT)
{
// Change currect position by forward vector
m_kPosition += (m_kForward * m_fSpeed);
return;
}
// If first person camera
if(m_eCamView == K_CAM_FIRST_PERSON)
{
m_kPosition.SubtractScalar(m_fSpeed * m_kForward.GetScalar(0) ,0);
m_kPosition.AddScalar(m_fSpeed * m_kForward.GetScalar(2) ,2);
return;
}
// If spectate camera
if(m_eCamView == K_CAM_SPECTATE)
{
m_kPosition.SubtractScalar(m_fSpeed * m_kForward.GetScalar(0) ,0);
m_kPosition.SubtractScalar(m_fSpeed * m_kForward.GetScalar(1) ,1);
m_kPosition.AddScalar(m_fSpeed * m_kForward.GetScalar(2) ,2);
return;
}
}
///\brief Go backward by camera
void CCamera::GoBackward()
{
// If descent camera
if(m_eCamView == K_CAM_DESCENT)
{
// Change currect position by right vector
m_kPosition -= (m_kForward * m_fSpeed);
return;
}
// If first person camera
if(m_eCamView == K_CAM_FIRST_PERSON)
{
m_kPosition.SubtractScalar(-m_fSpeed * m_kForward.GetScalar(0) ,0);
m_kPosition.AddScalar(-m_fSpeed * m_kForward.GetScalar(2) ,2);
return;
}
// If spectate camera
if(m_eCamView == K_CAM_SPECTATE)
{
m_kPosition.SubtractScalar(-m_fSpeed * m_kForward.GetScalar(0) ,0);
m_kPosition.SubtractScalar(-m_fSpeed * m_kForward.GetScalar(1) ,1);
m_kPosition.AddScalar(-m_fSpeed * m_kForward.GetScalar(2) ,2);
return;
}
}
///\brief Turn left by camera
void CCamera::TurnLeft()
{
m_kAngle.SubtractScalar(m_fSpeed* 0.01f ,1);
}
///\brief Turn right by camera
void CCamera::TurnRight()
{
m_kAngle.AddScalar(m_fSpeed* 0.01f ,1);
}
///\brief Strafe left by camera
void CCamera::StrafeLeft()
{
// If descent camera
if(m_eCamView == K_CAM_DESCENT)
{
// Change currect position by right vector
m_kPosition -= (m_kRight * m_fSpeed);
}
else
{
SetStrafeDirection();
// Move by new direction
Move(m_fSpeed);
}
}
///\brief Strafe right by camera
void CCamera::StrafeRight()
{
// If descent camera
if(m_eCamView == K_CAM_DESCENT)
{
// Change currect position by right vector
m_kPosition += m_kRight * m_fSpeed;
}
else
{
SetStrafeDirection();
// Move by new direction
Move(-m_fSpeed);
}
}
///\brief Go up by camera
void CCamera::GoUp()
{
// If descent camera
if(m_eCamView == K_CAM_DESCENT)
{
// Change currect position by up vector
m_kPosition += m_kUp * m_fSpeed;
}
else
{
m_kPosition.AddScalar(m_fSpeed ,1);
}
}
///\brief Go down by camera
void CCamera::GoDown()
{
if(m_eCamView == K_CAM_DESCENT)
{
// Change currect position by up vector
m_kPosition -= m_kUp * m_fSpeed;
}
else
{
m_kPosition.SubtractScalar(m_fSpeed ,1);
}
}
///\brief Camera rotate left by Z axis
void CCamera::LurchLeft()
{
if(m_eCamView == K_CAM_DESCENT)
{
// Set angles
m_kAngle.SubtractScalar(m_fSpeed * 0.01f ,2);
}
}
///\brief Camera rotate right by Z axis
void CCamera::LurchRight()
{
if(m_eCamView == K_CAM_DESCENT)
{
// Set angle
m_kAngle.AddScalar(m_fSpeed * 0.01f ,2);
}
}
///\brief Rotate up by camera
void CCamera::TurnUp()
{
if(m_eCamView == K_CAM_DESCENT)
{
// Set angles
m_kAngle.AddScalar(m_fSpeed * 0.01f ,0);
}
else
{
m_kAngle.AddScalar(m_fSpeed * 0.01f ,0);
// If spectator or first person view than restric camera view
RestrictCamView();
}
}
///\brief Rotate down by camera
void CCamera::TurnDown()
{
if(m_eCamView == K_CAM_DESCENT)
{
// Set angles
m_kAngle.SubtractScalar(m_fSpeed * 0.01f ,0);
}
else
{
m_kAngle.SubtractScalar(m_fSpeed * 0.01f ,0);
// If spectator or first person view than restric camera view
RestrictCamView();
}
}
Funkce TurnUp() a TurnDown() volá funkci RestrictCamView() , která omezuje rotaci kamery. Kamera se díky tomu otočí maximálně kolmo vzhůru a kolmo dolu.
///\brief Restrict camera view. Up and down view is max 90 degree
void CCamera::RestrictCamView()
{
if ( m_kAngle[0] >= CMath::K_FI )
{
m_kAngle[0] = CMath::K_FI;
}
if ( m_kAngle[0] <= -CMath::K_FI )
{
m_kAngle[0] = -CMath::K_FI;
}
}
Rotace kamery pomocí myši
Kamera rotuje podle toho, kterým směrem se pohne kurzor myši.
Aktuální pozici kurzoru myši získáme odchycením SDL události SDL_MOUSEMOTION
///\brief Catch system messages
bool ProcessEvent()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
...
...
...
case SDL_MOUSEMOTION:
...
...
...
// Get mouse cursor position
g_pGameData->GetMouse()->MousePosition()[0] = event.motion.x;
g_pGameData->GetMouse()->MousePosition()[1] = event.motion.y;
break;
...
...
...
default:
break;
}
}
return true;
}
Funkce MouseRotate(...)
///\brief Camera rotation by mouse move
void CCamera::MouseRotate()
{
// Get global graphics options
TGraphicOption *pOptions = m_pGameData->GetGraphicOption();
// Set middle of screen
int aiMiddle[2];
aiMiddle[0] = pOptions->iWidth >> 1;
aiMiddle[1] = pOptions->iHeight >> 1;
// Get current mouse cursor position
int aiPos[2];
aiPos[0] = m_pGameData->GetMouse()->MousePosition()[0];
aiPos[1] = m_pGameData->GetMouse()->MousePosition()[1];
// Calculate mouse step
int aiStep[2];
aiStep[0] = (aiPos[0] - aiMiddle[0]);
aiStep[1] = (aiPos[1] - aiMiddle[1]);
// Change rotation angles by mouse step
m_kAngle.AddScalar((float)aiStep[0]*0.01 ,1);
m_kAngle.AddScalar((float)aiStep[1]*0.01 ,0);
// Move mouse cursor to the middle of screen
SDL_WarpMouse(aiMiddle[0], aiMiddle[1]);
// If spectator or first person view than restric c