Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将轴对齐的边界框和三角形的轴测试分离会产生不正确的结果(3D)_Java_Collision Detection - Fatal编程技术网

Java 将轴对齐的边界框和三角形的轴测试分离会产生不正确的结果(3D)

Java 将轴对齐的边界框和三角形的轴测试分离会产生不正确的结果(3D),java,collision-detection,Java,Collision Detection,我正在做三角形到AABB交叉点的测试,我从Christer Ericson的实时碰撞检测中获取了这个示例代码。作者在给出示例之前在书中所说的与示例不同,因此我不确定如何测试其余轴。。a01-a22 测试:由两条边组合的叉积给出的九条轴 // Test axes a00..a22 ( category 3 ) // Test axis a00 originDistance0 = triangle.point0.z * triangle.point1.y - triangle.po

我正在做三角形到AABB交叉点的测试,我从Christer Ericson的实时碰撞检测中获取了这个示例代码。作者在给出示例之前在书中所说的与示例不同,因此我不确定如何测试其余轴。。a01-a22

测试:由两条边组合的叉积给出的九条轴

// Test axes a00..a22 ( category 3 )
// Test axis a00
originDistance0 = triangle.point0.z * triangle.point1.y 
        - triangle.point0.y * triangle.point1.z;
originDistance2 = triangle.point1.z *( triangle.point1.y - triangle.point0.y ) 
        - triangle.point1.z * ( triangle.point1.z - triangle.point0.z );
projectionRadius = extent1 * Math.abs( edge0.z ) + extent2 * Math.abs( edge0.y );
if ( Math.max( -Math.max( originDistance0, originDistance2 ), Math.min( originDistance0, originDistance2 ) ) > projectionRadius ) {
    return false; // Axis is a separating axis
}

// Repeat similar tests for remaining axes a01..a22
这是对第一个轴的测试。根据这本书,这些是轴:

a00 = u0×f0 = (1,0,0)×f0 = (0,-f0z,f0y)

a01 = u0×f1 = (1,0,0)×f1 = (0,-f1z,f1y)

a02 = u0×f2 = (1,0,0)×f2 = (0,-f2z,f2y)

a10 = u1×f0 = (0,1,0)×f0 = (f0z,0,-f0x)

a11 = u1×f1 = (0,1,0)×f1 = (f1z,0,-f1x)

a12 = u1×f2 = (0,1,0)×f2 = (f2z,0,-f2x)

a20 = u2×f0 = (0,0,1)×f0 = (-f0y,f0x,0)

a21 = u2×f1 = (0,0,1)×f1 = (-f1y,f1x,0)

a22 = u2×f2 = (0,0,1)×f2 = (-f2y,f2x,0)

============

p0 = V0·a00

p1 = V1·a00=V1=p0

p2 = V2·a00=V2

图例:u=中心向量,f=三角形边向量。p=从原点到三角形顶点投影到法线的距离。V=三角形点

如何计算后续的轴测试?也许如果有人能做一个,我就可以更好地了解其余的,但只有一个例子,我被卡住了。。谢谢

编辑:我尝试了以下方法。。对于没有运气的a00-a22,测试仍然通过。 首先我添加了这个代码,替换了a00,并添加了a01-a22

// Test axes a00..a22 ( category 3 )
Vector3d a00 = new Vector3d();
Vector3d a01 = new Vector3d();
Vector3d a02 = new Vector3d();
Vector3d a10 = new Vector3d();
Vector3d a11 = new Vector3d();
Vector3d a12 = new Vector3d();
Vector3d a20 = new Vector3d();
Vector3d a21 = new Vector3d();
Vector3d a22 = new Vector3d();
a00.cross( u0, edge0 );
a01.cross( u0, edge1 );
a02.cross( u0, edge2 );
a10.cross( u1, edge0 );
a11.cross( u1, edge1 );
a12.cross( u1, edge2 );
a20.cross( u2, edge0 );
a21.cross( u2, edge1 );
a22.cross( u2, edge2 );


// Test axes a00-a22
originDistance0 = triangle.point0.dot( a00 );
originDistance2 = triangle.point2.dot( a00 );
projectionRadius = extent1 * Math.abs( edge0.z ) + extent2 * Math.abs( edge0.y );
if ( Math.max( -Math.max( originDistance0, originDistance2 ), Math.min( originDistance0, originDistance2 ) ) > projectionRadius ) {
    return false; // Axis is a separating axis
}
...
编辑2:我也尝试了以下方法,这让我更接近了,但仍然没有得到所有交叉点,也没有得到不应该得到的交叉点

更新:仍然无法获得正确的交叉点结果。查看了Eli的代码,但它似乎是针对2d数据的,并且术语不同,所以我没有找到我的代码和他的代码之间的联系

更新2:其他尝试一直在尝试代码,这与事实标准类似。我得到一个交点,应该有4个交点,其中2个包含三角形的点,3个包含边,1个只是平面

