2 (in-package :cl-tuples
)
4 (def-tuple-type quaternion
5 :tuple-element-type fast-float
9 (export-tuple-operations quaternion
)
11 (def-tuple-type angle-axis
12 :tuple-element-type fast-float
13 :initial-element
0.0f0
16 (export-tuple-operations angle-axis
)
18 ;; need conjugate, angle-axis conversion, slerp
20 (def-tuple-op quaternion-conjugate
*
21 ((q quaternion
(x y z w
)))
22 (quaternion-values* (- x
) (- y
) (- z
) w
))
24 (def-tuple-op quaternion-scale
*
25 ((q quaternion
(x y z w
))
27 "Multiply a quat by a scalar"
30 (* s x
) (* s y
) (* s z
) (* s w
))))
32 (def-tuple-op quaternion-mag-square
*
33 ((q quaternion
(x y z w
)))
35 (+ (* x x
) (* y y
) (* z z
) (* w w
))))
37 (def-tuple-op quaternion-mag
*
38 ((q quaternion
(x y z w
)))
40 (sqrt (quaternion-mag-square* q
))))
42 (def-tuple-op quaternion-normalize
*
43 ((q quaternion
(x y z w
)))
44 "Ensure a quaternion is a unit"
47 (quaternion-values* x y z w
)
48 (/ 1f0
(quaternion-mag*
49 (quaternion-values* x y z w
))))))
51 (def-tuple-op quaternion-sum
*
52 ((q0 quaternion
(x0 y0 z0 w0
))
53 (q1 quaternion
(x1 y1 z1 w1
)))
54 "Sum the components of two quaternions"
56 (quaternion-values* (+ x0 x1
) (+ y0 y1
) (+ z0 z1
) (+ w0 w1
))))
58 (def-tuple-op quaternion-dot
*
59 ((quaternion-lhs quaternion
(x0 y0 z0 w0
))
60 (quaternion-rhs quaternion
(x1 y1 z1 w1
)))
61 "Dot product of two quaternions."
63 (+ (* x0 x1
) (* y0 y1
) (* z0 z1
) (* w0 w1
))))
65 (def-tuple-op quaternion-inverse
*
66 ((q quaternion
(x y z w
)))
67 "Inverse of quaternion"
71 (sqrt (+ (* x x
) (* y y
) (* z z
) (* w w
)))))
73 (the single-float
(/ 1.0 (* mag mag
)))))
74 (declare (single-float 1/mag2
))
75 (quaternion-values* (* x
1/mag2
) (* y
1/mag2
) (* z
1/mag2
) (* w
1/mag2
)))))
78 (def-tuple-op quaternion-product
*
79 ((q-lhs quaternion
(x1 y1 z1 w1
))
80 (q-rhs quaternion
(x2 y2 z2 w2
)))
81 "Multiple of two quaternions"
83 (quaternion-values* (- (+ (* w1 x2
) (* x1 w2
) (* y1 z2
)) (* z1 y2
))
84 (- (+ (* w1 y2
) (* y1 w2
) (* z1 x2
)) (* x1 z2
))
85 (- (+ (* w1 z2
) (* x1 y2
) (* z1 w2
)) (* y1 x2
))
86 (- (* w1 w2
) (* x1 x2
) (* y1 y2
) (* z1 z2
)))))
88 (def-tuple-op quaternion-matrix33
*
89 ((q quaternion
(x y z w
)))
90 "Convert a quaternion to a 3x3 rotation matrix."
93 (- 1 (* 2 y y
) (* 2 z z
)) (- (* 2 x y
) (* 2 w z
)) (+ (* 2 x z
) (* 2 w y
))
94 (+ (* 2 x y
) (* 2 w z
)) (- 1 (* 2 x x
) (* 2 z z
)) (- (* 2 y z
) (* 2 w x
))
95 (- (* 2 x z
) (* 2 w y
)) (+ (* 2 y z
) (* 2 w x
)) (- 1 (* 2 x x
) (* 2 y y
)))))
97 (def-tuple-op angle-axis-quaternion
*
98 ((aa angle-axis
(x y z a
)))
99 "Convert an angle-axis tuple to a quaternion tuple"
101 (let* ((a/2 (* 0.5 a
))
102 (sin-angle (sin a
/2)))
109 (def-tuple-op quaternion-transform-vector3d
*
110 ((vector vector3d
(vx vy vz
))
111 (quat quaternion
(qx qy qz qw
)))
112 "Transform a 3d vector with a quaternion"
118 (vector3d-quaternion* vector
))
119 (quaternion-conjugate* quat
))
121 (vector3d-values* rx ry rz
))))
123 (def-tuple-op vector3d-quaternion
*
124 ((vector vector3d
(vx vy vz
)))
125 "Convert a 3d vector into q auqt for angular velocity purposes"
127 (quaternion-values* vx vy vz
0.0)))