1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use crate::core::traits::{
matrix::FloatMatrix4x4, quaternion::Quaternion, scalar::FloatEx, vector::*,
};
pub trait ProjectionMatrix<T: FloatEx, V4: FloatVector4<T> + Quaternion<T>>:
FloatMatrix4x4<T, V4>
{
fn perspective_rh_gl(fov_y_radians: T, aspect_ratio: T, z_near: T, z_far: T) -> Self {
let inv_length = T::ONE / (z_near - z_far);
let f = T::ONE / (T::HALF * fov_y_radians).tan();
let a = f / aspect_ratio;
let b = (z_near + z_far) * inv_length;
let c = (T::TWO * z_near * z_far) * inv_length;
Self::from_cols(
V4::new(a, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, f, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, b, -T::ONE),
V4::new(T::ZERO, T::ZERO, c, T::ZERO),
)
}
fn perspective_lh(fov_y_radians: T, aspect_ratio: T, z_near: T, z_far: T) -> Self {
glam_assert!(z_near > T::ZERO && z_far > T::ZERO);
let (sin_fov, cos_fov) = (T::HALF * fov_y_radians).sin_cos();
let h = cos_fov / sin_fov;
let w = h / aspect_ratio;
let r = z_far / (z_far - z_near);
Self::from_cols(
V4::new(w, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, h, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, r, T::ONE),
V4::new(T::ZERO, T::ZERO, -r * z_near, T::ZERO),
)
}
fn perspective_rh(fov_y_radians: T, aspect_ratio: T, z_near: T, z_far: T) -> Self {
glam_assert!(z_near > T::ZERO && z_far > T::ZERO);
let (sin_fov, cos_fov) = (T::HALF * fov_y_radians).sin_cos();
let h = cos_fov / sin_fov;
let w = h / aspect_ratio;
let r = z_far / (z_near - z_far);
Self::from_cols(
V4::new(w, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, h, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, r, -T::ONE),
V4::new(T::ZERO, T::ZERO, r * z_near, T::ZERO),
)
}
fn perspective_infinite_lh(fov_y_radians: T, aspect_ratio: T, z_near: T) -> Self {
glam_assert!(z_near > T::ZERO);
let (sin_fov, cos_fov) = (T::HALF * fov_y_radians).sin_cos();
let h = cos_fov / sin_fov;
let w = h / aspect_ratio;
Self::from_cols(
V4::new(w, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, h, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, T::ONE, T::ONE),
V4::new(T::ZERO, T::ZERO, -z_near, T::ZERO),
)
}
fn perspective_infinite_reverse_lh(fov_y_radians: T, aspect_ratio: T, z_near: T) -> Self {
glam_assert!(z_near > T::ZERO);
let (sin_fov, cos_fov) = (T::HALF * fov_y_radians).sin_cos();
let h = cos_fov / sin_fov;
let w = h / aspect_ratio;
Self::from_cols(
V4::new(w, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, h, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, T::ZERO, T::ONE),
V4::new(T::ZERO, T::ZERO, z_near, T::ZERO),
)
}
fn perspective_infinite_rh(fov_y_radians: T, aspect_ratio: T, z_near: T) -> Self {
let f = T::ONE / (T::HALF * fov_y_radians).tan();
Self::from_cols(
V4::new(f / aspect_ratio, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, f, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, -T::ONE, -T::ONE),
V4::new(T::ZERO, T::ZERO, -z_near, T::ZERO),
)
}
fn perspective_infinite_reverse_rh(fov_y_radians: T, aspect_ratio: T, z_near: T) -> Self {
let f = T::ONE / (T::HALF * fov_y_radians).tan();
Self::from_cols(
V4::new(f / aspect_ratio, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, f, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, T::ZERO, -T::ONE),
V4::new(T::ZERO, T::ZERO, z_near, T::ZERO),
)
}
fn orthographic_rh_gl(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Self {
let a = T::TWO / (right - left);
let b = T::TWO / (top - bottom);
let c = -T::TWO / (far - near);
let tx = -(right + left) / (right - left);
let ty = -(top + bottom) / (top - bottom);
let tz = -(far + near) / (far - near);
Self::from_cols(
V4::new(a, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, b, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, c, T::ZERO),
V4::new(tx, ty, tz, T::ONE),
)
}
fn orthographic_lh(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Self {
let rcp_width = T::ONE / (right - left);
let rcp_height = T::ONE / (top - bottom);
let r = T::ONE / (far - near);
Self::from_cols(
V4::new(rcp_width + rcp_width, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, rcp_height + rcp_height, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, r, T::ZERO),
V4::new(
-(left + right) * rcp_width,
-(top + bottom) * rcp_height,
-r * near,
T::ONE,
),
)
}
fn orthographic_rh(left: T, right: T, bottom: T, top: T, near: T, far: T) -> Self {
let rcp_width = T::ONE / (right - left);
let rcp_height = T::ONE / (top - bottom);
let r = T::ONE / (near - far);
Self::from_cols(
V4::new(rcp_width + rcp_width, T::ZERO, T::ZERO, T::ZERO),
V4::new(T::ZERO, rcp_height + rcp_height, T::ZERO, T::ZERO),
V4::new(T::ZERO, T::ZERO, r, T::ZERO),
V4::new(
-(left + right) * rcp_width,
-(top + bottom) * rcp_height,
r * near,
T::ONE,
),
)
}
}