From 767ffb69e477645bb6b569be3e8235df2546f5c5 Mon Sep 17 00:00:00 2001 From: Cameron Hart Date: Mon, 19 Aug 2024 23:54:06 +1200 Subject: [PATCH] Add look_at and look_to methods to Quat and Mat3. --- codegen/templates/mat.rs.tera | 97 +++++++++++++++++++++++++++++----- codegen/templates/quat.rs.tera | 63 ++++++++++++++++++++++ src/f32/coresimd/mat3a.rs | 63 ++++++++++++++++++++++ src/f32/coresimd/mat4.rs | 34 +++++++----- src/f32/coresimd/quat.rs | 63 ++++++++++++++++++++++ src/f32/mat3.rs | 63 ++++++++++++++++++++++ src/f32/neon/mat3a.rs | 63 ++++++++++++++++++++++ src/f32/neon/mat4.rs | 34 +++++++----- src/f32/neon/quat.rs | 63 ++++++++++++++++++++++ src/f32/scalar/mat3a.rs | 63 ++++++++++++++++++++++ src/f32/scalar/mat4.rs | 34 +++++++----- src/f32/scalar/quat.rs | 63 ++++++++++++++++++++++ src/f32/sse2/mat3a.rs | 63 ++++++++++++++++++++++ src/f32/sse2/mat4.rs | 34 +++++++----- src/f32/sse2/quat.rs | 63 ++++++++++++++++++++++ src/f32/wasm32/mat3a.rs | 63 ++++++++++++++++++++++ src/f32/wasm32/mat4.rs | 34 +++++++----- src/f32/wasm32/quat.rs | 63 ++++++++++++++++++++++ src/f64/dmat3.rs | 63 ++++++++++++++++++++++ src/f64/dmat4.rs | 34 +++++++----- src/f64/dquat.rs | 63 ++++++++++++++++++++++ tests/mat4.rs | 8 +-- 22 files changed, 1104 insertions(+), 87 deletions(-) diff --git a/codegen/templates/mat.rs.tera b/codegen/templates/mat.rs.tera index fdb0f6e1..b3af67be 100644 --- a/codegen/templates/mat.rs.tera +++ b/codegen/templates/mat.rs.tera @@ -1660,25 +1660,98 @@ impl {{ self_t }} { {{ mat2_t }}::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs } -{% elif dim == 4 %} - /// Creates a left-handed view matrix using a camera position, an up direction, and a facing + /// Creates a left-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a right-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_cols( + {{ col_t }}::new(s.x, u.x, -f.x), + {{ col_t }}::new(s.y, u.y, -f.y), + {{ col_t }}::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + +{% elif dim == 4 %} + /// Creates a left-handed view matrix using a camera position, a facing direction and an up + /// direction + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: {{ vec3_t }}, dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_rh(eye, -dir, up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a facing + /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: {{ vec3_t }}, dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { - let f = dir.normalize(); + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); @@ -1690,8 +1763,9 @@ impl {{ self_t }} { ) } - /// Creates a left-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a left-handed view matrix using a camera position, a focal points and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics @@ -1700,12 +1774,12 @@ impl {{ self_t }} { #[inline] #[must_use] pub fn look_at_lh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_lh(eye, center.sub(eye), up) + Self::look_to_lh(eye, center.sub(eye).normalize(), up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a right-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics @@ -1713,8 +1787,7 @@ impl {{ self_t }} { /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_rh(eye, center.sub(eye), up) + Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with [-1,1] depth range. diff --git a/codegen/templates/quat.rs.tera b/codegen/templates/quat.rs.tera index 47221e67..0374ea49 100644 --- a/codegen/templates/quat.rs.tera +++ b/codegen/templates/quat.rs.tera @@ -518,6 +518,69 @@ impl {{ self_t }} { } } + /// Creates a quaterion rotation from a facing direction and an up direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a quaterion rotation from facing direction and an up direction. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_rotation_axes( + {{ vec3_t }}::new(s.x, u.x, -f.x), + {{ vec3_t }}::new(s.y, u.y, -f.y), + {{ vec3_t }}::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, an up direction, and a focal + /// point. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Returns the rotation axis (normalized) and angle (in radians) of `self`. #[inline] #[must_use] diff --git a/src/f32/coresimd/mat3a.rs b/src/f32/coresimd/mat3a.rs index 6e6b29ea..f0d7a564 100644 --- a/src/f32/coresimd/mat3a.rs +++ b/src/f32/coresimd/mat3a.rs @@ -619,6 +619,69 @@ impl Mat3A { Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs } + /// Creates a left-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a right-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_cols( + Vec3A::new(s.x, u.x, -f.x), + Vec3A::new(s.y, u.y, -f.y), + Vec3A::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Transforms a 3D vector. #[inline] #[must_use] diff --git a/src/f32/coresimd/mat4.rs b/src/f32/coresimd/mat4.rs index 2f106d77..d05dc6e9 100644 --- a/src/f32/coresimd/mat4.rs +++ b/src/f32/coresimd/mat4.rs @@ -793,24 +793,34 @@ impl Mat4 { } } - /// Creates a left-handed view matrix using a camera position, an up direction, and a facing - /// direction. + /// Creates a left-handed view matrix using a camera position, a facing direction and an up + /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a facing + /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { - let f = dir.normalize(); + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); @@ -822,8 +832,9 @@ impl Mat4 { ) } - /// Creates a left-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a left-handed view matrix using a camera position, a focal points and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics @@ -832,12 +843,12 @@ impl Mat4 { #[inline] #[must_use] pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_lh(eye, center.sub(eye), up) + Self::look_to_lh(eye, center.sub(eye).normalize(), up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a right-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics @@ -845,8 +856,7 @@ impl Mat4 { /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_rh(eye, center.sub(eye), up) + Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with [-1,1] depth range. diff --git a/src/f32/coresimd/quat.rs b/src/f32/coresimd/quat.rs index ffcafe74..ab276b8a 100644 --- a/src/f32/coresimd/quat.rs +++ b/src/f32/coresimd/quat.rs @@ -389,6 +389,69 @@ impl Quat { } } + /// Creates a quaterion rotation from a facing direction and an up direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a quaterion rotation from facing direction and an up direction. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_rotation_axes( + Vec3::new(s.x, u.x, -f.x), + Vec3::new(s.y, u.y, -f.y), + Vec3::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, an up direction, and a focal + /// point. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Returns the rotation axis (normalized) and angle (in radians) of `self`. #[inline] #[must_use] diff --git a/src/f32/mat3.rs b/src/f32/mat3.rs index ba22c329..e2921fe9 100644 --- a/src/f32/mat3.rs +++ b/src/f32/mat3.rs @@ -549,6 +549,69 @@ impl Mat3 { Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs } + /// Creates a left-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a right-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_cols( + Vec3::new(s.x, u.x, -f.x), + Vec3::new(s.y, u.y, -f.y), + Vec3::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Transforms a 3D vector. #[inline] #[must_use] diff --git a/src/f32/neon/mat3a.rs b/src/f32/neon/mat3a.rs index 3e2448db..52473077 100644 --- a/src/f32/neon/mat3a.rs +++ b/src/f32/neon/mat3a.rs @@ -630,6 +630,69 @@ impl Mat3A { Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs } + /// Creates a left-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a right-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_cols( + Vec3A::new(s.x, u.x, -f.x), + Vec3A::new(s.y, u.y, -f.y), + Vec3A::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Transforms a 3D vector. #[inline] #[must_use] diff --git a/src/f32/neon/mat4.rs b/src/f32/neon/mat4.rs index 0c6dd74d..4071b9f4 100644 --- a/src/f32/neon/mat4.rs +++ b/src/f32/neon/mat4.rs @@ -798,24 +798,34 @@ impl Mat4 { } } - /// Creates a left-handed view matrix using a camera position, an up direction, and a facing - /// direction. + /// Creates a left-handed view matrix using a camera position, a facing direction and an up + /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a facing + /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { - let f = dir.normalize(); + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); @@ -827,8 +837,9 @@ impl Mat4 { ) } - /// Creates a left-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a left-handed view matrix using a camera position, a focal points and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics @@ -837,12 +848,12 @@ impl Mat4 { #[inline] #[must_use] pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_lh(eye, center.sub(eye), up) + Self::look_to_lh(eye, center.sub(eye).normalize(), up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a right-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics @@ -850,8 +861,7 @@ impl Mat4 { /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_rh(eye, center.sub(eye), up) + Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with [-1,1] depth range. diff --git a/src/f32/neon/quat.rs b/src/f32/neon/quat.rs index 414aa7ab..f0b2b17c 100644 --- a/src/f32/neon/quat.rs +++ b/src/f32/neon/quat.rs @@ -394,6 +394,69 @@ impl Quat { } } + /// Creates a quaterion rotation from a facing direction and an up direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a quaterion rotation from facing direction and an up direction. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_rotation_axes( + Vec3::new(s.x, u.x, -f.x), + Vec3::new(s.y, u.y, -f.y), + Vec3::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, an up direction, and a focal + /// point. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Returns the rotation axis (normalized) and angle (in radians) of `self`. #[inline] #[must_use] diff --git a/src/f32/scalar/mat3a.rs b/src/f32/scalar/mat3a.rs index 7bcb7679..f322fda9 100644 --- a/src/f32/scalar/mat3a.rs +++ b/src/f32/scalar/mat3a.rs @@ -617,6 +617,69 @@ impl Mat3A { Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs } + /// Creates a left-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a right-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_cols( + Vec3A::new(s.x, u.x, -f.x), + Vec3A::new(s.y, u.y, -f.y), + Vec3A::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Transforms a 3D vector. #[inline] #[must_use] diff --git a/src/f32/scalar/mat4.rs b/src/f32/scalar/mat4.rs index beec9b84..a4652539 100644 --- a/src/f32/scalar/mat4.rs +++ b/src/f32/scalar/mat4.rs @@ -715,24 +715,34 @@ impl Mat4 { inverse.mul(rcp_det) } - /// Creates a left-handed view matrix using a camera position, an up direction, and a facing - /// direction. + /// Creates a left-handed view matrix using a camera position, a facing direction and an up + /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a facing + /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { - let f = dir.normalize(); + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); @@ -744,8 +754,9 @@ impl Mat4 { ) } - /// Creates a left-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a left-handed view matrix using a camera position, a focal points and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics @@ -754,12 +765,12 @@ impl Mat4 { #[inline] #[must_use] pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_lh(eye, center.sub(eye), up) + Self::look_to_lh(eye, center.sub(eye).normalize(), up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a right-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics @@ -767,8 +778,7 @@ impl Mat4 { /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_rh(eye, center.sub(eye), up) + Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with [-1,1] depth range. diff --git a/src/f32/scalar/quat.rs b/src/f32/scalar/quat.rs index cadeca78..f19b1f92 100644 --- a/src/f32/scalar/quat.rs +++ b/src/f32/scalar/quat.rs @@ -397,6 +397,69 @@ impl Quat { } } + /// Creates a quaterion rotation from a facing direction and an up direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a quaterion rotation from facing direction and an up direction. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_rotation_axes( + Vec3::new(s.x, u.x, -f.x), + Vec3::new(s.y, u.y, -f.y), + Vec3::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, an up direction, and a focal + /// point. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Returns the rotation axis (normalized) and angle (in radians) of `self`. #[inline] #[must_use] diff --git a/src/f32/sse2/mat3a.rs b/src/f32/sse2/mat3a.rs index c6e6ad2f..5245845c 100644 --- a/src/f32/sse2/mat3a.rs +++ b/src/f32/sse2/mat3a.rs @@ -624,6 +624,69 @@ impl Mat3A { Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs } + /// Creates a left-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a right-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_cols( + Vec3A::new(s.x, u.x, -f.x), + Vec3A::new(s.y, u.y, -f.y), + Vec3A::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Transforms a 3D vector. #[inline] #[must_use] diff --git a/src/f32/sse2/mat4.rs b/src/f32/sse2/mat4.rs index 81900f83..6d88452c 100644 --- a/src/f32/sse2/mat4.rs +++ b/src/f32/sse2/mat4.rs @@ -802,24 +802,34 @@ impl Mat4 { } } - /// Creates a left-handed view matrix using a camera position, an up direction, and a facing - /// direction. + /// Creates a left-handed view matrix using a camera position, a facing direction and an up + /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a facing + /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { - let f = dir.normalize(); + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); @@ -831,8 +841,9 @@ impl Mat4 { ) } - /// Creates a left-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a left-handed view matrix using a camera position, a focal points and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics @@ -841,12 +852,12 @@ impl Mat4 { #[inline] #[must_use] pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_lh(eye, center.sub(eye), up) + Self::look_to_lh(eye, center.sub(eye).normalize(), up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a right-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics @@ -854,8 +865,7 @@ impl Mat4 { /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_rh(eye, center.sub(eye), up) + Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with [-1,1] depth range. diff --git a/src/f32/sse2/quat.rs b/src/f32/sse2/quat.rs index 181e3f43..e661cfb2 100644 --- a/src/f32/sse2/quat.rs +++ b/src/f32/sse2/quat.rs @@ -397,6 +397,69 @@ impl Quat { } } + /// Creates a quaterion rotation from a facing direction and an up direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a quaterion rotation from facing direction and an up direction. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_rotation_axes( + Vec3::new(s.x, u.x, -f.x), + Vec3::new(s.y, u.y, -f.y), + Vec3::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, an up direction, and a focal + /// point. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Returns the rotation axis (normalized) and angle (in radians) of `self`. #[inline] #[must_use] diff --git a/src/f32/wasm32/mat3a.rs b/src/f32/wasm32/mat3a.rs index bbaffd62..5be04137 100644 --- a/src/f32/wasm32/mat3a.rs +++ b/src/f32/wasm32/mat3a.rs @@ -619,6 +619,69 @@ impl Mat3A { Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs } + /// Creates a left-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a right-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_cols( + Vec3A::new(s.x, u.x, -f.x), + Vec3A::new(s.y, u.y, -f.y), + Vec3A::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Transforms a 3D vector. #[inline] #[must_use] diff --git a/src/f32/wasm32/mat4.rs b/src/f32/wasm32/mat4.rs index 290dda35..9a2757ff 100644 --- a/src/f32/wasm32/mat4.rs +++ b/src/f32/wasm32/mat4.rs @@ -793,24 +793,34 @@ impl Mat4 { } } - /// Creates a left-handed view matrix using a camera position, an up direction, and a facing - /// direction. + /// Creates a left-handed view matrix using a camera position, a facing direction and an up + /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a facing + /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { - let f = dir.normalize(); + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); @@ -822,8 +832,9 @@ impl Mat4 { ) } - /// Creates a left-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a left-handed view matrix using a camera position, a focal points and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics @@ -832,12 +843,12 @@ impl Mat4 { #[inline] #[must_use] pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_lh(eye, center.sub(eye), up) + Self::look_to_lh(eye, center.sub(eye).normalize(), up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a right-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics @@ -845,8 +856,7 @@ impl Mat4 { /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_rh(eye, center.sub(eye), up) + Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with [-1,1] depth range. diff --git a/src/f32/wasm32/quat.rs b/src/f32/wasm32/quat.rs index 0055c012..eb5d82d8 100644 --- a/src/f32/wasm32/quat.rs +++ b/src/f32/wasm32/quat.rs @@ -389,6 +389,69 @@ impl Quat { } } + /// Creates a quaterion rotation from a facing direction and an up direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a quaterion rotation from facing direction and an up direction. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_rotation_axes( + Vec3::new(s.x, u.x, -f.x), + Vec3::new(s.y, u.y, -f.y), + Vec3::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, an up direction, and a focal + /// point. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Returns the rotation axis (normalized) and angle (in radians) of `self`. #[inline] #[must_use] diff --git a/src/f64/dmat3.rs b/src/f64/dmat3.rs index 4f84b1a5..dfddd422 100644 --- a/src/f64/dmat3.rs +++ b/src/f64/dmat3.rs @@ -553,6 +553,69 @@ impl DMat3 { DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs } + /// Creates a left-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: DVec3, up: DVec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a right-handed view matrix using a facing direction and an up direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: DVec3, up: DVec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_cols( + DVec3::new(s.x, u.x, -f.x), + DVec3::new(s.y, u.y, -f.y), + DVec3::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, a focal point and an up + /// direction. + /// + /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Transforms a 3D vector. #[inline] #[must_use] diff --git a/src/f64/dmat4.rs b/src/f64/dmat4.rs index 82c0071f..e6e2302d 100644 --- a/src/f64/dmat4.rs +++ b/src/f64/dmat4.rs @@ -697,24 +697,34 @@ impl DMat4 { inverse.mul(rcp_det) } - /// Creates a left-handed view matrix using a camera position, an up direction, and a facing - /// direction. + /// Creates a left-handed view matrix using a camera position, a facing direction and an up + /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self { Self::look_to_rh(eye, -dir, up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a facing + /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self { - let f = dir.normalize(); + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); @@ -726,8 +736,9 @@ impl DMat4 { ) } - /// Creates a left-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a left-handed view matrix using a camera position, a focal points and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics @@ -736,12 +747,12 @@ impl DMat4 { #[inline] #[must_use] pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_lh(eye, center.sub(eye), up) + Self::look_to_lh(eye, center.sub(eye).normalize(), up) } - /// Creates a right-handed view matrix using a camera position, an up direction, and a focal - /// point. + /// Creates a right-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics @@ -749,8 +760,7 @@ impl DMat4 { /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self { - glam_assert!(up.is_normalized()); - Self::look_to_rh(eye, center.sub(eye), up) + Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with [-1,1] depth range. diff --git a/src/f64/dquat.rs b/src/f64/dquat.rs index a5f48192..5072d5a4 100644 --- a/src/f64/dquat.rs +++ b/src/f64/dquat.rs @@ -379,6 +379,69 @@ impl DQuat { } } + /// Creates a quaterion rotation from a facing direction and an up direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_lh(dir: DVec3, up: DVec3) -> Self { + Self::look_to_rh(-dir, up) + } + + /// Creates a quaterion rotation from facing direction and an up direction. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_to_rh(dir: DVec3, up: DVec3) -> Self { + glam_assert!(dir.is_normalized()); + glam_assert!(up.is_normalized()); + let f = dir; + let s = f.cross(up).normalize(); + let u = s.cross(f); + + Self::from_rotation_axes( + DVec3::new(s.x, u.x, -f.x), + DVec3::new(s.y, u.y, -f.y), + DVec3::new(s.z, u.z, -f.z), + ) + } + + /// Creates a left-handed view matrix using a camera position, a focal point, and an up + /// direction. + /// + /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + #[must_use] + pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self { + Self::look_to_lh(center.sub(eye).normalize(), up) + } + + /// Creates a right-handed view matrix using a camera position, an up direction, and a focal + /// point. + /// + /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. + /// + /// # Panics + /// + /// Will panic if `up` is not normalized when `glam_assert` is enabled. + #[inline] + pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self { + Self::look_to_rh(center.sub(eye).normalize(), up) + } + /// Returns the rotation axis (normalized) and angle (in radians) of `self`. #[inline] #[must_use] diff --git a/tests/mat4.rs b/tests/mat4.rs index d9036331..7ee75d73 100644 --- a/tests/mat4.rs +++ b/tests/mat4.rs @@ -446,14 +446,16 @@ macro_rules! impl_mat4_tests { assert_approx_eq!(lh.transform_point3(point), $vec3::new(0.0, 1.0, 5.0)); assert_approx_eq!(rh.transform_point3(point), $vec3::new(0.0, 1.0, -5.0)); - let dir = center - eye; + let dir = (center - eye).normalize(); let lh = $mat4::look_to_lh(eye, dir, up); let rh = $mat4::look_to_rh(eye, dir, up); assert_approx_eq!(lh.transform_point3(point), $vec3::new(0.0, 1.0, 5.0)); assert_approx_eq!(rh.transform_point3(point), $vec3::new(0.0, 1.0, -5.0)); - should_glam_assert!({ $mat4::look_at_lh($vec3::ONE, $vec3::ZERO, $vec3::ZERO) }); - should_glam_assert!({ $mat4::look_at_rh($vec3::ONE, $vec3::ZERO, $vec3::ZERO) }); + should_glam_assert!({ $mat4::look_to_lh($vec3::ONE, $vec3::ONE, $vec3::ZERO) }); + should_glam_assert!({ $mat4::look_to_lh($vec3::ONE, $vec3::ZERO, $vec3::ONE) }); + should_glam_assert!({ $mat4::look_to_rh($vec3::ONE, $vec3::ONE, $vec3::ZERO) }); + should_glam_assert!({ $mat4::look_to_rh($vec3::ONE, $vec3::ZERO, $vec3::ONE) }); }); glam_test!(test_mat4_perspective_gl_rh, {