OBB OBB test

This commit is contained in:
Jorijn van der Graaf 2026-03-04 15:57:34 +01:00
commit 55a319a6ac
4 changed files with 137 additions and 35 deletions

View file

@ -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<typename T>
std::vector<Vector<T, 3, 0>> getOBBCorners(Vector<T, 3, 0> size, MatrixRowMajor<T, 4, 3, 1> matrix) {
std::vector<Vector<T, 3, 0>> localCorners = {
Vector<T, 3, 0>(-size.x, -size.y, -size.z),
Vector<T, 3, 0>( size.x, -size.y, -size.z),
Vector<T, 3, 0>(-size.x, size.y, -size.z),
Vector<T, 3, 0>( size.x, size.y, -size.z),
Vector<T, 3, 0>(-size.x, -size.y, size.z),
Vector<T, 3, 0>( size.x, -size.y, size.z),
Vector<T, 3, 0>(-size.x, size.y, size.z),
Vector<T, 3, 0>( size.x, size.y, size.z)
};
std::vector<Vector<T, 3, 0>> worldCorners;
for (Vector<T, 3, 0> localCorner : localCorners) {
Vector<T, 3, 0> rotatedCorner = matrix * localCorner;
worldCorners.push_back(rotatedCorner);
}
return worldCorners;
}
export template<typename T>
constexpr T IntersectionTestOrientedBoxOrientedBox(Vector<T, 3, 0> sizeA, MatrixRowMajor<T, 4, 3, 1> boxA, Vector<T, 3, 0> sizeB, MatrixRowMajor<T, 4, 3, 1> boxB) {
std::vector<Vector<T, 3, 0>> axes;
std::vector<Vector<T, 3, 0>> box1Corners = getOBBCorners(sizeA, boxA);
std::vector<Vector<T, 3, 0>> box2Corners = getOBBCorners(sizeB, boxB);
axes.push_back(Vector<T, 3, 0>(boxA.m[0][0], boxA.m[0][1], boxA.m[0][2]));
axes.push_back(Vector<T, 3, 0>(boxA.m[1][0], boxA.m[1][1], boxA.m[1][2]));
axes.push_back(Vector<T, 3, 0>(boxA.m[2][0], boxA.m[2][1], boxA.m[2][2]));
axes.push_back(Vector<T, 3, 0>(boxB.m[0][0], boxB.m[0][1], boxB.m[0][2]));
axes.push_back(Vector<T, 3, 0>(boxB.m[1][0], boxB.m[1][1], boxB.m[1][2]));
axes.push_back(Vector<T, 3, 0>(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<T, 3, 0>::Cross(Vector<T, 3, 0>(boxA.m[i][0], boxA.m[i][1], boxA.m[i][2]), Vector<T, 3, 0>(boxB.m[j][0], boxB.m[j][1], boxB.m[j][2])));
}
}
for (Vector<T, 3, 0> axis : axes) {
T min1 = Vector<T, 3, 0>::Dot(box1Corners[0], axis);
T max1 = min1;
for (Vector<T, 3, 0> corner : box1Corners) {
T projection = Vector<T, 3, 0>::Dot(corner, axis);
min1 = std::min(min1, projection);
max1 = std::max(max1, projection);
}
T min2 = Vector<T, 3, 0>::Dot(box2Corners[0], axis);
T max2 = min2;
for (Vector<T, 3, 0> corner : box2Corners) {
T projection = Vector<T, 3, 0>::Dot(corner, axis);
min2 = std::min(min2, projection);
max2 = std::max(max2, projection);
}
if (max1 < min2 || max2 < min1) {
return false;
}
}
return true;
}
}

View file

@ -80,11 +80,11 @@ namespace Crafter {
}
template <std::uint32_t VAligment>
Vector<T, 3, VAligment> operator*(Vector<T, 3, VAligment> b) const requires(CollumSize == 4 && RowSize == 4 && Repeats == 1 && std::same_as<T, float>) {
Vector<T, 3, VAligment> operator*(Vector<T, 3, VAligment> b) const requires(CollumSize == 4 && RowSize == 3 && Repeats == 1 && std::same_as<T, float>) {
return Vector<T, 3, VAligment>(
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]
);
}

