🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Obb vs triangle

Started by
1 comment, last by RulerOfNothing 4 years, 7 months ago

I have programmed Obb vs Triangle test from https://www.geometrictools.com/Documentation/DynamicCollisionDetection.pdf.

However, when I run the test, I got incorrect results. I have this test case:

{x=0.000000000 y=1.00000000 z=1.41421354 }
{x=1.41421354 y=1.00000000 z=0.000000000 }
{x=1.41421354 y=-1.00000000 z=0.000000000 }
{x=0.000000000 y=-1.00000000 z=1.41421354 }
{x=-1.41421354 y=1.00000000 z=0.000000000 }
{x=0.000000000 y=1.00000000 z=-1.41421354 }
{x=0.000000000 y=-1.00000000 z=-1.41421354 }
{x=-1.41421354 y=-1.00000000 z=0.000000000 }

And my trignale is:

a: { x=-1 y= -1 z=-1 }
b: { x=1, y=-1 z=-1 }
c: { x=0 y=0.8 z=1.0 }

If I test points separatelly, I got c as inside but triangle vs Obb test is returns false.


bool ObbVsObbSAT::TestIntersectTriangle(const Obb & oA,
const Vector3 & a,
const Vector3 & b,
const Vector3 & c)
{
const Vector3 & A0 = oA.axisX;
const Vector3 & A1 = oA.axisY;
const Vector3 & A2 = oA.axisZ;


Vector3 e0 = b - a;
Vector3 e1 = c - a;
Vector3 e2 = e1 - e0;
Vector3 n = Vector3::Cross(e0, e1);

Vector3 d = a - oA.center;

float a0n = Vector3::Dot(A0, n);
float a1n = Vector3::Dot(A1, n);
float a2n = Vector3::Dot(A2, n);

float p0, r;
p0 = r = 0.0f;

//
p0 = Vector3::Dot(n, d std::abs(a0n) + oA.halfHeight s(a0n) + oA.halfHeight * std::abs(a1n) + oA.halfDepth * std::abs(a2n);
if (std::abs(p0) > r) return false; //no intersection

//=========

//a's x axis
p0 = Vector3::Dot(A0, d);
float a0e0 = Vector3::Dot(A0, e0);
float a0e1 = Vector3::Dot(A0, e1);
if (TestTriangleAxisAk(p0, a0e0, a0e1, oA.halfWidth) == false) return false; //no intersection

// a's y axis
p0 = Vector3::Dot(A1, d);
float a1e0 = Vector3::Dot(A1, e0);
float a1e1 = Vector3::Dot(A1, e1);
if (TestTriangleAxisAk(p0, a1e0, a1e1, oA.halfHeight) == false) return false; //no intersection

// a's z axis
p0 = Vector3::Dot(A2, d);
float a2e0 = Vector3::Dot(A2, e0);
float a2e1 = Vector3::Dot(A2, e1);
if (TestTriangleAxisAk(p0, a2e0, a2e1, oA.halfDepth) == false) return false; //no intersection

//=========

// Cross( a.x, e0 )
p0 = Vector3::Dot(Vector3::Cross(A0, e0), d);
r = oA.halfHeight * std::abs(a2e0) + oA.halfDepth * std::abs(a1e0);
if (TestTriangleAxisAiEj(p0, a0n, r) == false) return false; //no intersection

// Cross( a.x, e1 )
p0 = Vector3::Dot(Vector3::Cross(A0, e1), d);
r = oA.halfHeight * std::abs(a2e1) + oA.halfDepth * std::abs(a1e1);
if (TestTriangleAxisAiEj(p0, a0n, r) == false) return false; //no intersection

// Cross( a.x, e2 )
float a2e2 = Vector3::Dot(A2, e2);
float a1e2 = Vector3::Dot(A1, e2);
p0 = Vector3::Dot(Vector3::Cross(A0, e2), d);
r = oA.halfHeight * std::abs(a2e2) + oA.halfDepth * std::abs(a1e2);
if (TestTriangleAxisAiEj(p0, a0n, r) == false) return false; //no intersection



// Cross( a.y, e0 )
p0 = Vector3::Dot(Vector3::Cross(A1, e0), d);
r = oA.halfWidth * std::abs(a2e0) + oA.halfDepth * std::abs(a0e0);
if (TestTriangleAxisAiEj(p0, a1n, r) == false) return false; //no intersection

// Cross( a.y, e1 )
p0 = Vector3::Dot(Vector3::Cross(A1, e1), d);
r = oA.halfWidth * std::abs(a2e1) + oA.halfDepth * std::abs(a0e1);
if (TestTriangleAxisAiEj(p0, a1n, r) == false) return false; //no intersection

// Cross( a.y, e2 )
float a0e2 = Vector3::Dot(A0, e2);
p0 = Vector3::Dot(Vector3::Cross(A1, e2), d);
r = oA.halfWidth * std::abs(a2e2) + oA.halfDepth * std::abs(a0e2);
if (TestTriangleAxisAiEj(p0, a1n, r) == false) return false; //no intersection


// Cross( a.z, e0 )
p0 = Vector3::Dot(Vector3::Cross(A2, e0), d);
r = oA.halfWidth * std::abs(a1e0) + oA.halfHeight * std::abs(a0e0);
if (TestTriangleAxisAiEj(p0, a2n, r) == false) return false; //no intersection

// Cross( a.z, e1 )
p0 = Vector3::Dot(Vector3::Cross(A2, e1), d);
r = oA.halfWidth * std::abs(a1e1) + oA.halfHeight * std::abs(a0e1);
if (TestTriangleAxisAiEj(p0, a2n, r) == false) return false; //no intersection

// Cross( a.z, e2 )
p0 = Vector3::Dot(Vector3::Cross(A2, e2), d);
r = oA.halfWidth * std::abs(a1e2) + oA.halfHeight * std::abs(a0e2);
if (TestTriangleAxisAiEj(p0, a2n, r) == false) return false; //no intersection

return true;
}

bool ObbVsObbSAT::TestTriangleAxisAk(float p, float d0, float d1, float r)
{
if (p > r)
{
if (d0 >= 0)
{
if (d1 >= 0) return false; //no intersection
if (p + d1 > r) return false; //no intersection
}
else if (d1 <= d0)
{
if (p + d1 > r) return false; //no intersection
}
else
{
if (p + d0 > r) return false; //no intersection
}
}
else if (p < -r)
{
if (d0 <= 0)
{
if (d1 <= 0) return false; //no intersection
if (p + d1 < -r) return false; //no intersection
}
else if (d1 >= d0)
{
if (p + d1 < -r) return false; //no intersection
}
else
{
if (p + d0 < -r) return false; //no intersection
}
}

return true;
}

bool ObbVsObbSAT::TestTriangleAxisAiEj(float p, float d, float r)
{
if (p > r)
{
if (d >= 0) return false; //no intersection
if (p + d > r) return false; //no intersection
}
else if (p < -r)
{
if (d <= 0) return false; //no intersection
if (p + d < -r) return false; //no intersection
}

return true;
}

Can anyone help me with what is wrong? Obb-Obb test based on same source (https://www.geometrictools.com/Documentation/DynamicCollisionDetection.pdf) is working correctly.

Advertisement

Two things that I can think of:

1) your point c is on the boundary of the OBB so maybe that's causing the problem

2) for some reason GameDev.net has mangled the code that is calculating the first r (right above if(std::abs(p0)<r)) so this could be where the problem lies

This topic is closed to new replies.

Advertisement