Camera.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. using System;
  2. using System.Diagnostics.CodeAnalysis;
  3. using System.Numerics;
  4. using System.Runtime.InteropServices;
  5. using Veldrid.Common;
  6. using Veldrid.Common.Tools;
  7. using Veldrid.Sdl2;
  8. namespace Veldrid.Common
  9. {
  10. public class Camera
  11. {
  12. private float _fov = 1f;
  13. private float _near = 0.1f;
  14. private float _far = 100f;
  15. private float _xangle = 0;
  16. private float _yangle = 0;
  17. private float _zangle = 0;
  18. private Matrix4x4 _viewMatrix;
  19. private Matrix4x4 _projectionMatrix;
  20. private Matrix4x4 _orthographicMatrix;
  21. private Matrix4x4 _ymirror = new Matrix4x4(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
  22. private Vector3 _position = new Vector3(0, 0, 5);
  23. private Vector3 _lookDirection = new Vector3(0, 0, 0);
  24. private float _moveSpeed = 1.0f;
  25. private float _yaw;
  26. private float _pitch;
  27. private float _roll;
  28. private Vector2 _mousePressedPos;
  29. private bool _mousePressed = false;
  30. private GraphicsDevice _gd;
  31. private bool _useReverseDepth;
  32. private float _windowWidth;
  33. private float _windowHeight;
  34. private Sdl2Window _window;
  35. private InputTracker inputTracker;
  36. private Matrix4x4 _modelMarix;
  37. public Matrix4x4 OrthographicMatrix => _orthographicMatrix;
  38. public event Action<Matrix4x4> ProjectionChanged;
  39. public event Action<Matrix4x4> ViewChanged;
  40. public event Action<Matrix4x4> ModelChanged;
  41. public float XAngle { get => _xangle;set { _xangle = value;UpdateModel(); } }
  42. public float YAngle { get => _yangle; set { _yangle = value; UpdateModel(); } }
  43. public float ZAngle { get => _zangle; set { _zangle = value; UpdateModel(); } }
  44. private void UpdateModel()
  45. {
  46. _modelMarix = Matrix4x4.CreateRotationZ(_zangle) * Matrix4x4.CreateRotationY(_yangle) * Matrix4x4.CreateRotationX(_xangle);
  47. ModelChanged?.Invoke(_modelMarix);
  48. }
  49. public Camera(GraphicsDevice gd, Sdl2Window window)
  50. {
  51. _modelMarix = Matrix4x4.Identity;
  52. _gd = gd;
  53. _useReverseDepth = gd.IsDepthRangeZeroToOne;
  54. _window = window;
  55. _windowWidth = window.Width;
  56. _windowHeight = window.Height;
  57. UpdatePerspectiveMatrix();
  58. UpdateOrthographicMatrix();
  59. UpdateViewMatrix();
  60. inputTracker= new InputTracker();
  61. }
  62. public Matrix4x4 ModelMatrix => _modelMarix;
  63. public Matrix4x4 ViewMatrix => _viewMatrix;
  64. public Matrix4x4 ProjectionMatrix => _projectionMatrix;
  65. public Vector3 Position { get => _position; set { _position = value; UpdateViewMatrix(); } }
  66. public Vector3 LookDirection => _lookDirection;
  67. public float FarDistance => _far;
  68. public float FieldOfView => _fov;
  69. public float NearDistance => _near;
  70. public float AspectRatio => _windowWidth / _windowHeight;
  71. public float Yaw { get => _yaw; set { _yaw = value; UpdateViewMatrix(); } }
  72. public float Pitch { get => _pitch; set { _pitch = value; UpdateViewMatrix(); } }
  73. public float Roll { get => _roll;set{ _roll = value;UpdateViewMatrix(); } }
  74. public void Update(float deltaSeconds,InputSnapshot inputSnapshot)
  75. {
  76. inputTracker.UpdateFrameInput(inputSnapshot);
  77. //float sprintFactor = inputTracker.GetKey(Key.ControlLeft)
  78. // ? 0.1f
  79. // : inputTracker.GetKey(Key.ShiftLeft)
  80. // ? 2.5f
  81. // : 1f;
  82. //Vector3 motionDir = Vector3.Zero;
  83. //if (inputTracker.GetKey(Key.A))
  84. //{
  85. // motionDir += -Vector3.UnitX;
  86. //}
  87. //if (inputTracker.GetKey(Key.D))
  88. //{
  89. // motionDir += Vector3.UnitX;
  90. //}
  91. //if (inputTracker.GetKey(Key.W))
  92. //{
  93. // motionDir += -Vector3.UnitZ;
  94. //}
  95. //if (inputTracker.GetKey(Key.S))
  96. //{
  97. // motionDir += Vector3.UnitZ;
  98. //}
  99. //if (inputTracker.GetKey(Key.Q))
  100. //{
  101. // motionDir += -Vector3.UnitY;
  102. //}
  103. //if (inputTracker.GetKey(Key.E))
  104. //{
  105. // motionDir += Vector3.UnitY;
  106. //}
  107. //if (motionDir != Vector3.Zero|| true)
  108. //{
  109. // Quaternion lookRotation = Quaternion.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
  110. // motionDir = Vector3.Transform(motionDir, lookRotation);
  111. // _position += motionDir * _moveSpeed * sprintFactor * deltaSeconds;
  112. // UpdateViewMatrix();
  113. //}
  114. if ((inputTracker.GetMouseButton(MouseButton.Left)))
  115. {
  116. if (!_mousePressed)
  117. {
  118. _mousePressed = true;
  119. _mousePressedPos = inputTracker.MousePosition;
  120. //Sdl2Native.SDL_ShowCursor(0);
  121. //Sdl2Native.SDL_SetWindowGrab(_window.SdlWindowHandle, true);
  122. }
  123. Vector2 mouseDelta = _mousePressedPos - inputTracker.MousePosition;
  124. //Sdl2Native.SDL_WarpMouseInWindow(_window.SdlWindowHandle, (int)_mousePressedPos.X, (int)_mousePressedPos.Y);
  125. _yangle -= mouseDelta.X * 0.01f;
  126. _xangle -= mouseDelta.Y * 0.01f;
  127. _mousePressedPos= inputTracker.MousePosition;
  128. UpdateModel();
  129. }
  130. else if(_mousePressed)
  131. {
  132. // Sdl2Native.SDL_WarpMouseInWindow(_window.SdlWindowHandle, (int)_mousePressedPos.X, (int)_mousePressedPos.Y);
  133. //Sdl2Native.SDL_SetWindowGrab(_window.SdlWindowHandle, false);
  134. //Sdl2Native.SDL_ShowCursor(1);
  135. _mousePressed = false;
  136. }
  137. if(inputSnapshot.WheelDelta!=0)
  138. {
  139. _fov -= inputSnapshot.WheelDelta * 0.05f;
  140. if (_fov <= 0) _fov = 0.05f;
  141. if (_fov >= MathF.PI) _fov = 3.14f;
  142. UpdatePerspectiveMatrix();
  143. }
  144. Pitch = Math.Clamp(Pitch, -1.55f, 1.55f);
  145. UpdateViewMatrix();
  146. }
  147. public void WindowResized(float width, float height)
  148. {
  149. _windowWidth = width;
  150. _windowHeight = height;
  151. UpdatePerspectiveMatrix();
  152. UpdateOrthographicMatrix();
  153. }
  154. private void UpdatePerspectiveMatrix()
  155. {
  156. //_projectionMatrix = Util.CreatePerspective(
  157. // _gd,
  158. // _useReverseDepth,
  159. // _fov,
  160. // _windowWidth / _windowHeight,
  161. // _near,
  162. // _far);
  163. _projectionMatrix = Matrix4x4.CreatePerspectiveFieldOfView(_fov,_windowWidth/_windowHeight,_near,_far);
  164. ProjectionChanged?.Invoke(_projectionMatrix);
  165. }
  166. internal Matrix4x4 GetOrthographicMatrix(UInt32 width, UInt32 height) => Matrix4x4.CreateOrthographicOffCenter(0, width, height, 0, 0, -1);
  167. private void UpdateOrthographicMatrix()
  168. {
  169. _orthographicMatrix = Matrix4x4.CreateOrthographicOffCenter(0, _windowWidth, _windowHeight, 0, 0, -1);
  170. }
  171. internal Matrix4x4 GetLineMatrix(UInt32 windowwidth,UInt32 windowheight, Veldrid.Common.Padding margin, LineRange lineRange,Boolean yinverted = false)
  172. {
  173. float width = windowwidth - (margin.Left + margin.Right);
  174. float height = windowheight - (margin.Top + margin.Bottom);
  175. float hscale = width / lineRange.XLenght;
  176. float vscale = height / lineRange.YLenght;
  177. var tran = Matrix4x4.CreateTranslation(0, -1 + (height / windowheight - 1), 0);
  178. return Matrix4x4.CreateScale(hscale, vscale, 1, new Vector3(-1, 1, 1)) * tran * Matrix4x4.CreateTranslation(margin.Left * 2 / windowwidth, margin.Top * 2 / windowheight, 0) * (!yinverted ? _ymirror : Matrix4x4.Identity);
  179. }
  180. /// <summary>
  181. /// 根据<paramref name="margin"/>参数和<paramref name="lineRange"/>参数获取转换矩阵
  182. /// </summary>
  183. /// <param name="margin"></param>
  184. /// <param name="lineRange"></param>
  185. /// <returns></returns>
  186. internal Matrix4x4 GetLineMatrix(Veldrid.Common.Padding margin, LineRange lineRange)
  187. {
  188. float width = _windowWidth - (margin.Left + margin.Right);
  189. float height = _windowHeight - (margin.Top + margin.Bottom);
  190. float hscale = width / lineRange.XLenght;
  191. float vscale = height / lineRange.YLenght;
  192. var tran = Matrix4x4.CreateTranslation(0,-1+(height/_windowHeight-1), 0);
  193. return Matrix4x4.CreateScale(hscale, vscale, 1, new Vector3(-1, 1, 1)) * tran * Matrix4x4.CreateTranslation(margin.Left*2/_windowWidth,margin.Top*2/_windowHeight, 0) * (!_gd.IsClipSpaceYInverted? _ymirror:Matrix4x4.Identity);
  194. }
  195. private void UpdateViewMatrix()
  196. {
  197. Quaternion lookRotation = Quaternion.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
  198. Vector3 lookDir = Vector3.Transform(-Vector3.UnitZ, lookRotation);
  199. _lookDirection = lookDir;
  200. _viewMatrix = Matrix4x4.CreateLookAt(_position, _position + _lookDirection, Vector3.UnitY);
  201. ViewChanged?.Invoke(_viewMatrix);
  202. }
  203. public CameraInfo GetCameraInfo() => new CameraInfo
  204. {
  205. CameraPosition_WorldSpace = _position,
  206. CameraLookDirection = _lookDirection
  207. };
  208. }
  209. [StructLayout(LayoutKind.Sequential)]
  210. public struct CameraInfo
  211. {
  212. public Vector3 CameraPosition_WorldSpace;
  213. private float _padding1;
  214. public Vector3 CameraLookDirection;
  215. private float _padding2;
  216. }
  217. }