8#include <glm/gtc/quaternion.hpp>
10#include "core/math/easing.h"
12namespace Vkm::Engine {
28 AnimationTrack() =
default;
57 auto it = std::upper_bound(m_times.begin(), m_times.end(), time);
58 auto index =
static_cast<size_t>(it - m_times.begin());
59 m_times.insert(it, time);
60 m_values.insert(m_values.begin() + index, value);
73 for (
size_t i = 0; i < m_times.size(); ++i) {
88 if (index >= m_times.size())
return;
89 m_times.erase(m_times.begin() +
static_cast<std::ptrdiff_t
>(index));
90 m_values.erase(m_values.begin() +
static_cast<std::ptrdiff_t
>(index));
100 if (index >= m_values.size())
return;
101 m_values[index] = value;
114 if (index >= m_times.size())
return index;
115 T value = m_values[index];
143 if (m_times.empty()) {
147 if (m_times.size() == 1) {
152 if (time <= m_times.front()) {
153 return m_values.front();
156 if (time >= m_times.back()) {
157 return m_values.back();
161 auto it = std::upper_bound(m_times.begin(), m_times.end(), time);
163 const size_t nextIndex =
static_cast<size_t>(it - m_times.begin());
164 const size_t prevIndex = nextIndex - 1;
166 float segmentDuration = m_times[nextIndex] - m_times[prevIndex];
167 if (segmentDuration <= 0.0f) {
168 return m_values[prevIndex];
171 float t = (time - m_times[prevIndex]) / segmentDuration;
173 const float eased = easingFunction(m_easing)(t);
175 return interpolate(m_values[prevIndex], m_values[nextIndex], eased);
184 if (m_times.empty()) {
187 return m_times.back();
190 bool isEmpty()
const {
191 return m_times.empty();
194 size_t keyframeCount()
const {
195 return m_times.size();
212 const std::vector<float>&
getTimes()
const {
return m_times; }
219 const std::vector<T>&
getValues()
const {
return m_values; }
231 template<
typename U = T>
232 static U interpolate(
const U& a,
const U& b,
float t) {
233 if constexpr (std::is_same_v<U, glm::quat>) {
234 return glm::slerp(a, b, t);
236 return glm::mix(a, b, t);
241 std::vector<float> m_times;
242 std::vector<T> m_values;
243 Easing m_easing = Easing::Linear;
Keyframes of type T sorted by time, sampled through an easing curve.
Definition animation_track.h:22
size_t addKeyframe(float time, const T &value)
Add a keyframe at time.
Definition animation_track.h:56
float getDuration() const
The track's length.
Definition animation_track.h:183
size_t setKeyframeTime(size_t index, float time)
Move the keyframe at index to time.
Definition animation_track.h:113
const std::vector< float > & getTimes() const
The keyframe times, ascending.
Definition animation_track.h:212
static constexpr float SAME_INSTANT_SECONDS
Two keyframe times closer than this, in seconds, are one instant.
Definition animation_track.h:25
void removeKeyframe(size_t index)
Remove the keyframe at index; out of range is a no-op.
Definition animation_track.h:87
Easing getEasing() const
The curve this track eases with.
Definition animation_track.h:203
void setKeyframeValue(size_t index, const T &value)
Replace the value of the keyframe at index; out of range is a no-op.
Definition animation_track.h:99
void setKeyframe(float time, const T &value)
Set the value at time, replacing any keyframe already there.
Definition animation_track.h:72
T getValue(float time) const
Sample the track at time.
Definition animation_track.h:142
void setEasing(Easing easing)
Choose the curve this track eases its interpolation with.
Definition animation_track.h:130
const std::vector< T > & getValues() const
The keyframe values, parallel to getTimes.
Definition animation_track.h:219
AnimationTrack(Easing easing)
Construct a track that interpolates with easing.
Definition animation_track.h:35