そこで、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;