From 40e69d5c4fec701acf285039e93f26faa4728549 Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 31 Jan 2024 18:34:15 -0500 Subject: [PATCH] Implement Mat4x4 Translate, Transform, FromTranslation --- include/J3ML/Geometry/AABB.h | 75 ++++++++++++++++++++++---- include/J3ML/Geometry/Capsule.h | 2 +- include/J3ML/Geometry/LineSegment.h | 3 ++ include/J3ML/Geometry/Sphere.h | 6 +++ include/J3ML/LinearAlgebra/Matrix3x3.h | 5 ++ include/J3ML/LinearAlgebra/Matrix4x4.h | 32 ++++++----- include/J3ML/LinearAlgebra/Vector3.h | 57 +++++++++++++------- src/J3ML/Geometry/Capsule.cpp | 1 + src/J3ML/Geometry/LineSegment.cpp | 6 +++ src/J3ML/LinearAlgebra/Matrix3x3.cpp | 4 ++ src/J3ML/LinearAlgebra/Matrix4x4.cpp | 60 +++++++++++++++++++-- 11 files changed, 202 insertions(+), 49 deletions(-) diff --git a/include/J3ML/Geometry/AABB.h b/include/J3ML/Geometry/AABB.h index 2f8d699..ebb7969 100644 --- a/include/J3ML/Geometry/AABB.h +++ b/include/J3ML/Geometry/AABB.h @@ -37,21 +37,75 @@ namespace Geometry class AABB { - static AABB FromCenterAndSize(const Vector3 FromSize); - float MinX(); - // Returns the smallest sphere that contains this AABB. - // This function computes the minimal volume sphere that contains all the points inside this AABB - Sphere MinimalEnclosingSphere() const; - // Returns the largest sphere that can fit inside this AABB + public: + Vector3 minPoint; + Vector3 maxPoint; + + static int NumFaces() { return 6; } + static int NumEdges() { return 12;} + static int NumVertices() { return 8;} + + static AABB FromCenterAndSize(const Vector3& center, const Vector3& size) + { + Vector3 halfSize = size * 0.5f; + return {center - halfSize, center + halfSize}; + } + float MinX() const { return minPoint.x; } + float MinY() const { return minPoint.y; } + float MinZ() const { return minPoint.z; } + + float MaxX() const { return maxPoint.x; } + float MaxY() const { return maxPoint.y; } + float MaxZ() const { return maxPoint.z; } + + + /// Returns the smallest sphere that contains this AABB. + /// This function computes the minimal volume sphere that contains all the points inside this AABB + Sphere MinimalEnclosingSphere() const + { + return Sphere(Centroid(), Size().Length()*0.5f); + } + + Vector3 HalfSize() const { + return this->Size()/2.f; + } + +// Returns the largest sphere that can fit inside this AABB // This function computes the largest sphere that can fit inside this AABB. - Sphere MaximalContainedSphere() const; - Vector3 GetCentroid() const; + Sphere MaximalContainedSphere() const + { + Vector3 halfSize = HalfSize(); + return Sphere(Centroid(), std::min(halfSize.x, std::min(halfSize.y, halfSize.z))); + } + bool IsFinite() const + { + return minPoint.IsFinite() && maxPoint.IsFinite(); + } + Vector3 Centroid() const + { + return (minPoint+maxPoint) * 0.5f; + } + Vector3 Size() const + { + return this->maxPoint - this->minPoint; + } // Quickly returns an arbitrary point inside this AABB Vector3 AnyPointFast() const; - Vector3 PointInside(float x, float y, float z) const; + Vector3 PointInside(float x, float y, float z) const + { + Vector3 d = maxPoint - minPoint; + return minPoint + d.Mul({x, y, z}); + } // Returns an edge of this AABB - LineSegment Edge(int edgeIndex) const; + LineSegment Edge(int edgeIndex) const + { + switch(edgeIndex) + { + default: + case 0: return LineSegment(minPoint, {minPoint.x, minPoint.y, maxPoint.z}); + } + } Vector3 CornerPoint(int cornerIndex); Vector3 ExtremePoint(const Vector3& direction) const; Vector3 ExtremePoint(const Vector3& direction, float projectionDistance); @@ -61,7 +115,6 @@ namespace Geometry Vector3 FaceNormal(int faceIndex) const; Plane FacePlane(int faceIndex); static AABB MinimalEnclosingAABB(const Vector3* pointArray, int numPoints); - Vector3 GetSize(); Vector3 GetVolume(); float GetVolumeCubed(); float GetSurfaceArea(); diff --git a/include/J3ML/Geometry/Capsule.h b/include/J3ML/Geometry/Capsule.h index ba1b59c..609c3c0 100644 --- a/include/J3ML/Geometry/Capsule.h +++ b/include/J3ML/Geometry/Capsule.h @@ -13,7 +13,7 @@ namespace Geometry // Specifies the radius of this capsule float r; - Capsule() {} + Capsule(); Capsule(const LineSegment& endPoints, float radius); Capsule(const Vector3& bottomPt, const Vector3& topPt, float radius); bool IsDegenerate()const; diff --git a/include/J3ML/Geometry/LineSegment.h b/include/J3ML/Geometry/LineSegment.h index 64c2b75..4e4d79a 100644 --- a/include/J3ML/Geometry/LineSegment.h +++ b/include/J3ML/Geometry/LineSegment.h @@ -7,6 +7,9 @@ namespace Geometry using LinearAlgebra::Vector3; class LineSegment { + public: + LineSegment(); + LineSegment(const Vector3& a, const Vector3& b); Vector3 A; Vector3 B; }; diff --git a/include/J3ML/Geometry/Sphere.h b/include/J3ML/Geometry/Sphere.h index a8e180a..9203b5f 100644 --- a/include/J3ML/Geometry/Sphere.h +++ b/include/J3ML/Geometry/Sphere.h @@ -1,9 +1,15 @@ #pragma once +#include "J3ML/Geometry.h" + namespace Geometry { class Sphere { + public: + Sphere(const Vector3& pos, float radius) + { + } }; } \ No newline at end of file diff --git a/include/J3ML/LinearAlgebra/Matrix3x3.h b/include/J3ML/LinearAlgebra/Matrix3x3.h index 590b33f..539d2c5 100644 --- a/include/J3ML/LinearAlgebra/Matrix3x3.h +++ b/include/J3ML/LinearAlgebra/Matrix3x3.h @@ -44,6 +44,7 @@ namespace LinearAlgebra { Vector3 GetRow(int index) const; Vector3 GetColumn(int index) const; + float &At(int row, int col); float At(int x, int y) const; void SetRotatePart(const Vector3& a, float angle); @@ -132,6 +133,10 @@ namespace LinearAlgebra { Vector2 Transform(const Vector2& rhs) const; Vector3 Transform(const Vector3& rhs) const; + Vector3 operator[](int row) const + { + return Vector3{elems[row][0], elems[row][1], elems[row][2]}; + } Vector3 operator * (const Vector3& rhs) const; Matrix3x3 operator * (const Matrix3x3& rhs) const; diff --git a/include/J3ML/LinearAlgebra/Matrix4x4.h b/include/J3ML/LinearAlgebra/Matrix4x4.h index 35fcea1..8ec0b04 100644 --- a/include/J3ML/LinearAlgebra/Matrix4x4.h +++ b/include/J3ML/LinearAlgebra/Matrix4x4.h @@ -76,7 +76,8 @@ namespace LinearAlgebra { void SetTranslatePart(float translateX, float translateY, float translateZ); void SetTranslatePart(const Vector3& offset); void SetRotatePart(const Quaternion& q); - void SetRotatePart(const Matrix3x3& r); + void Set3x3Part(const Matrix3x3& r); + void SetRow(int row, const Vector3& rowVector, float m_r3); @@ -86,6 +87,7 @@ namespace LinearAlgebra { Vector4 GetRow(int index) const; Vector4 GetColumn(int index) const; + float &At(int row, int col); float At(int x, int y) const; /// Tests if this matrix does not contain any NaNs or infs. @@ -109,11 +111,21 @@ namespace LinearAlgebra { Matrix4x4 Transpose() const; + Vector2 Transform(float tx, float ty) const; Vector2 Transform(const Vector2& rhs) const; + + + Vector3 Transform(float tx, float ty, float tz) const; Vector3 Transform(const Vector3& rhs) const; + + Vector4 Transform(float tx, float ty, float tz, float tw) const; Vector4 Transform(const Vector4& rhs) const; + Matrix4x4 Translate(const Vector3& rhs) const; + static Matrix4x4 FromTranslation(const Vector3& rhs); + + static Matrix4x4 D3DOrthoProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize); static Matrix4x4 D3DOrthoProjRH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize); static Matrix4x4 D3DPerspProjLH(float nearPlane, float farPlane, float hViewportSize, float vViewportSize); @@ -139,6 +151,8 @@ namespace LinearAlgebra { Matrix4x4 operator *(float scalar) const; Matrix4x4 operator /(float scalar) const; + + Vector2 operator * (const Vector2& rhs) const { return this->Transform(rhs);} Vector3 operator * (const Vector3& rhs) const { return this->Transform(rhs);} Vector4 operator * (const Vector4& rhs) const { return this->Transform(rhs);} @@ -149,23 +163,13 @@ namespace LinearAlgebra { Matrix4x4 operator * (const Matrix4x4& rhs) const; - Matrix4x4 &operator = (const Matrix3x3& rhs) - { - SetRotatePart(rhs); - SetTranslatePart(0,0,0); - SetRow(3, 0, 0, 0, 1); - return *this; - } - Matrix4x4 &operator = (const Quaternion& rhs) - { - *this = rhs.ToMatrix4x4(); - return *this; - } + Matrix4x4 &operator = (const Matrix3x3& rhs); + Matrix4x4 &operator = (const Quaternion& rhs); Matrix4x4 &operator = (const Matrix4x4& rhs) = default; protected: float elems[4][4]; - void SetMatrixRotatePart(Matrix4x4 &m, const Quaternion &q); + }; } \ No newline at end of file diff --git a/include/J3ML/LinearAlgebra/Vector3.h b/include/J3ML/LinearAlgebra/Vector3.h index 0a6b86b..b128d6c 100644 --- a/include/J3ML/LinearAlgebra/Vector3.h +++ b/include/J3ML/LinearAlgebra/Vector3.h @@ -38,7 +38,7 @@ public: } - //Returns the DirectionVector for a given angle. + /// Returns the DirectionVector for a given angle. static Vector3 Direction(const Vector3 &rhs) ; @@ -78,6 +78,11 @@ public: bool operator == (const Vector3& rhs) const; bool operator != (const Vector3& rhs) const; + bool IsFinite() const + { + return std::isfinite(x) && std::isfinite(y) && std::isfinite(z); + } + Vector3 Min(const Vector3& min) const; static Vector3 Min(const Vector3& lhs, const Vector3& rhs); @@ -87,7 +92,7 @@ public: Vector3 Clamp(const Vector3& min, const Vector3& max) const; static Vector3 Clamp(const Vector3& min, const Vector3& input, const Vector3& max); - // Returns the magnitude between the two vectors. + /// Returns the magnitude between the two vectors. float Distance(const Vector3& to) const; static float Distance(const Vector3& from, const Vector3& to); @@ -97,33 +102,33 @@ public: float LengthSquared() const; static float LengthSquared(const Vector3& of); - // Returns the length of the vector, which is sqrt(x^2 + y^2 + z^2) + /// Returns the length of the vector, which is sqrt(x^2 + y^2 + z^2) float Magnitude() const; static float Magnitude(const Vector3& of); - // Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them. - // For normalized vectors, dot returns 1 if they point in exactly the same direction, - // -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular. + /// Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them. + /// For normalized vectors, dot returns 1 if they point in exactly the same direction, + /// -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular. float Dot(const Vector3& rhs) const; static float Dot(const Vector3& lhs, const Vector3& rhs); - // Projects one vector onto another and returns the result. (IDK) + /// Projects one vector onto another and returns the result. (IDK) Vector3 Project(const Vector3& rhs) const; static Vector3 Project(const Vector3& lhs, const Vector3& rhs); - // The cross product of two vectors results in a third vector which is perpendicular to the two input vectors. - // The result's magnitude is equal to the magnitudes of the two inputs multiplied together and then multiplied by the sine of the angle between the inputs. + /// The cross product of two vectors results in a third vector which is perpendicular to the two input vectors. + /// The result's magnitude is equal to the magnitudes of the two inputs multiplied together and then multiplied by the sine of the angle between the inputs. Vector3 Cross(const Vector3& rhs) const; static Vector3 Cross(const Vector3& lhs, const Vector3& rhs); - // Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction" + /// Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction" Vector3 Normalize() const; static Vector3 Normalize(const Vector3& targ); - // Linearly interpolates between two points. - // Interpolates between the points and b by the interpolant t. - // The parameter is (TODO: SHOULD BE!) clamped to the range[0, 1]. - // This is most commonly used to find a point some fraction of the wy along a line between two endpoints (eg. to move an object gradually between those points). + /// Linearly interpolates between two points. + /// Interpolates between the points and b by the interpolant t. + /// The parameter is (TODO: SHOULD BE!) clamped to the range[0, 1]. + /// This is most commonly used to find a point some fraction of the wy along a line between two endpoints (eg. to move an object gradually between those points). Vector3 Lerp(const Vector3& goal, float alpha) const; static Vector3 Lerp(const Vector3& lhs, const Vector3& rhs, float alpha); @@ -136,24 +141,38 @@ public: Vector3 Add(const Vector3& rhs) const; static Vector3 Add(const Vector3& lhs, const Vector3& rhs); - // Subtracts two vectors + /// Subtracts two vectors Vector3 operator-(const Vector3& rhs) const; Vector3 Sub(const Vector3& rhs) const; static Vector3 Sub(const Vector3& lhs, const Vector3& rhs); - // Multiplies this vector by a scalar value + /// Multiplies this vector by a scalar value Vector3 operator*(float rhs) const; Vector3 Mul(float scalar) const; static Vector3 Mul(const Vector3& lhs, float rhs); - // Divides this vector by a scalar + /// Multiplies this vector by a vector, element-wise + /// @note Mathematically, the multiplication of two vectors is not defined in linear space structures, + /// but this function is provided here for syntactical convenience. + Vector3 Mul(const Vector3& rhs) const + { + + } + + /// Divides this vector by a scalar Vector3 operator/(float rhs) const; Vector3 Div(float scalar) const; static Vector3 Div(const Vector3& lhs, float rhs); - // Unary + operator + + /// Divides this vector by a vector, element-wise + /// @note Mathematically, the multiplication of two vectors is not defined in linear space structures, + /// but this function is provided here for syntactical convenience + Vector2 Div(const Vector2& v) const; + + /// Unary + operator Vector3 operator+() const; // TODO: Implement - // Unary - operator (Negation) + /// Unary - operator (Negation) Vector3 operator-() const; public: float x = 0; diff --git a/src/J3ML/Geometry/Capsule.cpp b/src/J3ML/Geometry/Capsule.cpp index ef2c454..1c509f8 100644 --- a/src/J3ML/Geometry/Capsule.cpp +++ b/src/J3ML/Geometry/Capsule.cpp @@ -3,4 +3,5 @@ namespace Geometry { + Capsule::Capsule() : l() {} } \ No newline at end of file diff --git a/src/J3ML/Geometry/LineSegment.cpp b/src/J3ML/Geometry/LineSegment.cpp index 5c55958..556b643 100644 --- a/src/J3ML/Geometry/LineSegment.cpp +++ b/src/J3ML/Geometry/LineSegment.cpp @@ -2,4 +2,10 @@ namespace Geometry { + LineSegment::LineSegment(const Vector3 &a, const Vector3 &b) : A(a), B(b) + { + + } + + LineSegment::LineSegment() {} } \ No newline at end of file diff --git a/src/J3ML/LinearAlgebra/Matrix3x3.cpp b/src/J3ML/LinearAlgebra/Matrix3x3.cpp index 0d2273b..e9e9fb8 100644 --- a/src/J3ML/LinearAlgebra/Matrix3x3.cpp +++ b/src/J3ML/LinearAlgebra/Matrix3x3.cpp @@ -296,5 +296,9 @@ namespace LinearAlgebra { }; } + float &Matrix3x3::At(int row, int col) { + return elems[row][col]; + } + } diff --git a/src/J3ML/LinearAlgebra/Matrix4x4.cpp b/src/J3ML/LinearAlgebra/Matrix4x4.cpp index b61f435..f684fb9 100644 --- a/src/J3ML/LinearAlgebra/Matrix4x4.cpp +++ b/src/J3ML/LinearAlgebra/Matrix4x4.cpp @@ -90,11 +90,8 @@ namespace LinearAlgebra { elems[2][3] = offset.z; } - void Matrix4x4::SetRotatePart(const Quaternion &q) { - SetMatrixRotatePart(*this, q); - } - void Matrix4x4::SetMatrixRotatePart(Matrix4x4 &m, const Quaternion& q) + void Matrix4x4::SetRotatePart(const Quaternion& q) { // See e.g. http://www.geometrictools.com/Documentation/LinearAlgebraicQuaternions.pdf . const float x = q.x; @@ -106,6 +103,15 @@ namespace LinearAlgebra { elems[2][0] = 2*(x*z - y*w); elems[2][1] = 2*(y*z + x*w); elems[2][2] = 1 - 2*(x*x + y*y); } + void Matrix4x4::Set3x3Part(const Matrix3x3& r) + { + At(0, 0) = r[0][0]; At(0, 1) = r[0][1]; At(0, 2) = r[0][2]; + At(1, 0) = r[1][0]; At(1, 1) = r[1][1]; At(1, 2) = r[1][2]; + At(2, 0) = r[2][0]; At(2, 1) = r[2][1]; At(2, 2) = r[2][2]; + } + + + void Matrix4x4::SetRow(int row, const Vector3 &rowVector, float m_r3) { SetRow(row, rowVector.x, rowVector.y, rowVector.z, m_r3); } @@ -224,4 +230,50 @@ namespace LinearAlgebra { } Matrix4x4 Matrix4x4::operator+() const { return *this; } + + Matrix4x4 Matrix4x4::FromTranslation(const Vector3 &rhs) { + return Matrix4x4(1.f, 0, 0, rhs.x, + 0, 1.f, 0, rhs.y, + 0, 0, 1.f, rhs.z, + 0, 0, 0, 1.f); + } + + Matrix4x4 Matrix4x4::Translate(const Vector3 &rhs) const { + return *this * FromTranslation(rhs); + } + + Vector3 Matrix4x4::Transform(const Vector3 &rhs) const { + return Transform(rhs.x, rhs.y, rhs.z); + } + + Vector3 Matrix4x4::Transform(float tx, float ty, float tz) const { + return Vector3(At(0, 0) * tx + At(0, 1) * ty + At(0, 2) * tz + At(0, 3), + At(1, 0) * tx + At(1, 1) * ty + At(1, 2) * tz + At(1, 3), + At(2, 0) * tx + At(2, 1) * ty + At(2, 2) * tz + At(2, 3)); + } + + Vector2 Matrix4x4::Transform(float tx, float ty) const { + return Vector2(At(0, 0) * tx + At(0, 1) * ty + At(0, 2) + At(0, 3), + At(1, 0) * tx + At(1, 1) * ty + At(1, 2) + At(1, 3)); + } + + Vector2 Matrix4x4::Transform(const Vector2 &rhs) const { + return Transform(rhs.x, rhs.y); + } + + Matrix4x4 &Matrix4x4::operator=(const Matrix3x3 &rhs) { + Set3x3Part(rhs); + SetTranslatePart(0,0,0); + SetRow(3, 0, 0, 0, 1); + return *this; + } + + Matrix4x4 &Matrix4x4::operator=(const Quaternion &rhs) { + *this = rhs.ToMatrix4x4(); + return *this; + } + + float &Matrix4x4::At(int row, int col) { + return elems[row][col]; + } } \ No newline at end of file