blob: c9e118ab343a54f1a02999d5e2a43b086ae6b617 [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
Mathias Agopian1d77b712017-02-17 15:46:13 -080017#pragma once
Romain Guy5d4bae72016-11-08 09:49:25 -080018
Mathias Agopian1d77b712017-02-17 15:46:13 -080019#include <math/mat3.h>
20#include <math/quat.h>
21#include <math/TMatHelpers.h>
22#include <math/vec3.h>
23#include <math/vec4.h>
Mathias Agopian595ea772013-08-21 23:10:41 -070024
25#include <stdint.h>
26#include <sys/types.h>
Romain Guy5d4bae72016-11-08 09:49:25 -080027#include <limits>
Mathias Agopian595ea772013-08-21 23:10:41 -070028
29#define PURE __attribute__((pure))
30
Romain Guycaf2ca42016-11-10 11:45:58 -080031#if __cplusplus >= 201402L
32#define CONSTEXPR constexpr
33#else
34#define CONSTEXPR
35#endif
36
Michael Hoisieafdffd82024-03-05 23:22:13 +000037#ifdef _WIN32
38// windows.h contains obsolete defines of 'near' and 'far' for systems using
39// legacy 16 bit pointers. Undefine them to avoid conflicting with the usage of
40// 'near' and 'far' in this file.
41#undef near
42#undef far
43#endif
44
Mathias Agopian595ea772013-08-21 23:10:41 -070045namespace android {
46// -------------------------------------------------------------------------------------
Romain Guy5d4bae72016-11-08 09:49:25 -080047namespace details {
Mathias Agopian595ea772013-08-21 23:10:41 -070048
Romain Guy5d4bae72016-11-08 09:49:25 -080049template<typename T>
50class TQuaternion;
51
52/**
53 * A 4x4 column-major matrix class.
54 *
55 * Conceptually a 4x4 matrix is a an array of 4 column double4:
56 *
57 * mat4 m =
58 * \f$
59 * \left(
60 * \begin{array}{cccc}
61 * m[0] & m[1] & m[2] & m[3] \\
62 * \end{array}
63 * \right)
64 * \f$
65 * =
66 * \f$
67 * \left(
68 * \begin{array}{cccc}
69 * m[0][0] & m[1][0] & m[2][0] & m[3][0] \\
70 * m[0][1] & m[1][1] & m[2][1] & m[3][1] \\
71 * m[0][2] & m[1][2] & m[2][2] & m[3][2] \\
72 * m[0][3] & m[1][3] & m[2][3] & m[3][3] \\
73 * \end{array}
74 * \right)
75 * \f$
76 * =
77 * \f$
78 * \left(
79 * \begin{array}{cccc}
80 * m(0,0) & m(0,1) & m(0,2) & m(0,3) \\
81 * m(1,0) & m(1,1) & m(1,2) & m(1,3) \\
82 * m(2,0) & m(2,1) & m(2,2) & m(2,3) \\
83 * m(3,0) & m(3,1) & m(3,2) & m(3,3) \\
84 * \end{array}
85 * \right)
86 * \f$
87 *
88 * m[n] is the \f$ n^{th} \f$ column of the matrix and is a double4.
89 *
90 */
Mathias Agopian595ea772013-08-21 23:10:41 -070091template <typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -080092class TMat44 : public TVecUnaryOperators<TMat44, T>,
93 public TVecComparisonOperators<TMat44, T>,
94 public TVecAddOperators<TMat44, T>,
95 public TMatProductOperators<TMat44, T>,
96 public TMatSquareFunctions<TMat44, T>,
97 public TMatTransform<TMat44, T>,
98 public TMatHelpers<TMat44, T>,
99 public TMatDebug<TMat44, T> {
Mathias Agopian595ea772013-08-21 23:10:41 -0700100public:
101 enum no_init { NO_INIT };
102 typedef T value_type;
103 typedef T& reference;
104 typedef T const& const_reference;
105 typedef size_t size_type;
Romain Guy5d4bae72016-11-08 09:49:25 -0800106 typedef TVec4<T> col_type;
107 typedef TVec4<T> row_type;
Mathias Agopian595ea772013-08-21 23:10:41 -0700108
Romain Guy5d4bae72016-11-08 09:49:25 -0800109 static constexpr size_t COL_SIZE = col_type::SIZE; // size of a column (i.e.: number of rows)
110 static constexpr size_t ROW_SIZE = row_type::SIZE; // size of a row (i.e.: number of columns)
111 static constexpr size_t NUM_ROWS = COL_SIZE;
112 static constexpr size_t NUM_COLS = ROW_SIZE;
Mathias Agopian595ea772013-08-21 23:10:41 -0700113
114private:
Mathias Agopian595ea772013-08-21 23:10:41 -0700115 /*
116 * <-- N columns -->
117 *
Romain Guy5d4bae72016-11-08 09:49:25 -0800118 * a[0][0] a[1][0] a[2][0] ... a[N][0] ^
119 * a[0][1] a[1][1] a[2][1] ... a[N][1] |
120 * a[0][2] a[1][2] a[2][2] ... a[N][2] M rows
121 * ... |
122 * a[0][M] a[1][M] a[2][M] ... a[N][M] v
Mathias Agopian595ea772013-08-21 23:10:41 -0700123 *
124 * COL_SIZE = M
125 * ROW_SIZE = N
Romain Guy5d4bae72016-11-08 09:49:25 -0800126 * m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
Mathias Agopian595ea772013-08-21 23:10:41 -0700127 */
128
Romain Guy5d4bae72016-11-08 09:49:25 -0800129 col_type m_value[NUM_COLS];
Mathias Agopian595ea772013-08-21 23:10:41 -0700130
131public:
132 // array access
Romain Guy5d4bae72016-11-08 09:49:25 -0800133 inline constexpr col_type const& operator[](size_t column) const {
134#if __cplusplus >= 201402L
135 // only possible in C++0x14 with constexpr
136 assert(column < NUM_COLS);
137#endif
138 return m_value[column];
139 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700140
Romain Guy5d4bae72016-11-08 09:49:25 -0800141 inline col_type& operator[](size_t column) {
142 assert(column < NUM_COLS);
143 return m_value[column];
144 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700145
146 // -----------------------------------------------------------------------
Romain Guy5d4bae72016-11-08 09:49:25 -0800147 // we want the compiler generated versions for these...
148 TMat44(const TMat44&) = default;
149 ~TMat44() = default;
150 TMat44& operator = (const TMat44&) = default;
Mathias Agopian595ea772013-08-21 23:10:41 -0700151
152 /*
153 * constructors
154 */
155
156 // leaves object uninitialized. use with caution.
Romain Guycaf2ca42016-11-10 11:45:58 -0800157 explicit constexpr TMat44(no_init)
Romain Guy5d4bae72016-11-08 09:49:25 -0800158 : m_value{ col_type(col_type::NO_INIT),
159 col_type(col_type::NO_INIT),
160 col_type(col_type::NO_INIT),
161 col_type(col_type::NO_INIT) } {}
Mathias Agopian595ea772013-08-21 23:10:41 -0700162
Romain Guy5d4bae72016-11-08 09:49:25 -0800163 /** initialize to identity.
164 *
165 * \f$
166 * \left(
167 * \begin{array}{cccc}
168 * 1 & 0 & 0 & 0 \\
169 * 0 & 1 & 0 & 0 \\
170 * 0 & 0 & 1 & 0 \\
171 * 0 & 0 & 0 & 1 \\
172 * \end{array}
173 * \right)
174 * \f$
175 */
Romain Guycaf2ca42016-11-10 11:45:58 -0800176 CONSTEXPR TMat44();
Mathias Agopian595ea772013-08-21 23:10:41 -0700177
Romain Guy5d4bae72016-11-08 09:49:25 -0800178 /** initialize to Identity*scalar.
179 *
180 * \f$
181 * \left(
182 * \begin{array}{cccc}
183 * v & 0 & 0 & 0 \\
184 * 0 & v & 0 & 0 \\
185 * 0 & 0 & v & 0 \\
186 * 0 & 0 & 0 & v \\
187 * \end{array}
188 * \right)
189 * \f$
190 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700191 template<typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800192 explicit CONSTEXPR TMat44(U v);
Mathias Agopian595ea772013-08-21 23:10:41 -0700193
Romain Guy5d4bae72016-11-08 09:49:25 -0800194 /** sets the diagonal to a vector.
195 *
196 * \f$
197 * \left(
198 * \begin{array}{cccc}
199 * v[0] & 0 & 0 & 0 \\
200 * 0 & v[1] & 0 & 0 \\
201 * 0 & 0 & v[2] & 0 \\
202 * 0 & 0 & 0 & v[3] \\
203 * \end{array}
204 * \right)
205 * \f$
206 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700207 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800208 explicit CONSTEXPR TMat44(const TVec4<U>& v);
Mathias Agopian595ea772013-08-21 23:10:41 -0700209
210 // construct from another matrix of the same size
211 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800212 explicit CONSTEXPR TMat44(const TMat44<U>& rhs);
Mathias Agopian595ea772013-08-21 23:10:41 -0700213
Romain Guy5d4bae72016-11-08 09:49:25 -0800214 /** construct from 4 column vectors.
215 *
216 * \f$
217 * \left(
218 * \begin{array}{cccc}
219 * v0 & v1 & v2 & v3 \\
220 * \end{array}
221 * \right)
222 * \f$
223 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700224 template <typename A, typename B, typename C, typename D>
Romain Guycaf2ca42016-11-10 11:45:58 -0800225 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 -0700226
Romain Guy5d4bae72016-11-08 09:49:25 -0800227 /** construct from 16 elements in column-major form.
228 *
229 * \f$
230 * \left(
231 * \begin{array}{cccc}
232 * m[0][0] & m[1][0] & m[2][0] & m[3][0] \\
233 * m[0][1] & m[1][1] & m[2][1] & m[3][1] \\
234 * m[0][2] & m[1][2] & m[2][2] & m[3][2] \\
235 * m[0][3] & m[1][3] & m[2][3] & m[3][3] \\
236 * \end{array}
237 * \right)
238 * \f$
239 */
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700240 template <
241 typename A, typename B, typename C, typename D,
242 typename E, typename F, typename G, typename H,
243 typename I, typename J, typename K, typename L,
244 typename M, typename N, typename O, typename P>
Romain Guycaf2ca42016-11-10 11:45:58 -0800245 CONSTEXPR TMat44(
246 A m00, B m01, C m02, D m03,
247 E m10, F m11, G m12, H m13,
248 I m20, J m21, K m22, L m23,
249 M m30, N m31, O m32, P m33);
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700250
Romain Guy5d4bae72016-11-08 09:49:25 -0800251 /**
252 * construct from a quaternion
253 */
Mathias Agopian595ea772013-08-21 23:10:41 -0700254 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800255 explicit CONSTEXPR TMat44(const TQuaternion<U>& q);
Romain Guy5d4bae72016-11-08 09:49:25 -0800256
257 /**
258 * construct from a C array in column major form.
259 */
260 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800261 explicit CONSTEXPR TMat44(U const* rawArray);
Romain Guy5d4bae72016-11-08 09:49:25 -0800262
263 /**
264 * construct from a 3x3 matrix
265 */
266 template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800267 explicit CONSTEXPR TMat44(const TMat33<U>& matrix);
Romain Guy5d4bae72016-11-08 09:49:25 -0800268
269 /**
270 * construct from a 3x3 matrix and 3d translation
271 */
272 template <typename U, typename V>
Romain Guycaf2ca42016-11-10 11:45:58 -0800273 CONSTEXPR TMat44(const TMat33<U>& matrix, const TVec3<V>& translation);
Romain Guy5d4bae72016-11-08 09:49:25 -0800274
275 /**
276 * construct from a 3x3 matrix and 4d last column.
277 */
278 template <typename U, typename V>
Romain Guycaf2ca42016-11-10 11:45:58 -0800279 CONSTEXPR TMat44(const TMat33<U>& matrix, const TVec4<V>& column3);
Mathias Agopian595ea772013-08-21 23:10:41 -0700280
281 /*
282 * helpers
283 */
284
Romain Guycaf2ca42016-11-10 11:45:58 -0800285 static CONSTEXPR TMat44 ortho(T left, T right, T bottom, T top, T near, T far);
Mathias Agopian595ea772013-08-21 23:10:41 -0700286
Romain Guycaf2ca42016-11-10 11:45:58 -0800287 static CONSTEXPR TMat44 frustum(T left, T right, T bottom, T top, T near, T far);
Romain Guy5d4bae72016-11-08 09:49:25 -0800288
289 enum class Fov {
290 HORIZONTAL,
291 VERTICAL
292 };
Romain Guycaf2ca42016-11-10 11:45:58 -0800293 static CONSTEXPR TMat44 perspective(T fov, T aspect, T near, T far, Fov direction = Fov::VERTICAL);
Mathias Agopian595ea772013-08-21 23:10:41 -0700294
295 template <typename A, typename B, typename C>
Romain Guycaf2ca42016-11-10 11:45:58 -0800296 static CONSTEXPR TMat44 lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up);
Mathias Agopian595ea772013-08-21 23:10:41 -0700297
298 template <typename A>
Romain Guycaf2ca42016-11-10 11:45:58 -0800299 static CONSTEXPR TVec3<A> project(const TMat44& projectionMatrix, TVec3<A> vertice) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800300 TVec4<A> r = projectionMatrix * TVec4<A>{ vertice, 1 };
301 return r.xyz / r.w;
302 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700303
304 template <typename A>
Romain Guycaf2ca42016-11-10 11:45:58 -0800305 static CONSTEXPR TVec4<A> project(const TMat44& projectionMatrix, TVec4<A> vertice) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800306 vertice = projectionMatrix * vertice;
307 return { vertice.xyz / vertice.w, 1 };
308 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700309
Romain Guy5d4bae72016-11-08 09:49:25 -0800310 /**
311 * Constructs a 3x3 matrix from the upper-left corner of this 4x4 matrix
312 */
313 inline constexpr TMat33<T> upperLeft() const {
314 return TMat33<T>(m_value[0].xyz, m_value[1].xyz, m_value[2].xyz);
315 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700316};
317
318// ----------------------------------------------------------------------------------------
319// Constructors
320// ----------------------------------------------------------------------------------------
321
Romain Guy5d4bae72016-11-08 09:49:25 -0800322// Since the matrix code could become pretty big quickly, we don't inline most
323// operations.
Mathias Agopian595ea772013-08-21 23:10:41 -0700324
325template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800326CONSTEXPR TMat44<T>::TMat44() {
Romain Guy5d4bae72016-11-08 09:49:25 -0800327 m_value[0] = col_type(1, 0, 0, 0);
328 m_value[1] = col_type(0, 1, 0, 0);
329 m_value[2] = col_type(0, 0, 1, 0);
330 m_value[3] = col_type(0, 0, 0, 1);
Mathias Agopian595ea772013-08-21 23:10:41 -0700331}
332
333template <typename T>
334template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800335CONSTEXPR TMat44<T>::TMat44(U v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800336 m_value[0] = col_type(v, 0, 0, 0);
337 m_value[1] = col_type(0, v, 0, 0);
338 m_value[2] = col_type(0, 0, v, 0);
339 m_value[3] = col_type(0, 0, 0, v);
Mathias Agopian595ea772013-08-21 23:10:41 -0700340}
341
342template<typename T>
343template<typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800344CONSTEXPR TMat44<T>::TMat44(const TVec4<U>& v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800345 m_value[0] = col_type(v.x, 0, 0, 0);
346 m_value[1] = col_type(0, v.y, 0, 0);
347 m_value[2] = col_type(0, 0, v.z, 0);
348 m_value[3] = col_type(0, 0, 0, v.w);
Mathias Agopian595ea772013-08-21 23:10:41 -0700349}
350
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700351// construct from 16 scalars
352template<typename T>
353template <
354 typename A, typename B, typename C, typename D,
355 typename E, typename F, typename G, typename H,
356 typename I, typename J, typename K, typename L,
357 typename M, typename N, typename O, typename P>
Romain Guycaf2ca42016-11-10 11:45:58 -0800358CONSTEXPR TMat44<T>::TMat44(
359 A m00, B m01, C m02, D m03,
360 E m10, F m11, G m12, H m13,
361 I m20, J m21, K m22, L m23,
362 M m30, N m31, O m32, P m33) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800363 m_value[0] = col_type(m00, m01, m02, m03);
364 m_value[1] = col_type(m10, m11, m12, m13);
365 m_value[2] = col_type(m20, m21, m22, m23);
366 m_value[3] = col_type(m30, m31, m32, m33);
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700367}
368
Mathias Agopian595ea772013-08-21 23:10:41 -0700369template <typename T>
370template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800371CONSTEXPR TMat44<T>::TMat44(const TMat44<U>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800372 for (size_t col = 0; col < NUM_COLS; ++col) {
373 m_value[col] = col_type(rhs[col]);
374 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700375}
376
Romain Guy5d4bae72016-11-08 09:49:25 -0800377// Construct from 4 column vectors.
Mathias Agopian595ea772013-08-21 23:10:41 -0700378template <typename T>
379template <typename A, typename B, typename C, typename D>
Romain Guycaf2ca42016-11-10 11:45:58 -0800380CONSTEXPR TMat44<T>::TMat44(
381 const TVec4<A>& v0, const TVec4<B>& v1,
382 const TVec4<C>& v2, const TVec4<D>& v3) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800383 m_value[0] = col_type(v0);
384 m_value[1] = col_type(v1);
385 m_value[2] = col_type(v2);
386 m_value[3] = col_type(v3);
387}
388
389// Construct from raw array, in column-major form.
390template <typename T>
391template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800392CONSTEXPR TMat44<T>::TMat44(U const* rawArray) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800393 for (size_t col = 0; col < NUM_COLS; ++col) {
394 for (size_t row = 0; row < NUM_ROWS; ++row) {
395 m_value[col][row] = *rawArray++;
396 }
397 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700398}
399
400template <typename T>
401template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800402CONSTEXPR TMat44<T>::TMat44(const TQuaternion<U>& q) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800403 const U n = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w;
404 const U s = n > 0 ? 2/n : 0;
405 const U x = s*q.x;
406 const U y = s*q.y;
407 const U z = s*q.z;
408 const U xx = x*q.x;
409 const U xy = x*q.y;
410 const U xz = x*q.z;
411 const U xw = x*q.w;
412 const U yy = y*q.y;
413 const U yz = y*q.z;
414 const U yw = y*q.w;
415 const U zz = z*q.z;
416 const U zw = z*q.w;
417 m_value[0] = col_type(1-yy-zz, xy+zw, xz-yw, 0);
418 m_value[1] = col_type( xy-zw, 1-xx-zz, yz+xw, 0); // NOLINT
419 m_value[2] = col_type( xz+yw, yz-xw, 1-xx-yy, 0); // NOLINT
420 m_value[3] = col_type( 0, 0, 0, 1); // NOLINT
421}
422
423template <typename T>
424template <typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800425CONSTEXPR TMat44<T>::TMat44(const TMat33<U>& m) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800426 m_value[0] = col_type(m[0][0], m[0][1], m[0][2], 0);
427 m_value[1] = col_type(m[1][0], m[1][1], m[1][2], 0);
428 m_value[2] = col_type(m[2][0], m[2][1], m[2][2], 0);
429 m_value[3] = col_type( 0, 0, 0, 1); // NOLINT
430}
431
432template <typename T>
433template <typename U, typename V>
Romain Guycaf2ca42016-11-10 11:45:58 -0800434CONSTEXPR TMat44<T>::TMat44(const TMat33<U>& m, const TVec3<V>& v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800435 m_value[0] = col_type(m[0][0], m[0][1], m[0][2], 0);
436 m_value[1] = col_type(m[1][0], m[1][1], m[1][2], 0);
437 m_value[2] = col_type(m[2][0], m[2][1], m[2][2], 0);
438 m_value[3] = col_type( v[0], v[1], v[2], 1); // NOLINT
439}
440
441template <typename T>
442template <typename U, typename V>
Romain Guycaf2ca42016-11-10 11:45:58 -0800443CONSTEXPR TMat44<T>::TMat44(const TMat33<U>& m, const TVec4<V>& v) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800444 m_value[0] = col_type(m[0][0], m[0][1], m[0][2], 0); // NOLINT
445 m_value[1] = col_type(m[1][0], m[1][1], m[1][2], 0); // NOLINT
446 m_value[2] = col_type(m[2][0], m[2][1], m[2][2], 0); // NOLINT
447 m_value[3] = col_type( v[0], v[1], v[2], v[3]); // NOLINT
Mathias Agopian595ea772013-08-21 23:10:41 -0700448}
449
450// ----------------------------------------------------------------------------------------
451// Helpers
452// ----------------------------------------------------------------------------------------
453
454template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800455CONSTEXPR TMat44<T> TMat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800456 TMat44<T> m;
Mathias Agopian595ea772013-08-21 23:10:41 -0700457 m[0][0] = 2 / (right - left);
458 m[1][1] = 2 / (top - bottom);
459 m[2][2] = -2 / (far - near);
460 m[3][0] = -(right + left) / (right - left);
461 m[3][1] = -(top + bottom) / (top - bottom);
462 m[3][2] = -(far + near) / (far - near);
463 return m;
464}
465
466template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800467CONSTEXPR TMat44<T> TMat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800468 TMat44<T> m;
469 m[0][0] = (2 * near) / (right - left);
470 m[1][1] = (2 * near) / (top - bottom);
471 m[2][0] = (right + left) / (right - left);
472 m[2][1] = (top + bottom) / (top - bottom);
473 m[2][2] = -(far + near) / (far - near);
474 m[2][3] = -1;
475 m[3][2] = -(2 * far * near) / (far - near);
476 m[3][3] = 0;
Mathias Agopian595ea772013-08-21 23:10:41 -0700477 return m;
478}
479
480template <typename T>
Romain Guycaf2ca42016-11-10 11:45:58 -0800481CONSTEXPR TMat44<T> TMat44<T>::perspective(T fov, T aspect, T near, T far, TMat44::Fov direction) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800482 T h;
483 T w;
Mathias Agopian595ea772013-08-21 23:10:41 -0700484
Romain Guy5d4bae72016-11-08 09:49:25 -0800485 if (direction == TMat44::Fov::VERTICAL) {
486 h = std::tan(fov * M_PI / 360.0f) * near;
487 w = h * aspect;
Mathias Agopian595ea772013-08-21 23:10:41 -0700488 } else {
Romain Guy5d4bae72016-11-08 09:49:25 -0800489 w = std::tan(fov * M_PI / 360.0f) * near;
490 h = w / aspect;
Mathias Agopian595ea772013-08-21 23:10:41 -0700491 }
Romain Guy5d4bae72016-11-08 09:49:25 -0800492 return frustum(-w, w, -h, h, near, far);
493}
494
495/*
496 * Returns a matrix representing the pose of a virtual camera looking towards -Z in its
497 * local Y-up coordinate system. "eye" is where the camera is located, "center" is the points its
498 * looking at and "up" defines where the Y axis of the camera's local coordinate system is.
499 */
500template <typename T>
501template <typename A, typename B, typename C>
Romain Guycaf2ca42016-11-10 11:45:58 -0800502CONSTEXPR TMat44<T> TMat44<T>::lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800503 TVec3<T> z_axis(normalize(center - eye));
504 TVec3<T> norm_up(normalize(up));
505 if (std::abs(dot(z_axis, norm_up)) > 0.999) {
506 // Fix up vector if we're degenerate (looking straight up, basically)
507 norm_up = { norm_up.z, norm_up.x, norm_up.y };
508 }
509 TVec3<T> x_axis(normalize(cross(z_axis, norm_up)));
510 TVec3<T> y_axis(cross(x_axis, z_axis));
511 return TMat44<T>(
512 TVec4<T>(x_axis, 0),
513 TVec4<T>(y_axis, 0),
514 TVec4<T>(-z_axis, 0),
515 TVec4<T>(eye, 1));
Mathias Agopian595ea772013-08-21 23:10:41 -0700516}
517
518// ----------------------------------------------------------------------------------------
Mathias Agopian595ea772013-08-21 23:10:41 -0700519// Arithmetic operators outside of class
520// ----------------------------------------------------------------------------------------
521
522/* We use non-friend functions here to prevent the compiler from using
523 * implicit conversions, for instance of a scalar to a vector. The result would
524 * not be what the caller expects.
525 *
526 * Also note that the order of the arguments in the inner loop is important since
527 * it determines the output type (only relevant when T != U).
528 */
529
Romain Guy5d4bae72016-11-08 09:49:25 -0800530// matrix * column-vector, result is a vector of the same type than the input vector
Mathias Agopian595ea772013-08-21 23:10:41 -0700531template <typename T, typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800532CONSTEXPR typename TMat44<T>::col_type PURE operator *(const TMat44<T>& lhs, const TVec4<U>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800533 // Result is initialized to zero.
534 typename TMat44<T>::col_type result;
535 for (size_t col = 0; col < TMat44<T>::NUM_COLS; ++col) {
536 result += lhs[col] * rhs[col];
537 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700538 return result;
539}
540
Romain Guy5d4bae72016-11-08 09:49:25 -0800541// mat44 * vec3, result is vec3( mat44 * {vec3, 1} )
Mathias Agopian595ea772013-08-21 23:10:41 -0700542template <typename T, typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800543CONSTEXPR typename TMat44<T>::col_type PURE operator *(const TMat44<T>& lhs, const TVec3<U>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800544 return lhs * TVec4<U>{ rhs, 1 };
545}
546
547
548// row-vector * matrix, result is a vector of the same type than the input vector
549template <typename T, typename U>
Romain Guycaf2ca42016-11-10 11:45:58 -0800550CONSTEXPR typename TMat44<U>::row_type PURE operator *(const TVec4<U>& lhs, const TMat44<T>& rhs) {
Romain Guy5d4bae72016-11-08 09:49:25 -0800551 typename TMat44<U>::row_type result(TMat44<U>::row_type::NO_INIT);
552 for (size_t col = 0; col < TMat44<T>::NUM_COLS; ++col) {
553 result[col] = dot(lhs, rhs[col]);
554 }
Mathias Agopian595ea772013-08-21 23:10:41 -0700555 return result;
556}
557
558// matrix * scalar, 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 *(TMat44<T> lhs, U rhs) {
562 return lhs *= rhs;
Mathias Agopian595ea772013-08-21 23:10:41 -0700563}
564
565// scalar * matrix, result is a matrix of the same type than the input matrix
566template <typename T, typename U>
Romain Guy5d4bae72016-11-08 09:49:25 -0800567constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat44<T>>::type PURE
568operator *(U lhs, const TMat44<T>& rhs) {
569 return rhs * lhs;
Mathias Agopian595ea772013-08-21 23:10:41 -0700570}
571
Mathias Agopian595ea772013-08-21 23:10:41 -0700572// ----------------------------------------------------------------------------------------
573
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700574/* FIXME: this should go into TMatSquareFunctions<> but for some reason
575 * BASE<T>::col_type is not accessible from there (???)
576 */
577template<typename T>
Romain Guy5d4bae72016-11-08 09:49:25 -0800578typename TMat44<T>::col_type PURE diag(const TMat44<T>& m) {
Mathias Agopian595ea772013-08-21 23:10:41 -0700579 return matrix::diag(m);
580}
581
Romain Guy5d4bae72016-11-08 09:49:25 -0800582} // namespace details
Mathias Agopian595ea772013-08-21 23:10:41 -0700583
584// ----------------------------------------------------------------------------------------
Romain Guy5d4bae72016-11-08 09:49:25 -0800585
586typedef details::TMat44<double> mat4d;
587typedef details::TMat44<float> mat4;
588typedef details::TMat44<float> mat4f;
589
590// ----------------------------------------------------------------------------------------
591} // namespace android
Mathias Agopian595ea772013-08-21 23:10:41 -0700592
Ryan Prichardbb01a642024-08-01 18:00:24 -0700593TVECHELPERS_STD_HASH(android::details::TMat44);
594
Mathias Agopian595ea772013-08-21 23:10:41 -0700595#undef PURE
Romain Guycaf2ca42016-11-10 11:45:58 -0800596#undef CONSTEXPR