개요


삼각형과 평면의 교차 여부를 판정하는 알고리즘이다. 각 정점이 평면의 어느 쪽에 있는지만 알면, 평면이 삼각형을 관통하는지 판별할 수 있다. 평면의 방정식을 통해 삼각형의 각 정점을 부호 있는 거리로 계산한다. 계산된 3개의 부호있는 거리를 통해 삼각형과 평면의 교차 판정을 알 수 있다.

  • 세 정점이 모두 같은 쪽에 있으면 (d1, d2, d3의 부호가 모두 같음) → 교차 안 함
  • 정점들이 양쪽에 나뉘어 있으면 (부호가 다름) → 교차함
  • 하나 이상의 정점이 평면 위에 있으면 (d = 0) → 접촉 또는 교차


구현 코드


단일 정점 거리 계산
// 정점에서 평면까지의 부호 있는 거리 계산
float SignedDistance( const FVector& Vertex, const FVector& PlanePoint, const FVector& PlaneNormal )
{
    return ( Vertex - PlanePoint ).Dot( PlaneNormal );
}

삼각형-평면 교차 판정
bool IsTriangleIntersectPlane
(
    const FVector& V0, const FVector& V1, const FVector& V2,  // 삼각형의 세 정점
    const FVector& PlanePoint, const FVector& PlaneNormal     // 평면 정의
)
{
    // 각 정점에서 평면까지의 부호 있는 거리 계산
    float d0 = SignedDistance( V0, PlanePoint, PlaneNormal );
    float d1 = SignedDistance( V1, PlanePoint, PlaneNormal );
    float d2 = SignedDistance( V2, PlanePoint, PlaneNormal );
 
    // 부호 확인을 위한 임계값 (부동소수점 오차 고려)
    const float Epsilon = 1e-6f;
 
    // 정점이 평면 위에 있는지 확인
    bool bV0OnPlane = FMath::Abs( d0 ) < Epsilon;
    bool bV1OnPlane = FMath::Abs( d1 ) < Epsilon;
    bool bV2OnPlane = FMath::Abs( d2 ) < Epsilon;
 
    // 하나 이상의 정점이 평면 위에 있으면 접촉으로 판정
    if ( bV0OnPlane || bV1OnPlane || bV2OnPlane )
    {
        return true;
    }
 
    // 모든 정점이 같은 쪽에 있는지 확인
    bool bAllPositive = ( d0 > 0 ) && ( d1 > 0 ) && ( d2 > 0 );
    bool bAllNegative = ( d0 < 0 ) && ( d1 < 0 ) && ( d2 < 0 );
 
    // 같은 쪽에 있으면 교차하지 않음
    if ( bAllPositive || bAllNegative )
    {
        return false;
    }
 
    // 정점들이 양쪽에 나뉘어 있으면 교차함
    return true;
}