query_gltf_primitives/
query_gltf_primitives.rs

1//! This example demonstrates how to query a [`StandardMaterial`] within a glTF scene.
2//! It is particularly useful for glTF scenes with a mesh that consists of multiple primitives.
3
4use std::f32::consts::PI;
5
6use bevy::{gltf::GltfMaterialName, mesh::VertexAttributeValues, prelude::*};
7
8fn main() {
9    App::new()
10        .add_plugins(DefaultPlugins)
11        .add_systems(Startup, setup)
12        .add_systems(Update, find_top_material_and_mesh)
13        .run();
14}
15
16fn find_top_material_and_mesh(
17    mut materials: ResMut<Assets<StandardMaterial>>,
18    mut meshes: ResMut<Assets<Mesh>>,
19    time: Res<Time>,
20    mat_query: Query<(
21        &MeshMaterial3d<StandardMaterial>,
22        &Mesh3d,
23        &GltfMaterialName,
24    )>,
25) {
26    for (mat_handle, mesh_handle, name) in mat_query.iter() {
27        // locate a material by material name
28        if name.0 == "Top" {
29            if let Some(material) = materials.get_mut(mat_handle) {
30                if let Color::Hsla(ref mut hsla) = material.base_color {
31                    *hsla = hsla.rotate_hue(time.delta_secs() * 100.0);
32                } else {
33                    material.base_color = Color::from(Hsla::hsl(0.0, 0.9, 0.7));
34                }
35            }
36
37            if let Some(mesh) = meshes.get_mut(mesh_handle)
38                && let Some(VertexAttributeValues::Float32x3(positions)) =
39                    mesh.attribute_mut(Mesh::ATTRIBUTE_POSITION)
40            {
41                for position in positions {
42                    *position = (
43                        position[0],
44                        1.5 + 0.5 * ops::sin(time.elapsed_secs() / 2.0),
45                        position[2],
46                    )
47                        .into();
48                }
49            }
50        }
51    }
52}
53
54fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
55    commands.spawn((
56        Camera3d::default(),
57        Transform::from_xyz(4.0, 4.0, 12.0).looking_at(Vec3::new(0.0, 0.0, 0.5), Vec3::Y),
58    ));
59
60    commands.spawn((
61        Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
62        DirectionalLight::default(),
63    ));
64
65    commands.spawn(SceneRoot(asset_server.load(
66        GltfAssetLabel::Scene(0).from_asset("models/GltfPrimitives/gltf_primitives.glb"),
67    )));
68}