/* * Copyright 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef UI_MAT4_H #define UI_MAT4_H #include #include #include #include #define TMAT_IMPLEMENTATION #include #define PURE __attribute__((pure)) namespace android { // ------------------------------------------------------------------------------------- template class tmat44 : public TVecUnaryOperators, public TVecComparisonOperators { public: enum no_init { NO_INIT }; typedef T value_type; typedef T& reference; typedef T const& const_reference; typedef size_t size_type; typedef tvec4 col_type; typedef tvec4 row_type; // size of a column (i.e.: number of rows) enum { COL_SIZE = col_type::SIZE }; static inline size_t col_size() { return COL_SIZE; } // size of a row (i.e.: number of columns) enum { ROW_SIZE = row_type::SIZE }; static inline size_t row_size() { return ROW_SIZE; } static inline size_t size() { return row_size(); } // for TVec*<> private: /* * <-- N columns --> * * a00 a10 a20 ... aN0 ^ * a01 a11 a21 ... aN1 | * a02 a12 a22 ... aN2 M rows * ... | * a0M a1M a2M ... aNM v * * COL_SIZE = M * ROW_SIZE = N * m[0] = [a00 a01 a02 ... a01M] */ col_type mValue[ROW_SIZE]; public: // array access inline col_type const& operator [] (size_t i) const { return mValue[i]; } inline col_type& operator [] (size_t i) { return mValue[i]; } T const* asArray() const { return &mValue[0][0]; } // ----------------------------------------------------------------------- // we don't provide copy-ctor and operator= on purpose // because we want the compiler generated versions /* * constructors */ // leaves object uninitialized. use with caution. explicit tmat44(no_init) { } // initialize to identity tmat44(); // initialize to Identity*scalar. template explicit tmat44(U v); // sets the diagonal to the passed vector template explicit tmat44(const tvec4& rhs); // construct from another matrix of the same size template explicit tmat44(const tmat44& rhs); // construct from 4 column vectors template tmat44(const tvec4& v0, const tvec4& v1, const tvec4& v2, const tvec4& v3); // construct from a C array template explicit tmat44(U const* rawArray); /* * helpers */ static tmat44 ortho(T left, T right, T bottom, T top, T near, T far); static tmat44 frustum(T left, T right, T bottom, T top, T near, T far); template static tmat44 lookAt(const tvec3& eye, const tvec3& center, const tvec3& up); template static tmat44 translate(const tvec4& t); template static tmat44 scale(const tvec4& s); template static tmat44 rotate(A radian, const tvec3& about); /* * Compound assignment arithmetic operators */ // add another matrix of the same size template tmat44& operator += (const tmat44& v); // subtract another matrix of the same size template tmat44& operator -= (const tmat44& v); // multiply by a scalar template tmat44& operator *= (U v); // divide by a scalar template tmat44& operator /= (U v); /* * debugging */ String8 asString() const; }; // ---------------------------------------------------------------------------------------- // Constructors // ---------------------------------------------------------------------------------------- /* * Since the matrix code could become pretty big quickly, we don't inline most * operations. */ template tmat44::tmat44() { mValue[0] = col_type(1,0,0,0); mValue[1] = col_type(0,1,0,0); mValue[2] = col_type(0,0,1,0); mValue[3] = col_type(0,0,0,1); } template template tmat44::tmat44(U v) { mValue[0] = col_type(v,0,0,0); mValue[1] = col_type(0,v,0,0); mValue[2] = col_type(0,0,v,0); mValue[3] = col_type(0,0,0,v); } template template tmat44::tmat44(const tvec4& v) { mValue[0] = col_type(v.x,0,0,0); mValue[1] = col_type(0,v.y,0,0); mValue[2] = col_type(0,0,v.z,0); mValue[3] = col_type(0,0,0,v.w); } template template tmat44::tmat44(const tmat44& rhs) { for (size_t r=0 ; r template tmat44::tmat44(const tvec4& v0, const tvec4& v1, const tvec4& v2, const tvec4& v3) { mValue[0] = v0; mValue[1] = v1; mValue[2] = v2; mValue[3] = v3; } template template tmat44::tmat44(U const* rawArray) { for (size_t r=0 ; r tmat44 tmat44::ortho(T left, T right, T bottom, T top, T near, T far) { tmat44 m; m[0][0] = 2 / (right - left); m[1][1] = 2 / (top - bottom); m[2][2] = -2 / (far - near); m[3][0] = -(right + left) / (right - left); m[3][1] = -(top + bottom) / (top - bottom); m[3][2] = -(far + near) / (far - near); return m; } template tmat44 tmat44::frustum(T left, T right, T bottom, T top, T near, T far) { tmat44 m; T A = (right + left) / (right - left); T B = (top + bottom) / (top - bottom); T C = (far + near) / (far - near); T D = (2 * far * near) / (far - near); m[0][0] = (2 * near) / (right - left); m[1][1] = (2 * near) / (top - bottom); m[2][0] = A; m[2][1] = B; m[2][2] = C; m[2][3] =-1; m[3][2] = D; m[3][3] = 0; return m; } template template tmat44 tmat44::lookAt(const tvec3& eye, const tvec3& center, const tvec3& up) { tvec3 L(normalize(center - eye)); tvec3 S(normalize( cross(L, up) )); tvec3 U(cross(S, L)); return tmat44( tvec4( S, 0), tvec4( U, 0), tvec4(-L, 0), tvec4(-eye, 1)); } template template tmat44 tmat44::translate(const tvec4& t) { tmat44 r; r[3] = t; return r; } template template tmat44 tmat44::scale(const tvec4& s) { tmat44 r; r[0][0] = s[0]; r[1][1] = s[1]; r[2][2] = s[2]; r[3][3] = s[3]; return r; } template template tmat44 tmat44::rotate(A radian, const tvec3& about) { tmat44 rotation; T* r = const_cast(rotation.asArray()); T c = cos(radian); T s = sin(radian); if (about.x==1 && about.y==0 && about.z==0) { r[5] = c; r[10]= c; r[6] = s; r[9] = -s; } else if (about.x==0 && about.y==1 && about.z==0) { r[0] = c; r[10]= c; r[8] = s; r[2] = -s; } else if (about.x==0 && about.y==0 && about.z==1) { r[0] = c; r[5] = c; r[1] = s; r[4] = -s; } else { tvec3 nabout = normalize(about); B x = nabout.x; B y = nabout.y; B z = nabout.z; T nc = 1 - c; T xy = x * y; T yz = y * z; T zx = z * x; T xs = x * s; T ys = y * s; T zs = z * s; r[ 0] = x*x*nc + c; r[ 4] = xy*nc - zs; r[ 8] = zx*nc + ys; r[ 1] = xy*nc + zs; r[ 5] = y*y*nc + c; r[ 9] = yz*nc - xs; r[ 2] = zx*nc - ys; r[ 6] = yz*nc + xs; r[10] = z*z*nc + c; } } // ---------------------------------------------------------------------------------------- // Compound assignment arithmetic operators // ---------------------------------------------------------------------------------------- template template tmat44& tmat44::operator += (const tmat44& v) { for (size_t r=0 ; r template tmat44& tmat44::operator -= (const tmat44& v) { for (size_t r=0 ; r template tmat44& tmat44::operator *= (U v) { for (size_t r=0 ; r template tmat44& tmat44::operator /= (U v) { for (size_t r=0 ; r tmat44 PURE operator +(const tmat44& lhs, const tmat44& rhs) { tmat44 result(tmat44::NO_INIT); for (size_t r=0 ; r::row_size() ; r++) result[r] = lhs[r] + rhs[r]; return result; } // matrix - matrix, result is a matrix of the same type than the lhs matrix template tmat44 PURE operator -(const tmat44& lhs, const tmat44& rhs) { tmat44 result(tmat44::NO_INIT); for (size_t r=0 ; r::row_size() ; r++) result[r] = lhs[r] - rhs[r]; return result; } // matrix * vector, result is a vector of the same type than the input vector template typename tmat44::col_type PURE operator *(const tmat44& lv, const tvec4& rv) { typename tmat44::col_type result; for (size_t r=0 ; r::row_size() ; r++) result += rv[r]*lv[r]; return result; } // vector * matrix, result is a vector of the same type than the input vector template typename tmat44::row_type PURE operator *(const tvec4& rv, const tmat44& lv) { typename tmat44::row_type result(tmat44::row_type::NO_INIT); for (size_t r=0 ; r::row_size() ; r++) result[r] = dot(rv, lv[r]); return result; } // matrix * scalar, result is a matrix of the same type than the input matrix template tmat44 PURE operator *(const tmat44& lv, U rv) { tmat44 result(tmat44::NO_INIT); for (size_t r=0 ; r::row_size() ; r++) result[r] = lv[r]*rv; return result; } // scalar * matrix, result is a matrix of the same type than the input matrix template tmat44 PURE operator *(U rv, const tmat44& lv) { tmat44 result(tmat44::NO_INIT); for (size_t r=0 ; r::row_size() ; r++) result[r] = lv[r]*rv; return result; } // matrix * matrix, result is a matrix of the same type than the lhs matrix template tmat44 PURE operator *(const tmat44& lhs, const tmat44& rhs) { return matrix::multiply< tmat44 >(lhs, rhs); } // ---------------------------------------------------------------------------------------- // Functions // ---------------------------------------------------------------------------------------- // inverse a matrix template tmat44 PURE inverse(const tmat44& m) { return matrix::inverse(m); } template tmat44 PURE transpose(const tmat44& m) { return matrix::transpose(m); } template T PURE trace(const tmat44& m) { return matrix::trace(m); } template tvec4 PURE diag(const tmat44& m) { return matrix::diag(m); } // ---------------------------------------------------------------------------------------- // Debugging // ---------------------------------------------------------------------------------------- template String8 tmat44::asString() const { return matrix::asString(*this); } // ---------------------------------------------------------------------------------------- typedef tmat44 mat4; // ---------------------------------------------------------------------------------------- }; // namespace android #undef PURE #endif /* UI_MAT4_H */