허용 오차 계산


double DegenerateEdgeTolSq = DegenerateEdgeTolFactor * DegenerateEdgeTolFactor * 
                             SnapTolerance * SnapTolerance; 

최적화를 위해 squared 기준으로 연산한다.



짧은 엣지 찾기


TArray< int > EIDs;  
// 절단으로 새로 생성된 버텍스 체인들을 순회
for ( int ChainIdx = 0; ChainIdx < Cut.VertexChains[ MeshIdx ].Num(); )  
{  
    int ChainLen = Cut.VertexChains[ MeshIdx ][ ChainIdx ]; // 체인 길이
    int ChainEnd = ChainIdx + 1 + ChainLen;                 // 체인 끝 위치
    
    // 체인 내 연속된 버텍스 쌍들 검사
    for ( int ChainSubIdx = ChainIdx + 1; ChainSubIdx + 1 < ChainEnd; ChainSubIdx++ )  
    {  
        int VID[ 2 ]
        { 
            Cut.VertexChains[ MeshIdx ][ ChainSubIdx     ],
            Cut.VertexChains[ MeshIdx ][ ChainSubIdx + 1 ]
        };
        
        float distanceSquared = DistanceSquared
        (
            CutMesh[ MeshIdx ]->GetVertex( VID[ 0 ] ),
            CutMesh[ MeshIdx ]->GetVertex( VID[ 1 ] )
        )
         
        // 두 버텍스 사이 거리가 허용 오차보다 작으면 퇴화 에지로 판정
        if ( distanceSquared < DegenerateEdgeTolSq )  
        {  
            EIDs.Add( CutMesh[ MeshIdx ]->FindEdge( VID[ 0 ], VID[ 1 ] ) );  
        }  
    }  
    ChainIdx = ChainEnd;  
}  


엣지 병합


TSet< int > AllEIDs( EIDs );  
for ( int Idx = 0; Idx < EIDs.Num(); Idx++ )  
{  
    int EID = EIDs[ Idx ];
    
    if ( !CutMesh[ MeshIdx ]->IsEdge( EID ) ) // 이미 제거된 에지 
    {  
        continue;  
    }  
    
    FVector3d A, B;  
    CutMesh[ MeshIdx ]->GetEdgeV( EID, A, B );  
    
    if (DistanceSquared( A, B ) > DegenerateEdgeTolSq ) // 재검사
    {  
        continue;  
    }  
    FIndex2i EV = CutMesh[ MeshIdx ]->GetEdgeV( EID );  
    
    // UV Seam에 있는 버텍스는 함부로 제거하면 안됨
    if ( CutMesh[ MeshIdx ]->HasAttributes() &&
         CutMesh[ MeshIdx ]->Attributes()->IsSeamVertex( EV.B, false ) )  
    {  
        Swap( EV.A, EV.행
    FDynamicMesh3::FEdgeCollapseInfo CollapseInfo;  
    EMeshResult CollapseResult = CutMesh[ MeshIdx ]->CollapseEdge( EV.A, EV.B, .5, CollapseInfo );  
    
    if ( CollapseResult == EMeshResult::Ok )  
    {  
        // 성공시 새로 생성된 엣지들도 후보에 추가
        for ( int i = 0; i < 2; i++ )  
        {  
            if ( AllEIDs.Contains( CollapseInfo.RemovedEdges[ i ] ) )  
            {  
                int ToAdd = CollapseInfo.KeptEdges[ i ];  
                bool bWasPresent;  
                
                AllEIDs.Add( ToAdd, &bWasPresent );  
                
                if ( !bWasPresent )  
                {  
                    EIDs.Add( ToAdd ); // 새 엣지도 검사 대상에 추가
                }  
            }  
        }  
    }
}