1use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign};
2
3use crate::{GlEnum, GlAttrib, GlUniform, GlslType, impl_glsl};
4
5macro_rules! impl_vec {
6 ($Name: ident, $($field: ident),+; $size: expr) => {
7 #[repr(C)]
8 #[derive(Default, Debug, Clone, Copy, PartialEq)]
9 pub struct $Name<T> { $(pub $field: T),+ }
10
11 impl<T> $Name<T> {
12 pub fn new($($field: T),+) -> $Name<T> {
13 $Name { $($field: $field),+ }
14 }
15
16 pub fn as_array(&self) -> [&T; $size] {
23 [$(&self.$field),+]
24 }
25
26 pub fn stride() -> usize { $size * std::mem::size_of::<T>() }
35 }
36
37 impl<T: Add> Add<$Name<T> > for $Name<T>
38 where T: Add<Output = T>
39 {
40 type Output = $Name<T>;
41 fn add(self, rhs: $Name<T>) -> Self::Output {
42 $Name::new($(self.$field + rhs.$field),+)
43 }
44 }
45
46 impl<T: Sub> Sub<$Name<T> > for $Name<T>
47 where T: Sub<Output = T>
48 {
49 type Output = $Name<T>;
50 fn sub(self, rhs: $Name<T>) -> Self::Output {
51 $Name::new($(self.$field - rhs.$field),+)
52 }
53 }
54
55 impl<T: AddAssign> AddAssign<$Name<T> > for $Name<T> {
56 fn add_assign(&mut self, rhs: Self) {
57 $(self.$field += rhs.$field);+
58 }
59 }
60
61 impl<T: SubAssign> SubAssign<$Name<T> > for $Name<T> {
62 fn sub_assign(&mut self, rhs: Self) {
63 $(self.$field -= rhs.$field);+
64 }
65 }
66
67 impl<T: GlEnum> GlEnum for $Name<T> {
68 fn gl_enum() -> u32 { T::gl_enum() }
69
70 fn to_enum(&self) -> u32 { T::gl_enum() }
71 }
72
73 impl<T: GlEnum> GlAttrib for $Name<T> {
74 fn size() -> u32 { $size }
75 }
76
77 impl<T: GlUniform> GlUniform for $Name<T> {
78 fn uniform(location: i32, val: &Self) {
79 Self::uniformv(location, $size, val as *const Self);
80 }
81
82 fn uniformv(location: i32, count: i32, ptr: *const Self) {
83 T::uniformv(location, count * $size, ptr as *const T);
84 }
85
86 fn send_uniform(&self, location: i32) {
87 let ptr: *const T = &self.x;
88 T::uniformv(location, $size, ptr);
89 }
90 }
91 }
92}
93
94pub trait UniformType {
95 fn get_type(&self) -> u32;
96}
97
98impl_vec!(Vector2, x, y; 2);
99impl_vec!(Vector3, x, y, z; 3);
100impl_vec!(Vector4, x, y, z, w; 4);
101
102pub type BVec2 = Vector2<bool>;
103pub type IVec2 = Vector2<i32>;
104pub type UVec2 = Vector2<u32>;
105pub type Vec2 = Vector2<f32>;
106
107impl_glsl!(BVec2, "bvec2");
108impl_glsl!(IVec2, "ivec2");
109impl_glsl!(UVec2, "uvec2");
110impl_glsl!(Vec2, "vec2");
111
112pub type BVec3 = Vector3<bool>;
113pub type IVec3 = Vector3<i32>;
114pub type UVec3 = Vector3<u32>;
115pub type Vec3 = Vector3<f32>;
116
117impl_glsl!(BVec3, "bvec3");
118impl_glsl!(IVec3, "ivec3");
119impl_glsl!(UVec3, "uvec3");
120impl_glsl!(Vec3, "vec3");
121
122pub type BVec4 = Vector4<bool>;
123pub type IVec4 = Vector4<i32>;
124pub type UVec4 = Vector4<u32>;
125pub type Vec4 = Vector4<f32>;
126
127impl_glsl!(BVec4, "bvec4");
128impl_glsl!(IVec4, "ivec4");
129impl_glsl!(UVec4, "uvec4");
130impl_glsl!(Vec4, "vec4");
131
132impl Vec3 {
133 pub fn zero() -> Self {
134 Self { x: 0.0, y: 0.0, z: 0.0 }
135 }
136
137 pub fn up() -> Self { Self { x: 0.0, y: 1.0, z: 0.0 } }
138 pub fn down() -> Self { Self { x: 0.0, y: -1.0, z: 0.0 } }
139 pub fn front() -> Self { Self { x: 0.0, y: 0.0, z: -1.0 } }
140 pub fn back() -> Self { Self { x: 0.0, y: 0.0, z: 1.0 } }
141
142 pub fn from_array(data: [f32; 4]) -> Self {
143 Vec3 { x: data[0], y: data[1], z: data[2] }
144 }
145
146 pub fn dot(&self, rhs: &Self) -> f32 {
147 self.x*rhs.x + self.y*rhs.y + self.z*rhs.z
148 }
149
150 pub fn len(&self) -> f32 {
151 self.x*self.x + self.y*self.y + self.z*self.z
152 }
153
154 pub fn cross(&self, other: &Self) -> Self {
155 let x = self.y*other.z - self.z*other.y;
156 let y = self.z*other.x - self.x*other.z;
157 let z = self.x*other.y - self.y*other.x;
158 Vec3::new(x, y, z)
159 }
160
161 pub fn normalize(&self) -> Self {
162 let len = self.len().sqrt();
163 Vec3::new(self.x / len, self.y / len, self.z / len)
164 }
165
166 pub fn scalar(&self, val: f32) -> Self {
167 Vec3::new(self.x * val, self.y * val, self.z * val)
168 }
169}
170
171impl Vec4 {
172 pub fn zero() -> Vec4 {
173 Self { x: 0.0, y: 0.0, z: 0.0, w: 0.0 }
174 }
175
176 pub fn from_array(data: [f32; 4]) -> Vec4 {
177 Vec4 { x: data[0], y: data[1], z: data[2], w: data[3] }
178 }
179
180 pub fn dot(&self, rhs: &Self) -> f32 {
181 self.x*rhs.x + self.y*rhs.y + self.z*rhs.z + self.w*rhs.w
182 }
183
184 pub fn len(&self) -> f32 {
185 self.x*self.x + self.y*self.y + self.z*self.z + self.w*self.w
186 }
187
188 pub fn cross(&self, other: &Self) -> Self {
189 let x = self.y*other.z - self.z*other.y;
190 let y = self.z*other.x - self.x*other.z;
191 let z = self.x*other.y - self.y*other.x;
192 Vec4::new(x, y, z, 0.0)
193 }
194
195 pub fn normalize(&self) -> Self {
196 let len = self.len().sqrt();
197 Vec4::new(self.x / len, self.y / len, self.z / len, self.w / len)
198 }
199
200 pub fn apply_matrix(&mut self, matrix: Mat4) {
201 let aux = self.clone();
202 let m = matrix.transpose();
203 self.x = aux.dot(&m.data[0]);
204 self.y = aux.dot(&m.data[1]);
205 self.z = aux.dot(&m.data[2]);
206 self.w = aux.dot(&m.data[3]);
207 }
208}
209
210#[repr(C)]
211#[derive(Debug, Clone, Copy, PartialEq)]
212pub struct Mat4 {
213 pub data: [Vec4; 4],
214}
215
216impl Default for Mat4 {
217 fn default() -> Self { Mat4::identity() }
218}
219
220impl Mat4 {
221 pub fn new(data: [Vec4; 4]) -> Mat4 {
222 Mat4 { data }
223 }
224
225 pub fn identity() -> Mat4 {
226 let data: [Vec4; 4] = [
227 Vec4::new(1.0, 0.0, 0.0, 0.0),
228 Vec4::new(0.0, 1.0, 0.0, 0.0),
229 Vec4::new(0.0, 0.0, 1.0, 0.0),
230 Vec4::new(0.0, 0.0, 0.0, 1.0),
231 ];
232 Mat4 { data }
233 }
234
235 pub fn ortho(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) -> Mat4 {
236 let mut data: [Vec4; 4] = [Vec4::zero(); 4];
237 data[0].x = 2.0 / (right - left);
238 data[0].y = 0.0;
239 data[0].z = 0.0;
240 data[0].w = 0.0;
241
242 data[1].x = 0.0;
243 data[1].y = 2.0 / (top - bottom);
244 data[1].z = 0.0;
245 data[1].w = 0.0;
246
247 data[2].x = 0.0;
248 data[2].y = 0.0;
249 data[2].z = -2.0 / (far - near);
250 data[2].w = 0.0;
251
252 data[3].x = -(right + left) / (right - left);
253 data[3].y = -(top + bottom) / (top - bottom);
254 data[3].z = -(far + near) / (far - near);
255 data[3].w = 1.0;
256 Mat4 { data }
257 }
258
259 pub fn perspective(fov: f32, aspect: f32, near: f32, far: f32) -> Mat4 {
260 let mut data: [Vec4; 4] = [Vec4::zero(); 4];
261 let f = 1.0 / (fov / 2.0).tan();
262 let inv_range = 1.0 / (near - far);
263
264 data[0].x = f / aspect;
265 data[0].y = 0.0;
266 data[0].z = 0.0;
267 data[0].w = 0.0;
268
269 data[1].x = 0.0;
270 data[1].y = f;
271 data[1].z = 0.0;
272 data[1].w = 0.0;
273
274 data[2].x = 0.0;
275 data[2].y = 0.0;
276 data[2].z = (far + near) * inv_range;
277 data[2].w = -1.0;
278
279 data[3].x = 0.0;
280 data[3].y = 0.0;
281 data[3].z = 2.0 * far * near * inv_range;
282 data[3].w = 0.0;
283 Mat4 { data }
284 }
285
286 pub fn look_at(position: Vec3, target: Vec3, up: Vec3) -> Mat4 {
287 let f = (target - position).normalize();
288 let r = up.cross(&f).normalize();
289 let u = f.cross(&r);
290
291 let data: [Vec4; 4] = [
292 Vec4::new(r.x, u.x, -f.x, 0.0),
293 Vec4::new(r.y, u.y, -f.y, 0.0),
294 Vec4::new(r.z, u.z, -f.z, 0.0),
295 Vec4::new(-r.dot(&position), -u.dot(&position), f.dot(&position), 1.0),
296 ];
297 Mat4 { data }
298 }
299
300 pub fn from_array(data: [f32; 16]) -> Mat4 {
301 let mut dt: [Vec4; 4] = [Vec4::zero(); 4];
302
303 for i in 0..4 {
304 let index = 4 * i;
305 dt[i] = Vec4::new(data[index], data[index+1], data[index+2], data[index+3]);
306 }
307 Mat4 { data: dt }
308 }
309
310 pub fn translation_matrix(pos: Vec3) -> Mat4 {
311 let mut mat = Mat4::identity();
312 mat.data[3].x = pos.x;
313 mat.data[3].y = pos.y;
314 mat.data[3].z = pos.z;
315 mat
316 }
317
318 pub fn scale_matrix(scale: Vec3) -> Mat4 {
319 let mut mat = Mat4::identity();
320 mat.data[0].x = scale.x;
321 mat.data[1].y = scale.y;
322 mat.data[2].z = scale.z;
323 mat
324 }
325
326 pub fn rotation_matrix(axis: Vec3, angle: f32) -> Mat4 {
327 let r = angle.to_radians();
328 let mut m = Mat4::identity();
329 m
330 }
331
332 pub fn rotation_matrix_z(angle: f32) -> Mat4 {
333 let rad = angle.to_radians();
334 let mut m = Mat4::identity();
335 m.data[0].x = rad.cos();
336 m.data[0].y = rad.sin();
337 m.data[1].x = -rad.sin();
338 m.data[1].y = rad.cos();
339 m.data[2].z = 1.0;
340 m.data[3].w = 1.0;
341 m
342 }
343
344 pub fn transpose(&self) -> Mat4 {
345 let mut data: [f32; 16] = [0.0; 16];
346
347 let mut i = 0;
348 for vec in self.data {
349 data[i] = vec.x;
350 data[4+i] = vec.y;
351 data[8+i] = vec.z;
352 data[12+i] = vec.w;
353 i += 1;
354 }
355 Mat4::from_array(data)
356 }
357
358 pub fn translate(&mut self, v: Vec3) {
359 let mat = Mat4::translation_matrix(v);
360 *self *= mat;
361 }
362
363 pub fn scale(&mut self, scale: Vec3) {
364 let mat = Mat4::scale_matrix(scale);
365 *self *= mat;
366 }
367
368 pub fn rotate(&mut self, angle: f32) {
369 let mat = Mat4::rotation_matrix_z(angle);
370 *self *= mat;
371 }
372}
373
374impl Mul for Mat4 {
375 type Output = Mat4;
376 fn mul(self, rhs: Self) -> Self::Output {
377 let aux = rhs.transpose();
378 let mut data: [Vec4; 4] = [Vec4::zero(); 4];
379 let mut i = 0;
380 for d in &mut data {
381 d.x = self.data[i].dot(&aux.data[0]);
382 d.y = self.data[i].dot(&aux.data[1]);
383 d.z = self.data[i].dot(&aux.data[2]);
384 d.w = self.data[i].dot(&aux.data[3]);
385 i += 1;
386 }
387
388 Mat4 { data }
389 }
390}
391
392impl MulAssign for Mat4 {
393 fn mul_assign(&mut self, rhs: Self) {
394 let aux = rhs.transpose();
395 let mut data: [Vec4; 4] = [Vec4::zero(); 4];
396 let mut i = 0;
397 for d in &mut data {
398 d.x = self.data[i].dot(&aux.data[0]);
399 d.y = self.data[i].dot(&aux.data[1]);
400 d.z = self.data[i].dot(&aux.data[2]);
401 d.w = self.data[i].dot(&aux.data[3]);
402 i += 1;
403 }
404 self.data = data;
405 }
406}
407
408impl_glsl!(Mat4, "mat4");
409
410impl GlUniform for Mat4 {
411 fn uniform(location: i32, val: &Self) {
412 Self::uniformv(location, 1, val);
413 }
414
415 fn uniformv(location: i32, count: i32, ptr: *const Self) {
416 unsafe {
417 gl::UniformMatrix4fv(location, count, gl::FALSE, ptr as *const f32);
418 }
419 }
420
421 fn send_uniform(&self, location: i32) {
422 Self::uniform(location, self);
423 }
424}