Split Vec3.
[mandelwow.git] / support / camera.rs
1 extern crate glutin;
2
3 use support::vec3::Vec3;
4 use support::vec3::norm;
5
6 use std::f32;
7
8 //use glutin::Event;
9 //use glutin::VirtualKeyCode;
10
11 #[derive(Default)]
12 pub struct CameraState {
13     aspect_ratio: f32,
14     pos: Vec3,
15     dir: Vec3,
16
17     moving_up: bool,
18     moving_left: bool,
19     moving_down: bool,
20     moving_right: bool,
21     moving_forward: bool,
22     moving_backward: bool,
23     turning_up: bool,
24     turning_left: bool,
25     turning_down: bool,
26     turning_right: bool,
27 }
28
29 impl CameraState {
30     pub fn new() -> CameraState {
31         CameraState {
32             aspect_ratio: 1024.0 / 768.0,
33             pos: Vec3(0.0, 0.0, 0.0),
34             dir: Vec3(0.0, 0.0, 1.0),
35             .. Default::default()
36         }
37     }
38
39     pub fn set_pos(&mut self, pos: Vec3) {
40         self.pos = pos;
41     }
42
43     pub fn set_dir(&mut self, dir: Vec3) {
44         self.dir = dir;
45     }
46
47     pub fn get_perspective(&self) -> [[f32; 4]; 4] {
48         let fov: f32 = 3.141592 / 2.0;
49         let zfar = 1024.0;
50         let znear = 0.1;
51
52         let f = 1.0 / (fov / 2.0).tan();
53
54         // note: remember that this is column-major, so the lines of code are actually columns
55         [
56             [f / self.aspect_ratio,    0.0,              0.0              ,   0.0],
57             [         0.0         ,     f ,              0.0              ,   0.0],
58             [         0.0         ,    0.0,  (zfar+znear)/(zfar-znear)    ,   1.0],
59             [         0.0         ,    0.0, -(2.0*zfar*znear)/(zfar-znear),   0.0],
60         ]
61     }
62
63
64     pub fn get_view(&self) -> [[f32; 4]; 4] {
65         let f = norm(&self.dir);
66
67         let up = Vec3(0.0, 1.0, 0.0);
68
69         let s = Vec3(f.1 * up.2 - f.2 * up.1,
70                      f.2 * up.0 - f.0 * up.2,
71                      f.0 * up.1 - f.1 * up.0);
72         let sn = norm(&s);
73
74         let u = (sn.1 * f.2 - sn.2 * f.1,
75                  sn.2 * f.0 - sn.0 * f.2,
76                  sn.0 * f.1 - sn.1 * f.0);
77
78         let p = (-self.pos.0 * s.0 - self.pos.1 * s.1 - self.pos.2 * s.2,
79                  -self.pos.0 * u.0 - self.pos.1 * u.1 - self.pos.2 * u.2,
80                  -self.pos.0 * f.0 - self.pos.1 * f.1 - self.pos.2 * f.2);
81
82         // note: remember that this is column-major, so the lines of code are actually columns
83         [
84             [sn.0, u.0, f.0, 0.0],
85             [sn.1, u.1, f.1, 0.0],
86             [sn.2, u.2, f.2, 0.0],
87             [p.0,  p.1, p.2, 1.0],
88         ]
89     }
90
91     pub fn update(&mut self) {
92         let f = norm(&self.dir);
93
94         let up = Vec3(0.0, 1.0, 0.0);
95
96         let s = Vec3(f.1 * up.2 - f.2 * up.1,
97                      f.2 * up.0 - f.0 * up.2,
98                      f.0 * up.1 - f.1 * up.0);
99
100         let s = norm(&s);
101
102         let u = Vec3(s.1 * f.2 - s.2 * f.1,
103                      s.2 * f.0 - s.0 * f.2,
104                      s.0 * f.1 - s.1 * f.0);
105
106         if self.moving_up {
107             self.pos += u * 0.01;
108         }
109         if self.moving_left {
110             self.pos.0 -= s.0 * 0.01;
111             self.pos.1 -= s.1 * 0.01;
112             self.pos.2 -= s.2 * 0.01;
113         }
114         if self.moving_down {
115             self.pos.0 -= u.0 * 0.01;
116             self.pos.1 -= u.1 * 0.01;
117             self.pos.2 -= u.2 * 0.01;
118         }
119         if self.moving_right {
120             self.pos += s * 0.01;
121         }
122         if self.moving_forward {
123             self.pos += f * 0.01;
124         }
125         if self.moving_backward {
126             self.pos.0 -= f.0 * 0.01;
127             self.pos.1 -= f.1 * 0.01;
128             self.pos.2 -= f.2 * 0.01;
129         }
130         if self.turning_left {
131             let a: f32 = -0.05;
132             self.dir = Vec3(f.0 * a.cos() + f.2 * a.sin(), f.1, - f.0 * a.sin() + f.2 * a.cos());
133         }
134         if self.turning_right {
135             let a: f32 = 0.05;
136             self.dir = Vec3(f.0 * a.cos() + f.2 * a.sin(), f.1, - f.0 * a.sin() + f.2 * a.cos());
137         }
138         if self.turning_up {
139             let a: f32 = -0.05;
140             self.dir = Vec3(f.0, f.1 * a.cos() - f.2 * a.sin(), f.1 * a.sin() + f.2 * a.cos());
141         }
142         if self.turning_down {
143             let a: f32 = 0.05;
144             self.dir = Vec3(f.0, f.1 * a.cos() - f.2 * a.sin(), f.1 * a.sin() + f.2 * a.cos());
145         }
146         //println!("camera_pos = {:?}", self.pos);
147         //println!("camera_dir = {:?}", self.dir);
148     }
149
150     pub fn process_input(&mut self, event: &glutin::Event) {
151         match event {
152             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Up)) => {
153                 self.moving_up = true;
154             },
155             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::Up)) => {
156                 self.moving_up = false;
157             },
158             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Down)) => {
159                 self.moving_down = true;
160             },
161             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::Down)) => {
162                 self.moving_down = false;
163             },
164             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Left)) => {
165                 self.moving_left = true;
166             },
167             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::Left)) => {
168                 self.moving_left = false;
169             },
170             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Right)) => {
171                 self.moving_right = true;
172             },
173             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::Right)) => {
174                 self.moving_right = false;
175             },
176             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::A)) => {
177                 self.turning_left = true;
178             },
179             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::A)) => {
180                 self.turning_left = false;
181             },
182             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::D)) => {
183                 self.turning_right = true;
184             },
185             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::D)) => {
186                 self.turning_right = false;
187             },
188             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::W)) => {
189                 self.moving_forward = true;
190             },
191             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::W)) => {
192                 self.moving_forward = false;
193             },
194             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::S)) => {
195                 self.moving_backward = true;
196             },
197             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::S)) => {
198                 self.moving_backward = false;
199             },
200             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::R)) => {
201                 self.turning_up = true;
202             },
203             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::R)) => {
204                 self.turning_up = false;
205             },
206             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::F)) => {
207                 self.turning_down = true;
208             },
209             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::F)) => {
210                 self.turning_down = false;
211             },
212             _ => {}
213         }
214     }
215 }