Am revenit la un proiect mai vechi, un .bsp loader(formatul folosit de quake 3) si m-am gandit sa-i adaug o clasa care sa simuleze o camera first person shooter. Informatiile pe care le retin pentru a reprezenta camera sunt cele 3 axe (X, Y si Z) si un vector de pozitie. Pentru a transforma obiectele in spatiul camerei construiesc inversa matricei determinata de aceste informatii in functia Look() astfel:
Cod sursă:
void CCamera::Look()
{
CMatrix mat(xAxis.x, yAxis.x, zAxis.x, 0.0f,
xAxis.y, yAxis.y, zAxis.y, 0.0f,
xAxis.z, yAxis.z, zAxis.z, 0.0f,
-Dot(eyePos,xAxis), -Dot(eyePos,yAxis),-Dot(eyePos,zAxis), 1.0f);
glMultMatrixf(*mat);
}
Problema este ca in timp ce ma "plimb" prin interiorul nivelului, camera capata o rotatie ciudata pentru care nu gasesc explicatie. Incercati sa rotiti camera stanga-dreapta veti observa la ce ma refer, linkul este aici:
http://files-upload.com/files/514988/bspmd3.rarCodul pentru camera este foarte mic si usor de inteles:
CCamera.h
Cod sursă:
#ifndef CCAMERA_H
#define CCAMERA_H
#include "CVector3D.h"
#include "CMatrix.h"
#include
namespace CAMERA
{
const unsigned int FPS_CAM = 0;
const unsigned int TPS_CAM = 1;
}
class CCamera
{
private:
unsigned int CameraType;
bool FlyMode; // Used only with FPS_CAM
float CameraSensitivity;
void RegenerateVectors();
public:
CVector3D eyePos;
CVector3D xAxis;
CVector3D yAxis;
CVector3D zAxis;
float AngleXZ;
float AngleYZ;
int *mx, *my, *w, *h;
CCamera():CameraSensitivity(0.1f)
{
CameraType = CAMERA::FPS_CAM;
FlyMode = true;
eyePos = CVector3D(0.0f, 0.0f, 6.0f);
xAxis = CVector3D(1.0f, 0.0f, 0.0f);
yAxis = CVector3D(0.0f, 1.0f, 0.0f);
zAxis = CVector3D(0.0f, 0.0f, 1.0f);
};
void Pitch(float angle);
void Yaw(float angle);
void Roll(float angle);
void Look();
void Set(int *_mx, int *_my, int *_w, int *_h);
void SetFly(bool FlyMode);
void SetCameraType(unsigned int CameraType);
void Move(float Amount);
void Strafe(float Amount);
void SetViewByMouse();
void SetPosition(CVector3D Position);
};
#endif
Camera.cpp
Cod sursă:
#include "CCamera.h"
#include
void CCamera::Set(int *_mx, int *_my, int *_w, int *_h)
{
mx = _mx;
my = _my;
w = _w;
h = _h;
}
void CCamera::Look()
{
CMatrix mat(xAxis.x, yAxis.x, zAxis.x, 0.0f,
xAxis.y, yAxis.y, zAxis.y, 0.0f,
xAxis.z, yAxis.z, zAxis.z, 0.0f,
-Dot(eyePos,xAxis), -Dot(eyePos,yAxis),-Dot(eyePos,zAxis), 1.0f);
glMultMatrixf(*mat);
}
void CCamera::Move(float Amount)
{
if (CameraType == CAMERA::FPS_CAM)
{
if ( FlyMode )
{
eyePos = eyePos + -zAxis * Amount;
}
else
{
eyePos.x = eyePos.x - zAxis.x * Amount;
eyePos.z = eyePos.z - zAxis.z * Amount;
}
}else
{
// Camera type CAMERA::TPS_CAM --- Not implemented yet
}
}
void CCamera::Strafe(float Amount)
{
eyePos += xAxis * Amount;
}
void CCamera::SetFly(bool FlyMode)
{
this->FlyMode = FlyMode;
}
void CCamera::SetCameraType(unsigned int CameraType)
{
this->CameraType = CameraType;
}
void CCamera::SetPosition(CVector3D Position)
{
eyePos = Position;
}
void CCamera::Pitch(float angle)
{
CMatrix mat;
mat.Rotate(angle, xAxis, true);
yAxis = yAxis.MatrixMultiply(mat);
zAxis = zAxis.MatrixMultiply(mat);
RegenerateVectors();
}
void CCamera::Yaw(float angle)
{
CMatrix mat;
mat.Rotate(angle, CVector3D(0.0f, 1.0f, 0.0f), true);
xAxis = xAxis.MatrixMultiply(mat);
zAxis = zAxis.MatrixMultiply(mat);
RegenerateVectors();
}
void CCamera::Roll(float angle)
{
CMatrix mat;
mat.Rotate(angle, zAxis, true);
xAxis = xAxis.MatrixMultiply(mat);
yAxis = yAxis.MatrixMultiply(mat);
RegenerateVectors();
}
void CCamera::RegenerateVectors()
{
zAxis.Normalize();
yAxis = Cross(zAxis, xAxis);
yAxis.Normalize();
xAxis = Cross(yAxis, zAxis);
xAxis.Normalize();
}
void CCamera::SetViewByMouse()
{
// Get current cursor position
int MiddleX = (*w) >> 1;
int MiddleY = (*h) >> 1;
// Now move it back to the middle of the screen
if (MiddleX==(*mx) && MiddleY==(*my))
return;
glutWarpPointer(MiddleX, MiddleY);
int X = (*mx) - MiddleX;
int Y = (*my) - MiddleY;
AngleXZ += X * CameraSensitivity;
AngleYZ += Y * CameraSensitivity;
Pitch(-Y * CameraSensitivity);
Yaw(-X * CameraSensitivity);
if (AngleYZ 90.0f)
{
Pitch(Y * CameraSensitivity);
AngleYZ = 90.0f;
}
}