Path: blob/main/crates/bevy_gltf/src/convert_coordinates.rs
9374 views
//! Utilities for converting from glTF's [standard coordinate system](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#coordinate-system-and-units)1//! to Bevy's.2use serde::{Deserialize, Serialize};34use bevy_math::{Mat4, Quat, Vec3};5use bevy_transform::components::Transform;67pub(crate) trait ConvertCoordinates {8/// Converts from glTF coordinates to Bevy's coordinate system. See9/// [`GltfConvertCoordinates`] for an explanation of the conversion.10fn convert_coordinates(self) -> Self;11}1213impl ConvertCoordinates for Vec3 {14fn convert_coordinates(self) -> Self {15Vec3::new(-self.x, self.y, -self.z)16}17}1819impl ConvertCoordinates for [f32; 3] {20fn convert_coordinates(self) -> Self {21[-self[0], self[1], -self[2]]22}23}2425impl ConvertCoordinates for [f32; 4] {26fn convert_coordinates(self) -> Self {27// Solution of q' = r q r*28[-self[0], self[1], -self[2], self[3]]29}30}3132/// Options for converting scenes and assets from glTF's [standard coordinate system](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#coordinate-system-and-units)33/// (+Z forward) to Bevy's coordinate system (-Z forward).34///35/// _CAUTION: This is an experimental feature. Behavior may change in future versions._36///37/// The exact coordinate system conversion is as follows:38///39/// - glTF:40/// - forward: +Z41/// - up: +Y42/// - right: -X43/// - Bevy:44/// - forward: -Z45/// - up: +Y46/// - right: +X47///48/// Cameras and lights are an exception - they already use Bevy's coordinate49/// system. This means cameras and lights will match Bevy's forward even if50/// conversion is disabled.51///52/// If a glTF file uses the standard coordinate system, then the conversion53/// options will behave like so:54///55/// - `rotate_scene_entity` will make the glTF's scene forward align with the [`Transform::forward`]56/// of the entity with the [`SceneInstance`](bevy_scene::SceneInstance) component.57/// - `rotate_meshes` will do the same for entities with a `Mesh3d` component.58///59/// Other entities in the scene are not converted, so their forward may not60/// match `Transform::forward`. In particular, the entities that correspond to61/// glTF nodes are not converted.62#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)]63pub struct GltfConvertCoordinates {64/// If true, convert scenes by rotating the top-level transform of the scene entity.65/// This will ensure that [`Transform::forward`] of the "root" entity (the one with [`SceneInstance`](bevy_scene::SceneInstance))66/// aligns with the "forward" of the glTF scene.67///68/// The scene entity is created by the glTF loader. Its parent is the entity69/// with the `SceneInstance` component, and its children are the root nodes70/// of the glTF scene.71///72/// This option only changes the transform of the scene entity. It does not73/// directly change the transforms of node entities - it only changes them74/// indirectly through transform inheritance.75pub rotate_scene_entity: bool,7677/// If true, convert mesh assets and skinned mesh bind poses.78///79/// This option only changes mesh assets and the transforms of entities that80/// instance meshes through [`Mesh3d`](bevy_mesh::Mesh3d).81pub rotate_meshes: bool,82}8384impl GltfConvertCoordinates {85const CONVERSION_TRANSFORM: Transform =86Transform::from_rotation(Quat::from_xyzw(0.0, 1.0, 0.0, 0.0));8788fn conversion_mat4() -> Mat4 {89Mat4::from_scale(Vec3::new(-1.0, 1.0, -1.0))90}9192pub(crate) fn scene_conversion_transform(&self) -> Transform {93if self.rotate_scene_entity {94Self::CONVERSION_TRANSFORM95} else {96Transform::IDENTITY97}98}99100pub(crate) fn mesh_conversion_transform(&self) -> Transform {101if self.rotate_meshes {102Self::CONVERSION_TRANSFORM103} else {104Transform::IDENTITY105}106}107108pub(crate) fn mesh_conversion_transform_inverse(&self) -> Transform {109// We magically know that the transform is its own inverse. We still110// make a distinction at the interface level in case that changes.111self.mesh_conversion_transform()112}113114pub(crate) fn mesh_conversion_mat4(&self) -> Mat4 {115if self.rotate_meshes {116Self::conversion_mat4()117} else {118Mat4::IDENTITY119}120}121}122123124