Skip to content

Commit 5ece7ce

Browse files
mockersfalice-i-cecileLiamGallagher737
authored andcommitted
Fix look_to resulting in NaN rotations (bevyengine#7817)
Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: Liam Gallagher <[email protected]>
1 parent 223f543 commit 5ece7ce

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

crates/bevy_transform/src/components/transform.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ impl Transform {
120120

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

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

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

333348
/// Rotates this [`Transform`] so that [`Transform::forward`] points in the given `direction`
334349
/// and [`Transform::up`] points towards `up`.
350+
///
351+
/// In some cases it's not possible to construct a rotation. Another axis will be picked in those cases:
352+
/// * if `direction` is zero, `Vec3::Z` is used instead
353+
/// * if `up` is zero, `Vec3::Y` is used instead
354+
/// * if `direction` is parallel with `up`, an orthogonal vector is used as the "right" direction
335355
#[inline]
336356
pub fn look_to(&mut self, direction: Vec3, up: Vec3) {
337-
let forward = -direction.normalize();
338-
let right = up.cross(forward).normalize();
357+
let forward = -direction.try_normalize().unwrap_or(Vec3::Z);
358+
let up = up.try_normalize().unwrap_or(Vec3::Y);
359+
let right = up
360+
.cross(forward)
361+
.try_normalize()
362+
.unwrap_or_else(|| up.any_orthonormal_vector());
339363
let up = forward.cross(right);
340364
self.rotation = Quat::from_mat3(&Mat3::from_cols(right, up, forward));
341365
}

0 commit comments

Comments
 (0)