Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Curve-based animation #15434

Merged
merged 27 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
df68f07
Allow curves to animate transforms, properties, and morph weights
mweatherley Sep 25, 2024
423e4b0
Move some imports around in glTF loader
mweatherley Sep 25, 2024
39f7f0a
Drastically improve reflection trait implementations of curve adaptors
mweatherley Sep 26, 2024
030deb4
Merge branch 'main' into curve-anim
mweatherley Sep 27, 2024
6db9e53
Resolve new std -> core lints
mweatherley Sep 27, 2024
eee7a23
Fix doc typo
mweatherley Sep 28, 2024
8c366e4
Fix compile issue without bevy_reflect feature
mweatherley Sep 28, 2024
e350c7d
Improve reflection implementations for sample-based curves with expli…
mweatherley Sep 28, 2024
bbb5b81
Lint
mweatherley Sep 28, 2024
2089667
Wrangle features
mweatherley Sep 28, 2024
7c4fd9d
Apply `#[reflect(Debug)]`
mweatherley Sep 28, 2024
fd0709b
Hide paths behind bevy_reflect feature
mweatherley Sep 28, 2024
7416549
Revert nonfunctional Debug reflects
mweatherley Sep 28, 2024
a88109e
Added comments on instability of TypeName implementations
mweatherley Sep 28, 2024
a80ac91
Tweaks to curve adaptor reflection
mweatherley Sep 28, 2024
a709058
Merge branch 'main' into curve-anim
mweatherley Sep 29, 2024
f12555d
Remove PhantomData from Debug, use AnimationEntityMut
mweatherley Sep 29, 2024
8e480d6
Improve cubic spline interpolation function used by gltf curves
mweatherley Sep 29, 2024
766db9b
Fix cubic interpolation formula used by gltf curves
mweatherley Sep 30, 2024
a1869b2
Merge branch 'main' into sample-curve-reflection
mweatherley Sep 30, 2024
f104a49
Update doc comments
mweatherley Sep 30, 2024
e697a0b
Apply suggestions from code review
mweatherley Sep 30, 2024
934d44e
More error formatting
mweatherley Sep 30, 2024
07e80c5
Rename ProductCurve -> ZipCurve
mweatherley Sep 30, 2024
25a1251
Merge branch 'sample-curve-reflection' into curve-anim
mweatherley Sep 30, 2024
926aa7b
Rebase again
mweatherley Sep 30, 2024
cb9e054
Merge again again (and pray?)
mweatherley Sep 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 2 additions & 84 deletions crates/bevy_animation/src/animatable.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Traits and type for interpolating between values.

use crate::{util, AnimationEvaluationError, Interpolation};
use crate::util;
use bevy_color::{Laba, LinearRgba, Oklaba, Srgba, Xyza};
use bevy_math::*;
use bevy_reflect::Reflect;
Expand Down Expand Up @@ -188,93 +188,11 @@ impl Animatable for Quat {
}
}

/// An abstraction over a list of keyframes.
///
/// Using this abstraction instead of `Vec<T>` enables more flexibility in how
/// keyframes are stored. In particular, morph weights use this trait in order
/// to flatten the keyframes for all morph weights into a single vector instead
/// of nesting vectors.
pub(crate) trait GetKeyframe {
/// The type of the property to be animated.
type Output;
/// Retrieves the value of the keyframe at the given index.
fn get_keyframe(&self, index: usize) -> Option<&Self::Output>;
}

/// Interpolates between keyframes and stores the result in `dest`.
///
/// This is factored out so that it can be shared between implementations of
/// [`crate::keyframes::Keyframes`].
pub(crate) fn interpolate_keyframes<T>(
dest: &mut T,
keyframes: &(impl GetKeyframe<Output = T> + ?Sized),
interpolation: Interpolation,
step_start: usize,
time: f32,
weight: f32,
duration: f32,
) -> Result<(), AnimationEvaluationError>
where
T: Animatable + Clone,
{
let value = match interpolation {
Interpolation::Step => {
let Some(start_keyframe) = keyframes.get_keyframe(step_start) else {
return Err(AnimationEvaluationError::KeyframeNotPresent(step_start));
};
(*start_keyframe).clone()
}

Interpolation::Linear => {
let (Some(start_keyframe), Some(end_keyframe)) = (
keyframes.get_keyframe(step_start),
keyframes.get_keyframe(step_start + 1),
) else {
return Err(AnimationEvaluationError::KeyframeNotPresent(step_start + 1));
};

T::interpolate(start_keyframe, end_keyframe, time)
}

Interpolation::CubicSpline => {
let (
Some(start_keyframe),
Some(start_tangent_keyframe),
Some(end_tangent_keyframe),
Some(end_keyframe),
) = (
keyframes.get_keyframe(step_start * 3 + 1),
keyframes.get_keyframe(step_start * 3 + 2),
keyframes.get_keyframe(step_start * 3 + 3),
keyframes.get_keyframe(step_start * 3 + 4),
)
else {
return Err(AnimationEvaluationError::KeyframeNotPresent(
step_start * 3 + 4,
));
};

interpolate_with_cubic_bezier(
start_keyframe,
start_tangent_keyframe,
end_tangent_keyframe,
end_keyframe,
time,
duration,
)
}
};

*dest = T::interpolate(dest, &value, weight);

Ok(())
}

/// Evaluates a cubic Bézier curve at a value `t`, given two endpoints and the
/// derivatives at those endpoints.
///
/// The derivatives are linearly scaled by `duration`.
fn interpolate_with_cubic_bezier<T>(p0: &T, d0: &T, d3: &T, p3: &T, t: f32, duration: f32) -> T
pub fn interpolate_with_cubic_bezier<T>(p0: &T, d0: &T, d3: &T, p3: &T, t: f32, duration: f32) -> T
where
T: Animatable + Clone,
{
Expand Down
Loading