💿🐜 Antkeeper source code https://antkeeper.com
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.

224 lines
6.3 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "animation/orbit-cam.hpp"
  20. #include "scene/camera.hpp"
  21. #include "math/math.hpp"
  22. #include <algorithm>
  23. #include <cmath>
  24. #include <limits>
  25. #include <iostream>
  26. orbit_cam::orbit_cam():
  27. azimuth_limits({-std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity()}),
  28. elevation_limits({-std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity()}),
  29. focal_distance_limits({-std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity()}),
  30. fov_limits({-std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity()}),
  31. clip_near_limits({-std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity()}),
  32. clip_far_limits({-std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity()})
  33. {
  34. // Make all springs critically-damped
  35. focal_point_spring.z = 1.0f;
  36. azimuth_spring.z = 1.0f;
  37. elevation_spring.z = 1.0f;
  38. zoom_spring.z = 1.0f;
  39. // Init spring oscillation frequencies to 1 rad/s
  40. focal_point_spring.w = math::two_pi<float>;
  41. azimuth_spring.w = math::two_pi<float>;
  42. elevation_spring.w = math::two_pi<float>;
  43. zoom_spring.w = math::two_pi<float>;
  44. // Zero spring values and velocities
  45. focal_point_spring.x1 = {0.0f, 0.0f, 0.0f};
  46. azimuth_spring.x1 = 0.0f;
  47. elevation_spring.x1 = 0.0f;
  48. zoom_spring.x1 = 0.0f;
  49. reset_springs();
  50. }
  51. orbit_cam::~orbit_cam()
  52. {}
  53. void orbit_cam::update(float dt)
  54. {
  55. if (!get_camera())
  56. {
  57. return;
  58. }
  59. // Solve springs
  60. solve_numeric_spring<float3, float>(focal_point_spring, dt);
  61. solve_numeric_spring<float, float>(azimuth_spring, dt);
  62. solve_numeric_spring<float, float>(elevation_spring, dt);
  63. solve_numeric_spring<float, float>(zoom_spring, dt);
  64. // Calculate zoom-dependent variables
  65. float focal_distance = math::log_lerp<float>(focal_distance_limits[1], focal_distance_limits[0], zoom_spring.x0);
  66. float fov = math::log_lerp<float>(fov_limits[1], fov_limits[0], zoom_spring.x0);
  67. float clip_near = math::log_lerp<float>(clip_near_limits[1], clip_near_limits[0], zoom_spring.x0);
  68. float clip_far = math::log_lerp<float>(clip_far_limits[1], clip_far_limits[0], zoom_spring.x0);
  69. // Calculate camera transform
  70. transform_type transform = math::identity_transform<float>;
  71. // Determine rotation
  72. azimuth_rotation = math::angle_axis(azimuth_spring.x0, float3{0.0f, 1.0f, 0.0f});
  73. elevation_rotation = math::angle_axis(elevation_spring.x0, float3{-1.0f, 0.0f, 0.0f});
  74. transform.rotation = math::normalize(azimuth_rotation * elevation_rotation);
  75. // Determine translation
  76. transform.translation = focal_point_spring.x0 + transform.rotation * float3{0.0f, 0.0f, focal_distance};
  77. // Update camera transform
  78. update_transform(transform);
  79. // Update camera projection
  80. update_projection(fov, aspect_ratio, clip_near, clip_far);
  81. }
  82. void orbit_cam::move(const float3& translation)
  83. {
  84. set_target_focal_point(focal_point_spring.x1 + translation);
  85. }
  86. void orbit_cam::pan(float angle)
  87. {
  88. set_target_azimuth(azimuth_spring.x1 + angle);
  89. }
  90. void orbit_cam::tilt(float angle)
  91. {
  92. set_target_elevation(elevation_spring.x1 + angle);
  93. }
  94. void orbit_cam::zoom(float factor)
  95. {
  96. set_target_zoom(zoom_spring.x1 + factor);
  97. }
  98. void orbit_cam::reset_springs()
  99. {
  100. // Reset values
  101. focal_point_spring.x0 = focal_point_spring.x1;
  102. azimuth_spring.x0 = azimuth_spring.x1;
  103. elevation_spring.x0 = elevation_spring.x1;
  104. zoom_spring.x0 = zoom_spring.x1;
  105. // Reset velocities
  106. focal_point_spring.v = {0.0f, 0.0f, 0.0f};
  107. azimuth_spring.v = 0.0f;
  108. elevation_spring.v = 0.0f;
  109. zoom_spring.v = 0.0f;
  110. }
  111. void orbit_cam::set_aspect_ratio(float ratio)
  112. {
  113. aspect_ratio = ratio;
  114. }
  115. void orbit_cam::set_focal_point(const float3& point)
  116. {
  117. focal_point_spring.x0 = point;
  118. }
  119. void orbit_cam::set_azimuth(float angle)
  120. {
  121. azimuth_spring.x0 = std::max<float>(azimuth_limits[0], std::min<float>(azimuth_limits[1], angle));
  122. }
  123. void orbit_cam::set_elevation(float angle)
  124. {
  125. elevation_spring.x0 = std::max<float>(elevation_limits[0], std::min<float>(elevation_limits[1], angle));
  126. }
  127. void orbit_cam::set_zoom(float factor)
  128. {
  129. zoom_spring.x0 = std::max<float>(0.0f, std::min<float>(1.0f, factor));
  130. }
  131. void orbit_cam::set_target_focal_point(const float3& point)
  132. {
  133. focal_point_spring.x1 = point;
  134. }
  135. void orbit_cam::set_target_azimuth(float angle)
  136. {
  137. azimuth_spring.x1 = std::max<float>(azimuth_limits[0], std::min<float>(azimuth_limits[1], angle));
  138. }
  139. void orbit_cam::set_target_elevation(float angle)
  140. {
  141. elevation_spring.x1 = std::max<float>(elevation_limits[0], std::min<float>(elevation_limits[1], angle));
  142. }
  143. void orbit_cam::set_target_zoom(float factor)
  144. {
  145. zoom_spring.x1 = std::max<float>(0.0f, std::min<float>(1.0f, factor));
  146. }
  147. void orbit_cam::set_azimuth_limits(const std::array<float, 2>& limits)
  148. {
  149. azimuth_limits = limits;
  150. }
  151. void orbit_cam::set_elevation_limits(const std::array<float, 2>& limits)
  152. {
  153. elevation_limits = limits;
  154. }
  155. void orbit_cam::set_focal_distance_limits(const std::array<float, 2>& limits)
  156. {
  157. focal_distance_limits = limits;
  158. }
  159. void orbit_cam::set_fov_limits(const std::array<float, 2>& limits)
  160. {
  161. fov_limits = limits;
  162. }
  163. void orbit_cam::set_clip_near_limits(const std::array<float, 2>& limits)
  164. {
  165. clip_near_limits = limits;
  166. }
  167. void orbit_cam::set_clip_far_limits(const std::array<float, 2>& limits)
  168. {
  169. clip_far_limits = limits;
  170. }
  171. void orbit_cam::set_focal_point_oscillation(float frequency)
  172. {
  173. focal_point_spring.w = frequency;
  174. }
  175. void orbit_cam::set_azimuth_oscillation(float frequency)
  176. {
  177. azimuth_spring.w = frequency;
  178. }
  179. void orbit_cam::set_elevation_oscillation(float frequency)
  180. {
  181. elevation_spring.w = frequency;
  182. }
  183. void orbit_cam::set_zoom_oscillation(float frequency)
  184. {
  185. zoom_spring.w = frequency;
  186. }