Make A and D turn the camera left and right, respectively.
[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 get_pos(&self) -> Vec3 {
44         self.pos
45     }
46
47     pub fn set_dir(&mut self, dir: Vec3) {
48         self.dir = dir;
49     }
50
51     pub fn get_perspective(&self) -> [[f32; 4]; 4] {
52         let fov: f32 = 3.141592 / 2.0;
53         let zfar = 1024.0;
54         let znear = 0.1;
55
56         let f = 1.0 / (fov / 2.0).tan();
57
58         // note: remember that this is column-major, so the lines of code are actually columns
59         [
60             [f / self.aspect_ratio,    0.0,              0.0              ,   0.0],
61             [         0.0         ,     f ,              0.0              ,   0.0],
62             [         0.0         ,    0.0,  (zfar+znear)/(zfar-znear)    ,   1.0],
63             [         0.0         ,    0.0, -(2.0*zfar*znear)/(zfar-znear),   0.0],
64         ]
65     }
66
67     pub fn get_view(&self) -> [[f32; 4]; 4] {
68         let f = norm(&self.dir);
69
70         let up = Vec3(0.0, 1.0, 0.0);
71
72         let s = Vec3(f.1 * up.2 - f.2 * up.1,
73                      f.2 * up.0 - f.0 * up.2,
74                      f.0 * up.1 - f.1 * up.0);
75         let sn = norm(&s);
76
77         let u = (sn.1 * f.2 - sn.2 * f.1,
78                  sn.2 * f.0 - sn.0 * f.2,
79                  sn.0 * f.1 - sn.1 * f.0);
80
81         let p = (-self.pos.0 * s.0 - self.pos.1 * s.1 - self.pos.2 * s.2,
82                  -self.pos.0 * u.0 - self.pos.1 * u.1 - self.pos.2 * u.2,
83                  -self.pos.0 * f.0 - self.pos.1 * f.1 - self.pos.2 * f.2);
84
85         // note: remember that this is column-major, so the lines of code are actually columns
86         [
87             [sn.0, u.0, f.0, 0.0],
88             [sn.1, u.1, f.1, 0.0],
89             [sn.2, u.2, f.2, 0.0],
90             [p.0,  p.1, p.2, 1.0],
91         ]
92     }
93
94     pub fn update(&mut self) {
95         let f = norm(&self.dir);
96
97         let up = Vec3(0.0, 1.0, 0.0);
98
99         let s = Vec3(f.1 * up.2 - f.2 * up.1,
100                      f.2 * up.0 - f.0 * up.2,
101                      f.0 * up.1 - f.1 * up.0);
102
103         let s = norm(&s);
104
105         let u = Vec3(s.1 * f.2 - s.2 * f.1,
106                      s.2 * f.0 - s.0 * f.2,
107                      s.0 * f.1 - s.1 * f.0);
108
109         if self.moving_up {
110             self.pos += u * 0.01;
111         }
112         if self.moving_left {
113             self.pos.0 -= s.0 * 0.01;
114             self.pos.1 -= s.1 * 0.01;
115             self.pos.2 -= s.2 * 0.01;
116         }
117         if self.moving_down {
118             self.pos.0 -= u.0 * 0.01;
119             self.pos.1 -= u.1 * 0.01;
120             self.pos.2 -= u.2 * 0.01;
121         }
122         if self.moving_right {
123             self.pos += s * 0.01;
124         }
125         if self.moving_forward {
126             self.pos += f * 0.01;
127         }
128         if self.moving_backward {
129             self.pos.0 -= f.0 * 0.01;
130             self.pos.1 -= f.1 * 0.01;
131             self.pos.2 -= f.2 * 0.01;
132         }
133         if self.turning_left {
134             let a: f32 = 0.05;
135             self.dir = Vec3(f.0 * a.cos() + f.2 * a.sin(), f.1, - f.0 * a.sin() + f.2 * a.cos());
136         }
137         if self.turning_right {
138             let a: f32 = -0.05;
139             self.dir = Vec3(f.0 * a.cos() + f.2 * a.sin(), f.1, - f.0 * a.sin() + f.2 * a.cos());
140         }
141         if self.turning_up {
142             let a: f32 = -0.05;
143             self.dir = Vec3(f.0, f.1 * a.cos() - f.2 * a.sin(), f.1 * a.sin() + f.2 * a.cos());
144         }
145         if self.turning_down {
146             let a: f32 = 0.05;
147             self.dir = Vec3(f.0, f.1 * a.cos() - f.2 * a.sin(), f.1 * a.sin() + f.2 * a.cos());
148         }
149         //println!("camera_pos = {:?}", self.pos);
150         //println!("camera_dir = {:?}", self.dir);
151     }
152
153     pub fn process_input(&mut self, event: &glutin::Event) {
154         match event {
155             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Up)) => {
156                 self.moving_up = true;
157             },
158             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::Up)) => {
159                 self.moving_up = false;
160             },
161             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Down)) => {
162                 self.moving_down = true;
163             },
164             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::Down)) => {
165                 self.moving_down = false;
166             },
167             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Left)) => {
168                 self.moving_left = true;
169             },
170             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::Left)) => {
171                 self.moving_left = false;
172             },
173             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Right)) => {
174                 self.moving_right = true;
175             },
176             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::Right)) => {
177                 self.moving_right = false;
178             },
179             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::A)) => {
180                 self.turning_left = true;
181             },
182             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::A)) => {
183                 self.turning_left = false;
184             },
185             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::D)) => {
186                 self.turning_right = true;
187             },
188             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::D)) => {
189                 self.turning_right = false;
190             },
191             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::W)) => {
192                 self.moving_forward = true;
193             },
194             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::W)) => {
195                 self.moving_forward = false;
196             },
197             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::S)) => {
198                 self.moving_backward = true;
199             },
200             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::S)) => {
201                 self.moving_backward = false;
202             },
203             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::R)) => {
204                 self.turning_up = true;
205             },
206             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::R)) => {
207                 self.turning_up = false;
208             },
209             &glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::F)) => {
210                 self.turning_down = true;
211             },
212             &glutin::Event::KeyboardInput(glutin::ElementState::Released, _, Some(glutin::VirtualKeyCode::F)) => {
213                 self.turning_down = false;
214             },
215             _ => {}
216         }
217     }
218 }