1
2use std::ops::{Add, Sub, Mul, AddAssign, SubAssign, MulAssign};
3use num_traits::NumCast;
4use std::default::Default;
5use float_cmp::{Ulps, ApproxEq};
6use {FullFloat, Vec3, Mat3, Angle, Direction3};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10#[derive(Serialize, Deserialize)]
11pub struct Quat<F> {
12 pub v: Vec3<F>,
13 pub w: F
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18#[derive(Serialize, Deserialize)]
19pub struct NQuat<F> {
20 v: Vec3<F>,
21 w: F
22}
23
24impl<F: FullFloat> Quat<F> {
25 pub fn new(v: Vec3<F>, w: F) -> Quat<F> {
26 Quat {
27 v: v,
28 w: w,
29 }
30 }
31}
32
33impl<F: FullFloat> NQuat<F> {
34 pub fn new_isnormal(v: Vec3<F>, w: F) -> NQuat<F> {
35 let q = NQuat {
36 v: v,
37 w: w,
38 };
39
40 assert!((w*w + v.squared_magnitude()).sqrt().approx_eq(
41 &F::one(),
42 <F as NumCast>::from(20.0_f32).unwrap() * F::epsilon(),
43 NumCast::from(20_u32).unwrap(),
44 ));
45
46 q
47 }
48}
49
50impl<F: FullFloat> Quat<F> {
51 pub fn identity() -> Quat<F> {
52 Quat {
53 v: Vec3::new(F::zero(), F::zero(), F::zero()),
54 w: F::one()
55 }
56 }
57}
58impl<F: FullFloat> NQuat<F> {
59 pub fn identity() -> NQuat<F> {
60 NQuat::new_isnormal(
61 Vec3::new(F::zero(), F::zero(), F::zero()),
62 F::one())
63 }
64}
65
66impl<F: FullFloat> Default for Quat<F> {
67 fn default() -> Quat<F> {
68 Quat::identity()
69 }
70}
71
72impl<F: FullFloat> Default for NQuat<F> {
73 fn default() -> NQuat<F> {
74 NQuat::identity()
75 }
76}
77
78impl From<Quat<f32>> for Quat<f64> {
82 fn from(q: Quat<f32>) -> Quat<f64> {
83 Quat {
84 v: From::from(q.v),
85 w: q.w as f64
86 }
87 }
88}
89
90impl From<Quat<f64>> for Quat<f32> {
91 fn from(q: Quat<f64>) -> Quat<f32> {
92 Quat {
93 v: From::from(q.v),
94 w: q.w as f32
95 }
96 }
97}
98
99impl From<NQuat<f32>> for NQuat<f64> {
100 fn from(q: NQuat<f32>) -> NQuat<f64> {
101 NQuat::new_isnormal(
102 From::from(q.v),
103 q.w as f64)
104 }
105}
106
107impl From<NQuat<f64>> for NQuat<f32> {
108 fn from(q: NQuat<f64>) -> NQuat<f32> {
109 NQuat::new_isnormal(
110 From::from(q.v),
111 q.w as f32)
112 }
113}
114
115impl<F: FullFloat> From<Quat<F>> for NQuat<F>
119{
120 fn from(q: Quat<F>) -> NQuat<F> {
121 let mag = q.magnitude();
122 NQuat::new_isnormal(
123 q.v / mag,
124 q.w / mag)
125 }
126}
127
128impl<F: FullFloat> From<NQuat<F>> for Quat<F> {
129 fn from(nq: NQuat<F>) -> Quat<F> {
130 Quat { v: nq.v, w: nq.w }
131 }
132}
133
134impl<F: FullFloat> NQuat<F> {
138 pub fn from_axis_angle(axis: &Direction3<F>, angle: &Angle<F>) -> NQuat<F>
141 {
142 let two: F = NumCast::from(2.0_f32).unwrap();
143 let (s,c) = (angle.as_radians() / two).sin_cos();
144 let q = Quat {
145 v: Vec3::new(axis.x * s, axis.y * s, axis.z * s),
146 w: c
147 };
148 From::from(q)
149 }
150}
151
152impl<F: FullFloat> NQuat<F> {
153 pub fn as_axis_angle(&self) -> (Direction3<F>, Angle<F>)
155 {
156 let two: F = NumCast::from(2.0_f32).unwrap();
157 let angle = self.w.acos() * two;
158 let axis = self.v;
159 (From::from(axis), Angle::from_radians(angle))
160 }
161}
162
163impl<F: FullFloat> NQuat<F> {
167 pub fn from_directions(start: Direction3<F>, end: Direction3<F>) -> Option<NQuat<F>>
169 {
170 if start.approx_eq(&end,
172 <F as NumCast>::from(10.0_f32).unwrap() * F::epsilon(),
173 NumCast::from(10_u32).unwrap())
174 {
175 return Some(NQuat::identity())
176 }
177 if start.approx_eq(&-end,
179 <F as NumCast>::from(10.0_f32).unwrap() * F::epsilon(),
180 NumCast::from(10_u32).unwrap())
181 {
182 return None
183 }
184
185 let two: F = NumCast::from(2.0_f32).unwrap();
186 let e = start.dot(end);
187 if e==-F::one() {
188 return None;
191 }
192 let term = (two * (F::one() + e)).sqrt();
193 let v: Vec3<F> = start.cross(end);
194 let q = Quat {
195 v: v / term,
196 w: term / two
197 };
198 Some(From::from(q))
200 }
201}
202
203impl<F: FullFloat> Quat<F>
207{
208 pub fn squared_magnitude(&self) -> F {
209 self.w * self.w + self.v.squared_magnitude()
210 }
211}
212
213impl<F: FullFloat> Quat<F>
214{
215 pub fn magnitude(&self) -> F {
216 self.squared_magnitude().sqrt()
217 }
218}
219
220impl<F: FullFloat> Quat<F> {
221 pub fn is_normal(&self) -> bool {
222 self.magnitude().approx_eq(
223 &F::one(),
224 <F as NumCast>::from(10.0_f32).unwrap() * F::epsilon(),
225 NumCast::from(10_u32).unwrap()
226 )
227 }
228}
229
230impl<F: FullFloat> Add for Quat<F>
234{
235 type Output = Quat<F>;
236
237 fn add(self, rhs: Quat<F>) -> Quat<F> {
238 Quat {
239 v: self.v + rhs.v,
240 w: self.w + rhs.w,
241 }
242 }
243}
244
245impl<F: FullFloat> AddAssign for Quat<F>
246{
247 fn add_assign(&mut self, rhs: Quat<F>) {
248 self.v += rhs.v;
249 self.w += rhs.w;
250 }
251}
252
253impl<F: FullFloat> Sub for Quat<F>
254{
255 type Output = Quat<F>;
256
257 fn sub(self, rhs: Quat<F>) -> Quat<F> {
258 Quat {
259 v: self.v - rhs.v,
260 w: self.w - rhs.w,
261 }
262 }
263}
264
265impl<F: FullFloat> SubAssign for Quat<F>
266{
267 fn sub_assign(&mut self, rhs: Quat<F>) {
268 self.v -= rhs.v;
269 self.w -= rhs.w;
270 }
271}
272
273impl<F: FullFloat> Mul<F> for Quat<F>
277{
278 type Output = Quat<F>;
279
280 fn mul(self, rhs: F) -> Quat<F> {
281 Quat {
282 v: self.v * rhs,
283 w: self.w * rhs,
284 }
285 }
286}
287
288impl<F: FullFloat> MulAssign<F> for Quat<F>
289{
290 fn mul_assign(&mut self, rhs: F) {
291 self.v *= rhs;
292 self.w *= rhs;
293 }
294}
295
296impl<F: FullFloat> MulAssign for Quat<F>
297{
298 fn mul_assign(&mut self, rhs: Quat<F>) {
299 self.v = self.v.cross(rhs.v) + rhs.v * self.w + self.v * rhs.w;
300 self.w = self.w * rhs.w - self.v.dot(rhs.v);
301 }
302}
303
304impl<F: FullFloat> Quat<F>
305{
306 pub fn dot(&self, other: Quat<F>) -> F
307 {
308 (self.w * other.w) + self.v.dot(other.v)
309 }
310}
311
312impl<F: FullFloat> NQuat<F>
313{
314 pub fn dot(&self, other: Quat<F>) -> F
315 {
316 (self.w * other.w) + self.v.dot(other.v)
317 }
318}
319
320impl<F: FullFloat> Mul for Quat<F>
321{
322 type Output = Quat<F>;
323
324 fn mul(self, rhs: Quat<F>) -> Quat<F> {
325 Quat {
326 v: self.v.cross(rhs.v) + rhs.v * self.w + self.v * rhs.w,
327 w: self.w * rhs.w - self.v.dot(rhs.v)
328 }
329 }
330}
331
332impl<F: FullFloat> Mul for NQuat<F>
333{
334 type Output = NQuat<F>;
335
336 fn mul(self, rhs: NQuat<F>) -> NQuat<F> {
337 let a: Quat<F> = From::from(self);
338 let b: Quat<F> = From::from(rhs);
339 From::from(a * b)
340 }
341}
342
343impl<F: FullFloat> Quat<F>
347{
348 pub fn conjugate(&self) -> Quat<F> {
349 Quat {
350 v: -self.v,
351 w: self.w
352 }
353 }
354}
355
356impl<F: FullFloat> NQuat<F>
357{
358 pub fn conjugate(&self) -> NQuat<F> {
359 NQuat::new_isnormal(
360 -self.v,
361 self.w)
362 }
363}
364
365impl<F: FullFloat> NQuat<F>
369{
370 pub fn rotate(&self, v: Vec3<F>) -> Vec3<F> {
376 let dot = v.dot(self.v);
377
378 v * ((self.w * self.w) - (self.v.x * self.v.x) - (self.v.y * self.v.y) - (self.v.z * self.v.z))
379 + self.v * (dot + dot)
380 + self.v.cross(v) * (self.w + self.w)
381 }
382}
383
384impl<F: FullFloat> Mul<Vec3<F>> for NQuat<F>
386{
387 type Output = Vec3<F>;
388
389 fn mul(self, rhs: Vec3<F>) -> Vec3<F> {
390 self.rotate(rhs)
391 }
392}
393
394impl<F: FullFloat> From<NQuat<F>> for Mat3<F> {
398 fn from(q: NQuat<F>) -> Mat3<F> {
399 let two: F = NumCast::from(2.0_f32).unwrap();
400 let x2 = q.v.x * q.v.x;
401 let y2 = q.v.y * q.v.y;
402 let z2 = q.v.z * q.v.z;
403 let xy = q.v.x * q.v.y;
404 let xz = q.v.x * q.v.z;
405 let yz = q.v.y * q.v.z;
406 let wx = q.w * q.v.x;
407 let wy = q.w * q.v.y;
408 let wz = q.w * q.v.z;
409
410 Mat3::new(
411 F::one() - two * (y2 + z2), two * (xy - wz), two * (xz + wy),
412 two * (xy + wz), F::one() - two * (x2 + z2), two * (yz - wx),
413 two * (xz - wy), two * (yz + wx), F::one() - two * (x2 + y2)
414 )
415 }
416}
417
418impl<F: FullFloat> From<Mat3<F>> for NQuat<F> {
419 fn from(m: Mat3<F>) -> NQuat<F> {
420 let one: F = F::one();
421 let half: F = NumCast::from(0.5_f32).unwrap();
422 let quarter: F = NumCast::from(0.25_f32).unwrap();
423
424 let sum = m.x.x + m.y.y + m.z.z;
425 let x;
426 let y;
427 let z;
428 let w;
429 if sum>F::zero() {
430 w = (sum + one).sqrt() * half;
431 let f = quarter / w;
432 x = (m.z.y - m.y.z) * f;
433 y = (m.x.z - m.z.x) * f;
434 z = (m.y.x - m.x.y) * f;
435 }
436 else if (m.x.x > m.y.y) && (m.x.x > m.z.z) {
437 x = (m.x.x - m.y.y - m.z.z + one).sqrt() * half;
438 let f = quarter / x;
439 y = (m.y.x + m.x.y) * f;
440 z = (m.x.z + m.z.x) * f;
441 w = (m.z.y - m.y.z) * f;
442 }
443 else if m.y.y > m.z.z {
444 y = (m.y.y - m.x.x - m.z.z + one).sqrt() * half;
445 let f = quarter / y;
446 x = (m.y.x + m.x.y) * f;
447 z = (m.z.y + m.y.z) * f;
448 w = (m.x.z - m.z.x) * f;
449 }
450 else {
451 z = (m.z.z - m.x.x - m.y.y + one).sqrt() * half;
452 let f = quarter / z;
453 x = (m.x.z + m.z.x) * f;
454 y = (m.z.y + m.y.z) * f;
455 w = (m.y.x - m.x.y) * f;
456 }
457
458 let q = Quat {
459 v: Vec3 { x: x, y: y, z: z },
460 w: w
461 };
462
463 From::from(q)
466 }
467}
468
469impl<F: FullFloat> ApproxEq for Quat<F> {
473 type Flt = F;
474
475 fn approx_eq(&self, other: &Self,
476 epsilon: <F as ApproxEq>::Flt,
477 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
478 {
479 self.v.approx_eq(&other.v, epsilon, ulps) &&
480 self.w.approx_eq(&other.w, epsilon, ulps)
481 }
482}
483
484impl<F: FullFloat> ApproxEq for NQuat<F> {
485 type Flt = F;
486
487 fn approx_eq(&self, other: &Self,
488 epsilon: <F as ApproxEq>::Flt,
489 ulps: <<F as ApproxEq>::Flt as Ulps>::U) -> bool
490 {
491 self.v.approx_eq(&other.v, epsilon, ulps) &&
492 self.w.approx_eq(&other.w, epsilon, ulps)
493 }
494}
495
496#[cfg(test)]
499mod tests {
500 use {Quat, NQuat, Vec3, Mat3, Angle, Direction3};
501
502 #[test]
503 fn test_quat_basic() {
504 let q = Quat::<f64>::new(
505 Vec3::<f64>::new(3.0, 4.0, 5.0),
506 6.0);
507 assert_eq!(q.v.x, 3.0);
508 assert_eq!(q.v.y, 4.0);
509 assert_eq!(q.v.z, 5.0);
510 assert_eq!(q.w, 6.0);
511
512 let q = Quat::<f64>::identity();
513 assert_eq!(q.v.x, 0.0);
514 assert_eq!(q.v.y, 0.0);
515 assert_eq!(q.v.z, 0.0);
516 assert_eq!(q.w, 1.0);
517
518 let q2 = Quat::<f64>::default();
519 assert_eq!(q, q2);
520
521 let q: NQuat<f64> = From::from(
522 Quat::<f64>::new(Vec3::<f64>::new(3.0, 4.0, 5.0), 6.0)
523 );
524 let q2: Quat<f64> = From::from(q);
525 assert!(0.999999999 < q2.magnitude());
526 assert!(q2.magnitude() < 1.000000001);
527 }
528
529 #[test]
530 fn test_quat_mat_conversion() {
531 use float_cmp::ApproxEq;
532
533 let v = Vec3::<f32>::new(1.0, 0.2, -0.3);
534 let q = Quat::<f32>::new(v, 5.0);
535 let nq: NQuat<f32> = From::from(q);
536 let q: Quat<f32> = From::from(nq);
537
538 let m: Mat3<f32> = From::from(nq);
539
540 let nq: NQuat<f32> = From::from(m);
544 let q2: Quat<f32> = From::from(nq);
545 let q2c: Quat<f32> = q2.conjugate();
546
547 assert!(q2.approx_eq(&q, 2.0 * ::std::f32::EPSILON, 2) ||
548 q2c.approx_eq(&q, 2.0 * ::std::f32::EPSILON, 2));
549 }
550
551 #[test]
552 fn test_axis_angle() {
553 use float_cmp::ApproxEq;
554
555 let axis: Direction3<f32> = From::from(Vec3::<f32>::new(1.0, 1.0, 1.0));
556 let angle = Angle::<f32>::from_degrees(90.0);
557 let q = NQuat::<f32>::from_axis_angle(&axis, &angle);
558 let (axis2, angle2) = q.as_axis_angle();
559 println!("axis {:?} angle {:?} axis {:?} angle {:?}",
560 axis, angle, axis2, angle2);
561 assert!(axis.approx_eq(&axis2, 2.0 * ::std::f32::EPSILON, 2));
562 assert!(angle.approx_eq(&angle2, 2.0 * ::std::f32::EPSILON, 2));
563 }
564
565 #[test]
566 fn test_rotation_x() {
567 use float_cmp::ApproxEq;
568
569 let axis: Direction3<f32> = From::from(Vec3::<f32>::new(1.0, 0.0, 0.0));
570 let angle = Angle::<f32>::from_degrees(90.0);
571 let q = NQuat::<f32>::from_axis_angle(&axis, &angle);
572
573 let object = Vec3::<f32>::new(10.0, 5.0, 3.0);
574
575 let object2 = q.rotate(object);
576
577 assert!(object2.x.approx_eq(&10.0, 2.0 * ::std::f32::EPSILON, 2));
578 assert!(object2.y.approx_eq(&-3.0, 2.0 * ::std::f32::EPSILON, 2));
579 assert!(object2.z.approx_eq(&5.0, 2.0 * ::std::f32::EPSILON, 2));
580 }
581
582 }