{"id":2957,"date":"2015-06-17T17:30:56","date_gmt":"2015-06-17T17:30:56","guid":{"rendered":"http:\/\/anthroponaute.fr\/blog-informatique\/?p=2957"},"modified":"2015-11-24T17:44:15","modified_gmt":"2015-11-24T17:44:15","slug":"une-camera-premiere-personne-fps","status":"publish","type":"post","link":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/?p=2957","title":{"rendered":"Une cam\u00e9ra \u00e0 la premi\u00e8re personne (FPS)"},"content":{"rendered":"<p><strong>Intro :<\/strong><\/p>\n<p><a href=\"https:\/\/anthropoya.cluster014.ovh.net\/blog-informatique\/wp-content\/uploads\/2015\/06\/camera.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone  wp-image-2959\" src=\"https:\/\/anthropoya.cluster014.ovh.net\/blog-informatique\/wp-content\/uploads\/2015\/06\/camera.jpg\" alt=\"camera\" width=\"403\" height=\"289\" srcset=\"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/06\/camera.jpg 1024w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/06\/camera-300x215.jpg 300w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/06\/camera-624x447.jpg 624w\" sizes=\"(max-width: 403px) 100vw, 403px\" \/><\/a><\/p>\n<p>Pour pouvoir observer nos entit\u00e9s dans une sc\u00e8ne 3D, il faut pour cela mouvoir <strong>une cam\u00e9ra<\/strong> que l&rsquo;on peut bouger ais\u00e9ment.<\/p>\n<p><strong>Pr\u00e9requis : <\/strong><\/p>\n<p>&#8211; Savoir lire et \u00e9crire du C++<\/p>\n<p>&#8211; Savoir utiliser les objets et fonctions math\u00e9matiques de la librairie D3DX<\/p>\n<p>&#8211; Savoir ce qu&rsquo;est une matrice<\/p>\n<p>&#8211; Savoir ce que sont les transformations de rep\u00e8re<\/p>\n<p>&#8211; Savoir utiliser la classe <em>InputManager<\/em> utilis\u00e9e dans le code pr\u00e9sent\u00e9<\/p>\n<p>&#8211; Savoir utiliser les math\u00e9matiques des vecteurs (<em>produit vectoriel<\/em> et <em>produit scalaire<\/em>)<\/p>\n<p><strong>Explications :<\/strong><\/p>\n<p>Voici le code tout simplement de notre cam\u00e9ra \u00e0 la premi\u00e8re personne.<\/p>\n<p>A not\u00e9 l&rsquo;utilisation de <strong>la classe InputManage<\/strong>r avec les appels \u00e0 INPUT_MANAGER dans le code.<\/p>\n<p>Voici le code pour le fichier FPSCamera.h :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#ifndef FPS_CAMERA_H\r\n#define FPS_CAMERA_H\r\n\r\n#include &lt;d3d10.h&gt;\r\n#include &lt;d3dx10.h&gt;\r\n\r\nclass FPSCamera\r\n{\r\npublic:\r\n\u00a0\u00a0 \u00a0FPSCamera();\r\n\u00a0\u00a0 \u00a0virtual ~FPSCamera();\r\n\r\n\u00a0\u00a0 \u00a0D3DXMATRIX* GetViewMatrix();\r\n\u00a0\u00a0 \u00a0D3DXMATRIX* GetProjectionMatrix();\r\n\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 GetPosition();\r\n\r\n\u00a0\u00a0 \u00a0void LookAt(D3DXVECTOR3&amp; target);\r\n\r\n\u00a0\u00a0 \u00a0void UpdateLens(float fFov, float fAspect, float fNearZ, float fFarZ);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0void SetSpeed(float fSpeed);\r\n\r\n\u00a0\u00a0 \u00a0void Update(float dt);\r\n\r\n\u00a0\u00a0 \u00a0void Walk(float d);\r\n\r\n\u00a0\u00a0 \u00a0void Strafe(float d);\r\n\r\nprivate:\r\n\u00a0\u00a0 \u00a0void BuildView();\r\n\r\nprivate:\r\n\u00a0\u00a0 \u00a0D3DXMATRIX m_view;\r\n\u00a0\u00a0 \u00a0D3DXMATRIX m_proj;\r\n\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 m_pos;\r\n\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 m_right;\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 m_up;\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 m_lookAt;\r\n\r\n\u00a0\u00a0 \u00a0float m_fSpeed;\r\n};\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Voici le code pour le fichier FPSCamera.cpp :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &quot;FPSCamera.h&quot;\r\n\r\nFPSCamera::FPSCamera() :\r\nm_fSpeed(30)\r\n{\r\n\u00a0\u00a0 \u00a0D3DXMatrixIdentity(&amp;m_view);\r\n\u00a0\u00a0 \u00a0D3DXMatrixIdentity(&amp;m_proj);\r\n\r\n\u00a0\u00a0 \u00a0m_pos = D3DXVECTOR3(0.0f, 0.0f, 0.0f);\r\n\u00a0\u00a0 \u00a0m_right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);\r\n\u00a0\u00a0 \u00a0m_up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);\r\n\u00a0\u00a0 \u00a0m_lookAt = D3DXVECTOR3(0.0f, 0.0f, 1.0f);\r\n\r\n\u00a0\u00a0 \u00a0UpdateLens((float)D3DX_PI * 0.25f, (float)D3D10_RENDERER-&gt;GetViewportWidth() \/ (float)D3D10_RENDERER-&gt;GetViewportHeight(), 0.1f, 100.0f);\r\n}\r\n\r\nFPSCamera::~FPSCamera()\r\n{\r\n}\r\n\r\nD3DXMATRIX* FPSCamera::GetViewMatrix()\r\n{\r\n\u00a0\u00a0 \u00a0return &amp;m_view;\r\n}\r\n\r\nD3DXMATRIX* FPSCamera::GetProjectionMatrix()\r\n{\r\n\u00a0\u00a0 \u00a0return &amp;m_proj;\r\n}\r\n\r\nD3DXVECTOR3 FPSCamera::GetPosition()\r\n{\r\n\u00a0\u00a0 \u00a0return m_pos;\r\n}\r\n\r\nvoid FPSCamera::LookAt(D3DXVECTOR3&amp; target)\r\n{\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 L = target - m_pos;\r\n\u00a0\u00a0 \u00a0D3DXVec3Normalize(&amp;L, &amp;L);\r\n\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 R;\r\n\u00a0\u00a0 \u00a0D3DXVec3Cross(&amp;R, &amp;m_up, &amp;L);\r\n\u00a0\u00a0 \u00a0D3DXVec3Normalize(&amp;R, &amp;R);\r\n\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 U;\r\n\u00a0\u00a0 \u00a0D3DXVec3Cross(&amp;U, &amp;L, &amp;R);\r\n\u00a0\u00a0 \u00a0D3DXVec3Normalize(&amp;U, &amp;U);\r\n\r\n\u00a0\u00a0 \u00a0m_pos = m_pos;\r\n\u00a0\u00a0 \u00a0m_right = R;\r\n\u00a0\u00a0 \u00a0m_up = U;\r\n\u00a0\u00a0 \u00a0m_lookAt = L;\r\n\r\n\u00a0\u00a0 \u00a0BuildView();\r\n}\r\n\r\nvoid FPSCamera::UpdateLens(float fFov, float fAspect, float fNearZ, float fFarZ)\r\n{\r\n\u00a0\u00a0 \u00a0D3DXMatrixPerspectiveFovLH(&amp;m_proj, fFov, fAspect, fNearZ, fFarZ);\r\n}\r\n\u00a0\u00a0 \u00a0\r\nvoid FPSCamera::SetSpeed(float fSpeed)\r\n{\r\n\u00a0\u00a0 \u00a0m_fSpeed = fSpeed;\r\n}\r\n\r\nvoid FPSCamera::Walk(float d)\r\n{\r\n\u00a0\u00a0 \u00a0m_pos += d * m_lookAt;\r\n}\r\n\r\nvoid FPSCamera::Strafe(float d)\r\n{\r\n\u00a0\u00a0 \u00a0m_pos += d * m_right;\r\n}\r\n\r\nvoid FPSCamera::Update(float dt)\r\n{\r\n\u00a0\u00a0 \u00a0if (INPUT_MANAGER-&gt;IsKeyDown('Z'))\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Walk(dt * m_fSpeed);\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0if (INPUT_MANAGER-&gt;IsKeyDown('S'))\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Walk(dt * -m_fSpeed);\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0if (INPUT_MANAGER-&gt;IsKeyDown('D'))\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Strafe(dt * m_fSpeed);\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0if (INPUT_MANAGER-&gt;IsKeyDown('Q'))\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Strafe(dt * -m_fSpeed);\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0float x = 0.0f;\r\n\u00a0\u00a0 \u00a0float y = 0.0f;\r\n\r\n\u00a0\u00a0  INPUT_MANAGER-&gt;GetMouseRelativePosition(x, y);\r\n\r\n\u00a0\u00a0 \u00a0float pitch = y * dt * 1800;\r\n\u00a0\u00a0 \u00a0float yAngle = x * dt * 1800;\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 \/* Contrainte du pitch *\/\r\n\r\n\u00a0\u00a0 \u00a0D3DXMATRIX R;\r\n\u00a0\u00a0 \u00a0D3DXMatrixRotationAxis(&amp;R, &amp;m_right, pitch);\r\n\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 tmpVect;\r\n\u00a0\u00a0 \u00a0D3DXVec3TransformCoord(&amp;tmpVect, &amp;m_up, &amp;R);\r\n\r\n\u00a0\u00a0 \u00a0D3DXVECTOR3 axisY(0.0f, -1.0f, 0.0f);\r\n\r\n\u00a0\u00a0 \u00a0if (D3DXVec3Dot(&amp;tmpVect, &amp;axisY) &lt; 0.0f)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0D3DXVec3TransformCoord(&amp;m_up, &amp;m_up, &amp;R);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0D3DXVec3TransformCoord(&amp;m_lookAt, &amp;m_lookAt, &amp;R);\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\/* Rotate Y *\/\r\n\r\n\u00a0\u00a0 \u00a0D3DXMatrixRotationY(&amp;R, yAngle);\r\n\u00a0\u00a0 \u00a0D3DXVec3TransformCoord(&amp;m_right, &amp;m_right, &amp;R);\r\n\u00a0\u00a0 \u00a0D3DXVec3TransformCoord(&amp;m_up, &amp;m_up, &amp;R);\r\n\u00a0\u00a0 \u00a0D3DXVec3TransformCoord(&amp;m_lookAt, &amp;m_lookAt, &amp;R);\r\n\r\n\u00a0\u00a0 \u00a0BuildView();\r\n\r\n\u00a0\u00a0 \u00a0INPUT_MANAGER-&gt;CenterMouseCursor();\r\n}\r\n\r\nvoid FPSCamera::BuildView()\r\n{\r\n\u00a0\u00a0 \u00a0D3DXVec3Normalize(&amp;m_lookAt, &amp;m_lookAt);\r\n\r\n\u00a0\u00a0 \u00a0D3DXVec3Cross(&amp;m_up, &amp;m_lookAt, &amp;m_right);\r\n\u00a0\u00a0 \u00a0D3DXVec3Normalize(&amp;m_up, &amp;m_up);\r\n\r\n\u00a0\u00a0 \u00a0D3DXVec3Cross(&amp;m_right, &amp;m_up, &amp;m_lookAt);\r\n\u00a0\u00a0 \u00a0D3DXVec3Normalize(&amp;m_right, &amp;m_right);\r\n\r\n\u00a0\u00a0 \u00a0float x = -D3DXVec3Dot(&amp;m_pos, &amp;m_right);\r\n\u00a0\u00a0 \u00a0float y = -D3DXVec3Dot(&amp;m_pos, &amp;m_up);\r\n\u00a0\u00a0 \u00a0float z = -D3DXVec3Dot(&amp;m_pos, &amp;m_lookAt);\r\n\r\n\u00a0\u00a0 \u00a0m_view(0,0) = m_right.x;\r\n\u00a0\u00a0 \u00a0m_view(1,0) = m_right.y;\r\n\u00a0\u00a0 \u00a0m_view(2,0) = m_right.z;\r\n\u00a0\u00a0 \u00a0m_view(3,0) = x;\r\n\r\n\u00a0\u00a0 \u00a0m_view(0,1) = m_up.x;\r\n\u00a0\u00a0 \u00a0m_view(1,1) = m_up.y;\r\n\u00a0\u00a0 \u00a0m_view(2,1) = m_up.z;\r\n\u00a0\u00a0 \u00a0m_view(3,1) = y;\r\n\r\n\u00a0\u00a0 \u00a0m_view(0,2) = m_lookAt.x;\r\n\u00a0\u00a0 \u00a0m_view(1,2) = m_lookAt.y;\r\n\u00a0\u00a0 \u00a0m_view(2,2) = m_lookAt.z;\r\n\u00a0\u00a0 \u00a0m_view(3,2) = z;\r\n\r\n\u00a0\u00a0 \u00a0m_view(0,3) = 0.0f;\r\n\u00a0\u00a0 \u00a0m_view(1,3) = 0.0f;\r\n\u00a0\u00a0 \u00a0m_view(2,3) = 0.0f;\r\n\u00a0\u00a0 \u00a0m_view(3,3) = 1.0f;\r\n}\r\n\r\n#endif\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"text-decoration: underline;\">Comment se servir du code pr\u00e9c\u00e9dent ?\u00a0 <\/span><\/p>\n<p>Ce qui nous int\u00e9resse dans cette impl\u00e9mentation de cam\u00e9ra ce sont <strong>la matrice de vue<\/strong> (m_view) et <strong>la matrice de projection<\/strong> (m_proj).<\/p>\n<p>Dans votre propre code, avant d&rsquo;effectuer le rendu de vos mod\u00e8les 3D vos devez sp\u00e9cifier ces matrices au shader correspondant :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nm_pViewShaderVariable-&gt;SetMatrix((float*)CAMERA-&gt;GetViewMatrix());\r\nm_pProjShaderVariable-&gt;SetMatrix((float*)CAMERA-&gt;GetProjectionMatrix();\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Et voil\u00e0 c&rsquo;est tout simple !<\/p>\n<p>&nbsp;<\/p>\n<p><strong>R\u00e9sum\u00e9 :<\/strong><\/p>\n<p>Nous avons impl\u00e9ment\u00e9 une cam\u00e9ra \u00e0 la premi\u00e8re personne (FPS) qui nous permet de naviguer facilement dans notre sc\u00e8ne 3D.<\/p>\n<p>Nous acc\u00e9dons aux matrices de vue et de projection avec les m\u00e9thodes <strong>GetViewMatrix()<\/strong> et <strong>GetProjectionMatrix()<\/strong>.<\/p>\n<p><strong>R\u00e9f\u00e9rences :<\/strong><\/p>\n<p>&#8211; Introduction to DirectX 9.0c &#8211; A shader approach<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Intro : Pour pouvoir observer nos entit\u00e9s dans une sc\u00e8ne 3D, il faut pour cela mouvoir une cam\u00e9ra que l&rsquo;on peut bouger ais\u00e9ment. Pr\u00e9requis : &#8211; Savoir lire et \u00e9crire du C++ &#8211; Savoir utiliser les objets et fonctions math\u00e9matiques de la librairie D3DX &#8211; Savoir ce qu&rsquo;est une matrice &#8211; Savoir ce que sont [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/2957"}],"collection":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2957"}],"version-history":[{"count":40,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/2957\/revisions"}],"predecessor-version":[{"id":3983,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/2957\/revisions\/3983"}],"wp:attachment":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2957"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2957"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2957"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}