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 }
    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 */
    395