Home | History | Annotate | Download | only in ndk_helper
      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 VECMATH_H_
     18 #define VECMATH_H_
     19 
     20 #include <math.h>
     21 #include "JNIHelper.h"
     22 
     23 namespace ndk_helper
     24 {
     25 
     26 /******************************************************************
     27  * Helper class for vector math operations
     28  * Currently all implementations are in pure C++.
     29  * Each class is an opaque class so caller does not have a direct access
     30  * to each element. This is for an ease of future optimization to use vector operations.
     31  *
     32  */
     33 
     34 class Vec2;
     35 class Vec3;
     36 class Vec4;
     37 class Mat4;
     38 
     39 /******************************************************************
     40  * 2 elements vector class
     41  *
     42  */
     43 class Vec2
     44 {
     45 private:
     46     float x_;
     47     float y_;
     48 
     49 public:
     50     friend class Vec3;
     51     friend class Vec4;
     52     friend class Mat4;
     53     friend class Quaternion;
     54 
     55     Vec2()
     56     {
     57         x_ = y_ = 0.f;
     58     }
     59 
     60     Vec2( const float fX, const float fY )
     61     {
     62         x_ = fX;
     63         y_ = fY;
     64     }
     65 
     66     Vec2( const Vec2& vec )
     67     {
     68         x_ = vec.x_;
     69         y_ = vec.y_;
     70     }
     71 
     72     Vec2( const float* pVec )
     73     {
     74         x_ = (*pVec++);
     75         y_ = (*pVec++);
     76     }
     77 
     78     //Operators
     79     Vec2 operator*( const Vec2& rhs ) const
     80     {
     81         Vec2 ret;
     82         ret.x_ = x_ * rhs.x_;
     83         ret.y_ = y_ * rhs.y_;
     84         return ret;
     85     }
     86 
     87     Vec2 operator/( const Vec2& rhs ) const
     88     {
     89         Vec2 ret;
     90         ret.x_ = x_ / rhs.x_;
     91         ret.y_ = y_ / rhs.y_;
     92         return ret;
     93     }
     94 
     95     Vec2 operator+( const Vec2& rhs ) const
     96     {
     97         Vec2 ret;
     98         ret.x_ = x_ + rhs.x_;
     99         ret.y_ = y_ + rhs.y_;
    100         return ret;
    101     }
    102 
    103     Vec2 operator-( const Vec2& rhs ) const
    104     {
    105         Vec2 ret;
    106         ret.x_ = x_ - rhs.x_;
    107         ret.y_ = y_ - rhs.y_;
    108         return ret;
    109     }
    110 
    111     Vec2& operator+=( const Vec2& rhs )
    112     {
    113         x_ += rhs.x_;
    114         y_ += rhs.y_;
    115         return *this;
    116     }
    117 
    118     Vec2& operator-=( const Vec2& rhs )
    119     {
    120         x_ -= rhs.x_;
    121         y_ -= rhs.y_;
    122         return *this;
    123     }
    124 
    125     Vec2& operator*=( const Vec2& rhs )
    126     {
    127         x_ *= rhs.x_;
    128         y_ *= rhs.y_;
    129         return *this;
    130     }
    131 
    132     Vec2& operator/=( const Vec2& rhs )
    133     {
    134         x_ /= rhs.x_;
    135         y_ /= rhs.y_;
    136         return *this;
    137     }
    138 
    139     //External operators
    140     friend Vec2 operator-( const Vec2& rhs )
    141     {
    142         return Vec2( rhs ) *= -1;
    143     }
    144 
    145     friend Vec2 operator*( const float lhs, const Vec2& rhs )
    146     {
    147         Vec2 ret;
    148         ret.x_ = lhs * rhs.x_;
    149         ret.y_ = lhs * rhs.y_;
    150         return ret;
    151     }
    152 
    153     friend Vec2 operator/( const float lhs, const Vec2& rhs )
    154     {
    155         Vec2 ret;
    156         ret.x_ = lhs / rhs.x_;
    157         ret.y_ = lhs / rhs.y_;
    158         return ret;
    159     }
    160 
    161     //Operators with float
    162     Vec2 operator*( const float& rhs ) const
    163     {
    164         Vec2 ret;
    165         ret.x_ = x_ * rhs;
    166         ret.y_ = y_ * rhs;
    167         return ret;
    168     }
    169 
    170     Vec2& operator*=( const float& rhs )
    171     {
    172         x_ = x_ * rhs;
    173         y_ = y_ * rhs;
    174         return *this;
    175     }
    176 
    177     Vec2 operator/( const float& rhs ) const
    178     {
    179         Vec2 ret;
    180         ret.x_ = x_ / rhs;
    181         ret.y_ = y_ / rhs;
    182         return ret;
    183     }
    184 
    185     Vec2& operator/=( const float& rhs )
    186     {
    187         x_ = x_ / rhs;
    188         y_ = y_ / rhs;
    189         return *this;
    190     }
    191 
    192     //Compare
    193     bool operator==( const Vec2& rhs ) const
    194     {
    195         if( x_ != rhs.x_ || y_ != rhs.y_ )
    196             return false;
    197         return true;
    198     }
    199 
    200     bool operator!=( const Vec2& rhs ) const
    201     {
    202         if( x_ == rhs.x_ )
    203             return false;
    204 
    205         return true;
    206     }
    207 
    208     float Length() const
    209     {
    210         return sqrtf( x_ * x_ + y_ * y_ );
    211     }
    212 
    213     Vec2 Normalize()
    214     {
    215         float len = Length();
    216         x_ = x_ / len;
    217         y_ = y_ / len;
    218         return *this;
    219     }
    220 
    221     float Dot( const Vec2& rhs )
    222     {
    223         return x_ * rhs.x_ + y_ * rhs.y_;
    224     }
    225 
    226     bool Validate()
    227     {
    228         if( isnan( x_ ) || isnan( y_ ) )
    229             return false;
    230         return true;
    231     }
    232 
    233     void Value( float& fX, float& fY )
    234     {
    235         fX = x_;
    236         fY = y_;
    237     }
    238 
    239     void Dump()
    240     {
    241         LOGI( "Vec2 %f %f", x_, y_ );
    242     }
    243 };
    244 
    245 /******************************************************************
    246  * 3 elements vector class
    247  *
    248  */
    249 class Vec3
    250 {
    251 private:
    252     float x_, y_, z_;
    253 
    254 public:
    255     friend class Vec4;
    256     friend class Mat4;
    257     friend class Quaternion;
    258 
    259     Vec3()
    260     {
    261         x_ = y_ = z_ = 0.f;
    262     }
    263 
    264     Vec3( const float fX, const float fY, const float fZ )
    265     {
    266         x_ = fX;
    267         y_ = fY;
    268         z_ = fZ;
    269     }
    270 
    271     Vec3( const Vec3& vec )
    272     {
    273         x_ = vec.x_;
    274         y_ = vec.y_;
    275         z_ = vec.z_;
    276     }
    277 
    278     Vec3( const float* pVec )
    279     {
    280         x_ = (*pVec++);
    281         y_ = (*pVec++);
    282         z_ = *pVec;
    283     }
    284 
    285     Vec3( const Vec2& vec, float f )
    286     {
    287         x_ = vec.x_;
    288         y_ = vec.y_;
    289         z_ = f;
    290     }
    291 
    292     Vec3( const Vec4& vec );
    293 
    294     //Operators
    295     Vec3 operator*( const Vec3& rhs ) const
    296     {
    297         Vec3 ret;
    298         ret.x_ = x_ * rhs.x_;
    299         ret.y_ = y_ * rhs.y_;
    300         ret.z_ = z_ * rhs.z_;
    301         return ret;
    302     }
    303 
    304     Vec3 operator/( const Vec3& rhs ) const
    305     {
    306         Vec3 ret;
    307         ret.x_ = x_ / rhs.x_;
    308         ret.y_ = y_ / rhs.y_;
    309         ret.z_ = z_ / rhs.z_;
    310         return ret;
    311     }
    312 
    313     Vec3 operator+( const Vec3& rhs ) const
    314     {
    315         Vec3 ret;
    316         ret.x_ = x_ + rhs.x_;
    317         ret.y_ = y_ + rhs.y_;
    318         ret.z_ = z_ + rhs.z_;
    319         return ret;
    320     }
    321 
    322     Vec3 operator-( const Vec3& rhs ) const
    323     {
    324         Vec3 ret;
    325         ret.x_ = x_ - rhs.x_;
    326         ret.y_ = y_ - rhs.y_;
    327         ret.z_ = z_ - rhs.z_;
    328         return ret;
    329     }
    330 
    331     Vec3& operator+=( const Vec3& rhs )
    332     {
    333         x_ += rhs.x_;
    334         y_ += rhs.y_;
    335         z_ += rhs.z_;
    336         return *this;
    337     }
    338 
    339     Vec3& operator-=( const Vec3& rhs )
    340     {
    341         x_ -= rhs.x_;
    342         y_ -= rhs.y_;
    343         z_ -= rhs.z_;
    344         return *this;
    345     }
    346 
    347     Vec3& operator*=( const Vec3& rhs )
    348     {
    349         x_ *= rhs.x_;
    350         y_ *= rhs.y_;
    351         z_ *= rhs.z_;
    352         return *this;
    353     }
    354 
    355     Vec3& operator/=( const Vec3& rhs )
    356     {
    357         x_ /= rhs.x_;
    358         y_ /= rhs.y_;
    359         z_ /= rhs.z_;
    360         return *this;
    361     }
    362 
    363     //External operators
    364     friend Vec3 operator-( const Vec3& rhs )
    365     {
    366         return Vec3( rhs ) *= -1;
    367     }
    368 
    369     friend Vec3 operator*( const float lhs, const Vec3& rhs )
    370     {
    371         Vec3 ret;
    372         ret.x_ = lhs * rhs.x_;
    373         ret.y_ = lhs * rhs.y_;
    374         ret.z_ = lhs * rhs.z_;
    375         return ret;
    376     }
    377 
    378     friend Vec3 operator/( const float lhs, const Vec3& rhs )
    379     {
    380         Vec3 ret;
    381         ret.x_ = lhs / rhs.x_;
    382         ret.y_ = lhs / rhs.y_;
    383         ret.z_ = lhs / rhs.z_;
    384         return ret;
    385     }
    386 
    387     //Operators with float
    388     Vec3 operator*( const float& rhs ) const
    389     {
    390         Vec3 ret;
    391         ret.x_ = x_ * rhs;
    392         ret.y_ = y_ * rhs;
    393         ret.z_ = z_ * rhs;
    394         return ret;
    395     }
    396 
    397     Vec3& operator*=( const float& rhs )
    398     {
    399         x_ = x_ * rhs;
    400         y_ = y_ * rhs;
    401         z_ = z_ * rhs;
    402         return *this;
    403     }
    404 
    405     Vec3 operator/( const float& rhs ) const
    406     {
    407         Vec3 ret;
    408         ret.x_ = x_ / rhs;
    409         ret.y_ = y_ / rhs;
    410         ret.z_ = z_ / rhs;
    411         return ret;
    412     }
    413 
    414     Vec3& operator/=( const float& rhs )
    415     {
    416         x_ = x_ / rhs;
    417         y_ = y_ / rhs;
    418         z_ = z_ / rhs;
    419         return *this;
    420     }
    421 
    422     //Compare
    423     bool operator==( const Vec3& rhs ) const
    424     {
    425         if( x_ != rhs.x_ || y_ != rhs.y_ || z_ != rhs.z_ )
    426             return false;
    427         return true;
    428     }
    429 
    430     bool operator!=( const Vec3& rhs ) const
    431     {
    432         if( x_ == rhs.x_ )
    433             return false;
    434 
    435         return true;
    436     }
    437 
    438     float Length() const
    439     {
    440         return sqrtf( x_ * x_ + y_ * y_ + z_ * z_ );
    441     }
    442 
    443     Vec3 Normalize()
    444     {
    445         float len = Length();
    446         x_ = x_ / len;
    447         y_ = y_ / len;
    448         z_ = z_ / len;
    449         return *this;
    450     }
    451 
    452     float Dot( const Vec3& rhs )
    453     {
    454         return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_;
    455     }
    456 
    457     Vec3 Cross( const Vec3& rhs )
    458     {
    459         Vec3 ret;
    460         ret.x_ = y_ * rhs.z_ - z_ * rhs.y_;
    461         ret.y_ = z_ * rhs.x_ - x_ * rhs.z_;
    462         ret.z_ = x_ * rhs.y_ - y_ * rhs.x_;
    463         return ret;
    464     }
    465 
    466     bool Validate()
    467     {
    468         if( isnan( x_ ) || isnan( y_ ) || isnan( z_ ) )
    469             return false;
    470         return true;
    471     }
    472 
    473     void Value( float& fX, float& fY, float& fZ )
    474     {
    475         fX = x_;
    476         fY = y_;
    477         fZ = z_;
    478     }
    479 
    480     void Dump()
    481     {
    482         LOGI( "Vec3 %f %f %f", x_, y_, z_ );
    483     }
    484 };
    485 
    486 /******************************************************************
    487  * 4 elements vector class
    488  *
    489  */
    490 class Vec4
    491 {
    492 private:
    493     float x_, y_, z_, w_;
    494 
    495 public:
    496     friend class Vec3;
    497     friend class Mat4;
    498     friend class Quaternion;
    499 
    500     Vec4()
    501     {
    502         x_ = y_ = z_ = w_ = 0.f;
    503     }
    504 
    505     Vec4( const float fX, const float fY, const float fZ, const float fW )
    506     {
    507         x_ = fX;
    508         y_ = fY;
    509         z_ = fZ;
    510         w_ = fW;
    511     }
    512 
    513     Vec4( const Vec4& vec )
    514     {
    515         x_ = vec.x_;
    516         y_ = vec.y_;
    517         z_ = vec.z_;
    518         w_ = vec.w_;
    519     }
    520 
    521     Vec4( const Vec3& vec, const float fW )
    522     {
    523         x_ = vec.x_;
    524         y_ = vec.y_;
    525         z_ = vec.z_;
    526         w_ = fW;
    527     }
    528 
    529     Vec4( const float* pVec )
    530     {
    531         x_ = (*pVec++);
    532         y_ = (*pVec++);
    533         z_ = *pVec;
    534         w_ = *pVec;
    535     }
    536 
    537     //Operators
    538     Vec4 operator*( const Vec4& rhs ) const
    539     {
    540         Vec4 ret;
    541         ret.x_ = x_ * rhs.x_;
    542         ret.y_ = y_ * rhs.y_;
    543         ret.z_ = z_ * rhs.z_;
    544         ret.w_ = z_ * rhs.w_;
    545         return ret;
    546     }
    547 
    548     Vec4 operator/( const Vec4& rhs ) const
    549     {
    550         Vec4 ret;
    551         ret.x_ = x_ / rhs.x_;
    552         ret.y_ = y_ / rhs.y_;
    553         ret.z_ = z_ / rhs.z_;
    554         ret.w_ = z_ / rhs.w_;
    555         return ret;
    556     }
    557 
    558     Vec4 operator+( const Vec4& rhs ) const
    559     {
    560         Vec4 ret;
    561         ret.x_ = x_ + rhs.x_;
    562         ret.y_ = y_ + rhs.y_;
    563         ret.z_ = z_ + rhs.z_;
    564         ret.w_ = z_ + rhs.w_;
    565         return ret;
    566     }
    567 
    568     Vec4 operator-( const Vec4& rhs ) const
    569     {
    570         Vec4 ret;
    571         ret.x_ = x_ - rhs.x_;
    572         ret.y_ = y_ - rhs.y_;
    573         ret.z_ = z_ - rhs.z_;
    574         ret.w_ = z_ - rhs.w_;
    575         return ret;
    576     }
    577 
    578     Vec4& operator+=( const Vec4& rhs )
    579     {
    580         x_ += rhs.x_;
    581         y_ += rhs.y_;
    582         z_ += rhs.z_;
    583         w_ += rhs.w_;
    584         return *this;
    585     }
    586 
    587     Vec4& operator-=( const Vec4& rhs )
    588     {
    589         x_ -= rhs.x_;
    590         y_ -= rhs.y_;
    591         z_ -= rhs.z_;
    592         w_ -= rhs.w_;
    593         return *this;
    594     }
    595 
    596     Vec4& operator*=( const Vec4& rhs )
    597     {
    598         x_ *= rhs.x_;
    599         y_ *= rhs.y_;
    600         z_ *= rhs.z_;
    601         w_ *= rhs.w_;
    602         return *this;
    603     }
    604 
    605     Vec4& operator/=( const Vec4& rhs )
    606     {
    607         x_ /= rhs.x_;
    608         y_ /= rhs.y_;
    609         z_ /= rhs.z_;
    610         w_ /= rhs.w_;
    611         return *this;
    612     }
    613 
    614     //External operators
    615     friend Vec4 operator-( const Vec4& rhs )
    616     {
    617         return Vec4( rhs ) *= -1;
    618     }
    619 
    620     friend Vec4 operator*( const float lhs, const Vec4& rhs )
    621     {
    622         Vec4 ret;
    623         ret.x_ = lhs * rhs.x_;
    624         ret.y_ = lhs * rhs.y_;
    625         ret.z_ = lhs * rhs.z_;
    626         ret.w_ = lhs * rhs.w_;
    627         return ret;
    628     }
    629 
    630     friend Vec4 operator/( const float lhs, const Vec4& rhs )
    631     {
    632         Vec4 ret;
    633         ret.x_ = lhs / rhs.x_;
    634         ret.y_ = lhs / rhs.y_;
    635         ret.z_ = lhs / rhs.z_;
    636         ret.w_ = lhs / rhs.w_;
    637         return ret;
    638     }
    639 
    640     //Operators with float
    641     Vec4 operator*( const float& rhs ) const
    642     {
    643         Vec4 ret;
    644         ret.x_ = x_ * rhs;
    645         ret.y_ = y_ * rhs;
    646         ret.z_ = z_ * rhs;
    647         ret.w_ = w_ * rhs;
    648         return ret;
    649     }
    650 
    651     Vec4& operator*=( const float& rhs )
    652     {
    653         x_ = x_ * rhs;
    654         y_ = y_ * rhs;
    655         z_ = z_ * rhs;
    656         w_ = w_ * rhs;
    657         return *this;
    658     }
    659 
    660     Vec4 operator/( const float& rhs ) const
    661     {
    662         Vec4 ret;
    663         ret.x_ = x_ / rhs;
    664         ret.y_ = y_ / rhs;
    665         ret.z_ = z_ / rhs;
    666         ret.w_ = w_ / rhs;
    667         return ret;
    668     }
    669 
    670     Vec4& operator/=( const float& rhs )
    671     {
    672         x_ = x_ / rhs;
    673         y_ = y_ / rhs;
    674         z_ = z_ / rhs;
    675         w_ = w_ / rhs;
    676         return *this;
    677     }
    678 
    679     //Compare
    680     bool operator==( const Vec4& rhs ) const
    681     {
    682         if( x_ != rhs.x_ || y_ != rhs.y_ || z_ != rhs.z_ || w_ != rhs.w_ )
    683             return false;
    684         return true;
    685     }
    686 
    687     bool operator!=( const Vec4& rhs ) const
    688     {
    689         if( x_ == rhs.x_ )
    690             return false;
    691 
    692         return true;
    693     }
    694 
    695     Vec4 operator*( const Mat4& rhs ) const;
    696 
    697     float Length() const
    698     {
    699         return sqrtf( x_ * x_ + y_ * y_ + z_ * z_ + w_ * w_ );
    700     }
    701 
    702     Vec4 Normalize()
    703     {
    704         float len = Length();
    705         x_ = x_ / len;
    706         y_ = y_ / len;
    707         z_ = z_ / len;
    708         w_ = w_ / len;
    709         return *this;
    710     }
    711 
    712     float Dot( const Vec3& rhs )
    713     {
    714         return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_;
    715     }
    716 
    717     Vec3 Cross( const Vec3& rhs )
    718     {
    719         Vec3 ret;
    720         ret.x_ = y_ * rhs.z_ - z_ * rhs.y_;
    721         ret.y_ = z_ * rhs.x_ - x_ * rhs.z_;
    722         ret.z_ = x_ * rhs.y_ - y_ * rhs.x_;
    723         return ret;
    724     }
    725 
    726     bool Validate()
    727     {
    728         if( isnan( x_ ) || isnan( y_ ) || isnan( z_ ) || isnan( w_ ) )
    729             return false;
    730         return true;
    731     }
    732 
    733     void Value( float& fX, float& fY, float& fZ, float& fW )
    734     {
    735         fX = x_;
    736         fY = y_;
    737         fZ = z_;
    738         fW = w_;
    739     }
    740 };
    741 
    742 /******************************************************************
    743  * 4x4 matrix
    744  *
    745  */
    746 class Mat4
    747 {
    748 private:
    749     float f_[16];
    750 
    751 public:
    752     friend class Vec3;
    753     friend class Vec4;
    754     friend class Quaternion;
    755 
    756     Mat4();
    757     Mat4( const float* );
    758 
    759     Mat4 operator*( const Mat4& rhs ) const;
    760     Vec4 operator*( const Vec4& rhs ) const;
    761 
    762     Mat4 operator+( const Mat4& rhs ) const
    763     {
    764         Mat4 ret;
    765         for( int32_t i = 0; i < 16; ++i )
    766         {
    767             ret.f_[i] = f_[i] + rhs.f_[i];
    768         }
    769         return ret;
    770     }
    771 
    772     Mat4 operator-( const Mat4& rhs ) const
    773     {
    774         Mat4 ret;
    775         for( int32_t i = 0; i < 16; ++i )
    776         {
    777             ret.f_[i] = f_[i] - rhs.f_[i];
    778         }
    779         return ret;
    780     }
    781 
    782     Mat4& operator+=( const Mat4& rhs )
    783     {
    784         for( int32_t i = 0; i < 16; ++i )
    785         {
    786             f_[i] += rhs.f_[i];
    787         }
    788         return *this;
    789     }
    790 
    791     Mat4& operator-=( const Mat4& rhs )
    792     {
    793         for( int32_t i = 0; i < 16; ++i )
    794         {
    795             f_[i] -= rhs.f_[i];
    796         }
    797         return *this;
    798     }
    799 
    800     Mat4& operator*=( const Mat4& rhs )
    801     {
    802         Mat4 ret;
    803         ret.f_[0] = f_[0] * rhs.f_[0] + f_[4] * rhs.f_[1] + f_[8] * rhs.f_[2]
    804                 + f_[12] * rhs.f_[3];
    805         ret.f_[1] = f_[1] * rhs.f_[0] + f_[5] * rhs.f_[1] + f_[9] * rhs.f_[2]
    806                 + f_[13] * rhs.f_[3];
    807         ret.f_[2] = f_[2] * rhs.f_[0] + f_[6] * rhs.f_[1] + f_[10] * rhs.f_[2]
    808                 + f_[14] * rhs.f_[3];
    809         ret.f_[3] = f_[3] * rhs.f_[0] + f_[7] * rhs.f_[1] + f_[11] * rhs.f_[2]
    810                 + f_[15] * rhs.f_[3];
    811 
    812         ret.f_[4] = f_[0] * rhs.f_[4] + f_[4] * rhs.f_[5] + f_[8] * rhs.f_[6]
    813                 + f_[12] * rhs.f_[7];
    814         ret.f_[5] = f_[1] * rhs.f_[4] + f_[5] * rhs.f_[5] + f_[9] * rhs.f_[6]
    815                 + f_[13] * rhs.f_[7];
    816         ret.f_[6] = f_[2] * rhs.f_[4] + f_[6] * rhs.f_[5] + f_[10] * rhs.f_[6]
    817                 + f_[14] * rhs.f_[7];
    818         ret.f_[7] = f_[3] * rhs.f_[4] + f_[7] * rhs.f_[5] + f_[11] * rhs.f_[6]
    819                 + f_[15] * rhs.f_[7];
    820 
    821         ret.f_[8] = f_[0] * rhs.f_[8] + f_[4] * rhs.f_[9] + f_[8] * rhs.f_[10]
    822                 + f_[12] * rhs.f_[11];
    823         ret.f_[9] = f_[1] * rhs.f_[8] + f_[5] * rhs.f_[9] + f_[9] * rhs.f_[10]
    824                 + f_[13] * rhs.f_[11];
    825         ret.f_[10] = f_[2] * rhs.f_[8] + f_[6] * rhs.f_[9] + f_[10] * rhs.f_[10]
    826                 + f_[14] * rhs.f_[11];
    827         ret.f_[11] = f_[3] * rhs.f_[8] + f_[7] * rhs.f_[9] + f_[11] * rhs.f_[10]
    828                 + f_[15] * rhs.f_[11];
    829 
    830         ret.f_[12] = f_[0] * rhs.f_[12] + f_[4] * rhs.f_[13] + f_[8] * rhs.f_[14]
    831                 + f_[12] * rhs.f_[15];
    832         ret.f_[13] = f_[1] * rhs.f_[12] + f_[5] * rhs.f_[13] + f_[9] * rhs.f_[14]
    833                 + f_[13] * rhs.f_[15];
    834         ret.f_[14] = f_[2] * rhs.f_[12] + f_[6] * rhs.f_[13] + f_[10] * rhs.f_[14]
    835                 + f_[14] * rhs.f_[15];
    836         ret.f_[15] = f_[3] * rhs.f_[12] + f_[7] * rhs.f_[13] + f_[11] * rhs.f_[14]
    837                 + f_[15] * rhs.f_[15];
    838 
    839         *this = ret;
    840         return *this;
    841     }
    842 
    843     Mat4 operator*( const float rhs )
    844     {
    845         Mat4 ret;
    846         for( int32_t i = 0; i < 16; ++i )
    847         {
    848             ret.f_[i] = f_[i] * rhs;
    849         }
    850         return ret;
    851     }
    852 
    853     Mat4& operator*=( const float rhs )
    854     {
    855         for( int32_t i = 0; i < 16; ++i )
    856         {
    857             f_[i] *= rhs;
    858         }
    859         return *this;
    860     }
    861 
    862     Mat4& operator=( const Mat4& rhs )
    863     {
    864         for( int32_t i = 0; i < 16; ++i )
    865         {
    866             f_[i] = rhs.f_[i];
    867         }
    868         return *this;
    869     }
    870 
    871     Mat4 Inverse();
    872 
    873     Mat4 Transpose()
    874     {
    875         Mat4 ret;
    876         ret.f_[0] = f_[0];
    877         ret.f_[1] = f_[4];
    878         ret.f_[2] = f_[8];
    879         ret.f_[3] = f_[12];
    880         ret.f_[4] = f_[1];
    881         ret.f_[5] = f_[5];
    882         ret.f_[6] = f_[9];
    883         ret.f_[7] = f_[13];
    884         ret.f_[8] = f_[2];
    885         ret.f_[9] = f_[6];
    886         ret.f_[10] = f_[10];
    887         ret.f_[11] = f_[14];
    888         ret.f_[12] = f_[3];
    889         ret.f_[13] = f_[7];
    890         ret.f_[14] = f_[11];
    891         ret.f_[15] = f_[15];
    892         *this = ret;
    893         return *this;
    894     }
    895 
    896     Mat4& PostTranslate( float tx, float ty, float tz )
    897     {
    898         f_[12] += (tx * f_[0]) + (ty * f_[4]) + (tz * f_[8]);
    899         f_[13] += (tx * f_[1]) + (ty * f_[5]) + (tz * f_[9]);
    900         f_[14] += (tx * f_[2]) + (ty * f_[6]) + (tz * f_[10]);
    901         f_[15] += (tx * f_[3]) + (ty * f_[7]) + (tz * f_[11]);
    902         return *this;
    903     }
    904 
    905     float* Ptr()
    906     {
    907         return f_;
    908     }
    909 
    910     //--------------------------------------------------------------------------------
    911     // Misc
    912     //--------------------------------------------------------------------------------
    913     static Mat4 Perspective( float width, float height, float nearPlane, float farPlane );
    914 
    915     static Mat4 LookAt( const Vec3& vEye, const Vec3& vAt, const Vec3& vUp );
    916 
    917     static Mat4 Translation( const float fX, const float fY, const float fZ );
    918     static Mat4 Translation( const Vec3 vec );
    919 
    920     static Mat4 RotationX( const float angle );
    921 
    922     static Mat4 RotationY( const float angle );
    923 
    924     static Mat4 RotationZ( const float angle );
    925 
    926     static Mat4 Identity()
    927     {
    928         Mat4 ret;
    929         ret.f_[0] = 1.f;
    930         ret.f_[1] = 0;
    931         ret.f_[2] = 0;
    932         ret.f_[3] = 0;
    933         ret.f_[4] = 0;
    934         ret.f_[5] = 1.f;
    935         ret.f_[6] = 0;
    936         ret.f_[7] = 0;
    937         ret.f_[8] = 0;
    938         ret.f_[9] = 0;
    939         ret.f_[10] = 1.f;
    940         ret.f_[11] = 0;
    941         ret.f_[12] = 0;
    942         ret.f_[13] = 0;
    943         ret.f_[14] = 0;
    944         ret.f_[15] = 1.f;
    945         return ret;
    946     }
    947 
    948     void Dump()
    949     {
    950         LOGI( "%f %f %f %f", f_[0], f_[1], f_[2], f_[3] );
    951         LOGI( "%f %f %f %f", f_[4], f_[5], f_[6], f_[7] );
    952         LOGI( "%f %f %f %f", f_[8], f_[9], f_[10], f_[11] );
    953         LOGI( "%f %f %f %f", f_[12], f_[13], f_[14], f_[15] );
    954     }
    955 };
    956 
    957 /******************************************************************
    958  * Quaternion class
    959  *
    960  */
    961 class Quaternion
    962 {
    963 private:
    964     float x_, y_, z_, w_;
    965 
    966 public:
    967     friend class Vec3;
    968     friend class Vec4;
    969     friend class Mat4;
    970 
    971     Quaternion()
    972     {
    973         x_ = 0.f;
    974         y_ = 0.f;
    975         z_ = 0.f;
    976         w_ = 1.f;
    977     }
    978 
    979     Quaternion( const float fX, const float fY, const float fZ, const float fW )
    980     {
    981         x_ = fX;
    982         y_ = fY;
    983         z_ = fZ;
    984         w_ = fW;
    985     }
    986 
    987     Quaternion( const Vec3 vec, const float fW )
    988     {
    989         x_ = vec.x_;
    990         y_ = vec.y_;
    991         z_ = vec.z_;
    992         w_ = fW;
    993     }
    994 
    995     Quaternion( const float* p )
    996     {
    997         x_ = *p++;
    998         y_ = *p++;
    999         z_ = *p++;
   1000         w_ = *p++;
   1001     }
   1002 
   1003     Quaternion operator*( const Quaternion rhs )
   1004     {
   1005         Quaternion ret;
   1006         ret.x_ = x_ * rhs.w_ + y_ * rhs.z_ - z_ * rhs.y_ + w_ * rhs.x_;
   1007         ret.y_ = -x_ * rhs.z_ + y_ * rhs.w_ + z_ * rhs.x_ + w_ * rhs.y_;
   1008         ret.z_ = x_ * rhs.y_ - y_ * rhs.x_ + z_ * rhs.w_ + w_ * rhs.z_;
   1009         ret.w_ = -x_ * rhs.x_ - y_ * rhs.y_ - z_ * rhs.z_ + w_ * rhs.w_;
   1010         return ret;
   1011     }
   1012 
   1013     Quaternion& operator*=( const Quaternion rhs )
   1014     {
   1015         Quaternion ret;
   1016         ret.x_ = x_ * rhs.w_ + y_ * rhs.z_ - z_ * rhs.y_ + w_ * rhs.x_;
   1017         ret.y_ = -x_ * rhs.z_ + y_ * rhs.w_ + z_ * rhs.x_ + w_ * rhs.y_;
   1018         ret.z_ = x_ * rhs.y_ - y_ * rhs.x_ + z_ * rhs.w_ + w_ * rhs.z_;
   1019         ret.w_ = -x_ * rhs.x_ - y_ * rhs.y_ - z_ * rhs.z_ + w_ * rhs.w_;
   1020         *this = ret;
   1021         return *this;
   1022     }
   1023 
   1024     Quaternion Conjugate()
   1025     {
   1026         x_ = -x_;
   1027         y_ = -y_;
   1028         z_ = -z_;
   1029         return *this;
   1030     }
   1031 
   1032     //Non destuctive version
   1033     Quaternion Conjugated()
   1034     {
   1035         Quaternion ret;
   1036         ret.x_ = -x_;
   1037         ret.y_ = -y_;
   1038         ret.z_ = -z_;
   1039         ret.w_ = w_;
   1040         return ret;
   1041     }
   1042 
   1043     void ToMatrix( Mat4& mat )
   1044     {
   1045         float x2 = x_ * x_ * 2.0f;
   1046         float y2 = y_ * y_ * 2.0f;
   1047         float z2 = z_ * z_ * 2.0f;
   1048         float xy = x_ * y_ * 2.0f;
   1049         float yz = y_ * z_ * 2.0f;
   1050         float zx = z_ * x_ * 2.0f;
   1051         float xw = x_ * w_ * 2.0f;
   1052         float yw = y_ * w_ * 2.0f;
   1053         float zw = z_ * w_ * 2.0f;
   1054 
   1055         mat.f_[0] = 1.0f - y2 - z2;
   1056         mat.f_[1] = xy + zw;
   1057         mat.f_[2] = zx - yw;
   1058         mat.f_[4] = xy - zw;
   1059         mat.f_[5] = 1.0f - z2 - x2;
   1060         mat.f_[6] = yz + xw;
   1061         mat.f_[8] = zx + yw;
   1062         mat.f_[9] = yz - xw;
   1063         mat.f_[10] = 1.0f - x2 - y2;
   1064 
   1065         mat.f_[3] = mat.f_[7] = mat.f_[11] = mat.f_[12] = mat.f_[13] = mat.f_[14] = 0.0f;
   1066         mat.f_[15] = 1.0f;
   1067     }
   1068 
   1069     void ToMatrixPreserveTranslate( Mat4& mat )
   1070     {
   1071         float x2 = x_ * x_ * 2.0f;
   1072         float y2 = y_ * y_ * 2.0f;
   1073         float z2 = z_ * z_ * 2.0f;
   1074         float xy = x_ * y_ * 2.0f;
   1075         float yz = y_ * z_ * 2.0f;
   1076         float zx = z_ * x_ * 2.0f;
   1077         float xw = x_ * w_ * 2.0f;
   1078         float yw = y_ * w_ * 2.0f;
   1079         float zw = z_ * w_ * 2.0f;
   1080 
   1081         mat.f_[0] = 1.0f - y2 - z2;
   1082         mat.f_[1] = xy + zw;
   1083         mat.f_[2] = zx - yw;
   1084         mat.f_[4] = xy - zw;
   1085         mat.f_[5] = 1.0f - z2 - x2;
   1086         mat.f_[6] = yz + xw;
   1087         mat.f_[8] = zx + yw;
   1088         mat.f_[9] = yz - xw;
   1089         mat.f_[10] = 1.0f - x2 - y2;
   1090 
   1091         mat.f_[3] = mat.f_[7] = mat.f_[11] = 0.0f;
   1092         mat.f_[15] = 1.0f;
   1093     }
   1094 
   1095     static Quaternion RotationAxis( const Vec3 axis, const float angle )
   1096     {
   1097         Quaternion ret;
   1098         float s = sinf( angle / 2 );
   1099         ret.x_ = s * axis.x_;
   1100         ret.y_ = s * axis.y_;
   1101         ret.z_ = s * axis.z_;
   1102         ret.w_ = cosf( angle / 2 );
   1103         return ret;
   1104     }
   1105 
   1106     void Value( float& fX, float& fY, float& fZ, float& fW )
   1107     {
   1108         fX = x_;
   1109         fY = y_;
   1110         fZ = z_;
   1111         fW = w_;
   1112     }
   1113 };
   1114 
   1115 } //namespace ndk_helper
   1116 #endif /* VECMATH_H_ */
   1117