Antkeeper  0.0.1
camera-system.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 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 
26 #include <engine/scene/camera.hpp>
28 #include <execution>
29 
32 {}
33 
34 void camera_system::update(float t, float dt)
35 {
36  m_fixed_update_time = static_cast<double>(t);
37  m_fixed_timestep = static_cast<double>(dt);
38 }
39 
40 void camera_system::interpolate(float alpha)
41 {
42  const double variable_update_time = m_fixed_update_time + m_fixed_timestep * static_cast<double>(alpha);
43  const double variable_timestep = std::max(0.0, variable_update_time - m_variable_update_time);
44  m_variable_update_time = variable_update_time;
45 
46  /*
47  auto autofocus_group = registry.group<autofocus_component>(entt::get<scene_component>);
48  std::for_each
49  (
50  std::execution::seq,
51  autofocus_group.begin(),
52  autofocus_group.end(),
53  [&](auto entity_id)
54  {
55  auto& autofocus = autofocus_group.get<autofocus_component>(entity_id);
56  auto& camera = static_cast<scene::camera&>(*autofocus_group.get<scene_component>(entity_id).object);
57 
58  // Clamp zoom factor
59  autofocus.zoom = std::min<double>(std::max<double>(autofocus.zoom, 0.0), 1.0);
60 
61  // Calculate horizontal and vertical FoV
62  autofocus.hfov = ease<double, double>::out_sine(autofocus.far_hfov, autofocus.near_hfov, autofocus.zoom);
63  autofocus.vfov = math::vertical_fov(autofocus.hfov, static_cast<double>(camera.get_aspect_ratio()));
64 
65  // Calculate focal plane dimensions
66  autofocus.focal_plane_size.y() = ease<double, double>::out_sine(autofocus.far_focal_plane_height, autofocus.near_focal_plane_height, autofocus.zoom);
67  autofocus.focal_plane_size.x() = autofocus.focal_plane_size.y() * static_cast<double>(camera.get_aspect_ratio());
68 
69  // Calculate focal distance
70  autofocus.focal_distance = autofocus.focal_plane_height * 0.5 / std::tan(autofocus.vfov * 0.5);
71 
72  // Update camera projection matrix
73  camera.set_vertical_fov(static_cast<float>(autofocus.vfov));
74  }
75  );
76  */
77 
78  auto spring_arm_group = registry.group<spring_arm_component>(entt::get<scene_component>);
79  std::for_each
80  (
81  std::execution::seq,
82  spring_arm_group.begin(),
83  spring_arm_group.end(),
84  [&](auto entity_id)
85  {
86  auto& spring_arm = spring_arm_group.get<spring_arm_component>(entity_id);
87  auto& camera = static_cast<scene::camera&>(*spring_arm_group.get<scene_component>(entity_id).object);
88 
89  math::transform<double> parent_transform = math::transform<double>::identity();
90  if (spring_arm.parent_eid != entt::null)
91  {
92  const auto parent_scene = registry.try_get<scene_component>(spring_arm.parent_eid);
93  if (parent_scene)
94  {
95  parent_transform.translation = math::dvec3(parent_scene->object->get_translation());
96  parent_transform.rotation = math::dquat(parent_scene->object->get_rotation());
97  }
98  }
99 
100  // Calculate focal point
101  spring_arm.focal_point_spring.set_target_value(parent_transform * spring_arm.focal_point_offset);
102 
103  // Integrate angular velocities
104  spring_arm.angles_spring.set_target_value(spring_arm.angles_spring.get_target_value() + spring_arm.angular_velocities * variable_timestep);
105 
106  // Apply angular constraints
107  spring_arm.angles_spring.set_target_value(math::clamp(spring_arm.angles_spring.get_target_value(), spring_arm.min_angles, spring_arm.max_angles));
108 
109  // Solve springs
110  spring_arm.focal_point_spring.solve(variable_timestep);
111  spring_arm.angles_spring.solve(variable_timestep);
112 
113  // Recalculate zoom
114  // if (spring_arm.pitch_velocity)
115  {
116  spring_arm.zoom = ease<double, double>::in_sine(1.0, 0.0, spring_arm.angles_spring.get_value().x() / -math::half_pi<double>);
117  }
118 
119  // Clamp zoom
120  spring_arm.zoom = std::min<double>(std::max<double>(spring_arm.zoom, 0.0), 1.0);
121 
122  // Update FoV
123  spring_arm.hfov = ease<double, double>::out_sine(spring_arm.far_hfov, spring_arm.near_hfov, spring_arm.zoom);
124  spring_arm.vfov = math::vertical_fov(spring_arm.hfov, static_cast<double>(camera.get_aspect_ratio()));
125 
126  // Update focal plane size
127  spring_arm.focal_plane_height = ease<double, double>::out_sine(spring_arm.far_focal_plane_height, spring_arm.near_focal_plane_height, spring_arm.zoom);
128  spring_arm.focal_plane_width = spring_arm.focal_plane_height * static_cast<double>(camera.get_aspect_ratio());
129 
130  // Update focal distance
131  spring_arm.focal_distance = spring_arm.focal_plane_height * 0.5 / std::tan(spring_arm.vfov * 0.5);
132 
133  const auto camera_up = spring_arm.up_rotation * math::dvec3{0, 1, 0};
134  const auto parent_up = parent_transform.rotation * math::dvec3{0, 1, 0};
135  spring_arm.up_rotation = math::normalize(math::rotation(camera_up, parent_up) * spring_arm.up_rotation);
136 
137  // Update camera rotation
138  spring_arm.camera_rotation = math::normalize(spring_arm.up_rotation * math::euler_xyz_to_quat(spring_arm.angles_spring.get_value()));
139 
140  // Update transform
141  const auto camera_translation = spring_arm.focal_point_spring.get_value() + spring_arm.camera_rotation * math::dvec3{0.0f, 0.0f, spring_arm.focal_distance};
142 
143  math::transform<float> camera_transform;
144  camera_transform.translation = math::fvec3(camera_translation);
145  camera_transform.rotation = math::fquat(spring_arm.camera_rotation);
146  camera_transform.scale = {1, 1, 1};
147 
148 
149  double center_offset = (1.0 - std::abs(spring_arm.angles_spring.get_value().x()) / math::half_pi<double>) * (spring_arm.focal_plane_height / 3.0 * 0.5);
150  camera_transform.translation += math::fvec3(spring_arm.camera_rotation * math::dvec3{0, center_offset, 0});
151 
152  camera.set_transform(camera_transform);
153  camera.set_vertical_fov(static_cast<float>(spring_arm.vfov));
154  }
155  );
156 }
157 
159 {
160  m_viewport = math::dvec4(viewport);
161  m_aspect_ratio = m_viewport[2] / m_viewport[3];
162 }
163 
void interpolate(float alpha)
void set_viewport(const math::fvec4 &viewport)
camera_system(entity::registry &registry)
void update(float t, float dt) override
Perform's a system's update() function.
Abstract base class for updatable systems.
entity::registry & registry
Registry on which the system operate.
entt::registry registry
Component registry type.
Definition: registry.hpp:28
dvec< 4 > dvec4
n-dimensional vector of double-precision floating-point numbers.
Definition: vector.hpp:439
T vertical_fov(T h, T r)
Calculates a vertical FoV given a horizontal FoV and aspect ratio.
quat< T > euler_xyz_to_quat(const vec3< T > &angles)
Constructs a quaternion from Euler angles.
constexpr vector< T, N > max(const vector< T, N > &x, const vector< T, N > &y)
Returns a vector containing the maximum elements of two vectors.
Definition: vector.hpp:1328
quaternion< T > normalize(const quaternion< T > &q)
Normalizes a quaternion.
Definition: quaternion.hpp:679
constexpr vector< T, N > abs(const vector< T, N > &x)
Returns the absolute values of each element.
Definition: vector.hpp:985
quaternion< T > rotation(const vec3< T > &from, const vec3< T > &to, T tolerance=T{1e-6})
Constructs a quaternion representing the minimum rotation from one direction to another direction.
Definition: quaternion.hpp:691
constexpr vector< T, N > clamp(const vector< T, N > &x, const vector< T, N > &min, const vector< T, N > &max)
Clamps the values of a vector's elements.
Definition: vector.hpp:1069
Container for templated easing functions.
Definition: ease.hpp:71
Quaternion composed of a real scalar part and imaginary vector part.
Definition: quaternion.hpp:39
vector_type translation
Translation vector.
Definition: transform.hpp:50
n-dimensional vector.
Definition: vector.hpp:44
Attaches a camera to an entity using springs.