1#![allow(dead_code)]
2
3use input::{ Button, GenericEvent };
6use vecmath::traits::{ Float, Radians };
7
8use Camera;
9
10bitflags!(pub struct Keys: u8 {
11 const MOVE_FORWARD = 0b00000001;
12 const MOVE_BACKWARD = 0b00000010;
13 const STRAFE_LEFT = 0b00000100;
14 const STRAFE_RIGHT = 0b00001000;
15 const FLY_UP = 0b00010000;
16 const FLY_DOWN = 0b00100000;
17});
18
19pub struct FirstPersonSettings<T=f32> {
21 pub move_forward_button: Button,
23 pub move_backward_button: Button,
25 pub strafe_left_button: Button,
27 pub strafe_right_button: Button,
29 pub fly_up_button: Button,
31 pub fly_down_button: Button,
33 pub move_faster_button: Button,
35 pub speed_horizontal: T,
39 pub speed_vertical: T,
43 pub mouse_sensitivity_horizontal: T,
47 pub mouse_sensitivity_vertical: T,
51}
52
53impl<T> FirstPersonSettings<T>
54 where T: Float
55{
56 pub fn keyboard_wasd() -> FirstPersonSettings<T> {
58 use input::Button::Keyboard;
59 use input::Key;
60
61 FirstPersonSettings {
62 move_forward_button: Keyboard(Key::W),
63 move_backward_button: Keyboard(Key::S),
64 strafe_left_button: Keyboard(Key::A),
65 strafe_right_button: Keyboard(Key::D),
66 fly_up_button: Keyboard(Key::Space),
67 fly_down_button: Keyboard(Key::LShift),
68 move_faster_button: Keyboard(Key::LCtrl),
69 speed_horizontal: T::one(),
70 speed_vertical: T::one(),
71 mouse_sensitivity_horizontal: T::one(),
72 mouse_sensitivity_vertical: T::one(),
73 }
74 }
75
76 pub fn keyboard_esdf() -> FirstPersonSettings<T> {
78 use input::Button::Keyboard;
79 use input::Key;
80
81 FirstPersonSettings {
82 move_forward_button: Keyboard(Key::E),
83 move_backward_button: Keyboard(Key::D),
84 strafe_left_button: Keyboard(Key::S),
85 strafe_right_button: Keyboard(Key::F),
86 fly_up_button: Keyboard(Key::Space),
87 fly_down_button: Keyboard(Key::Z),
88 move_faster_button: Keyboard(Key::LShift),
89 speed_horizontal: T::one(),
90 speed_vertical: T::one(),
91 mouse_sensitivity_horizontal: T::one(),
92 mouse_sensitivity_vertical: T::one(),
93 }
94 }
95
96 pub fn keyboard_zqsd() -> FirstPersonSettings<T> {
98 use input::Button::Keyboard;
99 use input::Key;
100
101 FirstPersonSettings {
102 move_forward_button: Keyboard(Key::Z),
103 move_backward_button: Keyboard(Key::S),
104 strafe_left_button: Keyboard(Key::Q),
105 strafe_right_button: Keyboard(Key::D),
106 fly_up_button: Keyboard(Key::Space),
107 fly_down_button: Keyboard(Key::LShift),
108 move_faster_button: Keyboard(Key::LCtrl),
109 speed_horizontal: T::one(),
110 speed_vertical: T::one(),
111 mouse_sensitivity_horizontal: T::one(),
112 mouse_sensitivity_vertical: T::one(),
113 }
114 }
115}
116
117pub struct FirstPerson<T=f32> {
119 pub settings: FirstPersonSettings<T>,
121 pub yaw: T,
123 pub pitch: T,
125 pub direction: [T; 3],
130 pub position: [T; 3],
132 pub velocity: T,
136 keys: Keys,
138}
139
140impl<T> FirstPerson<T>
141 where T: Float
142{
143 pub fn new(
145 position: [T; 3],
146 settings: FirstPersonSettings<T>
147 ) -> FirstPerson<T> {
148 let _0: T = T::zero();
149 FirstPerson {
150 settings: settings,
151 yaw: _0,
152 pitch: _0,
153 keys: Keys::empty(),
154 direction: [_0, _0, _0],
155 position: position,
156 velocity: T::one(),
157 }
158 }
159
160 pub fn camera(&self, dt: f64) -> Camera<T> {
162 let dt = T::from_f64(dt);
163 let dh = dt * self.velocity * self.settings.speed_horizontal;
164 let [dx, dy, dz] = self.direction;
165 let (s, c) = (self.yaw.sin(), self.yaw.cos());
166 let mut camera = Camera::new([
167 self.position[0] + (s * dx - c * dz) * dh,
168 self.position[1] + dy * dt * self.settings.speed_vertical,
169 self.position[2] + (s * dz + c * dx) * dh
170 ]);
171 camera.set_yaw_pitch(self.yaw, self.pitch);
172 camera
173 }
174
175 pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
177 e.update(|args| {
178 let cam = self.camera(args.dt);
179 self.position = cam.position;
180 });
181
182 let &mut FirstPerson {
183 ref mut yaw,
184 ref mut pitch,
185 ref mut keys,
186 ref mut direction,
187 ref mut velocity,
188 ref settings,
189 ..
190 } = self;
191
192 let pi: T = Radians::_180();
193
194
195 let _0 = T::zero();
196 let _1 = T::one();
197 let _2 = _1 + _1;
198 let _3 = _2 + _1;
199 let _4 = _3 + _1;
200 let _360 = T::from_isize(360);
201 let sqrt2 = _2.sqrt();
202
203 e.mouse_relative(|d| {
204
205 let dx = T::from_f64(d[0]) * settings.mouse_sensitivity_horizontal;
206 let dy = T::from_f64(d[1]) * settings.mouse_sensitivity_vertical;
207
208 *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
209 *pitch = *pitch + dy / _360 * pi / _4;
210 *pitch = (*pitch).min(pi / _2).max(-pi / _2);
211 });
212 e.press(|button| {
213 let [dx, dy, dz] = *direction;
214 let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
215 let mut set = |k, x: T, y: T, z: T| {
216 let (x, z) = (sgn(x), sgn(z));
217 let (x, z) = if x != _0 && z != _0 {
218 (x / sqrt2, z / sqrt2)
219 } else {
220 (x, z)
221 };
222 *direction = [x, y, z];
223 keys.insert(k);
224 };
225 match button {
226 x if x == settings.move_forward_button =>
227 set(Keys::MOVE_FORWARD, -_1, dy, dz),
228 x if x == settings.move_backward_button =>
229 set(Keys::MOVE_BACKWARD, _1, dy, dz),
230 x if x == settings.strafe_left_button =>
231 set(Keys::STRAFE_LEFT, dx, dy, _1),
232 x if x == settings.strafe_right_button =>
233 set(Keys::STRAFE_RIGHT, dx, dy, -_1),
234 x if x == settings.fly_up_button =>
235 set(Keys::FLY_UP, dx, _1, dz),
236 x if x == settings.fly_down_button =>
237 set(Keys::FLY_DOWN, dx, -_1, dz),
238 x if x == settings.move_faster_button => *velocity = _2,
239 _ => {}
240 }
241 });
242 e.release(|button| {
243 let [dx, dy, dz] = *direction;
244 let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
245 let mut set = |x: T, y: T, z: T| {
246 let (x, z) = (sgn(x), sgn(z));
247 let (x, z) = if x != _0 && z != _0 {
248 (x / sqrt2, z / sqrt2)
249 } else {
250 (x, z)
251 };
252 *direction = [x, y, z];
253 };
254 let mut release = |key, rev_key, rev_val| {
255 keys.remove(key);
256 if keys.contains(rev_key) { rev_val } else { _0 }
257 };
258 match button {
259 x if x == settings.move_forward_button =>
260 set(release(Keys::MOVE_FORWARD, Keys::MOVE_BACKWARD, _1), dy, dz),
261 x if x == settings.move_backward_button =>
262 set(release(Keys::MOVE_BACKWARD, Keys::MOVE_FORWARD, -_1), dy, dz),
263 x if x == settings.strafe_left_button =>
264 set(dx, dy, release(Keys::STRAFE_LEFT, Keys::STRAFE_RIGHT, -_1)),
265 x if x == settings.strafe_right_button =>
266 set(dx, dy, release(Keys::STRAFE_RIGHT, Keys::STRAFE_LEFT, _1)),
267 x if x == settings.fly_up_button =>
268 set(dx, release(Keys::FLY_UP, Keys::FLY_DOWN, -_1), dz),
269 x if x == settings.fly_down_button =>
270 set(dx, release(Keys::FLY_DOWN, Keys::FLY_UP, _1), dz),
271 x if x == settings.move_faster_button => *velocity = _1,
272 _ => {}
273 }
274 });
275 }
276}