Skip to content
This repository has been archived by the owner on May 7, 2024. It is now read-only.

Quat animation #1

Merged
merged 10 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -351,4 +351,3 @@ icon = "@mipmap/ic_launcher"
build_targets = ["aarch64-linux-android", "armv7-linux-androideabi"]
min_sdk_version = 16
target_sdk_version = 29

2 changes: 1 addition & 1 deletion crates/bevy_animation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ bevy_transform = { path = "../bevy_transform", version = "0.3.0" }
bevy_render = { path = "../bevy_render", version = "0.3.0" }
bevy_property = { path = "../bevy_property", version = "0.3.0" }

splines = { version = "3.5.0", features = ["serialization"] }
splines = { version = "3.5.0", features = ["serialization", "impl-glam"] }
5 changes: 3 additions & 2 deletions crates/bevy_animation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ pub mod prelude {
plugin::AnimationPlugin,
spline_group::{LoopStyle, SplineGroup},
spline_groups::{
one::AnimationSplineOne, three::AnimationSplineThree,
transform::AnimationSplineTransform,
one::AnimationSplineOne,
three::AnimationSplineThree,
transform::{AnimationSplineTransform, SplineQuatExt},
},
vec3_option::Vec3Option,
};
Expand Down
14 changes: 7 additions & 7 deletions crates/bevy_animation/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
use bevy_app::{AppBuilder, Plugin};
use bevy_core::Time;
use bevy_ecs::{IntoSystem, Query, Res};
use bevy_math::{Quat, Vec3};
use bevy_math::Vec3;
use bevy_transform::components::Transform;

