blob: f63d40aa6a7b27d8cce8b317b438c2782aad6111 [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
Romain Guycaf2ca42016-11-10 11:45:58 -080032#if __cplusplus >= 201402L
33#define CONSTEXPR constexpr
34#else
35#define CONSTEXPR
36#endif
37
Mathias Agopian595ea772013-08-21 23:10:41 -070038namespace android {
39// -------------------------------------------------------------------------------------
Romain Guy5d4bae72016-11-08 09:49:25 -080040namespace details {
Mathias Agopian595ea772013-08-21 23:10:41 -070041
Romain Guy5d4bae72016-11-08 09:49:25 -080042template<typename T>
43class TQuaternion;
44
45/**
46 * A 4x4 column-major matrix class.
47 *
48 * Conceptually a 4x4 matrix is a an array of 4 column double4:
49 *
50 * mat4 m =
51 * \f$
52 * \left(
53 * \begin{array}{cccc}
54 * m[0] & m[1] & m[2] & m[3] \\
55 * \end{array}
56 * \right)
57 * \f$
58 * =
59 * \f$
60 * \left(
61 * \begin{array}{cccc}
62 * m[0][0] & m[1][0] & m[2][0] & m[3][0] \\
63 * m[0][1] & m[1][1] & m[2][1] & m[3][1] \\
64 * m[0][2] & m[1][2] & m[2][2] & m[3][2] \\
65 * m[0][3] & m[1][3] & m[2][3] & m[3][3] \\
66 * \end{array}
67 * \right)
68 * \f$
69 * =
70 * \f$
71 * \left(
72 * \begin{array}{cccc}
73 * m(0,0) & m(0,1) & m(0,2) & m(0,3) \\
74 * m(1,0) & m(1,1) & m(1,2) & m(1,3) \\
75 * m(2,0) & m(2,1) & m(2,2) & m(2,3) \\
76 * m(3,0) & m(3,1) & m(3,2) & m(3,3) \\
77 * \end{array}
78 * \right)
79 * \f$
80 *
81 * m[n] is the \f$ n^{th} \f$ column of the matrix and is a double4.
82 *
83 */
Mathias Agopian595ea772013-08-21 23:10:41 -070084template <typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -080085class TMat44 : public TVecUnaryOperators<TMat44, T>,
86 public TVecComparisonOperators<TMat44, T>,
87 public TVecAddOperators<TMat44, T>,
88 public TMatProductOperators<TMat44, T>,
89 public TMatSquareFunctions<TMat44, T>,
90 public TMatTransform<TMat44, T>,
91 public TMatHelpers<TMat44, T>,
92 public TMatDebug<TMat44, T> {
Mathias Agopian595ea772013-08-21 23:10:41 -070093public:
94 enum no_init { NO_INIT };
95 typedef T value_type;
96 typedef T& reference;
97 typedef T const& const_reference;
98 typedef size_t size_type;
Romain Guy5d4bae72016-11-08 09:49:25 -080099 typedef TVec4<T> col_type;
100 typedef TVec4<T> row_type;
Mathias Agopian595ea772013-08-21 23:10:41 -0700101
Romain Guy5d4bae72016-11-08 09:49:25 -0800102 static constexpr size_t COL_SIZE = col_type::SIZE; // size of a column (i.e.: number of rows)
103 static constexpr size_t ROW_SIZE = row_type::SIZE; // size of a row (i.e.: number of columns)
104 static constexpr size_t NUM_ROWS = COL_SIZE;
105 static constexpr size_t NUM_COLS = ROW_SIZE;
Mathias Agopian595ea772013-08-21 23:10:41 -0700106
107private:
Mathias Agopian595ea772013-08-21 23:10:41 -0700108 /*
109 * <-- N columns -->
110 *
Romain Guy5d4bae72016-11-08 09:49:25 -0800111 * a[0][0] a[1][0] a[2][0] ... a[N][0] ^
112 * a[0][1] a[1][1] a[2][1] ... a[N][1] |
113 * a[0][2] a[1][2] a[2][2] ... a[N][2] M rows
114 * ... |
115 * a[0][M] a[1][M] a[2][M] ... a[N][M] v
Mathias Agopian595ea772013-08-21 23:10:41 -0700116 *
117 * COL_SIZE = M
118 * ROW_SIZE = N
Romain Guy5d4bae72016-11-08 09:49:25 -0800119 * m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
Mathias Agopian595ea772013-08-21 23:10:41 -0700120 */
121
Romain Guy5d4bae72016-11-08 09:49:25 -0800122 col_type m_value[NUM_COLS];
Mathias Agopian595ea772013-08-21 23:10:41 -0700123
124public:
125 // array access
Romain Guy5d4bae72016-11-08 09:49:25 -0800126 inline constexpr col_type const& operator[](size_t column) const {
127#if __cplusplus >= 201402L
128 // only possible in C++0x14 with constexpr
129 assert(column < NUM_COLS);
130#endif
131 return m_value[column];
132 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700133
Romain Guy5d4bae72016-11-08 09:49:25 -0800134 inline col_type& operator[](size_t column) {
135 assert(column < NUM_COLS);
136 return m_value[column];
137 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700138
139 // -----------------------------------------------------------------------
Romain Guy5d4bae72016-11-08 09:49:25 -0800140 // we want the compiler generated versions for these...
141 TMat44(const TMat44&) = default;
142 ~TMat44() = default;
143 TMat44& operator = (const TMat44&) = default;
Mathias Agopian595ea772013-08-21 23:10:41 -0700144
145 /*
146 * constructors
147 */
148
149 // leaves object uninitialized. use with caution.
Romain Guycaf2ca42016-11-10 11:45:58 -0800150 explicit constexpr TMat44(no_init)
Romain Guy5d4bae72016-11-08 09:49:25 -0800151 : m_value{ col_type(col_type::NO_INIT),
152 col_type(col_type::NO_INIT),
153 col_type(col_type::NO_INIT),
154 col_type(col_type::NO_INIT) } {}
Mathias Agopian595ea772013-08-21 23:10:41 -0700155
Romain Guy5d4bae72016-11-08 09:49:25 -0800156 /** initialize to identity.
157 *
158 * \f$
159 * \left(
160 * \begin{array}{cccc}
161 * 1 & 0 & 0 & 0 \\
162 * 0 & 1 & 0 & 0 \\
163 * 0 & 0 & 1 & 0 \\
164 * 0 & 0 & 0 & 1 \\
165 * \end{array}
166 * \right)
167 * \f$
168 */
Romain Guycaf2ca42016-11-10 11:45:58 -0800169 CONSTEXPR TMat44();
Mathias Agopian595ea772013-08-21 23:10:41 -0700170
Romain Guy5d4bae72016-11-08 09:49:25 -0800171 /** initialize to Identity*scalar.
172 *
173 * \f$
174 * \left(
175 * \begin{array}{cccc}
176 * v & 0 & 0 & 0 \\
177 * 0 & v & 0 & 0 \\
178 * 0 & 0 & v & 0 \\
179 * 0 & 0 & 0 & v \\
180 * \end{array}
181 * \right)
182 * \f$
183 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700184 template<typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800185 explicit CONSTEXPR TMat44(U v);
Mathias Agopian595ea772013-08-21 23:10:41 -0700186
Romain Guy5d4bae72016-11-08 09:49:25 -0800187 /** sets the diagonal to a vector.
188 *
189 * \f$
190 * \left(
191 * \begin{array}{cccc}
192 * v[0] & 0 & 0 & 0 \\
193 * 0 & v[1] & 0 & 0 \\
194 * 0 & 0 & v[2] & 0 \\
195 * 0 & 0 & 0 & v[3] \\
196 * \end{array}
197 * \right)
198 * \f$
199 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700200 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800201 explicit CONSTEXPR TMat44(const TVec4<U>& v);
Mathias Agopian595ea772013-08-21 23:10:41 -0700202
203 // construct from another matrix of the same size
204 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800205 explicit CONSTEXPR TMat44(const TMat44<U>& rhs);
Mathias Agopian595ea772013-08-21 23:10:41 -0700206
Romain Guy5d4bae72016-11-08 09:49:25 -0800207 /** construct from 4 column vectors.
208 *
209 * \f$
210 * \left(
211 * \begin{array}{cccc}
212 * v0 & v1 & v2 & v3 \\
213 * \end{array}
214 * \right)
215 * \f$
216 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700217 template <typename A, typename B, typename C, typename D>
Romain Guycaf2ca42016-11-10 11:45:58 -0800218 CONSTEXPR TMat44(const TVec4<A>& v0, const TVec4<B>& v1, const TVec4<C>& v2, const TVec4<D>& v3);
Mathias Agopian595ea772013-08-21 23:10:41 -0700219
Romain Guy5d4bae72016-11-08 09:49:25 -0800220 /** construct from 16 elements in column-major form.
221 *
222 * \f$
223 * \left(
224 * \begin{array}{cccc}
225 * m[0][0] & m[1][0] & m[2][0] & m[3][0] \\
226 * m[0][1] & m[1][1] & m[2][1] & m[3][1] \\
227 * m[0][2] & m[1][2] & m[2][2] & m[3][2] \\
228 * m[0][3] & m[1][3] & m[2][3] & m[3][3] \\
229 * \end{array}
230 * \right)
231 * \f$
232 */
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700233 template <
234 typename A, typename B, typename C, typename D,
235 typename E, typename F, typename G, typename H,
236 typename I, typename J, typename K, typename L,
237 typename M, typename N, typename O, typename P>
Romain Guycaf2ca42016-11-10 11:45:58 -0800238 CONSTEXPR TMat44(
239 A m00, B m01, C m02, D m03,
240 E m10, F m11, G m12, H m13,
241 I m20, J m21, K m22, L m23,
242 M m30, N m31, O m32, P m33);
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700243
Romain Guy5d4bae72016-11-08 09:49:25 -0800244 /**
245 * construct from a quaternion
246 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700247 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800248 explicit CONSTEXPR TMat44(const TQuaternion<U>& q);
Romain Guy5d4bae72016-11-08 09:49:25 -0800249
250 /**
251 * construct from a C array in column major form.
252 */
253 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800254 explicit CONSTEXPR TMat44(U const* rawArray);
Romain Guy5d4bae72016-11-08 09:49:25 -0800255
256 /**
257 * construct from a 3x3 matrix
258 */
259 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800260 explicit CONSTEXPR TMat44(const TMat33<U>& matrix);
Romain Guy5d4bae72016-11-08 09:49:25 -0800261
262 /**
263 * construct from a 3x3 matrix and 3d translation
264 */
265 template <typename U, typename V>
Romain Guycaf2ca42016-11-10 11:45:58 -0800266 CONSTEXPR TMat44(const TMat33<U>& matrix, const TVec3<V>& translation);
Romain Guy5d4bae72016-11-08 09:49:25 -0800267
268 /**
269 * construct from a 3x3 matrix and 4d last column.
270 */
271 template <typename U, typename V>
Romain Guycaf2ca42016-11-10 11:45:58 -0800272 CONSTEXPR TMat44(const TMat33<U>& matrix, const TVec4<V>& column3);
Mathias Agopian595ea772013-08-21 23:10:41 -0700273
274 /*
275 * helpers
276 */
277
Romain Guycaf2ca42016-11-10 11:45:58 -0800278 static CONSTEXPR TMat44 ortho(T left, T right, T bottom, T top, T near, T far);
Mathias Agopian595ea772013-08-21 23:10:41 -0700279
Romain Guycaf2ca42016-11-10 11:45:58 -0800280 static CONSTEXPR TMat44 frustum(T left, T right, T bottom, T top, T near, T far);
Romain Guy5d4bae72016-11-08 09:49:25 -0800281
282 enum class Fov {
283 HORIZONTAL,
284 VERTICAL
285 };
Romain Guycaf2ca42016-11-10 11:45:58 -0800286 static CONSTEXPR TMat44 perspective(T fov, T aspect, T near, T far, Fov direction = Fov::VERTICAL);
Mathias Agopian595ea772013-08-21 23:10:41 -0700287
288 template <typename A, typename B, typename C>
Romain Guycaf2ca42016-11-10 11:45:58 -0800289 static CONSTEXPR TMat44 lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up);
Mathias Agopian595ea772013-08-21 23:10:41 -0700290
291 template <typename A>
Romain Guycaf2ca42016-11-10 11:45:58 -0800292 static CONSTEXPR TVec3<A> project(const TMat44& projectionMatrix, TVec3<A> vertice) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800293 TVec4<A> r = projectionMatrix * TVec4<A>{ vertice, 1 };
294 return r.xyz / r.w;
295 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700296
297 template <typename A>
Romain Guycaf2ca42016-11-10 11:45:58 -0800298 static CONSTEXPR TVec4<A> project(const TMat44& projectionMatrix, TVec4<A> vertice) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800299 vertice = projectionMatrix * vertice;
300 return { vertice.xyz / vertice.w, 1 };
301 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700302
Romain Guy5d4bae72016-11-08 09:49:25 -0800303 /**
304 * Constructs a 3x3 matrix from the upper-left corner of this 4x4 matrix
305 */
306 inline constexpr TMat33<T> upperLeft() const {
307 return TMat33<T>(m_value[0].xyz, m_value[1].xyz, m_value[2].xyz);
308 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700309};
310
311// ----------------------------------------------------------------------------------------
312// Constructors
313// ----------------------------------------------------------------------------------------
314
Romain Guy5d4bae72016-11-08 09:49:25 -0800315// Since the matrix code could become pretty big quickly, we don't inline most
316// operations.
Mathias Agopian595ea772013-08-21 23:10:41 -0700317
318template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800319CONSTEXPR TMat44<T>::TMat44() {
Romain Guy5d4bae72016-11-08 09:49:25 -0800320 m_value[0] = col_type(1, 0, 0, 0);
321 m_value[1] = col_type(0, 1, 0, 0);
322 m_value[2] = col_type(0, 0, 1, 0);
323 m_value[3] = col_type(0, 0, 0, 1);
Mathias Agopian595ea772013-08-21 23:10:41 -0700324}
325
326template <typename T>
327template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800328CONSTEXPR TMat44<T>::TMat44(U v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800329 m_value[0] = col_type(v, 0, 0, 0);
330 m_value[1] = col_type(0, v, 0, 0);
331 m_value[2] = col_type(0, 0, v, 0);
332 m_value[3] = col_type(0, 0, 0, v);
Mathias Agopian595ea772013-08-21 23:10:41 -0700333}
334
335template<typename T>
336template<typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800337CONSTEXPR TMat44<T>::TMat44(const TVec4<U>& v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800338 m_value[0] = col_type(v.x, 0, 0, 0);
339 m_value[1] = col_type(0, v.y, 0, 0);
340 m_value[2] = col_type(0, 0, v.z, 0);
341 m_value[3] = col_type(0, 0, 0, v.w);
Mathias Agopian595ea772013-08-21 23:10:41 -0700342}
343
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700344// construct from 16 scalars
345template<typename T>
346template <
347 typename A, typename B, typename C, typename D,
348 typename E, typename F, typename G, typename H,
349 typename I, typename J, typename K, typename L,
350 typename M, typename N, typename O, typename P>
Romain Guycaf2ca42016-11-10 11:45:58 -0800351CONSTEXPR TMat44<T>::TMat44(
352 A m00, B m01, C m02, D m03,
353 E m10, F m11, G m12, H m13,
354 I m20, J m21, K m22, L m23,
355 M m30, N m31, O m32, P m33) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800356 m_value[0] = col_type(m00, m01, m02, m03);
357 m_value[1] = col_type(m10, m11, m12, m13);
358 m_value[2] = col_type(m20, m21, m22, m23);
359 m_value[3] = col_type(m30, m31, m32, m33);
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700360}
361
Mathias Agopian595ea772013-08-21 23:10:41 -0700362template <typename T>
363template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800364CONSTEXPR TMat44<T>::TMat44(const TMat44<U>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800365 for (size_t col = 0; col < NUM_COLS; ++col) {
366 m_value[col] = col_type(rhs[col]);
367 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700368}
369
Romain Guy5d4bae72016-11-08 09:49:25 -0800370// Construct from 4 column vectors.
Mathias Agopian595ea772013-08-21 23:10:41 -0700371template <typename T>
372template <typename A, typename B, typename C, typename D>
Romain Guycaf2ca42016-11-10 11:45:58 -0800373CONSTEXPR TMat44<T>::TMat44(
374 const TVec4<A>& v0, const TVec4<B>& v1,
375 const TVec4<C>& v2, const TVec4<D>& v3) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800376 m_value[0] = col_type(v0);
377 m_value[1] = col_type(v1);
378 m_value[2] = col_type(v2);
379 m_value[3] = col_type(v3);
380}
381
382// Construct from raw array, in column-major form.
383template <typename T>
384template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800385CONSTEXPR TMat44<T>::TMat44(U const* rawArray) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800386 for (size_t col = 0; col < NUM_COLS; ++col) {
387 for (size_t row = 0; row < NUM_ROWS; ++row) {
388 m_value[col][row] = *rawArray++;
389 }
390 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700391}
392
393template <typename T>
394template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800395CONSTEXPR TMat44<T>::TMat44(const TQuaternion<U>& q) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800396 const U n = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
397 const U s = n > 0 ? 2/n : 0;
398 const U x = s*q.x;
399 const U y = s*q.y;
400 const U z = s*q.z;
401 const U xx = x*q.x;
402 const U xy = x*q.y;
403 const U xz = x*q.z;
404 const U xw = x*q.w;
405 const U yy = y*q.y;
406 const U yz = y*q.z;
407 const U yw = y*q.w;
408 const U zz = z*q.z;
409 const U zw = z*q.w;
410 m_value[0] = col_type(1-yy-zz, xy+zw, xz-yw, 0);
411 m_value[1] = col_type( xy-zw, 1-xx-zz, yz+xw, 0); // NOLINT
412 m_value[2] = col_type( xz+yw, yz-xw, 1-xx-yy, 0); // NOLINT
413 m_value[3] = col_type( 0, 0, 0, 1); // NOLINT
414}
415
416template <typename T>
417template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800418CONSTEXPR TMat44<T>::TMat44(const TMat33<U>& m) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800419 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( 0, 0, 0, 1); // NOLINT
423}
424
425template <typename T>
426template <typename U, typename V>
Romain Guycaf2ca42016-11-10 11:45:58 -0800427CONSTEXPR TMat44<T>::TMat44(const TMat33<U>& m, const TVec3<V>& v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800428 m_value[0] = col_type(m[0][0], m[0][1], m[0][2], 0);
429 m_value[1] = col_type(m[1][0], m[1][1], m[1][2], 0);
430 m_value[2] = col_type(m[2][0], m[2][1], m[2][2], 0);
431 m_value[3] = col_type( v[0], v[1], v[2], 1); // NOLINT
432}
433
434template <typename T>
435template <typename U, typename V>
Romain Guycaf2ca42016-11-10 11:45:58 -0800436CONSTEXPR TMat44<T>::TMat44(const TMat33<U>& m, const TVec4<V>& v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800437 m_value[0] = col_type(m[0][0], m[0][1], m[0][2], 0); // NOLINT
438 m_value[1] = col_type(m[1][0], m[1][1], m[1][2], 0); // NOLINT
439 m_value[2] = col_type(m[2][0], m[2][1], m[2][2], 0); // NOLINT
440 m_value[3] = col_type( v[0], v[1], v[2], v[3]); // NOLINT
Mathias Agopian595ea772013-08-21 23:10:41 -0700441}
442
443// ----------------------------------------------------------------------------------------
444// Helpers
445// ----------------------------------------------------------------------------------------
446
447template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800448CONSTEXPR TMat44<T> TMat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800449 TMat44<T> m;
Mathias Agopian595ea772013-08-21 23:10:41 -0700450 m[0][0] = 2 / (right - left);
451 m[1][1] = 2 / (top - bottom);
452 m[2][2] = -2 / (far - near);
453 m[3][0] = -(right + left) / (right - left);
454 m[3][1] = -(top + bottom) / (top - bottom);
455 m[3][2] = -(far + near) / (far - near);
456 return m;
457}
458
459template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800460CONSTEXPR TMat44<T> TMat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800461 TMat44<T> m;
462 m[0][0] = (2 * near) / (right - left);
463 m[1][1] = (2 * near) / (top - bottom);
464 m[2][0] = (right + left) / (right - left);
465 m[2][1] = (top + bottom) / (top - bottom);
466 m[2][2] = -(far + near) / (far - near);
467 m[2][3] = -1;
468 m[3][2] = -(2 * far * near) / (far - near);
469 m[3][3] = 0;
Mathias Agopian595ea772013-08-21 23:10:41 -0700470 return m;
471}
472
473template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800474CONSTEXPR TMat44<T> TMat44<T>::perspective(T fov, T aspect, T near, T far, TMat44::Fov direction) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800475 T h;
476 T w;
Mathias Agopian595ea772013-08-21 23:10:41 -0700477
Romain Guy5d4bae72016-11-08 09:49:25 -0800478 if (direction == TMat44::Fov::VERTICAL) {
479 h = std::tan(fov * M_PI / 360.0f) * near;
480 w = h * aspect;
Mathias Agopian595ea772013-08-21 23:10:41 -0700481 } else {
Romain Guy5d4bae72016-11-08 09:49:25 -0800482 w = std::tan(fov * M_PI / 360.0f) * near;
483 h = w / aspect;
Mathias Agopian595ea772013-08-21 23:10:41 -0700484 }
Romain Guy5d4bae72016-11-08 09:49:25 -0800485 return frustum(-w, w, -h, h, near, far);
486}
487
488/*
489 * Returns a matrix representing the pose of a virtual camera looking towards -Z in its
490 * local Y-up coordinate system. "eye" is where the camera is located, "center" is the points its
491 * looking at and "up" defines where the Y axis of the camera's local coordinate system is.
492 */
493template <typename T>
494template <typename A, typename B, typename C>
Romain Guycaf2ca42016-11-10 11:45:58 -0800495CONSTEXPR TMat44<T> TMat44<T>::lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800496 TVec3<T> z_axis(normalize(center - eye));
497 TVec3<T> norm_up(normalize(up));
498 if (std::abs(dot(z_axis, norm_up)) > 0.999) {
499 // Fix up vector if we're degenerate (looking straight up, basically)
500 norm_up = { norm_up.z, norm_up.x, norm_up.y };
501 }
502 TVec3<T> x_axis(normalize(cross(z_axis, norm_up)));
503 TVec3<T> y_axis(cross(x_axis, z_axis));
504 return TMat44<T>(
505 TVec4<T>(x_axis, 0),
506 TVec4<T>(y_axis, 0),
507 TVec4<T>(-z_axis, 0),
508 TVec4<T>(eye, 1));
Mathias Agopian595ea772013-08-21 23:10:41 -0700509}
510
511// ----------------------------------------------------------------------------------------
Mathias Agopian595ea772013-08-21 23:10:41 -0700512// Arithmetic operators outside of class
513// ----------------------------------------------------------------------------------------
514
515/* We use non-friend functions here to prevent the compiler from using
516 * implicit conversions, for instance of a scalar to a vector. The result would
517 * not be what the caller expects.
518 *
519 * Also note that the order of the arguments in the inner loop is important since
520 * it determines the output type (only relevant when T != U).
521 */
522
Romain Guy5d4bae72016-11-08 09:49:25 -0800523// matrix * column-vector, result is a vector of the same type than the input vector
Mathias Agopian595ea772013-08-21 23:10:41 -0700524template <typename T, typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800525CONSTEXPR typename TMat44<T>::col_type PURE operator *(const TMat44<T>& lhs, const TVec4<U>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800526 // Result is initialized to zero.
527 typename TMat44<T>::col_type result;
528 for (size_t col = 0; col < TMat44<T>::NUM_COLS; ++col) {
529 result += lhs[col] * rhs[col];
530 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700531 return result;
532}
533
Romain Guy5d4bae72016-11-08 09:49:25 -0800534// mat44 * vec3, result is vec3( mat44 * {vec3, 1} )
Mathias Agopian595ea772013-08-21 23:10:41 -0700535template <typename T, typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800536CONSTEXPR typename TMat44<T>::col_type PURE operator *(const TMat44<T>& lhs, const TVec3<U>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800537 return lhs * TVec4<U>{ rhs, 1 };
538}
539
540
541// row-vector * matrix, result is a vector of the same type than the input vector
542template <typename T, typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800543CONSTEXPR typename TMat44<U>::row_type PURE operator *(const TVec4<U>& lhs, const TMat44<T>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800544 typename TMat44<U>::row_type result(TMat44<U>::row_type::NO_INIT);
545 for (size_t col = 0; col < TMat44<T>::NUM_COLS; ++col) {
546 result[col] = dot(lhs, rhs[col]);
547 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700548 return result;
549}
550
551// matrix * scalar, result is a matrix of the same type than the input matrix
552template <typename T, typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800553constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat44<T>>::type PURE
554operator *(TMat44<T> lhs, U rhs) {
555 return lhs *= rhs;
Mathias Agopian595ea772013-08-21 23:10:41 -0700556}
557
558// scalar * matrix, result is a matrix of the same type than the input matrix
559template <typename T, typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800560constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat44<T>>::type PURE
561operator *(U lhs, const TMat44<T>& rhs) {
562 return rhs * lhs;
Mathias Agopian595ea772013-08-21 23:10:41 -0700563}
564
Mathias Agopian595ea772013-08-21 23:10:41 -0700565// ----------------------------------------------------------------------------------------
566
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700567/* FIXME: this should go into TMatSquareFunctions<> but for some reason
568 * BASE<T>::col_type is not accessible from there (???)
569 */
570template<typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -0800571typename TMat44<T>::col_type PURE diag(const TMat44<T>& m) {
Mathias Agopian595ea772013-08-21 23:10:41 -0700572 return matrix::diag(m);
573}
574
Romain Guy5d4bae72016-11-08 09:49:25 -0800575} // namespace details
Mathias Agopian595ea772013-08-21 23:10:41 -0700576
577// ----------------------------------------------------------------------------------------
Romain Guy5d4bae72016-11-08 09:49:25 -0800578
579typedef details::TMat44<double> mat4d;
580typedef details::TMat44<float> mat4;
581typedef details::TMat44<float> mat4f;
582
583// ----------------------------------------------------------------------------------------
584} // namespace android
Mathias Agopian595ea772013-08-21 23:10:41 -0700585
586#undef PURE
Romain Guycaf2ca42016-11-10 11:45:58 -0800587#undef CONSTEXPR
Mathias Agopian595ea772013-08-21 23:10:41 -0700588
Romain Guy5d4bae72016-11-08 09:49:25 -0800589#endif // UI_MAT4_H_