捕捉的交点有一个点和两条边(加上平面)。还有一个对象具有相同的特征,但位置不同,不被视为相交。这是我正在处理的数据,突出显示的“体素”是在与三角形相交时返回的数据

以下测试类别返回的交叉点结果:

体素1:无,全部通过,返回默认值“true”。
体素2:类别2
体素3:类别3
体素4:类别3
体素5:类别3

更新3:另一个实施,更好的结果

好的,在阅读了William Bittle在codezealot.org上的文章后,我实现了以下内容:

public static boolean testTriangleAABB( Triangle triangle, BoundingBox boundingBox, double size ) {
    Vector3d[] triangleAxes = getAxes( triangle.getPoints() );
    Vector3d[] aabbVertices = getVertices( boundingBox, size );
    Vector3d[] aabbAxes = getAxes( aabbVertices );

    // loop over the triangleAxes
    for( int i = 0; i < triangleAxes.length; i++ ) {
      Vector3d axis = triangleAxes[ i ];
      // project both shapes onto the axis
      Projection p1 = project( triangle.getPoints(), axis );
      Projection p2 = project( aabbVertices, axis );
      // do the projections overlap?
      if ( !p1.overlap( p2 ) ) {
        // then we can guarantee that the shapes do not overlap
        return false;
      }
    }

    // loop over the aabbAxes
    for( int i = 0; i < aabbAxes.length; i++ ) {
      Vector3d axis = aabbAxes[ i ];
      axis.normalize();
      // project both shapes onto the axis
      Projection p1 = project( triangle.getPoints(), axis );
      Projection p2 = project( aabbVertices, axis );
      // do the projections overlap?
      if ( !p1.overlap( p2 ) ) {
        // then we can guarantee that the shapes do not overlap
        return false;
      }
    }
    // if we get here then we know that every axis had overlap on it
    // so we can guarantee an intersection
    return true;
}
现在我正在使用另一个数据集来全面测试交叉点,因为我从上一个数据集中得到了一些误报

三角形0:真
三角形1:正确
三角形2:正确您可以检查我的c#(在本例中几乎与java相同…)植入到我不久前制作的一个游戏中。

寻找方法:IsSATCollision


为简单起见,将它接受的参数看作是具有顶点的参数。

我的测试得到误报的原因与三角形测试有关

要测试三角形,即三维空间中的平面,必须针对4个轴(也称法线)进行测试

  • 表面法线
    • 三角形两条边之间的叉积
  • 边缘法线1
    • 曲面法线和边1之间的叉积
  • 边缘法线2
    • 曲面法线和边2之间的叉积
  • 边缘法线3
    • 曲面法线和边3之间的叉积
  • 最后,要在立方体和三角形之间进行正确的碰撞测试(至少目前为止它工作正常),必须执行7轴测试

    每个测试包括对照轴(法线)检查三角形和长方体顶点。这可以分解成一个三角形和长方体测试,如果其中一个有一个分离轴,那么你就不必做另一个

    注意:此测试只会给出正确/错误的结果。没有提供其他数据

    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;
    }
    

    是不是
    Vector2
    ,只是一个2d向量,所以它只有一个x和一个y(没有z)?没错(这是一个XNA的东西。)你使用
    Vector2
    是因为这是2d游戏吗?喂,你有完整的代码吗?“testTriangleNormal”是做什么的?
    public boolean overlap( Projection projection ) {
        double test1;
        double test2;
    
        // and test if they are touching 
        test1 = min - projection.max;   // test min1 and max2 
        test2 = projection.min - max;   // test min2 and max1
    
        if( ( ( test1 > 0 ) || ( test2 > 0 ) ) ) {      // if they are greater than 0, there is a gap 
            return false;                               // just quit } 
        }
        return true;
    }    
    
    public static Vector3d[] getAABBAxes( Vector3d[] vertices ) {
        Vector3d[] axes = new Vector3d[ 6 ];
        // loop over the vertices
        for ( int i = 0; i < 6; i++ ) {
            // get the current vertex
            Vector3d p1 = vertices[ i ];
            // get the next vertex
            Vector3d p2 = vertices[ i + 1 == vertices.length ? 0 : i + 1 ];
            Vector3d p4 = vertices[ i + 3 == vertices.length ? 0 : i + 3 ];
            Vector3d edge1 = new Vector3d();
            Vector3d edge2 = new Vector3d();
            edge1.sub( p2, p1 );
            edge2.sub( p4, p1 );
            // subtract the two to get the edge vector
            // edge vector can be skipped since we can get the normal by cross product.
            // get either perpendicular vector
            Vector3d normal = new Vector3d();
            normal.cross( edge2, edge1 );
            normal.normalize();
            axes[ i ] = normal;
        }
        return axes;
    }
    
    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;
    }
    
    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 ) };