/* * OpenClonk, http://www.openclonk.org * * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ * Copyright (c) 2011-2016, The OpenClonk Team and contributors * * Distributed under the terms of the ISC license; see accompanying file * "COPYING" for details. * * "Clonk" is a registered trademark of Matthes Bender, used with permission. * See accompanying file "TRADEMARK" for details. * * To redistribute this file separately, substitute the full license texts * for the above references. */ #ifndef INC_StdMeshMath #define INC_StdMeshMath // OGRE mesh struct StdMeshVector { float x, y, z; static StdMeshVector Zero(); static StdMeshVector UnitScale(); static StdMeshVector Translate(float dx, float dy, float dz); static StdMeshVector Cross(const StdMeshVector& lhs, const StdMeshVector& rhs); void Normalize(); }; struct StdMeshVertex { static const size_t MaxBoneWeightCount = 8; // Match GL_T2F_N3F_V3F float u{0}, v{0}; float nx{0}, ny{0}, nz{0}; float x{0}, y{0}, z{0}; float bone_weight[MaxBoneWeightCount]; uint16_t bone_index[MaxBoneWeightCount]; char _padding[16]; StdMeshVertex() { std::uninitialized_fill(std::begin(bone_weight), std::end(bone_weight), 0); std::uninitialized_fill(std::begin(bone_index), std::end(bone_index), 0); std::uninitialized_fill(std::begin(_padding), std::end(_padding), 0); } }; static_assert((sizeof(StdMeshVertex) & 31) == 0, "StdMeshVertex should be a multiple of 32 bytes"); struct StdMeshQuaternion { float w; float x, y, z; static StdMeshQuaternion Zero(); static StdMeshQuaternion AngleAxis(float theta, const StdMeshVector& axis); float LenSqr() const { return w*w+x*x+y*y+z*z; } void Normalize(); static StdMeshQuaternion Nlerp(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs, float w); }; struct StdMeshTransformation { StdMeshVector scale; StdMeshQuaternion rotate; StdMeshVector translate; static StdMeshTransformation Zero(); static StdMeshTransformation Identity(); static StdMeshTransformation Inverse(const StdMeshTransformation& transform); static StdMeshTransformation Translate(float dx, float dy, float dz); static StdMeshTransformation Scale(float sx, float sy, float sz); static StdMeshTransformation Rotate(float angle, float rx, float ry, float rz); // TODO: Might add path parameter if necessary static StdMeshTransformation Nlerp(const StdMeshTransformation& lhs, const StdMeshTransformation& rhs, float w); }; class StdMeshMatrix { public: static const int NColumns = 4; static const int NRows = 3; static StdMeshMatrix Zero(); static StdMeshMatrix Identity(); static StdMeshMatrix Inverse(const StdMeshMatrix& mat); static StdMeshMatrix Translate(float dx, float dy, float dz); static StdMeshMatrix Scale(float sx, float sy, float sz); static StdMeshMatrix Rotate(float angle, float rx, float ry, float rz); static StdMeshMatrix Transform(const StdMeshTransformation& transform); static StdMeshMatrix TransformInverse(const StdMeshTransformation& transform); static StdMeshMatrix LookAt(const StdMeshVector& eye, const StdMeshVector& center, const StdMeshVector& up); float& operator()(int i, int j) { return a[i][j]; } float operator()(int i, int j) const { return a[i][j]; } float Determinant() const; StdMeshTransformation Decompose() const; const float* data() const { return &a[0][0]; } private: // 3x3 orthogonal + translation in last column float a[3][4]; }; // Full 4x4 matrix with projection components class StdProjectionMatrix { public: static const int NColumns = 4; static const int NRows = 4; static StdProjectionMatrix Identity(); static StdProjectionMatrix Translate(float dx, float dy, float dz); static StdProjectionMatrix Scale(float sx, float sy, float sz); static StdProjectionMatrix Rotate(float angle, float rx, float ry, float rz); static StdProjectionMatrix Orthographic(float left, float right, float bottom, float top); static StdMeshMatrix Upper3x4(const StdProjectionMatrix& matrix); float& operator()(int i, int j) { return a[i][j]; } float operator()(int i, int j) const { return a[i][j]; } const float* data() const { return &a[0][0]; } private: float a[4][4]; }; StdMeshMatrix operator*(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs); StdMeshMatrix operator*(float lhs, const StdMeshMatrix& rhs); StdMeshMatrix operator*(const StdMeshMatrix& lhs, float rhs); StdMeshMatrix& operator*=(StdMeshMatrix& lhs, const StdMeshMatrix& rhs); StdMeshMatrix operator+(const StdMeshMatrix& lhs, const StdMeshMatrix& rhs); StdProjectionMatrix operator*(const StdProjectionMatrix& lhs, const StdProjectionMatrix& rhs); StdProjectionMatrix& operator*=(StdProjectionMatrix& lhs, const StdProjectionMatrix& rhs); StdMeshQuaternion operator-(const StdMeshQuaternion& rhs); StdMeshQuaternion operator*(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs); StdMeshQuaternion& operator*=(StdMeshQuaternion& lhs, float rhs); StdMeshQuaternion operator*(const StdMeshQuaternion& lhs, float rhs); StdMeshQuaternion operator*(float lhs, const StdMeshQuaternion& rhs); StdMeshQuaternion& operator+=(StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs); StdMeshQuaternion operator+(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs); StdMeshQuaternion operator-(const StdMeshQuaternion& lhs, const StdMeshQuaternion& rhs); StdMeshTransformation operator*(const StdMeshTransformation& lhs, const StdMeshTransformation& rhs); StdMeshVector operator-(const StdMeshVector& rhs); StdMeshVector& operator+=(StdMeshVector& lhs, const StdMeshVector& rhs); StdMeshVector operator+(const StdMeshVector& lhs, const StdMeshVector& rhs); StdMeshVector& operator-=(StdMeshVector& lhs, const StdMeshVector& rhs); StdMeshVector operator-(const StdMeshVector& lhs, const StdMeshVector& rhs); StdMeshVector operator*(const StdMeshVector& lhs, const StdMeshVector& rhs); StdMeshVector& operator*=(StdMeshVector& lhs, float rhs); StdMeshVector operator*(const StdMeshVector& lhs, float rhs); StdMeshVector operator*(float lhs, const StdMeshVector& rhs); StdMeshVector operator/(const StdMeshVector& lhs, const StdMeshVector& rhs); StdMeshVector operator/(float lhs, const StdMeshVector& rhs); StdMeshVector operator/(const StdMeshVector& lhs, float rhs); StdMeshVector operator*(const StdMeshMatrix& lhs, const StdMeshVector& rhs); // does not apply translation part StdMeshVector operator*(const StdMeshQuaternion& lhs, const StdMeshVector& rhs); StdMeshVertex& operator+=(StdMeshVertex& lhs, const StdMeshVertex& rhs); StdMeshVertex operator+(const StdMeshVertex& lhs, const StdMeshVertex& rhs); StdMeshVertex operator*(float lhs, const StdMeshVertex& rhs); StdMeshVertex operator*(const StdMeshVertex& lhs, float rhs); StdMeshVertex operator*(const StdMeshMatrix& lhs, const StdMeshVertex& rhs); // Multiply in-place the given matrix with a translation matrix to the right template void Translate(MatrixType& mat, float dx, float dy, float dz) { static_assert(MatrixType::NColumns >= 4, "Matrix must have at least 4 columns"); for (int i = 0; i < MatrixType::NRows; ++i) mat(i, 3) += mat(i,0)*dx + mat(i,1)*dy + mat(i,2)*dz; } // Multiply in-place the given matrix with a scale matrix to the right template void Scale(MatrixType& mat, float sx, float sy, float sz) { static_assert(MatrixType::NColumns >= 3, "Matrix must have at least 3 columns"); for (int i = 0; i < MatrixType::NRows; ++i) { mat(i, 0) *= sx; mat(i, 1) *= sy; mat(i, 2) *= sz; } } // Multiply in-place the given matrix with a rotation matrix to the right template void Rotate(MatrixType& mat, float angle, float x, float y, float z) { mat *= MatrixType::Rotate(angle, x, y, z); } // Multiply in-place the given matrix with a perspective projection matrix to the right template void Perspective(MatrixType& mat, float cot_fovy2, float aspect, float nearVal, float farVal) { static_assert(MatrixType::NColumns >= 4, "Matrix must have at least 4 columns"); const float fa = cot_fovy2 / aspect; const float fb = cot_fovy2; const float z1 = (nearVal + farVal) / (nearVal - farVal); const float z2 = 2 * nearVal * farVal / (nearVal - farVal); for (int i = 0; i < MatrixType::NRows; ++i) { const float mat2 = mat(i, 2); mat(i, 0) *= fa; mat(i, 1) *= fb; mat(i, 2) = mat2 * z1 - mat(i, 3); mat(i, 3) = mat2 * z2; } } #endif