only take up to the max number of joints (#9351)
# Objective - Meshes with a higher number of joints than `MAX_JOINTS` are crashing - Fixes partly #9021 (doesn't crash anymore, but the mesh is not correctly displayed) ## Solution - Only take up to `MAX_JOINTS` joints when extending the buffer
This commit is contained in:
parent
f38549c68d
commit
b28f6334da
@ -11,7 +11,7 @@ use bevy_log::warn;
|
|||||||
use bevy_math::{Mat4, Vec3};
|
use bevy_math::{Mat4, Vec3};
|
||||||
use bevy_pbr::{
|
use bevy_pbr::{
|
||||||
AlphaMode, DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle,
|
AlphaMode, DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle,
|
||||||
SpotLight, SpotLightBundle, StandardMaterial,
|
SpotLight, SpotLightBundle, StandardMaterial, MAX_JOINTS,
|
||||||
};
|
};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::{Camera, OrthographicProjection, PerspectiveProjection, Projection, ScalingMode},
|
camera::{Camera, OrthographicProjection, PerspectiveProjection, Projection, ScalingMode},
|
||||||
@ -489,6 +489,7 @@ async fn load_gltf<'a, 'b>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut warned_about_max_joints = HashSet::new();
|
||||||
for (&entity, &skin_index) in &entity_to_skin_index_map {
|
for (&entity, &skin_index) in &entity_to_skin_index_map {
|
||||||
let mut entity = world.entity_mut(entity);
|
let mut entity = world.entity_mut(entity);
|
||||||
let skin = gltf.skins().nth(skin_index).unwrap();
|
let skin = gltf.skins().nth(skin_index).unwrap();
|
||||||
@ -497,6 +498,16 @@ async fn load_gltf<'a, 'b>(
|
|||||||
.map(|node| node_index_to_entity_map[&node.index()])
|
.map(|node| node_index_to_entity_map[&node.index()])
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
if joint_entities.len() > MAX_JOINTS && warned_about_max_joints.insert(skin_index) {
|
||||||
|
warn!(
|
||||||
|
"The glTF skin {:?} has {} joints, but the maximum supported is {}",
|
||||||
|
skin.name()
|
||||||
|
.map(|name| name.to_string())
|
||||||
|
.unwrap_or_else(|| skin.index().to_string()),
|
||||||
|
joint_entities.len(),
|
||||||
|
MAX_JOINTS
|
||||||
|
);
|
||||||
|
}
|
||||||
entity.insert(SkinnedMesh {
|
entity.insert(SkinnedMesh {
|
||||||
inverse_bindposes: skinned_mesh_inverse_bindposes[skin_index].clone(),
|
inverse_bindposes: skinned_mesh_inverse_bindposes[skin_index].clone(),
|
||||||
joints: joint_entities,
|
joints: joint_entities,
|
||||||
|
@ -52,7 +52,8 @@ use crate::render::{
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct MeshRenderPlugin;
|
pub struct MeshRenderPlugin;
|
||||||
|
|
||||||
const MAX_JOINTS: usize = 256;
|
/// Maximum number of joints supported for skinned meshes.
|
||||||
|
pub const MAX_JOINTS: usize = 256;
|
||||||
const JOINT_SIZE: usize = std::mem::size_of::<Mat4>();
|
const JOINT_SIZE: usize = std::mem::size_of::<Mat4>();
|
||||||
pub(crate) const JOINT_BUFFER_SIZE: usize = MAX_JOINTS * JOINT_SIZE;
|
pub(crate) const JOINT_BUFFER_SIZE: usize = MAX_JOINTS * JOINT_SIZE;
|
||||||
|
|
||||||
@ -323,6 +324,7 @@ impl SkinnedMeshJoints {
|
|||||||
joints
|
joints
|
||||||
.iter_many(&skin.joints)
|
.iter_many(&skin.joints)
|
||||||
.zip(inverse_bindposes.iter())
|
.zip(inverse_bindposes.iter())
|
||||||
|
.take(MAX_JOINTS)
|
||||||
.map(|(joint, bindpose)| joint.affine() * *bindpose),
|
.map(|(joint, bindpose)| joint.affine() * *bindpose),
|
||||||
);
|
);
|
||||||
// iter_many will skip any failed fetches. This will cause it to assign the wrong bones,
|
// iter_many will skip any failed fetches. This will cause it to assign the wrong bones,
|
||||||
|
Loading…
Reference in New Issue
Block a user