From 84cf6bd79e692512ebf5129135e94760d4670856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 25 Feb 2023 01:22:54 +0100 Subject: [PATCH 1/4] orthogonal! --- .../bevy_transform/src/components/transform.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index a7615cb9b9387..1e0d81d3d12e5 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -120,6 +120,9 @@ 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. #[inline] #[must_use] pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self { @@ -129,6 +132,9 @@ 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. #[inline] #[must_use] pub fn looking_to(mut self, direction: Vec3, up: Vec3) -> Self { @@ -325,6 +331,9 @@ 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. #[inline] pub fn look_at(&mut self, target: Vec3, up: Vec3) { self.look_to(target - self.translation, up); @@ -332,10 +341,16 @@ impl Transform { /// 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. #[inline] pub fn look_to(&mut self, direction: Vec3, up: Vec3) { let forward = -direction.normalize(); - let right = up.cross(forward).normalize(); + let right = up + .cross(forward) + .try_normalize() + .unwrap_or_else(|| up.any_orthogonal_vector()); let up = forward.cross(right); self.rotation = Quat::from_mat3(&Mat3::from_cols(right, up, forward)); } From 37ce9ed78509542afa09f661535c31e784f1a40c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 25 Feb 2023 13:14:49 +0100 Subject: [PATCH 2/4] also direction defaults to Z --- crates/bevy_transform/src/components/transform.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index 1e0d81d3d12e5..1f184d3824204 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -123,6 +123,7 @@ impl Transform { /// /// 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 { @@ -135,6 +136,7 @@ impl Transform { /// /// 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 { @@ -334,6 +336,7 @@ impl Transform { /// /// 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); @@ -344,9 +347,10 @@ impl Transform { /// /// 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 forward = -direction.try_normalize().unwrap_or(Vec3::Z); let right = up .cross(forward) .try_normalize() From 1e855ca4272807c12931844f1000a2de0884c0cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sat, 25 Feb 2023 15:46:44 +0100 Subject: [PATCH 3/4] normalize up and replace with Y if it fails --- .../src/components/transform.rs | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index 1f184d3824204..841b2ec5465c6 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -121,9 +121,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. + /// 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] #[must_use] pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self { @@ -134,9 +135,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. + /// 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 { @@ -334,9 +336,10 @@ 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. + /// 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); @@ -345,16 +348,18 @@ impl Transform { /// 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. + /// 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.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_orthogonal_vector()); + .unwrap_or_else(|| up.any_orthonormal_vector()); let up = forward.cross(right); self.rotation = Quat::from_mat3(&Mat3::from_cols(right, up, forward)); } From be4b94a695d75c07357aa0c5c26e49bef9f9ea89 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Wed, 15 Mar 2023 12:54:08 -0400 Subject: [PATCH 4/4] Fix typo Co-authored-by: Liam Gallagher --- crates/bevy_transform/src/components/transform.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index 841b2ec5465c6..1e122ae08f2f4 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -122,7 +122,7 @@ impl Transform { /// 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 `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]