View file

@ -238,7 +238,7 @@ namespace Crafter {
}
template <typename BT>
constexpr Vector<T, Len, Aligment> operator+(BT b) const {
constexpr Vector<T, Len, Aligment> operator+(BT b) const requires std::is_arithmetic_v<BT> {
Vector<T, Len, Aligment> 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 <typename BT>
constexpr Vector<T, Len, Aligment> operator-(BT b) const {
constexpr Vector<T, Len, Aligment> operator-(BT b) const requires std::is_arithmetic_v<BT> {
Vector<T, Len, Aligment> 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 <typename BT>
constexpr Vector<T, Len, Aligment> operator*(BT b) const {
constexpr Vector<T, Len, Aligment> operator*(BT b) const requires std::is_arithmetic_v<BT> {
Vector<T, Len, Aligment> 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 <typename BT>
constexpr Vector<T, Len, Aligment> operator/(BT b) const {
constexpr Vector<T, Len, Aligment> operator/(BT b) const requires std::is_arithmetic_v<BT> {
Vector<T, Len, Aligment> 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 <typename BT>
constexpr void operator+=(BT b){
constexpr void operator+=(BT b) requires std::is_arithmetic_v<BT>{
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] += b;
}
}
template <typename BT>
constexpr void operator-=(BT b){
constexpr void operator-=(BT b) requires std::is_arithmetic_v<BT>{
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] -= b;
}
}
template <typename BT>
constexpr void operator*=(BT b){
constexpr void operator*=(BT b) requires std::is_arithmetic_v<BT>{
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] *= b;
}
}
template <typename BT>
constexpr void operator/=(BT b){
constexpr void operator/=(BT b) requires std::is_arithmetic_v<BT>{
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] /= b;
}
@ -489,6 +489,6 @@ struct std::formatter<Crafter::Vector<T, 4, Aligment>> : std::formatter<std::str
template <typename T, std::uint32_t Len, std::uint32_t Aligment, typename BT>
constexpr Crafter::Vector<T, Len, Aligment> operator*(BT b, const Crafter::Vector<T, Len, Aligment>& v) {
constexpr Crafter::Vector<T, Len, Aligment> operator*(BT b, const Crafter::Vector<T, Len, Aligment>& v) requires std::is_arithmetic_v<BT> {
return v * b;
}

View file

@ -4,25 +4,56 @@ import std;
using namespace Crafter;
int main() {
// // Test Ray-OrientedBox intersection
// Vector<float, 3, 0> boxPos(0.0f, 0.0f, 0.0f);
// Vector<float, 3, 0> boxSize(2.0f, 2.0f, 2.0f);
// Vector<float, 3, 0> boxRot(0.0f, 0.0f, 0.0f); // No rotation
// Vector<float, 3, 0> rayOrigin(0.0f, 0.0f, -5.0f);
// Vector<float, 3, 0> rayDir(0.0f, 0.0f, 1.0f);
// Intersection Test
// float hitDistance = IntersectionTestRayOrientedBox(boxPos, boxSize, boxRot, rayOrigin, rayDir);
// Define Box A (size and matrix for transformation)
Vector<float, 3, 0> sizeA(1.0f, 1.0f, 1.0f); // Box A size
MatrixRowMajor<float, 4, 3, 1> 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;
// if (hitDistance < std::numeric_limits<float>::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;
// }
// Define Box B (size and matrix for transformation)
Vector<float, 3, 0> sizeB(1.0f, 1.0f, 1.0f); // Box B size
MatrixRowMajor<float, 4, 3, 1> 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;
// return 0;
// 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<float, 3, 0>(5, 0, 0) == Vector<float, 3, 0>(5,0,1)) << std::endl;
// Miss Test
// Define Box A (size and matrix for transformation)
Vector<float, 3, 0> sizeC(1.0f, 1.0f, 1.0f); // Box C size
MatrixRowMajor<float, 4, 3, 1> 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<float, 3, 0> sizeD(1.0f, 1.0f, 1.0f); // Box D size
MatrixRowMajor<float, 4, 3, 1> 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;
}