blob: 4f5dba9c3e253592e6a401f9dfc765a64bd1f597 [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#ifndef UI_MAT3_H_
18#define UI_MAT3_H_
19
20#include <ui/quat.h>
21#include <ui/TMatHelpers.h>
22#include <ui/vec3.h>
23#include <stdint.h>
24#include <sys/types.h>
25
26#define PURE __attribute__((pure))
27
Romain Guycaf2ca42016-11-10 11:45:58 -080028#if __cplusplus >= 201402L
29#define CONSTEXPR constexpr
30#else
31#define CONSTEXPR
32#endif
33
Romain Guy5d4bae72016-11-08 09:49:25 -080034namespace android {
35// -------------------------------------------------------------------------------------
36namespace details {
37
38template<typename T>
39class TQuaternion;
40
41/**
42 * A 3x3 column-major matrix class.
43 *
44 * Conceptually a 3x3 matrix is a an array of 3 column vec3:
45 *
46 * mat3 m =
47 * \f$
48 * \left(
49 * \begin{array}{ccc}
50 * m[0] & m[1] & m[2] \\
51 * \end{array}
52 * \right)
53 * \f$
54 * =
55 * \f$
56 * \left(
57 * \begin{array}{ccc}
58 * m[0][0] & m[1][0] & m[2][0] \\
59 * m[0][1] & m[1][1] & m[2][1] \\
60 * m[0][2] & m[1][2] & m[2][2] \\
61 * \end{array}
62 * \right)
63 * \f$
64 * =
65 * \f$
66 * \left(
67 * \begin{array}{ccc}
68 * m(0,0) & m(0,1) & m(0,2) \\
69 * m(1,0) & m(1,1) & m(1,2) \\
70 * m(2,0) & m(2,1) & m(2,2) \\
71 * \end{array}
72 * \right)
73 * \f$
74 *
75 * m[n] is the \f$ n^{th} \f$ column of the matrix and is a vec3.
76 *
77 */
78template <typename T>
79class TMat33 : public TVecUnaryOperators<TMat33, T>,
80 public TVecComparisonOperators<TMat33, T>,
81 public TVecAddOperators<TMat33, T>,
82 public TMatProductOperators<TMat33, T>,
83 public TMatSquareFunctions<TMat33, T>,
84 public TMatTransform<TMat33, T>,
85 public TMatHelpers<TMat33, T>,
86 public TMatDebug<TMat33, T> {
87public:
88 enum no_init { NO_INIT };
89 typedef T value_type;
90 typedef T& reference;
91 typedef T const& const_reference;
92 typedef size_t size_type;
93 typedef TVec3<T> col_type;
94 typedef TVec3<T> row_type;
95
96 static constexpr size_t COL_SIZE = col_type::SIZE; // size of a column (i.e.: number of rows)
97 static constexpr size_t ROW_SIZE = row_type::SIZE; // size of a row (i.e.: number of columns)
98 static constexpr size_t NUM_ROWS = COL_SIZE;
99 static constexpr size_t NUM_COLS = ROW_SIZE;
100
101private:
102 /*
103 * <-- N columns -->
104 *
105 * a[0][0] a[1][0] a[2][0] ... a[N][0] ^
106 * a[0][1] a[1][1] a[2][1] ... a[N][1] |
107 * a[0][2] a[1][2] a[2][2] ... a[N][2] M rows
108 * ... |
109 * a[0][M] a[1][M] a[2][M] ... a[N][M] v
110 *
111 * COL_SIZE = M
112 * ROW_SIZE = N
113 * m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
114 */
115
116 col_type m_value[NUM_COLS];
117
118public:
119 // array access
120 inline constexpr col_type const& operator[](size_t column) const {
121#if __cplusplus >= 201402L
122 // only possible in C++0x14 with constexpr
123 assert(column < NUM_COLS);
124#endif
125 return m_value[column];
126 }
127
128 inline col_type& operator[](size_t column) {
129 assert(column < NUM_COLS);
130 return m_value[column];
131 }
132
133 // -----------------------------------------------------------------------
134 // we want the compiler generated versions for these...
135 TMat33(const TMat33&) = default;
136 ~TMat33() = default;
137 TMat33& operator = (const TMat33&) = default;
138
139 /**
140 * constructors
141 */
142
143 /**
144 * leaves object uninitialized. use with caution.
145 */
Romain Guycaf2ca42016-11-10 11:45:58 -0800146 explicit constexpr TMat33(no_init)
Romain Guy5d4bae72016-11-08 09:49:25 -0800147 : m_value{ col_type(col_type::NO_INIT),
148 col_type(col_type::NO_INIT),
149 col_type(col_type::NO_INIT) } {}
150
151
152 /**
153 * initialize to identity.
154 *
155 * \f$
156 * \left(
157 * \begin{array}{ccc}
158 * 1 & 0 & 0 \\
159 * 0 & 1 & 0 \\
160 * 0 & 0 & 1 \\
161 * \end{array}
162 * \right)
163 * \f$
164 */
Romain Guycaf2ca42016-11-10 11:45:58 -0800165 CONSTEXPR TMat33();
Romain Guy5d4bae72016-11-08 09:49:25 -0800166
167 /**
168 * initialize to Identity*scalar.
169 *
170 * \f$
171 * \left(
172 * \begin{array}{ccc}
173 * v & 0 & 0 \\
174 * 0 & v & 0 \\
175 * 0 & 0 & v \\
176 * \end{array}
177 * \right)
178 * \f$
179 */
180 template<typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800181 explicit CONSTEXPR TMat33(U v);
Romain Guy5d4bae72016-11-08 09:49:25 -0800182
183 /**
184 * sets the diagonal to a vector.
185 *
186 * \f$
187 * \left(
188 * \begin{array}{ccc}
189 * v[0] & 0 & 0 \\
190 * 0 & v[1] & 0 \\
191 * 0 & 0 & v[2] \\
192 * \end{array}
193 * \right)
194 * \f$
195 */
196 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800197 explicit CONSTEXPR TMat33(const TVec3<U>& v);
Romain Guy5d4bae72016-11-08 09:49:25 -0800198
199 /**
200 * construct from another matrix of the same size
201 */
202 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800203 explicit CONSTEXPR TMat33(const TMat33<U>& rhs);
Romain Guy5d4bae72016-11-08 09:49:25 -0800204
205 /**
206 * construct from 3 column vectors.
207 *
208 * \f$
209 * \left(
210 * \begin{array}{ccc}
211 * v0 & v1 & v2 \\
212 * \end{array}
213 * \right)
214 * \f$
215 */
216 template <typename A, typename B, typename C>
Romain Guycaf2ca42016-11-10 11:45:58 -0800217 CONSTEXPR TMat33(const TVec3<A>& v0, const TVec3<B>& v1, const TVec3<C>& v2);
Romain Guy5d4bae72016-11-08 09:49:25 -0800218
219 /** construct from 9 elements in column-major form.
220 *
221 * \f$
222 * \left(
223 * \begin{array}{ccc}
224 * m[0][0] & m[1][0] & m[2][0] \\
225 * m[0][1] & m[1][1] & m[2][1] \\
226 * m[0][2] & m[1][2] & m[2][2] \\
227 * \end{array}
228 * \right)
229 * \f$
230 */
231 template <
232 typename A, typename B, typename C,
233 typename D, typename E, typename F,
234 typename G, typename H, typename I>
Romain Guycaf2ca42016-11-10 11:45:58 -0800235 CONSTEXPR TMat33(
236 A m00, B m01, C m02,
Romain Guy5d4bae72016-11-08 09:49:25 -0800237 D m10, E m11, F m12,
238 G m20, H m21, I m22);
239
240 /**
241 * construct from a quaternion
242 */
243 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800244 explicit CONSTEXPR TMat33(const TQuaternion<U>& q);
Romain Guy5d4bae72016-11-08 09:49:25 -0800245
246 /**
247 * construct from a C array in column major form.
248 */
249 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800250 explicit CONSTEXPR TMat33(U const* rawArray);
Romain Guy5d4bae72016-11-08 09:49:25 -0800251
252 /**
253 * orthogonalize only works on matrices of size 3x3
254 */
255 friend inline
Romain Guycaf2ca42016-11-10 11:45:58 -0800256 CONSTEXPR TMat33 orthogonalize(const TMat33& m) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800257 TMat33 ret(TMat33::NO_INIT);
258 ret[0] = normalize(m[0]);
259 ret[2] = normalize(cross(ret[0], m[1]));
260 ret[1] = normalize(cross(ret[2], ret[0]));
261 return ret;
262 }
263};
264
265// ----------------------------------------------------------------------------------------
266// Constructors
267// ----------------------------------------------------------------------------------------
268
269// Since the matrix code could become pretty big quickly, we don't inline most
270// operations.
271
272template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800273CONSTEXPR TMat33<T>::TMat33() {
Romain Guy5d4bae72016-11-08 09:49:25 -0800274 m_value[0] = col_type(1, 0, 0);
275 m_value[1] = col_type(0, 1, 0);
276 m_value[2] = col_type(0, 0, 1);
277}
278
279template <typename T>
280template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800281CONSTEXPR TMat33<T>::TMat33(U v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800282 m_value[0] = col_type(v, 0, 0);
283 m_value[1] = col_type(0, v, 0);
284 m_value[2] = col_type(0, 0, v);
285}
286
287template<typename T>
288template<typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800289CONSTEXPR TMat33<T>::TMat33(const TVec3<U>& v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800290 m_value[0] = col_type(v.x, 0, 0);
291 m_value[1] = col_type(0, v.y, 0);
292 m_value[2] = col_type(0, 0, v.z);
293}
294
Courtney Goeltzenleuchter3691aba2016-12-01 11:34:58 -0700295// construct from 9 scalars. Note that the arrangement
Romain Guy5d4bae72016-11-08 09:49:25 -0800296// of values in the constructor is the transpose of the matrix
297// notation.
298template<typename T>
299template <
300 typename A, typename B, typename C,
301 typename D, typename E, typename F,
302 typename G, typename H, typename I>
Romain Guycaf2ca42016-11-10 11:45:58 -0800303CONSTEXPR TMat33<T>::TMat33(
304 A m00, B m01, C m02,
305 D m10, E m11, F m12,
306 G m20, H m21, I m22) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800307 m_value[0] = col_type(m00, m01, m02);
308 m_value[1] = col_type(m10, m11, m12);
309 m_value[2] = col_type(m20, m21, m22);
310}
311
312template <typename T>
313template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800314CONSTEXPR TMat33<T>::TMat33(const TMat33<U>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800315 for (size_t col = 0; col < NUM_COLS; ++col) {
316 m_value[col] = col_type(rhs[col]);
317 }
318}
319
320// Construct from 3 column vectors.
321template <typename T>
322template <typename A, typename B, typename C>
Romain Guycaf2ca42016-11-10 11:45:58 -0800323CONSTEXPR TMat33<T>::TMat33(const TVec3<A>& v0, const TVec3<B>& v1, const TVec3<C>& v2) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800324 m_value[0] = v0;
325 m_value[1] = v1;
326 m_value[2] = v2;
327}
328
329// Construct from raw array, in column-major form.
330template <typename T>
331template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800332CONSTEXPR TMat33<T>::TMat33(U const* rawArray) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800333 for (size_t col = 0; col < NUM_COLS; ++col) {
334 for (size_t row = 0; row < NUM_ROWS; ++row) {
335 m_value[col][row] = *rawArray++;
336 }
337 }
338}
339
340template <typename T>
341template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800342CONSTEXPR TMat33<T>::TMat33(const TQuaternion<U>& q) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800343 const U n = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
344 const U s = n > 0 ? 2/n : 0;
345 const U x = s*q.x;
346 const U y = s*q.y;
347 const U z = s*q.z;
348 const U xx = x*q.x;
349 const U xy = x*q.y;
350 const U xz = x*q.z;
351 const U xw = x*q.w;
352 const U yy = y*q.y;
353 const U yz = y*q.z;
354 const U yw = y*q.w;
355 const U zz = z*q.z;
356 const U zw = z*q.w;
357 m_value[0] = col_type(1-yy-zz, xy+zw, xz-yw); // NOLINT
358 m_value[1] = col_type( xy-zw, 1-xx-zz, yz+xw); // NOLINT
359 m_value[2] = col_type( xz+yw, yz-xw, 1-xx-yy); // NOLINT
360}
361
362// ----------------------------------------------------------------------------------------
363// Arithmetic operators outside of class
364// ----------------------------------------------------------------------------------------
365
366/* We use non-friend functions here to prevent the compiler from using
367 * implicit conversions, for instance of a scalar to a vector. The result would
368 * not be what the caller expects.
369 *
370 * Also note that the order of the arguments in the inner loop is important since
371 * it determines the output type (only relevant when T != U).
372 */
373
374// matrix * column-vector, result is a vector of the same type than the input vector
375template <typename T, typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800376CONSTEXPR typename TMat33<U>::col_type PURE operator *(const TMat33<T>& lhs, const TVec3<U>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800377 // Result is initialized to zero.
378 typename TMat33<U>::col_type result;
379 for (size_t col = 0; col < TMat33<T>::NUM_COLS; ++col) {
380 result += lhs[col] * rhs[col];
381 }
382 return result;
383}
384
385// row-vector * matrix, result is a vector of the same type than the input vector
386template <typename T, typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800387CONSTEXPR typename TMat33<U>::row_type PURE operator *(const TVec3<U>& lhs, const TMat33<T>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800388 typename TMat33<U>::row_type result(TMat33<U>::row_type::NO_INIT);
389 for (size_t col = 0; col < TMat33<T>::NUM_COLS; ++col) {
390 result[col] = dot(lhs, rhs[col]);
391 }
392 return result;
393}
394
395// matrix * scalar, result is a matrix of the same type than the input matrix
396template<typename T, typename U>
397constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat33<T>>::type PURE
398operator*(TMat33<T> lhs, U rhs) {
399 return lhs *= rhs;
400}
401
402// scalar * matrix, result is a matrix of the same type than the input matrix
403template<typename T, typename U>
404constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat33<T>>::type PURE
405operator*(U lhs, const TMat33<T>& rhs) {
406 return rhs * lhs;
407}
408
409//------------------------------------------------------------------------------
410template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800411CONSTEXPR TMat33<T> orthogonalize(const TMat33<T>& m) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800412 TMat33<T> ret(TMat33<T>::NO_INIT);
413 ret[0] = normalize(m[0]);
414 ret[2] = normalize(cross(ret[0], m[1]));
415 ret[1] = normalize(cross(ret[2], ret[0]));
416 return ret;
417}
418
419// ----------------------------------------------------------------------------------------
420
421/* FIXME: this should go into TMatSquareFunctions<> but for some reason
422 * BASE<T>::col_type is not accessible from there (???)
423 */
424template<typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800425CONSTEXPR typename TMat33<T>::col_type PURE diag(const TMat33<T>& m) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800426 return matrix::diag(m);
427}
428
429} // namespace details
430
431// ----------------------------------------------------------------------------------------
432
433typedef details::TMat33<double> mat3d;
434typedef details::TMat33<float> mat3;
435typedef details::TMat33<float> mat3f;
436
437// ----------------------------------------------------------------------------------------
438} // namespace android
439
440#undef PURE
Romain Guycaf2ca42016-11-10 11:45:58 -0800441#undef CONSTEXPR
Romain Guy5d4bae72016-11-08 09:49:25 -0800442
443#endif // UI_MAT3_H_