blob: 2f0f70fb60f00b750b59755dfd966ae97750eee8 [file] [log] [blame]
Romain Guy5d4bae72016-11-08 09:49:25 -08001/*
2 * Copyright 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18#ifndef UI_TQUATHELPERS_H_
19#define UI_TQUATHELPERS_H_
20
21#include <math.h>
22#include <stdint.h>
23#include <sys/types.h>
24
25#include <iostream>
26
27#include <ui/vec3.h>
28
29#define PURE __attribute__((pure))
30
31namespace android {
32namespace details {
33// -------------------------------------------------------------------------------------
34
35/*
36 * No user serviceable parts here.
37 *
38 * Don't use this file directly, instead include ui/quat.h
39 */
40
41
42/*
43 * TQuatProductOperators implements basic arithmetic and basic compound assignment
44 * operators on a quaternion of type BASE<T>.
45 *
46 * BASE only needs to implement operator[] and size().
47 * By simply inheriting from TQuatProductOperators<BASE, T> BASE will automatically
48 * get all the functionality here.
49 */
50
51template <template<typename T> class QUATERNION, typename T>
52class TQuatProductOperators {
53public:
54 /* compound assignment from a another quaternion of the same size but different
55 * element type.
56 */
57 template <typename OTHER>
58 QUATERNION<T>& operator *= (const QUATERNION<OTHER>& r) {
59 QUATERNION<T>& q = static_cast<QUATERNION<T>&>(*this);
60 q = q * r;
61 return q;
62 }
63
64 /* compound assignment products by a scalar
65 */
66 QUATERNION<T>& operator *= (T v) {
67 QUATERNION<T>& lhs = static_cast<QUATERNION<T>&>(*this);
68 for (size_t i = 0; i < QUATERNION<T>::size(); i++) {
69 lhs[i] *= v;
70 }
71 return lhs;
72 }
73 QUATERNION<T>& operator /= (T v) {
74 QUATERNION<T>& lhs = static_cast<QUATERNION<T>&>(*this);
75 for (size_t i = 0; i < QUATERNION<T>::size(); i++) {
76 lhs[i] /= v;
77 }
78 return lhs;
79 }
80
81 /*
82 * NOTE: the functions below ARE NOT member methods. They are friend functions
83 * with they definition inlined with their declaration. This makes these
84 * template functions available to the compiler when (and only when) this class
85 * is instantiated, at which point they're only templated on the 2nd parameter
86 * (the first one, BASE<T> being known).
87 */
88
89 /* The operators below handle operation between quaternion of the same size
90 * but of a different element type.
91 */
92 template<typename RT>
93 friend inline
94 constexpr QUATERNION<T> PURE operator *(const QUATERNION<T>& q, const QUATERNION<RT>& r) {
95 // could be written as:
96 // return QUATERNION<T>(
97 // q.w*r.w - dot(q.xyz, r.xyz),
98 // q.w*r.xyz + r.w*q.xyz + cross(q.xyz, r.xyz));
99
100 return QUATERNION<T>(
101 q.w*r.w - q.x*r.x - q.y*r.y - q.z*r.z,
102 q.w*r.x + q.x*r.w + q.y*r.z - q.z*r.y,
103 q.w*r.y - q.x*r.z + q.y*r.w + q.z*r.x,
104 q.w*r.z + q.x*r.y - q.y*r.x + q.z*r.w);
105 }
106
107 template<typename RT>
108 friend inline
109 constexpr TVec3<T> PURE operator *(const QUATERNION<T>& q, const TVec3<RT>& v) {
110 // note: if q is known to be a unit quaternion, then this simplifies to:
111 // TVec3<T> t = 2 * cross(q.xyz, v)
112 // return v + (q.w * t) + cross(q.xyz, t)
113 return imaginary(q * QUATERNION<T>(v, 0) * inverse(q));
114 }
115
116
117 /* For quaternions, we use explicit "by a scalar" products because it's much faster
118 * than going (implicitly) through the quaternion multiplication.
119 * For reference: we could use the code below instead, but it would be a lot slower.
120 * friend inline
121 * constexpr BASE<T> PURE operator *(const BASE<T>& q, const BASE<T>& r) {
122 * return BASE<T>(
123 * q.w*r.w - q.x*r.x - q.y*r.y - q.z*r.z,
124 * q.w*r.x + q.x*r.w + q.y*r.z - q.z*r.y,
125 * q.w*r.y - q.x*r.z + q.y*r.w + q.z*r.x,
126 * q.w*r.z + q.x*r.y - q.y*r.x + q.z*r.w);
127 *
128 */
129 friend inline
130 constexpr QUATERNION<T> PURE operator *(QUATERNION<T> q, T scalar) {
131 // don't pass q by reference because we need a copy anyways
132 return q *= scalar;
133 }
134 friend inline
135 constexpr QUATERNION<T> PURE operator *(T scalar, QUATERNION<T> q) {
136 // don't pass q by reference because we need a copy anyways
137 return q *= scalar;
138 }
139
140 friend inline
141 constexpr QUATERNION<T> PURE operator /(QUATERNION<T> q, T scalar) {
142 // don't pass q by reference because we need a copy anyways
143 return q /= scalar;
144 }
145};
146
147
148/*
149 * TQuatFunctions implements functions on a quaternion of type BASE<T>.
150 *
151 * BASE only needs to implement operator[] and size().
152 * By simply inheriting from TQuatFunctions<BASE, T> BASE will automatically
153 * get all the functionality here.
154 */
155template <template<typename T> class QUATERNION, typename T>
156class TQuatFunctions {
157public:
158 /*
159 * NOTE: the functions below ARE NOT member methods. They are friend functions
160 * with they definition inlined with their declaration. This makes these
161 * template functions available to the compiler when (and only when) this class
162 * is instantiated, at which point they're only templated on the 2nd parameter
163 * (the first one, BASE<T> being known).
164 */
165
166 template<typename RT>
167 friend inline
168 constexpr T PURE dot(const QUATERNION<T>& p, const QUATERNION<RT>& q) {
169 return p.x * q.x +
170 p.y * q.y +
171 p.z * q.z +
172 p.w * q.w;
173 }
174
175 friend inline
176 constexpr T PURE norm(const QUATERNION<T>& q) {
177 return std::sqrt( dot(q, q) );
178 }
179
180 friend inline
181 constexpr T PURE length(const QUATERNION<T>& q) {
182 return norm(q);
183 }
184
185 friend inline
186 constexpr T PURE length2(const QUATERNION<T>& q) {
187 return dot(q, q);
188 }
189
190 friend inline
191 constexpr QUATERNION<T> PURE normalize(const QUATERNION<T>& q) {
192 return length(q) ? q / length(q) : QUATERNION<T>(1);
193 }
194
195 friend inline
196 constexpr QUATERNION<T> PURE conj(const QUATERNION<T>& q) {
197 return QUATERNION<T>(q.w, -q.x, -q.y, -q.z);
198 }
199
200 friend inline
201 constexpr QUATERNION<T> PURE inverse(const QUATERNION<T>& q) {
202 return conj(q) * (1 / dot(q, q));
203 }
204
205 friend inline
206 constexpr T PURE real(const QUATERNION<T>& q) {
207 return q.w;
208 }
209
210 friend inline
211 constexpr TVec3<T> PURE imaginary(const QUATERNION<T>& q) {
212 return q.xyz;
213 }
214
215 friend inline
216 constexpr QUATERNION<T> PURE unreal(const QUATERNION<T>& q) {
217 return QUATERNION<T>(q.xyz, 0);
218 }
219
220 friend inline
221 constexpr QUATERNION<T> PURE cross(const QUATERNION<T>& p, const QUATERNION<T>& q) {
222 return unreal(p*q);
223 }
224
225 friend inline
226 QUATERNION<T> PURE exp(const QUATERNION<T>& q) {
227 const T nq(norm(q.xyz));
228 return std::exp(q.w)*QUATERNION<T>((sin(nq)/nq)*q.xyz, cos(nq));
229 }
230
231 friend inline
232 QUATERNION<T> PURE log(const QUATERNION<T>& q) {
233 const T nq(norm(q));
234 return QUATERNION<T>((std::acos(q.w/nq)/norm(q.xyz))*q.xyz, log(nq));
235 }
236
237 friend inline
238 QUATERNION<T> PURE pow(const QUATERNION<T>& q, T a) {
239 // could also be computed as: exp(a*log(q));
240 const T nq(norm(q));
241 const T theta(a*std::acos(q.w / nq));
242 return std::pow(nq, a) * QUATERNION<T>(normalize(q.xyz) * std::sin(theta), std::cos(theta));
243 }
244
245 friend inline
246 QUATERNION<T> PURE slerp(const QUATERNION<T>& p, const QUATERNION<T>& q, T t) {
247 // could also be computed as: pow(q * inverse(p), t) * p;
248 const T d = dot(p, q);
249 const T npq = sqrt(dot(p, p) * dot(q, q)); // ||p|| * ||q||
250 const T a = std::acos(std::abs(d) / npq);
251 const T a0 = a * (1 - t);
252 const T a1 = a * t;
253 const T isina = 1 / sin(a);
254 const T s0 = std::sin(a0) * isina;
255 const T s1 = std::sin(a1) * isina;
256 // ensure we're taking the "short" side
257 return normalize(s0 * p + ((d < 0) ? (-s1) : (s1)) * q);
258 }
259
260 friend inline
261 constexpr QUATERNION<T> PURE lerp(const QUATERNION<T>& p, const QUATERNION<T>& q, T t) {
262 return ((1 - t) * p) + (t * q);
263 }
264
265 friend inline
266 constexpr QUATERNION<T> PURE nlerp(const QUATERNION<T>& p, const QUATERNION<T>& q, T t) {
267 return normalize(lerp(p, q, t));
268 }
269
270 friend inline
271 constexpr QUATERNION<T> PURE positive(const QUATERNION<T>& q) {
272 return q.w < 0 ? -q : q;
273 }
274};
275
276/*
277 * TQuatDebug implements functions on a vector of type BASE<T>.
278 *
279 * BASE only needs to implement operator[] and size().
280 * By simply inheriting from TQuatDebug<BASE, T> BASE will automatically
281 * get all the functionality here.
282 */
283template <template<typename T> class QUATERNION, typename T>
284class TQuatDebug {
285public:
286 /*
287 * NOTE: the functions below ARE NOT member methods. They are friend functions
288 * with they definition inlined with their declaration. This makes these
289 * template functions available to the compiler when (and only when) this class
290 * is instantiated, at which point they're only templated on the 2nd parameter
291 * (the first one, BASE<T> being known).
292 */
293 friend std::ostream& operator<< (std::ostream& stream, const QUATERNION<T>& q) {
294 return stream << "< " << q.w << " + " << q.x << "i + " << q.y << "j + " << q.z << "k >";
295 }
296};
297#undef PURE
298
299// -------------------------------------------------------------------------------------
300} // namespace details
301} // namespace android
302
303
304#endif // UI_TQUATHELPERS_H_