Skip to content

Instantly share code, notes, and snippets.

@dmlary
Created December 29, 2023 01:58
Show Gist options
  • Save dmlary/c0c08b3ba69cca771a4dd220526842c9 to your computer and use it in GitHub Desktop.
Save dmlary/c0c08b3ba69cca771a4dd220526842c9 to your computer and use it in GitHub Desktop.
bevy 0.12 system for spawning a `GltfNode` from `Handle<GltfNode>`
fn gltf_node_spawner(
mut commands: Commands,
node_handles: Query<(Entity, &Handle<GltfNode>), Added<Handle<GltfNode>>>,
assets_gltf_nodes: Res<Assets<GltfNode>>,
assets_gltf_mesh: Res<Assets<GltfMesh>>,
) {
for (parent, handle) in &node_handles {
let Some(node) = assets_gltf_nodes.get(handle) else {
warn!("GltfNode not found: entity {:?}, {:?}", parent, handle);
continue;
};
// because the root GltfNode has a Transform component, we need to
// start loading the node in a child entity. If we don't do this,
// modifying the `Transform` on the `Handle<GltfNode>` entity will
// warp the mesh.
let node_entity = commands
.spawn(SpatialBundle::default())
.set_parent(parent)
.id();
let mut node_queue: VecDeque<(Entity, &GltfNode)> = VecDeque::from([(node_entity, node)]);
while let Some((node_entity, node)) = node_queue.pop_front() {
// create a child entity for each of the GltfNode children and
// queue it for processing
let mut children: Vec<Entity> = node
.children
.iter()
.map(|child_node| {
let child = commands.spawn_empty().id();
node_queue.push_back((child, &child_node));
child
})
.collect();
// If the GltfNode has a GltfMesh, process it now and add any
// children to the list.
if let Some(handle) = &node.mesh {
if let Some(gltf_mesh) = assets_gltf_mesh.get(handle) {
// create a PbrBundle child for every primitive in the
// GltfMesh
for primitive in gltf_mesh.primitives.iter() {
let child = commands.spawn(PbrBundle {
mesh: primitive.mesh.clone_weak(),
material: primitive
.material
.as_ref()
.expect("primitive to have a material")
.clone_weak(),
..default()
});
children.push(child.id());
}
} else {
warn!("GltfMesh not found: entity {:?}, {:?}", node_entity, handle);
}
}
commands
.entity(node_entity)
.push_children(&children)
.insert(SpatialBundle {
transform: node.transform,
..default()
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment