animated_mesh/
animated_mesh.rs1use std::f32::consts::PI;
4
5use bevy::{
6 light::CascadeShadowConfigBuilder, prelude::*, world_serialization::WorldInstanceReady,
7};
8
9const GLTF_PATH: &str = "models/animated/Fox.glb";
11
12fn main() {
13 App::new()
14 .insert_resource(GlobalAmbientLight {
15 color: Color::WHITE,
16 brightness: 2000.,
17 ..default()
18 })
19 .add_plugins(DefaultPlugins)
20 .add_systems(Startup, setup_mesh_and_animation)
21 .add_systems(Startup, setup_camera_and_environment)
22 .run();
23}
24
25#[derive(Component)]
29struct AnimationToPlay {
30 graph_handle: Handle<AnimationGraph>,
31 index: AnimationNodeIndex,
32}
33
34fn setup_mesh_and_animation(
35 mut commands: Commands,
36 asset_server: Res<AssetServer>,
37 mut graphs: ResMut<Assets<AnimationGraph>>,
38) {
39 let (graph, index) = AnimationGraph::from_clip(
42 asset_server.load(GltfAssetLabel::Animation(2).from_asset(GLTF_PATH)),
43 );
44
45 let graph_handle = graphs.add(graph);
47
48 let animation_to_play = AnimationToPlay {
50 graph_handle,
51 index,
52 };
53
54 let mesh_scene =
58 WorldAssetRoot(asset_server.load(GltfAssetLabel::Scene(0).from_asset(GLTF_PATH)));
59
60 commands
63 .spawn((animation_to_play, mesh_scene))
64 .observe(play_animation_when_ready);
65}
66
67fn play_animation_when_ready(
68 scene_ready: On<WorldInstanceReady>,
69 mut commands: Commands,
70 children: Query<&Children>,
71 animations_to_play: Query<&AnimationToPlay>,
72 mut players: Query<&mut AnimationPlayer>,
73) {
74 if let Ok(animation_to_play) = animations_to_play.get(scene_ready.entity) {
77 for child in children.iter_descendants(scene_ready.entity) {
82 if let Ok(mut player) = players.get_mut(child) {
83 player.play(animation_to_play.index).repeat();
89
90 commands
93 .entity(child)
94 .insert(AnimationGraphHandle(animation_to_play.graph_handle.clone()));
95 }
96 }
97 }
98}
99
100fn setup_camera_and_environment(
102 mut commands: Commands,
103 mut meshes: ResMut<Assets<Mesh>>,
104 mut materials: ResMut<Assets<StandardMaterial>>,
105) {
106 commands.spawn((
108 Camera3d::default(),
109 Transform::from_xyz(100.0, 100.0, 150.0).looking_at(Vec3::new(0.0, 20.0, 0.0), Vec3::Y),
110 ));
111
112 commands.spawn((
114 Mesh3d(meshes.add(Plane3d::default().mesh().size(500000.0, 500000.0))),
115 MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
116 ));
117
118 commands.spawn((
120 Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
121 DirectionalLight {
122 shadow_maps_enabled: true,
123 ..default()
124 },
125 CascadeShadowConfigBuilder {
126 first_cascade_far_bound: 200.0,
127 maximum_distance: 400.0,
128 ..default()
129 }
130 .build(),
131 ));
132}