Czech

OpenGL Linux game

Descent, first person and spectate camera.

Download source (541,5kB)

06.06.22

This program load from file map000.lua default camera position and rotation, load if camera was moving by mouse, load camera type and camera speed.

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
}


The camera moving through the space is implemented from changing camera model view matrix.

///\brief Look at the scene by camera
void CCamera::Look()
{
	// Load OpenGL model matrix from camera matrix
	glLoadMatrixf(m_kMatrix.GetMatrix());
}


The matrix is changing from current camera position and rotation 3D vector CVector3

CVector3 m_kPosition;	///< Camera position
CVector3 m_kAngle; ///< Rotation angle


We will need following functions of CQuaternion and CMatrix class:

FromAxisAngle(...) translate rotation camera vector to the 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] );
}


The ToRotationMatrix (...) function translate quaternion to the rotation matrix.

///\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] );
}


The SetMatrix(...) function set 4x4 matrix

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


The Inverse() function inverse current camera model view matrix

///\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];
	}
}


The ChangeVectorGL(...) function change 3D vector by OpenGL matrix.

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


The InverseTranslation(...) function set matrix inverse translation from 3D vector.

///\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];
}


The Multiply(...) function multiply current camera matrix with new matrix. The result is saved to current camera matrix.

///\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 );
}


The MultiplyTranspose(...) function transpose multiply current camera matrix with new matrix. The result is saved to current camera matrix.

///\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 );
}


Functions
RotationXGL(...)
RotationYGL(...)
RotationZGL(...)
set XYZ rotation matrix from rotation vector.

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


Functions
ChangeVectorXGL(...)
ChangeVectorYGL(...)
ChangeVectorZGL(...)
change XYZ vector coordination by OpenGL matrix.

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


Model view matrix for descent, first person and spectate camera.

The model view matrix change function 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;
	}
}


Model view matrix for descent camera.


Create transformation and rotation matrix.

CMatrix kT;
CMatrix kR;


Get quaternion from rotation vector.

CQuaternion kQuat;
kQuat.FromAxisAngle(m_kAngle);


Get rotation vector from quaternion.

kQuat.ToRotationMatrix(kR);


Copy rotation matrix to the camera model view matrix.

m_kMatrix = kR;


Multiply camera model view matrix with matrix of frame before.

m_kMatrix.Multiply(m_kPrevMatrix);


Copy model view matrix to the rotation matrix.

m_kRotMatrix = m_kMatrix;


Inverse rotation matrix.

m_kRotMatrix.Inverse();


Set DIRECTION vector. Rotation matrix change this vector.

m_kForward.Set(0,0,-1);
m_kRotMatrix.ChangeVectorGL(m_kForward);


Set UP vector. Rotation matrix change this vector.

m_kUp.Set(0,1,0);
m_kRotMatrix.ChangeVectorGL(m_kUp);


Set RIGHT vector. Rotation matrix change this vector..

m_kRight.Set(1,0,0);
m_kRotMatrix.ChangeVectorGL(m_kRight);


Save current matrix like a matrix of frame before.

m_kPrevMatrix = m_kMatrix;


Set inverse translation matrix from camera position vector.

kT.InverseTranslation(m_kPosition);


Multiply current matrix with inverse transformation matrix.

m_kMatrix.Multiply(kT);


Reset camera rotation vector.

m_kAngle.Reset();


Model view matrix for first person camera.


Create direction vector, XY rotation matrices and transformation matrix.

CVector3 kDirection;
CMatrix kMX;
CMatrix kMY;
CMatrix kMT;


Set rotation matrix XY from camera rotation vector. Set inverse transformation matrix from camera position vector.

kMX.RotationXGL(m_kAngle[0]);
kMY.RotationYGL(m_kAngle[1]);
kMT.InverseTranslation(m_kPosition);


Set Z axis of direction vector by Y rotation matrix.

kDirection.Set(0,0,-1);
kMY.ChangeVectorZGL(kDirection);
m_kForward.SetZ(kDirection[2]);


Copy rotation matrix Y to the camera model view matrix.

m_kMatrix = kMY;


Transpose multiply current camera model view matrix by X rotation matrix

m_kMatrix.MultiplyTranspose(kMX);


Multiply current model view matrix by transformation matrix.

m_kMatrix.Multiply(kMT);


Set X axis of direction vector by current camera model view matrix.

kDirection.Set(0,0,-1);
m_kMatrix.ChangeVectorXGL(kDirection);
m_kForward.SetX(kDirection[0]);

Model view matrix for spectate camera.


Create direction vector, XY rotation matrices and transformation matrix.

CVector3 kDirection;
CMatrix kMX;
CMatrix kMY;
CMatrix kMT;


Set rotation matrix XY from camera rotation vector. Set inverse transformation matrix from camera position vector.

kMX.RotationXGL(m_kAngle[0]);
kMY.RotationYGL(m_kAngle[1]);
kMT.InverseTranslation(m_kPosition);


Set Z axis of direction vector by Y rotation matrix.

kDirection.Set(0,0,-1);
kMY.ChangeVectorZGL(kDirection);
m_kForward.SetZ(kDirection[2]);


Set Y axis of direction vector by X rotation matrix.

kDirection.Set(0,0,-1);
kMX.ChangeVectorYGL(kDirection);
m_kForward.SetY(kDirection[1]);


Copy rotation matrix Y to the camera model view matrix.

m_kMatrix = kMY;


Transpose multiply current camera model view matrix by X rotation matrix

m_kMatrix.MultiplyTranspose(kMX);


Multiply current model view matrix by transformation matrix.

m_kMatrix.Multiply(kMT);


Set X axis of direction vector by current camera model view matrix.

kDirection.Set(0,0,-1);
m_kMatrix.ChangeVectorXGL(kDirection);
m_kForward.SetX(kDirection[0]);



Camera position m_kPosition and rotation m_kAngle vector.

Camera position and rotation vector change following functions:
GoForward()
GoBackward()
TurnLeft()
TurnRight()
StrafeRight()
StrafeLeft()
GoUp()
GoDown()
LurchLeft()
LurchRight()
TurnUp()
TurnDown()
there are called by some of keyboard key and there are defined in keyboard 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();
	}
}


Functions TurnUp() and TurnDown() call function RestrictCamView() , there is restrict camera rotation vector. The maximum camera moving is vertically up and down.

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



Camera rotation by mouse


The camera is rotate by mouse cursor step direction. We get current mouse cursor position by catching mouse SDL event 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;
}


The MouseRotate(...) function

///\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();
	}
}


calculate middle of screen from screen width and height.

// 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 position.

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


Calculate mouse cursor direction vector from middle of screen and current cursor position.

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


Change rotation vector by mouse cursor direction vector.

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


Return the mouse cursor back to the middle of screen.

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


If is set first person or spectate camera mode so restrict camera view. The maximum camera moving is vertically up and down.

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