documentation on Transform and GlobalTransform (#1687)
fixes #1599 * Added doc on `Transform` and `GlobalTransform` to describe usage and how `GlobalTransform` is updated * Documented all methods on `Transform` * `#[doc(hidden)]` most constructors and methods mutating `GlobalTransform`, documented the other * Mentioned z-ordering for `Transform` in 2d
This commit is contained in:
parent
8d1e52be31
commit
348e2a3d40
@ -4,6 +4,35 @@ use bevy_math::{Mat3, Mat4, Quat, Vec3};
|
|||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
|
|
||||||
|
/// Describe the position of an entity relative to the reference frame.
|
||||||
|
///
|
||||||
|
/// * To place or move an entity, you should set its [`Transform`].
|
||||||
|
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
|
||||||
|
/// * To get the global position of an entity, you should get its [`GlobalTransform`].
|
||||||
|
///
|
||||||
|
/// ## [`Transform`] and [`GlobalTransform`]
|
||||||
|
///
|
||||||
|
/// [`Transform`] is the position of an entity relative to its parent position, or the reference
|
||||||
|
/// frame if it doesn't have a [`Parent`](super::Parent).
|
||||||
|
///
|
||||||
|
/// [`GlobalTransform`] is the position of an entity relative to the reference frame.
|
||||||
|
///
|
||||||
|
/// [`GlobalTransform`] is updated from [`Transform`] in the system
|
||||||
|
/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system).
|
||||||
|
///
|
||||||
|
/// In pseudo code:
|
||||||
|
/// ```ignore
|
||||||
|
/// for entity in entities_without_parent:
|
||||||
|
/// set entity.global_transform to entity.transform
|
||||||
|
/// recursively:
|
||||||
|
/// set parent to current entity
|
||||||
|
/// for child in parent.children:
|
||||||
|
/// set child.global_transform to parent.global_transform * child.transform
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you
|
||||||
|
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
|
||||||
|
/// before the [`GlobalTransform`] is updated.
|
||||||
#[derive(Debug, PartialEq, Clone, Copy, Reflect)]
|
#[derive(Debug, PartialEq, Clone, Copy, Reflect)]
|
||||||
#[reflect(Component, PartialEq)]
|
#[reflect(Component, PartialEq)]
|
||||||
pub struct GlobalTransform {
|
pub struct GlobalTransform {
|
||||||
@ -13,12 +42,14 @@ pub struct GlobalTransform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalTransform {
|
impl GlobalTransform {
|
||||||
/// Create a new [`GlobalTransform`] at the position `(x, y, z)`
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_xyz(x: f32, y: f32, z: f32) -> Self {
|
pub fn from_xyz(x: f32, y: f32, z: f32) -> Self {
|
||||||
Self::from_translation(Vec3::new(x, y, z))
|
Self::from_translation(Vec3::new(x, y, z))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new identity [`GlobalTransform`], with no translation, rotation, and a scale of 1
|
||||||
|
/// on all axes.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn identity() -> Self {
|
pub const fn identity() -> Self {
|
||||||
GlobalTransform {
|
GlobalTransform {
|
||||||
@ -28,6 +59,7 @@ impl GlobalTransform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_matrix(matrix: Mat4) -> Self {
|
pub fn from_matrix(matrix: Mat4) -> Self {
|
||||||
let (scale, rotation, translation) = matrix.to_scale_rotation_translation();
|
let (scale, rotation, translation) = matrix.to_scale_rotation_translation();
|
||||||
@ -39,6 +71,7 @@ impl GlobalTransform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_translation(translation: Vec3) -> Self {
|
pub fn from_translation(translation: Vec3) -> Self {
|
||||||
GlobalTransform {
|
GlobalTransform {
|
||||||
@ -47,6 +80,7 @@ impl GlobalTransform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_rotation(rotation: Quat) -> Self {
|
pub fn from_rotation(rotation: Quat) -> Self {
|
||||||
GlobalTransform {
|
GlobalTransform {
|
||||||
@ -55,6 +89,7 @@ impl GlobalTransform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_scale(scale: Vec3) -> Self {
|
pub fn from_scale(scale: Vec3) -> Self {
|
||||||
GlobalTransform {
|
GlobalTransform {
|
||||||
@ -63,43 +98,46 @@ impl GlobalTransform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns transform with the same translation and scale, but rotation so that
|
#[doc(hidden)]
|
||||||
/// transform.forward() points at target
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
|
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
|
||||||
self.look_at(target, up);
|
self.look_at(target, up);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the 3d affine transformation matrix from this transforms translation,
|
||||||
|
/// rotation, and scale.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compute_matrix(&self) -> Mat4 {
|
pub fn compute_matrix(&self) -> Mat4 {
|
||||||
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
|
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Get the unit vector in the local x direction
|
/// Get the unit vector in the local x direction
|
||||||
|
#[inline]
|
||||||
pub fn local_x(&self) -> Vec3 {
|
pub fn local_x(&self) -> Vec3 {
|
||||||
self.rotation * Vec3::X
|
self.rotation * Vec3::X
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Get the unit vector in the local y direction
|
/// Get the unit vector in the local y direction
|
||||||
|
#[inline]
|
||||||
pub fn local_y(&self) -> Vec3 {
|
pub fn local_y(&self) -> Vec3 {
|
||||||
self.rotation * Vec3::Y
|
self.rotation * Vec3::Y
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Get the unit vector in the local z direction
|
/// Get the unit vector in the local z direction
|
||||||
|
#[inline]
|
||||||
pub fn local_z(&self) -> Vec3 {
|
pub fn local_z(&self) -> Vec3 {
|
||||||
self.rotation * Vec3::Z
|
self.rotation * Vec3::Z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Rotate the transform by the given rotation
|
|
||||||
pub fn rotate(&mut self, rotation: Quat) {
|
pub fn rotate(&mut self, rotation: Quat) {
|
||||||
self.rotation *= rotation;
|
self.rotation *= rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Multiplies `self` with `transform` component by component, returning the
|
||||||
|
/// resulting [`GlobalTransform`]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mul_transform(&self, transform: Transform) -> GlobalTransform {
|
pub fn mul_transform(&self, transform: Transform) -> GlobalTransform {
|
||||||
let translation = self.mul_vec3(transform.translation);
|
let translation = self.mul_vec3(transform.translation);
|
||||||
@ -112,6 +150,7 @@ impl GlobalTransform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a [`Vec3`] of this [`Transform`] applied to `value`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 {
|
pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 {
|
||||||
value = self.rotation * value;
|
value = self.rotation * value;
|
||||||
@ -120,11 +159,13 @@ impl GlobalTransform {
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn apply_non_uniform_scale(&mut self, scale: Vec3) {
|
pub fn apply_non_uniform_scale(&mut self, scale: Vec3) {
|
||||||
self.scale *= scale;
|
self.scale *= scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn look_at(&mut self, target: Vec3, up: Vec3) {
|
pub fn look_at(&mut self, target: Vec3, up: Vec3) {
|
||||||
let forward = Vec3::normalize(self.translation - target);
|
let forward = Vec3::normalize(self.translation - target);
|
||||||
|
@ -4,21 +4,58 @@ use bevy_math::{Mat3, Mat4, Quat, Vec3};
|
|||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
|
|
||||||
|
/// Describe the position of an entity. If the entity has a parent, the position is relative
|
||||||
|
/// to its parent position.
|
||||||
|
///
|
||||||
|
/// * To place or move an entity, you should set its [`Transform`].
|
||||||
|
/// * To be displayed, an entity must have both a [`Transform`] and a [`GlobalTransform`].
|
||||||
|
/// * To get the global position of an entity, you should get its [`GlobalTransform`].
|
||||||
|
///
|
||||||
|
/// ## [`Transform`] and [`GlobalTransform`]
|
||||||
|
///
|
||||||
|
/// [`Transform`] is the position of an entity relative to its parent position, or the reference
|
||||||
|
/// frame if it doesn't have a [`Parent`](super::Parent).
|
||||||
|
///
|
||||||
|
/// [`GlobalTransform`] is the position of an entity relative to the reference frame.
|
||||||
|
///
|
||||||
|
/// [`GlobalTransform`] is updated from [`Transform`] in the system
|
||||||
|
/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system).
|
||||||
|
///
|
||||||
|
/// In pseudo code:
|
||||||
|
/// ```ignore
|
||||||
|
/// for entity in entities_without_parent:
|
||||||
|
/// set entity.global_transform to entity.transform
|
||||||
|
/// recursively:
|
||||||
|
/// set parent to current entity
|
||||||
|
/// for child in parent.children:
|
||||||
|
/// set child.global_transform to parent.global_transform * child.transform
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you
|
||||||
|
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
|
||||||
|
/// before the [`GlobalTransform`] is updated.
|
||||||
#[derive(Debug, PartialEq, Clone, Copy, Reflect)]
|
#[derive(Debug, PartialEq, Clone, Copy, Reflect)]
|
||||||
#[reflect(Component, PartialEq)]
|
#[reflect(Component, PartialEq)]
|
||||||
pub struct Transform {
|
pub struct Transform {
|
||||||
|
/// Position of the entity. In 2d, the last value of the `Vec3` is used for z-ordering.
|
||||||
pub translation: Vec3,
|
pub translation: Vec3,
|
||||||
|
/// Rotation of the entity.
|
||||||
pub rotation: Quat,
|
pub rotation: Quat,
|
||||||
|
/// Scale of the entity.
|
||||||
pub scale: Vec3,
|
pub scale: Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Transform {
|
impl Transform {
|
||||||
/// Create a new [`Transform`] at the position `(x, y, z)`
|
/// Creates a new [`Transform`] at the position `(x, y, z)`. In 2d, the `z` component
|
||||||
|
/// is used for z-ordering elements: higher `z`-value will be in front of lower
|
||||||
|
/// `z`-value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_xyz(x: f32, y: f32, z: f32) -> Self {
|
pub fn from_xyz(x: f32, y: f32, z: f32) -> Self {
|
||||||
Self::from_translation(Vec3::new(x, y, z))
|
Self::from_translation(Vec3::new(x, y, z))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new identity [`Transform`], with no translation, rotation, and a scale of 1 on
|
||||||
|
/// all axes.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn identity() -> Self {
|
pub const fn identity() -> Self {
|
||||||
Transform {
|
Transform {
|
||||||
@ -28,6 +65,8 @@ impl Transform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extracts the translation, rotation, and scale from `matrix`. It must be a 3d affine
|
||||||
|
/// transformation matrix.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_matrix(matrix: Mat4) -> Self {
|
pub fn from_matrix(matrix: Mat4) -> Self {
|
||||||
let (scale, rotation, translation) = matrix.to_scale_rotation_translation();
|
let (scale, rotation, translation) = matrix.to_scale_rotation_translation();
|
||||||
@ -39,6 +78,8 @@ impl Transform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new [`Transform`], with `translation`. Rotation will be 0 and scale 1 on
|
||||||
|
/// all axes.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_translation(translation: Vec3) -> Self {
|
pub fn from_translation(translation: Vec3) -> Self {
|
||||||
Transform {
|
Transform {
|
||||||
@ -47,6 +88,8 @@ impl Transform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new [`Transform`], with `rotation`. Translation will be 0 and scale 1 on
|
||||||
|
/// all axes.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_rotation(rotation: Quat) -> Self {
|
pub fn from_rotation(rotation: Quat) -> Self {
|
||||||
Transform {
|
Transform {
|
||||||
@ -55,6 +98,8 @@ impl Transform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new [`Transform`], with `scale`. Translation will be 0 and rotation 0 on
|
||||||
|
/// all axes.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_scale(scale: Vec3) -> Self {
|
pub fn from_scale(scale: Vec3) -> Self {
|
||||||
Transform {
|
Transform {
|
||||||
@ -63,43 +108,48 @@ impl Transform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns transform with the same translation and scale, but rotation so that
|
/// Updates and returns this [`Transform`] by rotating it so that its unit vector in the
|
||||||
/// transform.forward() points at target
|
/// local z direction is toward `target` and its unit vector in the local y direction
|
||||||
|
/// is toward `up`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
|
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
|
||||||
self.look_at(target, up);
|
self.look_at(target, up);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the 3d affine transformation matrix from this transforms translation,
|
||||||
|
/// rotation, and scale.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compute_matrix(&self) -> Mat4 {
|
pub fn compute_matrix(&self) -> Mat4 {
|
||||||
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
|
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the unit vector in the local x direction.
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Get the unit vector in the local x direction
|
|
||||||
pub fn local_x(&self) -> Vec3 {
|
pub fn local_x(&self) -> Vec3 {
|
||||||
self.rotation * Vec3::X
|
self.rotation * Vec3::X
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the unit vector in the local y direction.
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Get the unit vector in the local y direction
|
|
||||||
pub fn local_y(&self) -> Vec3 {
|
pub fn local_y(&self) -> Vec3 {
|
||||||
self.rotation * Vec3::Y
|
self.rotation * Vec3::Y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the unit vector in the local z direction.
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Get the unit vector in the local z direction
|
|
||||||
pub fn local_z(&self) -> Vec3 {
|
pub fn local_z(&self) -> Vec3 {
|
||||||
self.rotation * Vec3::Z
|
self.rotation * Vec3::Z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rotates the transform by the given rotation.
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Rotate the transform by the given rotation
|
|
||||||
pub fn rotate(&mut self, rotation: Quat) {
|
pub fn rotate(&mut self, rotation: Quat) {
|
||||||
self.rotation *= rotation;
|
self.rotation *= rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Multiplies `self` with `transform` component by component, returning the
|
||||||
|
/// resulting [`Transform`]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mul_transform(&self, transform: Transform) -> Self {
|
pub fn mul_transform(&self, transform: Transform) -> Self {
|
||||||
let translation = self.mul_vec3(transform.translation);
|
let translation = self.mul_vec3(transform.translation);
|
||||||
@ -112,6 +162,7 @@ impl Transform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a [`Vec3`] of this [`Transform`] applied to `value`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 {
|
pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 {
|
||||||
value = self.rotation * value;
|
value = self.rotation * value;
|
||||||
@ -120,11 +171,15 @@ impl Transform {
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Changes the `scale` of this [`Transform`], multiplying the current `scale` by
|
||||||
|
/// `scale_factor`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn apply_non_uniform_scale(&mut self, scale: Vec3) {
|
pub fn apply_non_uniform_scale(&mut self, scale_factor: Vec3) {
|
||||||
self.scale *= scale;
|
self.scale *= scale_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rotates this [`Transform`] so that its unit vector in the local z direction is toward
|
||||||
|
/// `target` and its unit vector in the local y direction is toward `up`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn look_at(&mut self, target: Vec3, up: Vec3) {
|
pub fn look_at(&mut self, target: Vec3, up: Vec3) {
|
||||||
let forward = Vec3::normalize(self.translation - target);
|
let forward = Vec3::normalize(self.translation - target);
|
||||||
|
@ -5,6 +5,8 @@ use bevy_ecs::{
|
|||||||
system::Query,
|
system::Query,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Update [`GlobalTransform`] component of entities based on entity hierarchy and
|
||||||
|
/// [`Transform`] component.
|
||||||
pub fn transform_propagate_system(
|
pub fn transform_propagate_system(
|
||||||
mut root_query: Query<
|
mut root_query: Query<
|
||||||
(Entity, Option<&Children>, &Transform, &mut GlobalTransform),
|
(Entity, Option<&Children>, &Transform, &mut GlobalTransform),
|
||||||
|
Loading…
Reference in New Issue
Block a user