Path: blob/main/crates/bevy_gltf/src/loader/gltf_ext/scene.rs
9451 views
use bevy_ecs::name::Name;1use bevy_math::{Mat4, Vec3};2use bevy_transform::components::Transform;34use gltf::scene::Node;56use fixedbitset::FixedBitSet;7use itertools::Itertools;89#[cfg(feature = "bevy_animation")]10use bevy_platform::collections::{HashMap, HashSet};1112use crate::GltfError;1314pub(crate) fn node_name(node: &Node) -> Name {15let name = node16.name()17.map(ToString::to_string)18.unwrap_or_else(|| format!("GltfNode{}", node.index()));19Name::new(name)20}2122/// Calculate the transform of gLTF [`Node`].23///24/// This should be used instead of calling [`gltf::scene::Transform::matrix()`]25/// on [`Node::transform()`](gltf::Node::transform) directly because it uses optimized glam types and26/// if `libm` feature of `bevy_math` crate is enabled also handles cross27/// platform determinism properly.28pub(crate) fn node_transform(node: &Node) -> Transform {29match node.transform() {30gltf::scene::Transform::Matrix { matrix } => {31Transform::from_matrix(Mat4::from_cols_array_2d(&matrix))32}33gltf::scene::Transform::Decomposed {34translation,35rotation,36scale,37} => Transform {38translation: Vec3::from(translation),39rotation: bevy_math::Quat::from_array(rotation),40scale: Vec3::from(scale),41},42}43}4445#[cfg_attr(46not(target_arch = "wasm32"),47expect(48clippy::result_large_err,49reason = "need to be signature compatible with `load_gltf`"50)51)]52/// Check if [`Node`] is part of cycle53pub(crate) fn check_is_part_of_cycle(54node: &Node,55visited: &mut FixedBitSet,56) -> Result<(), GltfError> {57// Do we have a cycle?58if visited.contains(node.index()) {59return Err(GltfError::CircularChildren(format!(60"glTF nodes form a cycle: {} -> {}",61visited.ones().map(|bit| bit.to_string()).join(" -> "),62node.index()63)));64}6566// Recurse.67visited.insert(node.index());68for kid in node.children() {69check_is_part_of_cycle(&kid, visited)?;70}71visited.remove(node.index());7273Ok(())74}7576#[cfg(feature = "bevy_animation")]77pub(crate) fn collect_path(78node: &Node,79current_path: &[Name],80paths: &mut HashMap<usize, (usize, Vec<Name>)>,81root_index: usize,82visited: &mut HashSet<usize>,83) {84let mut path = current_path.to_owned();85path.push(node_name(node));86visited.insert(node.index());87for child in node.children() {88if !visited.contains(&child.index()) {89collect_path(&child, &path, paths, root_index, visited);90}91}92paths.insert(node.index(), (root_index, path));93}949596