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

271 lines
8.1 KiB

3 years ago
  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 "control.hpp"
  20. #include "input/control.hpp"
  21. #include "geom/intersection.hpp"
  22. #include "animation/ease.hpp"
  23. #include "math/math.hpp"
  24. #include "entity/commands.hpp"
  25. #include "entity/systems/camera.hpp"
  26. #include "animation/orbit-cam.hpp"
  27. #include "../../nest.hpp"
  28. #include <iostream>
  29. namespace entity {
  30. namespace system {
  31. control::control(entity::registry& registry):
  32. updatable(registry),
  33. timestep(0.0f),
  34. zoom(0.0f),
  35. tool(nullptr),
  36. flashlight_entity(entt::null),
  37. underground_camera(nullptr)
  38. {
  39. control_set.add_control(&move_forward_control);
  40. control_set.add_control(&move_back_control);
  41. control_set.add_control(&move_right_control);
  42. control_set.add_control(&move_left_control);
  43. control_set.add_control(&rotate_ccw_control);
  44. control_set.add_control(&rotate_cw_control);
  45. control_set.add_control(&tilt_up_control);
  46. control_set.add_control(&tilt_down_control);
  47. control_set.add_control(&zoom_in_control);
  48. control_set.add_control(&zoom_out_control);
  49. control_set.add_control(&adjust_camera_control);
  50. control_set.add_control(&ascend_control);
  51. control_set.add_control(&descend_control);
  52. control_set.add_control(&toggle_view_control);
  53. control_set.add_control(&tool_menu_control);
  54. control_set.add_control(&equip_lens_control);
  55. control_set.add_control(&equip_brush_control);
  56. control_set.add_control(&equip_forceps_control);
  57. control_set.add_control(&equip_marker_control);
  58. control_set.add_control(&equip_container_control);
  59. control_set.add_control(&equip_twig_control);
  60. control_set.add_control(&next_marker_control);
  61. control_set.add_control(&previous_marker_control);
  62. control_set.add_control(&use_tool_control);
  63. control_set.add_control(&fast_forward_control);
  64. control_set.add_control(&rewind_control);
  65. control_set.add_control(&exposure_increase_control);
  66. control_set.add_control(&exposure_decrease_control);
  67. // Set deadzone at 15% for all controls
  68. const std::list<input::control*>* controls = control_set.get_controls();
  69. for (input::control* control: *controls)
  70. {
  71. control->set_deadzone(0.15f);
  72. }
  73. zoom_speed = 5.0f; //1
  74. min_elevation = math::radians(-85.0f);
  75. max_elevation = math::radians(85.0f);
  76. near_focal_distance = 2.0f;
  77. far_focal_distance = 200.0f;
  78. near_movement_speed = 10.0f;
  79. far_movement_speed = 80.0f;
  80. near_fov = math::radians(80.0f);
  81. far_fov = math::radians(35.0f);
  82. near_clip_near = 0.1f;
  83. far_clip_near = 5.0f;
  84. near_clip_far = 100.0f;
  85. far_clip_far = 2000.0f;
  86. nest = nullptr;
  87. mouse_angle = 0.0f;
  88. old_mouse_angle = mouse_angle;
  89. flashlight_turns = 0.0f;
  90. flashlight_turns_i = 0;
  91. flashlight_turns_f = 0.0f;
  92. }
  93. void control::update(double t, double dt)
  94. {
  95. timestep = dt;
  96. // Zoom camera
  97. if (zoom_in_control.is_active())
  98. camera_system->zoom(zoom_speed * dt);
  99. if (zoom_out_control.is_active())
  100. camera_system->zoom(-zoom_speed * dt);
  101. // Rotate camera
  102. const float rotation_speed = math::radians(270.0f);
  103. if (rotate_ccw_control.is_active())
  104. camera_system->pan(rotation_speed * dt * std::min<float>(1.0f, rotate_ccw_control.get_current_value()));
  105. if (rotate_cw_control.is_active())
  106. camera_system->pan(-rotation_speed * dt * std::min<float>(1.0f, rotate_cw_control.get_current_value()));
  107. // Exposure
  108. if (camera_system->get_camera())
  109. {
  110. const float exposure = camera_system->get_camera()->get_exposure();
  111. const float exposure_rate = 0.1f;
  112. if (exposure_increase_control.is_active())
  113. {
  114. camera_system->get_camera()->set_exposure(exposure + exposure_rate);
  115. std::cout << "exposure: " << (exposure + exposure_rate) << std::endl;
  116. }
  117. if (exposure_decrease_control.is_active())
  118. {
  119. camera_system->get_camera()->set_exposure(exposure - exposure_rate);
  120. std::cout << "exposure: " << (exposure - exposure_rate) << std::endl;
  121. }
  122. }
  123. // Move camera
  124. float3 movement{0.0f, 0.0f, 0.0f};
  125. if (move_right_control.is_active())
  126. movement.x += move_right_control.get_current_value();
  127. if (move_left_control.is_active())
  128. movement.x -= move_left_control.get_current_value();
  129. if (move_forward_control.is_active())
  130. movement.z -= move_forward_control.get_current_value();
  131. if (move_back_control.is_active())
  132. movement.z += move_back_control.get_current_value();
  133. if (math::length_squared(movement) != 0.0f)
  134. {
  135. std::array<float, 2> speed_limits = {15.0f, 100.0f};
  136. float zoom = camera_system->get_orbit_cam()->get_zoom();
  137. float max_speed = math::log_lerp(speed_limits[1], speed_limits[0], zoom) * dt;
  138. float speed = std::min<float>(max_speed, math::length(movement * max_speed));
  139. movement = math::normalize(movement) * speed;
  140. const math::quaternion<float>& azimuth_rotation = camera_system->get_orbit_cam()->get_azimuth_rotation();
  141. movement = azimuth_rotation * movement;
  142. command::translate(registry, camera_subject_entity, movement);
  143. }
  144. // Turn flashlight
  145. float2 viewport_center = {(viewport[0] + viewport[2]) * 0.5f, (viewport[1] + viewport[3]) * 0.5f};
  146. float2 mouse_direction = math::normalize(mouse_position - viewport_center);
  147. old_mouse_angle = mouse_angle;
  148. mouse_angle = std::atan2(-mouse_direction.y, mouse_direction.x);
  149. if (mouse_angle - old_mouse_angle != 0.0f)
  150. {
  151. if (mouse_angle - old_mouse_angle <= -math::pi<float>)
  152. flashlight_turns_i -= 1;
  153. else if (mouse_angle - old_mouse_angle >= math::pi<float>)
  154. flashlight_turns_i += 1;
  155. flashlight_turns_f = (mouse_angle) / math::two_pi<float>;
  156. flashlight_turns = flashlight_turns_i - flashlight_turns_f;
  157. if (flashlight_entity != entt::null && nest)
  158. {
  159. math::transform<float> flashlight_transform = math::identity_transform<float>;
  160. float flashlight_depth = nest->get_shaft_depth(*nest->get_central_shaft(), flashlight_turns);
  161. flashlight_transform.translation = {0.0f, -flashlight_depth, 0.0f};
  162. flashlight_transform.rotation = math::angle_axis(-flashlight_turns * math::two_pi<float> + math::half_pi<float>, {0, 1, 0});
  163. command::set_transform(registry, flashlight_entity, flashlight_transform, false);
  164. if (underground_camera)
  165. {
  166. underground_camera->look_at({0, -flashlight_depth + 50.0f, 0}, {0, -flashlight_depth, 0}, {0, 0, -1});
  167. }
  168. }
  169. }
  170. }
  171. void control::set_camera_system(system::camera* camera_system)
  172. {
  173. this->camera_system = camera_system;
  174. }
  175. void control::set_nest(::nest* nest)
  176. {
  177. this->nest = nest;
  178. }
  179. void control::set_tool(scene::model_instance* tool)
  180. {
  181. this->tool = tool;
  182. }
  183. void control::set_flashlight(entity::id entity_id)
  184. {
  185. flashlight_entity = entity_id;
  186. }
  187. void control::set_camera_subject(entity::id entity_id)
  188. {
  189. camera_subject_entity = entity_id;
  190. }
  191. void control::set_viewport(const float4& viewport)
  192. {
  193. this->viewport = viewport;
  194. }
  195. void control::set_underground_camera(scene::camera* camera)
  196. {
  197. this->underground_camera = camera;
  198. }
  199. void control::handle_event(const mouse_moved_event& event)
  200. {
  201. if (adjust_camera_control.is_active())
  202. {
  203. bool invert_x = true;
  204. bool invert_y = false;
  205. float rotation_factor = event.dx;
  206. float elevation_factor = event.dy;
  207. if (invert_x)
  208. {
  209. rotation_factor *= -1.0f;
  210. }
  211. if (invert_y)
  212. {
  213. elevation_factor *= -1.0f;
  214. }
  215. float rotation = math::radians(15.0f) * rotation_factor * timestep;
  216. float tilt = math::radians(15.0f) * elevation_factor * timestep;
  217. camera_system->pan(rotation);
  218. camera_system->tilt(tilt);
  219. }
  220. else if (!adjust_camera_control.was_active())
  221. {
  222. mouse_position[0] = event.x;
  223. mouse_position[1] = event.y;
  224. }
  225. }
  226. void control::handle_event(const window_resized_event& event)
  227. {
  228. set_viewport({0.0f, 0.0f, static_cast<float>(event.w), static_cast<float>(event.h)});
  229. }
  230. } // namespace system
  231. } // namespace entity