慢速移动3D球体到3D三角碰撞

时间:2012-08-19 02:25:48

标签: c++ 3d geometry collision-detection

所以,我编写了这个函数来检查3D空间中三角形和球体类之间的碰撞。这些物体在它们被认为时会碰撞一百万次。我想知道是否有人可以仔细检查我的数学?我用C ++编写代码。我的三角形类有一个联合,您可以使用A,B和C或P0,P1和P2访问顶点。使用的方法是从三角形创建一个平面,并将球体的中心投影到平面上。完成此操作后,将针对三角形的三个平面边缘检查投影点。我一直在看这个!非常感谢任何和所有帮助。

// create the edges
float3 TriEdge0 = tVerts.m_P1 - tVerts.m_P0;// 0 -> 1
float3 TriEdge1 = tVerts.m_P2 - tVerts.m_P1;// 1 -> 2
float3 TriEdge2 = tVerts.m_P0 - tVerts.m_P2;// 2 -> 0
float3 TriPlaneNormal = TriEdge1.Cross(TriEdge2);

// normalize
TriPlaneNormal /= TriPlaneNormal.Magnitude();

float fTriPlaneOffset = tVerts.m_A.Dot(TriPlaneNormal);

// get vector from point on plane to sphere center
float3 TriToSphereCenter = pSphere->GetCenter() - tVerts.m_A;

// distance between the sphere and the triangle plane
float fDistanceToPlane = TriToSphereCenter.Dot(TriPlaneNormal);

// project the sphere's center onto the triangle plane
float3 ProjectionVector = TriPlaneNormal * -fDistanceToPlane;
float3 ProjectedSphereOnPlane = pSphere->GetCenter() + ProjectionVector;


// use the point in triangle test to see if the projected point is in the triangle
    // if it is, then it is the closest point between the shapes

float3 TriEdge0Normal = TriEdge0.Cross(TriPlaneNormal);
float fTriPlane0Offset = tVerts.m_P0.Dot(TriEdge0Normal);

float3 TriEdge1Normal = TriEdge1.Cross(TriPlaneNormal);
float fTriPlane1Offset = tVerts.m_P1.Dot(TriEdge1Normal);

float3 TriEdge2Normal = TriEdge2.Cross(TriPlaneNormal);
float fTriPlane2Offset = tVerts.m_P2.Dot(TriEdge2Normal);

float3 ClosestPointToSphere;
float PositionOfProjectedPoint0 = TriEdge0Normal.Dot(ProjectedSphereOnPlane) - fTriPlane0Offset;
float PositionOfProjectedPoint1 = TriEdge1Normal.Dot(ProjectedSphereOnPlane) - fTriPlane1Offset;
float PositionOfProjectedPoint2 = TriEdge2Normal.Dot(ProjectedSphereOnPlane) - fTriPlane2Offset;

// if the point is in the triangle, it is the closest point
if (PositionOfProjectedPoint0 < 0.0f && PositionOfProjectedPoint1 < 0.0f 
    && PositionOfProjectedPoint2 < 0.0f )
{
    ClosestPointToSphere = ProjectedSphereOnPlane;
}
else    // find the closest edge
{
    // check each edge to see if it is in front of the plane 
        // if so, it is the closest edge
    float3 StartPoint;
    float3 EndPoint;
    float3 LineNormal;
    float3 LineSegment;

    if(PositionOfProjectedPoint0 > 0.0f)        // edge 0
    {
        StartPoint = tVerts.m_P0;
        EndPoint = tVerts.m_P1;
        LineNormal = TriEdge0Normal;
        LineSegment = TriEdge0;
    }
    else if (PositionOfProjectedPoint1 > 0.0f)  // edge 1
    {
        StartPoint = tVerts.m_P1;
        EndPoint = tVerts.m_P2;
        LineNormal = TriEdge1Normal;
        LineSegment = TriEdge1;
    }
    else if (PositionOfProjectedPoint2 > 0.0f)  // edge 2
    {
        StartPoint = tVerts.m_P2;
        EndPoint = tVerts.m_P0;
        LineNormal = TriEdge2Normal;
        LineSegment = TriEdge2;
    }

    // calculate a vector between the test point and the start point
        // and scale it by the distance between them
    float3 LineToTestPoint = ClosestPointToSphere - StartPoint;
    float fDistance = LineNormal.Dot(LineToTestPoint);

    // limit the closest point on the line to the given segment
    if (fDistance < 0.0f)
    {
        ClosestPointToSphere = StartPoint;
    }
    else if (fDistance > LineSegment.Magnitude())
    {
        ClosestPointToSphere = EndPoint;
    }
    else    // closest point is within line segment
    {
        float3 ScaledNormal = LineToTestPoint * fDistance;
        ClosestPointToSphere = StartPoint + ScaledNormal;
    }
}

// distance test between the closest point and the sphere's radius
float fDistance = (pSphere->GetCenter() - ClosestPointToSphere).Dot(
    pSphere->GetCenter() - ClosestPointToSphere);

// if squared radius is less than the distance between the projected point and the sphere, 
    // there is collision
if (fDistance < pSphere->GetRadius() * pSphere->GetRadius())
{
    return true;
}

// triangle is not colliding
return false;

1 个答案:

答案 0 :(得分:0)

在DirectX SDK的碰撞示例中查看XNACollision.cpp。提供了此碰撞测试(以及许多其他)的源代码。另外,我刚刚注意到DirectXCollisions.h最近替换了XNAMath.h等。请参阅此处http://msdn.microsoft.com/en-us/library/windows/desktop/ee418730(v=vs.85).aspx