Browse Source

Add damped numeric springing function

master
C. J. Howard 3 years ago
parent
commit
bd8a818d84
3 changed files with 63 additions and 5 deletions
  1. +53
    -0
      src/animation/spring.hpp
  2. +2
    -2
      src/game/bootloader.cpp
  3. +8
    -3
      src/game/systems/camera-system.cpp

+ 53
- 0
src/animation/spring.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <typename T, typename S>
void spring(T& x0, T& v, const T& x1, S z, S w, S dt);
template <typename T, typename S>
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

+ 2
- 2
src/game/bootloader.cpp View File

@ -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

+ 8
- 3
src/game/systems/camera-system.cpp View File

@ -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 <cmath>
@ -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>);
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<float, float>(smooth_azimuth, velocity, smooth_azimuth + shortest_angle, 1.0f, 2.0f * math::two_pi<float>, 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);

Loading…
Cancel
Save