Intro :
Pour pouvoir observer nos entités dans une scène 3D, il faut pour cela mouvoir une caméra que l’on peut bouger aisément.
Prérequis :
– Savoir lire et écrire du C++
– Savoir utiliser les objets et fonctions mathématiques de la librairie D3DX
– Savoir ce qu’est une matrice
– Savoir ce que sont les transformations de repère
– Savoir utiliser la classe InputManager utilisée dans le code présenté
– Savoir utiliser les mathématiques des vecteurs (produit vectoriel et produit scalaire)
Explications :
Voici le code tout simplement de notre caméra à la première personne.
A noté l’utilisation de la classe InputManager avec les appels à INPUT_MANAGER dans le code.
Voici le code pour le fichier FPSCamera.h :
#ifndef FPS_CAMERA_H
#define FPS_CAMERA_H
#include <d3d10.h>
#include <d3dx10.h>
class FPSCamera
{
public:
FPSCamera();
virtual ~FPSCamera();
D3DXMATRIX* GetViewMatrix();
D3DXMATRIX* GetProjectionMatrix();
D3DXVECTOR3 GetPosition();
void LookAt(D3DXVECTOR3& target);
void UpdateLens(float fFov, float fAspect, float fNearZ, float fFarZ);
void SetSpeed(float fSpeed);
void Update(float dt);
void Walk(float d);
void Strafe(float d);
private:
void BuildView();
private:
D3DXMATRIX m_view;
D3DXMATRIX m_proj;
D3DXVECTOR3 m_pos;
D3DXVECTOR3 m_right;
D3DXVECTOR3 m_up;
D3DXVECTOR3 m_lookAt;
float m_fSpeed;
};
Voici le code pour le fichier FPSCamera.cpp :
#include "FPSCamera.h"
FPSCamera::FPSCamera() :
m_fSpeed(30)
{
D3DXMatrixIdentity(&m_view);
D3DXMatrixIdentity(&m_proj);
m_pos = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
m_up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
m_lookAt = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
UpdateLens((float)D3DX_PI * 0.25f, (float)D3D10_RENDERER->GetViewportWidth() / (float)D3D10_RENDERER->GetViewportHeight(), 0.1f, 100.0f);
}
FPSCamera::~FPSCamera()
{
}
D3DXMATRIX* FPSCamera::GetViewMatrix()
{
return &m_view;
}
D3DXMATRIX* FPSCamera::GetProjectionMatrix()
{
return &m_proj;
}
D3DXVECTOR3 FPSCamera::GetPosition()
{
return m_pos;
}
void FPSCamera::LookAt(D3DXVECTOR3& target)
{
D3DXVECTOR3 L = target - m_pos;
D3DXVec3Normalize(&L, &L);
D3DXVECTOR3 R;
D3DXVec3Cross(&R, &m_up, &L);
D3DXVec3Normalize(&R, &R);
D3DXVECTOR3 U;
D3DXVec3Cross(&U, &L, &R);
D3DXVec3Normalize(&U, &U);
m_pos = m_pos;
m_right = R;
m_up = U;
m_lookAt = L;
BuildView();
}
void FPSCamera::UpdateLens(float fFov, float fAspect, float fNearZ, float fFarZ)
{
D3DXMatrixPerspectiveFovLH(&m_proj, fFov, fAspect, fNearZ, fFarZ);
}
void FPSCamera::SetSpeed(float fSpeed)
{
m_fSpeed = fSpeed;
}
void FPSCamera::Walk(float d)
{
m_pos += d * m_lookAt;
}
void FPSCamera::Strafe(float d)
{
m_pos += d * m_right;
}
void FPSCamera::Update(float dt)
{
if (INPUT_MANAGER->IsKeyDown('Z'))
{
Walk(dt * m_fSpeed);
}
if (INPUT_MANAGER->IsKeyDown('S'))
{
Walk(dt * -m_fSpeed);
}
if (INPUT_MANAGER->IsKeyDown('D'))
{
Strafe(dt * m_fSpeed);
}
if (INPUT_MANAGER->IsKeyDown('Q'))
{
Strafe(dt * -m_fSpeed);
}
float x = 0.0f;
float y = 0.0f;
INPUT_MANAGER->GetMouseRelativePosition(x, y);
float pitch = y * dt * 1800;
float yAngle = x * dt * 1800;
/* Contrainte du pitch */
D3DXMATRIX R;
D3DXMatrixRotationAxis(&R, &m_right, pitch);
D3DXVECTOR3 tmpVect;
D3DXVec3TransformCoord(&tmpVect, &m_up, &R);
D3DXVECTOR3 axisY(0.0f, -1.0f, 0.0f);
if (D3DXVec3Dot(&tmpVect, &axisY) < 0.0f)
{
D3DXVec3TransformCoord(&m_up, &m_up, &R);
D3DXVec3TransformCoord(&m_lookAt, &m_lookAt, &R);
}
/* Rotate Y */
D3DXMatrixRotationY(&R, yAngle);
D3DXVec3TransformCoord(&m_right, &m_right, &R);
D3DXVec3TransformCoord(&m_up, &m_up, &R);
D3DXVec3TransformCoord(&m_lookAt, &m_lookAt, &R);
BuildView();
INPUT_MANAGER->CenterMouseCursor();
}
void FPSCamera::BuildView()
{
D3DXVec3Normalize(&m_lookAt, &m_lookAt);
D3DXVec3Cross(&m_up, &m_lookAt, &m_right);
D3DXVec3Normalize(&m_up, &m_up);
D3DXVec3Cross(&m_right, &m_up, &m_lookAt);
D3DXVec3Normalize(&m_right, &m_right);
float x = -D3DXVec3Dot(&m_pos, &m_right);
float y = -D3DXVec3Dot(&m_pos, &m_up);
float z = -D3DXVec3Dot(&m_pos, &m_lookAt);
m_view(0,0) = m_right.x;
m_view(1,0) = m_right.y;
m_view(2,0) = m_right.z;
m_view(3,0) = x;
m_view(0,1) = m_up.x;
m_view(1,1) = m_up.y;
m_view(2,1) = m_up.z;
m_view(3,1) = y;
m_view(0,2) = m_lookAt.x;
m_view(1,2) = m_lookAt.y;
m_view(2,2) = m_lookAt.z;
m_view(3,2) = z;
m_view(0,3) = 0.0f;
m_view(1,3) = 0.0f;
m_view(2,3) = 0.0f;
m_view(3,3) = 1.0f;
}
#endif
Comment se servir du code précédent ?
Ce qui nous intéresse dans cette implémentation de caméra ce sont la matrice de vue (m_view) et la matrice de projection (m_proj).
Dans votre propre code, avant d’effectuer le rendu de vos modèles 3D vos devez spécifier ces matrices au shader correspondant :
m_pViewShaderVariable->SetMatrix((float*)CAMERA->GetViewMatrix()); m_pProjShaderVariable->SetMatrix((float*)CAMERA->GetProjectionMatrix();
Et voilà c’est tout simple !
Résumé :
Nous avons implémenté une caméra à la première personne (FPS) qui nous permet de naviguer facilement dans notre scène 3D.
Nous accédons aux matrices de vue et de projection avec les méthodes GetViewMatrix() et GetProjectionMatrix().
Références :
– Introduction to DirectX 9.0c – A shader approach

