diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/ui/TMatHelpers.h | 179 | ||||
-rw-r--r-- | include/ui/TVecHelpers.h | 348 | ||||
-rw-r--r-- | include/ui/mat4.h | 473 | ||||
-rw-r--r-- | include/ui/vec2.h | 85 | ||||
-rw-r--r-- | include/ui/vec3.h | 106 | ||||
-rw-r--r-- | include/ui/vec4.h | 110 |
6 files changed, 1301 insertions, 0 deletions
diff --git a/include/ui/TMatHelpers.h b/include/ui/TMatHelpers.h new file mode 100644 index 0000000..b778af0 --- /dev/null +++ b/include/ui/TMatHelpers.h @@ -0,0 +1,179 @@ +/* + * 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 TMAT_IMPLEMENTATION +#error "Don't include TMatHelpers.h directly. use ui/mat*.h instead" +#else +#undef TMAT_IMPLEMENTATION +#endif + + +#ifndef UI_TMAT_HELPERS_H +#define UI_TMAT_HELPERS_H + +#include <stdint.h> +#include <sys/types.h> +#include <utils/Debug.h> +#include <utils/String8.h> + +#define PURE __attribute__((pure)) + +namespace android { +// ------------------------------------------------------------------------------------- + +/* + * No user serviceable parts here. + * + * Don't use this file directly, instead include ui/mat*.h + */ + + +/* + * Matrix utilities + */ + +namespace matrix { + +inline int PURE transpose(int v) { return v; } +inline float PURE transpose(float v) { return v; } +inline double PURE transpose(double v) { return v; } + +inline int PURE trace(int v) { return v; } +inline float PURE trace(float v) { return v; } +inline double PURE trace(double v) { return v; } + +template<typename MATRIX> +MATRIX PURE inverse(const MATRIX& src) { + + COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::COL_SIZE == MATRIX::ROW_SIZE ); + + typename MATRIX::value_type t; + const size_t N = MATRIX::col_size(); + size_t swap; + MATRIX tmp(src); + MATRIX inverse(1); + + for (size_t i=0 ; i<N ; i++) { + // look for largest element in column + swap = i; + for (size_t j=i+1 ; j<N ; j++) { + if (fabs(tmp[j][i]) > fabs(tmp[i][i])) { + swap = j; + } + } + + if (swap != i) { + /* swap rows. */ + for (size_t k=0 ; k<N ; k++) { + t = tmp[i][k]; + tmp[i][k] = tmp[swap][k]; + tmp[swap][k] = t; + + t = inverse[i][k]; + inverse[i][k] = inverse[swap][k]; + inverse[swap][k] = t; + } + } + + t = 1 / tmp[i][i]; + for (size_t k=0 ; k<N ; k++) { + tmp[i][k] *= t; + inverse[i][k] *= t; + } + for (size_t j=0 ; j<N ; j++) { + if (j != i) { + t = tmp[j][i]; + for (size_t k=0 ; k<N ; k++) { + tmp[j][k] -= tmp[i][k] * t; + inverse[j][k] -= inverse[i][k] * t; + } + } + } + } + return inverse; +} + +template<typename MATRIX_R, typename MATRIX_A, typename MATRIX_B> +MATRIX_R PURE multiply(const MATRIX_A& lhs, const MATRIX_B& rhs) { + // pre-requisite: + // lhs : D columns, R rows + // rhs : C columns, D rows + // res : C columns, R rows + + COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_A::ROW_SIZE == MATRIX_B::COL_SIZE ); + COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::ROW_SIZE == MATRIX_B::ROW_SIZE ); + COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::COL_SIZE == MATRIX_A::COL_SIZE ); + + MATRIX_R res(MATRIX_R::NO_INIT); + for (size_t r=0 ; r<MATRIX_R::row_size() ; r++) { + res[r] = lhs * rhs[r]; + } + return res; +} + +// transpose. this handles matrices of matrices +template <typename MATRIX> +MATRIX PURE transpose(const MATRIX& m) { + // for now we only handle square matrix transpose + COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE ); + MATRIX result(MATRIX::NO_INIT); + for (size_t r=0 ; r<MATRIX::row_size() ; r++) + for (size_t c=0 ; c<MATRIX::col_size() ; c++) + result[c][r] = transpose(m[r][c]); + return result; +} + +// trace. this handles matrices of matrices +template <typename MATRIX> +typename MATRIX::value_type PURE trace(const MATRIX& m) { + COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE ); + typename MATRIX::value_type result(0); + for (size_t r=0 ; r<MATRIX::row_size() ; r++) + result += trace(m[r][r]); + return result; +} + +// trace. this handles matrices of matrices +template <typename MATRIX> +typename MATRIX::col_type PURE diag(const MATRIX& m) { + COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE ); + typename MATRIX::col_type result(MATRIX::col_type::NO_INIT); + for (size_t r=0 ; r<MATRIX::row_size() ; r++) + result[r] = m[r][r]; + return result; +} + +template <typename MATRIX> +String8 asString(const MATRIX& m) { + String8 s; + for (size_t c=0 ; c<MATRIX::col_size() ; c++) { + s.append("| "); + for (size_t r=0 ; r<MATRIX::row_size() ; r++) { + s.appendFormat("%7.2f ", m[r][c]); + } + s.append("|\n"); + } + return s; +} + +}; // namespace matrix + +// ------------------------------------------------------------------------------------- +}; // namespace android + +#undef PURE + +#endif /* UI_TMAT_HELPERS_H */ diff --git a/include/ui/TVecHelpers.h b/include/ui/TVecHelpers.h new file mode 100644 index 0000000..081c69c --- /dev/null +++ b/include/ui/TVecHelpers.h @@ -0,0 +1,348 @@ +/* + * 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 TVEC_IMPLEMENTATION +#error "Don't include TVecHelpers.h directly. use ui/vec*.h instead" +#else +#undef TVEC_IMPLEMENTATION +#endif + + +#ifndef UI_TVEC_HELPERS_H +#define UI_TVEC_HELPERS_H + +#include <stdint.h> +#include <sys/types.h> + +#define PURE __attribute__((pure)) + +namespace android { +// ------------------------------------------------------------------------------------- + +/* + * No user serviceable parts here. + * + * Don't use this file directly, instead include ui/vec{2|3|4}.h + */ + +/* + * This class casts itself into anything and assign itself from anything! + * Use with caution! + */ +template <typename TYPE> +struct Impersonator { + Impersonator& operator = (const TYPE& rhs) { + reinterpret_cast<TYPE&>(*this) = rhs; + return *this; + } + operator TYPE& () { + return reinterpret_cast<TYPE&>(*this); + } + operator TYPE const& () const { + return reinterpret_cast<TYPE const&>(*this); + } +}; + +/* + * TVecArithmeticOperators implements basic arithmetic and basic compound assignments + * operators on a vector of type BASE<T>. + * + * BASE only needs to implement operator[] and size(). + * By simply inheriting from TVecArithmeticOperators<BASE, T> BASE will automatically + * get all the functionality here. + */ + +template <template<typename T> class BASE, typename T> +class TVecArithmeticOperators { +public: + /* compound assignment from a another vector of the same size but different + * element type. + */ + template <typename OTHER> + BASE<T>& operator += (const BASE<OTHER>& v) { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + rhs[i] += v[i]; + } + return rhs; + } + template <typename OTHER> + BASE<T>& operator -= (const BASE<OTHER>& v) { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + rhs[i] -= v[i]; + } + return rhs; + } + template <typename OTHER> + BASE<T>& operator *= (const BASE<OTHER>& v) { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + rhs[i] *= v[i]; + } + return rhs; + } + template <typename OTHER> + BASE<T>& operator /= (const BASE<OTHER>& v) { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + rhs[i] /= v[i]; + } + return rhs; + } + + /* compound assignment from a another vector of the same type. + * These operators can be used for implicit conversion and handle operations + * like "vector *= scalar" by letting the compiler implicitly convert a scalar + * to a vector (assuming the BASE<T> allows it). + */ + BASE<T>& operator += (const BASE<T>& v) { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + rhs[i] += v[i]; + } + return rhs; + } + BASE<T>& operator -= (const BASE<T>& v) { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + rhs[i] -= v[i]; + } + return rhs; + } + BASE<T>& operator *= (const BASE<T>& v) { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + rhs[i] *= v[i]; + } + return rhs; + } + BASE<T>& operator /= (const BASE<T>& v) { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + rhs[i] /= v[i]; + } + return rhs; + } + + /* + * NOTE: the functions below ARE NOT member methods. They are friend functions + * with they definition inlined with their declaration. This makes these + * template functions available to the compiler when (and only when) this class + * is instantiated, at which point they're only templated on the 2nd parameter + * (the first one, BASE<T> being known). + */ + + /* The operators below handle operation between vectors of the same side + * but of a different element type. + */ + template<typename RT> + friend inline + BASE<T> PURE operator +(const BASE<T>& lv, const BASE<RT>& rv) { + return BASE<T>(lv) += rv; + } + template<typename RT> + friend inline + BASE<T> PURE operator -(const BASE<T>& lv, const BASE<RT>& rv) { + return BASE<T>(lv) -= rv; + } + template<typename RT> + friend inline + BASE<T> PURE operator *(const BASE<T>& lv, const BASE<RT>& rv) { + return BASE<T>(lv) *= rv; + } + template<typename RT> + friend inline + BASE<T> PURE operator /(const BASE<T>& lv, const BASE<RT>& rv) { + return BASE<T>(lv) /= rv; + } + + /* The operators below (which are not templates once this class is instanced, + * i.e.: BASE<T> is known) can be used for implicit conversion on both sides. + * These handle operations like "vector * scalar" and "scalar * vector" by + * letting the compiler implicitly convert a scalar to a vector (assuming + * the BASE<T> allows it). + */ + friend inline + BASE<T> PURE operator +(const BASE<T>& lv, const BASE<T>& rv) { + return BASE<T>(lv) += rv; + } + friend inline + BASE<T> PURE operator -(const BASE<T>& lv, const BASE<T>& rv) { + return BASE<T>(lv) -= rv; + } + friend inline + BASE<T> PURE operator *(const BASE<T>& lv, const BASE<T>& rv) { + return BASE<T>(lv) *= rv; + } + friend inline + BASE<T> PURE operator /(const BASE<T>& lv, const BASE<T>& rv) { + return BASE<T>(lv) /= rv; + } +}; + +/* + * TVecUnaryOperators implements unary operators on a vector of type BASE<T>. + * + * BASE only needs to implement operator[] and size(). + * By simply inheriting from TVecUnaryOperators<BASE, T> BASE will automatically + * get all the functionality here. + * + * These operators are implemented as friend functions of TVecUnaryOperators<BASE, T> + */ +template <template<typename T> class BASE, typename T> +class TVecUnaryOperators { +public: + BASE<T>& operator ++ () { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + ++rhs[i]; + } + return rhs; + } + BASE<T>& operator -- () { + BASE<T>& rhs = static_cast<BASE<T>&>(*this); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + --rhs[i]; + } + return rhs; + } + BASE<T> operator - () const { + BASE<T> r(BASE<T>::NO_INIT); + BASE<T> const& rv(static_cast<BASE<T> const&>(*this)); + for (size_t i=0 ; i<BASE<T>::size() ; i++) { + r[i] = -rv[i]; + } + return r; + } +}; + + +/* + * TVecComparisonOperators implements relational/comparison operators + * on a vector of type BASE<T>. + * + * BASE only needs to implement operator[] and size(). + * By simply inheriting from TVecComparisonOperators<BASE, T> BASE will automatically + * get all the functionality here. + */ +template <template<typename T> class BASE, typename T> +class TVecComparisonOperators { +public: + /* + * NOTE: the functions below ARE NOT member methods. They are friend functions + * with they definition inlined with their declaration. This makes these + * template functions available to the compiler when (and only when) this class + * is instantiated, at which point they're only templated on the 2nd parameter + * (the first one, BASE<T> being known). + */ + template<typename RT> + friend inline + bool PURE operator ==(const BASE<T>& lv, const BASE<RT>& rv) { + for (size_t i = 0; i < BASE<T>::size(); i++) + if (lv[i] != rv[i]) + return false; + return true; + } + + template<typename RT> + friend inline + bool PURE operator !=(const BASE<T>& lv, const BASE<RT>& rv) { + return !operator ==(lv, rv); + } + + template<typename RT> + friend inline + bool PURE operator >(const BASE<T>& lv, const BASE<RT>& rv) { + for (size_t i = 0; i < BASE<T>::size(); i++) + if (lv[i] <= rv[i]) + return false; + return true; + } + + template<typename RT> + friend inline + bool PURE operator <=(const BASE<T>& lv, const BASE<RT>& rv) { + return !(lv > rv); + } + + template<typename RT> + friend inline + bool PURE operator <(const BASE<T>& lv, const BASE<RT>& rv) { + for (size_t i = 0; i < BASE<T>::size(); i++) + if (lv[i] >= rv[i]) + return false; + return true; + } + + template<typename RT> + friend inline + bool PURE operator >=(const BASE<T>& lv, const BASE<RT>& rv) { + return !(lv < rv); + } +}; + + +/* + * TVecFunctions implements functions on a vector of type BASE<T>. + * + * BASE only needs to implement operator[] and size(). + * By simply inheriting from TVecFunctions<BASE, T> BASE will automatically + * get all the functionality here. + */ +template <template<typename T> class BASE, typename T> +class TVecFunctions { +public: + /* + * NOTE: the functions below ARE NOT member methods. They are friend functions + * with they definition inlined with their declaration. This makes these + * template functions available to the compiler when (and only when) this class + * is instantiated, at which point they're only templated on the 2nd parameter + * (the first one, BASE<T> being known). + */ + template<typename RT> + friend inline + T PURE dot(const BASE<T>& lv, const BASE<RT>& rv) { + T r(0); + for (size_t i = 0; i < BASE<T>::size(); i++) + r += lv[i]*rv[i]; + return r; + } + + friend inline + T PURE length(const BASE<T>& lv) { + return sqrt( dot(lv, lv) ); + } + + template<typename RT> + friend inline + T PURE distance(const BASE<T>& lv, const BASE<RT>& rv) { + return length(rv - lv); + } + + friend inline + BASE<T> PURE normalize(const BASE<T>& lv) { + return lv * (1 / length(lv)); + } +}; + +#undef PURE + +// ------------------------------------------------------------------------------------- +}; // namespace android + + +#endif /* UI_TVEC_HELPERS_H */ diff --git a/include/ui/mat4.h b/include/ui/mat4.h new file mode 100644 index 0000000..08a67c7 --- /dev/null +++ b/include/ui/mat4.h @@ -0,0 +1,473 @@ +/* + * 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 <stdint.h> +#include <sys/types.h> + +#include <ui/vec4.h> +#include <utils/String8.h> + +#define TMAT_IMPLEMENTATION +#include <ui/TMatHelpers.h> + +#define PURE __attribute__((pure)) + +namespace android { +// ------------------------------------------------------------------------------------- + +template <typename T> +class tmat44 : public TVecUnaryOperators<tmat44, T>, + public TVecComparisonOperators<tmat44, T> +{ +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<T> col_type; + typedef tvec4<T> 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<typename U> + explicit tmat44(U v); + + // sets the diagonal to the passed vector + template <typename U> + explicit tmat44(const tvec4<U>& rhs); + + // construct from another matrix of the same size + template <typename U> + explicit tmat44(const tmat44<U>& rhs); + + // construct from 4 column vectors + template <typename A, typename B, typename C, typename D> + tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3); + + // construct from a C array + template <typename U> + 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 <typename A, typename B, typename C> + static tmat44 lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up); + + template <typename A> + static tmat44 translate(const tvec4<A>& t); + + template <typename A> + static tmat44 scale(const tvec4<A>& s); + + template <typename A, typename B> + static tmat44 rotate(A radian, const tvec3<B>& about); + + + /* + * Compound assignment arithmetic operators + */ + + // add another matrix of the same size + template <typename U> + tmat44& operator += (const tmat44<U>& v); + + // subtract another matrix of the same size + template <typename U> + tmat44& operator -= (const tmat44<U>& v); + + // multiply by a scalar + template <typename U> + tmat44& operator *= (U v); + + // divide by a scalar + template <typename U> + 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 <typename T> +tmat44<T>::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 <typename T> +template <typename U> +tmat44<T>::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<typename T> +template<typename U> +tmat44<T>::tmat44(const tvec4<U>& 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 <typename T> +template <typename U> +tmat44<T>::tmat44(const tmat44<U>& rhs) { + for (size_t r=0 ; r<row_size() ; r++) + mValue[r] = rhs[r]; +} + +template <typename T> +template <typename A, typename B, typename C, typename D> +tmat44<T>::tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3) { + mValue[0] = v0; + mValue[1] = v1; + mValue[2] = v2; + mValue[3] = v3; +} + +template <typename T> +template <typename U> +tmat44<T>::tmat44(U const* rawArray) { + for (size_t r=0 ; r<row_size() ; r++) + for (size_t c=0 ; c<col_size() ; c++) + mValue[r][c] = *rawArray++; +} + +// ---------------------------------------------------------------------------------------- +// Helpers +// ---------------------------------------------------------------------------------------- + +template <typename T> +tmat44<T> tmat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) { + tmat44<T> 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 <typename T> +tmat44<T> tmat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) { + tmat44<T> 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 <typename T> +template <typename A, typename B, typename C> +tmat44<T> tmat44<T>::lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up) { + tvec3<T> L(normalize(center - eye)); + tvec3<T> S(normalize( cross(L, up) )); + tvec3<T> U(cross(S, L)); + return tmat44<T>( + tvec4<T>( S, 0), + tvec4<T>( U, 0), + tvec4<T>(-L, 0), + tvec4<T>(-eye, 1)); +} + +template <typename T> +template <typename A> +tmat44<T> tmat44<T>::translate(const tvec4<A>& t) { + tmat44<T> r; + r[3] = t; + return r; +} + +template <typename T> +template <typename A> +tmat44<T> tmat44<T>::scale(const tvec4<A>& s) { + tmat44<T> r; + r[0][0] = s[0]; + r[1][1] = s[1]; + r[2][2] = s[2]; + r[3][3] = s[3]; + return r; +} + +template <typename T> +template <typename A, typename B> +tmat44<T> tmat44<T>::rotate(A radian, const tvec3<B>& about) { + tmat44<T> rotation; + T* r = const_cast<T*>(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<B> 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 <typename T> +template <typename U> +tmat44<T>& tmat44<T>::operator += (const tmat44<U>& v) { + for (size_t r=0 ; r<row_size() ; r++) + mValue[r] += v[r]; + return *this; +} + +template <typename T> +template <typename U> +tmat44<T>& tmat44<T>::operator -= (const tmat44<U>& v) { + for (size_t r=0 ; r<row_size() ; r++) + mValue[r] -= v[r]; + return *this; +} + +template <typename T> +template <typename U> +tmat44<T>& tmat44<T>::operator *= (U v) { + for (size_t r=0 ; r<row_size() ; r++) + mValue[r] *= v; + return *this; +} + +template <typename T> +template <typename U> +tmat44<T>& tmat44<T>::operator /= (U v) { + for (size_t r=0 ; r<row_size() ; r++) + mValue[r] /= v; + return *this; +} + +// ---------------------------------------------------------------------------------------- +// Arithmetic operators outside of class +// ---------------------------------------------------------------------------------------- + +/* We use non-friend functions here to prevent the compiler from using + * implicit conversions, for instance of a scalar to a vector. The result would + * not be what the caller expects. + * + * Also note that the order of the arguments in the inner loop is important since + * it determines the output type (only relevant when T != U). + */ + +// matrix + matrix, result is a matrix of the same type than the lhs matrix +template <typename T, typename U> +tmat44<T> PURE operator +(const tmat44<T>& lhs, const tmat44<U>& rhs) { + tmat44<T> result(tmat44<T>::NO_INIT); + for (size_t r=0 ; r<tmat44<T>::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 <typename T, typename U> +tmat44<T> PURE operator -(const tmat44<T>& lhs, const tmat44<U>& rhs) { + tmat44<T> result(tmat44<T>::NO_INIT); + for (size_t r=0 ; r<tmat44<T>::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 T, typename U> +typename tmat44<U>::col_type PURE operator *(const tmat44<T>& lv, const tvec4<U>& rv) { + typename tmat44<U>::col_type result; + for (size_t r=0 ; r<tmat44<T>::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 T, typename U> +typename tmat44<U>::row_type PURE operator *(const tvec4<U>& rv, const tmat44<T>& lv) { + typename tmat44<U>::row_type result(tmat44<U>::row_type::NO_INIT); + for (size_t r=0 ; r<tmat44<T>::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 <typename T, typename U> +tmat44<T> PURE operator *(const tmat44<T>& lv, U rv) { + tmat44<T> result(tmat44<T>::NO_INIT); + for (size_t r=0 ; r<tmat44<T>::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 <typename T, typename U> +tmat44<T> PURE operator *(U rv, const tmat44<T>& lv) { + tmat44<T> result(tmat44<T>::NO_INIT); + for (size_t r=0 ; r<tmat44<T>::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 <typename T, typename U> +tmat44<T> PURE operator *(const tmat44<T>& lhs, const tmat44<U>& rhs) { + return matrix::multiply< tmat44<T> >(lhs, rhs); +} + +// ---------------------------------------------------------------------------------------- +// Functions +// ---------------------------------------------------------------------------------------- + +// inverse a matrix +template <typename T> +tmat44<T> PURE inverse(const tmat44<T>& m) { + return matrix::inverse(m); +} + +template <typename T> +tmat44<T> PURE transpose(const tmat44<T>& m) { + return matrix::transpose(m); +} + +template <typename T> +T PURE trace(const tmat44<T>& m) { + return matrix::trace(m); +} + +template <typename T> +tvec4<T> PURE diag(const tmat44<T>& m) { + return matrix::diag(m); +} + +// ---------------------------------------------------------------------------------------- +// Debugging +// ---------------------------------------------------------------------------------------- + +template <typename T> +String8 tmat44<T>::asString() const { + return matrix::asString(*this); +} + +// ---------------------------------------------------------------------------------------- + +typedef tmat44<float> mat4; + +// ---------------------------------------------------------------------------------------- +}; // namespace android + +#undef PURE + +#endif /* UI_MAT4_H */ diff --git a/include/ui/vec2.h b/include/ui/vec2.h new file mode 100644 index 0000000..b4edfc6 --- /dev/null +++ b/include/ui/vec2.h @@ -0,0 +1,85 @@ +/* + * 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_VEC2_H +#define UI_VEC2_H + +#include <stdint.h> +#include <sys/types.h> + +#define TVEC_IMPLEMENTATION +#include <ui/TVecHelpers.h> + +namespace android { +// ------------------------------------------------------------------------------------- + +template <typename T> +class tvec2 : public TVecArithmeticOperators<tvec2, T>, + public TVecUnaryOperators<tvec2, T>, + public TVecComparisonOperators<tvec2, T>, + public TVecFunctions<tvec2, T> +{ +public: + enum no_init { NO_INIT }; + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef size_t size_type; + + union { + struct { T x, y; }; + struct { T s, t; }; + struct { T r, g; }; + }; + + enum { SIZE = 2 }; + inline static size_type size() { return SIZE; } + + // array access + inline T const& operator [] (size_t i) const { return (&x)[i]; } + inline T& operator [] (size_t i) { return (&x)[i]; } + + // ----------------------------------------------------------------------- + // 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 tvec2(no_init) { } + + // default constructor + tvec2() : x(0), y(0) { } + + // handles implicit conversion to a tvec4. must not be explicit. + template<typename A> + tvec2(A v) : x(v), y(v) { } + + template<typename A, typename B> + tvec2(A x, B y) : x(x), y(y) { } + + template<typename A> + explicit tvec2(const tvec2<A>& v) : x(v.x), y(v.y) { } +}; + +// ---------------------------------------------------------------------------------------- + +typedef tvec2<float> vec2; + +// ---------------------------------------------------------------------------------------- +}; // namespace android + +#endif /* UI_VEC4_H */ diff --git a/include/ui/vec3.h b/include/ui/vec3.h new file mode 100644 index 0000000..591b8b2 --- /dev/null +++ b/include/ui/vec3.h @@ -0,0 +1,106 @@ +/* + * 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_VEC3_H +#define UI_VEC3_H + +#include <stdint.h> +#include <sys/types.h> + +#include <ui/vec2.h> + +namespace android { +// ------------------------------------------------------------------------------------- + +template <typename T> +class tvec3 : public TVecArithmeticOperators<tvec3, T>, + public TVecUnaryOperators<tvec3, T>, + public TVecComparisonOperators<tvec3, T>, + public TVecFunctions<tvec3, T> +{ +public: + enum no_init { NO_INIT }; + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef size_t size_type; + + union { + struct { T x, y, z; }; + struct { T s, t, p; }; + struct { T r, g, b; }; + Impersonator< tvec2<T> > xy; + Impersonator< tvec2<T> > st; + Impersonator< tvec2<T> > rg; + }; + + enum { SIZE = 3 }; + inline static size_type size() { return SIZE; } + + // array access + inline T const& operator [] (size_t i) const { return (&x)[i]; } + inline T& operator [] (size_t i) { return (&x)[i]; } + + // ----------------------------------------------------------------------- + // 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 tvec3(no_init) { } + + // default constructor + tvec3() : x(0), y(0), z(0) { } + + // handles implicit conversion to a tvec4. must not be explicit. + template<typename A> + tvec3(A v) : x(v), y(v), z(v) { } + + template<typename A, typename B, typename C> + tvec3(A x, B y, C z) : x(x), y(y), z(z) { } + + template<typename A, typename B> + tvec3(const tvec2<A>& v, B z) : x(v.x), y(v.y), z(z) { } + + template<typename A> + explicit tvec3(const tvec3<A>& v) : x(v.x), y(v.y), z(v.z) { } + + template<typename A, typename B> + tvec3(const Impersonator< tvec2<A> >& v, B z) + : x(((const tvec2<A>&)v).x), + y(((const tvec2<A>&)v).y), + z(z) { } + + // cross product works only on vectors of size 3 + template <typename RT> + friend inline + tvec3 __attribute__((pure)) cross(const tvec3& u, const tvec3<RT>& v) { + return tvec3( + u.y*v.z - u.z*v.y, + u.z*v.x - u.x*v.z, + u.x*v.y - u.y*v.x); + } +}; + + +// ---------------------------------------------------------------------------------------- + +typedef tvec3<float> vec3; + +// ---------------------------------------------------------------------------------------- +}; // namespace android + +#endif /* UI_VEC4_H */ diff --git a/include/ui/vec4.h b/include/ui/vec4.h new file mode 100644 index 0000000..798382d --- /dev/null +++ b/include/ui/vec4.h @@ -0,0 +1,110 @@ +/* + * 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_VEC4_H +#define UI_VEC4_H + +#include <stdint.h> +#include <sys/types.h> + +#include <ui/vec3.h> + +namespace android { +// ------------------------------------------------------------------------------------- + +template <typename T> +class tvec4 : public TVecArithmeticOperators<tvec4, T>, + public TVecUnaryOperators<tvec4, T>, + public TVecComparisonOperators<tvec4, T>, + public TVecFunctions<tvec4, T> +{ +public: + enum no_init { NO_INIT }; + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef size_t size_type; + + union { + struct { T x, y, z, w; }; + struct { T s, t, p, q; }; + struct { T r, g, b, a; }; + Impersonator< tvec2<T> > xy; + Impersonator< tvec2<T> > st; + Impersonator< tvec2<T> > rg; + Impersonator< tvec3<T> > xyz; + Impersonator< tvec3<T> > stp; + Impersonator< tvec3<T> > rgb; + }; + + enum { SIZE = 4 }; + inline static size_type size() { return SIZE; } + + // array access + inline T const& operator [] (size_t i) const { return (&x)[i]; } + inline T& operator [] (size_t i) { return (&x)[i]; } + + // ----------------------------------------------------------------------- + // 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 tvec4(no_init) { } + + // default constructor + tvec4() : x(0), y(0), z(0), w(0) { } + + // handles implicit conversion to a tvec4. must not be explicit. + template<typename A> + tvec4(A v) : x(v), y(v), z(v), w(v) { } + + template<typename A, typename B, typename C, typename D> + tvec4(A x, B y, C z, D w) : x(x), y(y), z(z), w(w) { } + + template<typename A, typename B, typename C> + tvec4(const tvec2<A>& v, B z, C w) : x(v.x), y(v.y), z(z), w(w) { } + + template<typename A, typename B> + tvec4(const tvec3<A>& v, B w) : x(v.x), y(v.y), z(v.z), w(w) { } + + template<typename A> + explicit tvec4(const tvec4<A>& v) : x(v.x), y(v.y), z(v.z), w(v.w) { } + + template<typename A, typename B> + tvec4(const Impersonator< tvec3<A> >& v, B w) + : x(((const tvec3<A>&)v).x), + y(((const tvec3<A>&)v).y), + z(((const tvec3<A>&)v).z), + w(w) { } + + template<typename A, typename B, typename C> + tvec4(const Impersonator< tvec2<A> >& v, B z, C w) + : x(((const tvec2<A>&)v).x), + y(((const tvec2<A>&)v).y), + z(z), + w(w) { } +}; + +// ---------------------------------------------------------------------------------------- + +typedef tvec4<float> vec4; + +// ---------------------------------------------------------------------------------------- +}; // namespace android + +#endif /* UI_VEC4_H */ |