Skip to content

Commit

Permalink
return Direction3d from Transform::up and friends (#11604)
Browse files Browse the repository at this point in the history
# Objective
Drawing a `Gizmos::circle` whose normal is derived from a Transform's
local axes now requires converting a Vec3 to a Direction3d and
unwrapping the result, and I think we shold move the conversion into
Bevy.

## Solution
We can make
`Transform::{left,right,up,down,forward,back,local_x,local_y,local_z}`
return a Direction3d, because they know that their results will be of
finite non-zero length (roughly 1.0).

---

## Changelog
`Transform::up()` and similar functions now return `Direction3d` instead
of `Vec3`.

## Migration Guide
Callers of `Transform::up()` and similar functions may have to
dereference the returned `Direction3d` to get to the inner `Vec3`.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Joona Aalto <jondolf.dev@gmail.com>
  • Loading branch information
3 people authored Feb 2, 2024
1 parent 91c467e commit d6f1649
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 17 deletions.
13 changes: 13 additions & 0 deletions crates/bevy_math/src/primitives/dim3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ impl TryFrom<Vec3> for Direction3d {
}
}

impl From<Direction3d> for Vec3 {
fn from(value: Direction3d) -> Self {
value.0
}
}

impl std::ops::Deref for Direction3d {
type Target = Vec3;
fn deref(&self) -> &Self::Target {
Expand All @@ -85,6 +91,13 @@ impl std::ops::Neg for Direction3d {
}
}

impl std::ops::Mul<f32> for Direction3d {
type Output = Vec3;
fn mul(self, rhs: f32) -> Self::Output {
self.0 * rhs
}
}

impl std::ops::Mul<Direction3d> for Quat {
type Output = Direction3d;

Expand Down
28 changes: 16 additions & 12 deletions crates/bevy_transform/src/components/transform.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::GlobalTransform;
use bevy_ecs::{component::Component, reflect::ReflectComponent};
use bevy_math::primitives::Direction3d;
use bevy_math::{Affine3A, Mat3, Mat4, Quat, Vec3};
use bevy_reflect::prelude::*;
use bevy_reflect::Reflect;
Expand Down Expand Up @@ -185,55 +186,58 @@ impl Transform {

/// Get the unit vector in the local `X` direction.
#[inline]
pub fn local_x(&self) -> Vec3 {
self.rotation * Vec3::X
pub fn local_x(&self) -> Direction3d {
// Direction3d::new(x) panics if x is of invalid length, but quat * unit vector is length 1
Direction3d::new(self.rotation * Vec3::X).unwrap()
}

/// Equivalent to [`-local_x()`][Transform::local_x()]
#[inline]
pub fn left(&self) -> Vec3 {
pub fn left(&self) -> Direction3d {
-self.local_x()
}

/// Equivalent to [`local_x()`][Transform::local_x()]
#[inline]
pub fn right(&self) -> Vec3 {
pub fn right(&self) -> Direction3d {
self.local_x()
}

/// Get the unit vector in the local `Y` direction.
#[inline]
pub fn local_y(&self) -> Vec3 {
self.rotation * Vec3::Y
pub fn local_y(&self) -> Direction3d {
// Direction3d::new(x) panics if x is of invalid length, but quat * unit vector is length 1
Direction3d::new(self.rotation * Vec3::Y).unwrap()
}

/// Equivalent to [`local_y()`][Transform::local_y]
#[inline]
pub fn up(&self) -> Vec3 {
pub fn up(&self) -> Direction3d {
self.local_y()
}

/// Equivalent to [`-local_y()`][Transform::local_y]
#[inline]
pub fn down(&self) -> Vec3 {
pub fn down(&self) -> Direction3d {
-self.local_y()
}

/// Get the unit vector in the local `Z` direction.
#[inline]
pub fn local_z(&self) -> Vec3 {
self.rotation * Vec3::Z
pub fn local_z(&self) -> Direction3d {
// Direction3d::new(x) panics if x is of invalid length, but quat * unit vector is length 1
Direction3d::new(self.rotation * Vec3::Z).unwrap()
}

/// Equivalent to [`-local_z()`][Transform::local_z]
#[inline]
pub fn forward(&self) -> Vec3 {
pub fn forward(&self) -> Direction3d {
-self.local_z()
}

/// Equivalent to [`local_z()`][Transform::local_z]
#[inline]
pub fn back(&self) -> Vec3 {
pub fn back(&self) -> Direction3d {
self.local_z()
}

Expand Down
4 changes: 2 additions & 2 deletions examples/3d/tonemapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ fn setup_color_gradient_scene(
camera_transform: Res<CameraTransform>,
) {
let mut transform = camera_transform.0;
transform.translation += transform.forward();
transform.translation += *transform.forward();

commands.spawn((
MaterialMeshBundle {
Expand All @@ -248,7 +248,7 @@ fn setup_image_viewer_scene(
camera_transform: Res<CameraTransform>,
) {
let mut transform = camera_transform.0;
transform.translation += transform.forward();
transform.translation += *transform.forward();

// exr/hdr viewer (exr requires enabling bevy feature)
commands.spawn((
Expand Down
4 changes: 2 additions & 2 deletions examples/helpers/camera_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ fn run_camera_controller(
controller.velocity = Vec3::ZERO;
}
}
let forward = transform.forward();
let right = transform.right();
let forward = *transform.forward();
let right = *transform.right();
transform.translation += controller.velocity.x * dt * right
+ controller.velocity.y * dt * Vec3::Y
+ controller.velocity.z * dt * forward;
Expand Down
2 changes: 1 addition & 1 deletion examples/transforms/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ fn rotate_cube(
// Update the rotation of the cube(s).
for (mut transform, cube) in &mut cubes {
// Calculate the rotation of the cube if it would be looking at the sphere in the center.
let look_at_sphere = transform.looking_at(center, transform.local_y());
let look_at_sphere = transform.looking_at(center, *transform.local_y());
// Interpolate between the current rotation and the fully turned rotation
// when looking a the sphere, with a given turn speed to get a smooth motion.
// With higher speed the curvature of the orbit would be smaller.
Expand Down

0 comments on commit d6f1649

Please sign in to comment.