2

My MTV (Minimum Translation Vector) in AABB/Triangle intersection gives incorrect result on corners by Y axis. How can I fix it?

Current result:
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.

Markus Meyer
  • 3,327
  • 10
  • 22
  • 35
Rede Boy
  • 21
  • 2

0 Answers0