2

そこで、3D 空間で三角形と球体クラスの間の衝突をチェックするために、この関数を作成しました。これらのオブジェクトは、想定されるときに 100 万回に 1 回衝突します。誰かが私の数学を再確認できるかどうか疑問に思っていましたか? 私はC++でコーディングしています。私の三角形クラスには、A、B、および C、または P0、P1、および P2 を使用して頂点にアクセスできる共用体があります。使用される方法は、三角形から平面を作成し、球の中心を平面に投影することです。これが完了すると、投影されたポイントが三角形の 3 つの平面エッジに対してチェックされます。私はこれをずっと見てきた!すべてのヘルプは非常に高く評価されています。

// 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;
4

1 に答える 1

0

DirectXSDKの衝突サンプルのXNACollision.cppを見てください。この衝突テスト(および他の多くのテスト)のソースコードが提供されています。また、DirectXCollisions.hが最近XNAMath.hなどに取って代わったことに気づきました。http://msdn.microsoft.com/en-us/library/windows/desktop/ee418730(v = vs.85).aspxを参照してください。

于 2012-10-21T23:47:34.633 に答える