💿🐜 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.

161 lines
4.5 KiB

  1. /*
  2. * Copyright (C) 2020 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 "orbit-cam.hpp"
  20. #include "scene/camera.hpp"
  21. #include <algorithm>
  22. #include <cmath>
  23. using namespace vmq::operators;
  24. template <class T>
  25. static inline T lerp(const T& x, const T& y, float a)
  26. {
  27. return x * (1.0f - a) + y * a;
  28. }
  29. orbit_cam::orbit_cam():
  30. elevation_rotation(vmq::identity_quaternion<float>),
  31. azimuth_rotation(vmq::identity_quaternion<float>),
  32. target_elevation_rotation(vmq::identity_quaternion<float>),
  33. target_azimuth_rotation(vmq::identity_quaternion<float>),
  34. target_rotation(vmq::identity_quaternion<float>)
  35. {}
  36. orbit_cam::~orbit_cam()
  37. {}
  38. void orbit_cam::update(float dt)
  39. {
  40. float interpolation_factor = 1.0f;
  41. // Calculate rotation and target rotation quaternions
  42. //rotation = azimuth_rotation * elevation_rotation;
  43. target_rotation = vmq::normalize(target_azimuth_rotation * target_elevation_rotation);
  44. // Calculate target translation
  45. target_translation = target_focal_point + target_rotation * float3{0.0f, 0.0f, target_focal_distance};
  46. // Interpolate rotation
  47. //rotation = glm::mix(rotation, target_rotation, interpolation_factor);
  48. // Interpolate angles
  49. set_elevation(lerp(elevation, target_elevation, interpolation_factor));
  50. set_azimuth(lerp(azimuth, target_azimuth, interpolation_factor));
  51. // Calculate rotation
  52. set_rotation(vmq::normalize(azimuth_rotation * elevation_rotation));
  53. // Interpolate focal point and focal distance
  54. focal_point = vmq::lerp(focal_point, target_focal_point, interpolation_factor);
  55. focal_distance = lerp(focal_distance, target_focal_distance, interpolation_factor);
  56. // Caluclate translation
  57. set_translation(focal_point + get_rotation() * float3{0.0f, 0.0f, focal_distance});
  58. /*
  59. // Recalculate azimuth
  60. azimuth_rotation = rotation;
  61. azimuth_rotation.x = 0.0f;
  62. azimuth_rotation.z = 0.0f;
  63. azimuth_rotation = glm::normalize(azimuth_rotation);
  64. azimuth = 2.0f * std::acos(azimuth_rotation.w);
  65. // Recalculate elevation
  66. elevation_rotation = rotation;
  67. elevation_rotation.y = 0.0f;
  68. elevation_rotation.z = 0.0f;
  69. elevation_rotation = glm::normalize(elevation_rotation);
  70. elevation = 2.0f * std::acos(elevation_rotation.w);
  71. */
  72. // Update camera
  73. if (get_camera() != nullptr)
  74. {
  75. transform<float> transform = vmq::identity_transform<float>;
  76. transform.translation = get_translation();
  77. transform.rotation = get_rotation();
  78. get_camera()->set_transform(transform);
  79. //get_camera()->look_at(get_translation(), get_translation() + get_forward(), get_up());
  80. }
  81. }
  82. void orbit_cam::move(const float2& direction)
  83. {
  84. target_focal_point += azimuth_rotation * float3{direction[0], 0.0f, direction[1]};
  85. }
  86. void orbit_cam::rotate(float angle)
  87. {
  88. set_target_azimuth(target_azimuth + angle);
  89. }
  90. void orbit_cam::tilt(float angle)
  91. {
  92. set_target_elevation(target_elevation + angle);
  93. }
  94. void orbit_cam::zoom(float distance)
  95. {
  96. set_target_focal_distance(target_focal_distance - distance);
  97. }
  98. void orbit_cam::set_focal_point(const float3& point)
  99. {
  100. focal_point = point;
  101. }
  102. void orbit_cam::set_focal_distance(float distance)
  103. {
  104. focal_distance = distance;
  105. }
  106. void orbit_cam::set_elevation(float angle)
  107. {
  108. elevation = angle;
  109. elevation_rotation = vmq::angle_axis(elevation, float3{-1.0f, 0.0f, 0.0f});
  110. }
  111. void orbit_cam::set_azimuth(float angle)
  112. {
  113. azimuth = angle;
  114. azimuth_rotation = vmq::angle_axis(azimuth, float3{0.0f, 1.0f, 0.0f});
  115. }
  116. void orbit_cam::set_target_focal_point(const float3& point)
  117. {
  118. target_focal_point = point;
  119. }
  120. void orbit_cam::set_target_focal_distance(float distance)
  121. {
  122. target_focal_distance = distance;
  123. }
  124. void orbit_cam::set_target_elevation(float angle)
  125. {
  126. target_elevation = angle;
  127. target_elevation_rotation = vmq::angle_axis(target_elevation, float3{-1.0f, 0.0f, 0.0f});
  128. }
  129. void orbit_cam::set_target_azimuth(float angle)
  130. {
  131. target_azimuth = angle;
  132. target_azimuth_rotation = vmq::angle_axis(target_azimuth, float3{0.0f, 1.0f, 0.0f});
  133. }