From 11062e761aa41b0ba3afd2646040998363c02346 Mon Sep 17 00:00:00 2001 From: josh Date: Mon, 5 Aug 2024 18:24:51 -0400 Subject: [PATCH] Actually builds now (Sorry bout that) --- include/J3ML/Geometry/Capsule.hpp | 2 +- include/J3ML/Geometry/Circle.hpp | 1 + include/J3ML/LinearAlgebra/Vector2.hpp | 4 ++-- include/J3ML/LinearAlgebra/Vector3.hpp | 25 +++++++++++++++------ include/J3ML/LinearAlgebra/Vector4.hpp | 4 +++- src/J3ML/Geometry/Capsule.cpp | 10 +++++++++ src/J3ML/Geometry/Polyhedron.cpp | 10 ++++----- src/J3ML/LinearAlgebra/Vector3.cpp | 31 ++++++++++++++++++++------ src/J3ML/LinearAlgebra/Vector4.cpp | 17 +++++++++++--- tests/LinearAlgebra/Vector2Tests.hpp | 2 +- tests/LinearAlgebra/Vector3Tests.hpp | 2 +- 11 files changed, 80 insertions(+), 28 deletions(-) diff --git a/include/J3ML/Geometry/Capsule.hpp b/include/J3ML/Geometry/Capsule.hpp index f6e3e62..4502dcc 100644 --- a/include/J3ML/Geometry/Capsule.hpp +++ b/include/J3ML/Geometry/Capsule.hpp @@ -14,7 +14,7 @@ #include #include #include -#include "Circle.hpp" +#include namespace J3ML::Geometry { diff --git a/include/J3ML/Geometry/Circle.hpp b/include/J3ML/Geometry/Circle.hpp index 45c4f0c..599a255 100644 --- a/include/J3ML/Geometry/Circle.hpp +++ b/include/J3ML/Geometry/Circle.hpp @@ -12,6 +12,7 @@ #pragma once #include +#include namespace J3ML { diff --git a/include/J3ML/LinearAlgebra/Vector2.hpp b/include/J3ML/LinearAlgebra/Vector2.hpp index 489f40f..b8ba2d4 100644 --- a/include/J3ML/LinearAlgebra/Vector2.hpp +++ b/include/J3ML/LinearAlgebra/Vector2.hpp @@ -239,8 +239,8 @@ namespace J3ML::LinearAlgebra { /// Returns a normalized copy of this vector. /** @note If the vector is zero and cannot be normalized, the vector (1, 0) is returned, and an error message is printed. If you do not want to generate an error message on failure, but want to handle the failure yourself, use the - Normalize() function instead. - @see Normalize() */ + Normalized() function instead. + @see Normalized() */ [[nodiscard]] Vector2 Normalized() const; /// Linearly interpolates between two points. diff --git a/include/J3ML/LinearAlgebra/Vector3.hpp b/include/J3ML/LinearAlgebra/Vector3.hpp index 36fc8ff..d6094f2 100644 --- a/include/J3ML/LinearAlgebra/Vector3.hpp +++ b/include/J3ML/LinearAlgebra/Vector3.hpp @@ -178,6 +178,13 @@ public: @see ScaledToLength(). */ float ScaleToLength(float newLength); + /// Returns a scaled copy of this vector which has its new length as given. + /** This function assumes the length of this vector is not zero. In the case of failure, an error message is printed, + and the vector (newLength, 0, 0) is returned. + @see ScaleToLength(). */ + [[nodiscard]] Vector3 ScaledToLength(float newLength) const; + + [[nodiscard]] Vector3 ProjectToNorm(const Vector3& direction) const; @@ -225,11 +232,15 @@ public: @see Perpendicular(), Cross(). */ Vector3 AnotherPerpendicular(const Vector3& hint = Vector3(0,1,0), const Vector3& hint2 = Vector3(0,0,1)) const; - /// Returns a scaled copy of this vector which has its new length as given. - /** This function assumes the length of this vector is not zero. In the case of failure, an error message is printed, - and the vector (newLength, 0, 0) is returned. - @see ScaleToLength(). */ - Vector3 ScaledToLength(float newLength) const; + /// Completes this vector to generate a perpendicular basis. + /** This function computes two new vectors b and c which are both orthogonal to this vector and to each other. + That is, the set { this, b, c} is an orthogonal set. The vectors b and c that are outputted are also normalized. + @param outB [out] Receives vector b. + @param outC [out] Receives vector c. + @note When calling this function, this vector should not be zero! */ + void PerpendicularBasis(Vector3& outB, Vector3& outC) const; + + [[nodiscard]] Vector3 Min(const Vector3& min) const; static Vector3 Min(const Vector3& a, const Vector3& b, const Vector3& c); @@ -282,8 +293,8 @@ public: /// Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction" /// @note If the vector is zero and cannot be normalized, the vector (1, 0, 0) is returned, and an error message is printed. - /// If you do not want to generate an error message on failure, but want to handle the failure yourself, use the Normalize() function instead. - /// @see Normalize() + /// If you do not want to generate an error message on failure, but want to handle the failure yourself, use the Normalized() function instead. + /// @see Normalized() [[nodiscard]] Vector3 Normalized() const; static Vector3 Normalized(const Vector3& targ); diff --git a/include/J3ML/LinearAlgebra/Vector4.hpp b/include/J3ML/LinearAlgebra/Vector4.hpp index e24d54f..523579c 100644 --- a/include/J3ML/LinearAlgebra/Vector4.hpp +++ b/include/J3ML/LinearAlgebra/Vector4.hpp @@ -217,7 +217,7 @@ namespace J3ML::LinearAlgebra { [[nodiscard]] Vector4 Cross3(const Vector4& rhs) const; [[nodiscard]] Vector4 Cross(const Vector4& rhs) const; - [[nodiscard]] Vector4 Normalize() const; + [[nodiscard]] Vector4 Normalized() const; [[nodiscard]] Vector4 Lerp(const Vector4& goal, float alpha) const; [[nodiscard]] float AngleBetween(const Vector4& rhs) const; @@ -265,6 +265,8 @@ namespace J3ML::LinearAlgebra { float y = 0; float z = 0; float w = 0; + + void Normalize(); }; } \ No newline at end of file diff --git a/src/J3ML/Geometry/Capsule.cpp b/src/J3ML/Geometry/Capsule.cpp index c31519f..591eced 100644 --- a/src/J3ML/Geometry/Capsule.cpp +++ b/src/J3ML/Geometry/Capsule.cpp @@ -189,6 +189,16 @@ namespace J3ML::Geometry return 2.f * Math::Pi * r * LineLength() + 4.f * Math::Pi * r * r; } + OBB Capsule::MinimalEnclosingOBB() const { + OBB obb; + obb.axis[0] = UpDirection(); + obb.axis[0].PerpendicularBasis(obb.axis[1], obb.axis[2]); + obb.pos = Center(); + obb.r[0] = Height() * 0.5f; + obb.r[1] = r; + obb.r[2] = r; + return obb; + } } \ No newline at end of file diff --git a/src/J3ML/Geometry/Polyhedron.cpp b/src/J3ML/Geometry/Polyhedron.cpp index 600965e..f7d0ac3 100644 --- a/src/J3ML/Geometry/Polyhedron.cpp +++ b/src/J3ML/Geometry/Polyhedron.cpp @@ -159,7 +159,7 @@ namespace J3ML::Geometry Vector3 Dir = ((Vector3)v[f[j].v[0]] + (Vector3)v[f[j].v[1]] + (Vector3)v[f[j].v[2]]) * 0.333333333333f - point; - //if (Dir.Normalize() <= 0.f) + //if (Dir.Normalized() <= 0.f) //continue; Ray r(Vector3(), Dir); @@ -368,7 +368,7 @@ namespace J3ML::Geometry Vector4 b = Vector4(poly.v[face.v[1]], 1.f); Vector4 c = Vector4(poly.v[face.v[2]], 1.f); Vector4 normal = (b-a).Cross(c-a); - normal.Normalize(); + normal.Normalized(); return normal; // return ((vec)v[face.v[1]]-(vec)v[face.v[0]]).Cross((vec)v[face.v[2]]-(vec)v[face.v[0]]).Normalized(); } @@ -386,7 +386,7 @@ namespace J3ML::Geometry normal.z += (double(poly.v[v0].x) - poly.v[v1].x) * (double(poly.v[v0].y) + poly.v[v1].y); // Project on xy v0 = v1; } - normal.Normalize(); + normal.Normalized(); return normal; #if 0 cv bestNormal; @@ -397,7 +397,7 @@ namespace J3ML::Geometry { cv c = poly.v[face.v[i]]; cv normal = (c-b).Cross(a-b); - float len = normal.Normalize(); + float len = normal.Normalized(); if (len > bestLen) { bestLen = len; @@ -441,7 +441,7 @@ namespace J3ML::Geometry cv edge = cv(poly.v[i]) - cv(poly.v[bestV0]); edge.Normalize(); cv normal = bestEdge.Cross(edge); - cs len = normal.Normalize(); + cs len = normal.Normalized(); if (len > bestLen) { bestLen = len; diff --git a/src/J3ML/LinearAlgebra/Vector3.cpp b/src/J3ML/LinearAlgebra/Vector3.cpp index 9b2fa13..0a84d98 100644 --- a/src/J3ML/LinearAlgebra/Vector3.cpp +++ b/src/J3ML/LinearAlgebra/Vector3.cpp @@ -105,7 +105,7 @@ namespace J3ML::LinearAlgebra { bool Vector3::operator!=(const Vector3& rhs) const { - return this->IsWithinMarginOfError(rhs) == false; + return !this->IsWithinMarginOfError(rhs); } @@ -318,9 +318,9 @@ namespace J3ML::LinearAlgebra { Angle2D Vector3::AngleBetween(const Vector3 &rhs) const { const auto Pi_x_180 = 180.f / M_PI; auto dist = this->Distance(rhs); - float x = -(asinf((rhs.y - this->y) / dist)); - float y = (atan2f(rhs.x - this->x,rhs.z - this->z)); - return {x, y}; + float dx = -(asinf((rhs.y - this->y) / dist)); + float dy = (atan2f(rhs.x - this->x,rhs.z - this->z)); + return {dx, dy}; } Angle2D Vector3::AngleBetween(const Vector3 &lhs, const Vector3 &rhs) // TODO: 3D Angle representation? @@ -329,9 +329,9 @@ namespace J3ML::LinearAlgebra { } Vector3 Vector3::Direction(const Vector3 &rhs) { - float x = (cos(Math::Radians(rhs.y)) * cos(Math::Radians(rhs.x))); - float y = -sin(Math::Radians(rhs.x)); - float z = (sin(Math::Radians(rhs.y)) * cos(Math::Radians(rhs.x))); + float x = (Math::Cos(Math::Radians(rhs.y)) * Math::Cos(Math::Radians(rhs.x))); + float y = -Math::Sin(Math::Radians(rhs.x)); + float z = (Math::Sin(Math::Radians(rhs.y)) * Math::Cos(Math::Radians(rhs.x))); return {x, y, z}; } @@ -600,5 +600,22 @@ namespace J3ML::LinearAlgebra { return *this + Vector3(s, s, s); } + Vector3 Vector3::ScaledToLength(float newLength) const { + assert(!IsZero()); + + Vector3 v = *this; + v.ScaleToLength(newLength); + return v; + } + + void Vector3::PerpendicularBasis(Vector3 &outB, Vector3 &outC) const { + // Pixar orthonormal basis code: https://graphics.pixar.com/library/OrthonormalB/paper.pdf + float sign = copysignf(1.0f, z); + const float a = -1.0f / (sign + z); + const float b = x * y * a; + outB = Vector3(1.0f + sign * x * x * a, sign * b, -sign * x); + outC = Vector3( b, sign + y * y * a, -y); + } + } \ No newline at end of file diff --git a/src/J3ML/LinearAlgebra/Vector4.cpp b/src/J3ML/LinearAlgebra/Vector4.cpp index 404b533..b4558f3 100644 --- a/src/J3ML/LinearAlgebra/Vector4.cpp +++ b/src/J3ML/LinearAlgebra/Vector4.cpp @@ -132,8 +132,8 @@ float Vector4::Magnitude() const float Vector4::Dot(const Vector4& rhs) const { - auto a = this->Normalize(); - auto b = rhs.Normalize(); + auto a = this->Normalized(); + auto b = rhs.Normalized(); return a.x * b.x + a.y * b.y + @@ -155,7 +155,17 @@ Vector4 Vector4::Project(const Vector4& rhs) const return rhs * scalar; } -Vector4 Vector4::Normalize() const +void Vector4::Normalize() +{ + if (Length() > 0) { + x = x / Length(); + y = y / Length(); + z = z / Length(); + w = w / Length(); + } +} + +Vector4 Vector4::Normalized() const { if (Length() > 0) return { @@ -274,6 +284,7 @@ Vector4 Vector4::operator-(const Vector4& rhs) const if (index == 2) return z; if (index == 3) return w; + return x; // This point should never be reached. } float Vector4::At(int index) const { diff --git a/tests/LinearAlgebra/Vector2Tests.hpp b/tests/LinearAlgebra/Vector2Tests.hpp index efe6540..d9f3b10 100644 --- a/tests/LinearAlgebra/Vector2Tests.hpp +++ b/tests/LinearAlgebra/Vector2Tests.hpp @@ -156,7 +156,7 @@ int Vector2Tests() jtest::check(Base.Project(Projected) == ExpectedResult); }); - TEST("Vector2::Normalize", [] + TEST("Vector2::Normalized", [] { Vector2 A(2, 0); Vector2 B(1, 0); diff --git a/tests/LinearAlgebra/Vector3Tests.hpp b/tests/LinearAlgebra/Vector3Tests.hpp index cbe8bdd..0f9f3b4 100644 --- a/tests/LinearAlgebra/Vector3Tests.hpp +++ b/tests/LinearAlgebra/Vector3Tests.hpp @@ -173,7 +173,7 @@ int Vector3Tests() { Vector3 Projection; Vector3 ExpectedResult; }); - TEST("Vector3::Normalize", [] { + TEST("Vector3::Normalized", [] { Vector3 Input (2, 0, 0); Vector3 ExpectedResult (1, 0, 0);