English

OpenGL Linux game

Descent, first person a spectate kamera.

Zdroják ke stažení (541,5kB)

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 camera view
	if((m_eCamView == K_CAM_FIRST_PERSON) || (m_eCamView == K_CAM_SPECTATE))
	{
		RestrictCamView();
	}
}


vypočítá střed render okna podle šířky a výšky tohoto okna.

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


Získá aktuální pozici kurzoru myši.

// Get current mouse cursor position
int aiPos[2];
aiPos[0] = m_pGameData->GetMouse()->MousePosition()[0];
aiPos[1] = m_pGameData->GetMouse()->MousePosition()[1];


Zjistí, kterým směrem se pohnul kurzor od středu okna.

// Calculate mouse step
int aiStep[2];
aiStep[0] = (aiPos[0] - aiMiddle[0]);
aiStep[1] = (aiPos[1] - aiMiddle[1]);


Změní rotační vektor podle směru pohybu kurzoru.

// Change rotation angles by mouse step
m_kAngle.AddScalar((float)aiStep[0]*0.01 ,1);
m_kAngle.AddScalar((float)aiStep[1]*0.01 ,0);


Vrátí kurzor zpět do středu okna.

// Move mouse cursor to the middle of screen
SDL_WarpMouse(aiMiddle[0], aiMiddle[1]);


Pokud je first person, nebo spectate mód kamery, tak se omezí rotace kamery tak, aby se otáčela maximálně kolmo vzhůru a kolmo dolu.

// If spectator or first person view than restric camera view
if((m_eCamView == K_CAM_FIRST_PERSON) || (m_eCamView == K_CAM_SPECTATE))
{
	RestrictCamView();
}



home / opengl game


Valid XHTML 1.0 Transitional