因此,我编写了这个函数来检查 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;