OSDN Git Service

merge in klp-release history after reset to klp-dev
[android-x86/frameworks-native.git] / include / ui / mat4.h
1 /*
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
31 namespace android {
32 // -------------------------------------------------------------------------------------
33
34 template <typename T>
35 class tmat44 :  public TVecUnaryOperators<tmat44, T>,
36                 public TVecComparisonOperators<tmat44, T>,
37                 public TVecAddOperators<tmat44, T>,
38                 public TMatProductOperators<tmat44, T>,
39                 public TMatSquareFunctions<tmat44, T>,
40                 public TMatDebug<tmat44, T>
41 {
42 public:
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
60 private:
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
78 public:
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
115     // 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
126     // 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);
149 };
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
160 template <typename T>
161 tmat44<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
168 template <typename T>
169 template <typename U>
170 tmat44<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
177 template<typename T>
178 template<typename U>
179 tmat44<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
186 // construct from 16 scalars
187 template<typename T>
188 template <
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>
193 tmat44<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
203 template <typename T>
204 template <typename U>
205 tmat44<T>::tmat44(const tmat44<U>& rhs) {
206     for (size_t r=0 ; r<row_size() ; r++)
207         mValue[r] = rhs[r];
208 }
209
210 template <typename T>
211 template <typename A, typename B, typename C, typename D>
212 tmat44<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
219 template <typename T>
220 template <typename U>
221 tmat44<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
231 template <typename T>
232 tmat44<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
243 template <typename T>
244 tmat44<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
261 template <typename T>
262 template <typename A, typename B, typename C>
263 tmat44<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
274 template <typename T>
275 template <typename A>
276 tmat44<T> tmat44<T>::translate(const tvec4<A>& t) {
277     tmat44<T> r;
278     r[3] = t;
279     return r;
280 }
281
282 template <typename T>
283 template <typename A>
284 tmat44<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
293 template <typename T>
294 template <typename A, typename B>
295 tmat44<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 // ----------------------------------------------------------------------------------------
328 // 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
339 // matrix * vector, result is a vector of the same type than the input vector
340 template <typename T, typename U>
341 typename 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
349 template <typename T, typename U>
350 typename 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
358 template <typename T, typename U>
359 tmat44<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
367 template <typename T, typename U>
368 tmat44<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
375 // ----------------------------------------------------------------------------------------
376
377 /* FIXME: this should go into TMatSquareFunctions<> but for some reason
378  * BASE<T>::col_type is not accessible from there (???)
379  */
380 template<typename T>
381 typename tmat44<T>::col_type PURE diag(const tmat44<T>& m) {
382     return matrix::diag(m);
383 }
384
385 // ----------------------------------------------------------------------------------------
386
387 typedef tmat44<float> mat4;
388
389 // ----------------------------------------------------------------------------------------
390 }; // namespace android
391
392 #undef PURE
393
394 #endif /* UI_MAT4_H */