1use approx::{AbsDiffEq, RelativeEq, UlpsEq};
2use nalgebra::{Isometry3, Point3, RealField, Unit, UnitQuaternion, Vector3};
3use simba::scalar::SubsetOf;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct Frame<N: Copy + RealField> {
9 pos: Point3<N>,
11 rot: UnitQuaternion<N>,
13 zat: N,
15}
16
17impl<N: Copy + RealField> Frame<N> {
18 #[must_use]
20 pub fn look_at(target: Point3<N>, eye: &Point3<N>, up: &Vector3<N>) -> Self {
21 let dir = target - eye;
22 Self {
23 pos: target,
24 rot: UnitQuaternion::face_towards(&-dir, up),
25 zat: dir.norm(),
26 }
27 }
28 #[must_use]
30 pub fn eye(&self) -> Point3<N> {
31 self.pos + self.rot * Vector3::z_axis().into_inner() * self.zat
32 }
33 pub fn set_eye(&mut self, eye: &Point3<N>, up: &Vector3<N>) {
35 *self = Self::look_at(self.pos, eye, up);
36 }
37 #[must_use]
39 pub const fn target(&self) -> &Point3<N> {
40 &self.pos
41 }
42 pub fn set_target(&mut self, pos: Point3<N>) {
46 let eye = self.eye();
47 let (new_dir, zat) = Unit::new_and_get(pos - eye);
48 let old_dir = Unit::new_normalize(self.pos - eye);
49 let rot = UnitQuaternion::rotation_between_axis(&old_dir, &new_dir)
50 .unwrap_or_else(|| UnitQuaternion::from_axis_angle(&self.yaw_axis(), N::pi()));
51 let rot = rot * self.rot;
52 *self = Self { pos, rot, zat }
53 }
54 #[must_use]
56 pub const fn distance(&self) -> N {
57 self.zat
58 }
59 pub const fn set_distance(&mut self, zat: N) {
61 self.zat = zat;
62 }
63 pub fn scale(&mut self, rat: N) {
65 self.zat *= rat;
66 }
67 pub fn local_scale_around(&mut self, rat: N, pos: &Point3<N>) {
69 self.local_slide(&(pos - pos * rat));
70 self.scale(rat);
71 }
72 pub fn scale_around(&mut self, rat: N, pos: &Point3<N>) {
74 let pos = pos - self.pos.coords;
75 self.slide(&(pos - pos * rat));
76 self.scale(rat);
77 }
78 pub fn local_slide(&mut self, vec: &Vector3<N>) {
80 self.pos += self.rot * vec;
81 }
82 pub fn slide(&mut self, vec: &Vector3<N>) {
84 self.pos += vec;
85 }
86 pub fn local_orbit(&mut self, rot: &UnitQuaternion<N>) {
88 self.rot *= rot;
89 }
90 pub fn local_orbit_around(&mut self, rot: &UnitQuaternion<N>, pos: &Point3<N>) {
92 self.local_slide(&(pos - rot * pos));
93 self.local_orbit(rot);
94 }
95 pub fn orbit(&mut self, rot: &UnitQuaternion<N>) {
97 self.rot = rot * self.rot;
98 }
99 pub fn orbit_around(&mut self, rot: &UnitQuaternion<N>, pos: &Point3<N>) {
101 let pos = pos - self.pos.coords;
102 self.slide(&(pos - rot * pos));
103 self.orbit(rot);
104 }
105 pub fn look_around(&mut self, pitch: N, yaw: N, yaw_axis: &Unit<Vector3<N>>) {
109 let pitch = UnitQuaternion::from_axis_angle(&self.pitch_axis(), pitch);
110 let yaw = UnitQuaternion::from_axis_angle(yaw_axis, yaw);
111 self.orbit_around(&(yaw * pitch), &self.eye());
112 }
113 #[allow(clippy::unused_self)]
115 #[must_use]
116 pub fn local_pitch_axis(&self) -> Unit<Vector3<N>> {
117 Vector3::x_axis()
118 }
119 #[allow(clippy::unused_self)]
121 #[must_use]
122 pub fn local_yaw_axis(&self) -> Unit<Vector3<N>> {
123 Vector3::y_axis()
124 }
125 #[allow(clippy::unused_self)]
127 #[must_use]
128 pub fn local_roll_axis(&self) -> Unit<Vector3<N>> {
129 Vector3::z_axis()
130 }
131 #[must_use]
133 pub fn pitch_axis(&self) -> Unit<Vector3<N>> {
134 self.rot * self.local_pitch_axis()
135 }
136 #[must_use]
138 pub fn yaw_axis(&self) -> Unit<Vector3<N>> {
139 self.rot * self.local_yaw_axis()
140 }
141 #[must_use]
143 pub fn roll_axis(&self) -> Unit<Vector3<N>> {
144 self.rot * self.local_roll_axis()
145 }
146 #[must_use]
160 pub fn try_lerp_slerp(&self, other: &Self, t: N, epsilon: N) -> Option<Self> {
161 Some(Self {
162 pos: self.pos.lerp(&other.pos, t),
163 rot: self.rot.try_slerp(&other.rot, t, epsilon)?,
164 zat: self.zat * (N::one() - t) + other.zat * t,
165 })
166 }
167 pub fn renormalize(&mut self) -> N {
169 self.rot.renormalize()
170 }
171 #[must_use]
173 pub fn view(&self) -> Isometry3<N> {
174 Isometry3::from_parts(
175 self.eye().into(),
177 self.rot,
179 )
180 }
181 #[must_use]
185 pub fn inverse_view(&self) -> Isometry3<N> {
186 let rot = self.rot.inverse();
188 let eye = rot * self.pos + Vector3::z_axis().into_inner() * self.zat;
190 Isometry3::from_parts((-eye.coords).into(), rot)
192 }
193 #[must_use]
195 pub fn cast<M: Copy + RealField>(self) -> Frame<M>
196 where
197 N: SubsetOf<M>,
198 {
199 Frame {
200 pos: self.pos.cast(),
201 rot: self.rot.cast(),
202 zat: self.zat.to_superset(),
203 }
204 }
205}
206
207impl<N: Copy + RealField + AbsDiffEq> AbsDiffEq for Frame<N>
208where
209 N::Epsilon: Copy,
210{
211 type Epsilon = N::Epsilon;
212
213 fn default_epsilon() -> N::Epsilon {
214 N::default_epsilon()
215 }
216
217 fn abs_diff_eq(&self, other: &Self, epsilon: N::Epsilon) -> bool {
218 self.pos.abs_diff_eq(&other.pos, epsilon)
219 && self.rot.abs_diff_eq(&other.rot, epsilon)
220 && self.zat.abs_diff_eq(&other.zat, epsilon)
221 }
222}
223
224impl<N: Copy + RealField + RelativeEq> RelativeEq for Frame<N>
225where
226 N::Epsilon: Copy,
227{
228 fn default_max_relative() -> N::Epsilon {
229 N::default_max_relative()
230 }
231
232 fn relative_eq(&self, other: &Self, epsilon: N::Epsilon, max_relative: N::Epsilon) -> bool {
233 self.pos.relative_eq(&other.pos, epsilon, max_relative)
234 && self.rot.relative_eq(&other.rot, epsilon, max_relative)
235 && self.zat.relative_eq(&other.zat, epsilon, max_relative)
236 }
237}
238
239impl<N: Copy + RealField + UlpsEq> UlpsEq for Frame<N>
240where
241 N::Epsilon: Copy,
242{
243 fn default_max_ulps() -> u32 {
244 N::default_max_ulps()
245 }
246
247 fn ulps_eq(&self, other: &Self, epsilon: N::Epsilon, max_ulps: u32) -> bool {
248 self.pos.ulps_eq(&other.pos, epsilon, max_ulps)
249 && self.rot.ulps_eq(&other.rot, epsilon, max_ulps)
250 && self.zat.ulps_eq(&other.zat, epsilon, max_ulps)
251 }
252}
253
254#[cfg(feature = "rkyv")]
255impl<N: Copy + RealField> rkyv::Archive for Frame<N> {
256 type Archived = Self;
257 type Resolver = ();
258
259 #[inline]
260 #[allow(unsafe_code)]
261 unsafe fn resolve(&self, _: usize, (): Self::Resolver, out: *mut Self::Archived) {
262 unsafe {
263 out.write(rkyv::to_archived!(*self as Self));
264 }
265 }
266}
267
268#[cfg(feature = "rkyv")]
269impl<Ser: rkyv::Fallible + ?Sized, N: Copy + RealField> rkyv::Serialize<Ser> for Frame<N> {
270 #[inline]
271 fn serialize(&self, _: &mut Ser) -> Result<Self::Resolver, Ser::Error> {
272 Ok(())
273 }
274}
275
276#[cfg(feature = "rkyv")]
277impl<De: rkyv::Fallible + ?Sized, N: Copy + RealField> rkyv::Deserialize<Self, De> for Frame<N> {
278 #[inline]
279 fn deserialize(&self, _: &mut De) -> Result<Self, De::Error> {
280 Ok(rkyv::from_archived!(*self))
281 }
282}