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