Home | History | Annotate | Download | only in ui
      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     return rotation;
    326 }
    327 
    328 // ----------------------------------------------------------------------------------------
    329 // 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 
    340 // matrix * vector, result is a vector of the same type than the input vector
    341 template <typename T, typename U>
    342 typename 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
    350 template <typename T, typename U>
    351 typename 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
    359 template <typename T, typename U>
    360 tmat44<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
    368 template <typename T, typename U>
    369 tmat44<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 
    376 // ----------------------------------------------------------------------------------------
    377 
    378 /* FIXME: this should go into TMatSquareFunctions<> but for some reason
    379  * BASE<T>::col_type is not accessible from there (???)
    380  */
    381 template<typename T>
    382 typename tmat44<T>::col_type PURE diag(const tmat44<T>& m) {
    383     return matrix::diag(m);
    384 }
    385 
    386 // ----------------------------------------------------------------------------------------
    387 
    388 typedef tmat44<float> mat4;
    389 
    390 // ----------------------------------------------------------------------------------------
    391 }; // namespace android
    392 
    393 #undef PURE
    394 
    395 #endif /* UI_MAT4_H */
    396