#ifndef __GEOMETRY_H__ #define __GEOMETRY_H__ #include #include #include namespace TinyRender { template class mat; template struct vec { vec() { for (size_t i = DIM; i--; data_[i] = T()) ; } T& operator[](const size_t i) { assert(i < DIM); return data_[i]; } const T& operator[](const size_t i) const { assert(i < DIM); return data_[i]; } private: T data_[DIM]; }; ///////////////////////////////////////////////////////////////////////////////// template struct vec<2, T> { vec() : x(T()), y(T()) {} vec(T X, T Y) : x(X), y(Y) {} template vec<2, T>(const vec<2, U>& v); T& operator[](const size_t i) { assert(i < 2); return i <= 0 ? x : y; } const T& operator[](const size_t i) const { assert(i < 2); return i <= 0 ? x : y; } T x, y; }; ///////////////////////////////////////////////////////////////////////////////// template struct vec<3, T> { vec() : x(T()), y(T()), z(T()) {} vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {} template vec<3, T>(const vec<3, U>& v); T& operator[](const size_t i) { assert(i < 3); return i <= 0 ? x : (1 == i ? y : z); } const T& operator[](const size_t i) const { assert(i < 3); return i <= 0 ? x : (1 == i ? y : z); } float norm() { return std::sqrt(x * x + y * y + z * z); } vec<3, T>& normalize(T l = 1) { *this = (*this) * (l / norm()); return *this; } T x, y, z; }; ///////////////////////////////////////////////////////////////////////////////// template T operator*(const vec& lhs, const vec& rhs) { T ret = T(); for (size_t i = DIM; i--; ret += lhs[i] * rhs[i]) ; return ret; } template vec operator+(vec lhs, const vec& rhs) { for (size_t i = DIM; i--; lhs[i] += rhs[i]) ; return lhs; } template vec operator-(vec lhs, const vec& rhs) { for (size_t i = DIM; i--; lhs[i] -= rhs[i]) ; return lhs; } template vec operator*(vec lhs, const U& rhs) { for (size_t i = DIM; i--; lhs[i] *= rhs) ; return lhs; } template vec operator/(vec lhs, const U& rhs) { for (size_t i = DIM; i--; lhs[i] /= rhs) ; return lhs; } template vec embed(const vec& v, T fill = 1) { vec ret; for (size_t i = LEN; i--; ret[i] = (i < DIM ? v[i] : fill)) ; return ret; } template vec proj(const vec& v) { vec ret; for (size_t i = LEN; i--; ret[i] = v[i]) ; return ret; } template vec<3, T> cross(vec<3, T> v1, vec<3, T> v2) { return vec<3, T>(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); } #if 0 template std::ostream& operator<<(std::ostream& out, vec& v) { for(unsigned int i=0; i struct dt { static T det(const mat& src) { T ret = 0; for (size_t i = DIM; i--; ret += src[0][i] * src.cofactor(0, i)) ; return ret; } }; template struct dt<1, T> { static T det(const mat<1, 1, T>& src) { return src[0][0]; } }; ///////////////////////////////////////////////////////////////////////////////// template class mat { vec rows[DimRows]; public: mat() {} vec& operator[](const size_t idx) { assert(idx < DimRows); return rows[idx]; } const vec& operator[](const size_t idx) const { assert(idx < DimRows); return rows[idx]; } vec col(const size_t idx) const { assert(idx < DimCols); vec ret; for (size_t i = DimRows; i--; ret[i] = rows[i][idx]) ; return ret; } void set_col(size_t idx, vec v) { assert(idx < DimCols); for (size_t i = DimRows; i--; rows[i][idx] = v[i]) ; } static mat identity() { mat ret; for (size_t i = DimRows; i--;) for (size_t j = DimCols; j--; ret[i][j] = (i == j)) ; return ret; } T det() const { return dt::det(*this); } mat get_minor(size_t row, size_t col) const { mat ret; for (size_t i = DimRows - 1; i--;) for (size_t j = DimCols - 1; j--; ret[i][j] = rows[i < row ? i : i + 1][j < col ? j : j + 1]) ; return ret; } T cofactor(size_t row, size_t col) const { return get_minor(row, col).det() * ((row + col) % 2 ? -1 : 1); } mat adjugate() const { mat ret; for (size_t i = DimRows; i--;) for (size_t j = DimCols; j--; ret[i][j] = cofactor(i, j)) ; return ret; } mat invert_transpose() { mat ret = adjugate(); T tmp = ret[0] * rows[0]; return ret / tmp; } mat invert() { return invert_transpose().transpose(); } mat transpose() { mat ret; for (size_t i = DimCols; i--; ret[i] = this->col(i)) ; return ret; } }; ///////////////////////////////////////////////////////////////////////////////// template vec operator*(const mat& lhs, const vec& rhs) { vec ret; for (size_t i = DimRows; i--; ret[i] = lhs[i] * rhs) ; return ret; } template mat operator*(const mat& lhs, const mat& rhs) { mat result; for (size_t i = R1; i--;) for (size_t j = C2; j--; result[i][j] = lhs[i] * rhs.col(j)) ; return result; } template mat operator/(mat lhs, const T& rhs) { for (size_t i = DimRows; i--; lhs[i] = lhs[i] / rhs) ; return lhs; } #if 0 template std::ostream& operator<<(std::ostream& out, mat& m) { for (size_t i=0; i Vec2f; typedef vec<2, double> Vec2d; typedef vec<2, int> Vec2i; typedef vec<3, float> Vec3f; typedef vec<3, double> Vec3d; typedef vec<3, int> Vec3i; typedef vec<4, float> Vec4f; typedef mat<4, 4, float> Matrix; } #endif //__GEOMETRY_H__