버텍스 법선이 존재하지 않는 메쉬에 법선을 만드는 방법


<< 면 법선 구하기 >>

버텍스 법선을 구하기 위한 가장 간단한 방법은 삼각형의 면 법선을 찾고 이 면 법선을
버텍스 법선에 이용하는 것이다

버텍스 로 이루어진 삼각형이 있고, 버텍스 의 법선을 계산한다고 가정하자.

먼저 삼각형에 있는 두 개의 벡터를 계산한다.

다음은 면 법선이다.

각각의 버텍스 법선은 면 법선과 같으므로,

다음은 시계 방향 두르기를 하고 있는 삼각형의 세 버텍스 포인트에서 삼각형의 면 벡터를 계산해낸다.

void ComputeNormal (D3DXVECTOR3* p0, D3DXVECTOR3* p1, D3DXVECTOR3* p2, D3DXVECTOR3* out)
{
        D3DXVECTOR3 u = *p1 - *p0;
        D3DXVECTOR3 v = *p2 - *p0;

        D3DXVec3Cross (out, &u, &v);
        D3DXVec3Normalize (out, out);
}

삼각형의 면 법선을 버텍스 법선으로 이용하면 부드러운 결과물을 얻기 위해서는 버텍스
공유하는 메쉬 내 모든 삼각형의 면 법선을 찾은 다음, 모든 면 법선의 평균을 구하여  을 얻을 수 있다.
예를 들어 3개의 면 법선 을 공유하는 은 면 법선의 평균을 구하여 계산할 수 있다.

예를  변환 단계에서 버텍스 법선이 왜곡되는 현상이 발생할 수 있으므로,
D3DRS_NORMALIZENORMALS 렌더 상태를 활성화하여 변환 단계 이후에 Direct3D가
모든 법선을 다시 정리하도록 하는 것이 안전하다.

Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);



<< 버텍스 법선 생성하기 >>

HRESULT D3DXComputeNormals(
      LPD3DXBASEMESH pMesh,          // 법선을 계산하려는 메쉬
      const DWORD *pAdjacency          //  입력 인접 정보
);

ID3DXBaseMesh 메쉬는 D3DFVF_NORMAL 플래그가 없어야 한다.

만약 제공된 인접 정보가 있다면 중복된 버텍스를 제거하며, 인접 정보가 제공되지 않는다면 중복된 버텍스도 참조한 면의 평균으로 법선을 가진다.

D3DXComputeNormals를 이용하기 전에 먼저 메쉬를 복제하고 복제한 메쉬의 버텍스 포맷을 지정해야 한다.
사용예는 다음과 같다.

//D3DFVF_NORMAL 포맷이 없는 경우 실행
if ( ! (pMesh->GetFVF() & D3DFVF_NORMAL) )
{
     ID3DXMESH* pTempMesh = 0;
     pMesh->CloneMeshFVF(
          D3DXMESH_MANAGED,
	  pMesh->GetFVF() | D3DFVF_NORMAL, 
	  Device,
	  &pTempMesh );
	  
      //법선을 계산한다.
      D3DXComputeNormals( pTempMesh, 0);
      
      pMesh->Release();    //기존의 메쉬를 제거한다.
      pMesh = pTempMesh;   //새로운 메쉬를 법선과 함께 저장한다.
}          	  

 

[펌]
http://www.moon-labs.com
DirectX 9를 이용한 3D GAME 프로그래밍 입문 - 정보 문화사
http://www.thehavok.co.uk