gltf_skinned_mesh/
gltf_skinned_mesh.rs

1//! Skinned mesh example with mesh and joints data loaded from a glTF file.
2//! Example taken from <https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_019_SimpleSkin.md>
3
4use std::f32::consts::*;
5
6use bevy::{math::ops, mesh::skinning::SkinnedMesh, prelude::*};
7
8fn main() {
9    App::new()
10        .add_plugins(DefaultPlugins)
11        .insert_resource(AmbientLight {
12            brightness: 750.0,
13            ..default()
14        })
15        .add_systems(Startup, setup)
16        .add_systems(Update, joint_animation)
17        .run();
18}
19
20fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
21    // Create a camera
22    commands.spawn((
23        Camera3d::default(),
24        Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::new(0.0, 1.0, 0.0), Vec3::Y),
25    ));
26
27    // Spawn the first scene in `models/SimpleSkin/SimpleSkin.gltf`
28    commands.spawn(SceneRoot(asset_server.load(
29        GltfAssetLabel::Scene(0).from_asset("models/SimpleSkin/SimpleSkin.gltf"),
30    )));
31}
32
33/// The scene hierarchy currently looks somewhat like this:
34///
35/// ```text
36/// <Parent entity>
37///   + Mesh node (without `Mesh3d` or `SkinnedMesh` component)
38///     + Skinned mesh entity (with `Mesh3d` and `SkinnedMesh` component, created by glTF loader)
39///     + First joint
40///       + Second joint
41/// ```
42///
43/// In this example, we want to get and animate the second joint.
44/// It is similar to the animation defined in `models/SimpleSkin/SimpleSkin.gltf`.
45fn joint_animation(
46    time: Res<Time>,
47    children: Query<&ChildOf, With<SkinnedMesh>>,
48    parents: Query<&Children>,
49    mut transform_query: Query<&mut Transform>,
50) {
51    // Iter skinned mesh entity
52    for child_of in &children {
53        // Mesh node is the parent of the skinned mesh entity.
54        let mesh_node_entity = child_of.parent();
55        // Get `Children` in the mesh node.
56        let mesh_node_parent = parents.get(mesh_node_entity).unwrap();
57
58        // First joint is the second child of the mesh node.
59        let first_joint_entity = mesh_node_parent[1];
60        // Get `Children` in the first joint.
61        let first_joint_children = parents.get(first_joint_entity).unwrap();
62
63        // Second joint is the first child of the first joint.
64        let second_joint_entity = first_joint_children[0];
65        // Get `Transform` in the second joint.
66        let mut second_joint_transform = transform_query.get_mut(second_joint_entity).unwrap();
67
68        second_joint_transform.rotation =
69            Quat::from_rotation_z(FRAC_PI_2 * ops::sin(time.elapsed_secs()));
70    }
71}