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.