blob: 8ea2e58fac95f426032bb986efa09d59d084282a [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_LIB_UI_SCENIC_UTIL_RK4_SPRING_SIMULATION_H_
#define GARNET_LIB_UI_SCENIC_UTIL_RK4_SPRING_SIMULATION_H_
namespace scenic_impl {
class RK4SpringSimulation {
public:
// |initial_value| is the starting point for the value that's being animated
// (using the spring-like physics).
// |tension| and |friction| are parameters for the spring simulation.
RK4SpringSimulation(float initial_value, float tension = 300.0,
float friction = 25.0);
// The simulation will iteratively approach |target_value|.
void SetTargetValue(float target_value);
// Whether the spring simulation has settled.
bool is_done() { return is_done_; }
float target_value() { return target_value_; }
// The current value of the animated value, interpolated from the start and
// end values using the spring simulation.
float GetValue();
// Step forward in time using the spring simulation.
void ElapseTime(float seconds);
private:
float x_acceleration(float x, float velocity) {
return (-tension_ * x - friction_ * velocity) * acceleration_multiplier_;
}
// Evaluates one tick of a spring using the Runge-Kutta Algorithm.
// This is generally a bit mathy, here is a reasonable intro for those
// interested:
// http://gafferongames.com/game-physics/integration-basics/
// |step_size| is the duration between steps.
// This should be around 1/60th of a second. Values too large will not
// work as the spring adjusts itself over time based on previous values,
// so if values are larger than 1/60th of a second this method should be
// called for each whole 1/60th of a second segment plus the remainder.
//
// Returns true if the spring has settled to minimum amount.
bool EvaluateRK(float step_size);
// The settle theshold for the spring (for both distance and/or velocity).
const float kTolerance = 0.01;
const float kMaxStepSize = 1 / 60.f;
// The parameters of the simulation.
const float tension_;
const float friction_;
float start_value_;
float target_value_;
// The current velocity of the spring.
float velocity_;
// The current acceleration multiplier. This slowly grows as the simulation
// progresses. This is used to make the spring more gentle by slowing its
// initial progress.
float acceleration_multiplier_;
bool is_done_;
/// How far along the spring the current value is, 0 being start and 1 being
/// end. Because this is a spring that value will go beyond 1 and then back
/// below 1 etc, as it 'springs'.
float spring_value_;
};
} // namespace scenic_impl
#endif // GARNET_LIB_UI_SCENIC_UTIL_RK4_SPRING_SIMULATION_H_