Separating Axis Test for Axis-Aligned Bounding Box and Triangle produces incorrect results (3D)

后端 未结 2 1093
没有蜡笔的小新
没有蜡笔的小新 2021-01-21 04:29

I\'m doing triangle to AABB intersection tests, and I\'m taking this sample code from Real-Time Collision Detection by Christer Ericson. What the author says in the boo

相关标签:
2条回答
  • 2021-01-21 04:31

    The reason that I was getting false positives for my tests was related to the triangle test.

    To test a triangle, which is a plane in 3D space, you have to test against 4 axes(aka normals).

    1. Surface Normal
      • The cross-product between two edges of the triangle.
    2. Edge Normal 1
      • The cross product between the surface normal and edge 1.
    3. Edge Normal 2
      • The cross product between the surface normal and edge 2.
    4. Edge Normal 3
      • The cross product between the surface normal and edge 3.

    So in the end, to get a proper (at least it is working correctly so far) collision test between a cube and a triangle, you have to perform 7 axes tests.

    Each test consists of checking the triangle and box vertices against the axis (normal). This can be broken down into a triangle and box test, and if one has a separating axis, then you don't have to do the other.

    Note: This test will only give you true/false results. No other data is provided.

    public static boolean testTriangleAABB( Triangle triangle, 
            Vector3d origin, double size ) {
        setTriangleNormal( triangle.getNormal( true ) );
        Vector3d[] aabbVertices = calculateAABBVertices( origin, size );
    
        // Triangle Normal axis test, false = No Collision.
        if( !testTriangleNormal( triangle, aabbVertices ) ) {
            return false;
        }
    
        // Triangle Edge Normals axis test, false = No Collision.
        if( !testTriangleEdgeNormals( triangle, aabbVertices ) ) {
            return false;
        }
    
        // Axis-Aligned Bounding Box X, Y, Z axis test, false = No Collision.
        if( !testAABBAxis( triangle, aabbVertices ) ) {
            return false;
        }     
    
        // if we get here then we know that every axis had overlap on it
        // so we can guarantee an intersection
        return true;
    }
    
    ...
    
    private static boolean testTriangleEdgeNormals( Triangle triangle, Vector3d[] aabbVertices ) {
        Vector3d edge = new Vector3d();
        Vector3d edgeNormal = new Vector3d();
    
        // loop over the triangle edge normals
        Vector3d[] points = triangle.getPoints();
        for( int i = 0; i < points.length; i++ ) {
            int iOverflow = i + 1 == points.length ? 0 : i + 1;
            edge.sub( points[ i ], points[ iOverflow ] );
            edge.normalize();
            edgeNormal.cross( getTriangleNormal(), edge );
    
            // project both shapes onto the axis
            projectionAABB = project2D1D( aabbVertices, edgeNormal );
            projectionTriangle = project2D1D( triangle.getPoints(), edgeNormal );
            // do the projections overlap?
            if ( !projectionAABB.hasOverlap( projectionTriangle ) ) {
                // then we can guarantee that the shapes do not overlap
                return false;
            }
        }
        return true;
    }
    

    Furthermore, there is no need to calculate Axis-Aligned Bounding Box axes..since they are axis aligned the axes will be like so:

    private static final Vector3d[] AABB_AXES = { 
        new Vector3d( -1.0, 0.0, 0.0 ), 
        new Vector3d( 0.0, -1.0, 0.0 ),
        new Vector3d( 0.0, 0.0, -1.0 ) };
    
    0 讨论(0)
  • 2021-01-21 04:55

    You can check my c# (almost identical to java in this case...) implantation in a game i made a little while ago. http://code.google.com/p/gotcha/source/browse/trunk/Gotcha/trunk/Gotcha/Gotcha/GameEnteties/GameEntity.cs#171

    Look for the method : IsSATCollision

    Think about the parameter it accepts as just something that has vertices for simplicity.

    0 讨论(0)
提交回复
热议问题