/Engine/Cameras/ArcBallCamera.cs

https://bitbucket.org/tomas_vahalik/straiki-game-engine · C# · 266 lines · 208 code · 47 blank · 11 comment · 11 complexity · 03d7e3ad370d09dbc474916dcc5ce17a MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Text;
  6. using Microsoft.Xna.Framework;
  7. namespace StraikiEngine.Cameras
  8. {
  9. public class ArcBallCamera : TargetCamera
  10. {
  11. public Matrix Rotation = Matrix.Identity;
  12. private const float VerticalAngleMin = 0.01f;
  13. private const float VerticalAngleMax = MathHelper.Pi - 0.01f;
  14. private const float ZoomMin = 0.1f;
  15. private const float ZoomMax = 1500.0f;
  16. private static bool _positionOrRot = false;
  17. private float _zoom;
  18. public float Zoom
  19. {
  20. get
  21. {
  22. return _zoom;
  23. }
  24. set
  25. { // Keep zoom within range
  26. _viewMatrixDirty = true;
  27. _zoom = MathHelper.Clamp(value, ZoomMin, ZoomMax);
  28. }
  29. }
  30. public ArcBallCamera(GameScreen parent, Vector3 position) : base(parent, position)
  31. {
  32. }
  33. public ArcBallCamera(GameScreen parent, Vector3 position, float zoom) : this(parent, position, Vector3.Zero, zoom)
  34. {
  35. }
  36. public ArcBallCamera(GameScreen parent, Vector3 position, Vector3 target, float zoom) : base(parent, position, target)
  37. {
  38. Zoom = zoom;
  39. _position = position;
  40. Position = position;
  41. Yaw = DestYaw;
  42. Pitch = DestPitch;
  43. InitCam();
  44. }
  45. private float _horizontalAngle = MathHelper.PiOver2;
  46. public float HorizontalAngle
  47. {
  48. get
  49. {
  50. return _horizontalAngle;
  51. }
  52. set
  53. { // Keep horizontalAngle between -pi and pi.
  54. _horizontalAngle = value % MathHelper.Pi;
  55. }
  56. }
  57. private float _verticalAngle = MathHelper.PiOver2;
  58. public float VerticalAngle
  59. {
  60. get
  61. {
  62. return _verticalAngle;
  63. }
  64. set
  65. { // Keep vertical angle within tolerances
  66. _verticalAngle = MathHelper.Clamp(value, VerticalAngleMin, VerticalAngleMax);
  67. }
  68. }
  69. private readonly Vector3 _destination = new Vector3(140,0,205);
  70. private Vector3 _camStep;
  71. private const float DestYaw = 0.41f;
  72. private const float DestPitch = -0.57f;
  73. private bool _isMoving = false;
  74. private const int Iterations = 200;
  75. private int _iterDone;
  76. private void InitCam()
  77. {
  78. var diff = _destination - _lookAt;
  79. _camStep = diff/Iterations;
  80. _isMoving = true;
  81. _iterDone = Iterations;
  82. }
  83. public override void Update()
  84. {
  85. if (_isMoving)
  86. {
  87. if (_iterDone > 0)
  88. {
  89. _lookAt += _camStep;
  90. _iterDone--;
  91. }
  92. else
  93. {
  94. _isMoving = false;
  95. }
  96. ReCreateView();
  97. return;
  98. }
  99. if (!Active) return;
  100. _positionOrRot = Parent.Engine.Input.DoubleTap;
  101. Zoom += Parent.Engine.Input.ScaleChange;
  102. if (_positionOrRot)
  103. {
  104. if (Math.Abs(Parent.Engine.Input.MoveDelta.X - 0) > 0.0001)
  105. {
  106. Yaw += Parent.Engine.Input.MoveDelta.X;
  107. }
  108. if (Math.Abs(Parent.Engine.Input.MoveDelta.Y - 0) > 0.0001)
  109. {
  110. Pitch += Parent.Engine.Input.MoveDelta.Y;
  111. }
  112. if(_viewMatrixDirty)
  113. ReCreateView();
  114. }
  115. else
  116. {
  117. if (Math.Abs(Parent.Engine.Input.MoveDelta.X - 0) > 0.0001)
  118. MoveCameraRight(Parent.Engine.Input.MoveDelta.X*100);
  119. if (Math.Abs(Parent.Engine.Input.MoveDelta.Y - 0) > 0.0001)
  120. MoveCameraForward(Parent.Engine.Input.MoveDelta.Y*-100);
  121. if (_viewMatrixDirty)
  122. ReCreateView();
  123. }
  124. }
  125. private void ReCreateView()
  126. {
  127. //Calculate the relative position of the camera
  128. _position = Vector3.Transform(Vector3.Backward, Matrix.CreateFromYawPitchRoll(_yaw, _pitch, 0));
  129. //Convert the relative position to the absolute position
  130. _position *= Zoom;
  131. _position += _lookAt;
  132. //Calculate a new viewmatrix
  133. this.View = Matrix.CreateLookAt(_position, _lookAt, Vector3.Up);
  134. Position = _position;
  135. _viewMatrixDirty = false;
  136. }
  137. #region HelperMethods
  138. /// <summary>
  139. /// Moves the camera and lookAt at to the right,
  140. /// as seen from the camera, while keeping the same height
  141. /// </summary>
  142. public void MoveCameraRight(float amount)
  143. {
  144. var right = Vector3.Normalize(LookAt - ArcPosition); //calculate forward
  145. right = Vector3.Cross(right, Vector3.Up); //calculate the real right
  146. right.Y = 0;
  147. right.Normalize();
  148. LookAt += right * amount;
  149. }
  150. /// <summary>
  151. /// Moves the camera and lookAt forward,
  152. /// as seen from the camera, while keeping the same height
  153. /// </summary>
  154. public void MoveCameraForward(float amount)
  155. {
  156. Vector3 forward = Vector3.Normalize(LookAt - ArcPosition);
  157. forward.Y = 0;
  158. forward.Normalize();
  159. LookAt += forward * amount;
  160. }
  161. #endregion
  162. #region FieldsAndProperties
  163. private bool _viewMatrixDirty = true;
  164. public float MinPitch = -1f; //-MathHelper.PiOver2 + 0.3f;
  165. public float MaxPitch = -0.1f;//MathHelper.PiOver2 - 0.3f;
  166. private float _pitch;
  167. public float Pitch
  168. {
  169. get { return _pitch; }
  170. set
  171. {
  172. _viewMatrixDirty = true;
  173. _pitch = MathHelper.Clamp(value, MinPitch, MaxPitch);
  174. }
  175. }
  176. public float MinYaw = -0.55f; //-MathHelper.PiOver2 + 0.3f;
  177. public float MaxYaw = 0.55f;//MathHelper.PiOver2 - 0.3f;
  178. private float _yaw;
  179. public float Yaw
  180. {
  181. get { return _yaw; }
  182. set
  183. {
  184. _viewMatrixDirty = true;
  185. _yaw = MathHelper.Clamp(value, MinYaw, MaxYaw);
  186. }
  187. }
  188. private Vector3 _position;
  189. public Vector3 ArcPosition
  190. {
  191. get
  192. {
  193. if (_viewMatrixDirty)
  194. {
  195. ReCreateView();
  196. }
  197. return _position;
  198. }
  199. set { _position = value; }
  200. }
  201. private Vector3 _lookAt;
  202. public Vector3 LookAt
  203. {
  204. get { return _lookAt; }
  205. set
  206. {
  207. _viewMatrixDirty = true;
  208. _lookAt = value;
  209. }
  210. }
  211. #endregion
  212. #region ICamera Members
  213. public Matrix ViewProjectionMatrix
  214. {
  215. get { return View * Projection; }
  216. }
  217. #endregion
  218. }
  219. }