개요


삼각형 내부에 새로운 정점을 삽입하여 1개의 삼각형을 3개로 분할한다.


center



Input


타입매개변수설명
intTriangleID분할할 삼각형의 ID
FVector3dBaryCoordinates새 정점의 무게중심 좌표 (w1, w2, w3)

분할할 삼각형의 ID와 무게중심 좌표를 입력받는다.



Output


타입매개변수설명
FPokeTriangleInfo&PokeResult분할 결과 정보를 저장할 출력 구조체

삼각형을 분할, FPokeTriangleInfo를 반환한다.



알고리즘


유효성 검사

if ( !IsTriangle( TriangleID ) )
{
    return EMeshResult::Failed_NotATriangle;
}

삼각형 ID가 유효한지 확인한다.


정점 정보 수집

FIndex3i tv = GetTriangle( TriangleID );   // 정점 [A, B, C]
FIndex3i te = GetTriEdges( TriangleID );   // 엣지 [eAB, eBC, eCA]
 
// 무게중심 좌표로 새 정점의 속성 보간
FVertexInfo vinfo;
GetTriBaryPoint( TriangleID, BaryCoordinates[ 0 ], BaryCoordinates[ 1 ], BaryCoordinates[ 2 ], vinfo );
int center = AppendVertex( vinfo );

FDynamicMesh3::GetTriBaryPoint()를 통해 정점 정보를 수집힌다.


새 엣지 생성

중심점(P)에서 각 꼭짓점으로 3개 엣지 생성:

// A-P, B-P, C-P 엣지 생성 (삼각형 연결은 아직 안 함)
int eaC = AddEdgeInternal( tv[ 0 ], center, -1, -1 );  // A-P
int ebC = AddEdgeInternal( tv[ 1 ], center, -1, -1 );  // B-P
int ecC = AddEdgeInternal( tv[ 2 ], center, -1, -1 );  // C-P
 
// 정점 참조 카운트 증가
VertexRefCounts.Increment( tv[ 0 ] );      // A
VertexRefCounts.Increment( tv[ 1 ] );      // B
VertexRefCounts.Increment( tv[ 2 ] );      // C
VertexRefCounts.Increment( center, 3 );    // P는 3개 삼각형에 사용

삼각형 재구성

원본 삼각형 재활용 (첫 번째 조각)
// ABC → ABP로 변경
SetTriangleInternal( TriangleID, tv[ 0 ], tv[ 1 ], center );
SetTriangleEdgesInternal( TriangleID, te[ 0 ], ebC, eaC );
// 정점: [A, B, P]
// 엣지: [eAB(원본), eBP(새), ePA(새)]
새 삼각형 2개 추가
// 두 번째 조각: BCP
int t1 = AddTriangleInternal( tv[ 1 ], tv[ 2 ], center, te[ 1 ], ecC, ebC );
// 정점: [B, C, P]
// 엣지: [eBC(원본), eCP(새), ePB(새)]
 
// 세 번째 조각: CAP
int t2 = AddTriangleInternal( tv[ 2 ], tv[ 0 ], center, te[ 2 ], eaC, ecC );
// 정점: [C, A, P]
// 엣지: [eCA(원본), eAP(새), ePC(새)]

엣지-삼각형 관계 업데이트

원본 엣지 수정
// eBC는 이제 OriginalTri 대신 t1에 속함
ReplaceEdgeTriangle( te[ 1 ], TriangleID, t1 );
 
// eCA는 이제 OriginalTri 대신 t2에 속함
ReplaceEdgeTriangle( te[ 2 ], TriangleID, t2 );
새 엣지에 삼각형 연결
// eAP: OriginalTri(ABP)와 t2(CAP)에 공유
SetEdgeTrianglesInternal( eaC, TriangleID, t2 );
 
// eBP: OriginalTri(ABP)와 t1(BCP)에 공유
SetEdgeTrianglesInternal( ebC, TriangleID, t1 );
 
// eCP: t1(BCP)와 t2(CAP)에 공유
SetEdgeTrianglesInternal( ecC, t1, t2 );

삼각형 그룹 복사

if ( HasTriangleGroups() )
{
    int g = TriangleGroups.GetValue()[ TriangleID ];
    TriangleGroups->InsertAt( g, t1 );
    TriangleGroups->InsertAt( g, t2 );
}

원본 삼각형의 그룹 ID를 새 삼각형들에도 적용한다.


결과 정보 저장

PokeResult.OriginalTriangle = TriangleID;
PokeResult.TriVertices = tv;                      // [A, B, C]
PokeResult.NewVertex = center;                    // P
PokeResult.NewTriangles = FIndex2i( t1, t2 );     // [BCP, CAP]
PokeResult.NewEdges = FIndex3i( eaC, ebC, ecC );  // [AP, BP, CP]
PokeResult.BaryCoords = BaryCoordinates;

어트리뷰트 업데이트 & 완료

// UV, 노멀 등 오버레이 어트리뷰트 업데이트
if ( HasAttributes() )
{
    Attributes()->OnPokeTriangle( PokeResult );
}
 
// 메시 변경 스탬프 업데이트
UpdateChangeStamps( true, true );
return EMeshResult::Ok;