From 78a3aae81bbf1cf60efbd0e44fb423f57afc1aff Mon Sep 17 00:00:00 2001 From: Sou1gh0st Date: Tue, 1 Oct 2024 00:51:52 +0800 Subject: [PATCH] feat(gltf): add name component to gltf mesh primitive (#13912) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective - fixes https://github.com/bevyengine/bevy/issues/13473 ## Solution - When a single mesh is assigned multiple materials, it is divided into several primitive nodes, with each primitive assigned a unique material. Presently, these primitives are named using the format Mesh.index, which complicates querying. To improve this, we can assign a specific name to each primitive based on the material’s name, since each primitive corresponds to one material exclusively. ## Testing - I have included a simple example which shows how to query a material and mesh part based on the new name component. ## Changelog - adds `GltfMaterialName` component to the mesh entity of the gltf primitive node. --------- Co-authored-by: Alice Cecile --- Cargo.toml | 11 ++ .../models/GltfPrimitives/gltf_primitives.glb | Bin 0 -> 4428 bytes crates/bevy_gltf/src/lib.rs | 8 ++ crates/bevy_gltf/src/loader.rs | 6 +- examples/3d/query_gltf_primitives.rs | 96 ++++++++++++++++++ examples/README.md | 1 + 6 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 assets/models/GltfPrimitives/gltf_primitives.glb create mode 100644 examples/3d/query_gltf_primitives.rs 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 0000000000000000000000000000000000000000..9a53f99cfea0dce12473c165ba13e4b32161827b GIT binary patch literal 4428 zcmb_e&2Jk;6rZ$(mLd*?8>eU_PHfD4?9Q%Dagv5qq@*!Qq6#UB+O@s0SF(4b^*W@r zEPUdE#0ey%N(hPn0->ZQj{F0NJAVNZaN)hlZg>3=e~?-lznQo5-uu1Zyf?dz*8cr# zgpln!g#7syArJN{J3Z=lI$lgmJ=*XBFLL8Bq9yuiGYW&Sv)lla<$EnJsC&`!)(4g4 z6IqZ2VN-*icu~g>1K2DIjP?!MseuDpV#%ySO9wp~xNXqUJ^jp}L0I?j0Xys;W~&}; zd!42>P4;hes~*KIZ8!EJ-)&uZtB2ic%iHtoUY(ZWsOy1`ivauKFD#RgSuZs6PYy=*kEB^=Fl`~>d+c?sPYc&yhA?Cp_4f*4m;!kB!kES zf7}WVR!1N7=Si4p*kZFPhAUJMmzJL#;5$EZY%W zS+Gw^!A)ZYt0UHa>7&gJ2^Z&Ze4t=P{At#}%G}msEH>~sZmpF%cVHojy|=Nxy}mnU z59Ey7Pvp)qEk`P@gr#gQ9eb2JO`m|KGljB+k|r0Xt!7XM2R$SFH0m_YsRy4~k5dQD zFdlmW>Yzo&?I%(}L?Cl!*+E~k<_oZgx52oBj6QrmZ`;np7T!3s;!WjiMyDX&%zgr46H7fKj6*pk_Gzm^L1fol z{@T-5UiE40ZF@l@hOaOajB#B#I?`W;aJI1cRzjGF9B=RCT3+DODr1(F`Kw&0CF_hDf%=R@10z^76+V(hSy$na4E?)67Z(%HFoc1#A} zJfB=A-SE}zaO5i z{un&}aGp6K%ix2+Ksf-vPm(oCTwfyq1;!E?iI30EVdP~x*ZOz9xl?`{hWYEW)p_O_ zh8LJ048(*#ToXWmXqGghJTEy67+1$mWV$~8_xq*t-!RVp=*=}xVnci#8zf>`OV(?v z*8v5xf~clof&CiK`4sNbJ)`nGwVfbwZ@M4%4b7kb@>lt%2T#s_d$D;J0KyM3kU?Ib zpX)6X_9S-N!SGzGw9jF^j+5-q??LVejFih%qJ98pi|f2Z{aUggCBgFtiTXjJM~V7D d`8IijyiRVzxJho|dBFb-@@8^ESii54{{Tzc7!d#f literal 0 HcmV?d00001 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