245 行
5.5 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cstring>
  14. #include <cstdlib>
  15. #include "core.h"
  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_BEFORE;
  26. m_drawgroup = DRAWGROUP_CAMERA;
  27. ivec2 screen_size = (g_renderer)?(Video::GetSize()):(ivec2(0));
  28. m_fov = 45.f;
  29. m_near = -1000.f;
  30. m_far = 1000.f;
  31. m_screen_size = (float)screen_size.x;
  32. m_screen_ratio = (float)screen_size.x / (float)screen_size.y;
  33. m_is_shifted = false;
  34. /* Create a default perspective */
  35. SetProjection(mat4::perspective(45.f, 800.f, 600.f, -1000.f, 1000.f));
  36. SetView(mat4::lookat(vec3(0.f, 50.f, 50.f),
  37. vec3(0.f),
  38. vec3(0.f, 1.f, 0.f)));
  39. }
  40. Camera::~Camera()
  41. {
  42. }
  43. //-----------------------------------------------------------------------------
  44. //View functions
  45. //--
  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_xyz(rot));
  60. }
  61. void Camera::SetView(vec3 pos, quat rot)
  62. {
  63. m_view_matrix = mat4::lookat(pos,
  64. pos + rot.transform(vec3(0.f, 0.f, -max(m_target_distance, 1.f))),
  65. rot.transform(vec3(0.f, 1.f, 0.f)));
  66. m_position = pos;
  67. }
  68. mat4 Camera::GetView()
  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. if (m_fov > .0f)
  91. {
  92. if (m_is_shifted)
  93. SetProjection(mat4::shifted_perspective(m_fov, screen_size, screen_ratio, m_far - m_near));
  94. else
  95. SetProjection(mat4::perspective(m_fov, screen_size, screen_size * screen_ratio, m_near, m_far));
  96. }
  97. else
  98. SetProjection(mat4::ortho(screen_size, screen_size * screen_ratio, m_near, m_far));
  99. }
  100. mat4 Camera::GetProjection()
  101. {
  102. return m_proj_matrix;
  103. }
  104. //-----------------------------------------------------------------------------
  105. //Projections manipulation functions
  106. //--
  107. void Camera::SetFov(float fov)
  108. {
  109. SetProjection(fov, m_near, m_far, m_screen_size, m_screen_ratio);
  110. }
  111. void Camera::SetScreenInfos(float screen_size)
  112. {
  113. SetScreenInfos(screen_size, m_screen_ratio);
  114. }
  115. void Camera::SetScreenInfos(float screen_size, float screen_ratio)
  116. {
  117. SetProjection(m_fov, m_near, m_far, screen_size, screen_ratio);
  118. }
  119. void Camera::SetDrawInfos(float far)
  120. {
  121. SetDrawInfos(m_near, far);
  122. }
  123. void Camera::SetDrawInfos(float near, float far)
  124. {
  125. SetProjection(m_fov, near, far, m_screen_size, m_screen_ratio);
  126. }
  127. void Camera::UseShift(bool should_shift)
  128. {
  129. m_is_shifted = should_shift;
  130. SetProjection(m_fov, m_near, m_far, m_screen_size, m_screen_ratio);
  131. }
  132. void Camera::UseTarget(bool use_target)
  133. {
  134. m_target_distance = ((use_target)?(max(m_target_distance, 1.f)):(.0f));
  135. }
  136. //-----------------------------------------------------------------------------
  137. //camera manipulation Functions
  138. //--
  139. void Camera::SetPosition(vec3 pos)
  140. {
  141. if (m_target_distance > .0f)
  142. SetView(m_position, m_position + GetTarget(), GetUp());
  143. else
  144. SetView(GetView() * mat4::translate(pos - m_position));
  145. m_position = pos;
  146. }
  147. void Camera::SetTarget(vec3 target)
  148. {
  149. SetView(m_position, target, GetUp());
  150. }
  151. void Camera::SetUp(vec3 up)
  152. {
  153. SetView(m_position, GetTarget(), up);
  154. }
  155. void Camera::SetRotation(vec3 rot)
  156. {
  157. SetRotation(quat::fromeuler_xyz(rot));
  158. }
  159. void Camera::SetRotation(quat rot)
  160. {
  161. SetView(m_position, rot);
  162. }
  163. //--
  164. vec3 Camera::GetPosition()
  165. {
  166. return m_position;
  167. }
  168. vec3 Camera::GetTarget()
  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()
  173. {
  174. return (inverse(m_view_matrix) * vec4(0.f, 1.f, 0.f, 0.f)).xyz;
  175. }
  176. vec3 Camera::GetRotationEuler()
  177. {
  178. return vec3::toeuler_zyx(GetRotation());
  179. }
  180. quat Camera::GetRotation()
  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)
  186. {
  187. return 2.f * distance * lol::tan(fov * .5f * (F_PI / 180.f));
  188. }
  189. // Calculate the FOV needed to get a given frustum height at a given distance.
  190. float Camera::GetFOVForHeightAndDistance(float distance, float height)
  191. {
  192. return 2.f * lol::atan(height * .5f / distance) * (180.f / F_PI);
  193. }
  194. void Camera::TickGame(float seconds)
  195. {
  196. WorldEntity::TickGame(seconds);
  197. }
  198. void Camera::TickDraw(float seconds)
  199. {
  200. WorldEntity::TickDraw(seconds);
  201. }
  202. } /* namespace lol */