diff --git a/Cargo.toml b/Cargo.toml index f742066426..21c86ede6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -910,6 +910,17 @@ description = "Loads and renders a glTF file as a scene, including the gltf extr category = "3D Rendering" wasm = true +[[example]] +name = "query_gltf_primitives" +path = "examples/3d/query_gltf_primitives.rs" +doc-scrape-examples = true + +[package.metadata.example.query_gltf_primitives] +name = "Query glTF primitives" +description = "Query primitives in a glTF scene" +category = "3D Rendering" +wasm = true + [[example]] name = "motion_blur" path = "examples/3d/motion_blur.rs" diff --git a/assets/models/GltfPrimitives/gltf_primitives.glb b/assets/models/GltfPrimitives/gltf_primitives.glb new file mode 100644 index 0000000000..9a53f99cfe Binary files /dev/null and b/assets/models/GltfPrimitives/gltf_primitives.glb differ diff --git a/crates/bevy_gltf/src/lib.rs b/crates/bevy_gltf/src/lib.rs index fdd3a6e783..df8ff45b72 100644 --- a/crates/bevy_gltf/src/lib.rs +++ b/crates/bevy_gltf/src/lib.rs @@ -153,6 +153,7 @@ impl Plugin for GltfPlugin { .register_type::() .register_type::() .register_type::() + .register_type::() .init_asset::() .init_asset::() .init_asset::() @@ -460,6 +461,13 @@ pub struct GltfMaterialExtras { pub value: String, } +/// The material name of a glTF primitive. +/// +/// See [the relevant glTF specification section](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#reference-material). +#[derive(Clone, Debug, Reflect, Default, Component)] +#[reflect(Component)] +pub struct GltfMaterialName(pub String); + /// Labels that can be used to load part of a glTF /// /// You can use [`GltfAssetLabel::from_asset`] to add it to an asset path diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 147d0f3232..758c4d44ca 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -1,6 +1,6 @@ use crate::{ vertex_attributes::convert_attribute, Gltf, GltfAssetLabel, GltfExtras, GltfMaterialExtras, - GltfMeshExtras, GltfNode, GltfSceneExtras, GltfSkin, + GltfMaterialName, GltfMeshExtras, GltfNode, GltfSceneExtras, GltfSkin, }; use alloc::collections::VecDeque; @@ -1380,6 +1380,10 @@ fn load_node( }); } + if let Some(name) = material.name() { + mesh_entity.insert(GltfMaterialName(String::from(name))); + } + mesh_entity.insert(Name::new(primitive_name(&mesh, &primitive))); // Mark for adding skinned mesh if let Some(skin) = gltf_node.skin() { diff --git a/examples/3d/query_gltf_primitives.rs b/examples/3d/query_gltf_primitives.rs new file mode 100644 index 0000000000..f89c090e54 --- /dev/null +++ b/examples/3d/query_gltf_primitives.rs @@ -0,0 +1,96 @@ +//! This example demonstrates how to query a [`StandardMaterial`] within a glTF scene. +//! It is particularly useful for glTF scenes with a mesh that consists of multiple primitives. + +use std::f32::consts::PI; + +use bevy::{ + gltf::GltfMaterialName, + pbr::{CascadeShadowConfigBuilder, DirectionalLightShadowMap}, + prelude::*, + render::mesh::VertexAttributeValues, +}; + +fn main() { + App::new() + .insert_resource(DirectionalLightShadowMap { size: 4096 }) + .add_plugins(DefaultPlugins) + .add_systems(Startup, setup) + .add_systems(Update, find_top_material_and_mesh) + .run(); +} + +fn find_top_material_and_mesh( + mut materials: ResMut>, + mut meshes: ResMut>, + time: Res