Skip to content

Commit

Permalink
Fix look_to resulting in NaN rotations (bevyengine#7817)
Browse files Browse the repository at this point in the history
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Liam Gallagher <ljpgallagher@xtra.co.nz>
  • Loading branch information
3 people authored and Shfty committed Mar 19, 2023
1 parent 3ce6ead commit 6ba3139
Showing 1 changed file with 26 additions and 2 deletions.
28 changes: 26 additions & 2 deletions crates/bevy_transform/src/components/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ impl Transform {

/// Returns this [`Transform`] with a new rotation so that [`Transform::forward`]
/// points towards the `target` position and [`Transform::up`] points towards `up`.
///
/// In some cases it's not possible to construct a rotation. Another axis will be picked in those cases:
/// * if `target` is the same as the transform translation, `Vec3::Z` is used instead
/// * if `up` is zero, `Vec3::Y` is used instead
/// * if the resulting forward direction is parallel with `up`, an orthogonal vector is used as the "right" direction
#[inline]
#[must_use]
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
Expand All @@ -129,6 +134,11 @@ impl Transform {

/// Returns this [`Transform`] with a new rotation so that [`Transform::forward`]
/// points in the given `direction` and [`Transform::up`] points towards `up`.
///
/// In some cases it's not possible to construct a rotation. Another axis will be picked in those cases:
/// * if `direction` is zero, `Vec3::Z` is used instead
/// * if `up` is zero, `Vec3::Y` is used instead
/// * if `direction` is parallel with `up`, an orthogonal vector is used as the "right" direction
#[inline]
#[must_use]
pub fn looking_to(mut self, direction: Vec3, up: Vec3) -> Self {
Expand Down Expand Up @@ -325,17 +335,31 @@ impl Transform {

/// Rotates this [`Transform`] so that [`Transform::forward`] points towards the `target` position,
/// and [`Transform::up`] points towards `up`.
///
/// In some cases it's not possible to construct a rotation. Another axis will be picked in those cases:
/// * if `target` is the same as the transtorm translation, `Vec3::Z` is used instead
/// * if `up` is zero, `Vec3::Y` is used instead
/// * if the resulting forward direction is parallel with `up`, an orthogonal vector is used as the "right" direction
#[inline]
pub fn look_at(&mut self, target: Vec3, up: Vec3) {
self.look_to(target - self.translation, up);
}

/// Rotates this [`Transform`] so that [`Transform::forward`] points in the given `direction`
/// and [`Transform::up`] points towards `up`.
///
/// In some cases it's not possible to construct a rotation. Another axis will be picked in those cases:
/// * if `direction` is zero, `Vec3::Z` is used instead
/// * if `up` is zero, `Vec3::Y` is used instead
/// * if `direction` is parallel with `up`, an orthogonal vector is used as the "right" direction
#[inline]
pub fn look_to(&mut self, direction: Vec3, up: Vec3) {
let forward = -direction.normalize();
let right = up.cross(forward).normalize();
let forward = -direction.try_normalize().unwrap_or(Vec3::Z);
let up = up.try_normalize().unwrap_or(Vec3::Y);
let right = up
.cross(forward)
.try_normalize()
.unwrap_or_else(|| up.any_orthonormal_vector());
let up = forward.cross(right);
self.rotation = Quat::from_mat3(&Mat3::from_cols(right, up, forward));
}
Expand Down

0 comments on commit 6ba3139

Please sign in to comment.