vector and matrix classes for graphics use
- this implements vec2, vec3, vec4, which are float vectors of size 2, 3 and 4 respectively. the code allows easy instantiation of vectors of a different type via the tvec{2|3|4}<T> template classes. - this also implements mat4 which is a float 4x4 matrix. the tmat44<T> template class allows easy instantiation of a 4x4 matrix of a different value_type. The vector types have some minimal support for the glsl style swizzled access; for instance: vec4 u; vec3 v = u.xyz; only .x, .xy, .xyz and their .stpq / .rgba equivalent are supported. most operators are supported on both vector and matrices: arithmetic, unary, compound assignment and comparison (bit-wise operators NOT supported). - operations available on vectors include: dot, length, distance, normalize and cross - operations available on matrices include: transpose, inverse, trace - and a few utilities to create matrices: ortho, frustum, lookAt Change-Id: I64add89ae90fa78d3f2f59985b63495575378635
This commit is contained in:
parent
f2e4fcd96c
commit
595ea77f6b
179
include/ui/TMatHelpers.h
Normal file
179
include/ui/TMatHelpers.h
Normal file
@ -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 */
|
348
include/ui/TVecHelpers.h
Normal file
348
include/ui/TVecHelpers.h
Normal file
@ -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 */
|
473
include/ui/mat4.h
Normal file
473
include/ui/mat4.h
Normal file
@ -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 */
|
85
include/ui/vec2.h
Normal file
85
include/ui/vec2.h
Normal file
@ -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 */
|
106
include/ui/vec3.h
Normal file
106
include/ui/vec3.h
Normal file
@ -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 */
|
110
include/ui/vec4.h
Normal file
110
include/ui/vec4.h
Normal file
@ -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 */
|
@ -4,9 +4,12 @@ include $(CLEAR_VARS)
|
||||
|
||||
# Build the unit tests.
|
||||
test_src_files := \
|
||||
Region_test.cpp
|
||||
Region_test.cpp \
|
||||
vec_test.cpp \
|
||||
mat_test.cpp
|
||||
|
||||
shared_libraries := \
|
||||
libutils \
|
||||
libui
|
||||
|
||||
static_libraries := \
|
||||
|
139
libs/ui/tests/mat_test.cpp
Normal file
139
libs/ui/tests/mat_test.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "RegionTest"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ui/Region.h>
|
||||
#include <ui/Rect.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <ui/mat4.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class MatTest : public testing::Test {
|
||||
protected:
|
||||
};
|
||||
|
||||
TEST_F(MatTest, Basics) {
|
||||
mat4 m0;
|
||||
EXPECT_EQ(sizeof(mat4), sizeof(float)*16);
|
||||
}
|
||||
|
||||
TEST_F(MatTest, ComparisonOps) {
|
||||
mat4 m0;
|
||||
mat4 m1(2);
|
||||
|
||||
EXPECT_TRUE(m0 == m0);
|
||||
EXPECT_TRUE(m0 != m1);
|
||||
EXPECT_FALSE(m0 != m0);
|
||||
EXPECT_FALSE(m0 == m1);
|
||||
}
|
||||
|
||||
TEST_F(MatTest, Constructors) {
|
||||
mat4 m0;
|
||||
ASSERT_EQ(m0[0].x, 1);
|
||||
ASSERT_EQ(m0[0].y, 0);
|
||||
ASSERT_EQ(m0[0].z, 0);
|
||||
ASSERT_EQ(m0[0].w, 0);
|
||||
ASSERT_EQ(m0[1].x, 0);
|
||||
ASSERT_EQ(m0[1].y, 1);
|
||||
ASSERT_EQ(m0[1].z, 0);
|
||||
ASSERT_EQ(m0[1].w, 0);
|
||||
ASSERT_EQ(m0[2].x, 0);
|
||||
ASSERT_EQ(m0[2].y, 0);
|
||||
ASSERT_EQ(m0[2].z, 1);
|
||||
ASSERT_EQ(m0[2].w, 0);
|
||||
ASSERT_EQ(m0[3].x, 0);
|
||||
ASSERT_EQ(m0[3].y, 0);
|
||||
ASSERT_EQ(m0[3].z, 0);
|
||||
ASSERT_EQ(m0[3].w, 1);
|
||||
|
||||
mat4 m1(2);
|
||||
mat4 m2(vec4(2));
|
||||
mat4 m3(m2);
|
||||
|
||||
EXPECT_EQ(m1, m2);
|
||||
EXPECT_EQ(m2, m3);
|
||||
EXPECT_EQ(m3, m1);
|
||||
|
||||
mat4 m4(vec4(1), vec4(2), vec4(3), vec4(4));
|
||||
}
|
||||
|
||||
TEST_F(MatTest, ArithmeticOps) {
|
||||
mat4 m0;
|
||||
mat4 m1(2);
|
||||
mat4 m2(vec4(2));
|
||||
|
||||
m1 += m2;
|
||||
EXPECT_EQ(mat4(4), m1);
|
||||
|
||||
m2 -= m1;
|
||||
EXPECT_EQ(mat4(-2), m2);
|
||||
|
||||
m1 *= 2;
|
||||
EXPECT_EQ(mat4(8), m1);
|
||||
|
||||
m1 /= 2;
|
||||
EXPECT_EQ(mat4(4), m1);
|
||||
|
||||
m0 = -m0;
|
||||
EXPECT_EQ(mat4(-1), m0);
|
||||
}
|
||||
|
||||
TEST_F(MatTest, UnaryOps) {
|
||||
const mat4 identity;
|
||||
mat4 m0;
|
||||
|
||||
++m0;
|
||||
EXPECT_EQ(mat4( vec4(2,1,1,1), vec4(1,2,1,1), vec4(1,1,2,1), vec4(1,1,1,2) ), m0);
|
||||
EXPECT_EQ(mat4( -vec4(2,1,1,1), -vec4(1,2,1,1), -vec4(1,1,2,1), -vec4(1,1,1,2) ), -m0);
|
||||
|
||||
--m0;
|
||||
EXPECT_EQ(identity, m0);
|
||||
}
|
||||
|
||||
TEST_F(MatTest, MiscOps) {
|
||||
const mat4 identity;
|
||||
mat4 m0;
|
||||
EXPECT_EQ(4, trace(m0));
|
||||
|
||||
mat4 m1(vec4(1,2,3,4), vec4(5,6,7,8), vec4(9,10,11,12), vec4(13,14,15,16));
|
||||
mat4 m2(vec4(1,5,9,13), vec4(2,6,10,14), vec4(3,7,11,15), vec4(4,8,12,16));
|
||||
EXPECT_EQ(m1, transpose(m2));
|
||||
EXPECT_EQ(m2, transpose(m1));
|
||||
EXPECT_EQ(vec4(1,6,11,16), diag(m1));
|
||||
|
||||
EXPECT_EQ(identity, inverse(identity));
|
||||
|
||||
mat4 m3(vec4(4,3,0,0), vec4(3,2,0,0), vec4(0,0,1,0), vec4(0,0,0,1));
|
||||
mat4 m3i(inverse(m3));
|
||||
EXPECT_FLOAT_EQ(-2, m3i[0][0]);
|
||||
EXPECT_FLOAT_EQ( 3, m3i[0][1]);
|
||||
EXPECT_FLOAT_EQ( 3, m3i[1][0]);
|
||||
EXPECT_FLOAT_EQ(-4, m3i[1][1]);
|
||||
|
||||
mat4 m3ii(inverse(m3i));
|
||||
EXPECT_FLOAT_EQ(m3[0][0], m3ii[0][0]);
|
||||
EXPECT_FLOAT_EQ(m3[0][1], m3ii[0][1]);
|
||||
EXPECT_FLOAT_EQ(m3[1][0], m3ii[1][0]);
|
||||
EXPECT_FLOAT_EQ(m3[1][1], m3ii[1][1]);
|
||||
|
||||
EXPECT_EQ(m1, m1*identity);
|
||||
}
|
||||
|
||||
}; // namespace android
|
256
libs/ui/tests/vec_test.cpp
Normal file
256
libs/ui/tests/vec_test.cpp
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "RegionTest"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ui/Region.h>
|
||||
#include <ui/Rect.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <ui/vec4.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class VecTest : public testing::Test {
|
||||
protected:
|
||||
};
|
||||
|
||||
TEST_F(VecTest, Basics) {
|
||||
vec4 v4;
|
||||
vec3& v3(v4.xyz);
|
||||
|
||||
EXPECT_EQ(sizeof(vec4), sizeof(float)*4);
|
||||
EXPECT_EQ(sizeof(vec3), sizeof(float)*3);
|
||||
EXPECT_EQ(sizeof(vec2), sizeof(float)*2);
|
||||
EXPECT_EQ((void*)&v3, (void*)&v4);
|
||||
}
|
||||
|
||||
TEST_F(VecTest, Constructors) {
|
||||
vec4 v0;
|
||||
EXPECT_EQ(v0.x, 0);
|
||||
EXPECT_EQ(v0.y, 0);
|
||||
EXPECT_EQ(v0.z, 0);
|
||||
EXPECT_EQ(v0.w, 0);
|
||||
|
||||
vec4 v1(1);
|
||||
EXPECT_EQ(v1.x, 1);
|
||||
EXPECT_EQ(v1.y, 1);
|
||||
EXPECT_EQ(v1.z, 1);
|
||||
EXPECT_EQ(v1.w, 1);
|
||||
|
||||
vec4 v2(1,2,3,4);
|
||||
EXPECT_EQ(v2.x, 1);
|
||||
EXPECT_EQ(v2.y, 2);
|
||||
EXPECT_EQ(v2.z, 3);
|
||||
EXPECT_EQ(v2.w, 4);
|
||||
|
||||
vec4 v3(v2);
|
||||
EXPECT_EQ(v3.x, 1);
|
||||
EXPECT_EQ(v3.y, 2);
|
||||
EXPECT_EQ(v3.z, 3);
|
||||
EXPECT_EQ(v3.w, 4);
|
||||
|
||||
vec4 v4(v3.xyz, 42);
|
||||
EXPECT_EQ(v4.x, 1);
|
||||
EXPECT_EQ(v4.y, 2);
|
||||
EXPECT_EQ(v4.z, 3);
|
||||
EXPECT_EQ(v4.w, 42);
|
||||
|
||||
vec4 v5(vec3(v2.xy, 42), 24);
|
||||
EXPECT_EQ(v5.x, 1);
|
||||
EXPECT_EQ(v5.y, 2);
|
||||
EXPECT_EQ(v5.z, 42);
|
||||
EXPECT_EQ(v5.w, 24);
|
||||
|
||||
tvec4<double> vd(2);
|
||||
EXPECT_EQ(vd.x, 2);
|
||||
EXPECT_EQ(vd.y, 2);
|
||||
EXPECT_EQ(vd.z, 2);
|
||||
EXPECT_EQ(vd.w, 2);
|
||||
}
|
||||
|
||||
TEST_F(VecTest, Access) {
|
||||
vec4 v0(1,2,3,4);
|
||||
v0.x = 10;
|
||||
v0.y = 20;
|
||||
v0.z = 30;
|
||||
v0.w = 40;
|
||||
EXPECT_EQ(v0.x, 10);
|
||||
EXPECT_EQ(v0.y, 20);
|
||||
EXPECT_EQ(v0.z, 30);
|
||||
EXPECT_EQ(v0.w, 40);
|
||||
|
||||
v0[0] = 100;
|
||||
v0[1] = 200;
|
||||
v0[2] = 300;
|
||||
v0[3] = 400;
|
||||
EXPECT_EQ(v0.x, 100);
|
||||
EXPECT_EQ(v0.y, 200);
|
||||
EXPECT_EQ(v0.z, 300);
|
||||
EXPECT_EQ(v0.w, 400);
|
||||
|
||||
v0.xyz = vec3(1,2,3);
|
||||
EXPECT_EQ(v0.x, 1);
|
||||
EXPECT_EQ(v0.y, 2);
|
||||
EXPECT_EQ(v0.z, 3);
|
||||
EXPECT_EQ(v0.w, 400);
|
||||
}
|
||||
|
||||
TEST_F(VecTest, UnaryOps) {
|
||||
vec4 v0(1,2,3,4);
|
||||
|
||||
v0 += 1;
|
||||
EXPECT_EQ(v0.x, 2);
|
||||
EXPECT_EQ(v0.y, 3);
|
||||
EXPECT_EQ(v0.z, 4);
|
||||
EXPECT_EQ(v0.w, 5);
|
||||
|
||||
v0 -= 1;
|
||||
EXPECT_EQ(v0.x, 1);
|
||||
EXPECT_EQ(v0.y, 2);
|
||||
EXPECT_EQ(v0.z, 3);
|
||||
EXPECT_EQ(v0.w, 4);
|
||||
|
||||
v0 *= 2;
|
||||
EXPECT_EQ(v0.x, 2);
|
||||
EXPECT_EQ(v0.y, 4);
|
||||
EXPECT_EQ(v0.z, 6);
|
||||
EXPECT_EQ(v0.w, 8);
|
||||
|
||||
v0 /= 2;
|
||||
EXPECT_EQ(v0.x, 1);
|
||||
EXPECT_EQ(v0.y, 2);
|
||||
EXPECT_EQ(v0.z, 3);
|
||||
EXPECT_EQ(v0.w, 4);
|
||||
|
||||
vec4 v1(10, 20, 30, 40);
|
||||
|
||||
v0 += v1;
|
||||
EXPECT_EQ(v0.x, 11);
|
||||
EXPECT_EQ(v0.y, 22);
|
||||
EXPECT_EQ(v0.z, 33);
|
||||
EXPECT_EQ(v0.w, 44);
|
||||
|
||||
v0 -= v1;
|
||||
EXPECT_EQ(v0.x, 1);
|
||||
EXPECT_EQ(v0.y, 2);
|
||||
EXPECT_EQ(v0.z, 3);
|
||||
EXPECT_EQ(v0.w, 4);
|
||||
|
||||
v0 *= v1;
|
||||
EXPECT_EQ(v0.x, 10);
|
||||
EXPECT_EQ(v0.y, 40);
|
||||
EXPECT_EQ(v0.z, 90);
|
||||
EXPECT_EQ(v0.w, 160);
|
||||
|
||||
v0 /= v1;
|
||||
EXPECT_EQ(v0.x, 1);
|
||||
EXPECT_EQ(v0.y, 2);
|
||||
EXPECT_EQ(v0.z, 3);
|
||||
EXPECT_EQ(v0.w, 4);
|
||||
|
||||
++v0;
|
||||
EXPECT_EQ(v0.x, 2);
|
||||
EXPECT_EQ(v0.y, 3);
|
||||
EXPECT_EQ(v0.z, 4);
|
||||
EXPECT_EQ(v0.w, 5);
|
||||
|
||||
++++v0;
|
||||
EXPECT_EQ(v0.x, 4);
|
||||
EXPECT_EQ(v0.y, 5);
|
||||
EXPECT_EQ(v0.z, 6);
|
||||
EXPECT_EQ(v0.w, 7);
|
||||
|
||||
--v1;
|
||||
EXPECT_EQ(v1.x, 9);
|
||||
EXPECT_EQ(v1.y, 19);
|
||||
EXPECT_EQ(v1.z, 29);
|
||||
EXPECT_EQ(v1.w, 39);
|
||||
|
||||
v1 = -v1;
|
||||
EXPECT_EQ(v1.x, -9);
|
||||
EXPECT_EQ(v1.y, -19);
|
||||
EXPECT_EQ(v1.z, -29);
|
||||
EXPECT_EQ(v1.w, -39);
|
||||
|
||||
tvec4<double> dv(1,2,3,4);
|
||||
v1 += dv;
|
||||
EXPECT_EQ(v1.x, -8);
|
||||
EXPECT_EQ(v1.y, -17);
|
||||
EXPECT_EQ(v1.z, -26);
|
||||
EXPECT_EQ(v1.w, -35);
|
||||
}
|
||||
|
||||
TEST_F(VecTest, ComparisonOps) {
|
||||
vec4 v0(1,2,3,4);
|
||||
vec4 v1(10,20,30,40);
|
||||
|
||||
EXPECT_TRUE(v0 == v0);
|
||||
EXPECT_TRUE(v0 != v1);
|
||||
EXPECT_FALSE(v0 != v0);
|
||||
EXPECT_FALSE(v0 == v1);
|
||||
}
|
||||
|
||||
TEST_F(VecTest, ArithmeticOps) {
|
||||
vec4 v0(1,2,3,4);
|
||||
vec4 v1(10,20,30,40);
|
||||
|
||||
vec4 v2(v0 + v1);
|
||||
EXPECT_EQ(v2.x, 11);
|
||||
EXPECT_EQ(v2.y, 22);
|
||||
EXPECT_EQ(v2.z, 33);
|
||||
EXPECT_EQ(v2.w, 44);
|
||||
|
||||
v0 = v1 * 2;
|
||||
EXPECT_EQ(v0.x, 20);
|
||||
EXPECT_EQ(v0.y, 40);
|
||||
EXPECT_EQ(v0.z, 60);
|
||||
EXPECT_EQ(v0.w, 80);
|
||||
|
||||
v0 = 2 * v1;
|
||||
EXPECT_EQ(v0.x, 20);
|
||||
EXPECT_EQ(v0.y, 40);
|
||||
EXPECT_EQ(v0.z, 60);
|
||||
EXPECT_EQ(v0.w, 80);
|
||||
|
||||
tvec4<double> vd(2);
|
||||
v0 = v1 * vd;
|
||||
EXPECT_EQ(v0.x, 20);
|
||||
EXPECT_EQ(v0.y, 40);
|
||||
EXPECT_EQ(v0.z, 60);
|
||||
EXPECT_EQ(v0.w, 80);
|
||||
}
|
||||
|
||||
TEST_F(VecTest, ArithmeticFunc) {
|
||||
vec3 east(1, 0, 0);
|
||||
vec3 north(0, 1, 0);
|
||||
vec3 up( cross(east, north) );
|
||||
EXPECT_EQ(up, vec3(0,0,1));
|
||||
EXPECT_EQ(dot(east, north), 0);
|
||||
EXPECT_EQ(length(east), 1);
|
||||
EXPECT_EQ(distance(east, north), sqrtf(2));
|
||||
|
||||
vec3 v0(1,2,3);
|
||||
vec3 vn(normalize(v0));
|
||||
EXPECT_FLOAT_EQ(1, length(vn));
|
||||
EXPECT_FLOAT_EQ(length(v0), dot(v0, vn));
|
||||
|
||||
tvec3<double> vd(east);
|
||||
EXPECT_EQ(length(vd), 1);
|
||||
}
|
||||
|
||||
}; // namespace android
|
Loading…
Reference in New Issue
Block a user