Repository: bitshifter/glam-rs
Pull request #38 (2019-12-20 19:20:18)

Added Mat4::perspective_lh_dx + minor consistency changes.


Patch:
diff --git a/src/f32/mat4.rs b/src/f32/mat4.rs
index d0258f2..1f8f1fa 100644
--- a/src/f32/mat4.rs
+++ b/src/f32/mat4.rs
@@ -562,7 +562,7 @@ impl Mat4 {
         aspect_ratio: f32,
         z_near: f32,
         z_far: f32,
-    ) -> Mat4 {
+    ) -> Self {
         let inv_length = 1.0 / (z_near - z_far);
         let f = 1.0 / (0.5 * fov_y_radians).tan();
         let a = f / aspect_ratio;
@@ -576,6 +576,26 @@ impl Mat4 {
         )
     }
 
+    /// Creates a left-handed perspective projection matrix with [0,1] depth range.
+    pub fn perspective_lh_dx(
+        fov_y_radians: f32,
+        aspect_ratio: f32,
+        z_near: f32,
+        z_far: f32,
+    ) -> Self {
+        glam_assert!(z_near > 0.0 && z_far > 0.0);
+        let (sin_fov, cos_fov) = scalar_sin_cos(0.5 * fov_y_radians);
+        let h = cos_fov / sin_fov;
+        let w = h / aspect_ratio;
+        let r = z_far / (z_far - z_near);
+        Mat4::from_cols(
+            Vec4::new(w, 0.0, 0.0, 0.0),
+            Vec4::new(0.0, h, 0.0, 0.0),
+            Vec4::new(0.0, 0.0, r, 1.0),
+            Vec4::new(0.0, 0.0, -r * z_near, 0.0),
+        )
+    }
+
     #[inline]
     #[deprecated(since = "0.8.2", note = "please use `Mat4::perspective_rh_gl` instead")]
     pub fn perspective_glu_rh(
@@ -583,13 +603,13 @@ impl Mat4 {
         aspect_ratio: f32,
         z_near: f32,
         z_far: f32,
-    ) -> Mat4 {
+    ) -> Self {
         Mat4::perspective_rh_gl(fov_y_radians, aspect_ratio, z_near, z_far)
     }
 
     /// Creates an infinite right-handed perspective projection matrix with
     /// [0,1] depth range.
-    pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Mat4 {
+    pub fn perspective_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self {
         let f = 1.0 / (0.5 * fov_y_radians).tan();
         Mat4::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
@@ -605,7 +625,7 @@ impl Mat4 {
         fov_y_radians: f32,
         aspect_ratio: f32,
         z_near: f32,
-    ) -> Mat4 {
+    ) -> Self {
         let f = 1.0 / (0.5 * fov_y_radians).tan();
         Mat4::from_cols(
             Vec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
@@ -626,7 +646,7 @@ impl Mat4 {
         top: f32,
         near: f32,
         far: f32,
-    ) -> Mat4 {
+    ) -> Self {
         let a = 2.0 / (right - left);
         let b = 2.0 / (top - bottom);
         let c = -2.0 / (far - near);


Test patch:
diff --git a/tests/mat4.rs b/tests/mat4.rs
index 664ea65..33f7b30 100644
--- a/tests/mat4.rs
+++ b/tests/mat4.rs
@@ -339,6 +339,19 @@ fn test_mat4_perspective_gl_rh() {
     assert_approx_eq!(Vec4::new(2.5, 5.0, -5.0, 5.0), projected);
 }
 
+#[test]
+fn test_mat4_perspective_dx_lh() {
+    let projection = Mat4::perspective_lh_dx(f32::to_radians(90.0), 2.0, 5.0, 15.0);
+
+    let original = Vec3::new(5.0, 5.0, 15.0);
+    let projected = projection * original.extend(1.0);
+    assert_approx_eq!(Vec4::new(2.5, 5.0, 15.0, 15.0), projected);
+
+    let original = Vec3::new(5.0, 5.0, 5.0);
+    let projected = projection * original.extend(1.0);
+    assert_approx_eq!(Vec4::new(2.5, 5.0, 0.0, 5.0), projected);
+}
+
 #[test]
 fn test_mat4_orthographic_gl_rh() {
     let projection = Mat4::orthographic_rh_gl(-10.0, 10.0, -5.0, 5.0, 0.0, -10.0);