@@ -16,10 +16,7 @@ | |||
namespace lol | |||
{ | |||
/* There are many reasons for wanting single-word type names, the most | |||
* important one being compilation speedups in our vector.h: we can hide | |||
* some global methods in namespaces that contain the name of the type, | |||
* but namespaces cannot have spaces in their names. */ | |||
/* It’s nice to have single-word type names, so define this. */ | |||
typedef long double ldouble; | |||
/* The “real” type used for real numbers. It’s a specialisation of the | |||
@@ -31,22 +28,23 @@ typedef Real<16> real; | |||
class half; | |||
/* | |||
* Forward declaration of vec and matrix | |||
* Forward declaration of vec_t, mat_t, cmplx_t, quat_t | |||
*/ | |||
int const FULL_SWIZZLE = 0xaaaa; | |||
int const NO_SWIZZLE = 0xbbbb; | |||
template<int N, typename T, int SWIZZLE = FULL_SWIZZLE> struct vec; | |||
template<int COLS, int ROWS, typename T> struct mat; | |||
template<typename T> struct Cmplx; | |||
template<typename T> struct Quat; | |||
template<typename T, int N, int SWIZZLE = FULL_SWIZZLE> struct vec_t; | |||
template<typename T, int COLS, int ROWS> struct mat_t; | |||
template<typename T> struct cmplx_t; | |||
template<typename T> struct quat_t; | |||
template<typename T> struct dualquat_t; | |||
/* | |||
* Generic GLSL-like type names | |||
*/ | |||
#define LOL_VECTOR_TYPEDEFS(tleft, tright, suffix) \ | |||
#define _T(tleft, tright, suffix) \ | |||
typedef tleft half tright f16##suffix; \ | |||
typedef tleft float tright suffix; \ | |||
typedef tleft double tright d##suffix; \ | |||
@@ -62,28 +60,29 @@ template<typename T> struct Quat; | |||
typedef tleft real tright r##suffix; | |||
/* Idiotic hack to put "," inside a macro argument */ | |||
#define COMMA , | |||
#define _C , | |||
LOL_VECTOR_TYPEDEFS(vec<2 COMMA, >, vec2) | |||
LOL_VECTOR_TYPEDEFS(vec<3 COMMA, >, vec3) | |||
LOL_VECTOR_TYPEDEFS(vec<4 COMMA, >, vec4) | |||
_T(vec_t<, _C 2>, vec2) | |||
_T(vec_t<, _C 3>, vec3) | |||
_T(vec_t<, _C 4>, vec4) | |||
LOL_VECTOR_TYPEDEFS(mat<2 COMMA 2 COMMA, >, mat2) | |||
LOL_VECTOR_TYPEDEFS(mat<3 COMMA 3 COMMA, >, mat3) | |||
LOL_VECTOR_TYPEDEFS(mat<4 COMMA 4 COMMA, >, mat4) | |||
_T(mat_t<, _C 2 _C 2>, mat2) | |||
_T(mat_t<, _C 3 _C 3>, mat3) | |||
_T(mat_t<, _C 4 _C 4>, mat4) | |||
LOL_VECTOR_TYPEDEFS(mat<2 COMMA 3 COMMA, >, mat2x3) | |||
LOL_VECTOR_TYPEDEFS(mat<2 COMMA 4 COMMA, >, mat2x4) | |||
LOL_VECTOR_TYPEDEFS(mat<3 COMMA 2 COMMA, >, mat3x2) | |||
LOL_VECTOR_TYPEDEFS(mat<3 COMMA 4 COMMA, >, mat3x4) | |||
LOL_VECTOR_TYPEDEFS(mat<4 COMMA 2 COMMA, >, mat4x2) | |||
LOL_VECTOR_TYPEDEFS(mat<4 COMMA 3 COMMA, >, mat4x3) | |||
_T(mat_t<, _C 2 _C 3>, mat2x3) | |||
_T(mat_t<, _C 2 _C 4>, mat2x4) | |||
_T(mat_t<, _C 3 _C 2>, mat3x2) | |||
_T(mat_t<, _C 3 _C 4>, mat3x4) | |||
_T(mat_t<, _C 4 _C 2>, mat4x2) | |||
_T(mat_t<, _C 4 _C 3>, mat4x3) | |||
LOL_VECTOR_TYPEDEFS(Cmplx<, >, cmplx) | |||
LOL_VECTOR_TYPEDEFS(Quat<, >, quat) | |||
_T(cmplx_t<, >, cmplx) | |||
_T(quat_t<, >, quat) | |||
_T(dualquat_t<, >, dualquat) | |||
#undef COMMA | |||
#undef LOL_VECTOR_TYPEDEFS | |||
#undef _C | |||
#undef _T | |||
/* | |||
* HLSL/Cg-compliant type names | |||
@@ -49,7 +49,7 @@ template <typename T> struct Box2 | |||
B(T(0)) | |||
{} | |||
inline Box2(vec<2,T> const &a, vec<2,T> const &b) | |||
inline Box2(vec_t<T,2> const &a, vec_t<T,2> const &b) | |||
: A(a), | |||
B(b) | |||
{} | |||
@@ -59,32 +59,32 @@ template <typename T> struct Box2 | |||
B(bx, by) | |||
{} | |||
Box2<T> operator +(vec<2,T> const &v) const | |||
Box2<T> operator +(vec_t<T,2> const &v) const | |||
{ | |||
return Box2<T>(A + v, B + v); | |||
} | |||
Box2<T> &operator +=(vec<2,T> const &v) | |||
Box2<T> &operator +=(vec_t<T,2> const &v) | |||
{ | |||
return *this = *this + v; | |||
} | |||
Box2<T> operator -(vec<2,T> const &v) const | |||
Box2<T> operator -(vec_t<T,2> const &v) const | |||
{ | |||
return Box2<T>(A - v, B - v); | |||
} | |||
Box2<T> &operator -=(vec<2,T> const &v) | |||
Box2<T> &operator -=(vec_t<T,2> const &v) | |||
{ | |||
return *this = *this - v; | |||
} | |||
Box2<T> operator *(vec<2,T> const &v) const | |||
Box2<T> operator *(vec_t<T,2> const &v) const | |||
{ | |||
return Box2<T>(A * v, B * v); | |||
} | |||
Box2<T> &operator *=(vec<2,T> const &v) | |||
Box2<T> &operator *=(vec_t<T,2> const &v) | |||
{ | |||
return *this = *this * v; | |||
} | |||
@@ -99,7 +99,7 @@ template <typename T> struct Box2 | |||
return A != box.A || B != box.B; | |||
} | |||
vec<2,T> A, B; | |||
vec_t<T,2> A, B; | |||
}; | |||
/* | |||
@@ -113,7 +113,7 @@ template <typename T> struct Box3 | |||
B(T(0)) | |||
{} | |||
inline Box3(vec<3,T> const &a, vec<3,T> const &b) | |||
inline Box3(vec_t<T,3> const &a, vec_t<T,3> const &b) | |||
: A(a), | |||
B(b) | |||
{} | |||
@@ -124,32 +124,32 @@ template <typename T> struct Box3 | |||
B(bx, by, bz) | |||
{} | |||
Box3<T> operator +(vec<3,T> const &v) const | |||
Box3<T> operator +(vec_t<T,3> const &v) const | |||
{ | |||
return Box3<T>(A + v, B + v); | |||
} | |||
Box3<T> &operator +=(vec<3,T> const &v) | |||
Box3<T> &operator +=(vec_t<T,3> const &v) | |||
{ | |||
return *this = *this + v; | |||
} | |||
Box3<T> operator -(vec<3,T> const &v) const | |||
Box3<T> operator -(vec_t<T,3> const &v) const | |||
{ | |||
return Box3<T>(A - v, B - v); | |||
} | |||
Box3<T> &operator -=(vec<3,T> const &v) | |||
Box3<T> &operator -=(vec_t<T,3> const &v) | |||
{ | |||
return *this = *this - v; | |||
} | |||
Box3<T> operator *(vec<3,T> const &v) const | |||
Box3<T> operator *(vec_t<T,3> const &v) const | |||
{ | |||
return Box3<T>(A * v, B * v); | |||
} | |||
Box3<T> &operator *=(vec<3,T> const &v) | |||
Box3<T> &operator *=(vec_t<T,3> const &v) | |||
{ | |||
return *this = *this * v; | |||
} | |||
@@ -164,7 +164,7 @@ template <typename T> struct Box3 | |||
return A != box.A || B != box.B; | |||
} | |||
vec<3,T> A, B; | |||
vec_t<T,3> A, B; | |||
}; | |||
/* | |||
@@ -29,17 +29,17 @@ namespace lol | |||
#endif | |||
/* | |||
* The generic "matrix" type, which is fixed-size | |||
* The generic “mat_t” type, which is fixed-size | |||
*/ | |||
template<int COLS, int ROWS, typename T> | |||
struct mat | |||
template<typename T, int COLS, int ROWS> | |||
struct mat_t | |||
{ | |||
typedef mat<COLS,ROWS,T> type; | |||
typedef mat_t<T,COLS,ROWS> type; | |||
inline mat() {} | |||
inline mat_t() {} | |||
explicit inline mat(T const &val) | |||
explicit inline mat_t(T const &val) | |||
{ | |||
T const zero = T(0); | |||
for (int i = 0; i < COLS; ++i) | |||
@@ -47,11 +47,11 @@ struct mat | |||
m_data[i][j] = i == j ? val : zero; | |||
} | |||
inline vec<ROWS,T>& operator[](size_t n) { return m_data[n]; } | |||
inline vec<ROWS,T> const& operator[](size_t n) const { return m_data[n]; } | |||
inline vec_t<T,ROWS>& operator[](size_t n) { return m_data[n]; } | |||
inline vec_t<T,ROWS> const& operator[](size_t n) const { return m_data[n]; } | |||
private: | |||
vec<ROWS,T> m_data[COLS]; | |||
vec_t<T,ROWS> m_data[COLS]; | |||
}; | |||
/* | |||
@@ -59,28 +59,28 @@ private: | |||
*/ | |||
template <typename T> | |||
struct mat<2, 2, T> | |||
struct mat_t<T, 2, 2> | |||
{ | |||
typedef mat<2,2,T> type; | |||
typedef mat_t<T,2,2> type; | |||
inline mat() {} | |||
inline mat(vec<2,T> v0, vec<2,T> v1) | |||
inline mat_t() {} | |||
inline mat_t(vec_t<T,2> v0, vec_t<T,2> v1) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ v0, v1 } {} | |||
#else | |||
: m_v0(v0), m_v1(v1) {} | |||
#endif | |||
explicit inline mat(T const &val) | |||
explicit inline mat_t(T const &val) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ vec<2,T>(val, T(0)), | |||
vec<2,T>(T(0), val) } {} | |||
: m_data{ vec_t<T,2>(val, T(0)), | |||
vec_t<T,2>(T(0), val) } {} | |||
#else | |||
: m_v0(val, T(0)), | |||
m_v1(T(0), val) {} | |||
#endif | |||
explicit inline mat(mat<4,4,T> const &m) | |||
explicit inline mat_t(mat_t<T,4,4> const &m) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ m[0].xy, m[1].xy } {} | |||
#else | |||
@@ -88,16 +88,16 @@ struct mat<2, 2, T> | |||
#endif | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
inline vec<2,T>& operator[](size_t n) { return m_data[n]; } | |||
inline vec<2,T> const& operator[](size_t n) const { return m_data[n]; } | |||
inline vec_t<T,2>& operator[](size_t n) { return m_data[n]; } | |||
inline vec_t<T,2> const& operator[](size_t n) const { return m_data[n]; } | |||
#else | |||
inline vec<2,T>& operator[](size_t n) { return (&m_v0)[n]; } | |||
inline vec<2,T> const& operator[](size_t n) const { return (&m_v0)[n]; } | |||
inline vec_t<T,2>& operator[](size_t n) { return (&m_v0)[n]; } | |||
inline vec_t<T,2> const& operator[](size_t n) const { return (&m_v0)[n]; } | |||
#endif | |||
/* Helpers for transformation matrices */ | |||
static mat<2,2,T> rotate(T degrees); | |||
static inline mat<2,2,T> rotate(mat<2,2,T> m, T degrees) | |||
static mat_t<T,2,2> rotate(T degrees); | |||
static inline mat_t<T,2,2> rotate(mat_t<T,2,2> m, T degrees) | |||
{ | |||
return rotate(degrees) * m; | |||
} | |||
@@ -107,15 +107,15 @@ struct mat<2, 2, T> | |||
template<class U> | |||
friend std::ostream &operator<<(std::ostream &stream, | |||
mat<2,2,U> const &m); | |||
mat_t<U,2,2> const &m); | |||
static const mat<2,2,T> identity; | |||
static const mat_t<T,2,2> identity; | |||
private: | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
vec<2,T> m_data[2]; | |||
vec_t<T,2> m_data[2]; | |||
#else | |||
vec<2,T> m_v0, m_v1; | |||
vec_t<T,2> m_v0, m_v1; | |||
#endif | |||
}; | |||
@@ -124,91 +124,91 @@ private: | |||
*/ | |||
template <typename T> | |||
struct mat<3,3,T> | |||
struct mat_t<T, 3, 3> | |||
{ | |||
typedef mat<3,3,T> type; | |||
typedef mat_t<T,3,3> type; | |||
inline mat() {} | |||
inline mat(vec<3,T> v0, vec<3,T> v1, vec<3,T> v2) | |||
inline mat_t() {} | |||
inline mat_t(vec_t<T,3> v0, vec_t<T,3> v1, vec_t<T,3> v2) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ v0, v1, v2 } {} | |||
#else | |||
: m_v0(v0), m_v1(v1), m_v2(v2) {} | |||
#endif | |||
explicit inline mat(T const &val) | |||
explicit inline mat_t(T const &val) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ vec<3,T>(val, (T)0, (T)0), | |||
vec<3,T>((T)0, val, (T)0), | |||
vec<3,T>((T)0, (T)0, val) } {} | |||
: m_data{ vec_t<T,3>(val, (T)0, (T)0), | |||
vec_t<T,3>((T)0, val, (T)0), | |||
vec_t<T,3>((T)0, (T)0, val) } {} | |||
#else | |||
: m_v0(val, (T)0, (T)0), | |||
m_v1((T)0, val, (T)0), | |||
m_v2((T)0, (T)0, val) {} | |||
#endif | |||
explicit inline mat(mat<2,2,T> m, T const &val = T(1)) | |||
explicit inline mat_t(mat_t<T,2,2> m, T const &val = T(1)) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ vec<3,T>(m[0], (T)0), | |||
vec<3,T>(m[1], (T)0), | |||
vec<3,T>((T)0, (T)0, val) } {} | |||
: m_data{ vec_t<T,3>(m[0], (T)0), | |||
vec_t<T,3>(m[1], (T)0), | |||
vec_t<T,3>((T)0, (T)0, val) } {} | |||
#else | |||
: m_v0(m[0], (T)0), | |||
m_v1(m[1], (T)0), | |||
m_v2((T)0, (T)0, val) {} | |||
#endif | |||
explicit inline mat(mat<4,4,T> const &m) | |||
explicit inline mat_t(mat_t<T,4,4> const &m) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ m[0].xyz, m[1].xyz, m[2].xyz } {} | |||
#else | |||
: m_v0(m[0].xyz), m_v1(m[1].xyz), m_v2(m[2].xyz) {} | |||
#endif | |||
explicit mat(Quat<T> const &q); | |||
explicit mat_t(quat_t<T> const &q); | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
inline vec<3,T>& operator[](size_t n) { return m_data[n]; } | |||
inline vec<3,T> const& operator[](size_t n) const { return m_data[n]; } | |||
inline vec_t<T,3>& operator[](size_t n) { return m_data[n]; } | |||
inline vec_t<T,3> const& operator[](size_t n) const { return m_data[n]; } | |||
#else | |||
inline vec<3,T>& operator[](size_t n) { return (&m_v0)[n]; } | |||
inline vec<3,T> const& operator[](size_t n) const { return (&m_v0)[n]; } | |||
inline vec_t<T,3>& operator[](size_t n) { return (&m_v0)[n]; } | |||
inline vec_t<T,3> const& operator[](size_t n) const { return (&m_v0)[n]; } | |||
#endif | |||
/* Helpers for transformation matrices */ | |||
static mat<3,3,T> scale(T x); | |||
static mat<3,3,T> scale(T x, T y, T z); | |||
static mat<3,3,T> scale(vec<3,T> v); | |||
static mat<3,3,T> rotate(T degrees, T x, T y, T z); | |||
static mat<3,3,T> rotate(T degrees, vec<3,T> v); | |||
static mat<3,3,T> fromeuler_xyz(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_xzy(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_yxz(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_yzx(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_zxy(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_zyx(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_xyz(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_xzy(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_yxz(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_yzx(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_zxy(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_zyx(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_xyx(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_xzx(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_yxy(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_yzy(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_zxz(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_zyz(vec<3,T> const &v); | |||
static mat<3,3,T> fromeuler_xyx(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_xzx(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_yxy(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_yzy(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_zxz(T phi, T theta, T psi); | |||
static mat<3,3,T> fromeuler_zyz(T phi, T theta, T psi); | |||
static inline mat<3,3,T> rotate(mat<3,3,T> m, T degrees, vec<3,T> v) | |||
static mat_t<T,3,3> scale(T x); | |||
static mat_t<T,3,3> scale(T x, T y, T z); | |||
static mat_t<T,3,3> scale(vec_t<T,3> v); | |||
static mat_t<T,3,3> rotate(T degrees, T x, T y, T z); | |||
static mat_t<T,3,3> rotate(T degrees, vec_t<T,3> v); | |||
static mat_t<T,3,3> fromeuler_xyz(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_xzy(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_yxz(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_yzx(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_zxy(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_zyx(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_xyz(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_xzy(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_yxz(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_yzx(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_zxy(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_zyx(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_xyx(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_xzx(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_yxy(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_yzy(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_zxz(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_zyz(vec_t<T,3> const &v); | |||
static mat_t<T,3,3> fromeuler_xyx(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_xzx(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_yxy(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_yzy(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_zxz(T phi, T theta, T psi); | |||
static mat_t<T,3,3> fromeuler_zyz(T phi, T theta, T psi); | |||
static inline mat_t<T,3,3> rotate(mat_t<T,3,3> m, T degrees, vec_t<T,3> v) | |||
{ | |||
return rotate(degrees, v) * m; | |||
} | |||
@@ -218,15 +218,15 @@ struct mat<3,3,T> | |||
template<class U> | |||
friend std::ostream &operator<<(std::ostream &stream, | |||
mat<3,3,U> const &m); | |||
mat_t<U,3,3> const &m); | |||
static const mat<3,3,T> identity; | |||
static const mat_t<T,3,3> identity; | |||
private: | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
vec<3,T> m_data[3]; | |||
vec_t<T,3> m_data[3]; | |||
#else | |||
vec<3,T> m_v0, m_v1, m_v2; | |||
vec_t<T,3> m_v0, m_v1, m_v2; | |||
#endif | |||
}; | |||
@@ -235,24 +235,24 @@ private: | |||
*/ | |||
template <typename T> | |||
struct mat<4, 4, T> | |||
struct mat_t<T, 4, 4> | |||
{ | |||
typedef mat<4,4,T> type; | |||
typedef mat_t<T,4,4> type; | |||
inline mat() {} | |||
inline mat(vec<4,T> v0, vec<4,T> v1, vec<4,T> v2, vec<4,T> v3) | |||
inline mat_t() {} | |||
inline mat_t(vec_t<T,4> v0, vec_t<T,4> v1, vec_t<T,4> v2, vec_t<T,4> v3) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ v0, v1, v2, v3 } {} | |||
#else | |||
: m_v0(v0), m_v1(v1), m_v2(v2), m_v3(v3) {} | |||
#endif | |||
explicit inline mat(T const &val) | |||
explicit inline mat_t(T const &val) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ vec<4,T>(val, (T)0, (T)0, (T)0), | |||
vec<4,T>((T)0, val, (T)0, (T)0), | |||
vec<4,T>((T)0, (T)0, val, (T)0), | |||
vec<4,T>((T)0, (T)0, (T)0, val) } {} | |||
: m_data{ vec_t<T,4>(val, (T)0, (T)0, (T)0), | |||
vec_t<T,4>((T)0, val, (T)0, (T)0), | |||
vec_t<T,4>((T)0, (T)0, val, (T)0), | |||
vec_t<T,4>((T)0, (T)0, (T)0, val) } {} | |||
#else | |||
: m_v0(val, (T)0, (T)0, (T)0), | |||
m_v1((T)0, val, (T)0, (T)0), | |||
@@ -260,12 +260,12 @@ struct mat<4, 4, T> | |||
m_v3((T)0, (T)0, (T)0, val) {} | |||
#endif | |||
explicit inline mat(mat<2,2,T> m, T const &val = T(1)) | |||
explicit inline mat_t(mat_t<T,2,2> m, T const &val = T(1)) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ vec<4,T>(m[0], (T)0, (T)0), | |||
vec<4,T>(m[1], (T)0, (T)0), | |||
vec<4,T>((T)0, (T)0, val, (T)0), | |||
vec<4,T>((T)0, (T)0, (T)0, val) } {} | |||
: m_data{ vec_t<T,4>(m[0], (T)0, (T)0), | |||
vec_t<T,4>(m[1], (T)0, (T)0), | |||
vec_t<T,4>((T)0, (T)0, val, (T)0), | |||
vec_t<T,4>((T)0, (T)0, (T)0, val) } {} | |||
#else | |||
: m_v0(m[0], (T)0, (T)0), | |||
m_v1(m[1], (T)0, (T)0), | |||
@@ -273,12 +273,12 @@ struct mat<4, 4, T> | |||
m_v3((T)0, (T)0, (T)0, val) {} | |||
#endif | |||
explicit inline mat(mat<3,3,T> m, T const &val = T(1)) | |||
explicit inline mat_t(mat_t<T,3,3> m, T const &val = T(1)) | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
: m_data{ vec<4,T>(m[0], (T)0), | |||
vec<4,T>(m[1], (T)0), | |||
vec<4,T>(m[2], (T)0), | |||
vec<4,T>((T)0, (T)0, (T)0, val) } {} | |||
: m_data{ vec_t<T,4>(m[0], (T)0), | |||
vec_t<T,4>(m[1], (T)0), | |||
vec_t<T,4>(m[2], (T)0), | |||
vec_t<T,4>((T)0, (T)0, (T)0, val) } {} | |||
#else | |||
: m_v0(m[0], (T)0), | |||
m_v1(m[1], (T)0), | |||
@@ -286,120 +286,120 @@ struct mat<4, 4, T> | |||
m_v3((T)0, (T)0, (T)0, val) {} | |||
#endif | |||
explicit mat(Quat<T> const &q); | |||
explicit mat_t(quat_t<T> const &q); | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
inline vec<4,T>& operator[](size_t n) { return m_data[n]; } | |||
inline vec<4,T> const& operator[](size_t n) const { return m_data[n]; } | |||
inline vec_t<T,4>& operator[](size_t n) { return m_data[n]; } | |||
inline vec_t<T,4> const& operator[](size_t n) const { return m_data[n]; } | |||
#else | |||
inline vec<4,T>& operator[](size_t n) { return (&m_v0)[n]; } | |||
inline vec<4,T> const& operator[](size_t n) const { return (&m_v0)[n]; } | |||
inline vec_t<T,4>& operator[](size_t n) { return (&m_v0)[n]; } | |||
inline vec_t<T,4> const& operator[](size_t n) const { return (&m_v0)[n]; } | |||
#endif | |||
/* Helpers for transformation matrices */ | |||
static mat<4,4,T> translate(T x, T y, T z); | |||
static mat<4,4,T> translate(vec<3,T> v); | |||
static mat_t<T,4,4> translate(T x, T y, T z); | |||
static mat_t<T,4,4> translate(vec_t<T,3> v); | |||
static inline mat<4,4,T> scale(T x) | |||
static inline mat_t<T,4,4> scale(T x) | |||
{ | |||
return mat<4,4,T>(mat<3,3,T>::scale(x), (T)1); | |||
return mat_t<T,4,4>(mat_t<T,3,3>::scale(x), (T)1); | |||
} | |||
static inline mat<4,4,T> scale(T x, T y, T z) | |||
static inline mat_t<T,4,4> scale(T x, T y, T z) | |||
{ | |||
return mat<4,4,T>(mat<3,3,T>::scale(x, y, z), (T)1); | |||
return mat_t<T,4,4>(mat_t<T,3,3>::scale(x, y, z), (T)1); | |||
} | |||
static inline mat<4,4,T> scale(vec<3,T> v) | |||
static inline mat_t<T,4,4> scale(vec_t<T,3> v) | |||
{ | |||
return mat<4,4,T>(mat<3,3,T>::scale(v), (T)1); | |||
return mat_t<T,4,4>(mat_t<T,3,3>::scale(v), (T)1); | |||
} | |||
static inline mat<4,4,T> translate(mat<4,4,T> const &m, vec<3,T> v) | |||
static inline mat_t<T,4,4> translate(mat_t<T,4,4> const &m, vec_t<T,3> v) | |||
{ | |||
return translate(v) * m; | |||
} | |||
static inline mat<4,4,T> rotate(T degrees, T x, T y, T z) | |||
static inline mat_t<T,4,4> rotate(T degrees, T x, T y, T z) | |||
{ | |||
return mat<4,4,T>(mat<3,3,T>::rotate(degrees, x, y, z), (T)1); | |||
return mat_t<T,4,4>(mat_t<T,3,3>::rotate(degrees, x, y, z), (T)1); | |||
} | |||
static inline mat<4,4,T> rotate(T degrees, vec<3,T> v) | |||
static inline mat_t<T,4,4> rotate(T degrees, vec_t<T,3> v) | |||
{ | |||
return mat<4,4,T>(mat<3,3,T>::rotate(degrees, v), (T)1); | |||
return mat_t<T,4,4>(mat_t<T,3,3>::rotate(degrees, v), (T)1); | |||
} | |||
static inline mat<4,4,T> rotate(mat<4,4,T> &m, T degrees, vec<3,T> v) | |||
static inline mat_t<T,4,4> rotate(mat_t<T,4,4> &m, T degrees, vec_t<T,3> v) | |||
{ | |||
return rotate(degrees, v) * m; | |||
} | |||
static mat<4,4,T> fromeuler_xyz(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_xzy(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_yxz(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_yzx(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_zxy(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_zyx(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_xyz(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_xzy(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_yxz(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_yzx(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_zxy(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_zyx(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_xyx(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_xzx(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_yxy(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_yzy(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_zxz(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_zyz(vec<3,T> const &v); | |||
static mat<4,4,T> fromeuler_xyx(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_xzx(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_yxy(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_yzy(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_zxz(T phi, T theta, T psi); | |||
static mat<4,4,T> fromeuler_zyz(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_xyz(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_xzy(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_yxz(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_yzx(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_zxy(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_zyx(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_xyz(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_xzy(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_yxz(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_yzx(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_zxy(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_zyx(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_xyx(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_xzx(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_yxy(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_yzy(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_zxz(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_zyz(vec_t<T,3> const &v); | |||
static mat_t<T,4,4> fromeuler_xyx(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_xzx(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_yxy(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_yzy(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_zxz(T phi, T theta, T psi); | |||
static mat_t<T,4,4> fromeuler_zyz(T phi, T theta, T psi); | |||
/* Helpers for view matrices */ | |||
static mat<4,4,T> lookat(vec<3,T> eye, vec<3,T> center, vec<3,T> up); | |||
static mat_t<T,4,4> lookat(vec_t<T,3> eye, vec_t<T,3> center, vec_t<T,3> up); | |||
/* Helpers for projection matrices */ | |||
static mat<4,4,T> ortho(T left, T right, T bottom, T top, T near, T far); | |||
static mat<4,4,T> ortho(T width, T height, T near, T far); | |||
static mat<4,4,T> frustum(T left, T right, T bottom, T top, T near, T far); | |||
static mat<4,4,T> perspective(T fov_y, T width, T height, T near, T far); | |||
static mat<4,4,T> shifted_perspective(T fov_y, T screen_size, T screen_ratio_yx, T near, T far); | |||
static mat_t<T,4,4> ortho(T left, T right, T bottom, T top, T near, T far); | |||
static mat_t<T,4,4> ortho(T width, T height, T near, T far); | |||
static mat_t<T,4,4> frustum(T left, T right, T bottom, T top, T near, T far); | |||
static mat_t<T,4,4> perspective(T fov_y, T width, T height, T near, T far); | |||
static mat_t<T,4,4> shifted_perspective(T fov_y, T screen_size, T screen_ratio_yx, T near, T far); | |||
void printf() const; | |||
String tostring() const; | |||
template<class U> | |||
friend std::ostream &operator<<(std::ostream &stream, | |||
mat<4,4,U> const &m); | |||
mat_t<U,4,4> const &m); | |||
static const mat<4,4,T> identity; | |||
static const mat_t<T,4,4> identity; | |||
private: | |||
#if LOL_FEATURE_CXX11_ARRAY_INITIALIZERS | |||
vec<4,T> m_data[4]; | |||
vec_t<T,4> m_data[4]; | |||
#else | |||
vec<4,T> m_v0, m_v1, m_v2, m_v3; | |||
vec_t<T,4> m_v0, m_v1, m_v2, m_v3; | |||
#endif | |||
}; | |||
template<typename T> T determinant(mat<2,2,T> const &); | |||
template<typename T> T determinant(mat<3,3,T> const &); | |||
template<typename T> T determinant(mat<4,4,T> const &); | |||
template<typename T> T determinant(mat_t<T,2,2> const &); | |||
template<typename T> T determinant(mat_t<T,3,3> const &); | |||
template<typename T> T determinant(mat_t<T,4,4> const &); | |||
template<typename T> mat<2,2,T> inverse(mat<2,2,T> const &); | |||
template<typename T> mat<3,3,T> inverse(mat<3,3,T> const &); | |||
template<typename T> mat<4,4,T> inverse(mat<4,4,T> const &); | |||
template<typename T> mat_t<T,2,2> inverse(mat_t<T,2,2> const &); | |||
template<typename T> mat_t<T,3,3> inverse(mat_t<T,3,3> const &); | |||
template<typename T> mat_t<T,4,4> inverse(mat_t<T,4,4> const &); | |||
template<int COLS, int ROWS, typename T> | |||
static inline mat<ROWS, COLS, T> transpose(mat<COLS, ROWS, T> const &m) | |||
template<typename T, int COLS, int ROWS> | |||
static inline mat_t<T, ROWS, COLS> transpose(mat_t<T, COLS, ROWS> const &m) | |||
{ | |||
mat<ROWS, COLS, T> ret; | |||
mat_t<T, ROWS, COLS> ret; | |||
for (int i = 0; i < COLS; ++i) | |||
for (int j = 0; j < ROWS; ++j) | |||
ret[j][i] = m[i][j]; | |||
@@ -410,50 +410,50 @@ static inline mat<ROWS, COLS, T> transpose(mat<COLS, ROWS, T> const &m) | |||
* Addition/subtraction/unary | |||
*/ | |||
template<int COLS, int ROWS, typename T> | |||
static inline mat<COLS, ROWS, T> &operator +=(mat<COLS, ROWS, T> &a, | |||
mat<COLS, ROWS, T> const &b) | |||
template<typename T, int COLS, int ROWS> | |||
static inline mat_t<T, COLS, ROWS> &operator +=(mat_t<T, COLS, ROWS> &a, | |||
mat_t<T, COLS, ROWS> const &b) | |||
{ | |||
for (int i = 0; i < COLS; ++i) | |||
a[i] += b[i]; | |||
return a; | |||
} | |||
template<int COLS, int ROWS, typename T> | |||
static inline mat<COLS, ROWS, T> operator +(mat<COLS, ROWS, T> const &a, | |||
mat<COLS, ROWS, T> const &b) | |||
template<typename T, int COLS, int ROWS> | |||
static inline mat_t<T, COLS, ROWS> operator +(mat_t<T, COLS, ROWS> const &a, | |||
mat_t<T, COLS, ROWS> const &b) | |||
{ | |||
mat<COLS, ROWS, T> ret = a; | |||
mat_t<T, COLS, ROWS> ret = a; | |||
return ret += b; | |||
} | |||
template<int COLS, int ROWS, typename T> | |||
static inline mat<COLS, ROWS, T> operator +(mat<COLS, ROWS, T> const &m) | |||
template<typename T, int COLS, int ROWS> | |||
static inline mat_t<T, COLS, ROWS> operator +(mat_t<T, COLS, ROWS> const &m) | |||
{ | |||
return m; | |||
} | |||
template<int COLS, int ROWS, typename T> | |||
static inline mat<COLS, ROWS, T> &operator -=(mat<COLS, ROWS, T> &a, | |||
mat<COLS, ROWS, T> const &b) | |||
template<typename T, int COLS, int ROWS> | |||
static inline mat_t<T, COLS, ROWS> &operator -=(mat_t<T, COLS, ROWS> &a, | |||
mat_t<T, COLS, ROWS> const &b) | |||
{ | |||
for (int i = 0; i < COLS; ++i) | |||
a[i] -= b[i]; | |||
return a; | |||
} | |||
template<int COLS, int ROWS, typename T> | |||
static inline mat<COLS, ROWS, T> operator -(mat<COLS, ROWS, T> const &a, | |||
mat<COLS, ROWS, T> const &b) | |||
template<typename T, int COLS, int ROWS> | |||
static inline mat_t<T, COLS, ROWS> operator -(mat_t<T, COLS, ROWS> const &a, | |||
mat_t<T, COLS, ROWS> const &b) | |||
{ | |||
mat<COLS, ROWS, T> ret = a; | |||
mat_t<T, COLS, ROWS> ret = a; | |||
return ret -= b; | |||
} | |||
template<int COLS, int ROWS, typename T> | |||
static inline mat<COLS, ROWS, T> operator -(mat<COLS, ROWS, T> const &m) | |||
template<typename T, int COLS, int ROWS> | |||
static inline mat_t<T, COLS, ROWS> operator -(mat_t<T, COLS, ROWS> const &m) | |||
{ | |||
mat<COLS, ROWS, T> ret; | |||
mat_t<T, COLS, ROWS> ret; | |||
for (int i = 0; i < COLS; ++i) | |||
ret[i] = -m[i]; | |||
return ret; | |||
@@ -463,21 +463,21 @@ static inline mat<COLS, ROWS, T> operator -(mat<COLS, ROWS, T> const &m) | |||
* Matrix-vector and vector-matrix multiplication | |||
*/ | |||
template<int COLS, int ROWS, int MASK, typename T> | |||
static inline vec<ROWS, T> operator *(mat<COLS, ROWS, T> const &m, | |||
vec<COLS, T, MASK> const &v) | |||
template<typename T, int COLS, int ROWS, int SWIZZLE> | |||
static inline vec_t<T, ROWS> operator *(mat_t<T, COLS, ROWS> const &m, | |||
vec_t<T, COLS, SWIZZLE> const &v) | |||
{ | |||
vec<ROWS, T> ret(T(0)); | |||
vec_t<T, ROWS> ret(T(0)); | |||
for (int i = 0; i < COLS; ++i) | |||
ret += m[i] * v[i]; | |||
return ret; | |||
} | |||
template<int COLS, int ROWS, int MASK, typename T> | |||
static inline vec<COLS, T> operator *(vec<ROWS, T, MASK> const &v, | |||
mat<COLS, ROWS, T> const &m) | |||
template<typename T, int COLS, int ROWS, int SWIZZLE> | |||
static inline vec_t<T, COLS> operator *(vec_t<T, ROWS, SWIZZLE> const &v, | |||
mat_t<T, COLS, ROWS> const &m) | |||
{ | |||
vec<COLS, T> ret(T(0)); | |||
vec_t<T, COLS> ret(T(0)); | |||
for (int i = 0; i < COLS; ++i) | |||
ret[i] = dot(v, m[i]); | |||
return ret; | |||
@@ -487,19 +487,19 @@ static inline vec<COLS, T> operator *(vec<ROWS, T, MASK> const &v, | |||
* Matrix-matrix multiplication | |||
*/ | |||
template<int COLS, int N, int ROWS, typename T> | |||
static inline mat<COLS, ROWS, T> operator *(mat<N, ROWS, T> const &a, | |||
mat<COLS, N, T> const &b) | |||
template<typename T, int COLS, int N, int ROWS> | |||
static inline mat_t<T, COLS, ROWS> operator *(mat_t<T, N, ROWS> const &a, | |||
mat_t<T, COLS, N> const &b) | |||
{ | |||
mat<COLS, ROWS, T> ret; | |||
mat_t<T, COLS, ROWS> ret; | |||
for (int i = 0; i < COLS; ++i) | |||
ret[i] = a * b[i]; | |||
return ret; | |||
} | |||
template<int N, typename T> | |||
static inline mat<N, N, T> &operator *=(mat<N, N, T> &a, | |||
mat<N, N, T> const &b) | |||
template<typename T, int N> | |||
static inline mat_t<T, N, N> &operator *=(mat_t<T, N, N> &a, | |||
mat_t<T, N, N> const &b) | |||
{ | |||
return a = a * b; | |||
} | |||
@@ -9,8 +9,8 @@ | |||
// | |||
// | |||
// The complex and quaternion classes | |||
// ---------------------------------- | |||
// The complex, quaternion and dual quaternion classes | |||
// --------------------------------------------------- | |||
// | |||
#if !defined __LOL_MATH_TRANSFORM_H__ | |||
@@ -18,9 +18,6 @@ | |||
#include <ostream> | |||
#include <lol/math/half.h> | |||
#include <lol/math/real.h> | |||
namespace lol | |||
{ | |||
@@ -29,162 +26,114 @@ namespace lol | |||
#endif | |||
/* | |||
* 2-element complexes | |||
* 2-element transforms: complex numbers | |||
*/ | |||
template <typename T> struct Cmplx | |||
template<typename T> | |||
struct cmplx_t | |||
{ | |||
typedef Cmplx<T> type; | |||
typedef cmplx_t<T> type; | |||
inline constexpr Cmplx() {} | |||
inline constexpr Cmplx(T X) : x(X), y(T(0)) {} | |||
inline constexpr Cmplx(T X, T Y) : x(X), y(Y) {} | |||
inline constexpr cmplx_t() {} | |||
inline constexpr cmplx_t(T X) : x(X), y(T(0)) {} | |||
inline constexpr cmplx_t(T X, T Y) : x(X), y(Y) {} | |||
template<typename U> | |||
explicit inline constexpr Cmplx(Cmplx<U> const &z) | |||
explicit inline constexpr cmplx_t(cmplx_t<U> const &z) | |||
: x(z.x), y(z.y) {} | |||
LOL_COMMON_MEMBER_OPS(x) | |||
LOL_NONVECTOR_MEMBER_OPS() | |||
inline Cmplx<T> operator *(Cmplx<T> const &val) const | |||
inline cmplx_t<T> operator *(cmplx_t<T> const &val) const | |||
{ | |||
return Cmplx<T>(x * val.x - y * val.y, x * val.y + y * val.x); | |||
return cmplx_t<T>(x * val.x - y * val.y, x * val.y + y * val.x); | |||
} | |||
inline Cmplx<T> operator *=(Cmplx<T> const &val) | |||
inline cmplx_t<T> operator *=(cmplx_t<T> const &val) | |||
{ | |||
return *this = (*this) * val; | |||
} | |||
inline Cmplx<T> operator ~() const | |||
inline cmplx_t<T> operator ~() const | |||
{ | |||
return Cmplx<T>(x, -y); | |||
return cmplx_t<T>(x, -y); | |||
} | |||
template<typename U> | |||
friend std::ostream &operator<<(std::ostream &stream, Cmplx<U> const &v); | |||
friend std::ostream &operator<<(std::ostream &stream, cmplx_t<U> const &v); | |||
T x, y; | |||
}; | |||
template<typename T> | |||
static inline T dot(Cmplx<T> const &z1, Cmplx<T> const &z2) | |||
{ | |||
T ret(0); | |||
for (size_t i = 0; i < sizeof(Cmplx<T>) / sizeof(T); ++i) | |||
ret += z1[i] * z2[i]; | |||
return ret; | |||
} | |||
template<typename T> | |||
static inline T sqlength(Cmplx<T> const &z) | |||
{ | |||
return dot(z, z); | |||
} | |||
template<typename T> | |||
static inline T length(Cmplx<T> const &z) | |||
{ | |||
/* FIXME: this is not very nice */ | |||
return (T)sqrt((double)sqlength(z)); | |||
} | |||
template<typename T> | |||
static inline T norm(Cmplx<T> const &z) | |||
{ | |||
return length(z); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> re(Cmplx<T> const &z) | |||
{ | |||
return ~z / sqlength(z); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> normalize(Cmplx<T> const &z) | |||
{ | |||
T norm = (T)length(z); | |||
return norm ? z / norm : Cmplx<T>(T(0)); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> operator /(T a, Cmplx<T> const &b) | |||
{ | |||
return a * re(b); | |||
} | |||
template<typename T> | |||
static inline Cmplx<T> operator /(Cmplx<T> a, Cmplx<T> const &b) | |||
{ | |||
return a * re(b); | |||
} | |||
template<typename T> | |||
static inline bool operator ==(Cmplx<T> const &a, T b) | |||
{ | |||
return (a.x == b) && !a.y; | |||
} | |||
template<typename T> | |||
static inline bool operator !=(Cmplx<T> const &a, T b) | |||
{ | |||
return (a.x != b) || a.y; | |||
} | |||
template<typename T> | |||
static inline bool operator ==(T a, Cmplx<T> const &b) { return b == a; } | |||
template<typename T> | |||
static inline bool operator !=(T a, Cmplx<T> const &b) { return b != a; } | |||
/* | |||
* 4-element quaternions | |||
* 4-element transforms: quaternions | |||
*/ | |||
template <typename T> struct Quat | |||
template<typename T> | |||
struct quat_t | |||
{ | |||
typedef Quat<T> type; | |||
typedef quat_t<T> type; | |||
inline constexpr Quat() {} | |||
inline constexpr Quat(T W) : w(W), x(0), y(0), z(0) {} | |||
inline constexpr Quat(T W, T X, T Y, T Z) : w(W), x(X), y(Y), z(Z) {} | |||
/* Default constructor and copy constructor */ | |||
inline constexpr quat_t() : w(), x(), y(), z() {} | |||
inline constexpr quat_t(quat_t<T> const &q) | |||
: w(q.w), x(q.x), y(q.y), z(q.z) {} | |||
/* Explicit constructor for type conversion */ | |||
template<typename U> | |||
explicit inline constexpr Quat(Quat<U> const &q) | |||
explicit inline constexpr quat_t(quat_t<U> const &q) | |||
: w(q.w), x(q.x), y(q.y), z(q.z) {} | |||
Quat(mat<3,3,T> const &m); | |||
Quat(mat<4,4,T> const &m); | |||
/* Various explicit constructors */ | |||
explicit inline constexpr quat_t(T W, T X, T Y, T Z) | |||
: w(W), x(X), y(Y), z(Z) {} | |||
explicit inline constexpr quat_t(T W) | |||
: w(W), x(0), y(0), z(0) {} | |||
explicit quat_t(mat_t<T,3,3> const &m); | |||
explicit quat_t(mat_t<T,4,4> const &m); | |||
LOL_COMMON_MEMBER_OPS(w) | |||
LOL_NONVECTOR_MEMBER_OPS() | |||
inline quat_t operator *(quat_t const &val) const | |||
{ | |||
vec_t<T,3> v1(x, y, z); | |||
vec_t<T,3> v2(val.x, val.y, val.z); | |||
vec_t<T,3> v3 = cross(v1, v2) + w * v2 + val.w * v1; | |||
return quat_t(w * val.w - dot(v1, v2), v3.x, v3.y, v3.z); | |||
} | |||
inline quat_t operator *=(quat_t const &val) | |||
{ | |||
return *this = (*this * val); | |||
} | |||
/* Create a unit quaternion representing a rotation around an axis. */ | |||
static Quat<T> rotate(T degrees, T x, T y, T z); | |||
static Quat<T> rotate(T degrees, vec<3,T> const &v); | |||
static quat_t rotate(T degrees, T x, T y, T z); | |||
static quat_t rotate(T degrees, vec_t<T,3> const &v); | |||
/* Create a unit quaternion representing a rotation between two vectors. | |||
* Input vectors need not be normalised. */ | |||
static Quat<T> rotate(vec<3,T> const &src, vec<3,T> const &dst); | |||
static quat_t rotate(vec_t<T,3> const &src, vec_t<T,3> const &dst); | |||
/* Convert from Euler angles. The axes in fromeuler_xyx are | |||
* x, then y', then x", ie. the axes are attached to the model. | |||
* If you want to rotate around static axes, just reverse the order | |||
* of the arguments. Angle values are in degrees. */ | |||
static Quat<T> fromeuler_xyx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xzx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yxy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yzy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zxz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zyz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xyx(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_xzx(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yxy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yzy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zxz(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zyz(T phi, T theta, T psi); | |||
static quat_t fromeuler_xyx(vec_t<T,3> const &v); | |||
static quat_t fromeuler_xzx(vec_t<T,3> const &v); | |||
static quat_t fromeuler_yxy(vec_t<T,3> const &v); | |||
static quat_t fromeuler_yzy(vec_t<T,3> const &v); | |||
static quat_t fromeuler_zxz(vec_t<T,3> const &v); | |||
static quat_t fromeuler_zyz(vec_t<T,3> const &v); | |||
static quat_t fromeuler_xyx(T phi, T theta, T psi); | |||
static quat_t fromeuler_xzx(T phi, T theta, T psi); | |||
static quat_t fromeuler_yxy(T phi, T theta, T psi); | |||
static quat_t fromeuler_yzy(T phi, T theta, T psi); | |||
static quat_t fromeuler_zxz(T phi, T theta, T psi); | |||
static quat_t fromeuler_zyz(T phi, T theta, T psi); | |||
/* Convert from Tait-Bryan angles (incorrectly called Euler angles, | |||
* but since everyone does it…). The axes in fromeuler_xyz are | |||
@@ -194,67 +143,60 @@ template <typename T> struct Quat | |||
* If you want to rotate around static axes, reverse the order in | |||
* the function name (_zyx instead of _xyz) AND reverse the order | |||
* of the arguments. */ | |||
static Quat<T> fromeuler_xyz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xzy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yxz(vec<3,T> const &v); | |||
static Quat<T> fromeuler_yzx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zxy(vec<3,T> const &v); | |||
static Quat<T> fromeuler_zyx(vec<3,T> const &v); | |||
static Quat<T> fromeuler_xyz(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_xzy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yxz(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_yzx(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zxy(T phi, T theta, T psi); | |||
static Quat<T> fromeuler_zyx(T phi, T theta, T psi); | |||
inline Quat<T> operator *(Quat<T> const &val) const; | |||
inline Quat<T> operator *=(Quat<T> const &val) | |||
{ | |||
return *this = (*this) * val; | |||
} | |||
inline Quat<T> operator ~() const | |||
static quat_t fromeuler_xyz(vec_t<T,3> const &v); | |||
static quat_t fromeuler_xzy(vec_t<T,3> const &v); | |||
static quat_t fromeuler_yxz(vec_t<T,3> const &v); | |||
static quat_t fromeuler_yzx(vec_t<T,3> const &v); | |||
static quat_t fromeuler_zxy(vec_t<T,3> const &v); | |||
static quat_t fromeuler_zyx(vec_t<T,3> const &v); | |||
static quat_t fromeuler_xyz(T phi, T theta, T psi); | |||
static quat_t fromeuler_xzy(T phi, T theta, T psi); | |||
static quat_t fromeuler_yxz(T phi, T theta, T psi); | |||
static quat_t fromeuler_yzx(T phi, T theta, T psi); | |||
static quat_t fromeuler_zxy(T phi, T theta, T psi); | |||
static quat_t fromeuler_zyx(T phi, T theta, T psi); | |||
inline quat_t operator ~() const | |||
{ | |||
return Quat<T>(w, -x, -y, -z); | |||
return quat_t(w, -x, -y, -z); | |||
} | |||
inline vec<3,T> transform(vec<3,T> const &v) const | |||
inline vec_t<T,3> transform(vec_t<T,3> const &v) const | |||
{ | |||
Quat<T> p = Quat<T>(0, v.x, v.y, v.z); | |||
Quat<T> q = *this * p / *this; | |||
return vec<3,T>(q.x, q.y, q.z); | |||
quat_t p = quat_t(0, v.x, v.y, v.z); | |||
quat_t q = *this * p / *this; | |||
return vec_t<T,3>(q.x, q.y, q.z); | |||
} | |||
inline vec<4,T> transform(vec<4,T> const &v) const | |||
inline vec_t<T,4> transform(vec_t<T,4> const &v) const | |||
{ | |||
Quat<T> p = Quat<T>(0, v.x, v.y, v.z); | |||
Quat<T> q = *this * p / *this; | |||
return vec<4,T>(q.x, q.y, q.z, v.w); | |||
quat_t p = quat_t(0, v.x, v.y, v.z); | |||
quat_t q = *this * p / *this; | |||
return vec_t<T,4>(q.x, q.y, q.z, v.w); | |||
} | |||
inline vec<3,T> operator *(vec<3,T> const &v) const | |||
inline vec_t<T,3> operator *(vec_t<T,3> const &v) const | |||
{ | |||
return transform(v); | |||
} | |||
inline vec<4,T> operator *(vec<4,T> const &v) const | |||
inline vec_t<T,4> operator *(vec_t<T,4> const &v) const | |||
{ | |||
return transform(v); | |||
} | |||
inline vec<3,T> axis() | |||
inline vec_t<T,3> axis() | |||
{ | |||
vec<3,T> v(x, y, z); | |||
vec_t<T,3> v(x, y, z); | |||
T n2 = sqlength(v); | |||
if (n2 <= (T)1e-6) | |||
return vec<3,T>::axis_x; | |||
return vec_t<T,3>::axis_x; | |||
return normalize(v); | |||
} | |||
inline T angle() | |||
{ | |||
vec<3,T> v(x, y, z); | |||
vec_t<T,3> v(x, y, z); | |||
T n2 = sqlength(v); | |||
if (n2 <= (T)1e-6) | |||
return (T)0; | |||
@@ -262,78 +204,153 @@ template <typename T> struct Quat | |||
} | |||
template<typename U> | |||
friend std::ostream &operator<<(std::ostream &stream, Quat<U> const &v); | |||
friend std::ostream &operator<<(std::ostream &stream, quat_t<U> const &v); | |||
/* XXX: storage order is wxyz, unlike vectors! */ | |||
T w, x, y, z; | |||
}; | |||
/* | |||
* Common operations on transforms | |||
*/ | |||
template<typename T> | |||
static inline T dot(Quat<T> const &q1, Quat<T> const &q2) | |||
static inline T dot(cmplx_t<T> const &t1, cmplx_t<T> const &t2) | |||
{ | |||
T ret(0); | |||
for (size_t i = 0; i < sizeof(Quat<T>) / sizeof(T); ++i) | |||
ret += q1[i] * q2[i]; | |||
for (size_t i = 0; i < sizeof(t1) / sizeof(T); ++i) | |||
ret += t1[i] * t2[i]; | |||
return ret; | |||
} | |||
template<typename T> | |||
static inline T sqlength(Quat<T> const &q) | |||
static inline T sqlength(cmplx_t<T> const &t) | |||
{ | |||
return dot(q, q); | |||
return dot(t, t); | |||
} | |||
template<typename T> | |||
static inline T length(Quat<T> const &q) | |||
static inline T length(cmplx_t<T> const &t) | |||
{ | |||
/* FIXME: this is not very nice */ | |||
return (T)sqrt((double)sqlength(q)); | |||
return (T)sqrt((double)sqlength(t)); | |||
} | |||
template<typename T> | |||
static inline T norm(Quat<T> const &q) | |||
static inline T norm(cmplx_t<T> const &t) | |||
{ | |||
return length(q); | |||
return length(t); | |||
} | |||
template<typename T> | |||
static inline Quat<T> re(Quat<T> const &q) | |||
static inline cmplx_t<T> normalize(cmplx_t<T> const &z) | |||
{ | |||
return ~q / sqlength(q); | |||
T norm = (T)length(z); | |||
return norm ? z / norm : cmplx_t<T>(T(0)); | |||
} | |||
/* XXX: duplicate */ | |||
template<typename T> | |||
static inline Quat<T> normalize(Quat<T> const &q) | |||
static inline T dot(quat_t<T> const &t1, quat_t<T> const &t2) | |||
{ | |||
T norm = (T)length(q); | |||
return norm ? q / norm : Quat<T>(T(0)); | |||
T ret(0); | |||
for (size_t i = 0; i < sizeof(t1) / sizeof(T); ++i) | |||
ret += t1[i] * t2[i]; | |||
return ret; | |||
} | |||
template<typename T> | |||
static inline Quat<T> operator /(T x, Quat<T> const &y) | |||
static inline T sqlength(quat_t<T> const &t) | |||
{ | |||
return x * re(y); | |||
return dot(t, t); | |||
} | |||
template<typename T> | |||
static inline Quat<T> operator /(Quat<T> const &x, Quat<T> const &y) | |||
static inline T length(quat_t<T> const &t) | |||
{ | |||
return x * re(y); | |||
/* FIXME: this is not very nice */ | |||
return (T)sqrt((double)sqlength(t)); | |||
} | |||
template<typename T> | |||
static inline T norm(quat_t<T> const &t) | |||
{ | |||
return length(t); | |||
} | |||
template<typename T> | |||
static inline quat_t<T> normalize(quat_t<T> const &z) | |||
{ | |||
T norm = (T)length(z); | |||
return norm ? z / norm : quat_t<T>(T(0)); | |||
} | |||
/* | |||
* Complex numbers only | |||
*/ | |||
template<typename T> | |||
extern Quat<T> slerp(Quat<T> const &qa, Quat<T> const &qb, T f); | |||
static inline cmplx_t<T> re(cmplx_t<T> const &z) | |||
{ | |||
return ~z / sqlength(z); | |||
} | |||
template<typename T> | |||
static inline cmplx_t<T> operator /(T a, cmplx_t<T> const &b) | |||
{ | |||
return a * re(b); | |||
} | |||
template<typename T> | |||
inline Quat<T> Quat<T>::operator *(Quat<T> const &val) const | |||
static inline cmplx_t<T> operator /(cmplx_t<T> a, cmplx_t<T> const &b) | |||
{ | |||
Quat<T> ret; | |||
vec<3,T> v1(x, y, z); | |||
vec<3,T> v2(val.x, val.y, val.z); | |||
vec<3,T> v3 = cross(v1, v2) + w * v2 + val.w * v1; | |||
return Quat<T>(w * val.w - dot(v1, v2), v3.x, v3.y, v3.z); | |||
return a * re(b); | |||
} | |||
template<typename T> | |||
static inline bool operator ==(cmplx_t<T> const &a, T b) | |||
{ | |||
return (a.x == b) && !a.y; | |||
} | |||
template<typename T> | |||
static inline bool operator !=(cmplx_t<T> const &a, T b) | |||
{ | |||
return (a.x != b) || a.y; | |||
} | |||
template<typename T> | |||
static inline bool operator ==(T a, cmplx_t<T> const &b) { return b == a; } | |||
template<typename T> | |||
static inline bool operator !=(T a, cmplx_t<T> const &b) { return b != a; } | |||
/* | |||
* Quaternions only | |||
*/ | |||
template<typename T> | |||
static inline quat_t<T> re(quat_t<T> const &q) | |||
{ | |||
return ~q / sqlength(q); | |||
} | |||
template<typename T> | |||
static inline quat_t<T> operator /(T x, quat_t<T> const &y) | |||
{ | |||
return x * re(y); | |||
} | |||
template<typename T> | |||
static inline quat_t<T> operator /(quat_t<T> const &x, quat_t<T> const &y) | |||
{ | |||
return x * re(y); | |||
} | |||
template<typename T> | |||
extern quat_t<T> slerp(quat_t<T> const &qa, quat_t<T> const &qb, T f); | |||
#if !LOL_FEATURE_CXX11_CONSTEXPR | |||
#undef constexpr | |||
#endif | |||
@@ -16,45 +16,45 @@ | |||
namespace lol { | |||
#define LOL_VEC_2_CONST(type, name, a, b) \ | |||
#define LOL_VEC_2_CONST(T, name, a, b) \ | |||
template<> \ | |||
vec<2,type> const vec<2,type>::name = vec<2,type>((type)a, (type)b); | |||
vec_t<T,2> const vec_t<T,2>::name = vec_t<T,2>((T)a, (T)b); | |||
#define LOL_VEC_3_CONST(type, name, a, b, c) \ | |||
#define LOL_VEC_3_CONST(T, name, a, b, c) \ | |||
template<> \ | |||
vec<3,type> const vec<3,type>::name = vec<3,type>((type)a, (type)b, (type)c); | |||
vec_t<T,3> const vec_t<T,3>::name = vec_t<T,3>((T)a, (T)b, (T)c); | |||
#define LOL_VEC_4_CONST(type, name, a, b, c, d) \ | |||
#define LOL_VEC_4_CONST(T, name, a, b, c, d) \ | |||
template<> \ | |||
vec<4,type> const vec<4,type>::name = vec<4,type>((type)a, (type)b, (type)c, (type)d); | |||
vec_t<T,4> const vec_t<T,4>::name = vec_t<T,4>((T)a, (T)b, (T)c, (T)d); | |||
#define LOL_MAT_CONST(type, name, a) \ | |||
#define LOL_MAT_CONST(T, name, a) \ | |||
template<> \ | |||
mat<2,2,type> const mat<2,2,type>::name = mat<2,2,type>((type)a); \ | |||
mat_t<T,2,2> const mat_t<T,2,2>::name = mat_t<T,2,2>((T)a); \ | |||
\ | |||
template<> \ | |||
mat<3,3,type> const mat<3,3,type>::name = mat<3,3,type>((type)a); \ | |||
mat_t<T,3,3> const mat_t<T,3,3>::name = mat_t<T,3,3>((T)a); \ | |||
\ | |||
template<> \ | |||
mat<4,4,type> const mat<4,4,type>::name = mat<4,4,type>((type)a); | |||
mat_t<T,4,4> const mat_t<T,4,4>::name = mat_t<T,4,4>((T)a); | |||
#define LOL_ALL_CONST_INNER(type) \ | |||
LOL_VEC_2_CONST(type, zero, 0, 0) \ | |||
LOL_VEC_2_CONST(type, axis_x, 1, 0) \ | |||
LOL_VEC_2_CONST(type, axis_y, 0, 1) \ | |||
#define LOL_ALL_CONST_INNER(T) \ | |||
LOL_VEC_2_CONST(T, zero, 0, 0) \ | |||
LOL_VEC_2_CONST(T, axis_x, 1, 0) \ | |||
LOL_VEC_2_CONST(T, axis_y, 0, 1) \ | |||
\ | |||
LOL_VEC_3_CONST(type, zero, 0, 0, 0) \ | |||
LOL_VEC_3_CONST(type, axis_x, 1, 0, 0) \ | |||
LOL_VEC_3_CONST(type, axis_y, 0, 1, 0) \ | |||
LOL_VEC_3_CONST(type, axis_z, 0, 0, 1) \ | |||
LOL_VEC_3_CONST(T, zero, 0, 0, 0) \ | |||
LOL_VEC_3_CONST(T, axis_x, 1, 0, 0) \ | |||
LOL_VEC_3_CONST(T, axis_y, 0, 1, 0) \ | |||
LOL_VEC_3_CONST(T, axis_z, 0, 0, 1) \ | |||
\ | |||
LOL_VEC_4_CONST(type, zero, 0, 0, 0, 0) \ | |||
LOL_VEC_4_CONST(type, axis_x, 1, 0, 0, 0) \ | |||
LOL_VEC_4_CONST(type, axis_y, 0, 1, 0, 0) \ | |||
LOL_VEC_4_CONST(type, axis_z, 0, 0, 1, 0) \ | |||
LOL_VEC_4_CONST(type, axis_w, 0, 0, 0, 1) \ | |||
LOL_VEC_4_CONST(T, zero, 0, 0, 0, 0) \ | |||
LOL_VEC_4_CONST(T, axis_x, 1, 0, 0, 0) \ | |||
LOL_VEC_4_CONST(T, axis_y, 0, 1, 0, 0) \ | |||
LOL_VEC_4_CONST(T, axis_z, 0, 0, 1, 0) \ | |||
LOL_VEC_4_CONST(T, axis_w, 0, 0, 0, 1) \ | |||
\ | |||
LOL_MAT_CONST(type, identity, 1) | |||
LOL_MAT_CONST(T, identity, 1) | |||
LOL_ALL_CONST_INNER(half) | |||
LOL_ALL_CONST_INNER(float) | |||
@@ -378,7 +378,7 @@ template<> mat3 mat3::rotate(float degrees, vec3 v) | |||
return rotate(degrees, v.x, v.y, v.z); | |||
} | |||
template<> mat3::mat(quat const &q) | |||
template<> mat3::mat_t(quat const &q) | |||
{ | |||
float n = norm(q); | |||
@@ -405,7 +405,7 @@ template<> mat3::mat(quat const &q) | |||
(*this)[2][2] = 1.0f - s * (q.x * q.x + q.y * q.y); | |||
} | |||
template<> mat4::mat(quat const &q) | |||
template<> mat4::mat_t(quat const &q) | |||
{ | |||
*this = mat4(mat3(q), 1.f); | |||
} | |||
@@ -448,12 +448,12 @@ static inline void MatrixToQuat(quat &that, mat3 const &m) | |||
} | |||
} | |||
template<> quat::Quat(mat3 const &m) | |||
template<> quat::quat_t(mat3 const &m) | |||
{ | |||
MatrixToQuat(*this, m); | |||
} | |||
template<> quat::Quat(mat4 const &m) | |||
template<> quat::quat_t(mat4 const &m) | |||
{ | |||
MatrixToQuat(*this, mat3(m)); | |||
} | |||
@@ -166,7 +166,7 @@ void EasyPhysic::BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol | |||
{ | |||
mat4 ThisMatrixLoc = NewMatrixLoc * inverse(PreviousMatrixLoc) * lol::mat4::translate(m_local_to_world[3].xyz); | |||
mat4 ThisMatrixRot = NewMatrixRot * inverse(PreviousMatrixRot) * lol::mat4(lol::quat(m_local_to_world)); | |||
SetTransform(ThisMatrixLoc[3].xyz, lol::mat4(lol::quat(ThisMatrixRot))); | |||
SetTransform(ThisMatrixLoc[3].xyz, lol::quat(ThisMatrixRot)); | |||
} | |||
} | |||