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.
 
 
 

245 rivejä
5.7 KiB

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