1#[derive(Debug, Clone, Copy, PartialEq)]
11pub struct Vec3f {
12 vx: f32,
13 vy: f32,
14 vz: f32,
15}
16
17impl Vec3f {
18 #[must_use]
20 pub fn new(x: f32, y: f32, z: f32) -> Self {
21 Self { vx: x, vy: y, vz: z }
22 }
23
24 #[must_use]
26 pub fn zero() -> Self {
27 Self { vx: 0.0, vy: 0.0, vz: 0.0 }
28 }
29
30 #[must_use]
32 pub fn unit_y() -> Self {
33 Self { vx: 0.0, vy: 1.0, vz: 0.0 }
34 }
35
36 #[must_use]
38 pub fn x(self) -> f32 {
39 self.vx
40 }
41
42 #[must_use]
44 pub fn y(self) -> f32 {
45 self.vy
46 }
47
48 #[must_use]
50 pub fn z(self) -> f32 {
51 self.vz
52 }
53
54 #[must_use]
56 pub fn dot(self, rhs: Self) -> f32 {
57 self.vx * rhs.vx + self.vy * rhs.vy + self.vz * rhs.vz
58 }
59
60 #[must_use]
62 pub fn cross(self, rhs: Self) -> Self {
63 Self {
64 vx: self.vy * rhs.vz - self.vz * rhs.vy,
65 vy: self.vz * rhs.vx - self.vx * rhs.vz,
66 vz: self.vx * rhs.vy - self.vy * rhs.vx,
67 }
68 }
69
70 #[must_use]
72 pub fn length_squared(self) -> f32 {
73 self.dot(self)
74 }
75
76 #[must_use]
78 pub fn length(self) -> f32 {
79 self.length_squared().sqrt()
80 }
81
82 #[must_use]
84 pub fn normalized(self) -> Self {
85 let len = self.length();
86 if len < 1e-10 {
87 Self { vx: 0.0, vy: 0.0, vz: 1.0 }
88 } else {
89 self.scale(1.0 / len)
90 }
91 }
92
93 #[must_use]
95 pub fn scale(self, s: f32) -> Self {
96 Self {
97 vx: self.vx * s,
98 vy: self.vy * s,
99 vz: self.vz * s,
100 }
101 }
102}
103
104impl std::ops::Add for Vec3f {
105 type Output = Self;
106 fn add(self, rhs: Self) -> Self {
107 Self {
108 vx: self.vx + rhs.vx,
109 vy: self.vy + rhs.vy,
110 vz: self.vz + rhs.vz,
111 }
112 }
113}
114
115impl std::ops::Sub for Vec3f {
116 type Output = Self;
117 fn sub(self, rhs: Self) -> Self {
118 Self {
119 vx: self.vx - rhs.vx,
120 vy: self.vy - rhs.vy,
121 vz: self.vz - rhs.vz,
122 }
123 }
124}
125
126impl std::ops::Neg for Vec3f {
127 type Output = Self;
128 fn neg(self) -> Self {
129 Self {
130 vx: -self.vx,
131 vy: -self.vy,
132 vz: -self.vz,
133 }
134 }
135}
136
137#[derive(Debug, Clone, Copy, PartialEq)]
141pub struct Vec4f {
142 vx: f32,
143 vy: f32,
144 vz: f32,
145 vw: f32,
146}
147
148impl Vec4f {
149 #[must_use]
151 pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
152 Self { vx: x, vy: y, vz: z, vw: w }
153 }
154
155 #[must_use]
157 pub fn x(self) -> f32 {
158 self.vx
159 }
160
161 #[must_use]
163 pub fn y(self) -> f32 {
164 self.vy
165 }
166
167 #[must_use]
169 pub fn z(self) -> f32 {
170 self.vz
171 }
172
173 #[must_use]
175 pub fn w(self) -> f32 {
176 self.vw
177 }
178
179 #[must_use]
181 pub fn dot(self, rhs: Self) -> f32 {
182 self.vx * rhs.vx + self.vy * rhs.vy + self.vz * rhs.vz + self.vw * rhs.vw
183 }
184}
185
186#[derive(Debug, Clone, Copy, PartialEq)]
190pub struct Mat4 {
191 c0: Vec4f,
192 c1: Vec4f,
193 c2: Vec4f,
194 c3: Vec4f,
195}
196
197impl Mat4 {
198 #[must_use]
200 pub fn from_columns(c0: Vec4f, c1: Vec4f, c2: Vec4f, c3: Vec4f) -> Self {
201 Self { c0, c1, c2, c3 }
202 }
203
204 #[must_use]
206 pub fn col0(self) -> Vec4f {
207 self.c0
208 }
209
210 #[must_use]
212 pub fn col1(self) -> Vec4f {
213 self.c1
214 }
215
216 #[must_use]
218 pub fn col2(self) -> Vec4f {
219 self.c2
220 }
221
222 #[must_use]
224 pub fn col3(self) -> Vec4f {
225 self.c3
226 }
227
228 #[must_use]
230 fn row(self, pick: fn(Vec4f) -> f32) -> Vec4f {
231 Vec4f::new(
232 pick(self.c0),
233 pick(self.c1),
234 pick(self.c2),
235 pick(self.c3),
236 )
237 }
238
239 #[must_use]
241 pub fn mul_mat(self, rhs: Self) -> Self {
242 let row_x = self.row(Vec4f::x);
243 let row_y = self.row(Vec4f::y);
244 let row_z = self.row(Vec4f::z);
245 let row_w = self.row(Vec4f::w);
246
247 let mul_col = |col: Vec4f| -> Vec4f {
248 Vec4f::new(
249 row_x.dot(col),
250 row_y.dot(col),
251 row_z.dot(col),
252 row_w.dot(col),
253 )
254 };
255
256 Self {
257 c0: mul_col(rhs.c0),
258 c1: mul_col(rhs.c1),
259 c2: mul_col(rhs.c2),
260 c3: mul_col(rhs.c3),
261 }
262 }
263
264 #[must_use]
266 pub fn as_array(self) -> [f32; 16] {
267 [
268 self.c0.vx, self.c0.vy, self.c0.vz, self.c0.vw,
269 self.c1.vx, self.c1.vy, self.c1.vz, self.c1.vw,
270 self.c2.vx, self.c2.vy, self.c2.vz, self.c2.vw,
271 self.c3.vx, self.c3.vy, self.c3.vz, self.c3.vw,
272 ]
273 }
274
275 #[must_use]
277 pub fn perspective(fov_y: f32, aspect: f32, near: f32, far: f32) -> Self {
278 let f = 1.0 / (fov_y / 2.0).tan();
279 let nf = 1.0 / (near - far);
280 Self {
281 c0: Vec4f::new(f / aspect, 0.0, 0.0, 0.0),
282 c1: Vec4f::new(0.0, f, 0.0, 0.0),
283 c2: Vec4f::new(0.0, 0.0, (far + near) * nf, -1.0),
284 c3: Vec4f::new(0.0, 0.0, 2.0 * far * near * nf, 0.0),
285 }
286 }
287
288 #[must_use]
290 pub fn look_at(eye: Vec3f, target: Vec3f, up: Vec3f) -> Self {
291 let fwd = (target - eye).normalized();
292 let right = fwd.cross(up).normalized();
293 let cam_up = right.cross(fwd);
294
295 Self {
296 c0: Vec4f::new(right.x(), cam_up.x(), -fwd.x(), 0.0),
297 c1: Vec4f::new(right.y(), cam_up.y(), -fwd.y(), 0.0),
298 c2: Vec4f::new(right.z(), cam_up.z(), -fwd.z(), 0.0),
299 c3: Vec4f::new(
300 -right.dot(eye),
301 -cam_up.dot(eye),
302 fwd.dot(eye),
303 1.0,
304 ),
305 }
306 }
307}
308
309impl std::ops::Mul for Mat4 {
310 type Output = Self;
311 fn mul(self, rhs: Self) -> Self {
312 self.mul_mat(rhs)
313 }
314}