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
2013-08-22 06:10:41 +00:00
|
|
|
/*
|
|
|
|
* 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>
|
2013-09-02 04:35:36 +00:00
|
|
|
#include <math.h>
|
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
2013-08-22 06:10:41 +00:00
|
|
|
#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
|
|
|
|
|
2013-09-02 04:35:36 +00:00
|
|
|
// -------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TMatProductOperators 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 TMatProductOperators<BASE, T> BASE will automatically
|
|
|
|
* get all the functionality here.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <template<typename T> class BASE, typename T>
|
|
|
|
class TMatProductOperators {
|
|
|
|
public:
|
|
|
|
// multiply by a scalar
|
|
|
|
BASE<T>& operator *= (T v) {
|
|
|
|
BASE<T>& lhs(static_cast< BASE<T>& >(*this));
|
|
|
|
for (size_t r=0 ; r<lhs.row_size() ; r++) {
|
|
|
|
lhs[r] *= v;
|
|
|
|
}
|
|
|
|
return lhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
// divide by a scalar
|
|
|
|
BASE<T>& operator /= (T v) {
|
|
|
|
BASE<T>& lhs(static_cast< BASE<T>& >(*this));
|
|
|
|
for (size_t r=0 ; r<lhs.row_size() ; r++) {
|
|
|
|
lhs[r] /= v;
|
|
|
|
}
|
|
|
|
return lhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
// matrix * matrix, result is a matrix of the same type than the lhs matrix
|
|
|
|
template<typename U>
|
|
|
|
friend BASE<T> PURE operator *(const BASE<T>& lhs, const BASE<U>& rhs) {
|
|
|
|
return matrix::multiply<BASE<T> >(lhs, rhs);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TMatSquareFunctions implements functions on a matrix of type BASE<T>.
|
|
|
|
*
|
|
|
|
* BASE only needs to implement:
|
|
|
|
* - operator[]
|
|
|
|
* - col_type
|
|
|
|
* - row_type
|
|
|
|
* - COL_SIZE
|
|
|
|
* - ROW_SIZE
|
|
|
|
*
|
|
|
|
* By simply inheriting from TMatSquareFunctions<BASE, T> BASE will automatically
|
|
|
|
* get all the functionality here.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template<template<typename U> class BASE, typename T>
|
|
|
|
class TMatSquareFunctions {
|
|
|
|
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).
|
|
|
|
*/
|
|
|
|
friend BASE<T> PURE inverse(const BASE<T>& m) { return matrix::inverse(m); }
|
|
|
|
friend BASE<T> PURE transpose(const BASE<T>& m) { return matrix::transpose(m); }
|
|
|
|
friend T PURE trace(const BASE<T>& m) { return matrix::trace(m); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <template<typename T> class BASE, typename T>
|
|
|
|
class TMatDebug {
|
|
|
|
public:
|
|
|
|
String8 asString() const {
|
|
|
|
return matrix::asString(*this);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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
2013-08-22 06:10:41 +00:00
|
|
|
// -------------------------------------------------------------------------------------
|
|
|
|
}; // namespace android
|
|
|
|
|
|
|
|
#undef PURE
|
|
|
|
|
|
|
|
#endif /* UI_TMAT_HELPERS_H */
|