From ba009f8edd6a6f28c49cd88561bdab5ac1dd33f0 Mon Sep 17 00:00:00 2001 From: Balhau Date: Fri, 23 Jun 2023 00:43:34 +0100 Subject: [PATCH] More stuff --- app/engine.cpp | 35 ++++++++++- premake/engine.lua | 8 +-- src/engine/math/matrix3d.cpp | 113 ++++++++++++++++++++++++++++++++--- src/engine/math/matrix3d.hpp | 29 +++++++-- src/engine/math/vector3d.cpp | 15 ++--- src/engine/math/vector3d.hpp | 7 ++- 6 files changed, 175 insertions(+), 32 deletions(-) diff --git a/app/engine.cpp b/app/engine.cpp index da0008e..08b4ff4 100644 --- a/app/engine.cpp +++ b/app/engine.cpp @@ -1,4 +1,5 @@ #include "../src/engine/math/matrix3d.hpp" +#include "../src/engine/math/point3d.hpp" #include "../src/engine/math/vector3d.hpp" #include @@ -40,7 +41,7 @@ int main() { cout << (id * 3.0f) * v1 << endl; cout << v1 * (id * 3.0f) << endl; - matrix3d m3(1, 2, 3, 4, 5, 6, 7, 8, 9); + matrix3d m3(1, 2, 3, 4, 5, 5, 7, 8, 9); cout << endl << m3 << endl; cout << endl << matrix3d::trans(m3) << endl; @@ -138,4 +139,36 @@ int main() { cout << "Reject [1,1,0] over [1,0,0]: " << vector3d::reject(vector3d(1, 1, 0), vector3d(1, 0, 0)) << endl; + + // Checking determinant properties + cout << "Det of identity matrix should be 1: " + << is_true(matrix3d::det(id) == 1) << endl; + + cout << "Det(m^T) should be the same as Det(m): " + << is_true(matrix3d::det(m3) == matrix3d::det(matrix3d::trans(m3))) + << endl; + + matrix3d m4 = matrix3d(4, -1, 1, 4, 5, 3, -2, 0, 0); + matrix3d m4_inv = matrix3d::inv(m4); + float32 dm4 = matrix3d::det(m4); + float32 dm4_inv = matrix3d::det(m4_inv); + float inv_dm4 = 1.0f / dm4; + float32 pdet = dm4 * dm4_inv; + + cout << "Determinant of inverse should be the inverse of the determinant: " + << is_true(dm4_inv == inv_dm4) << endl; + + cout << "Determinant of product should be the product of determinants: " + << is_true(matrix3d::det(m4 * m4_inv) == + matrix3d::det(m4) * matrix3d::det(m4_inv)) + << endl; + + cout << id.to_string() << endl; + + point3d p1 = point3d(0, 1, 0); + point3d p2 = point3d(1, 0, 0); + point3d p3 = point3d(0, 0, 1); + point3d p4 = p1 + v1; + cout << v1 << endl; + cout << point3d() - p4 << endl; } diff --git a/premake/engine.lua b/premake/engine.lua index 7c9f5a6..4456299 100644 --- a/premake/engine.lua +++ b/premake/engine.lua @@ -13,11 +13,11 @@ files { buildoptions { "-fpermissive" } filter "configurations:Debug" -defines { "DEBUG" } -symbols "On" + defines { "DEBUG" } + symbols "On" filter "configurations:Release" -defines { "NDEBUG" } -optimize "On" + defines { "NDEBUG" } + optimize "On" filter { "system:linux" } diff --git a/src/engine/math/matrix3d.cpp b/src/engine/math/matrix3d.cpp index 1e01e82..b944061 100644 --- a/src/engine/math/matrix3d.cpp +++ b/src/engine/math/matrix3d.cpp @@ -1,4 +1,5 @@ #include "matrix3d.hpp" +#include namespace engine::math { @@ -10,7 +11,6 @@ void matrix3d::setFloatArray(const float32 m[3][3]) { this->_m[1][0] = m[1][0]; this->_m[1][1] = m[1][1]; this->_m[1][2] = m[1][2]; - this->_m[2][0] = m[2][0]; this->_m[2][1] = m[2][1]; this->_m[2][2] = m[2][2]; @@ -90,14 +90,24 @@ matrix3d::matrix3d(const vector3d r1, const vector3d r2, const vector3d r3) { this->_m[2][2] = r3[2]; }; +std::string matrix3d::to_string() const { + std::string str = "\n"; + str += "[" + std::to_string(this->_m[0][0]) + ", " + + std::to_string(this->_m[0][1]) + ", " + + std::to_string(this->_m[0][2]) + "]\n"; + str += "[" + std::to_string(this->_m[1][0]) + ", " + + std::to_string(this->_m[1][1]) + ", " + + std::to_string(this->_m[1][2]) + "]\n"; + str += "[" + std::to_string(this->_m[2][0]) + ", " + + std::to_string(this->_m[2][1]) + ", " + + std::to_string(this->_m[2][2]) + "]\n"; + return str; +} + // Overload of << operator. Usefull to combine this with ostream stream std::ostream &operator<<(std::ostream &stream, matrix3d const &m) { - stream << "[" << m._m[0][0] << "," << m._m[0][1] << "," << m._m[0][2] << "]" - << std::endl; - stream << "[" << m._m[1][0] << "," << m._m[1][1] << "," << m._m[1][2] << "]" - << std::endl; - stream << "[" << m._m[2][0] << "," << m._m[2][1] << "," << m._m[2][2] << "]" - << std::endl; + std::string m_str = m.to_string(); + stream << m.to_string(); return stream; }; @@ -123,9 +133,94 @@ bool matrix3d::equals(const matrix3d &first, const matrix3d &second) { first(2, 2) == second(2, 2); } +float32 matrix3d::det(const matrix3d &m) { + return m(0, 0) * Det(m(1, 1), m(1, 2), m(2, 1), m(2, 2)) - + m(0, 1) * Det(m(1, 0), m(1, 2), m(2, 0), m(2, 2)) + + m(0, 2) * Det(m(1, 0), m(1, 1), m(2, 0), m(2, 1)); +}; + +matrix3d matrix3d::inv(const matrix3d &m) { + // Rows as vectors + const vector3d &a = m[0]; + const vector3d &b = m[1]; + const vector3d &c = m[2]; + + // Cross product of rows + vector3d r0 = vector3d::cross(b, c); + vector3d r1 = vector3d::cross(c, a); + vector3d r2 = vector3d::cross(a, b); + + // determinant inverse + float32 idet = 1.0f / vector3d::dot(r2, c); + + return matrix3d(Idet(r0, idet), Idet(r1, idet), Idet(r2, idet)); +}; + +matrix3d matrix3d::rotX(float32 angle) { + float32 _cos = cos(angle); + float32 _sin = sin(angle); + return matrix3d(1, 0, 0, 0, _cos, -_sin, 0, _sin, _cos); +}; + +matrix3d matrix3d::rotY(float32 angle) { + float32 _cos = cos(angle); + float32 _sin = sin(angle); + + return matrix3d(_cos, 0, _sin, 0, 1, 0, -_sin, 0, _cos); +}; + +matrix3d matrix3d::rotZ(float32 angle) { + float32 _cos = cos(angle); + float32 _sin = sin(angle); + return matrix3d(_cos, -_sin, 0, _sin, _cos, 0, 0, 0, 1); +}; + +matrix3d matrix3d::rot(float32 angle, const vector3d &axis) { + float32 _cos = cos(angle); + float32 _sin = sin(angle); + float32 d = 1 - _cos; + + float32 x = axis[0] * d; + float32 y = axis[1] * d; + float32 z = axis[2] * d; + float32 ax_y = x * axis[1]; + float32 ax_z = x * axis[2]; + float32 ay_z = y * axis[2]; + + return matrix3d( + _cos + x * axis[0], ax_y - _sin * axis[2], ax_z + _sin * axis[1], + ax_y + _sin * axis[2], _cos + y * axis[1], ay_z - _sin * axis[0], + ax_z - _sin * axis[1], ay_z + _sin * axis[0], _cos + z * axis[2]); +}; + +matrix3d matrix3d::scale(float32 scalex, float32 scaley, float32 scalez) { + return matrix3d(scalex, 0, 0, 0, scaley, 0, 0, 0, scalez); +}; + +matrix3d matrix3d::scale(float32 scale, const vector3d &vector) { + scale -= 1; + float32 x = vector[0] * scale; + float32 y = vector[1] * scale; + float32 z = vector[2] * scale; + float vx_vy = x * vector[1]; + float vx_vz = x * vector[1]; + float vy_vz = y * vector[2]; + return matrix3d(x * vector[0] + 1, vx_vy, vx_vz, vx_vy, y * vector[1] + 1, + vx_vz, vx_vz, vy_vz, z * vector[2] + 1); +}; + +matrix3d matrix3d::skew(float32 angle, const vector3d v1, const vector3d &v2) { + float32 t = tan(angle); + float32 x = v1[0]; + float32 y = v1[1]; + float32 z = v1[2]; + + return matrix3d(); +}; + // Overload of + operator. This will add 2 matrix3d instances matrix3d operator+(const matrix3d &left, const matrix3d &right) { - MATRIX(add); + Matrix(add); add[0][0] = left[0][0] + right[0][0]; add[0][1] = left[0][1] + right[0][1]; add[0][2] = left[0][2] + right[0][2]; @@ -142,7 +237,7 @@ matrix3d operator+(const matrix3d &left, const matrix3d &right) { }; matrix3d operator-(const matrix3d &left, const matrix3d &right) { - MATRIX(m_temp); + Matrix(m_temp); m_temp[0][0] = left[0][0] - right[0][0]; m_temp[0][1] = left[0][1] - right[0][1]; m_temp[0][2] = left[0][2] - right[0][2]; diff --git a/src/engine/math/matrix3d.hpp b/src/engine/math/matrix3d.hpp index cdedd6d..3624c1e 100644 --- a/src/engine/math/matrix3d.hpp +++ b/src/engine/math/matrix3d.hpp @@ -1,18 +1,20 @@ #pragma once #include "../../platform/base.hpp" +#include "math.h" #include "vector3d.hpp" -#define MATRIX(n) float32 n[3][3] - +// Defines a matrix in termos of float32 +#define Matrix(n) float32 n[3][3] +// Computes determinant sub block +#define Det(a, b, c, d) (a * d - b * c) +#define Idet(row, idet) row[0] * idet, row[1] * idet, row[2] * idet namespace engine::math { -class matrix3d { -private: - MATRIX(_m); +struct matrix3d { + Matrix(_m); void setFloatArray(const float32[3][3]); void setAll(float32 v); -public: // Default empty constructor matrix3d(); ~matrix3d(); @@ -27,6 +29,7 @@ public: const vector3d operator[](int i) const; float32 operator()(int r, int c); float32 operator()(int r, int c) const; + std::string to_string() const; friend std::ostream &operator<<(std::ostream &stream, engine::math::matrix3d const &m); @@ -36,8 +39,22 @@ public: static matrix3d trans(const matrix3d &matrix); // Compute the matrix determinant value static float32 det(const matrix3d &matrix); + // Compute matrix inverse + static matrix3d inv(const matrix3d &m); // Check if two matrices are equal, by checking each entry equality static bool equals(const matrix3d &first, const matrix3d &second); + + // Rotation matrices + static matrix3d rotX(float32 angle); + static matrix3d rotY(float32 angle); + static matrix3d rotZ(float32 angle); + static matrix3d rot(float32 angle, const vector3d &axis); + // Scaling matrix + static matrix3d scale(float32 scale_x, float32 scale_y, float32 scale_z); + // Scaling matrix in relation to a given vector + static matrix3d scale(float32 scale, const vector3d &vector); + // Skew matrix based on an angle and two vector3d + static matrix3d skew(float32 angle, const vector3d v1, const vector3d &v2); }; // Non instance operator overloading diff --git a/src/engine/math/vector3d.cpp b/src/engine/math/vector3d.cpp index baa1617..aae0b1b 100644 --- a/src/engine/math/vector3d.cpp +++ b/src/engine/math/vector3d.cpp @@ -21,27 +21,27 @@ vector3d &vector3d::operator-=(const vector3d &other) { }; vector3d operator+(const vector3d &left, const vector3d &right) { - return vector3d(left[0] + right[0], left[1] + right[1], left[2] + right[2]); + return vector3d(left.x + right.x, left.y + right.y, left.z + right.z); } vector3d operator-(const vector3d &left, const vector3d &right) { - return vector3d(left[0] - right[0], left[1] - right[1], left[2] - right[2]); + return vector3d(left.x - right.x, left.y - right.y, left.z - right.z); } vector3d operator-(const vector3d &vector, float32 scalar) { - return vector3d(vector[0] - scalar, vector[1] - scalar, vector[2] - scalar); + return vector3d(vector.x - scalar, vector.y - scalar, vector.z - scalar); } vector3d operator*(float32 scalar, const vector3d &vector) { - return vector3d(vector[0] * scalar, vector[1] * scalar, vector[2] * scalar); + return vector3d(vector.x * scalar, vector.y * scalar, vector.z * scalar); }; vector3d operator*(const vector3d &vector, float32 scalar) { - return vector3d(vector[0] * scalar, vector[1] * scalar, vector[2] * scalar); + return vector3d(vector.x * scalar, vector.y * scalar, vector.z * scalar); } vector3d operator*(const vector3d &v1, const vector3d &v2) { - return vector3d(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]); + return vector3d(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } vector3d vector3d::operator-() { @@ -70,9 +70,6 @@ float32 vector3d::dot(const vector3d &one, const vector3d &other) { }; // Cross product of two vectors given by -// v1_y*v2_z-v1_z*v2y, -// v1_z*v2_x-v1_x*v2_z -// v1_x*v2_y-v1_y*v2_x vector3d vector3d::cross(const vector3d &v1, const vector3d &v2) { return vector3d(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); diff --git a/src/engine/math/vector3d.hpp b/src/engine/math/vector3d.hpp index a220b12..2488b10 100644 --- a/src/engine/math/vector3d.hpp +++ b/src/engine/math/vector3d.hpp @@ -2,6 +2,7 @@ #include "../../platform/base.hpp" #include +#include using namespace std; @@ -9,11 +10,9 @@ namespace engine::math { /** * Class that abstracts away a vector in 3 dimensions */ -class vector3d { -private: +struct vector3d { float32 x, y, z; -public: // Default constructor; vector3d(); /*** @@ -40,6 +39,8 @@ public: vector3d operator/(const float32 scalar); vector3d operator-(); + + void dummy(); // Compute the magnitude of the vector static float32 norm(const vector3d &v); // Compute the normalized vector