From 3f79338304a2438a255ff7c427d2ff618c4cfef6 Mon Sep 17 00:00:00 2001 From: Balhau Date: Mon, 19 Jun 2023 17:54:09 +0100 Subject: [PATCH] Missing files --- app/engine.cpp | 122 +++++++++++++++++++++++++-- src/engine/math/matrix3d.cpp | 157 ++++++++++++++++++++++++++++++++--- src/engine/math/matrix3d.hpp | 21 ++++- src/engine/math/vector3d.cpp | 55 ++++++++++-- src/engine/math/vector3d.hpp | 26 +++++- 5 files changed, 351 insertions(+), 30 deletions(-) diff --git a/app/engine.cpp b/app/engine.cpp index 1b932cf..da0008e 100644 --- a/app/engine.cpp +++ b/app/engine.cpp @@ -5,6 +5,8 @@ using namespace engine::math; using namespace std; +#define is_true(n) ((n == true) ? "yes" : "no") + int main() { vector3d v1 = vector3d(1, 2, 3); vector3d v2 = vector3d(3, 2, 1); @@ -14,16 +16,126 @@ int main() { cout << v2 << endl; cout << (v1 - v2) + v3 << endl; cout << -v1 << endl; - cout << vector3d::Magnitude(v1) << endl; - cout << vector3d::Normalize(v1) << endl; - cout << vector3d::Magnitude(v3) << endl; - cout << vector3d::Normalize(v3) << endl; + cout << vector3d::norm(v1) << endl; + cout << vector3d::normalize(v1) << endl; + cout << vector3d::norm(v3) << endl; + cout << vector3d::normalize(v3) << endl; engine::math::matrix3d m = engine::math::matrix3d(); - engine::math::matrix3d id = matrix3d::Identity(); + engine::math::matrix3d id = matrix3d::id(); cout << m << endl; cout << m[0][0] << endl; cout << id << endl; cout << id[0][0] << id[1][1] << id[2][2] << endl; cout << id(0, 0) << id(0, 1) << id(0, 2) << endl; + + matrix3d m1 = matrix3d(v1, v2, v3); + matrix3d m2 = matrix3d(v3, v2, v1); + + cout << matrix3d::id() + matrix3d::id() << endl; + cout << m1 * id << endl; + cout << id * m1 << endl; + cout << id * id << endl; + cout << m1 * m2 << endl; + cout << (id * 3.0f) * v1 << endl; + cout << v1 * (id * 3.0f) << endl; + + matrix3d m3(1, 2, 3, 4, 5, 6, 7, 8, 9); + + cout << endl << m3 << endl; + cout << endl << matrix3d::trans(m3) << endl; + + cout << "Are " << m1 << " and " << m2 << " equals? " + << is_true(matrix3d::equals(m1, m2)) << endl; + + cout << "Are " << m2 << " and " << m2 << " equals? " + << is_true(matrix3d::equals(m2, m2)) << endl; + + // Validate matrix properties + cout << "Associative law for matrix add holds: " + << is_true(matrix3d::equals((m1 + m2) + id, m1 + (m2 + id))) << endl; + + cout << "Comutative law for add holds: " + << is_true(matrix3d::equals(m1 + m2, m2 + m1)) << endl; + cout << "Associative for scalar multiplication: " + << is_true(matrix3d::equals((2.0f * 2.0f) * m1, 2.0f * (2.0f * m1))) + << endl; + + cout << "Comutative law for scalar multiplication: " + << is_true(matrix3d::equals(2 * m1, m1 * 2)) << endl; + cout << "Distributive law for scalar multiplication: " + << is_true(matrix3d::equals((2 + 2) * m1, 2 * m1 + 2 * m1)) << endl; + + cout << "Associative for matrix multiplication: " + << is_true(matrix3d::equals((m1 * m2) * m3, m1 * (m2 * m3))) << endl; + + cout << "Distributive laws for matrix: " + << is_true(matrix3d::equals(m1 * (m2 + m3), m1 * m2 + m1 * m3)) + << " and " + << is_true(matrix3d::equals((m1 + m2) * m3, m1 * m3 + m2 * m3)) << endl; + + cout << "Scalar factorization for matrices: " + << is_true(matrix3d::equals((3 * m1) * m2, m1 * (3 * m2))) << " and " + << is_true(matrix3d::equals((3 * m1) * m2, 3 * (m1 * m2))) << endl; + + cout << "Product rule for matrix trans: " + << is_true(matrix3d::equals(matrix3d::trans(m1 * m2), + matrix3d::trans(m2) * matrix3d::trans(m1))) + << endl; + + cout << "Dot product comutative law: " + << is_true(vector3d::dot(v1, v2) == vector3d::dot(v2, v1)) << endl; + cout << "Dot product distributive law: " + << is_true(vector3d::dot(v1, (v2 + v3)) == + (vector3d::dot(v1, v2) + vector3d::dot(v1, v3))) + << endl; + + cout << "Dot scalar factorization: " + << is_true(vector3d::dot(2.0 * v1, v2) == vector3d::dot(v1, 2 * v2)) + << " and " + << is_true(vector3d::dot(v1, 2 * v2) == 2 * vector3d::dot(v1, v2)) + << endl; + + cout << "Cross anticomutativity: " + << is_true(vector3d::equals(vector3d::cross(v1, v2), + -vector3d::cross(v2, v1))) + << endl; + + cout << "Cross distributive law: " + << is_true(vector3d::equals(vector3d::cross(v1, v2 + v3), + vector3d::cross(v1, v2) + + vector3d::cross(v1, v3))) + << endl; + + cout << "Scalar factorization in cross: " + << is_true(vector3d::equals(vector3d::cross(2 * v1, v2), + vector3d::cross(v1, 2 * v2))) + << " and " + << is_true(vector3d::equals(vector3d::cross(v1, 2 * v2), + 2 * vector3d::cross(v1, v2))) + << endl; + + cout << "Vector triple product: " + << is_true(vector3d::equals(vector3d::cross(v1, vector3d::cross(v2, v3)), + v2 * vector3d::dot(v1, v3) - + v3 * vector3d::dot(v1, v2))) + << endl; + + // Check lagrande id: + // This means: + // dot(cross(v1,v2),cross(v1,v2)) = dot(v1,v1)*dot(v2,v2) - + // dot(v1,v2)*dot(v1,v2) + cout << "Lagrange id: " + << is_true( + vector3d::dot(vector3d::cross(v1, v2), vector3d::cross(v1, v2)) == + (vector3d::dot(v1, v1) * vector3d::dot(v2, v2) - + (vector3d::dot(v1, v2) * vector3d::dot(v1, v2)))) + << endl; + + // Projections + cout << "Project [1,1,0] in [1,0,0]: " + << vector3d::project(vector3d(1, 1, 0), vector3d(1, 0, 0)) << endl; + + cout << "Reject [1,1,0] over [1,0,0]: " + << vector3d::reject(vector3d(1, 1, 0), vector3d(1, 0, 0)) << endl; } diff --git a/src/engine/math/matrix3d.cpp b/src/engine/math/matrix3d.cpp index 36a56c4..1e01e82 100644 --- a/src/engine/math/matrix3d.cpp +++ b/src/engine/math/matrix3d.cpp @@ -35,14 +35,47 @@ vector3d matrix3d::operator[](int i) { return vector3d(*row, *(row + 1), *(row + 2)); }; +const vector3d matrix3d::operator[](int i) const { + return vector3d(this->_m[i][0], this->_m[i][1], this->_m[i][2]); +}; + float32 matrix3d::operator()(int row, int column) { return this->_m[row][column]; }; +float32 matrix3d::operator()(int row, int column) const { + return this->_m[row][column]; +}; + +// Default constructor all entries are 0 matrix3d::matrix3d() { this->setAll(0); }; + +// Default destructor just does nothing matrix3d::~matrix3d(){}; + +// Constructor based on other matrix3d instance matrix3d::matrix3d(const matrix3d &m){}; -matrix3d::matrix3d(const float32 m[3][3]) { this->setFloatArray(m); }; + +matrix3d::matrix3d(float32 a00, float32 a01, float32 a02, float32 a10, + float32 a11, float32 a12, float32 a20, float32 a21, + float32 a22) { + this->_m[0][0] = a00; + this->_m[0][1] = a01; + this->_m[0][2] = a02; + + this->_m[1][0] = a10; + this->_m[1][1] = a11; + this->_m[1][2] = a12; + + this->_m[2][0] = a20; + this->_m[2][1] = a21; + this->_m[2][2] = a22; +}; +// Constructor that sets matrix entries based in a two dimentional float32 3x3 +// array +matrix3d::matrix3d(float32 m[3][3]) { this->setFloatArray(m); }; + +// matrix3 Constructor with 3 vector3d each representing a row matrix3d::matrix3d(const vector3d r1, const vector3d r2, const vector3d r3) { this->_m[0][0] = r1[0]; this->_m[0][1] = r1[1]; @@ -57,24 +90,124 @@ matrix3d::matrix3d(const vector3d r1, const vector3d r2, const vector3d r3) { this->_m[2][2] = r3[2]; }; +// Overload of << operator. Usefull to combine this with ostream stream std::ostream &operator<<(std::ostream &stream, matrix3d const &m) { - stream << "matrix3d(" << std::endl; - 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; - stream << ")"; + 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; return stream; }; -matrix3d matrix3d::Identity() { +// Just builds an id matrix +matrix3d matrix3d::id() { float32 id[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; return matrix3d(id); }; -matrix3d operator+(const matrix3d &left, const matrix3d &right) { - MATRIX(m_temp); - m_temp[0][0]; - return NULL; +matrix3d matrix3d::trans(const matrix3d &matrix) { + return matrix3d( + matrix(0, 0), matrix(1, 0), matrix(2, 0), // First column into first row + matrix(0, 1), matrix(1, 1), matrix(2, 1), // Second column into second row + matrix(0, 2), matrix(1, 2), matrix(2, 2) // Third column into third row + ); }; -} // namespace engine::math +bool matrix3d::equals(const matrix3d &first, const matrix3d &second) { + return first(0, 0) == second(0, 0) && first(0, 1) == second(0, 1) && + first(0, 2) == second(0, 2) && first(1, 0) == second(1, 0) && + first(1, 1) == second(1, 1) && first(1, 2) == second(1, 2) && + first(2, 0) == second(2, 0) && first(2, 1) == second(2, 1) && + first(2, 2) == second(2, 2); +} + +// Overload of + operator. This will add 2 matrix3d instances +matrix3d operator+(const matrix3d &left, const matrix3d &right) { + 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]; + + add[1][0] = left[1][0] + right[1][0]; + add[1][1] = left[1][1] + right[1][1]; + add[1][2] = left[1][2] + right[1][2]; + + add[2][0] = left[2][0] + right[2][0]; + add[2][1] = left[2][1] + right[2][1]; + add[2][2] = left[2][2] + right[2][2]; + + return matrix3d(add); +}; + +matrix3d operator-(const matrix3d &left, const matrix3d &right) { + 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]; + + m_temp[1][0] = left[1][0] - right[1][0]; + m_temp[1][1] = left[1][1] - right[1][1]; + m_temp[1][2] = left[1][2] - right[1][2]; + + m_temp[2][0] = left[2][0] - right[2][0]; + m_temp[2][1] = left[2][1] - right[2][1]; + m_temp[2][2] = left[2][2] - right[2][2]; + + return matrix3d(m_temp); +}; + +// Multiplication of two 3d matrices +matrix3d operator*(const matrix3d &a, const matrix3d &b) { + float32 m00 = a(0, 0) * b(0, 0) + a(0, 1) * b(1, 0) + + a(0, 2) * b(2, 0); // a first row times b first column + float32 m01 = a(0, 0) * b(0, 1) + a(0, 1) * b(1, 1) + + a(0, 2) * b(2, 1); // a first row times b second column + float32 m02 = a(0, 0) * b(0, 2) + a(0, 1) * b(1, 2) + + a(0, 2) * b(2, 2); // a first row times b third column + float32 m10 = a(1, 0) * b(0, 0) + a(1, 1) * b(1, 0) + + a(1, 2) * b(2, 0); // a second row times b first column + float32 m11 = a(1, 0) * b(0, 1) + a(1, 1) * b(1, 1) + + a(1, 2) * b(2, 1); // a second row times b second column + float32 m12 = a(1, 0) * b(0, 2) + a(1, 1) * b(1, 2) + + a(1, 2) * b(2, 2); // a second row times b third column + float32 m20 = a(2, 0) * b(0, 0) + a(2, 1) * b(1, 0) + + a(2, 2) * b(2, 0); // a third row times b first column + float32 m21 = a(2, 0) * b(0, 1) + a(2, 1) * b(1, 1) + + a(2, 2) * b(2, 1); // a third column times b second column + float32 m22 = a(2, 0) * b(0, 2) + a(2, 1) * b(1, 2) + + a(2, 2) * b(2, 2); // a third column times b third column + return matrix3d(m00, m01, m02, m10, m11, m12, m20, m21, m22); +}; + +matrix3d operator*(const matrix3d &matrix, const float32 scalar) { + return matrix3d( + matrix(0, 0) * scalar, matrix(0, 1) * scalar, matrix(0, 2) * scalar, + matrix(1, 0) * scalar, matrix(1, 1) * scalar, matrix(1, 2) * scalar, + matrix(2, 0) * scalar, matrix(2, 1) * scalar, matrix(2, 2) * scalar); +}; + +matrix3d operator*(const float scalar, const matrix3d &matrix) { + return matrix * scalar; +} + +vector3d operator*(const matrix3d &matrix, const vector3d &vector) { + + return vector3d(matrix(0, 0) * vector[0] + matrix(0, 1) * vector[1] + + matrix(0, 2) * vector[2], // First row times vector + matrix(1, 0) * vector[0] + matrix(1, 1) * vector[1] + + matrix(1, 2) * vector[2], // Second row times vector + matrix(2, 0) * vector[0] + matrix(2, 1) * vector[1] + + matrix(2, 2) * vector[2]); // Third row times vector +}; + +vector3d operator*(const vector3d &vector, const matrix3d &matrix) { + return vector3d(vector[0] * matrix(0, 0) + vector[1] * matrix(1, 0) + + vector[2] * matrix(2, 0), // vector times first column + vector[0] * matrix(0, 1) + vector[1] * matrix(1, 1) + + vector[2] * matrix(2, 1), // vector times second column + vector[0] * matrix(0, 2) + vector[1] * matrix(1, 2) + + vector[2] * matrix(2, 2)); // vector times third column +} +}; // namespace engine::math diff --git a/src/engine/math/matrix3d.hpp b/src/engine/math/matrix3d.hpp index 50fc803..cdedd6d 100644 --- a/src/engine/math/matrix3d.hpp +++ b/src/engine/math/matrix3d.hpp @@ -16,20 +16,37 @@ public: // Default empty constructor matrix3d(); ~matrix3d(); - static matrix3d Identity(); - matrix3d(const float32[3][3]); + matrix3d(float32[3][3]); + matrix3d(float32 a00, float32 a01, float32 a02, float32 a10, float32 a11, + float32 a12, float32 a20, float32 a21, float32 a22); matrix3d(const vector3d r1, const vector3d r2, const vector3d r3); // Constructor with matrix3d object matrix3d(const matrix3d &m); vector3d operator[](int i); + const vector3d operator[](int i) const; float32 operator()(int r, int c); + float32 operator()(int r, int c) const; friend std::ostream &operator<<(std::ostream &stream, engine::math::matrix3d const &m); + + // Give us the identity matrix + static matrix3d id(); + // Transpose the matrix + static matrix3d trans(const matrix3d &matrix); + // Compute the matrix determinant value + static float32 det(const matrix3d &matrix); + // Check if two matrices are equal, by checking each entry equality + static bool equals(const matrix3d &first, const matrix3d &second); }; // Non instance operator overloading matrix3d operator+(const matrix3d &left, const matrix3d &right); matrix3d operator-(const matrix3d &left, const matrix3d &right); +matrix3d operator*(const matrix3d &left, const matrix3d &right); +matrix3d operator*(const matrix3d &matrix, const float32 scalar); +vector3d operator*(const matrix3d &matrix, const vector3d &vector); +vector3d operator*(const vector3d &vector, const matrix3d &matrix); +matrix3d operator*(const float32 scalar, const matrix3d &matrix); }; // namespace engine::math diff --git a/src/engine/math/vector3d.cpp b/src/engine/math/vector3d.cpp index decf27b..baa1617 100644 --- a/src/engine/math/vector3d.cpp +++ b/src/engine/math/vector3d.cpp @@ -20,12 +20,28 @@ vector3d &vector3d::operator-=(const vector3d &other) { return (*this); }; -vector3d vector3d::operator+(const vector3d &other) { - return vector3d(this->x + other.x, this->y + other.y, this->z + other.z); +vector3d operator+(const vector3d &left, const vector3d &right) { + return vector3d(left[0] + right[0], left[1] + right[1], left[2] + right[2]); } -vector3d vector3d::operator-(const vector3d &other) { - return vector3d(this->x - other.x, this->y - other.y, this->z - other.z); +vector3d operator-(const vector3d &left, const vector3d &right) { + return vector3d(left[0] - right[0], left[1] - right[1], left[2] - right[2]); +} + +vector3d operator-(const vector3d &vector, float32 scalar) { + return vector3d(vector[0] - scalar, vector[1] - scalar, vector[2] - scalar); +} + +vector3d operator*(float32 scalar, const vector3d &vector) { + return vector3d(vector[0] * scalar, vector[1] * scalar, vector[2] * scalar); +}; + +vector3d operator*(const vector3d &vector, float32 scalar) { + return vector3d(vector[0] * scalar, vector[1] * scalar, vector[2] * scalar); +} + +vector3d operator*(const vector3d &v1, const vector3d &v2) { + return vector3d(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]); } vector3d vector3d::operator-() { @@ -43,11 +59,36 @@ vector3d::vector3d(float32 _x, float32 _y, float32 _z) { this->z = _z; }; -float32 vector3d::Magnitude(const vector3d &v) { +float32 vector3d::norm(const vector3d &v) { return sqrt((v.x * v.x + v.y * v.y + v.z * v.z)); }; -vector3d vector3d::Normalize(vector3d &v) { return v / vector3d::Magnitude(v); } +vector3d vector3d::normalize(vector3d &v) { return v / vector3d::norm(v); } + +float32 vector3d::dot(const vector3d &one, const vector3d &other) { + return one.x * other.x + one.y * other.y + one.z * other.z; +}; + +// 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); +}; + +vector3d vector3d::project(const vector3d &v1, const vector3d &v2) { + return v2 * (vector3d::dot(v1, v2) / vector3d::dot(v2, v2)); +} + +vector3d vector3d::reject(const vector3d &v1, const vector3d &v2) { + return v1 - (v2 * (vector3d::dot(v1, v2) / vector3d::dot(v2, v2))); +} + +bool vector3d::equals(const vector3d &v1, const vector3d &v2) { + return v1.x == v2.x && v1.y == v2.y && v1.y == v2.y; +}; float32 &vector3d::operator[](int i) { return (&this->x)[i]; }; @@ -57,6 +98,6 @@ const float32 &engine::math::vector3d::operator[](int i) const { std::ostream &operator<<(std::ostream &stream, engine::math::vector3d const &v) { - return stream << "vector3d(" << v[0] << "," << v[1] << "," << v[2] << ")"; + return stream << "[" << v.x << "," << v.y << "," << v.z << "]"; }; } // namespace engine::math diff --git a/src/engine/math/vector3d.hpp b/src/engine/math/vector3d.hpp index a8a271a..a220b12 100644 --- a/src/engine/math/vector3d.hpp +++ b/src/engine/math/vector3d.hpp @@ -37,13 +37,31 @@ public: vector3d &operator+=(const vector3d &other); vector3d &operator-=(const vector3d &other); - vector3d operator+(const vector3d &other); - vector3d operator-(const vector3d &other); vector3d operator/(const float32 scalar); vector3d operator-(); - static float32 Magnitude(const vector3d &v); - static vector3d Normalize(vector3d &v); + // Compute the magnitude of the vector + static float32 norm(const vector3d &v); + // Compute the normalized vector + static vector3d normalize(vector3d &v); + // Compute the dot product + static float32 dot(const vector3d &one, const vector3d &other); + // Compute the vector3d cross product of two vectors + static vector3d cross(const vector3d &v1, const vector3d &v2); + // Check if two vectors are equal + static bool equals(const vector3d &v1, const vector3d &v2); + // Compute projection of a vector + static vector3d project(const vector3d &v1, const vector3d &v2); + // Compute rejection of a vector + static vector3d reject(const vector3d &v1, const vector3d &v2); ~vector3d(); }; + +// Non instance operator overloading +vector3d operator+(const vector3d &left, const vector3d &right); +vector3d operator-(const vector3d &left, const vector3d &right); +vector3d operator-(const vector3d &vector, float32 scalar); +vector3d operator*(float32 scalar, const vector3d &vector); +vector3d operator*(const vector3d &vector, float32 scalar); +vector3d operator*(const vector3d &v1, const vector3d &v2); }; // namespace engine::math