blob: 4fd1effd71a1e6a7abd3873547abb5b7d38de096 [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
17#ifndef UI_MAT4_H
18#define UI_MAT4_H
19
20#include <stdint.h>
21#include <sys/types.h>
22
23#include <ui/vec4.h>
24#include <utils/String8.h>
25
26#define TMAT_IMPLEMENTATION
27#include <ui/TMatHelpers.h>
28
29#define PURE __attribute__((pure))
30
31namespace android {
32// -------------------------------------------------------------------------------------
33
34template <typename T>
35class tmat44 : public TVecUnaryOperators<tmat44, T>,
Mathias Agopian1d4d8f92013-09-01 21:35:36 -070036 public TVecComparisonOperators<tmat44, T>,
37 public TVecAddOperators<tmat44, T>,
38 public TMatProductOperators<tmat44, T>,
39 public TMatSquareFunctions<tmat44, T>,
40 public TMatDebug<tmat44, T>
Mathias Agopian595ea772013-08-21 23:10:41 -070041{
42public:
43 enum no_init { NO_INIT };
44 typedef T value_type;
45 typedef T& reference;
46 typedef T const& const_reference;
47 typedef size_t size_type;
48 typedef tvec4<T> col_type;
49 typedef tvec4<T> row_type;
50
51 // size of a column (i.e.: number of rows)
52 enum { COL_SIZE = col_type::SIZE };
53 static inline size_t col_size() { return COL_SIZE; }
54
55 // size of a row (i.e.: number of columns)
56 enum { ROW_SIZE = row_type::SIZE };
57 static inline size_t row_size() { return ROW_SIZE; }
58 static inline size_t size() { return row_size(); } // for TVec*<>
59
60private:
61
62 /*
63 * <-- N columns -->
64 *
65 * a00 a10 a20 ... aN0 ^
66 * a01 a11 a21 ... aN1 |
67 * a02 a12 a22 ... aN2 M rows
68 * ... |
69 * a0M a1M a2M ... aNM v
70 *
71 * COL_SIZE = M
72 * ROW_SIZE = N
73 * m[0] = [a00 a01 a02 ... a01M]
74 */
75
76 col_type mValue[ROW_SIZE];
77
78public:
79 // array access
80 inline col_type const& operator [] (size_t i) const { return mValue[i]; }
81 inline col_type& operator [] (size_t i) { return mValue[i]; }
82
83 T const* asArray() const { return &mValue[0][0]; }
84
85 // -----------------------------------------------------------------------
86 // we don't provide copy-ctor and operator= on purpose
87 // because we want the compiler generated versions
88
89 /*
90 * constructors
91 */
92
93 // leaves object uninitialized. use with caution.
94 explicit tmat44(no_init) { }
95
96 // initialize to identity
97 tmat44();
98
99 // initialize to Identity*scalar.
100 template<typename U>
101 explicit tmat44(U v);
102
103 // sets the diagonal to the passed vector
104 template <typename U>
105 explicit tmat44(const tvec4<U>& rhs);
106
107 // construct from another matrix of the same size
108 template <typename U>
109 explicit tmat44(const tmat44<U>& rhs);
110
111 // construct from 4 column vectors
112 template <typename A, typename B, typename C, typename D>
113 tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3);
114
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700115 // construct from 16 scalars
116 template <
117 typename A, typename B, typename C, typename D,
118 typename E, typename F, typename G, typename H,
119 typename I, typename J, typename K, typename L,
120 typename M, typename N, typename O, typename P>
121 tmat44( A m00, B m01, C m02, D m03,
122 E m10, F m11, G m12, H m13,
123 I m20, J m21, K m22, L m23,
124 M m30, N m31, O m32, P m33);
125
Mathias Agopian595ea772013-08-21 23:10:41 -0700126 // construct from a C array
127 template <typename U>
128 explicit tmat44(U const* rawArray);
129
130 /*
131 * helpers
132 */
133
134 static tmat44 ortho(T left, T right, T bottom, T top, T near, T far);
135
136 static tmat44 frustum(T left, T right, T bottom, T top, T near, T far);
137
138 template <typename A, typename B, typename C>
139 static tmat44 lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up);
140
141 template <typename A>
142 static tmat44 translate(const tvec4<A>& t);
143
144 template <typename A>
145 static tmat44 scale(const tvec4<A>& s);
146
147 template <typename A, typename B>
148 static tmat44 rotate(A radian, const tvec3<B>& about);
Mathias Agopian595ea772013-08-21 23:10:41 -0700149};
150
151// ----------------------------------------------------------------------------------------
152// Constructors
153// ----------------------------------------------------------------------------------------
154
155/*
156 * Since the matrix code could become pretty big quickly, we don't inline most
157 * operations.
158 */
159
160template <typename T>
161tmat44<T>::tmat44() {
162 mValue[0] = col_type(1,0,0,0);
163 mValue[1] = col_type(0,1,0,0);
164 mValue[2] = col_type(0,0,1,0);
165 mValue[3] = col_type(0,0,0,1);
166}
167
168template <typename T>
169template <typename U>
170tmat44<T>::tmat44(U v) {
171 mValue[0] = col_type(v,0,0,0);
172 mValue[1] = col_type(0,v,0,0);
173 mValue[2] = col_type(0,0,v,0);
174 mValue[3] = col_type(0,0,0,v);
175}
176
177template<typename T>
178template<typename U>
179tmat44<T>::tmat44(const tvec4<U>& v) {
180 mValue[0] = col_type(v.x,0,0,0);
181 mValue[1] = col_type(0,v.y,0,0);
182 mValue[2] = col_type(0,0,v.z,0);
183 mValue[3] = col_type(0,0,0,v.w);
184}
185
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700186// construct from 16 scalars
187template<typename T>
188template <
189 typename A, typename B, typename C, typename D,
190 typename E, typename F, typename G, typename H,
191 typename I, typename J, typename K, typename L,
192 typename M, typename N, typename O, typename P>
193tmat44<T>::tmat44( A m00, B m01, C m02, D m03,
194 E m10, F m11, G m12, H m13,
195 I m20, J m21, K m22, L m23,
196 M m30, N m31, O m32, P m33) {
197 mValue[0] = col_type(m00, m01, m02, m03);
198 mValue[1] = col_type(m10, m11, m12, m13);
199 mValue[2] = col_type(m20, m21, m22, m23);
200 mValue[3] = col_type(m30, m31, m32, m33);
201}
202
Mathias Agopian595ea772013-08-21 23:10:41 -0700203template <typename T>
204template <typename U>
205tmat44<T>::tmat44(const tmat44<U>& rhs) {
206 for (size_t r=0 ; r<row_size() ; r++)
207 mValue[r] = rhs[r];
208}
209
210template <typename T>
211template <typename A, typename B, typename C, typename D>
212tmat44<T>::tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3) {
213 mValue[0] = v0;
214 mValue[1] = v1;
215 mValue[2] = v2;
216 mValue[3] = v3;
217}
218
219template <typename T>
220template <typename U>
221tmat44<T>::tmat44(U const* rawArray) {
222 for (size_t r=0 ; r<row_size() ; r++)
223 for (size_t c=0 ; c<col_size() ; c++)
224 mValue[r][c] = *rawArray++;
225}
226
227// ----------------------------------------------------------------------------------------
228// Helpers
229// ----------------------------------------------------------------------------------------
230
231template <typename T>
232tmat44<T> tmat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) {
233 tmat44<T> m;
234 m[0][0] = 2 / (right - left);
235 m[1][1] = 2 / (top - bottom);
236 m[2][2] = -2 / (far - near);
237 m[3][0] = -(right + left) / (right - left);
238 m[3][1] = -(top + bottom) / (top - bottom);
239 m[3][2] = -(far + near) / (far - near);
240 return m;
241}
242
243template <typename T>
244tmat44<T> tmat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) {
245 tmat44<T> m;
246 T A = (right + left) / (right - left);
247 T B = (top + bottom) / (top - bottom);
248 T C = (far + near) / (far - near);
249 T D = (2 * far * near) / (far - near);
250 m[0][0] = (2 * near) / (right - left);
251 m[1][1] = (2 * near) / (top - bottom);
252 m[2][0] = A;
253 m[2][1] = B;
254 m[2][2] = C;
255 m[2][3] =-1;
256 m[3][2] = D;
257 m[3][3] = 0;
258 return m;
259}
260
261template <typename T>
262template <typename A, typename B, typename C>
263tmat44<T> tmat44<T>::lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up) {
264 tvec3<T> L(normalize(center - eye));
265 tvec3<T> S(normalize( cross(L, up) ));
266 tvec3<T> U(cross(S, L));
267 return tmat44<T>(
268 tvec4<T>( S, 0),
269 tvec4<T>( U, 0),
270 tvec4<T>(-L, 0),
271 tvec4<T>(-eye, 1));
272}
273
274template <typename T>
275template <typename A>
276tmat44<T> tmat44<T>::translate(const tvec4<A>& t) {
277 tmat44<T> r;
278 r[3] = t;
279 return r;
280}
281
282template <typename T>
283template <typename A>
284tmat44<T> tmat44<T>::scale(const tvec4<A>& s) {
285 tmat44<T> r;
286 r[0][0] = s[0];
287 r[1][1] = s[1];
288 r[2][2] = s[2];
289 r[3][3] = s[3];
290 return r;
291}
292
293template <typename T>
294template <typename A, typename B>
295tmat44<T> tmat44<T>::rotate(A radian, const tvec3<B>& about) {
296 tmat44<T> rotation;
297 T* r = const_cast<T*>(rotation.asArray());
298 T c = cos(radian);
299 T s = sin(radian);
300 if (about.x==1 && about.y==0 && about.z==0) {
301 r[5] = c; r[10]= c;
302 r[6] = s; r[9] = -s;
303 } else if (about.x==0 && about.y==1 && about.z==0) {
304 r[0] = c; r[10]= c;
305 r[8] = s; r[2] = -s;
306 } else if (about.x==0 && about.y==0 && about.z==1) {
307 r[0] = c; r[5] = c;
308 r[1] = s; r[4] = -s;
309 } else {
310 tvec3<B> nabout = normalize(about);
311 B x = nabout.x;
312 B y = nabout.y;
313 B z = nabout.z;
314 T nc = 1 - c;
315 T xy = x * y;
316 T yz = y * z;
317 T zx = z * x;
318 T xs = x * s;
319 T ys = y * s;
320 T zs = z * s;
321 r[ 0] = x*x*nc + c; r[ 4] = xy*nc - zs; r[ 8] = zx*nc + ys;
322 r[ 1] = xy*nc + zs; r[ 5] = y*y*nc + c; r[ 9] = yz*nc - xs;
323 r[ 2] = zx*nc - ys; r[ 6] = yz*nc + xs; r[10] = z*z*nc + c;
324 }
Stephen Hines457296a2014-09-04 08:28:54 -0700325 return rotation;
Mathias Agopian595ea772013-08-21 23:10:41 -0700326}
327
328// ----------------------------------------------------------------------------------------
Mathias Agopian595ea772013-08-21 23:10:41 -0700329// Arithmetic operators outside of class
330// ----------------------------------------------------------------------------------------
331
332/* We use non-friend functions here to prevent the compiler from using
333 * implicit conversions, for instance of a scalar to a vector. The result would
334 * not be what the caller expects.
335 *
336 * Also note that the order of the arguments in the inner loop is important since
337 * it determines the output type (only relevant when T != U).
338 */
339
Mathias Agopian595ea772013-08-21 23:10:41 -0700340// matrix * vector, result is a vector of the same type than the input vector
341template <typename T, typename U>
342typename tmat44<U>::col_type PURE operator *(const tmat44<T>& lv, const tvec4<U>& rv) {
343 typename tmat44<U>::col_type result;
344 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
345 result += rv[r]*lv[r];
346 return result;
347}
348
349// vector * matrix, result is a vector of the same type than the input vector
350template <typename T, typename U>
351typename tmat44<U>::row_type PURE operator *(const tvec4<U>& rv, const tmat44<T>& lv) {
352 typename tmat44<U>::row_type result(tmat44<U>::row_type::NO_INIT);
353 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
354 result[r] = dot(rv, lv[r]);
355 return result;
356}
357
358// matrix * scalar, result is a matrix of the same type than the input matrix
359template <typename T, typename U>
360tmat44<T> PURE operator *(const tmat44<T>& lv, U rv) {
361 tmat44<T> result(tmat44<T>::NO_INIT);
362 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
363 result[r] = lv[r]*rv;
364 return result;
365}
366
367// scalar * matrix, result is a matrix of the same type than the input matrix
368template <typename T, typename U>
369tmat44<T> PURE operator *(U rv, const tmat44<T>& lv) {
370 tmat44<T> result(tmat44<T>::NO_INIT);
371 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
372 result[r] = lv[r]*rv;
373 return result;
374}
375
Mathias Agopian595ea772013-08-21 23:10:41 -0700376// ----------------------------------------------------------------------------------------
377
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700378/* FIXME: this should go into TMatSquareFunctions<> but for some reason
379 * BASE<T>::col_type is not accessible from there (???)
380 */
381template<typename T>
382typename tmat44<T>::col_type PURE diag(const tmat44<T>& m) {
Mathias Agopian595ea772013-08-21 23:10:41 -0700383 return matrix::diag(m);
384}
385
386// ----------------------------------------------------------------------------------------
Mathias Agopian595ea772013-08-21 23:10:41 -0700387
388typedef tmat44<float> mat4;
389
390// ----------------------------------------------------------------------------------------
391}; // namespace android
392
393#undef PURE
394
395#endif /* UI_MAT4_H */