3 use cgmath::{Matrix4, Vector4};
4 use cgmath::conv::array4x4;
5 use glutin::WindowEvent::{KeyboardInput, CursorMoved};
6 use glutin::VirtualKeyCode;
8 use std::f32::consts::PI;
9 use support::vec3::Vec3;
10 use support::vec3::norm;
13 pub struct CameraState {
23 moving_backward: bool,
36 pub fn new() -> CameraState {
38 aspect: 1280.0 / 720.0,
39 pos: Vec3(0.0, 0.0, 0.0),
40 dir: Vec3(0.0, 0.0, -1.0),
47 pub fn set_pos(&mut self, pos: Vec3) {
51 pub fn get_pos(&self) -> Vec3 {
55 pub fn set_dir(&mut self, dir: Vec3) {
59 pub fn get_persp_mat(&self) -> Matrix4<f32> {
60 let fov: f32 = PI / 2.0;
64 let f = 1.0 / (fov / 2.0).tan();
66 // note: remember that this is column-major, so the lines of code are actually columns
68 x: Vector4{ x: f / self.aspect, y: 0.0, z: 0.0, w: 0.0 },
69 y: Vector4{ x: 0.0, y: f, z: 0.0, w: 0.0 },
70 z: Vector4{ x: 0.0, y: 0.0, z: (zfar+znear)/(zfar-znear), w: 1.0 },
71 w: Vector4{ x: 0.0, y: 0.0, z: -(2.0*zfar*znear)/(zfar-znear), w: 0.0 },
75 pub fn get_view_mat(&self) -> Matrix4<f32> {
76 let f = norm(&self.dir);
78 let up = Vec3(0.0, 1.0, 0.0);
80 let s = Vec3(f.1 * up.2 - f.2 * up.1,
81 f.2 * up.0 - f.0 * up.2,
82 f.0 * up.1 - f.1 * up.0);
85 let u = (sn.1 * f.2 - sn.2 * f.1,
86 sn.2 * f.0 - sn.0 * f.2,
87 sn.0 * f.1 - sn.1 * f.0);
89 let p = (-self.pos.0 * s.0 - self.pos.1 * s.1 - self.pos.2 * s.2,
90 -self.pos.0 * u.0 - self.pos.1 * u.1 - self.pos.2 * u.2,
91 -self.pos.0 * f.0 - self.pos.1 * f.1 - self.pos.2 * f.2);
93 // note: remember that this is column-major, so the lines of code are actually columns
95 x: Vector4{ x: sn.0, y: u.0, z: f.0, w: 0.0 },
96 y: Vector4{ x: sn.1, y: u.1, z: f.1, w: 0.0 },
97 z: Vector4{ x: sn.2, y: u.2, z: f.2, w: 0.0 },
98 w: Vector4{ x: p.0, y: p.1, z: p.2, w: 1.0 },
102 pub fn get_perspview(&self) -> [[f32; 4]; 4] {
103 array4x4(self.get_persp_mat() * self.get_view_mat())
106 pub fn get_perspective(&self) -> [[f32; 4]; 4] {
107 array4x4(self.get_persp_mat())
110 pub fn get_view(&self) -> [[f32; 4]; 4] {
111 array4x4(self.get_view_mat())
114 pub fn update(&mut self) {
115 let f = norm(&self.dir);
117 let up = Vec3(0.0, 1.0, 0.0);
119 let s = Vec3(f.1 * up.2 - f.2 * up.1,
120 f.2 * up.0 - f.0 * up.2,
121 f.0 * up.1 - f.1 * up.0);
125 let u = Vec3(s.1 * f.2 - s.2 * f.1,
126 s.2 * f.0 - s.0 * f.2,
127 s.0 * f.1 - s.1 * f.0);
129 let walk_speed = 0.01;
130 let strife_speed = 0.02;
131 let pan_speed = 0.001;
134 self.pos += u * strife_speed;
136 if self.moving_down {
137 self.pos -= u * strife_speed;
139 if self.moving_left {
140 self.pos -= s * strife_speed;
142 if self.moving_right {
143 self.pos += s * strife_speed;
145 if self.moving_forward {
146 self.pos += f * walk_speed;
148 if self.moving_backward {
149 self.pos -= f * walk_speed;
152 if self.turning_left { self.rel_x -= 8; }
153 if self.turning_right { self.rel_x += 8; }
154 if self.turning_up { self.rel_y -= 2; }
155 if self.turning_down { self.rel_y += 2; }
156 let vx = -pan_speed * self.rel_x as f32;
157 let vy = -pan_speed * self.rel_y as f32;
158 self.dir = Vec3(f.0 * vx.cos() + f.2 * vx.sin(),
159 f.1 * vy.cos() - f.2 * vy.sin(),
160 f.1 * vy.sin() - f.0 * vx.sin() + f.2 * vx.cos() * vy.cos());
164 //println!("camera_pos = {:?}", self.pos);
165 //println!("camera_dir = {:?}", self.dir);
168 pub fn process_input(&mut self, event: &glutin::WindowEvent) {
170 &CursorMoved { position: (x, y), .. } => {
171 let (x, y) = (x as i32, y as i32);
172 if self.mouse_x == -1 {
173 // Set initial absolute position.
177 self.rel_x += x - self.mouse_x;
178 self.rel_y += y - self.mouse_y;
182 &KeyboardInput { input, .. } => {
183 let pressed = input.state == glutin::ElementState::Pressed;
184 let key = match input.virtual_keycode {
189 VirtualKeyCode::Left => self.moving_left = pressed,
190 VirtualKeyCode::Right => self.moving_right = pressed,
191 VirtualKeyCode::Up => self.moving_up = pressed,
192 VirtualKeyCode::Down => self.moving_down = pressed,
193 VirtualKeyCode::W => self.moving_forward = pressed,
194 VirtualKeyCode::S => self.moving_backward = pressed,
195 VirtualKeyCode::A => self.turning_left = pressed,
196 VirtualKeyCode::D => self.turning_right = pressed,
197 VirtualKeyCode::R => self.turning_up = pressed,
198 VirtualKeyCode::F => self.turning_down = pressed,