Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix look_to resulting in NaN rotations #7817

Merged
merged 4 commits into from
Mar 15, 2023
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 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,10 @@ impl Transform {

/// Returns this [`Transform`] with a new rotation so that [`Transform::forward`]
/// points towards the `target` position and [`Transform::up`] points towards `up`.
///
/// It is not possible to construct a rotation when the resulting forward direction is parallel with `up`.
/// If this happens, an orthogonal vector to `up` will be used as the "right" direction to get a valid value.
/// It is also not possible when the target is at the same place as the transform. In this case, the Z axis will be used as the "forward" direction.
#[inline]
#[must_use]
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
Expand All @@ -129,6 +133,10 @@ impl Transform {

/// Returns this [`Transform`] with a new rotation so that [`Transform::forward`]
/// points in the given `direction` and [`Transform::up`] points towards `up`.
///
/// It is not possible to construct a rotation when `direction` is parallel with `up`.
/// If this happens, an orthogonal vector to `up` will be used as the "right" direction to get a valid value.
/// It is also not possible when the direction provided is zero. In this case, the Z axis will be used as the "forward" direction.
#[inline]
#[must_use]
pub fn looking_to(mut self, direction: Vec3, up: Vec3) -> Self {
Expand Down Expand Up @@ -325,17 +333,28 @@ impl Transform {

/// Rotates this [`Transform`] so that [`Transform::forward`] points towards the `target` position,
/// and [`Transform::up`] points towards `up`.
///
/// It is not possible to construct a rotation when the resulting forward direction is parallel with `up`.
/// If this happens, an orthogonal vector to `up` will be used as the "right" direction to get a valid value.
/// It is also not possible when the target is at the same place as the transform. In this case, the Z axis will be used as the "forward" 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`.
///
/// It is not possible to construct a rotation when `direction` is parallel with `up`.
/// If this happens, an orthogonal vector to `up` will be used as the "right" direction to get a valid value.
/// It is also not possible when the direction provided is zero. In this case, the Z axis will be used as the "forward" 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 right = up
.cross(forward)
.try_normalize()
.unwrap_or_else(|| up.any_orthogonal_vector());
mockersf marked this conversation as resolved.
Show resolved Hide resolved
let up = forward.cross(right);
self.rotation = Quat::from_mat3(&Mat3::from_cols(right, up, forward));
}
Expand Down