Skip to content

Commit c6b93fc

Browse files
committed
Load each glTF skin at most once.
Currently, we reload a glTF skin each time we encounter a node that references it. By checking for duplicates, PR bevyengine#18013 turned this into a fatal error. But this was always wasteful. This commit fixes the issue by caching each skin by its index as we load it. The Maya babylon.js export plugin likes to emit glTFs with multiple nodes that reference the same skin, so this effectively unbreaks Maya rigs.
1 parent 20813ae commit c6b93fc

File tree

1 file changed

+35
-31
lines changed

1 file changed

+35
-31
lines changed

crates/bevy_gltf/src/loader.rs

+35-31
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ async fn load_gltf<'a, 'b, 'c>(
801801

802802
let mut nodes = HashMap::<usize, Handle<GltfNode>>::default();
803803
let mut named_nodes = <HashMap<_, _>>::default();
804-
let mut skins = vec![];
804+
let mut skins = <HashMap<_, _>>::default();
805805
let mut named_skins = <HashMap<_, _>>::default();
806806

807807
// First, create the node handles.
@@ -817,39 +817,43 @@ async fn load_gltf<'a, 'b, 'c>(
817817
// Now populate the nodes.
818818
for node in gltf.nodes() {
819819
let skin = node.skin().map(|skin| {
820-
let joints: Vec<_> = skin
821-
.joints()
822-
.map(|joint| nodes.get(&joint.index()).unwrap().clone())
823-
.collect();
824-
825-
if joints.len() > MAX_JOINTS {
826-
warn!(
827-
"The glTF skin {} has {} joints, but the maximum supported is {}",
828-
skin.name()
829-
.map(ToString::to_string)
830-
.unwrap_or_else(|| skin.index().to_string()),
831-
joints.len(),
832-
MAX_JOINTS
833-
);
834-
}
820+
skins
821+
.entry(skin.index())
822+
.or_insert_with(|| {
823+
let joints: Vec<_> = skin
824+
.joints()
825+
.map(|joint| nodes.get(&joint.index()).unwrap().clone())
826+
.collect();
827+
828+
if joints.len() > MAX_JOINTS {
829+
warn!(
830+
"The glTF skin {} has {} joints, but the maximum supported is {}",
831+
skin.name()
832+
.map(ToString::to_string)
833+
.unwrap_or_else(|| skin.index().to_string()),
834+
joints.len(),
835+
MAX_JOINTS
836+
);
837+
}
835838

836-
let gltf_skin = GltfSkin::new(
837-
&skin,
838-
joints,
839-
skinned_mesh_inverse_bindposes[skin.index()].clone(),
840-
get_gltf_extras(skin.extras()),
841-
);
839+
let gltf_skin = GltfSkin::new(
840+
&skin,
841+
joints,
842+
skinned_mesh_inverse_bindposes[skin.index()].clone(),
843+
get_gltf_extras(skin.extras()),
844+
);
842845

843-
let handle = load_context
844-
.add_labeled_asset(skin_label(&skin), gltf_skin)
845-
.expect("skin indices are unique, so the label is unique");
846+
let handle = load_context
847+
.add_labeled_asset(skin_label(&skin), gltf_skin)
848+
.expect("skin indices are unique, so the label is unique");
846849

847-
skins.push(handle.clone());
848-
if let Some(name) = skin.name() {
849-
named_skins.insert(name.into(), handle.clone());
850-
}
850+
if let Some(name) = skin.name() {
851+
named_skins.insert(name.into(), handle.clone());
852+
}
851853

852-
handle
854+
handle
855+
})
856+
.clone()
853857
});
854858

855859
let children = node
@@ -984,7 +988,7 @@ async fn load_gltf<'a, 'b, 'c>(
984988
named_scenes,
985989
meshes,
986990
named_meshes,
987-
skins,
991+
skins: skins.into_values().collect(),
988992
named_skins,
989993
materials,
990994
named_materials,

0 commit comments

Comments
 (0)