MovementController.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. //========================================================================
  2. // File: MovementController.cpp
  3. //
  4. // Part of the GameCode4 Application
  5. //
  6. // GameCode4 is the sample application that encapsulates much of the source code
  7. // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David
  8. // "Rez" Graham, published by Charles River Media.
  9. // ISBN-10: 1133776574 | ISBN-13: 978-1133776574
  10. //
  11. // If this source code has found it's way to you, and you think it has helped you
  12. // in any way, do the authors a favor and buy a new copy of the book - there are
  13. // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com
  14. // by clicking here:
  15. // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller=
  16. //
  17. // There's a companion web site at http://www.mcshaffry.com/GameCode/
  18. //
  19. // The source code is managed and maintained through Google Code:
  20. // http://code.google.com/p/gamecode4/
  21. //
  22. // (c) Copyright 2012 Michael L. McShaffry and David Graham
  23. //
  24. // This program is free software; you can redistribute it and/or
  25. // modify it under the terms of the GNU Lesser GPL v3
  26. // as published by the Free Software Foundation.
  27. //
  28. // This program is distributed in the hope that it will be useful,
  29. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  31. // http://www.gnu.org/licenses/lgpl-3.0.txt for more details.
  32. //
  33. // You should have received a copy of the GNU Lesser GPL v3
  34. // along with this program; if not, write to the Free Software
  35. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  36. //
  37. //========================================================================
  38. #include "../Unix/GameCodeStd.h"
  39. #include "Geometry.h"
  40. #include "MovementController.h"
  41. #include "SceneNodes.h"
  42. ////////////////////////////////////////////////////
  43. // MovementController Implementation - Chapter 10, page 282
  44. ////////////////////////////////////////////////////
  45. #define MAX(a, b) ((a) >= (b) ? (a) : (b))
  46. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  47. MovementController::MovementController(std::shared_ptr<SceneNode> object, float initialYaw, float initialPitch, bool rotateWhenLButtonDown)
  48. : m_object(object)
  49. {
  50. m_object->VGet()->Transform(&m_matToWorld, &m_matFromWorld);
  51. m_fTargetYaw = m_fYaw = glm::degrees(-initialYaw);
  52. m_fTargetPitch = m_fPitch = glm::degrees(initialPitch);
  53. m_maxSpeed = 30.0f; // 30 meters per second
  54. m_currentSpeed = 0.0f;
  55. glm::vec3 pos = geometry::GetPosition(m_matToWorld);
  56. m_matPosition = geometry::BuildTranslation(pos);
  57. float mouseX, mouseY;
  58. SDL_MouseButtonFlags mouseState = SDL_GetMouseState(&mouseX, &mouseY);
  59. m_lastMousePos.x = (int) mouseX;
  60. m_lastMousePos.y = (int) mouseY;
  61. memset(m_bKey, 0x00, sizeof(m_bKey));
  62. m_mouseLButtonDown = mouseState & SDL_BUTTON_LEFT;
  63. m_bRotateWhenLButtonDown = rotateWhenLButtonDown;
  64. }
  65. bool MovementController::VOnPointerButtonDown(const Point &mousePos, const int radius, const std::string &buttonName)
  66. {
  67. if (buttonName == "PointerLeft")
  68. {
  69. m_mouseLButtonDown = true;
  70. // We want mouse movement to be relative to the position
  71. // the cursor was at when the user first presses down on
  72. // the left button
  73. m_lastMousePos = mousePos;
  74. return true;
  75. }
  76. return false;
  77. }
  78. bool MovementController::VOnPointerButtonUp(const Point &mousePos, const int radius, const std::string &buttonName)
  79. {
  80. if (buttonName == "PointerLeft")
  81. {
  82. m_mouseLButtonDown = false;
  83. return true;
  84. }
  85. return false;
  86. }
  87. // class MovementController::VOnMouseMove - Chapter 10, page 282
  88. bool MovementController::VOnPointerMove(const Point &mousePos, const int radius)
  89. {
  90. // There are two modes supported by this controller.
  91. if (m_bRotateWhenLButtonDown)
  92. {
  93. // Mode 1 - rotate the view only when the left mouse button is down
  94. // Only look around if the left button is down
  95. if(m_lastMousePos!=mousePos && m_mouseLButtonDown)
  96. {
  97. m_fTargetYaw = m_fTargetYaw + (mousePos.x - m_lastMousePos.x);
  98. m_fTargetPitch = m_fTargetPitch + (mousePos.y - m_lastMousePos.y);
  99. m_lastMousePos = mousePos;
  100. }
  101. }
  102. else if(m_lastMousePos!=mousePos)
  103. {
  104. m_fTargetYaw = m_fTargetYaw + (mousePos.x - m_lastMousePos.x);
  105. m_fTargetPitch = m_fTargetPitch + (m_lastMousePos.y - mousePos.y);
  106. m_lastMousePos = mousePos;
  107. }
  108. return true;
  109. }
  110. // class MovementController::OnUpdate - Chapter 10, page 283
  111. void MovementController::OnUpdate(uint64_t const deltaMilliseconds)
  112. {
  113. //if (m_bKey['Q'])
  114. //{
  115. // // This code is a cheat to position the camera exactly in a given
  116. // // spot so I can take screen shots!
  117. // Mat4x4 camTranslate;
  118. // D3DXMatrixTranslation(&m_matPosition, 8.847f, 7.055f, 11.618f);
  119. // m_fTargetYaw = m_fYaw += -64.35f;
  120. // m_fTargetPitch = m_fPitch = 28.57f;
  121. // // Calculate the new rotation matrix from the camera
  122. // // yaw and pitch.
  123. // Mat4x4 matRot;
  124. // D3DXMatrixRotationYawPitchRoll(&matRot, DEGREES_TO_RADIANS(m_fYaw), DEGREES_TO_RADIANS(m_fPitch), 0);
  125. // // Create the new object-to-world matrix, and the
  126. // // new world-to-object matrix.
  127. // D3DXMatrixMultiply(&m_matToWorld, &matRot, &m_matPosition);
  128. // D3DXMatrixInverse(&m_matFromWorld, NULL, &m_matToWorld);
  129. // m_object->VSetTransform(&m_matToWorld, &m_matFromWorld);
  130. // return;
  131. //}
  132. bool bTranslating = false;
  133. glm::vec4 atWorld(0,0,0,0);
  134. glm::vec4 rightWorld(0,0,0,0);
  135. glm::vec4 upWorld(0,0,0,0);
  136. if (m_bKey[SDL_SCANCODE_W] || m_bKey[SDL_SCANCODE_S])
  137. {
  138. // In D3D, the "look at" default is always
  139. // the positive Z axis.
  140. glm::vec4 at = -g_Forward4;
  141. if (m_bKey[SDL_SCANCODE_S])
  142. at *= -1;
  143. // This will give us the "look at" vector
  144. // in world space - we'll use that to move
  145. // the camera.
  146. atWorld = m_matToWorld * at;
  147. bTranslating = true;
  148. }
  149. if (m_bKey[SDL_SCANCODE_A] || m_bKey[SDL_SCANCODE_D])
  150. {
  151. // In D3D, the "right" default is always
  152. // the positive X axis.
  153. glm::vec4 right = g_Right4;
  154. if (m_bKey[SDL_SCANCODE_A])
  155. right *= -1;
  156. // This will give us the "right" vector
  157. // in world space - we'll use that to move
  158. // the camera
  159. rightWorld = m_matToWorld * right;
  160. bTranslating = true;
  161. }
  162. if (m_bKey[SDL_SCANCODE_SPACE] || m_bKey[SDL_SCANCODE_C] || m_bKey[SDL_SCANCODE_X])
  163. {
  164. // In D3D, the "up" default is always
  165. // the positive Y axis.
  166. glm::vec4 up = g_Up4;
  167. if (!m_bKey[SDL_SCANCODE_SPACE])
  168. up *= -1;
  169. //Unlike strafing, Up is always up no matter
  170. //which way you are looking
  171. upWorld = up;
  172. bTranslating = true;
  173. }
  174. // Handling rotation as a result of mouse position
  175. {
  176. // The secret formula!!! Don't give it away!
  177. //If you are seeing this now, then you must be some kind of elite hacker!
  178. m_fYaw += (m_fTargetYaw - m_fYaw) * ( .35f );
  179. m_fTargetPitch = MAX(-90, MIN(90, m_fTargetPitch));
  180. m_fPitch += (m_fTargetPitch - m_fPitch) * ( .35f );
  181. // Calculate the new rotation matrix from the camera
  182. // yaw and pitch.
  183. glm::mat4 matRot = geometry::BuildYawPitchRoll(glm::radians(-m_fYaw), glm::radians(m_fPitch), 0);
  184. // Create the new object-to-world matrix, and the
  185. // new world-to-object matrix.
  186. m_matToWorld = m_matPosition * matRot;
  187. m_matFromWorld = glm::inverse(m_matToWorld);
  188. m_object->VSetTransform(m_matToWorld, m_matFromWorld);
  189. }
  190. if (bTranslating)
  191. {
  192. float elapsedTime = (float)deltaMilliseconds / 1000.0f;
  193. glm::vec3 direction = atWorld + rightWorld + upWorld;
  194. direction = glm::normalize(direction);
  195. // Ramp the acceleration by the elapsed time
  196. float numberOfSeconds = 5.f;
  197. m_currentSpeed += m_maxSpeed * ( (elapsedTime*elapsedTime) / numberOfSeconds);
  198. if (m_currentSpeed > m_maxSpeed)
  199. m_currentSpeed = m_maxSpeed;
  200. direction *= m_currentSpeed;
  201. glm::vec3 pos = geometry::GetPosition(m_matPosition) + direction;
  202. geometry::SetPosition(m_matPosition, pos);
  203. geometry::SetPosition(m_matToWorld, pos);
  204. m_matFromWorld = glm::inverse(m_matToWorld);
  205. m_object->VSetTransform(m_matToWorld, m_matFromWorld);
  206. }
  207. else
  208. {
  209. m_currentSpeed = 0.0f;
  210. }
  211. }