I'm trying to create a first-person shooter camera for my DirectX game. But I'm struggling in trying to get my view matrix right. At the moment I have only got a triangle to display on the screen, but when I rotate the camera and move forward it seems like the triangle is rotating around the camera instead. Here is the code I have done for the Camera Class
Camera.h
#pragma once
#include"Window.h"
#include"Matrix.h"
#include "Vector3.h"
class Camera
{
public:
Camera();
Camera(float pitch, float yaw, Vector3 position);
~Camera();
void Update();
D3DXMATRIX BuildViewMatrix();
Vector3 GetPosition() const { return position; }
void SetPosition(Vector3 val) { position = val; }
protected:
float yaw;
float pitch;
Vector3 position;
};
Camera.cpp
#include"Camera.h"
Camera::Camera()
{
yaw = 0.0f;
pitch = 0.0f;
}
Camera::Camera(float pitch, float yaw, Vector3 position)
{
this->pitch = pitch;
this->yaw = yaw;
this->position = position;
}
Camera::~Camera()
{
}
void Camera::Update()
{
pitch = min(pitch, 90.0f);
pitch = max(pitch, -90.0f);
if(yaw < 0)
yaw += 360.0f;
if( yaw > 360.0f)
yaw -= 360.0f;
if(Window::GetKeyboard()->KeyDown(KEYBOARD_W))
{
D3DXMATRIX translateMat;
D3DXMatrixTranslation(&translateMat, position.x, position.y, position.z);
D3DXMATRIX rotationMat;
D3DXMatrixRotationY(&rotationMat, D3DXToRadian(yaw));
D3DXMATRIX forwardMat;
D3DXMatrixTranslation(&forwardMat, 0.0f, 0.0f, 10.0f);
D3DXMATRIX transformMat = translateMat * rotationMat * forwardMat;
position.x = transformMat._41;
position.y = transformMat._42;
position.z = transformMat._43;
std::cout << "X: " << transformMat._41 << std::endl;
std::cout << "Y: " << transformMat._42 << std::endl;
std::cout << "Z: " << transformMat._43 << std::endl;
}
else if(Window::GetKeyboard()->KeyDown(KEYBOARD_S))
{
D3DXMATRIX translateMat;
D3DXMatrixTranslation(&translateMat, position.x, position.y, position.z);
D3DXMATRIX rotationMat;
D3DXMatrixRotationY(&rotationMat, D3DXToRadian(yaw));
D3DXMATRIX forwardMat;
D3DXMatrixTranslation(&forwardMat, 0.0f, 0.0f, -10.0f);
D3DXMATRIX transformMat = translateMat * rotationMat * forwardMat;
position.x = transformMat._41;
position.y = transformMat._42;
position.z = transformMat._43;
std::cout << "X: " << transformMat._41 << std::endl;
std::cout << "Y: " << transformMat._42 << std::endl;
std::cout << "Z: " << transformMat._43 << std::endl;
}
if(Window::GetKeyboard()->KeyDown(KEYBOARD_Q))
{
yaw = yaw - 1.0f;
}
if(Window::GetKeyboard()->KeyDown(KEYBOARD_E))
{
yaw = yaw + 1.0f;
}
}
D3DXMATRIX Camera::BuildViewMatrix()
{
D3DXMATRIX translationMat;
D3DXMatrixTranslation(&translationMat, (position.x * -1.0f), (position.y * -1.0f), (position.z * -1.0f));
D3DXMATRIX yawMat;
D3DXMatrixRotationY(&yawMat, D3DXToRadian((yaw * -1.0f)));
D3DXMATRIX pitchMat;
D3DXMatrixRotationX(&pitchMat, D3DXToRadian((pitch * -1.0f)));
D3DXMATRIX viewMat = pitchMat * yawMat * translationMat;
return viewMat;
}
I'm using device->SetTransform(D3DTS_VIEW, &camera->BuildViewMatrix());
to send the view matrix to directX. What exactly am I doing wrong? Please help
UPDATE:
I have change the code and tried to use the D3DXMatrixLookAtLH
function (doesn't use the Camera at all), but this time, it doesn't do anything - the triangle stays in the same position no matter how I change the LookAt parameter on the function. Here is the code for it:
void Renderer::Render()
{
device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(40, 40, 40), 1.0f, 0);
device->BeginScene(); //Must be used as it tells DirectX we're starting to draw stuff.
D3DXMATRIX worldMat;
D3DXMatrixTranslation(&worldMat, 0.0f, 0.0f, 0.0f);
device->SetTransform(D3DTS_WORLD, &worldMat);
D3DXMATRIX viewMatrix;
D3DXMatrixLookAtLH( &viewMatrix,
&D3DXVECTOR3(0.0f, -100.0f, 1000.0f), //position
&D3DXVECTOR3(0.0f, 1.0f, 0.0f), //Look at
&D3DXVECTOR3(0.0f, 1.0f, 0.0f));
device->SetTransform(D3DTS_VIEW, &viewMatrix);
//device->SetTransform(D3DTS_VIEW, &camera->BuildViewMatrix());
D3DXMATRIX projMatrix;
D3DXMatrixPerspectiveFovLH( &projMatrix,
D3DXToRadian(45),
(float)width/(float)height,
1.0f,
10000.0f);
device->SetTransform(D3DTS_PROJECTION, &projMatrix);
device->SetFVF(VERTEXFORMAT);
device->SetStreamSource(0, vertexBuffer, 0, sizeof(VERTEX));
device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
device->EndScene(); //Thank you for waiting, I have finished drawing stuff on the screen, please handle the rest Mr DirectX.
device->Present(NULL, NULL, NULL, NULL);
}
Found out the problem, the matrices I've calculated isn't correct as well as the view matrix. the fixed it by adding the following codes:
Camera.h
#pragma once
#pragma comment(lib, "d3dx9.lib")
#include<d3dx9math.h>
#include"Window.h"
class Camera
{
public:
Camera();
Camera(float pitch, float yaw, D3DXVECTOR3 position);
~Camera();
void Update();
D3DXMATRIX BuildViewMatrix();
inline D3DXVECTOR3 GetPosition() const { return position; }
inline void SetPosition(D3DXVECTOR3 position){ this->position = position;}
protected:
float yaw;
float pitch;
float roll;
D3DXVECTOR3 position;
private:
D3DXVECTOR3 xAxis;
D3DXVECTOR3 yAxis;
D3DXVECTOR3 zAxis;
};
Camera.cpp
#include"Camera.h"
Camera::Camera()
{
yaw = 0.0f;
pitch = 0.0f;
roll = 0.0f;
}
//yaw = head twist
//pitch = head tilt
Camera::Camera(float pitch, float yaw, D3DXVECTOR3 position)
{
this->pitch = pitch;
this->yaw = yaw;
roll = 0.0f;
this->position = position;
xAxis = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
yAxis = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
zAxis = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
}
Camera::~Camera()
{
}
void Camera::Update()
{
if(Window::GetKeyboard()->KeyDown(KEYBOARD_Q)){
yaw -= 1.0f;
}
else if(Window::GetKeyboard()->KeyDown(KEYBOARD_E)){
yaw += 1.0f;
}
if(Window::GetKeyboard()->KeyDown(KEYBOARD_Z)){
pitch += 1.0f;
}
else if(Window::GetKeyboard()->KeyDown(KEYBOARD_X)){
pitch -= 1.0f;
}
pitch = min(pitch, 90.0f);
pitch = max(pitch, -90.0f);
if(yaw < 0.0f)
yaw += 360.0f;
if( yaw > 360.0f)
yaw -= 360.0f;
D3DXMATRIX yawMat;
D3DXMatrixRotationAxis(&yawMat, &yAxis, D3DXToRadian(yaw));
D3DXVec3TransformCoord(&zAxis, &zAxis, &yawMat);
D3DXVec3TransformCoord(&xAxis, &xAxis, &yawMat);
D3DXMATRIX pitchMat;
D3DXMatrixRotationAxis(&pitchMat, &xAxis, D3DXToRadian(pitch));
D3DXVec3TransformCoord(&zAxis, &zAxis, &pitchMat);
D3DXVec3TransformCoord(&yAxis, &yAxis, &pitchMat);
D3DXMATRIX rollMat;
D3DXMatrixRotationAxis(&rollMat, &zAxis, D3DXToRadian(0.0f));
D3DXVec3TransformCoord(&xAxis, &xAxis, &rollMat);
D3DXVec3TransformCoord(&yAxis, &yAxis, &rollMat);
if(Window::GetKeyboard()->KeyDown(KEYBOARD_W))
{
position = position + (zAxis * -1) * 10.0f;
}
else if(Window::GetKeyboard()->KeyDown(KEYBOARD_S))
{
position = position + zAxis * 10.0f;
}
if(Window::GetKeyboard()->KeyDown(KEYBOARD_A))
{
position = position + xAxis * 10.0f;
}
else if(Window::GetKeyboard()->KeyDown(KEYBOARD_D))
{
position = position - xAxis * 10.0f;
}
yaw = 0.0f;
pitch = 0.0f;
roll = 0.0f;
}
D3DXMATRIX Camera::BuildViewMatrix()
{
D3DXMATRIX viewMatrix;
D3DXMatrixIdentity(&viewMatrix);
viewMatrix._11 = xAxis.x;
viewMatrix._21 = xAxis.y;
viewMatrix._31 = xAxis.z;
viewMatrix._12 = yAxis.x;
viewMatrix._22 = yAxis.y;
viewMatrix._32 = yAxis.z;
viewMatrix._13 = zAxis.x;
viewMatrix._23 = zAxis.y;
viewMatrix._33 = zAxis.z;
viewMatrix._41 = D3DXVec3Dot(&position, &xAxis);
viewMatrix._42 = D3DXVec3Dot(&position, &yAxis);
viewMatrix._43 = D3DXVec3Dot(&position, &zAxis);
return viewMatrix;
}