tea/
vec.rs

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 from_array(data: [T; $size])-> $Name<T> where T: Default {
17            //     let mut vec = $Name::default();
18            //     let ptr = &vec;
19            //     vec
20            // }
21
22            pub fn as_array(&self) -> [&T; $size] {
23                [$(&self.$field),+]
24            }
25
26            // pub fn dot(&self, rhs: &Self) -> T {
27            //     let sum: T = ($(&self.$field * rhs.$field),+);
28            //     sum
29            // }
30
31            /* pub fn from_value(v: T) -> $Name<T> {
32                $Name { $($field: v),+ }
33            } */
34            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}