1
2use vecmath::{
5 Vector3,
6 Matrix4,
7 vec3_normalized_sub,
8 vec3_cross,
9 vec3_dot,
10};
11use vecmath::col_mat4_mul as mul;
12use vecmath::traits::*;
13use quaternion::{Quaternion, rotate_vector};
14
15pub fn model_view_projection<T: Float + Copy>(
17 model: Matrix4<T>,
18 view: Matrix4<T>,
19 projection: Matrix4<T>
20) -> Matrix4<T> {
21 mul(mul(projection, view), model)
22}
23
24#[derive(Clone, Debug, PartialEq, PartialOrd, Hash)]
26pub struct Camera<T=f32> {
27 pub position: Vector3<T>,
29 pub up: Vector3<T>,
31 pub right: Vector3<T>,
33 pub forward: Vector3<T>
35}
36
37#[derive(Clone, Debug, PartialEq, PartialOrd, Hash)]
39pub struct CameraPerspective<T=f32> {
40 pub fov: T,
42 pub near_clip: T,
44 pub far_clip: T,
46 pub aspect_ratio: T,
48}
49
50impl<T: Float + Copy> Camera<T> {
51 pub fn new(position: Vector3<T>) -> Camera<T> {
55 let _0 = Zero::zero();
56 let _1 = One::one();
57 Camera {
58 position: position,
59 right: [_1, _0, _0],
60 up: [_0, _1, _0],
61 forward: [_0, _0, _1]
62 }
63 }
64
65 pub fn orthogonal(&self) -> Matrix4<T> {
69 let p = self.position;
70 let r = self.right;
71 let u = self.up;
72 let f = self.forward;
73 let _0 = Zero::zero();
74 [
75 [r[0], u[0], f[0], _0],
76 [r[1], u[1], f[1], _0],
77 [r[2], u[2], f[2], _0],
78 [-vec3_dot(r, p), -vec3_dot(u, p), -vec3_dot(f, p), One::one()]
79 ]
80 }
81
82 pub fn look_at(&mut self, point: Vector3<T>) {
84 self.forward = vec3_normalized_sub(point, self.position);
85 self.update_right();
86 }
87
88 pub fn set_yaw_pitch(&mut self, yaw: T, pitch: T) {
90 let (y_s, y_c, p_s, p_c) = (yaw.sin(), yaw.cos(), pitch.sin(), pitch.cos());
91 self.forward = [y_s * p_c, p_s, y_c * p_c];
92 self.up = [y_s * -p_s, p_c, y_c * -p_s];
93 self.update_right();
94 }
95
96 pub fn set_rotation(&mut self, rotation: Quaternion<T>)
99 {
100 let _0: T = Zero::zero();
101 let _1: T = One::one();
102 let forward: Vector3<T> = [_0, _0, _1];
103 let up: Vector3<T> = [_0, _1, _0];
104 self.forward = rotate_vector(rotation, forward);
105 self.up = rotate_vector(rotation, up);
106 self.update_right();
107 }
108
109 fn update_right(&mut self) {
110 self.right = vec3_cross(self.up, self.forward);
111 }
112}
113
114impl<T: Float> CameraPerspective<T>
115 where f64: Cast<T>
116{
117 pub fn projection(&self) -> Matrix4<T> {
119 let _0: T = Zero::zero();
120 let _1: T = One::one();
121 let _2: T = _1 + _1;
122 let pi: T = Radians::_180();
123 let _360: T = Cast::cast(360.0f64);
124 let f = _1 / (self.fov * (pi / _360)).tan();
125 let (far, near) = (self.far_clip, self.near_clip);
126 [
127 [f / self.aspect_ratio, _0, _0, _0],
128 [_0, f, _0, _0],
129 [_0, _0, (far + near) / (near - far), -_1],
130 [_0, _0, (_2 * far * near) / (near - far), _0]
131 ]
132 }
133}