diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 842290e2d4fcd..87fb8c6318b44 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -6,7 +6,7 @@ use bevy_core::Name; use bevy_core_pipeline::prelude::Camera3dBundle; use bevy_ecs::{entity::Entity, world::World}; use bevy_hierarchy::{BuildWorldChildren, WorldChildBuilder}; -use bevy_log::warn; +use bevy_log::{error, warn}; use bevy_math::{Mat4, Vec3}; use bevy_pbr::{ AlphaMode, DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle, @@ -36,7 +36,7 @@ use gltf::{ accessor::Iter, mesh::{util::ReadIndices, Mode}, texture::{MagFilter, MinFilter, WrappingMode}, - Material, Node, Primitive, + Material, Node, Primitive, Semantic, }; use serde::Deserialize; use std::{ @@ -329,6 +329,17 @@ async fn load_gltf<'a, 'b, 'c>( let mut meshes = vec![]; let mut named_meshes = HashMap::default(); + let mut meshes_on_skinned_nodes = HashSet::default(); + let mut meshes_on_non_skinned_nodes = HashSet::default(); + for gltf_node in gltf.nodes() { + if gltf_node.skin().is_some() { + if let Some(mesh) = gltf_node.mesh() { + meshes_on_skinned_nodes.insert(mesh.index()); + } + } else if let Some(mesh) = gltf_node.mesh() { + meshes_on_non_skinned_nodes.insert(mesh.index()); + } + } for gltf_mesh in gltf.meshes() { let mut primitives = vec![]; for primitive in gltf_mesh.primitives() { @@ -339,6 +350,18 @@ async fn load_gltf<'a, 'b, 'c>( // Read vertex attributes for (semantic, accessor) in primitive.attributes() { + if [Semantic::Joints(0), Semantic::Weights(0)].contains(&semantic) { + if !meshes_on_skinned_nodes.contains(&gltf_mesh.index()) { + warn!( + "Ignoring attribute {:?} for skinned mesh {:?} used on non skinned nodes (NODE_SKINNED_MESH_WITHOUT_SKIN)", + semantic, + primitive_label + ); + continue; + } else if meshes_on_non_skinned_nodes.contains(&gltf_mesh.index()) { + error!("Skinned mesh {:?} used on both skinned and non skin nodes, this is likely to cause an error (NODE_SKINNED_MESH_WITHOUT_SKIN)", primitive_label); + } + } match convert_attribute( semantic, accessor,