1 use cgmath::{Matrix4, Vector4};
2 use cgmath::conv::array4x4;
4 use glium::glutin::VirtualKeyCode;
6 use std::f32::consts::PI;
7 use support::vec3::Vec3;
8 use support::vec3::norm;
11 pub struct CameraState {
21 moving_backward: bool,
34 pub fn new() -> CameraState {
36 aspect: 1280.0 / 720.0,
37 pos: Vec3(0.0, 0.0, 0.0),
38 dir: Vec3(0.0, 0.0, -1.0),
45 pub fn set_pos(&mut self, pos: Vec3) {
49 pub fn get_pos(&self) -> Vec3 {
53 pub fn set_dir(&mut self, dir: Vec3) {
57 pub fn get_persp_mat(&self) -> Matrix4<f32> {
58 let fov: f32 = PI / 2.0;
62 let f = 1.0 / (fov / 2.0).tan();
64 // note: remember that this is column-major, so the lines of code are actually columns
66 x: Vector4{ x: f / self.aspect, y: 0.0, z: 0.0, w: 0.0 },
67 y: Vector4{ x: 0.0, y: f, z: 0.0, w: 0.0 },
68 z: Vector4{ x: 0.0, y: 0.0, z: (zfar+znear)/(zfar-znear), w: 1.0 },
69 w: Vector4{ x: 0.0, y: 0.0, z: -(2.0*zfar*znear)/(zfar-znear), w: 0.0 },
73 pub fn get_view_mat(&self) -> Matrix4<f32> {
74 let f = norm(&self.dir);
76 let up = Vec3(0.0, 1.0, 0.0);
78 let s = Vec3(f.1 * up.2 - f.2 * up.1,
79 f.2 * up.0 - f.0 * up.2,
80 f.0 * up.1 - f.1 * up.0);
83 let u = (sn.1 * f.2 - sn.2 * f.1,
84 sn.2 * f.0 - sn.0 * f.2,
85 sn.0 * f.1 - sn.1 * f.0);
87 let p = (-self.pos.0 * s.0 - self.pos.1 * s.1 - self.pos.2 * s.2,
88 -self.pos.0 * u.0 - self.pos.1 * u.1 - self.pos.2 * u.2,
89 -self.pos.0 * f.0 - self.pos.1 * f.1 - self.pos.2 * f.2);
91 // note: remember that this is column-major, so the lines of code are actually columns
93 x: Vector4{ x: sn.0, y: u.0, z: f.0, w: 0.0 },
94 y: Vector4{ x: sn.1, y: u.1, z: f.1, w: 0.0 },
95 z: Vector4{ x: sn.2, y: u.2, z: f.2, w: 0.0 },
96 w: Vector4{ x: p.0, y: p.1, z: p.2, w: 1.0 },
100 pub fn get_perspview(&self) -> [[f32; 4]; 4] {
101 array4x4(self.get_persp_mat() * self.get_view_mat())
104 pub fn get_perspective(&self) -> [[f32; 4]; 4] {
105 array4x4(self.get_persp_mat())
108 pub fn get_view(&self) -> [[f32; 4]; 4] {
109 array4x4(self.get_view_mat())
112 pub fn update(&mut self) {
113 let f = norm(&self.dir);
115 let up = Vec3(0.0, 1.0, 0.0);
117 let s = Vec3(f.1 * up.2 - f.2 * up.1,
118 f.2 * up.0 - f.0 * up.2,
119 f.0 * up.1 - f.1 * up.0);
123 let u = Vec3(s.1 * f.2 - s.2 * f.1,
124 s.2 * f.0 - s.0 * f.2,
125 s.0 * f.1 - s.1 * f.0);
127 let walk_speed = 0.01;
128 let strife_speed = 0.02;
129 let pan_speed = 0.001;
132 self.pos += u * strife_speed;
134 if self.moving_down {
135 self.pos -= u * strife_speed;
137 if self.moving_left {
138 self.pos -= s * strife_speed;
140 if self.moving_right {
141 self.pos += s * strife_speed;
143 if self.moving_forward {
144 self.pos += f * walk_speed;
146 if self.moving_backward {
147 self.pos -= f * walk_speed;
150 if self.turning_left { self.rel_x -= 8; }
151 if self.turning_right { self.rel_x += 8; }
152 if self.turning_up { self.rel_y -= 2; }
153 if self.turning_down { self.rel_y += 2; }
154 let vx = -pan_speed * self.rel_x as f32;
155 let vy = -pan_speed * self.rel_y as f32;
156 self.dir = Vec3(f.0 * vx.cos() + f.2 * vx.sin(),
157 f.1 * vy.cos() - f.2 * vy.sin(),
158 f.1 * vy.sin() - f.0 * vx.sin() + f.2 * vx.cos() * vy.cos());
162 //println!("camera_pos = {:?}", self.pos);
163 //println!("camera_dir = {:?}", self.dir);
166 pub fn process_input(&mut self, event: &glium::glutin::WindowEvent) {
168 &glium::glutin::WindowEvent::CursorMoved { position, .. } => {
169 let (x, y) = (position.x as i32, position.y as i32);
170 if self.mouse_x == -1 {
171 // Set initial absolute position.
175 self.rel_x += x - self.mouse_x;
176 self.rel_y += y - self.mouse_y;
180 &glium::glutin::WindowEvent::KeyboardInput { input, .. } => {
181 let pressed = input.state == glium::glutin::ElementState::Pressed;
182 let key = match input.virtual_keycode {
187 VirtualKeyCode::Left => self.moving_left = pressed,
188 VirtualKeyCode::Right => self.moving_right = pressed,
189 VirtualKeyCode::Up => self.moving_up = pressed,
190 VirtualKeyCode::Down => self.moving_down = pressed,
191 VirtualKeyCode::W => self.moving_forward = pressed,
192 VirtualKeyCode::S => self.moving_backward = pressed,
193 VirtualKeyCode::A => self.turning_left = pressed,
194 VirtualKeyCode::D => self.turning_right = pressed,
195 VirtualKeyCode::R => self.turning_up = pressed,
196 VirtualKeyCode::F => self.turning_down = pressed,