diff --git a/src/animation/spring.hpp b/src/animation/spring.hpp
new file mode 100644
index 0000000..bb6bb95
--- /dev/null
+++ b/src/animation/spring.hpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 Christopher J. Howard
+ *
+ * This file is part of Antkeeper source code.
+ *
+ * Antkeeper source code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Antkeeper source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Antkeeper source code. If not, see .
+ */
+
+#ifndef ANTKEEPER_SPRING_HPP
+#define ANTKEEPER_SPRING_HPP
+
+/**
+ * Performs numeric, damped springing on a value and velocity.
+ *
+ * @tparam T Value type.
+ * @tparam S Scalar type.
+ *
+ * @param[in,out] x0 Start value, which will be oscillated by this function.
+ * @param[in,out] v Velocity, which will be modified by this function.
+ * @param[in] x1 End value.
+ * @param[in] z Damping ratio, which can be undamped (z = 0), underdamped (z < 1), critically damped (z = 1), or overdamped (z > 1).
+ * @param[in] w Angular frequency of the oscillation, in radians per second (2pi = 1Hz).
+ * @param[in] dt Delta time, in seconds.
+ */
+template
+void spring(T& x0, T& v, const T& x1, S z, S w, S dt);
+
+template
+void spring(T& x0, T& v, const T& x1, S z, S w, S dt)
+{
+ const S w2_dt = w * w * dt;
+ const S w2_dt2 = w2_dt * dt;
+ const S f = z * w * dt * S(2) + S(1);
+ const T det_x = x0 * f + v * dt + x1 * w2_dt2;
+ const T det_v = v + (x1 - x0) * w2_dt;
+ const S inv_det = S(1) / (f + w2_dt2);
+
+ x0 = det_x * inv_det;
+ v = det_v * inv_det;
+}
+
+#endif // ANTKEEPER_SPRING_HPP
diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp
index f5a6dd6..a8b2977 100644
--- a/src/game/bootloader.cpp
+++ b/src/game/bootloader.cpp
@@ -888,12 +888,12 @@ void setup_controls(game_context* ctx)
ctx->rotate_ccw_control = new control();
ctx->rotate_ccw_control->set_activated_callback
(
- std::bind(&camera_system::rotate, ctx->camera_system, math::radians(-45.0f))
+ std::bind(&camera_system::rotate, ctx->camera_system, math::radians(-90.0f))
);
ctx->rotate_cw_control = new control();
ctx->rotate_cw_control->set_activated_callback
(
- std::bind(&camera_system::rotate, ctx->camera_system, math::radians(45.0f))
+ std::bind(&camera_system::rotate, ctx->camera_system, math::radians(90.0f))
);
// Create menu back control
diff --git a/src/game/systems/camera-system.cpp b/src/game/systems/camera-system.cpp
index dc0e3d2..3518442 100644
--- a/src/game/systems/camera-system.cpp
+++ b/src/game/systems/camera-system.cpp
@@ -20,6 +20,7 @@
#include "camera-system.hpp"
#include "game/components/camera-subject-component.hpp"
#include "game/components/transform-component.hpp"
+#include "animation/spring.hpp"
#include "scene/camera.hpp"
#include "math/math.hpp"
#include
@@ -69,12 +70,16 @@ void camera_system::update(double t, double dt)
float source_azimuth = math::wrap_radians(std::atan2(-xz_direction.y, xz_direction.x) - math::half_pi);
float source_elevation = elevation;
- std::cout << "azimuth: " << math::degrees(azimuth) << "\n";
- std::cout << "source azimuth: " << math::degrees(source_azimuth) << "\n";
-
float smooth_factor = 0.1f;
float smooth_azimuth = math::lerp_angle(source_azimuth, azimuth, smooth_factor);
float smooth_elevation = math::lerp_angle(source_elevation, elevation, smooth_factor);
+
+
+ smooth_azimuth = source_azimuth;
+ float shortest_angle = math::wrap_radians(azimuth - source_azimuth);
+ static float velocity = 0.0f;
+ spring(smooth_azimuth, velocity, smooth_azimuth + shortest_angle, 1.0f, 2.0f * math::two_pi, dt);
+
quaternion_type smooth_azimuth_rotation = math::angle_axis(smooth_azimuth, float3{0.0f, 1.0f, 0.0f});
quaternion_type smooth_elevation_rotation = math::angle_axis(smooth_elevation, float3{-1.0f, 0.0f, 0.0f});
quaternion_type smooth_rotation = math::normalize(smooth_azimuth_rotation * smooth_elevation_rotation);