From b7e237c6ea4b1fce8201309a0adb27ed7114fb05 Mon Sep 17 00:00:00 2001 From: Sam Hocevar <sam@hocevar.net> Date: Thu, 3 Jul 2014 06:43:28 +0000 Subject: [PATCH] math: move matrix code out of vector.h into a new matrix.h header. --- src/Makefile.am | 2 +- src/lol/base/types.h | 4 + src/lol/math/all.h | 1 + src/lol/math/matrix.h | 427 ++++++++++++++++++++++++++++++++++++ src/lol/math/vector.h | 424 +---------------------------------- src/lolcore.vcxproj | 1 + src/lolcore.vcxproj.filters | 3 + 7 files changed, 445 insertions(+), 417 deletions(-) create mode 100644 src/lol/math/matrix.h diff --git a/src/Makefile.am b/src/Makefile.am index 749e1904..a6fda3e6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,7 +43,7 @@ liblolcore_headers = \ lol/math/all.h \ lol/math/functions.h lol/math/vector.h lol/math/half.h lol/math/real.h \ lol/math/geometry.h lol/math/interp.h lol/math/rand.h lol/math/array2d.h \ - lol/math/array3d.h lol/math/constants.h \ + lol/math/array3d.h lol/math/constants.h lol/math/matrix.h \ \ lol/algorithm/all.h \ lol/algorithm/sort.h lol/algorithm/portal.h lol/algorithm/aabb_tree.h \ diff --git a/src/lol/base/types.h b/src/lol/base/types.h index 0180bc5d..5c24fc43 100644 --- a/src/lol/base/types.h +++ b/src/lol/base/types.h @@ -28,6 +28,10 @@ typedef Real<16> real; /* The “half” type used for 16-bit floating point numbers. */ class half; +/* Forward declaration of vec and matrix */ +template<int N, typename T, int MASK> struct vec; +template<int COLS, int ROWS, typename T> struct matrix; + } /* namespace lol */ #endif // __LOL_BASE_TYPES_H__ diff --git a/src/lol/math/all.h b/src/lol/math/all.h index 24cfe955..446901a9 100644 --- a/src/lol/math/all.h +++ b/src/lol/math/all.h @@ -16,6 +16,7 @@ #include <lol/math/half.h> #include <lol/math/real.h> #include <lol/math/vector.h> +#include <lol/math/matrix.h> #include <lol/math/array2d.h> #include <lol/math/array3d.h> #include <lol/math/geometry.h> diff --git a/src/lol/math/matrix.h b/src/lol/math/matrix.h new file mode 100644 index 00000000..863e37e7 --- /dev/null +++ b/src/lol/math/matrix.h @@ -0,0 +1,427 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://www.wtfpl.net/ for more details. +// + +// +// The matrix classes +// ------------------ +// + +#if !defined __LOL_MATH_MATRIX_H__ +#define __LOL_MATH_MATRIX_H__ + +#include <stdint.h> +#include <ostream> + +#include <lol/math/vector.h> + +namespace lol +{ + +#if !LOL_FEATURE_CXX11_CONSTEXPR +# define constexpr /* */ +#endif + +/* The generic "matrix" type, which is a fixed-size matrix */ +template<int COLS, int ROWS, typename T> +struct matrix +{ + typedef matrix<COLS,ROWS,T> type; + + inline matrix() {} + + explicit inline matrix(T const &val) + { + T const zero = T(0); + for (int i = 0; i < COLS; ++i) + for (int j = 0; j < ROWS; ++j) + 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]; } + +private: + vec<ROWS,T> m_data[COLS]; +}; + +/* + * 2×2-element matrices + */ + +template <typename T> +struct matrix<2, 2, T> +{ + typedef matrix<2,2,T> type; + + inline matrix() {} + inline matrix(vec<2,T> V0, vec<2,T> V1) + : v0(V0), v1(V1) {} + + explicit inline matrix(T const &val) + : v0(val, (T)0), + v1((T)0, val) {} + + explicit inline matrix(matrix<4,4,T> const &mat) + : v0(mat[0].xy), + v1(mat[1].xy) {} + + inline vec<2,T>& operator[](size_t n) { return (&v0)[n]; } + inline vec<2,T> const& operator[](size_t n) const { return (&v0)[n]; } + + /* Helpers for transformation matrices */ + static matrix<2,2,T> rotate(T degrees); + static inline matrix<2,2,T> rotate(matrix<2,2,T> mat, T degrees) + { + return rotate(degrees) * mat; + } + + void printf() const; + String tostring() const; + + template<class U> + friend std::ostream &operator<<(std::ostream &stream, + matrix<2,2,U> const &m); + + vec<2,T> v0, v1; + + static const matrix<2,2,T> identity; +}; + +/* + * 3×3-element matrices + */ + +template <typename T> +struct matrix<3,3,T> +{ + typedef matrix<3,3,T> type; + + inline matrix() {} + inline matrix(vec<3,T> V0, vec<3,T> V1, vec<3,T> V2) + : v0(V0), v1(V1), v2(V2) {} + + explicit inline matrix(T const &val) + : v0(val, (T)0, (T)0), + v1((T)0, val, (T)0), + v2((T)0, (T)0, val) {} + + explicit inline matrix(matrix<2,2,T> mat) + : v0(mat[0], (T)0), + v1(mat[1], (T)0), + v2((T)0, (T)0, (T)0) {} + + explicit inline matrix(matrix<2,2,T> mat, T const &val) + : v0(vec<3,T>(mat[0], (T)0)), + v1(vec<3,T>(mat[1], (T)0)), + v2((T)0, (T)0, val) {} + + explicit inline matrix(matrix<4,4,T> const &mat) + : v0(mat[0].xyz), + v1(mat[1].xyz), + v2(mat[2].xyz) {} + + explicit matrix(Quat<T> const &q); + + inline vec<3,T>& operator[](size_t n) { return (&v0)[n]; } + inline vec<3,T> const& operator[](size_t n) const { return (&v0)[n]; } + + /* Helpers for transformation matrices */ + static matrix<3,3,T> scale(T x); + static matrix<3,3,T> scale(T x, T y, T z); + static matrix<3,3,T> scale(vec<3,T> v); + static matrix<3,3,T> rotate(T degrees, T x, T y, T z); + static matrix<3,3,T> rotate(T degrees, vec<3,T> v); + + static matrix<3,3,T> fromeuler_xyz(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_xzy(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_yxz(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_yzx(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_zxy(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_zyx(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_xyz(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_xzy(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_yxz(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_yzx(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_zxy(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_zyx(T phi, T theta, T psi); + + static matrix<3,3,T> fromeuler_xyx(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_xzx(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_yxy(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_yzy(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_zxz(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_zyz(vec<3,T> const &v); + static matrix<3,3,T> fromeuler_xyx(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_xzx(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_yxy(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_yzy(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_zxz(T phi, T theta, T psi); + static matrix<3,3,T> fromeuler_zyz(T phi, T theta, T psi); + + static inline matrix<3,3,T> rotate(matrix<3,3,T> mat, T degrees, vec<3,T> v) + { + return rotate(degrees, v) * mat; + } + + void printf() const; + String tostring() const; + + template<class U> + friend std::ostream &operator<<(std::ostream &stream, + matrix<3,3,U> const &m); + + vec<3,T> v0, v1, v2; + + static const matrix<3,3,T> identity; +}; + +/* + * 4×4-element matrices + */ + +template <typename T> +struct matrix<4, 4, T> +{ + typedef matrix<4,4,T> type; + + inline matrix() {} + inline matrix(vec<4,T> V0, vec<4,T> V1, vec<4,T> V2, vec<4,T> V3) + : v0(V0), v1(V1), v2(V2), v3(V3) {} + + explicit inline matrix(T const &val) + : v0(val, (T)0, (T)0, (T)0), + v1((T)0, val, (T)0, (T)0), + v2((T)0, (T)0, val, (T)0), + v3((T)0, (T)0, (T)0, val) {} + + explicit inline matrix(matrix<2,2,T> mat) + : v0(mat[0], (T)0, (T)0), + v1(mat[1], (T)0, (T)0), + v2((T)0, (T)0, (T)0, (T)0), + v3((T)0, (T)0, (T)0, (T)0) {} + + explicit inline matrix(matrix<2,2,T> mat, T const &val1, T const &val2) + : v0(mat[0], (T)0, (T)0), + v1(mat[1], (T)0, (T)0), + v2((T)0, (T)0, val1, (T)0), + v3((T)0, (T)0, (T)0, val2) {} + + explicit inline matrix(matrix<3,3,T> mat) + : v0(mat[0], (T)0), + v1(mat[1], (T)0), + v2(mat[2], (T)0), + v3((T)0, (T)0, (T)0, (T)0) {} + + explicit inline matrix(matrix<3,3,T> mat, T const &val) + : v0(mat[0], (T)0), + v1(mat[1], (T)0), + v2(mat[2], (T)0), + v3((T)0, (T)0, (T)0, val) {} + + explicit matrix(Quat<T> const &q); + + inline vec<4,T>& operator[](size_t n) { return (&v0)[n]; } + inline vec<4,T> const& operator[](size_t n) const { return (&v0)[n]; } + + /* Helpers for transformation matrices */ + static matrix<4,4,T> translate(T x, T y, T z); + static matrix<4,4,T> translate(vec<3,T> v); + + static inline matrix<4,4,T> scale(T x) + { + return matrix<4,4,T>(matrix<3,3,T>::scale(x), (T)1); + } + + static inline matrix<4,4,T> scale(T x, T y, T z) + { + return matrix<4,4,T>(matrix<3,3,T>::scale(x, y, z), (T)1); + } + + static inline matrix<4,4,T> scale(vec<3,T> v) + { + return matrix<4,4,T>(matrix<3,3,T>::scale(v), (T)1); + } + + static inline matrix<4,4,T> translate(matrix<4,4,T> const &mat, vec<3,T> v) + { + return translate(v) * mat; + } + + static inline matrix<4,4,T> rotate(T degrees, T x, T y, T z) + { + return matrix<4,4,T>(matrix<3,3,T>::rotate(degrees, x, y, z), (T)1); + } + + static inline matrix<4,4,T> rotate(T degrees, vec<3,T> v) + { + return matrix<4,4,T>(matrix<3,3,T>::rotate(degrees, v), (T)1); + } + + static inline matrix<4,4,T> rotate(matrix<4,4,T> &mat, T degrees, vec<3,T> v) + { + return rotate(degrees, v) * mat; + } + + static matrix<4,4,T> fromeuler_xyz(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_xzy(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_yxz(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_yzx(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_zxy(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_zyx(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_xyz(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_xzy(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_yxz(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_yzx(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_zxy(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_zyx(T phi, T theta, T psi); + + static matrix<4,4,T> fromeuler_xyx(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_xzx(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_yxy(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_yzy(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_zxz(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_zyz(vec<3,T> const &v); + static matrix<4,4,T> fromeuler_xyx(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_xzx(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_yxy(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_yzy(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_zxz(T phi, T theta, T psi); + static matrix<4,4,T> fromeuler_zyz(T phi, T theta, T psi); + + /* Helpers for view matrices */ + static matrix<4,4,T> lookat(vec<3,T> eye, vec<3,T> center, vec<3,T> up); + + /* Helpers for projection matrices */ + static matrix<4,4,T> ortho(T left, T right, T bottom, T top, T near, T far); + static matrix<4,4,T> ortho(T width, T height, T near, T far); + static matrix<4,4,T> frustum(T left, T right, T bottom, T top, T near, T far); + static matrix<4,4,T> perspective(T fov_y, T width, T height, T near, T far); + static matrix<4,4,T> 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, + matrix<4,4,U> const &m); + + vec<4,T> v0, v1, v2, v3; + + static const matrix<4,4,T> identity; +}; + +template<typename T> T determinant(matrix<2,2,T> const &); +template<typename T> T determinant(matrix<3,3,T> const &); +template<typename T> T determinant(matrix<4,4,T> const &); + +template<typename T> matrix<2,2,T> transpose(matrix<2,2,T> const &); +template<typename T> matrix<3,3,T> transpose(matrix<3,3,T> const &); +template<typename T> matrix<4,4,T> transpose(matrix<4,4,T> const &); + +template<typename T> matrix<2,2,T> inverse(matrix<2,2,T> const &); +template<typename T> matrix<3,3,T> inverse(matrix<3,3,T> const &); +template<typename T> matrix<4,4,T> inverse(matrix<4,4,T> const &); + +/* + * Addition/subtraction/unary + */ + +template<int COLS, int ROWS, typename T> +static inline matrix<COLS, ROWS, T> &operator +=(matrix<COLS, ROWS, T> &a, + matrix<COLS, ROWS, T> const &b) +{ + for (int i = 0; i < COLS; ++i) + a[i] += b[i]; + return a; +} + +template<int COLS, int ROWS, typename T> +static inline matrix<COLS, ROWS, T> operator +(matrix<COLS, ROWS, T> const &a, + matrix<COLS, ROWS, T> const &b) +{ + matrix<COLS, ROWS, T> ret = a; + return ret += b; +} + +template<int COLS, int ROWS, typename T> +static inline matrix<COLS, ROWS, T> operator +(matrix<COLS, ROWS, T> const &m) +{ + return m; +} + +template<int COLS, int ROWS, typename T> +static inline matrix<COLS, ROWS, T> &operator -=(matrix<COLS, ROWS, T> &a, + matrix<COLS, ROWS, T> const &b) +{ + for (int i = 0; i < COLS; ++i) + a[i] -= b[i]; + return a; +} + +template<int COLS, int ROWS, typename T> +static inline matrix<COLS, ROWS, T> operator -(matrix<COLS, ROWS, T> const &a, + matrix<COLS, ROWS, T> const &b) +{ + matrix<COLS, ROWS, T> ret = a; + return ret -= b; +} + +template<int COLS, int ROWS, typename T> +static inline matrix<COLS, ROWS, T> operator -(matrix<COLS, ROWS, T> const &m) +{ + matrix<COLS, ROWS, T> ret; + for (int i = 0; i < COLS; ++i) + ret[i] = -m[i]; + return ret; +} + +/* + * Matrix-vector multiplication + */ + +template<int COLS, int ROWS, int MASK, typename T> +static inline vec<ROWS, T> operator *(matrix<COLS, ROWS, T> const &m, + vec<COLS, T, MASK> const &v) +{ + vec<ROWS, T> ret(T(0)); + for (int i = 0; i < COLS; ++i) + ret += m[i] * v[i]; + return ret; +} + +/* + * Matrix-matrix multiplication + */ + +template<int COLS, int N, int ROWS, typename T> +static inline matrix<COLS, ROWS, T> operator *(matrix<N, ROWS, T> const &a, + matrix<COLS, N, T> const &b) +{ + matrix<COLS, ROWS, T> ret; + for (int i = 0; i < COLS; ++i) + ret[i] = a * b[i]; + return ret; +} + +template<int N, typename T> +static inline matrix<N, N, T> &operator *=(matrix<N, N, T> &a, + matrix<N, N, T> const &b) +{ + return a = a * b; +} + +#if !LOL_FEATURE_CXX11_CONSTEXPR +#undef constexpr +#endif + +} /* namespace lol */ + +#endif // __LOL_MATH_MATRIX_H__ + diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h index 8aa6eb49..cc799578 100644 --- a/src/lol/math/vector.h +++ b/src/lol/math/vector.h @@ -52,6 +52,8 @@ namespace lol template<int N, typename T, int MASK = -1> struct vec { + typedef vec<N,T> type; + inline vec<N, T, MASK>& operator =(vec<N, T> that); #if LOL_FEATURE_CXX11_RELAXED_UNIONS @@ -78,16 +80,13 @@ struct vec template<int N, typename T> struct vec<N, T, -1> { -private: - T m_data[N]; -}; + typedef vec<N,T> type; + + inline T& operator[](size_t n) { return m_data[n]; } + inline T const& operator[](size_t n) const { return m_data[n]; } -/* The generic "matrix" type, which is a fixed-size matrix */ -template<int COLS, int ROWS, typename T> -struct matrix -{ private: - T m_data[COLS][ROWS]; + T m_data[N]; }; /* The generic complex and quaternion types. */ @@ -99,7 +98,6 @@ template<typename T> struct Quat; */ #define COMMA , - #define LOL_VECTOR_TYPEDEFS(tleft, tright, suffix) \ typedef tleft half tright f16##suffix; \ typedef tleft float tright suffix; \ @@ -134,6 +132,7 @@ LOL_VECTOR_TYPEDEFS(Cmplx<, >, cmplx) LOL_VECTOR_TYPEDEFS(Quat<, >, quat) #undef LOL_VECTOR_TYPEDEFS +#undef COMMA /* * HLSL/Cg-compliant type names. @@ -1612,413 +1611,6 @@ inline vec<N, T, MASK>& vec<N, T, MASK>::operator =(vec<N,T> that) } #endif -/* - * 2×2-element matrices - */ - -template <typename T> -struct matrix<2, 2, T> -{ - typedef matrix<2,2,T> type; - - inline matrix() {} - inline matrix(vec<2,T> V0, vec<2,T> V1) - : v0(V0), v1(V1) {} - - explicit inline matrix(T val) - : v0(val, (T)0), - v1((T)0, val) {} - - explicit inline matrix(matrix<4,4,T> const &mat) - : v0(mat[0].xy), - v1(mat[1].xy) {} - - inline vec<2,T>& operator[](size_t n) { return (&v0)[n]; } - inline vec<2,T> const& operator[](size_t n) const { return (&v0)[n]; } - - /* Helpers for transformation matrices */ - static matrix<2,2,T> rotate(T degrees); - static inline matrix<2,2,T> rotate(matrix<2,2,T> mat, T degrees) - { - return rotate(degrees) * mat; - } - - void printf() const; - String tostring() const; - - template<class U> - friend std::ostream &operator<<(std::ostream &stream, - matrix<2,2,U> const &m); - - inline matrix<2,2,T> operator +(matrix<2,2,T> const m) const - { - return matrix<2,2,T>(v0 + m[0], v1 + m[1]); - } - - inline matrix<2,2,T> operator +=(matrix<2,2,T> const m) - { - return *this = *this + m; - } - - inline matrix<2,2,T> operator -(matrix<2,2,T> const m) const - { - return matrix<2,2,T>(v0 - m[0], v1 - m[1]); - } - - inline matrix<2,2,T> operator -=(matrix<2,2,T> const m) - { - return *this = *this - m; - } - - inline matrix<2,2,T> operator *(matrix<2,2,T> const m) const - { - return matrix<2,2,T>(*this * m[0], *this * m[1]); - } - - inline matrix<2,2,T> operator *=(matrix<2,2,T> const m) - { - return *this = *this * m; - } - - inline vec<2,T> operator *(vec<2,T> const m) const - { - vec<2,T> ret; - for (int j = 0; j < 2; j++) - { - T tmp = 0; - for (int k = 0; k < 2; k++) - tmp += (*this)[k][j] * m[k]; - ret[j] = tmp; - } - return ret; - } - - vec<2,T> v0, v1; - - static const matrix<2,2,T> identity; -}; - -/* - * 3×3-element matrices - */ - -template <typename T> -struct matrix<3,3,T> -{ - typedef matrix<3,3,T> type; - - inline matrix() {} - inline matrix(vec<3,T> V0, vec<3,T> V1, vec<3,T> V2) - : v0(V0), v1(V1), v2(V2) {} - - explicit inline matrix(T val) - : v0(val, (T)0, (T)0), - v1((T)0, val, (T)0), - v2((T)0, (T)0, val) {} - - explicit inline matrix(matrix<2,2,T> mat) - : v0(mat[0], (T)0), - v1(mat[1], (T)0), - v2((T)0, (T)0, (T)0) {} - - explicit inline matrix(matrix<2,2,T> mat, T val) - : v0(vec<3,T>(mat[0], (T)0)), - v1(vec<3,T>(mat[1], (T)0)), - v2((T)0, (T)0, val) {} - - explicit inline matrix(matrix<4,4,T> const &mat) - : v0(mat[0].xyz), - v1(mat[1].xyz), - v2(mat[2].xyz) {} - - explicit matrix(Quat<T> const &q); - - inline vec<3,T>& operator[](size_t n) { return (&v0)[n]; } - inline vec<3,T> const& operator[](size_t n) const { return (&v0)[n]; } - - /* Helpers for transformation matrices */ - static matrix<3,3,T> scale(T x); - static matrix<3,3,T> scale(T x, T y, T z); - static matrix<3,3,T> scale(vec<3,T> v); - static matrix<3,3,T> rotate(T degrees, T x, T y, T z); - static matrix<3,3,T> rotate(T degrees, vec<3,T> v); - - static matrix<3,3,T> fromeuler_xyz(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_xzy(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_yxz(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_yzx(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_zxy(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_zyx(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_xyz(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_xzy(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_yxz(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_yzx(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_zxy(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_zyx(T phi, T theta, T psi); - - static matrix<3,3,T> fromeuler_xyx(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_xzx(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_yxy(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_yzy(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_zxz(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_zyz(vec<3,T> const &v); - static matrix<3,3,T> fromeuler_xyx(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_xzx(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_yxy(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_yzy(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_zxz(T phi, T theta, T psi); - static matrix<3,3,T> fromeuler_zyz(T phi, T theta, T psi); - - static inline matrix<3,3,T> rotate(matrix<3,3,T> mat, T degrees, vec<3,T> v) - { - return rotate(degrees, v) * mat; - } - - void printf() const; - String tostring() const; - - template<class U> - friend std::ostream &operator<<(std::ostream &stream, - matrix<3,3,U> const &m); - - inline matrix<3,3,T> operator +(matrix<3,3,T> const m) const - { - return matrix<3,3,T>(v0 + m[0], v1 + m[1], v2 + m[2]); - } - - inline matrix<3,3,T> operator +=(matrix<3,3,T> const m) - { - return *this = *this + m; - } - - inline matrix<3,3,T> operator -(matrix<3,3,T> const m) const - { - return matrix<3,3,T>(v0 - m[0], v1 - m[1], v2 - m[2]); - } - - inline matrix<3,3,T> operator -=(matrix<3,3,T> const m) - { - return *this = *this - m; - } - - inline matrix<3,3,T> operator *(matrix<3,3,T> const m) const - { - return matrix<3,3,T>(*this * m[0], *this * m[1], *this * m[2]); - } - - inline matrix<3,3,T> operator *=(matrix<3,3,T> const m) - { - return *this = *this * m; - } - - inline vec<3,T> operator *(vec<3,T> const m) const - { - vec<3,T> ret; - for (int j = 0; j < 3; j++) - { - T tmp = 0; - for (int k = 0; k < 3; k++) - tmp += (*this)[k][j] * m[k]; - ret[j] = tmp; - } - return ret; - } - - vec<3,T> v0, v1, v2; - - static const matrix<3,3,T> identity; -}; - -/* - * 4×4-element matrices - */ - -template <typename T> -struct matrix<4, 4, T> -{ - typedef matrix<4,4,T> type; - - inline matrix() {} - inline matrix(vec<4,T> V0, vec<4,T> V1, vec<4,T> V2, vec<4,T> V3) - : v0(V0), v1(V1), v2(V2), v3(V3) {} - - explicit inline matrix(T val) - : v0(val, (T)0, (T)0, (T)0), - v1((T)0, val, (T)0, (T)0), - v2((T)0, (T)0, val, (T)0), - v3((T)0, (T)0, (T)0, val) {} - - explicit inline matrix(matrix<2,2,T> mat) - : v0(mat[0], (T)0, (T)0), - v1(mat[1], (T)0, (T)0), - v2((T)0, (T)0, (T)0, (T)0), - v3((T)0, (T)0, (T)0, (T)0) {} - - explicit inline matrix(matrix<2,2,T> mat, T val1, T val2) - : v0(mat[0], (T)0, (T)0), - v1(mat[1], (T)0, (T)0), - v2((T)0, (T)0, val1, (T)0), - v3((T)0, (T)0, (T)0, val2) {} - - explicit inline matrix(matrix<3,3,T> mat) - : v0(mat[0], (T)0), - v1(mat[1], (T)0), - v2(mat[2], (T)0), - v3((T)0, (T)0, (T)0, (T)0) {} - - explicit inline matrix(matrix<3,3,T> mat, T val) - : v0(mat[0], (T)0), - v1(mat[1], (T)0), - v2(mat[2], (T)0), - v3((T)0, (T)0, (T)0, val) {} - - explicit matrix(Quat<T> const &q); - - inline vec<4,T>& operator[](size_t n) { return (&v0)[n]; } - inline vec<4,T> const& operator[](size_t n) const { return (&v0)[n]; } - - /* Helpers for transformation matrices */ - static matrix<4,4,T> translate(T x, T y, T z); - static matrix<4,4,T> translate(vec<3,T> v); - - static inline matrix<4,4,T> scale(T x) - { - return matrix<4,4,T>(matrix<3,3,T>::scale(x), (T)1); - } - - static inline matrix<4,4,T> scale(T x, T y, T z) - { - return matrix<4,4,T>(matrix<3,3,T>::scale(x, y, z), (T)1); - } - - static inline matrix<4,4,T> scale(vec<3,T> v) - { - return matrix<4,4,T>(matrix<3,3,T>::scale(v), (T)1); - } - - static inline matrix<4,4,T> translate(matrix<4,4,T> const &mat, vec<3,T> v) - { - return translate(v) * mat; - } - - static inline matrix<4,4,T> rotate(T degrees, T x, T y, T z) - { - return matrix<4,4,T>(matrix<3,3,T>::rotate(degrees, x, y, z), (T)1); - } - - static inline matrix<4,4,T> rotate(T degrees, vec<3,T> v) - { - return matrix<4,4,T>(matrix<3,3,T>::rotate(degrees, v), (T)1); - } - - static inline matrix<4,4,T> rotate(matrix<4,4,T> &mat, T degrees, vec<3,T> v) - { - return rotate(degrees, v) * mat; - } - - static matrix<4,4,T> fromeuler_xyz(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_xzy(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_yxz(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_yzx(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_zxy(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_zyx(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_xyz(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_xzy(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_yxz(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_yzx(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_zxy(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_zyx(T phi, T theta, T psi); - - static matrix<4,4,T> fromeuler_xyx(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_xzx(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_yxy(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_yzy(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_zxz(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_zyz(vec<3,T> const &v); - static matrix<4,4,T> fromeuler_xyx(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_xzx(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_yxy(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_yzy(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_zxz(T phi, T theta, T psi); - static matrix<4,4,T> fromeuler_zyz(T phi, T theta, T psi); - - /* Helpers for view matrices */ - static matrix<4,4,T> lookat(vec<3,T> eye, vec<3,T> center, vec<3,T> up); - - /* Helpers for projection matrices */ - static matrix<4,4,T> ortho(T left, T right, T bottom, T top, T near, T far); - static matrix<4,4,T> ortho(T width, T height, T near, T far); - static matrix<4,4,T> frustum(T left, T right, T bottom, T top, T near, T far); - static matrix<4,4,T> perspective(T fov_y, T width, T height, T near, T far); - static matrix<4,4,T> 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, - matrix<4,4,U> const &m); - - inline matrix<4,4,T> operator +(matrix<4,4,T> const &m) const - { - return matrix<4,4,T>(v0 + m[0], v1 + m[1], v2 + m[2], v3 + m[3]); - } - - inline matrix<4,4,T> operator +=(matrix<4,4,T> const &m) - { - return *this = *this + m; - } - - inline matrix<4,4,T> operator -(matrix<4,4,T> const &m) const - { - return matrix<4,4,T>(v0 - m[0], v1 - m[1], v2 - m[2], v3 - m[3]); - } - - inline matrix<4,4,T> operator -=(matrix<4,4,T> const &m) - { - return *this = *this - m; - } - - inline matrix<4,4,T> operator *(matrix<4,4,T> const &m) const - { - return matrix<4,4,T>(*this * m[0], *this * m[1], *this * m[2], *this * m[3]); - } - - inline matrix<4,4,T> operator *=(matrix<4,4,T> const &m) - { - return *this = *this * m; - } - - inline vec<4,T> operator *(vec<4,T> const &m) const - { - vec<4,T> ret; - for (int j = 0; j < 4; j++) - { - T tmp = 0; - for (int k = 0; k < 4; k++) - tmp += (*this)[k][j] * m[k]; - ret[j] = tmp; - } - return ret; - } - - vec<4,T> v0, v1, v2, v3; - - static const matrix<4,4,T> identity; -}; - -template<typename T> T determinant(matrix<2,2,T> const &); -template<typename T> T determinant(matrix<3,3,T> const &); -template<typename T> T determinant(matrix<4,4,T> const &); - -template<typename T> matrix<2,2,T> transpose(matrix<2,2,T> const &); -template<typename T> matrix<3,3,T> transpose(matrix<3,3,T> const &); -template<typename T> matrix<4,4,T> transpose(matrix<4,4,T> const &); - -template<typename T> matrix<2,2,T> inverse(matrix<2,2,T> const &); -template<typename T> matrix<3,3,T> inverse(matrix<3,3,T> const &); -template<typename T> matrix<4,4,T> inverse(matrix<4,4,T> const &); - #if !LOL_FEATURE_CXX11_CONSTEXPR #undef constexpr #endif diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index da0ea4e6..dd1e4100 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -326,6 +326,7 @@ <ClInclude Include="lol\math\geometry.h" /> <ClInclude Include="lol\math\half.h" /> <ClInclude Include="lol\math\interp.h" /> + <ClInclude Include="lol\math\matrix.h" /> <ClInclude Include="lol\math\rand.h" /> <ClInclude Include="lol\math\real.h" /> <ClInclude Include="lol\math\remez.h" /> diff --git a/src/lolcore.vcxproj.filters b/src/lolcore.vcxproj.filters index 988ca612..6849a1c8 100644 --- a/src/lolcore.vcxproj.filters +++ b/src/lolcore.vcxproj.filters @@ -438,6 +438,9 @@ <ClInclude Include="lol\math\all.h"> <Filter>lol\math</Filter> </ClInclude> + <ClInclude Include="lol\math\matrix.h"> + <Filter>lol\math</Filter> + </ClInclude> <ClInclude Include="lol\math\rand.h"> <Filter>lol\math</Filter> </ClInclude>