[출처 : http://assimp.sourceforge.net/index.html]
| cs |
살펴보면 벡터형태로 저장되어 있는 m_meshes를 리사이즈 시켜서 공간을 확보하는데,
이 때 m_pScene에서 가지고 있는 mNumMeshes란 변수를 통해 리사이즈를 시켜줍니다.
해당 변수는 내가 읽어들인 모델데이터가 몇개의 매쉬를 가지고 있는지 표기하고 있는 것입니다.
이처럼 assimp 라이브러리의 경우 모델데이터를 읽어드리고, 라이브러리 자체적으로 데이터를 변형함과 동시에 사용자가 해당 데이터를 이용하기 편하게 여러가지 변수들 또한
제공하고 있습니다.
여러가지 변수들이 존재하지만 개인적으로 자주 사용하게 되었던 것들을 정리하였습니다.
- mNumMeshes //매쉬 갯수
- mNumMaterials //메터리얼 갯수
- mNumAnimations //애니메이션 갯수
- mRootNode //루트노드
- mMeshes //실제 저장된 매쉬 데이터(포인터의 형태로 저장됨)
- mAnimation //실제 저장된 애니메이션 데이터(포인터의 형태로 저장됨)
만약 해당 모델에 애니메이션 데이터가 포함되어 있지 않을 경우 mNumAnimations에는
0이 저장되고, mAnimation은 nullptr인 것으로 처리가 됩니다.
0이 저장되고, mAnimation은 nullptr인 것으로 처리가 됩니다.
그러면 위에서 이어서 코드를 살펴보면 m_meshes의 공간을 확보하고, 매터리얼의 갯수를 현재 모델의 매터리얼 갯수로 초기화를 시켜줍니다.
그 후 InitScene() 함수를 수행합니다.
아래 코드는 InitScene() 함수 입니다.
void LoadModel::InitScene()
{
for (UINT i = 0; i < m_meshes.size(); ++i) {
const aiMesh* pMesh = m_pScene->mMeshes[i];
InitMesh(i, pMesh);
m_numVertices += (UINT)m_meshes[i].m_vertices.size();
}
}
| cs |
수행합니다.
그리고 추가로 m_numVertices변수를 계속 갱신해주는데 이는 이 변수가 해당모델의 총
버텍스 갯수를 가지기 때문입니다.
버텍스 갯수를 가지기 때문입니다.
단순히 특정 매쉬의 버텍스 갯수를 알고싶으면 m_meshes[해당인덱스].m_vertices.size()를 호출하면 됩니다. (m_vertices는 이전 포스터에서 선언한 벡터입니다.)
그러면 InitMesh()함수를 살펴봅시다.
void LoadModel::InitMesh(UINT index, const aiMesh * pMesh)
{
m_meshes[index].m_vertices.reserve(pMesh->mNumVertices);
m_meshes[index].m_indices.reserve(pMesh->mNumFaces * 3);
//삼각형이므로 면을 이루는 꼭지점 3개
for (UINT i = 0; i < pMesh->mNumVertices; ++i) {
XMFLOAT3 pos(&pMesh->mVertices[i].x);
XMFLOAT3 normal(&pMesh->mNormals[i].x);
XMFLOAT2 tex;
if (pMesh->HasTextureCoords(0))
tex = XMFLOAT2(&pMesh->mTextureCoords[0][i].x);
else
tex = XMFLOAT2(0.0f, 0.0f);
const vertexDatas data(pos, normal, tex);
m_meshes[index].m_vertices.push_back(data);
}
for (UINT i = 0; i < pMesh->mNumFaces; ++i) {
const aiFace& face = pMesh->mFaces[i];
m_meshes[index].m_indices.push_back(face.mIndices[0]);
m_meshes[index].m_indices.push_back(face.mIndices[1]);
m_meshes[index].m_indices.push_back(face.mIndices[2]);
}
}
| cs |
해당함수는 aiMesh에서 필요한 데이터를 추출하는 함수입니다.
여기서 필요한 데이터라 함은
버텍스의 위치, 법선벡터, 텍스쳐매핑좌표, 그리고 마지막으로 인덱스가 있습니다. (4가지)
위의 그림을 살펴보면 회색 점은 버텍스이고, 까만 면은 폴리곤입니다.
매쉬의 경우 폴리곤으로 이루어져 있습니다. (assimp에서는 face로 표현)
즉 육각형 큐브의 경우 6개의 면이 아닌 12개의 면을 가지는 것이지요. (12개의 삼각형 폴리곤)
여기서 문제가 한가지 생깁니다. 육각형의 경우 점을(버텍스를) 8개만 가지면 되는데
이를 삼각형으로 표현하려고 하니 36개의 점이 필요하게 됩니다. 또한 이 36개의 점들은 매우 많이 중복되는 점들이죠.
이를 해결하기 위한 것이 인덱스입니다.
버텍스는 8개만 저장하지만, 이를 조합하는 순서를 별도로 인덱싱해서 저장해두어서
쓸데없이 중복되는 데이터를 방지하는 것입니다.
위의 함수를 간단히 살펴보면 매쉬에 버텍스 갯수만큼 for루프를 수행하면서
버텍스 좌표, 벅선벡터, 그리고 텍스쳐매핑좌표가 존재할 경우에만 이를 저장하고,
벡터에 push_back을 해주는 것을 볼 수 있습니다.
벡터에 push_back을 해주는 것을 볼 수 있습니다.
큐브에 예를 들면 총 8개의 버텍스를 저장해둔다고 볼 수 있습니다.
이어서 Face의 갯수만큼 for루프를 수행하는 것을 볼 수 있습니다.
앞서 언급한 것처럼 Face는 폴리곤입니다. 그리고 이것은 삼각형의 형태입니다.
정확하게 말하면 대부분의 모델데이터의 경우 삼각형의 형태입니다. 하지만 드물게
사각형인 경우도 있습니다. 그러면 어떻게 해야할까요?
정확하게 말하면 대부분의 모델데이터의 경우 삼각형의 형태입니다. 하지만 드물게
사각형인 경우도 있습니다. 그러면 어떻게 해야할까요?
이전 게시글에서 aiImportFile 함수에서 여러가지 옵션을 선언한 것을 기억하실 것입니다.
그 때 제가 aiProcess_Triangulat를 꼭 사용하라고 언급했었습니다.
해당 플래그는 혹시나 삼각형이 아닌 형태로 폴리곤이 저장되어 있는 경우 이를 파일을 불러드릴 때
삼각형으로 나눠주는 옵션입니다. (사각형 -> 삼각형 2개)
해당 플래그는 혹시나 삼각형이 아닌 형태로 폴리곤이 저장되어 있는 경우 이를 파일을 불러드릴 때
삼각형으로 나눠주는 옵션입니다. (사각형 -> 삼각형 2개)
하지만 이는 어디까지나 보험차원이고 권장사항은 처음부터 삼각형의 폴리곤을 가진
모델데이터를 사용하는 것입니다.
모델데이터를 사용하는 것입니다.
그럼 다시 Face의 갯수만큼 for루프하는 부분을 살펴봅시다.
앞서 언급한 것처럼 Face는 삼각형인 것이 보장이 되고, 그러므로 단순히 해당 Face의 0번 부터 2번
인덱스까지를 m_indices 벡터에 push_back시켜주면 됩니다.
인덱스까지를 m_indices 벡터에 push_back시켜주면 됩니다.
여기까지 완료하면 내가 불러오고자 하는 모델데이터의 모든버텍스와 이를 위한 인덱스까지 모두 추출한 것입니다.
이제 여러분이 미리 선언해둔 버텍스 버퍼, 인덱스 버퍼를 이 데이터를 이용해서 갱신시켜주면
됩니다.
됩니다.
앞서 언급했던 것처럼 이 게시글은 다이렉트X에 대한 기본 지식을 요하기 때문에 버텍스 버퍼를
어떻게 만드는지, 인덱스 버퍼를 어떻게 만드는지에 대한 것을 게시하지 않을
예정입니다.
어떻게 만드는지, 인덱스 버퍼를 어떻게 만드는지에 대한 것을 게시하지 않을
예정입니다.
다음 게시글들에서는 셰이더 코드에서 해당 데이터들을 어떻게 다루는지 간단하게 설명하고,
애니메이션 데이터를 추출하는 방법에 대해 게시하려고 합니다.
애니메이션 데이터를 추출하는 방법에 대해 게시하려고 합니다.