fps_camera/
first_person.rs1use vecmath::traits::{ Float, Radians };
31
32use Camera;
33
34bitflags!(pub struct Actions: u8 {
35 const MOVE_FORWARD = 0b00000001;
36 const MOVE_BACKWARD = 0b00000010;
37 const STRAFE_LEFT = 0b00000100;
38 const STRAFE_RIGHT = 0b00001000;
39 const FLY_UP = 0b00010000;
40 const FLY_DOWN = 0b00100000;
41 const MOVE_FASTER = 0b01000000;
42});
43
44pub struct FirstPersonSettings<T=f32> {
46 pub speed_horizontal: T,
50 pub speed_vertical: T,
54 pub mouse_sensitivity_horizontal: T,
58 pub mouse_sensitivity_vertical: T,
62}
63
64impl<T> Default for FirstPersonSettings<T>
65 where T: Float
66{
67 fn default() -> FirstPersonSettings<T> {
69 FirstPersonSettings {
70 speed_horizontal: T::one(),
71 speed_vertical: T::one(),
72 mouse_sensitivity_horizontal: T::one(),
73 mouse_sensitivity_vertical: T::one(),
74 }
75 }
76}
77
78pub struct FirstPerson<T=f32> {
80 pub settings: FirstPersonSettings<T>,
82 pub yaw: T,
84 pub pitch: T,
86 pub position: [T; 3],
88 pub velocity: T,
90 pub actions: Actions,
92}
93
94impl<T> FirstPerson<T>
95 where T: Float
96{
97 pub fn new(
99 position: [T; 3],
100 settings: FirstPersonSettings<T>
101 ) -> FirstPerson<T> {
102 let _0: T = T::zero();
103 FirstPerson {
104 settings: settings,
105 yaw: _0,
106 pitch: _0,
107 position: position,
108 velocity: T::one(),
109 actions: Actions::empty(),
110 }
111 }
112
113 pub fn camera(&self, dt: T) -> Camera<T> {
115 let dh = dt * self.velocity * self.settings.speed_horizontal;
116 let (dx, dy, dz) = self.movement_direction();
117 let (s, c) = (self.yaw.sin(), self.yaw.cos());
118 let mut camera = Camera::new([
119 self.position[0] + (s * dx - c * dz) * dh,
120 self.position[1] + dy * dt * self.settings.speed_vertical,
121 self.position[2] + (s * dz + c * dx) * dh
122 ]);
123 camera.set_yaw_pitch(self.yaw, self.pitch);
124 camera
125 }
126
127 pub fn update(&mut self, dt: T) {
129 let cam = self.camera(dt);
130 self.position = cam.position;
131 }
132
133 pub fn update_mouse(&mut self, relative_dx: T, relative_dy: T) {
135 let FirstPerson {
136 ref mut yaw, ref mut pitch, ref settings, ..
137 } = *self;
138
139 let dx = relative_dx * settings.mouse_sensitivity_horizontal;
140 let dy = relative_dy * settings.mouse_sensitivity_vertical;
141
142 let pi: T = Radians::_180();
143 let _0 = T::zero();
144 let _1 = T::one();
145 let _2 = _1 + _1;
146 let _3 = _2 + _1;
147 let _4 = _3 + _1;
148 let _360 = T::from_isize(360);
149
150 *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
151 *pitch = *pitch + dy / _360 * pi / _4;
152 *pitch = (*pitch).min(pi / _2).max(-pi / _2);
153 }
154
155 pub fn movement_direction(&self) -> (T, T, T) {
157 let (mut dx, mut dy, mut dz) = (T::zero(), T::zero(), T::zero());
158
159 let set_axis = |axis: &mut T, positive, negative| {
160 if self.actions.contains(positive) &&
161 self.actions.contains(negative) {
162 *axis = T::zero();
163 } else if self.actions.contains(positive) {
164 *axis = T::one();
165 } else if self.actions.contains(negative) {
166 *axis = -T::one();
167 }
168 };
169
170 set_axis(&mut dx, Actions::MOVE_BACKWARD, Actions::MOVE_FORWARD);
171 set_axis(&mut dz, Actions::STRAFE_LEFT, Actions::STRAFE_RIGHT);
172 set_axis(&mut dy, Actions::FLY_UP, Actions::FLY_DOWN);
173
174 (dx,dy,dz)
175 }
176
177 pub fn enable_actions(&mut self, actions: Actions) {
178 self.actions |= actions;
179 }
180
181 pub fn disable_action(&mut self, action: Actions) {
182 self.actions &= !action;
183 }
184}