#[derive(Default)]
Expand Down Expand Up @@ -41,15 +41,15 @@ fn advance_animation_transform(
for (mut transform, mut splines) in q.iter_mut() {
let mut scale = transform.scale;
splines.advance(time.delta_seconds);
let s = splines.current();
s.translation.alter(&mut transform.translation);
if let Some(sample_scale) = s.scale {
let sample = splines.current();
sample.translation.alter(&mut transform.translation);
if let Some(sample_scale) = sample.scale {
scale = Vec3::one() * sample_scale;
}
let mut rot = Vec3::zero();
s.rotation.alter(&mut rot);
*transform = Transform::from_translation(transform.translation);
transform.rotation = Quat::from_rotation_ypr(rot.x, rot.y, rot.z);
if let Some(rotation) = sample.rotation {
transform.rotation = rotation;
}
transform.apply_non_uniform_scale(scale);
}
}
60 changes: 19 additions & 41 deletions crates/bevy_animation/src/spline_group.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use core::time::Duration;
use splines::Spline;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum LoopStyle {
Expand All @@ -11,7 +10,7 @@ pub enum LoopStyle {
pub trait SplineGroup {
type Sample;

fn splines(&self) -> Vec<&Spline<f32, f32>>;
fn spline_key_times(&self) -> Vec<Box<dyn DoubleEndedIterator<Item = f32> + '_>>;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I think we should leave the splines function available for general use alongside your new spline_key_times function, rather than replacing it.

  • Dunno about returning a Vec containing arbitrary iterators. Consider adding another type to the SplineGroup trait instead?

pub trait SplineGroup {
  type Sample;
  type KeyTimes;

  fn spline_key_times(&self) -> KeyTimes;

  // ...

}

impl SplineGroup for AnimationSplineOne {
  type Sample = Option<f32>;
  type KeyTimes = Box<dyn DoubleEndedIterator<Item = f32> + '_>;
  
  // ...

}

Copy link
Author

@iwikal iwikal Nov 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is, there can no longer be an fn splines(&self) -> Vec<&Spline<f32, f32>> on SplineGroup, since not all splines have f32 values - one of them has Quats instead. So I looked around to see what the splines method was used for internally, replaced it with spline_key_times, and didn't really think too hard about how people might want to use it in general. I kind of assumed that it was just a side effect of needing to use it internally, and not having private trait methods. What's the use case?

I was absolutely not pleased with returning a Vec<Box<dyn Iterator>>, but I just wanted to get a proof of concept working. Now that you've brought it back to my attention, I would like to look into if there's a better way to implement start_time, end_time and is_empty on SplineGroup, which to my knowledge are the only things spline_key_times is used for. Maybe we could just leave them as required methods, instead of trying to create a general default implementation that will probably end up needing dynamic dispatch?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is, there can no longer be an fn splines(&self) -> Vec<&Spline<f32, f32>> on SplineGroup, since not all splines have f32 values - one of them has Quats instead.

Ah, true that.

What's the use case?

main one I thought of is that if this is eventually integrated into a UI, you'd want direct access to the splines for drawing them in a curve editor.

Maybe we could just leave them as required methods, instead of trying to create a general default implementation that will probably end up needing dynamic dispatch?

Seems like a good option. Feel free to experiment.

It's worth mentioning that there's Another PR doing animation that uses property names and just seems overall more flexible than the hard-typed implementation we're doing here. It might be a better option entirely.

Copy link
Author

@iwikal iwikal Nov 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth mentioning that there's Another PR doing animation that uses property names and just seems overall more flexible than the hard-typed implementation we're doing here. It might be a better option entirely.

Wow, I hadn't seen that. I'm looking through it now, trying to understand what they're doing.


fn loop_style(&self) -> LoopStyle;
fn loop_style_mut(&mut self) -> &mut LoopStyle;
Expand All @@ -35,44 +34,33 @@ pub trait SplineGroup {
}

fn is_empty(&self) -> bool {
let any_not_empty = self.splines().into_iter().any(|v| !v.is_empty());
let any_not_empty = self
.spline_key_times()
.into_iter()
.any(|mut i| i.next().is_some());
!any_not_empty
}

fn start_time(&self) -> Option<f32> {
let starts: Vec<f32> = self
.splines()
let mut starts = self
.spline_key_times()
.into_iter()
.filter_map(spline_start_time)
.collect();

if starts.is_empty() {
None
} else {
Some(
starts
.iter()
.fold(starts[0], |acc, v| if *v < acc { *v } else { acc }),
)
}
.filter_map(|mut iter| iter.next());

let first = starts.next()?;

Some(starts.fold(first, |acc, v| if v < acc { v } else { acc }))
}

fn end_time(&self) -> Option<f32> {
let ends: Vec<f32> = self
.splines()
let mut ends = self
.spline_key_times()
.into_iter()
.map(|s| spline_end_time(s))
.filter_map(|s| s)
.collect();

if ends.is_empty() {
None
} else {
Some(
ends.iter()
.fold(ends[0], |acc, v| if *v > acc { *v } else { acc }),
)
}
.filter_map(|mut s| s.next_back());

let first = ends.next()?;

Some(ends.fold(first, |acc, v| if v > acc { v } else { acc }))
}

fn duration(&self) -> Option<Duration> {
Expand Down Expand Up @@ -147,13 +135,3 @@ pub trait SplineGroup {
*self.paused_mut() = !paused;
}
}

fn spline_start_time(spline: &Spline<f32, f32>) -> Option<f32> {
spline.get(0).map(|first_key| first_key.t)
}

fn spline_end_time(spline: &Spline<f32, f32>) -> Option<f32> {
spline
.get(spline.len().saturating_sub(1))
.map(|last_key| last_key.t)
}
4 changes: 2 additions & 2 deletions crates/bevy_animation/src/spline_groups/one.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ impl Default for AnimationSplineOne {
impl SplineGroup for AnimationSplineOne {
type Sample = Option<f32>;

fn splines(&self) -> Vec<&Spline<f32, f32>> {
vec![&self.spline]
fn spline_key_times(&self) -> Vec<Box<dyn DoubleEndedIterator<Item = f32> + '_>> {
vec![Box::new(self.spline.keys().iter().map(|key| key.t))]
}

fn loop_style(&self) -> LoopStyle {
Expand Down
8 changes: 6 additions & 2 deletions crates/bevy_animation/src/spline_groups/three.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ impl Default for AnimationSplineThree {
impl SplineGroup for AnimationSplineThree {
type Sample = Vec3Option;

fn splines(&self) -> Vec<&Spline<f32, f32>> {
vec![&self.x, &self.y, &self.z]
fn spline_key_times(&self) -> Vec<Box<dyn DoubleEndedIterator<Item = f32> + '_>> {
vec![
Box::new(self.x.keys().iter().map(|key| key.t)),
Box::new(self.y.keys().iter().map(|key| key.t)),
Box::new(self.z.keys().iter().map(|key| key.t)),
]
}

fn loop_style(&self) -> LoopStyle {
Expand Down
Loading