You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

247 lines
5.8 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
  5. // © 2009—2013 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
  6. //
  7. // This library is free software. It comes without any warranty, to
  8. // the extent permitted by applicable law. You can redistribute it
  9. // and/or modify it under the terms of the Do What the Fuck You Want
  10. // to Public License, Version 2, as published by the WTFPL Task Force.
  11. // See http://www.wtfpl.net/ for more details.
  12. //
  13. #include <lol/engine-internal.h>
  14. #include <cstring>
  15. #include <cstdlib>
  16. #if defined _WIN32 || defined _XBOX
  17. # define strcasecmp _stricmp
  18. # undef near
  19. # undef far
  20. #endif
  21. namespace lol
  22. {
  23. Camera::Camera()
  24. {
  25. m_gamegroup = GAMEGROUP_CAMERA;
  26. m_drawgroup = DRAWGROUP_CAMERA;
  27. //Arbitrary values when g_renderer is not ready.
  28. ivec2 screen_size = (Renderer::GetCount()) ? (Video::GetSize()) : (ivec2(800, 600));
  29. m_fov = 45.f;
  30. m_near = -1000.f;
  31. m_far = 1000.f;
  32. m_screen_size = (float)screen_size.x;
  33. m_screen_ratio = (float)screen_size.y / (float)screen_size.x;
  34. m_is_shifted = false;
  35. m_screen_scale = vec2(1.f);
  36. m_target_distance = .0f;
  37. /* Create a default perspective */
  38. SetProjection(m_fov, m_near, m_far, m_screen_size, m_screen_ratio);
  39. SetView(mat4::lookat(vec3(0.f, 50.f, 50.f), vec3::zero, vec3::axis_y));
  40. }
  41. Camera::~Camera()
  42. {
  43. }
  44. //-----------------------------------------------------------------------------
  45. //View functions
  46. //--
  47. //WARNING : Don't forget the position
  48. void Camera::SetView(mat4 const &view)
  49. {
  50. m_view_matrix = view;
  51. m_position = inverse(view)[3].xyz;
  52. }
  53. void Camera::SetView(vec3 eye, vec3 target, vec3 up)
  54. {
  55. m_view_matrix = mat4::lookat(eye, target, up);
  56. m_position = eye;
  57. m_target_distance = length(target - m_position);
  58. }
  59. void Camera::SetView(vec3 pos, vec3 rot)
  60. {
  61. SetView(pos, quat::fromeuler_zyx(rot));
  62. }
  63. void Camera::SetView(vec3 pos, quat rot)
  64. {
  65. m_view_matrix = inverse(mat4(rot)) * mat4::translate(-pos);
  66. m_position = pos;
  67. }
  68. mat4 Camera::GetView() const
  69. {
  70. return m_view_matrix;
  71. }
  72. //-----------------------------------------------------------------------------
  73. //Projections functions
  74. //--
  75. void Camera::SetProjection(mat4 const &proj)
  76. {
  77. m_proj_matrix = proj;
  78. }
  79. void Camera::SetProjection(float fov, float near, float far)
  80. {
  81. SetProjection(fov, near, far, m_screen_size, m_screen_ratio);
  82. }
  83. void Camera::SetProjection(float fov, float near, float far, float screen_size, float screen_ratio)
  84. {
  85. m_fov = fov;
  86. m_near = near;
  87. m_far = far;
  88. m_screen_size = screen_size;
  89. m_screen_ratio = screen_ratio;
  90. mat4 screen_scale = mat4::scale(vec3(m_screen_scale.xy, 1.f));
  91. if (m_fov > .001f)
  92. {
  93. if (m_is_shifted)
  94. SetProjection(screen_scale * mat4::shifted_perspective(m_fov, screen_size, screen_ratio, m_near, m_far));
  95. else
  96. SetProjection(screen_scale * mat4::perspective(m_fov, screen_size, screen_size * screen_ratio, m_near, m_far));
  97. }
  98. else
  99. SetProjection(screen_scale * mat4::ortho(screen_size, screen_size * screen_ratio, m_near, m_far));
  100. }
  101. mat4 Camera::GetProjection() const
  102. {
  103. return m_proj_matrix;
  104. }
  105. //-----------------------------------------------------------------------------
  106. //Projections manipulation functions
  107. //--
  108. void Camera::SetFov(float fov)
  109. {
  110. SetProjection(fov, m_near, m_far, m_screen_size, m_screen_ratio);
  111. }
  112. void Camera::SetScreenInfos(float screen_size)
  113. {
  114. SetScreenInfos(screen_size, m_screen_ratio);
  115. }
  116. void Camera::SetScreenInfos(float screen_size, float screen_ratio)
  117. {
  118. SetProjection(m_fov, m_near, m_far, screen_size, screen_ratio);
  119. }
  120. void Camera::SetDrawInfos(float far)
  121. {
  122. SetDrawInfos(m_near, far);
  123. }
  124. void Camera::SetDrawInfos(float near, float far)
  125. {
  126. SetProjection(m_fov, near, far, m_screen_size, m_screen_ratio);
  127. }
  128. void Camera::SetScreenScale(vec2 screen_scale)
  129. {
  130. m_screen_scale = screen_scale;
  131. SetProjection(m_fov, m_near, m_far, m_screen_size, m_screen_ratio);
  132. }
  133. void Camera::UseShift(bool should_shift)
  134. {
  135. m_is_shifted = should_shift;
  136. SetProjection(m_fov, m_near, m_far, m_screen_size, m_screen_ratio);
  137. }
  138. void Camera::UseTarget(bool use_target)
  139. {
  140. m_target_distance = ((use_target)?(max(m_target_distance, 1.f)):(.0f));
  141. }
  142. //-----------------------------------------------------------------------------
  143. //camera manipulation Functions
  144. //--
  145. void Camera::SetPosition(vec3 pos, bool keep_target)
  146. {
  147. if (keep_target)
  148. SetView(pos, GetTarget(), GetUp());
  149. else
  150. SetView(GetView() * mat4::translate(m_position - pos));
  151. m_position = pos;
  152. }
  153. void Camera::SetTarget(vec3 target, vec3 up)
  154. {
  155. SetView(m_position, target, up);
  156. }
  157. void Camera::SetRotation(vec3 rot)
  158. {
  159. SetView(m_position, rot);
  160. }
  161. void Camera::SetRotation(quat rot)
  162. {
  163. SetView(m_position, rot);
  164. }
  165. //--
  166. vec3 Camera::GetPosition() const
  167. {
  168. return m_position;
  169. }
  170. vec3 Camera::GetTarget() const
  171. {
  172. return m_position + (inverse(m_view_matrix) * vec4(0.f, 0.f, -max(m_target_distance, 1.f), 0.f)).xyz;
  173. }
  174. vec3 Camera::GetUp() const
  175. {
  176. return (inverse(m_view_matrix) * vec4(0.f, 1.f, 0.f, 0.f)).xyz;
  177. }
  178. vec3 Camera::GetRotationEuler() const
  179. {
  180. return vec3::toeuler_zyx(GetRotation());
  181. }
  182. quat Camera::GetRotation() const
  183. {
  184. return quat(inverse(mat3(m_view_matrix)));
  185. }
  186. // Calculate the frustum height at a given distance from the camera.
  187. float Camera::GetFrustumHeightAtDistance(float distance, float fov) const
  188. {
  189. return 2.f * distance * lol::tan(radians(fov * .5f));
  190. }
  191. // Calculate the FOV needed to get a given frustum height at a given distance.
  192. float Camera::GetFOVForHeightAndDistance(float distance, float height) const
  193. {
  194. return 2.f * radians(lol::atan(height * .5f / distance));
  195. }
  196. void Camera::TickGame(float seconds)
  197. {
  198. WorldEntity::TickGame(seconds);
  199. }
  200. void Camera::TickDraw(float seconds, Scene &scene)
  201. {
  202. WorldEntity::TickDraw(seconds, scene);
  203. }
  204. } /* namespace lol */