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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#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 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
#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 :
|
1 2 |
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


