My MTV (Minimum Translation Vector) in AABB/Triangle intersection gives incorrect result on corners by Y axis. How can I fix it?
Current result:
This is my code:
public static bool BoxTriangleIntersection(Box box, Triangle triangle, out Vector3 minTranslation) {
minTranslation = Vector3.Zero;
var boxCenter = box.GetCenter();
var boxExtents = box.GetHalfExtent();
var aPointRelativeToBox = triangle[0] - boxCenter;
var bPointRelativeToBox = triangle[1] - boxCenter;
var cPointRelativeToBox = triangle[2] - boxCenter;
var triangleEdges = new[] {
triangle[1] - triangle[0],
triangle[2] - triangle[1],
triangle[0] - triangle[2]
};
for (var i = 0; i < 3; i++) {
var projectionAxis = new Vector3(0, -triangleEdges[i].Z, triangleEdges[i].Y);
var testPointA = Vector3.Dot(aPointRelativeToBox, projectionAxis);
var testPointB = Vector3.Dot(bPointRelativeToBox, projectionAxis);
var testPointC = Vector3.Dot(cPointRelativeToBox, projectionAxis);
var radius = boxExtents.Y * Math.Abs(triangleEdges[i].Z) + boxExtents.Z * Math.Abs(triangleEdges[i].Y);
if (Math.Max(-MathBindings.Max(testPointA, testPointB, testPointC),
MathBindings.Min(testPointA, testPointB, testPointC)) > radius) {
return false;
}
}
for (var i = 0; i < 3; i++) {
var projectionAxis = new Vector3(triangleEdges[i].Z, 0, -triangleEdges[i].X);
var testPointA = Vector3.Dot(aPointRelativeToBox, projectionAxis);
var testPointB = Vector3.Dot(bPointRelativeToBox, projectionAxis);
var testPointC = Vector3.Dot(cPointRelativeToBox, projectionAxis);
var radius = boxExtents.X * Math.Abs(triangleEdges[i].Z) + boxExtents.Z * Math.Abs(triangleEdges[i].X);
if (Math.Max(-MathBindings.Max(testPointA, testPointB, testPointC),
MathBindings.Min(testPointA, testPointB, testPointC)) > radius) {
return false;
}
}
for (var i = 0; i < 3; i++) {
var projectionAxis = new Vector3(-triangleEdges[i].Y, triangleEdges[i].X, 0);
var testPointA = Vector3.Dot(aPointRelativeToBox, projectionAxis);
var testPointB = Vector3.Dot(bPointRelativeToBox, projectionAxis);
var testPointC = Vector3.Dot(cPointRelativeToBox, projectionAxis);
var radius = boxExtents.X * Math.Abs(triangleEdges[i].Y) + boxExtents.Y * Math.Abs(triangleEdges[i].X);
if (Math.Max(-MathBindings.Max(testPointA, testPointB, testPointC),
MathBindings.Min(testPointA, testPointB, testPointC)) > radius) {
return false;
}
}
for (var i = 0; i < 3; i++) {
if (MathBindings.Max(aPointRelativeToBox[i], bPointRelativeToBox[i], cPointRelativeToBox[i]) < -boxExtents[i] ||
MathBindings.Min(aPointRelativeToBox[i], bPointRelativeToBox[i], cPointRelativeToBox[i]) > boxExtents[i]) {
return false;
}
}
var planeNormal = triangle.GetNormal().Normalized();
var planeDistance = Math.Abs(Vector3.Dot(planeNormal, aPointRelativeToBox));
var projectionIntervalRadius = boxExtents.X * Math.Abs(planeNormal.X) +
boxExtents.Y * Math.Abs(planeNormal.Y) +
boxExtents.Z * Math.Abs(planeNormal.Z);
minTranslation = planeNormal * (projectionIntervalRadius - planeDistance);
return planeDistance <= projectionIntervalRadius;
}
I use difference between projection interval radius and plane distance as MTD(minimum translation distance). But I'm not sure if this is the correct solution.