diff --git a/interfaces/Crafter.Math-Intersection.cppm b/interfaces/Crafter.Math-Intersection.cppm index 2d9bbe9..395827e 100755 --- a/interfaces/Crafter.Math-Intersection.cppm +++ b/interfaces/Crafter.Math-Intersection.cppm @@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA export module Crafter.Math:Intersection; import :Vector; +import :MatrixRowMajor; import std; namespace Crafter { @@ -67,7 +68,7 @@ namespace Crafter { d = std::sqrt(d); - float t = (T(-0.5)) * (b + d) / a; + T t = (T(-0.5)) * (b + d) / a; if (t > T(0)) { return t; } else { @@ -121,4 +122,74 @@ namespace Crafter { return (tMin >= T(0)) ? tMin : tMax; } + + + export template + std::vector> getOBBCorners(Vector size, MatrixRowMajor matrix) { + std::vector> localCorners = { + Vector(-size.x, -size.y, -size.z), + Vector( size.x, -size.y, -size.z), + Vector(-size.x, size.y, -size.z), + Vector( size.x, size.y, -size.z), + Vector(-size.x, -size.y, size.z), + Vector( size.x, -size.y, size.z), + Vector(-size.x, size.y, size.z), + Vector( size.x, size.y, size.z) + }; + + std::vector> worldCorners; + + for (Vector localCorner : localCorners) { + Vector rotatedCorner = matrix * localCorner; + worldCorners.push_back(rotatedCorner); + } + + return worldCorners; + } + + export template + constexpr T IntersectionTestOrientedBoxOrientedBox(Vector sizeA, MatrixRowMajor boxA, Vector sizeB, MatrixRowMajor boxB) { + std::vector> axes; + + std::vector> box1Corners = getOBBCorners(sizeA, boxA); + std::vector> box2Corners = getOBBCorners(sizeB, boxB); + + axes.push_back(Vector(boxA.m[0][0], boxA.m[0][1], boxA.m[0][2])); + axes.push_back(Vector(boxA.m[1][0], boxA.m[1][1], boxA.m[1][2])); + axes.push_back(Vector(boxA.m[2][0], boxA.m[2][1], boxA.m[2][2])); + + axes.push_back(Vector(boxB.m[0][0], boxB.m[0][1], boxB.m[0][2])); + axes.push_back(Vector(boxB.m[1][0], boxB.m[1][1], boxB.m[1][2])); + axes.push_back(Vector(boxB.m[2][0], boxB.m[2][1], boxB.m[2][2])); + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + axes.push_back(Vector::Cross(Vector(boxA.m[i][0], boxA.m[i][1], boxA.m[i][2]), Vector(boxB.m[j][0], boxB.m[j][1], boxB.m[j][2]))); + } + } + + for (Vector axis : axes) { + T min1 = Vector::Dot(box1Corners[0], axis); + T max1 = min1; + for (Vector corner : box1Corners) { + T projection = Vector::Dot(corner, axis); + min1 = std::min(min1, projection); + max1 = std::max(max1, projection); + } + + T min2 = Vector::Dot(box2Corners[0], axis); + T max2 = min2; + for (Vector corner : box2Corners) { + T projection = Vector::Dot(corner, axis); + min2 = std::min(min2, projection); + max2 = std::max(max2, projection); + } + + if (max1 < min2 || max2 < min1) { + return false; + } + } + + return true; + } } \ No newline at end of file diff --git a/interfaces/Crafter.Math-MatrixRowMajor.cppm b/interfaces/Crafter.Math-MatrixRowMajor.cppm index 8cf9b5e..2bf810e 100755 --- a/interfaces/Crafter.Math-MatrixRowMajor.cppm +++ b/interfaces/Crafter.Math-MatrixRowMajor.cppm @@ -80,11 +80,11 @@ namespace Crafter { } template - Vector operator*(Vector b) const requires(CollumSize == 4 && RowSize == 4 && Repeats == 1 && std::same_as) { + Vector operator*(Vector b) const requires(CollumSize == 4 && RowSize == 3 && Repeats == 1 && std::same_as) { return Vector( - b.x * m[0][0] + b.y * m[1][0] + b.z * m[2][0] + m[3][0], - b.x * m[0][1] + b.y * m[1][1] + b.z * m[2][1] + m[3][1], - b.x * m[0][2] + b.y * m[1][2] + b.z * m[2][2] + m[3][2] + b.x * m[0][0] + b.y * m[0][1] + b.z * m[0][2] + m[0][3], + b.x * m[1][0] + b.y * m[1][1] + b.z * m[1][2] + m[1][3], + b.x * m[2][0] + b.y * m[2][1] + b.z * m[2][2] + m[2][3] ); } diff --git a/interfaces/Crafter.Math-Vector.cppm b/interfaces/Crafter.Math-Vector.cppm index 8db62b2..60a9c9a 100755 --- a/interfaces/Crafter.Math-Vector.cppm +++ b/interfaces/Crafter.Math-Vector.cppm @@ -238,7 +238,7 @@ namespace Crafter { } template - constexpr Vector operator+(BT b) const { + constexpr Vector operator+(BT b) const requires std::is_arithmetic_v { Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = this->v[i] + b; @@ -246,7 +246,7 @@ namespace Crafter { return resultVector; } template - constexpr Vector operator-(BT b) const { + constexpr Vector operator-(BT b) const requires std::is_arithmetic_v { Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = this->v[i] - b; @@ -254,7 +254,7 @@ namespace Crafter { return resultVector; } template - constexpr Vector operator*(BT b) const { + constexpr Vector operator*(BT b) const requires std::is_arithmetic_v { Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = this->v[i] * b; @@ -262,7 +262,7 @@ namespace Crafter { return resultVector; } template - constexpr Vector operator/(BT b) const { + constexpr Vector operator/(BT b) const requires std::is_arithmetic_v { Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = this->v[i] / b; @@ -270,25 +270,25 @@ namespace Crafter { return resultVector; } template - constexpr void operator+=(BT b){ + constexpr void operator+=(BT b) requires std::is_arithmetic_v{ for(std::uint32_t i = 0; i < Len; i++) { this->v[i] += b; } } template - constexpr void operator-=(BT b){ + constexpr void operator-=(BT b) requires std::is_arithmetic_v{ for(std::uint32_t i = 0; i < Len; i++) { this->v[i] -= b; } } template - constexpr void operator*=(BT b){ + constexpr void operator*=(BT b) requires std::is_arithmetic_v{ for(std::uint32_t i = 0; i < Len; i++) { this->v[i] *= b; } } template - constexpr void operator/=(BT b){ + constexpr void operator/=(BT b) requires std::is_arithmetic_v{ for(std::uint32_t i = 0; i < Len; i++) { this->v[i] /= b; } @@ -489,6 +489,6 @@ struct std::formatter> : std::formatter -constexpr Crafter::Vector operator*(BT b, const Crafter::Vector& v) { +constexpr Crafter::Vector operator*(BT b, const Crafter::Vector& v) requires std::is_arithmetic_v { return v * b; } \ No newline at end of file diff --git a/interfaces/main.cpp b/interfaces/main.cpp index 472cebf..b7e3b23 100644 --- a/interfaces/main.cpp +++ b/interfaces/main.cpp @@ -4,25 +4,56 @@ import std; using namespace Crafter; int main() { - // // Test Ray-OrientedBox intersection - // Vector boxPos(0.0f, 0.0f, 0.0f); - // Vector boxSize(2.0f, 2.0f, 2.0f); - // Vector boxRot(0.0f, 0.0f, 0.0f); // No rotation - // Vector rayOrigin(0.0f, 0.0f, -5.0f); - // Vector rayDir(0.0f, 0.0f, 1.0f); - - // float hitDistance = IntersectionTestRayOrientedBox(boxPos, boxSize, boxRot, rayOrigin, rayDir); - - // if (hitDistance < std::numeric_limits::max()) { - // // Hit occurred - // std::cout << "Ray-OrientedBox intersection at distance: " << hitDistance << std::endl; - // } else { - // // No hit - // std::cout << "No intersection with Ray-OrientedBox" << std::endl; - // } - - // return 0; + // Intersection Test + + // Define Box A (size and matrix for transformation) + Vector sizeA(1.0f, 1.0f, 1.0f); // Box A size + MatrixRowMajor boxA; + boxA.m[0][0] = 1.0f; boxA.m[1][0] = 0.0f; boxA.m[2][0] = 0.0f; + boxA.m[1][0] = 0.0f; boxA.m[1][1] = 1.0f; boxA.m[2][1] = 0.0f; + boxA.m[2][0] = 0.0f; boxA.m[1][2] = 0.0f; boxA.m[2][2] = 1.0f; + + // Define Box B (size and matrix for transformation) + Vector sizeB(1.0f, 1.0f, 1.0f); // Box B size + MatrixRowMajor boxB; + boxB.m[0][0] = 1.0f; boxB.m[1][0] = 0.0f; boxB.m[2][0] = 0.0f; + boxB.m[1][0] = 0.0f; boxB.m[1][1] = 1.0f; boxB.m[2][1] = 0.0f; + boxB.m[2][0] = 0.0f; boxB.m[1][2] = 0.0f; boxB.m[2][2] = 1.0f; + + // Apply a small translation to box B (so that they overlap) + boxB.m[0][3] = 0.5f; + boxB.m[1][3] = 0.5f; + boxB.m[2][3] = 0.0f; + + // Check if the boxes intersect (they should, as they're overlapping) + bool result = IntersectionTestOrientedBoxOrientedBox(sizeA, boxA, sizeB, boxB); + std::cout << result << std::endl; - std::cout << (Vector(5, 0, 0) == Vector(5,0,1)) << std::endl; + // Miss Test + + // Define Box A (size and matrix for transformation) + Vector sizeC(1.0f, 1.0f, 1.0f); // Box C size + MatrixRowMajor boxC; + boxC.m[0][0] = 1.0f; boxC.m[1][0] = 0.0f; boxC.m[2][0] = 0.0f; + boxC.m[1][0] = 0.0f; boxC.m[1][1] = 1.0f; boxC.m[2][1] = 0.0f; + boxC.m[2][0] = 0.0f; boxC.m[1][2] = 0.0f; boxC.m[2][2] = 1.0f; + + // Define Box D (size and matrix for transformation) + Vector sizeD(1.0f, 1.0f, 1.0f); // Box D size + MatrixRowMajor boxD; + boxD.m[0][0] = 1.0f; boxD.m[1][0] = 0.0f; boxD.m[2][0] = 0.0f; + boxD.m[1][0] = 0.0f; boxD.m[1][1] = 1.0f; boxD.m[2][1] = 0.0f; + boxD.m[2][0] = 0.0f; boxD.m[1][2] = 0.0f; boxD.m[2][2] = 1.0f; + + // Apply a large translation to box D (so that they do not intersect) + boxD.m[0][3] = 3.0f; + boxD.m[1][3] = 3.0f; + boxD.m[2][3] = 0.0f; + + // Check if the boxes do not intersect (they shouldn't, as they are far apart) + bool missResult = IntersectionTestOrientedBoxOrientedBox(sizeC, boxC, sizeD, boxD); + std::cout << missResult << std::endl; + + return 0; } \ No newline at end of file