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
extern crate cgmath;
extern crate num_traits;
use std::collections::VecDeque;
use cgmath::prelude::*;
use cgmath::{BaseFloat, Matrix4, Matrix3, Vector3, Point3};
pub struct MatrixStack<T: BaseFloat + num_traits::Float> {
current: Matrix4<T>,
stack: VecDeque<Matrix4<T>>,
}
impl<T: BaseFloat + num_traits::Float> MatrixStack<T> {
pub fn new() -> MatrixStack<T> {
MatrixStack {
current: Matrix4::identity(),
stack: VecDeque::new(),
}
}
pub fn transform(&mut self, transformation: Matrix4<T>) {
self.current = self.current * transformation;
}
pub fn rotate(&mut self, rotation: Matrix3<T>) {
self.current = self.current * Matrix4::from(rotation);
}
pub fn push(&mut self) {
self.stack.push_back(self.current);
}
pub fn pop(&mut self) -> Matrix4<T> {
if let Some(stack_top) = self.stack.pop_back() {
self.current = stack_top;
} else {
self.current = Matrix4::identity();
}
return self.current;
}
pub fn transform_vector(& self, target: Vector3<T>) -> Vector3<T> { (self.current * target.extend(<T as cgmath::Zero>::zero())).truncate() }
pub fn transform_point(& self, target: Point3<T>) -> Point3<T> { Point3::from_homogeneous(self.current * target.to_homogeneous()) }
pub fn transform_point_no_translate(& self, target: Point3<T>) -> Point3<T> {
let mut vec_version = target.to_homogeneous();
vec_version.w = <T as cgmath::Zero>::zero();
Point3::from_homogeneous(self.current * vec_version)
}
pub fn get_matrix(& self) -> Matrix4<T> { self.current }
pub fn origin(& self) -> Point3<T> { Point3::from_vec(self.current.w.truncate()) }
}