blob: d9647cc1a463ab948f33b4094fd08bd58670173f [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 }
325}
326
327// ----------------------------------------------------------------------------------------
Mathias Agopian595ea772013-08-21 23:10:41 -0700328// Arithmetic operators outside of class
329// ----------------------------------------------------------------------------------------
330
331/* We use non-friend functions here to prevent the compiler from using
332 * implicit conversions, for instance of a scalar to a vector. The result would
333 * not be what the caller expects.
334 *
335 * Also note that the order of the arguments in the inner loop is important since
336 * it determines the output type (only relevant when T != U).
337 */
338
Mathias Agopian595ea772013-08-21 23:10:41 -0700339// matrix * vector, result is a vector of the same type than the input vector
340template <typename T, typename U>
341typename tmat44<U>::col_type PURE operator *(const tmat44<T>& lv, const tvec4<U>& rv) {
342 typename tmat44<U>::col_type result;
343 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
344 result += rv[r]*lv[r];
345 return result;
346}
347
348// vector * matrix, result is a vector of the same type than the input vector
349template <typename T, typename U>
350typename tmat44<U>::row_type PURE operator *(const tvec4<U>& rv, const tmat44<T>& lv) {
351 typename tmat44<U>::row_type result(tmat44<U>::row_type::NO_INIT);
352 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
353 result[r] = dot(rv, lv[r]);
354 return result;
355}
356
357// matrix * scalar, result is a matrix of the same type than the input matrix
358template <typename T, typename U>
359tmat44<T> PURE operator *(const tmat44<T>& lv, U rv) {
360 tmat44<T> result(tmat44<T>::NO_INIT);
361 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
362 result[r] = lv[r]*rv;
363 return result;
364}
365
366// scalar * matrix, result is a matrix of the same type than the input matrix
367template <typename T, typename U>
368tmat44<T> PURE operator *(U rv, const tmat44<T>& lv) {
369 tmat44<T> result(tmat44<T>::NO_INIT);
370 for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
371 result[r] = lv[r]*rv;
372 return result;
373}
374
Mathias Agopian595ea772013-08-21 23:10:41 -0700375// ----------------------------------------------------------------------------------------
376
Mathias Agopian1d4d8f92013-09-01 21:35:36 -0700377/* FIXME: this should go into TMatSquareFunctions<> but for some reason
378 * BASE<T>::col_type is not accessible from there (???)
379 */
380template<typename T>
381typename tmat44<T>::col_type PURE diag(const tmat44<T>& m) {
Mathias Agopian595ea772013-08-21 23:10:41 -0700382 return matrix::diag(m);
383}
384
385// ----------------------------------------------------------------------------------------
Mathias Agopian595ea772013-08-21 23:10:41 -0700386
387typedef tmat44<float> mat4;
388
389// ----------------------------------------------------------------------------------------
390}; // namespace android
391
392#undef PURE
393
394#endif /* UI_MAT4_H */