Use glam for computing gLTF node transform (#11361)

# Objective

gltf-rs does its own computations when accessing `transform.matrix()`
which does not use glam types, rendering #11238 useless if people were
to load gltf models and expecting the results to be deterministic across
platforms.

## Solution

Move the computation to bevy side which uses glam types, it was already
used in one place, so I created one common function to handle the two
cases.

The added benefit this has, is that some gltf files can have
translation, rotation and scale directly instead of matrix which skips
the transform computation completely, win-win.
This commit is contained in:
Richard Hozák 2024-01-16 15:33:19 +01:00 committed by GitHub
parent 135c7240f1
commit 184f233a67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -525,20 +525,7 @@ async fn load_gltf<'a, 'b, 'c>(
.mesh()
.map(|mesh| mesh.index())
.and_then(|i| meshes.get(i).cloned()),
transform: match node.transform() {
gltf::scene::Transform::Matrix { matrix } => {
Transform::from_matrix(Mat4::from_cols_array_2d(&matrix))
}
gltf::scene::Transform::Decomposed {
translation,
rotation,
scale,
} => Transform {
translation: bevy_math::Vec3::from(translation),
rotation: bevy_math::Quat::from_array(rotation),
scale: bevy_math::Vec3::from(scale),
},
},
transform: node_transform(&node),
extras: get_gltf_extras(node.extras()),
},
node.children()
@ -690,6 +677,29 @@ fn get_gltf_extras(extras: &gltf::json::Extras) -> Option<GltfExtras> {
})
}
/// Calculate the transform of gLTF node.
///
/// This should be used instead of calling [`gltf::scene::Transform::matrix()`]
/// on [`Node::transform()`] directly because it uses optimized glam types and
/// if `libm` feature of `bevy_math` crate is enabled also handles cross
/// platform determinism properly.
fn node_transform(node: &Node) -> Transform {
match node.transform() {
gltf::scene::Transform::Matrix { matrix } => {
Transform::from_matrix(Mat4::from_cols_array_2d(&matrix))
}
gltf::scene::Transform::Decomposed {
translation,
rotation,
scale,
} => Transform {
translation: bevy_math::Vec3::from(translation),
rotation: bevy_math::Quat::from_array(rotation),
scale: bevy_math::Vec3::from(scale),
},
}
}
fn node_name(node: &Node) -> Name {
let name = node
.name()
@ -916,9 +926,8 @@ fn load_node(
active_camera_found: &mut bool,
parent_transform: &Transform,
) -> Result<(), GltfError> {
let transform = gltf_node.transform();
let mut gltf_error = None;
let transform = Transform::from_matrix(Mat4::from_cols_array_2d(&transform.matrix()));
let transform = node_transform(gltf_node);
let world_transform = *parent_transform * transform;
// according to https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#instantiation,
// if the determinant of the transform is negative we must invert the winding order of