blob: a607023e16ff97cb7eea9b1e2b3d207575a468d8 [file] [log] [blame]
Mathias Agopian595ea772013-08-21 23:10:41 -07001/*
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
Romain Guy5d4bae72016-11-08 09:49:25 -080017#ifndef UI_MAT4_H_
18#define UI_MAT4_H_
19
20#include <ui/mat3.h>
21#include <ui/quat.h>
22#include <ui/TMatHelpers.h>
23#include <ui/vec3.h>
24#include <ui/vec4.h>
Mathias Agopian595ea772013-08-21 23:10:41 -070025
26#include <stdint.h>
27#include <sys/types.h>
Romain Guy5d4bae72016-11-08 09:49:25 -080028#include <limits>
Mathias Agopian595ea772013-08-21 23:10:41 -070029
30#define PURE __attribute__((pure))
31
32namespace android {
33// -------------------------------------------------------------------------------------
Romain Guy5d4bae72016-11-08 09:49:25 -080034namespace details {
Mathias Agopian595ea772013-08-21 23:10:41 -070035
Romain Guy5d4bae72016-11-08 09:49:25 -080036template<typename T>
37class TQuaternion;
38
39/**
40 * A 4x4 column-major matrix class.
41 *
42 * Conceptually a 4x4 matrix is a an array of 4 column double4:
43 *
44 * mat4 m =
45 * \f$
46 * \left(
47 * \begin{array}{cccc}
48 * m[0] & m[1] & m[2] & m[3] \\
49 * \end{array}
50 * \right)
51 * \f$
52 * =
53 * \f$
54 * \left(
55 * \begin{array}{cccc}
56 * m[0][0] & m[1][0] & m[2][0] & m[3][0] \\
57 * m[0][1] & m[1][1] & m[2][1] & m[3][1] \\
58 * m[0][2] & m[1][2] & m[2][2] & m[3][2] \\
59 * m[0][3] & m[1][3] & m[2][3] & m[3][3] \\
60 * \end{array}
61 * \right)
62 * \f$
63 * =
64 * \f$
65 * \left(
66 * \begin{array}{cccc}
67 * m(0,0) & m(0,1) & m(0,2) & m(0,3) \\
68 * m(1,0) & m(1,1) & m(1,2) & m(1,3) \\
69 * m(2,0) & m(2,1) & m(2,2) & m(2,3) \\
70 * m(3,0) & m(3,1) & m(3,2) & m(3,3) \\
71 * \end{array}
72 * \right)
73 * \f$
74 *
75 * m[n] is the \f$ n^{th} \f$ column of the matrix and is a double4.
76 *
77 */
Mathias Agopian595ea772013-08-21 23:10:41 -070078template <typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -080079class TMat44 : public TVecUnaryOperators<TMat44, T>,
80 public TVecComparisonOperators<TMat44, T>,
81 public TVecAddOperators<TMat44, T>,
82 public TMatProductOperators<TMat44, T>,
83 public TMatSquareFunctions<TMat44, T>,
84 public TMatTransform<TMat44, T>,
85 public TMatHelpers<TMat44, T>,
86 public TMatDebug<TMat44, T> {
Mathias Agopian595ea772013-08-21 23:10:41 -070087public:
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;
Romain Guy5d4bae72016-11-08 09:49:25 -080093 typedef TVec4<T> col_type;
94 typedef TVec4<T> row_type;
Mathias Agopian595ea772013-08-21 23:10:41 -070095
Romain Guy5d4bae72016-11-08 09:49:25 -080096 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;
Mathias Agopian595ea772013-08-21 23:10:41 -0700100
101private:
Mathias Agopian595ea772013-08-21 23:10:41 -0700102 /*
103 * <-- N columns -->
104 *
Romain Guy5d4bae72016-11-08 09:49:25 -0800105 * 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
Mathias Agopian595ea772013-08-21 23:10:41 -0700110 *
111 * COL_SIZE = M
112 * ROW_SIZE = N
Romain Guy5d4bae72016-11-08 09:49:25 -0800113 * m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
Mathias Agopian595ea772013-08-21 23:10:41 -0700114 */
115
Romain Guy5d4bae72016-11-08 09:49:25 -0800116 col_type m_value[NUM_COLS];
Mathias Agopian595ea772013-08-21 23:10:41 -0700117
118public:
119 // array access
Romain Guy5d4bae72016-11-08 09:49:25 -0800120 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 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700127
Romain Guy5d4bae72016-11-08 09:49:25 -0800128 inline col_type& operator[](size_t column) {
129 assert(column < NUM_COLS);
130 return m_value[column];
131 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700132
133 // -----------------------------------------------------------------------
Romain Guy5d4bae72016-11-08 09:49:25 -0800134 // we want the compiler generated versions for these...
135 TMat44(const TMat44&) = default;
136 ~TMat44() = default;
137 TMat44& operator = (const TMat44&) = default;
Mathias Agopian595ea772013-08-21 23:10:41 -0700138
139 /*
140 * constructors
141 */
142
143 // leaves object uninitialized. use with caution.
Romain Guy5d4bae72016-11-08 09:49:25 -0800144 explicit
145 constexpr TMat44(no_init)
146 : m_value{ col_type(col_type::NO_INIT),
147 col_type(col_type::NO_INIT),
148 col_type(col_type::NO_INIT),
149 col_type(col_type::NO_INIT) } {}
Mathias Agopian595ea772013-08-21 23:10:41 -0700150
Romain Guy5d4bae72016-11-08 09:49:25 -0800151 /** initialize to identity.
152 *
153 * \f$
154 * \left(
155 * \begin{array}{cccc}
156 * 1 & 0 & 0 & 0 \\
157 * 0 & 1 & 0 & 0 \\
158 * 0 & 0 & 1 & 0 \\
159 * 0 & 0 & 0 & 1 \\
160 * \end{array}
161 * \right)
162 * \f$
163 */
164 TMat44();
Mathias Agopian595ea772013-08-21 23:10:41 -0700165
Romain Guy5d4bae72016-11-08 09:49:25 -0800166 /** initialize to Identity*scalar.
167 *
168 * \f$
169 * \left(
170 * \begin{array}{cccc}
171 * v & 0 & 0 & 0 \\
172 * 0 & v & 0 & 0 \\
173 * 0 & 0 & v & 0 \\
174 * 0 & 0 & 0 & v \\
175 * \end{array}
176 * \right)
177 * \f$
178 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700179 template<typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800180 explicit TMat44(U v);
Mathias Agopian595ea772013-08-21 23:10:41 -0700181
Romain Guy5d4bae72016-11-08 09:49:25 -0800182 /** sets the diagonal to a vector.
183 *
184 * \f$
185 * \left(
186 * \begin{array}{cccc}
187 * v[0] & 0 & 0 & 0 \\
188 * 0 & v[1] & 0 & 0 \\
189 * 0 & 0 & v[2] & 0 \\
190 * 0 & 0 & 0 & v[3] \\
191 * \end{array}
192 * \right)
193 * \f$
194 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700195 template <typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800196 explicit TMat44(const TVec4<U>& v);
Mathias Agopian595ea772013-08-21 23:10:41 -0700197
198 // construct from another matrix of the same size
199 template <typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800200 explicit TMat44(const TMat44<U>& rhs);
Mathias Agopian595ea772013-08-21 23:10:41 -0700201
Romain Guy5d4bae72016-11-08 09:49:25 -0800202 /** construct from 4 column vectors.
203 *
204 * \f$
205 * \left(
206 * \begin{array}{cccc}
207 * v0 & v1 & v2 & v3 \\
208 * \end{array}
209 * \right)
210 * \f$
211 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700212 template <typename A, typename B, typename C, typename D>
Romain Guy5d4bae72016-11-08 09:49:25 -0800213 TMat44(const TVec4<A>& v0, const TVec4<B>& v1, const TVec4<C>& v2, const TVec4<D>& v3);
Mathias Agopian595ea772013-08-21 23:10:41 -0700214
Romain Guy5d4bae72016-11-08 09:49:25 -0800215 /** construct from 16 elements in column-major form.
216 *
217 * \f$
218 * \left(
219 * \begin{array}{cccc}
220 * m[0][0] & m[1][0] & m[2][0] & m[3][0] \\
221 * m[0][1] & m[1][1] & m[2][1] & m[3][1] \\
222 * m[0][2] & m[1][2] & m[2][2] & m[3][2] \\
223 * m[0][3] & m[1][3] & m[2][3] & m[3][3] \\
224 * \end{array}
225 * \right)
226 * \f$
227 */
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700228 template <
229 typename A, typename B, typename C, typename D,
230 typename E, typename F, typename G, typename H,
231 typename I, typename J, typename K, typename L,
232 typename M, typename N, typename O, typename P>
Romain Guy5d4bae72016-11-08 09:49:25 -0800233 TMat44(A m00, B m01, C m02, D m03,
234 E m10, F m11, G m12, H m13,
235 I m20, J m21, K m22, L m23,
236 M m30, N m31, O m32, P m33);
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700237
Romain Guy5d4bae72016-11-08 09:49:25 -0800238 /**
239 * construct from a quaternion
240 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700241 template <typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800242 explicit TMat44(const TQuaternion<U>& q);
243
244 /**
245 * construct from a C array in column major form.
246 */
247 template <typename U>
248 explicit TMat44(U const* rawArray);
249
250 /**
251 * construct from a 3x3 matrix
252 */
253 template <typename U>
254 explicit TMat44(const TMat33<U>& matrix);
255
256 /**
257 * construct from a 3x3 matrix and 3d translation
258 */
259 template <typename U, typename V>
260 TMat44(const TMat33<U>& matrix, const TVec3<V>& translation);
261
262 /**
263 * construct from a 3x3 matrix and 4d last column.
264 */
265 template <typename U, typename V>
266 TMat44(const TMat33<U>& matrix, const TVec4<V>& column3);
Mathias Agopian595ea772013-08-21 23:10:41 -0700267
268 /*
269 * helpers
270 */
271
Romain Guy5d4bae72016-11-08 09:49:25 -0800272 static TMat44 ortho(T left, T right, T bottom, T top, T near, T far);
Mathias Agopian595ea772013-08-21 23:10:41 -0700273
Romain Guy5d4bae72016-11-08 09:49:25 -0800274 static TMat44 frustum(T left, T right, T bottom, T top, T near, T far);
275
276 enum class Fov {
277 HORIZONTAL,
278 VERTICAL
279 };
280 static TMat44 perspective(T fov, T aspect, T near, T far, Fov direction = Fov::VERTICAL);
Mathias Agopian595ea772013-08-21 23:10:41 -0700281
282 template <typename A, typename B, typename C>
Romain Guy5d4bae72016-11-08 09:49:25 -0800283 static TMat44 lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up);
Mathias Agopian595ea772013-08-21 23:10:41 -0700284
285 template <typename A>
Romain Guy5d4bae72016-11-08 09:49:25 -0800286 static TVec3<A> project(const TMat44& projectionMatrix, TVec3<A> vertice) {
287 TVec4<A> r = projectionMatrix * TVec4<A>{ vertice, 1 };
288 return r.xyz / r.w;
289 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700290
291 template <typename A>
Romain Guy5d4bae72016-11-08 09:49:25 -0800292 static TVec4<A> project(const TMat44& projectionMatrix, TVec4<A> vertice) {
293 vertice = projectionMatrix * vertice;
294 return { vertice.xyz / vertice.w, 1 };
295 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700296
Romain Guy5d4bae72016-11-08 09:49:25 -0800297 /**
298 * Constructs a 3x3 matrix from the upper-left corner of this 4x4 matrix
299 */
300 inline constexpr TMat33<T> upperLeft() const {
301 return TMat33<T>(m_value[0].xyz, m_value[1].xyz, m_value[2].xyz);
302 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700303};
304
305// ----------------------------------------------------------------------------------------
306// Constructors
307// ----------------------------------------------------------------------------------------
308
Romain Guy5d4bae72016-11-08 09:49:25 -0800309// Since the matrix code could become pretty big quickly, we don't inline most
310// operations.
Mathias Agopian595ea772013-08-21 23:10:41 -0700311
312template <typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -0800313TMat44<T>::TMat44() {
314 m_value[0] = col_type(1, 0, 0, 0);
315 m_value[1] = col_type(0, 1, 0, 0);
316 m_value[2] = col_type(0, 0, 1, 0);
317 m_value[3] = col_type(0, 0, 0, 1);
Mathias Agopian595ea772013-08-21 23:10:41 -0700318}
319
320template <typename T>
321template <typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800322TMat44<T>::TMat44(U v) {
323 m_value[0] = col_type(v, 0, 0, 0);
324 m_value[1] = col_type(0, v, 0, 0);
325 m_value[2] = col_type(0, 0, v, 0);
326 m_value[3] = col_type(0, 0, 0, v);
Mathias Agopian595ea772013-08-21 23:10:41 -0700327}
328
329template<typename T>
330template<typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800331TMat44<T>::TMat44(const TVec4<U>& v) {
332 m_value[0] = col_type(v.x, 0, 0, 0);
333 m_value[1] = col_type(0, v.y, 0, 0);
334 m_value[2] = col_type(0, 0, v.z, 0);
335 m_value[3] = col_type(0, 0, 0, v.w);
Mathias Agopian595ea772013-08-21 23:10:41 -0700336}
337
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700338// construct from 16 scalars
339template<typename T>
340template <
341 typename A, typename B, typename C, typename D,
342 typename E, typename F, typename G, typename H,
343 typename I, typename J, typename K, typename L,
344 typename M, typename N, typename O, typename P>
Romain Guy5d4bae72016-11-08 09:49:25 -0800345TMat44<T>::TMat44(A m00, B m01, C m02, D m03,
346 E m10, F m11, G m12, H m13,
347 I m20, J m21, K m22, L m23,
348 M m30, N m31, O m32, P m33) {
349 m_value[0] = col_type(m00, m01, m02, m03);
350 m_value[1] = col_type(m10, m11, m12, m13);
351 m_value[2] = col_type(m20, m21, m22, m23);
352 m_value[3] = col_type(m30, m31, m32, m33);
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700353}
354
Mathias Agopian595ea772013-08-21 23:10:41 -0700355template <typename T>
356template <typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800357TMat44<T>::TMat44(const TMat44<U>& rhs) {
358 for (size_t col = 0; col < NUM_COLS; ++col) {
359 m_value[col] = col_type(rhs[col]);
360 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700361}
362
Romain Guy5d4bae72016-11-08 09:49:25 -0800363// Construct from 4 column vectors.
Mathias Agopian595ea772013-08-21 23:10:41 -0700364template <typename T>
365template <typename A, typename B, typename C, typename D>
Romain Guy5d4bae72016-11-08 09:49:25 -0800366TMat44<T>::TMat44(const TVec4<A>& v0, const TVec4<B>& v1, const TVec4<C>& v2, const TVec4<D>& v3) {
367 m_value[0] = col_type(v0);
368 m_value[1] = col_type(v1);
369 m_value[2] = col_type(v2);
370 m_value[3] = col_type(v3);
371}
372
373// Construct from raw array, in column-major form.
374template <typename T>
375template <typename U>
376TMat44<T>::TMat44(U const* rawArray) {
377 for (size_t col = 0; col < NUM_COLS; ++col) {
378 for (size_t row = 0; row < NUM_ROWS; ++row) {
379 m_value[col][row] = *rawArray++;
380 }
381 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700382}
383
384template <typename T>
385template <typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800386TMat44<T>::TMat44(const TQuaternion<U>& q) {
387 const U n = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
388 const U s = n > 0 ? 2/n : 0;
389 const U x = s*q.x;
390 const U y = s*q.y;
391 const U z = s*q.z;
392 const U xx = x*q.x;
393 const U xy = x*q.y;
394 const U xz = x*q.z;
395 const U xw = x*q.w;
396 const U yy = y*q.y;
397 const U yz = y*q.z;
398 const U yw = y*q.w;
399 const U zz = z*q.z;
400 const U zw = z*q.w;
401 m_value[0] = col_type(1-yy-zz, xy+zw, xz-yw, 0);
402 m_value[1] = col_type( xy-zw, 1-xx-zz, yz+xw, 0); // NOLINT
403 m_value[2] = col_type( xz+yw, yz-xw, 1-xx-yy, 0); // NOLINT
404 m_value[3] = col_type( 0, 0, 0, 1); // NOLINT
405}
406
407template <typename T>
408template <typename U>
409TMat44<T>::TMat44(const TMat33<U>& m) {
410 m_value[0] = col_type(m[0][0], m[0][1], m[0][2], 0);
411 m_value[1] = col_type(m[1][0], m[1][1], m[1][2], 0);
412 m_value[2] = col_type(m[2][0], m[2][1], m[2][2], 0);
413 m_value[3] = col_type( 0, 0, 0, 1); // NOLINT
414}
415
416template <typename T>
417template <typename U, typename V>
418TMat44<T>::TMat44(const TMat33<U>& m, const TVec3<V>& v) {
419 m_value[0] = col_type(m[0][0], m[0][1], m[0][2], 0);
420 m_value[1] = col_type(m[1][0], m[1][1], m[1][2], 0);
421 m_value[2] = col_type(m[2][0], m[2][1], m[2][2], 0);
422 m_value[3] = col_type( v[0], v[1], v[2], 1); // NOLINT
423}
424
425template <typename T>
426template <typename U, typename V>
427TMat44<T>::TMat44(const TMat33<U>& m, const TVec4<V>& v) {
428 m_value[0] = col_type(m[0][0], m[0][1], m[0][2], 0); // NOLINT
429 m_value[1] = col_type(m[1][0], m[1][1], m[1][2], 0); // NOLINT
430 m_value[2] = col_type(m[2][0], m[2][1], m[2][2], 0); // NOLINT
431 m_value[3] = col_type( v[0], v[1], v[2], v[3]); // NOLINT
Mathias Agopian595ea772013-08-21 23:10:41 -0700432}
433
434// ----------------------------------------------------------------------------------------
435// Helpers
436// ----------------------------------------------------------------------------------------
437
438template <typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -0800439TMat44<T> TMat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) {
440 TMat44<T> m;
Mathias Agopian595ea772013-08-21 23:10:41 -0700441 m[0][0] = 2 / (right - left);
442 m[1][1] = 2 / (top - bottom);
443 m[2][2] = -2 / (far - near);
444 m[3][0] = -(right + left) / (right - left);
445 m[3][1] = -(top + bottom) / (top - bottom);
446 m[3][2] = -(far + near) / (far - near);
447 return m;
448}
449
450template <typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -0800451TMat44<T> TMat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) {
452 TMat44<T> m;
453 m[0][0] = (2 * near) / (right - left);
454 m[1][1] = (2 * near) / (top - bottom);
455 m[2][0] = (right + left) / (right - left);
456 m[2][1] = (top + bottom) / (top - bottom);
457 m[2][2] = -(far + near) / (far - near);
458 m[2][3] = -1;
459 m[3][2] = -(2 * far * near) / (far - near);
460 m[3][3] = 0;
Mathias Agopian595ea772013-08-21 23:10:41 -0700461 return m;
462}
463
464template <typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -0800465TMat44<T> TMat44<T>::perspective(T fov, T aspect, T near, T far, TMat44::Fov direction) {
466 T h;
467 T w;
Mathias Agopian595ea772013-08-21 23:10:41 -0700468
Romain Guy5d4bae72016-11-08 09:49:25 -0800469 if (direction == TMat44::Fov::VERTICAL) {
470 h = std::tan(fov * M_PI / 360.0f) * near;
471 w = h * aspect;
Mathias Agopian595ea772013-08-21 23:10:41 -0700472 } else {
Romain Guy5d4bae72016-11-08 09:49:25 -0800473 w = std::tan(fov * M_PI / 360.0f) * near;
474 h = w / aspect;
Mathias Agopian595ea772013-08-21 23:10:41 -0700475 }
Romain Guy5d4bae72016-11-08 09:49:25 -0800476 return frustum(-w, w, -h, h, near, far);
477}
478
479/*
480 * Returns a matrix representing the pose of a virtual camera looking towards -Z in its
481 * local Y-up coordinate system. "eye" is where the camera is located, "center" is the points its
482 * looking at and "up" defines where the Y axis of the camera's local coordinate system is.
483 */
484template <typename T>
485template <typename A, typename B, typename C>
486TMat44<T> TMat44<T>::lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up) {
487 TVec3<T> z_axis(normalize(center - eye));
488 TVec3<T> norm_up(normalize(up));
489 if (std::abs(dot(z_axis, norm_up)) > 0.999) {
490 // Fix up vector if we're degenerate (looking straight up, basically)
491 norm_up = { norm_up.z, norm_up.x, norm_up.y };
492 }
493 TVec3<T> x_axis(normalize(cross(z_axis, norm_up)));
494 TVec3<T> y_axis(cross(x_axis, z_axis));
495 return TMat44<T>(
496 TVec4<T>(x_axis, 0),
497 TVec4<T>(y_axis, 0),
498 TVec4<T>(-z_axis, 0),
499 TVec4<T>(eye, 1));
Mathias Agopian595ea772013-08-21 23:10:41 -0700500}
501
502// ----------------------------------------------------------------------------------------
Mathias Agopian595ea772013-08-21 23:10:41 -0700503// Arithmetic operators outside of class
504// ----------------------------------------------------------------------------------------
505
506/* We use non-friend functions here to prevent the compiler from using
507 * implicit conversions, for instance of a scalar to a vector. The result would
508 * not be what the caller expects.
509 *
510 * Also note that the order of the arguments in the inner loop is important since
511 * it determines the output type (only relevant when T != U).
512 */
513
Romain Guy5d4bae72016-11-08 09:49:25 -0800514// matrix * column-vector, result is a vector of the same type than the input vector
Mathias Agopian595ea772013-08-21 23:10:41 -0700515template <typename T, typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800516typename TMat44<T>::col_type PURE operator *(const TMat44<T>& lhs, const TVec4<U>& rhs) {
517 // Result is initialized to zero.
518 typename TMat44<T>::col_type result;
519 for (size_t col = 0; col < TMat44<T>::NUM_COLS; ++col) {
520 result += lhs[col] * rhs[col];
521 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700522 return result;
523}
524
Romain Guy5d4bae72016-11-08 09:49:25 -0800525// mat44 * vec3, result is vec3( mat44 * {vec3, 1} )
Mathias Agopian595ea772013-08-21 23:10:41 -0700526template <typename T, typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800527typename TMat44<T>::col_type PURE operator *(const TMat44<T>& lhs, const TVec3<U>& rhs) {
528 return lhs * TVec4<U>{ rhs, 1 };
529}
530
531
532// row-vector * matrix, result is a vector of the same type than the input vector
533template <typename T, typename U>
534typename TMat44<U>::row_type PURE operator *(const TVec4<U>& lhs, const TMat44<T>& rhs) {
535 typename TMat44<U>::row_type result(TMat44<U>::row_type::NO_INIT);
536 for (size_t col = 0; col < TMat44<T>::NUM_COLS; ++col) {
537 result[col] = dot(lhs, rhs[col]);
538 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700539 return result;
540}
541
542// matrix * scalar, result is a matrix of the same type than the input matrix
543template <typename T, typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800544constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat44<T>>::type PURE
545operator *(TMat44<T> lhs, U rhs) {
546 return lhs *= rhs;
Mathias Agopian595ea772013-08-21 23:10:41 -0700547}
548
549// scalar * matrix, result is a matrix of the same type than the input matrix
550template <typename T, typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800551constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat44<T>>::type PURE
552operator *(U lhs, const TMat44<T>& rhs) {
553 return rhs * lhs;
Mathias Agopian595ea772013-08-21 23:10:41 -0700554}
555
Mathias Agopian595ea772013-08-21 23:10:41 -0700556// ----------------------------------------------------------------------------------------
557
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700558/* FIXME: this should go into TMatSquareFunctions<> but for some reason
559 * BASE<T>::col_type is not accessible from there (???)
560 */
561template<typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -0800562typename TMat44<T>::col_type PURE diag(const TMat44<T>& m) {
Mathias Agopian595ea772013-08-21 23:10:41 -0700563 return matrix::diag(m);
564}
565
Romain Guy5d4bae72016-11-08 09:49:25 -0800566} // namespace details
Mathias Agopian595ea772013-08-21 23:10:41 -0700567
568// ----------------------------------------------------------------------------------------
Romain Guy5d4bae72016-11-08 09:49:25 -0800569
570typedef details::TMat44<double> mat4d;
571typedef details::TMat44<float> mat4;
572typedef details::TMat44<float> mat4f;
573
574// ----------------------------------------------------------------------------------------
575} // namespace android
Mathias Agopian595ea772013-08-21 23:10:41 -0700576
577#undef PURE
578
Romain Guy5d4bae72016-11-08 09:49:25 -0800579#endif // UI_MAT4_H_