forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
example on how to create an animation in code (bevyengine#4399)
# Objective - Animation can be used outside of glTF, but are not obvious on how to create them ## Solution - Add an example creating an animation
- Loading branch information
Showing
3 changed files
with
146 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
use std::f32::consts::{FRAC_PI_2, PI}; | ||
|
||
use bevy::prelude::*; | ||
|
||
fn main() { | ||
App::new() | ||
.add_plugins(DefaultPlugins) | ||
.insert_resource(AmbientLight { | ||
color: Color::WHITE, | ||
brightness: 1.0, | ||
}) | ||
.add_startup_system(setup) | ||
.run(); | ||
} | ||
|
||
fn setup( | ||
mut commands: Commands, | ||
mut meshes: ResMut<Assets<Mesh>>, | ||
mut materials: ResMut<Assets<StandardMaterial>>, | ||
mut animations: ResMut<Assets<AnimationClip>>, | ||
) { | ||
// Camera | ||
commands.spawn_bundle(PerspectiveCameraBundle { | ||
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), | ||
..default() | ||
}); | ||
|
||
// The animation API uses the `Name` component to target entities | ||
let planet = Name::new("planet"); | ||
let orbit_controller = Name::new("orbit_controller"); | ||
let satellite = Name::new("satellite"); | ||
|
||
// Creating the animation | ||
let mut animation = AnimationClip::default(); | ||
// A curve can modify a single part of a transform, here the translation | ||
animation.add_curve_to_path( | ||
EntityPath { | ||
parts: vec![planet.clone()], | ||
}, | ||
VariableCurve { | ||
keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0], | ||
keyframes: Keyframes::Translation(vec![ | ||
Vec3::new(1.0, 0.0, 1.0), | ||
Vec3::new(-1.0, 0.0, 1.0), | ||
Vec3::new(-1.0, 0.0, -1.0), | ||
Vec3::new(1.0, 0.0, -1.0), | ||
// in case seamless looping is wanted, the last keyframe should | ||
// be the same as the first one | ||
Vec3::new(1.0, 0.0, 1.0), | ||
]), | ||
}, | ||
); | ||
// Or it can modify the rotation of the transform. | ||
// To find the entity to modify, the hierarchy will be traversed looking for | ||
// an entity with the right name at each level | ||
animation.add_curve_to_path( | ||
EntityPath { | ||
parts: vec![planet.clone(), orbit_controller.clone()], | ||
}, | ||
VariableCurve { | ||
keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0], | ||
keyframes: Keyframes::Rotation(vec![ | ||
Quat::from_axis_angle(Vec3::Y, 0.0), | ||
Quat::from_axis_angle(Vec3::Y, FRAC_PI_2), | ||
Quat::from_axis_angle(Vec3::Y, PI), | ||
Quat::from_axis_angle(Vec3::Y, 3.0 * FRAC_PI_2), | ||
Quat::from_axis_angle(Vec3::Y, 0.0), | ||
]), | ||
}, | ||
); | ||
// If a curve in an animation is shorter than the other, it will not repeat | ||
// until all other curves are finished. In that case, another animation should | ||
// be created for each part that would have a different duration / period | ||
animation.add_curve_to_path( | ||
EntityPath { | ||
parts: vec![planet.clone(), orbit_controller.clone(), satellite.clone()], | ||
}, | ||
VariableCurve { | ||
keyframe_timestamps: vec![0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0], | ||
keyframes: Keyframes::Scale(vec![ | ||
Vec3::splat(0.8), | ||
Vec3::splat(1.2), | ||
Vec3::splat(0.8), | ||
Vec3::splat(1.2), | ||
Vec3::splat(0.8), | ||
Vec3::splat(1.2), | ||
Vec3::splat(0.8), | ||
Vec3::splat(1.2), | ||
Vec3::splat(0.8), | ||
]), | ||
}, | ||
); | ||
// There can be more than one curve targeting the same entity path | ||
animation.add_curve_to_path( | ||
EntityPath { | ||
parts: vec![planet.clone(), orbit_controller.clone(), satellite.clone()], | ||
}, | ||
VariableCurve { | ||
keyframe_timestamps: vec![0.0, 1.0, 2.0, 3.0, 4.0], | ||
keyframes: Keyframes::Rotation(vec![ | ||
Quat::from_axis_angle(Vec3::Y, 0.0), | ||
Quat::from_axis_angle(Vec3::Y, FRAC_PI_2), | ||
Quat::from_axis_angle(Vec3::Y, PI), | ||
Quat::from_axis_angle(Vec3::Y, 3.0 * FRAC_PI_2), | ||
Quat::from_axis_angle(Vec3::Y, 0.0), | ||
]), | ||
}, | ||
); | ||
|
||
// Create the animation player, and set it to repeat | ||
let mut player = AnimationPlayer::default(); | ||
player.play(animations.add(animation)).repeat(); | ||
|
||
// Create the scene that will be animated | ||
// First entity is the planet | ||
commands | ||
.spawn_bundle(PbrBundle { | ||
mesh: meshes.add(Mesh::from(shape::Icosphere::default())), | ||
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()), | ||
..default() | ||
}) | ||
// Add the Name component, and the animation player | ||
.insert_bundle((planet, player)) | ||
.with_children(|p| { | ||
// This entity is just used for animation, but doesn't display anything | ||
p.spawn_bundle(TransformBundle { ..default() }) | ||
// Add the Name component | ||
.insert(orbit_controller) | ||
.with_children(|p| { | ||
// The satellite, placed at a distance of the planet | ||
p.spawn_bundle(PbrBundle { | ||
transform: Transform::from_xyz(1.5, 0.0, 0.0), | ||
mesh: meshes.add(Mesh::from(shape::Cube { size: 0.5 })), | ||
material: materials.add(Color::rgb(0.3, 0.9, 0.3).into()), | ||
..default() | ||
}) | ||
// Add the Name component | ||
.insert(satellite); | ||
}); | ||
}); | ||
} |