OSDN Git Service

Add ColorSpace class
[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 <ui/mat3.h>
21 #include <ui/quat.h>
22 #include <ui/TMatHelpers.h>
23 #include <ui/vec3.h>
24 #include <ui/vec4.h>
25
26 #include <stdint.h>
27 #include <sys/types.h>
28 #include <limits>
29
30 #define PURE __attribute__((pure))
31
32 #if __cplusplus >= 201402L
33 #define CONSTEXPR constexpr
34 #else
35 #define CONSTEXPR
36 #endif
37
38 namespace android {
39 // -------------------------------------------------------------------------------------
40 namespace details {
41
42 template<typename T>
43 class 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  */
84 template <typename T>
85 class 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> {
93 public:
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;
99     typedef TVec4<T> col_type;
100     typedef TVec4<T> row_type;
101
102     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;
106
107 private:
108     /*
109      *  <--  N columns  -->
110      *
111      *  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
116      *
117      *  COL_SIZE = M
118      *  ROW_SIZE = N
119      *  m[0] = [ a[0][0] a[0][1] a[0][2] ... a[0][M] ]
120      */
121
122     col_type m_value[NUM_COLS];
123
124 public:
125     // array access
126     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     }
133
134     inline col_type& operator[](size_t column) {
135         assert(column < NUM_COLS);
136         return m_value[column];
137     }
138
139     // -----------------------------------------------------------------------
140     // we want the compiler generated versions for these...
141     TMat44(const TMat44&) = default;
142     ~TMat44() = default;
143     TMat44& operator = (const TMat44&) = default;
144
145     /*
146      *  constructors
147      */
148
149     // leaves object uninitialized. use with caution.
150     explicit constexpr TMat44(no_init)
151             : 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) } {}
155
156     /** 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      */
169     CONSTEXPR TMat44();
170
171     /** 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      */
184     template<typename U>
185     explicit CONSTEXPR TMat44(U v);
186
187     /** 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      */
200     template <typename U>
201     explicit CONSTEXPR TMat44(const TVec4<U>& v);
202
203     // construct from another matrix of the same size
204     template <typename U>
205     explicit CONSTEXPR TMat44(const TMat44<U>& rhs);
206
207     /** 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      */
217     template <typename A, typename B, typename C, typename D>
218     CONSTEXPR TMat44(const TVec4<A>& v0, const TVec4<B>& v1, const TVec4<C>& v2, const TVec4<D>& v3);
219
220     /** 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      */
233     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>
238     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);
243
244     /**
245      * construct from a quaternion
246      */
247     template <typename U>
248     explicit CONSTEXPR TMat44(const TQuaternion<U>& q);
249
250     /**
251      * construct from a C array in column major form.
252      */
253     template <typename U>
254     explicit CONSTEXPR TMat44(U const* rawArray);
255
256     /**
257      * construct from a 3x3 matrix
258      */
259     template <typename U>
260     explicit CONSTEXPR TMat44(const TMat33<U>& matrix);
261
262     /**
263      * construct from a 3x3 matrix and 3d translation
264      */
265     template <typename U, typename V>
266     CONSTEXPR TMat44(const TMat33<U>& matrix, const TVec3<V>& translation);
267
268     /**
269      * construct from a 3x3 matrix and 4d last column.
270      */
271     template <typename U, typename V>
272     CONSTEXPR TMat44(const TMat33<U>& matrix, const TVec4<V>& column3);
273
274     /*
275      *  helpers
276      */
277
278     static CONSTEXPR TMat44 ortho(T left, T right, T bottom, T top, T near, T far);
279
280     static CONSTEXPR TMat44 frustum(T left, T right, T bottom, T top, T near, T far);
281
282     enum class Fov {
283         HORIZONTAL,
284         VERTICAL
285     };
286     static CONSTEXPR TMat44 perspective(T fov, T aspect, T near, T far, Fov direction = Fov::VERTICAL);
287
288     template <typename A, typename B, typename C>
289     static CONSTEXPR TMat44 lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up);
290
291     template <typename A>
292     static CONSTEXPR TVec3<A> project(const TMat44& projectionMatrix, TVec3<A> vertice) {
293         TVec4<A> r = projectionMatrix * TVec4<A>{ vertice, 1 };
294         return r.xyz / r.w;
295     }
296
297     template <typename A>
298     static CONSTEXPR TVec4<A> project(const TMat44& projectionMatrix, TVec4<A> vertice) {
299         vertice = projectionMatrix * vertice;
300         return { vertice.xyz / vertice.w, 1 };
301     }
302
303     /**
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     }
309 };
310
311 // ----------------------------------------------------------------------------------------
312 // Constructors
313 // ----------------------------------------------------------------------------------------
314
315 // Since the matrix code could become pretty big quickly, we don't inline most
316 // operations.
317
318 template <typename T>
319 CONSTEXPR TMat44<T>::TMat44() {
320     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);
324 }
325
326 template <typename T>
327 template <typename U>
328 CONSTEXPR TMat44<T>::TMat44(U v) {
329     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);
333 }
334
335 template<typename T>
336 template<typename U>
337 CONSTEXPR TMat44<T>::TMat44(const TVec4<U>& v) {
338     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);
342 }
343
344 // construct from 16 scalars
345 template<typename T>
346 template <
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>
351 CONSTEXPR 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) {
356     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);
360 }
361
362 template <typename T>
363 template <typename U>
364 CONSTEXPR TMat44<T>::TMat44(const TMat44<U>& rhs) {
365     for (size_t col = 0; col < NUM_COLS; ++col) {
366         m_value[col] = col_type(rhs[col]);
367     }
368 }
369
370 // Construct from 4 column vectors.
371 template <typename T>
372 template <typename A, typename B, typename C, typename D>
373 CONSTEXPR TMat44<T>::TMat44(
374         const TVec4<A>& v0, const TVec4<B>& v1,
375         const TVec4<C>& v2, const TVec4<D>& v3) {
376     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.
383 template <typename T>
384 template <typename U>
385 CONSTEXPR TMat44<T>::TMat44(U const* rawArray) {
386     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     }
391 }
392
393 template <typename T>
394 template <typename U>
395 CONSTEXPR TMat44<T>::TMat44(const TQuaternion<U>& q) {
396     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
416 template <typename T>
417 template <typename U>
418 CONSTEXPR TMat44<T>::TMat44(const TMat33<U>& m) {
419     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
425 template <typename T>
426 template <typename U, typename V>
427 CONSTEXPR TMat44<T>::TMat44(const TMat33<U>& m, const TVec3<V>& v) {
428     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
434 template <typename T>
435 template <typename U, typename V>
436 CONSTEXPR TMat44<T>::TMat44(const TMat33<U>& m, const TVec4<V>& v) {
437     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
441 }
442
443 // ----------------------------------------------------------------------------------------
444 // Helpers
445 // ----------------------------------------------------------------------------------------
446
447 template <typename T>
448 CONSTEXPR TMat44<T> TMat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) {
449     TMat44<T> m;
450     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
459 template <typename T>
460 CONSTEXPR TMat44<T> TMat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) {
461     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;
470     return m;
471 }
472
473 template <typename T>
474 CONSTEXPR TMat44<T> TMat44<T>::perspective(T fov, T aspect, T near, T far, TMat44::Fov direction) {
475     T h;
476     T w;
477
478     if (direction == TMat44::Fov::VERTICAL) {
479         h = std::tan(fov * M_PI / 360.0f) * near;
480         w = h * aspect;
481     } else {
482         w = std::tan(fov * M_PI / 360.0f) * near;
483         h = w / aspect;
484     }
485     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  */
493 template <typename T>
494 template <typename A, typename B, typename C>
495 CONSTEXPR TMat44<T> TMat44<T>::lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up) {
496     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));
509 }
510
511 // ----------------------------------------------------------------------------------------
512 // 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
523 // matrix * column-vector, result is a vector of the same type than the input vector
524 template <typename T, typename U>
525 CONSTEXPR typename TMat44<T>::col_type PURE operator *(const TMat44<T>& lhs, const TVec4<U>& rhs) {
526     // 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     }
531     return result;
532 }
533
534 // mat44 * vec3, result is vec3( mat44 * {vec3, 1} )
535 template <typename T, typename U>
536 CONSTEXPR typename TMat44<T>::col_type PURE operator *(const TMat44<T>& lhs, const TVec3<U>& rhs) {
537     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
542 template <typename T, typename U>
543 CONSTEXPR typename TMat44<U>::row_type PURE operator *(const TVec4<U>& lhs, const TMat44<T>& rhs) {
544     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     }
548     return result;
549 }
550
551 // matrix * scalar, result is a matrix of the same type than the input matrix
552 template <typename T, typename U>
553 constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat44<T>>::type PURE
554 operator *(TMat44<T> lhs, U rhs) {
555     return lhs *= rhs;
556 }
557
558 // scalar * matrix, result is a matrix of the same type than the input matrix
559 template <typename T, typename U>
560 constexpr typename std::enable_if<std::is_arithmetic<U>::value, TMat44<T>>::type PURE
561 operator *(U lhs, const TMat44<T>& rhs) {
562     return rhs * lhs;
563 }
564
565 // ----------------------------------------------------------------------------------------
566
567 /* FIXME: this should go into TMatSquareFunctions<> but for some reason
568  * BASE<T>::col_type is not accessible from there (???)
569  */
570 template<typename T>
571 typename TMat44<T>::col_type PURE diag(const TMat44<T>& m) {
572     return matrix::diag(m);
573 }
574
575 } // namespace details
576
577 // ----------------------------------------------------------------------------------------
578
579 typedef details::TMat44<double> mat4d;
580 typedef details::TMat44<float> mat4;
581 typedef details::TMat44<float> mat4f;
582
583 // ----------------------------------------------------------------------------------------
584 }  // namespace android
585
586 #undef PURE
587 #undef CONSTEXPR
588
589 #endif  // UI_MAT4_H_