게시하려고 합니다.
포스팅하기에 앞서 이 글을 읽으실 때는 DirectX에 대한 기본적인 지식이 있으셔야
이해하실 수 있을 것입니다.
이 글에 경우 DirectX12를 기반으로 설명할 것이고, 글을 보시는 분들이 버텍스버퍼가 무엇인지, 인덱스버퍼가 무엇인지에 대한 기본적인 지식이 있다는 가정 하에 글을 진행할
것입니다. (즉, 적어도 DirectX의 기본 세팅을 완료하고
까지는 완료한 상태여야 이해를 하시기 편할 것입니다.)
그럼 시작하겠습니다.
먼저 ASSIMP 홈페이지에 접속하셔서 ASSIMP 라이브러리를 다운받아야 합니다.
여러가지 버전이 존재하는데 저는 ver 3.1.1 윈도우 바이너리 데이터도 포함하는
파일을 내려받았습니다.
이 파일을 받는 이유는 라이브러리 제작자가 직접 라이브러리를 이용하여 제작한 모델
뷰어를 제공하고, 또 여러가지 포맷의 샘플 모델 데이터를 제공하기 때문입니다.
내려받은 파일 압축을 해제하면 많은 폴더가 존재하는데 여기서
- include 폴더
- bin32 혹은 bin64 폴더의 assimp.dll 파일
- lib32 혹은 lib64 폴더의 assimp.lib 파일
이 3가지를 자신의 프로젝트로 복사해옵니다.
32비트인지 64비트인지는 자신이 제작하는 응용프로그램에 맞추어 복사해오면 될
것입니다.
것입니다.
그 후 자신의 응용프로그램에서 미리컴파일된 헤더('stdafx.h') 혹은 자신이 모델을 다룬
코드 헤더파일에
위의 코드를 복사해줍니다.
(여기서 assimp\ 경로는 자신이 include폴더 내부의 소스코드를 위치시킨 경로)
코드 헤더파일에
#include "assimp\Importer.hpp"
#include "assimp\cimport.h"
#include "assimp\postprocess.h"
#include "assimp\scene.h"
#pragma comment(lib, "assimp.lib")
| cs |
(여기서 assimp\ 경로는 자신이 include폴더 내부의 소스코드를 위치시킨 경로)
여기까지 완료하면 assimp를 사용하기 위한 기본적인 설정을 완료한 것입니다.
위 사진은 앞선 포스터에서 언급한 ASSIMP의 모델데이터 구조입니다.
보시는 바와 같이 최상단에 aiScene이 위치하고, 여기에 매쉬, 애니메이션, 노드가
저장되는 형태입니다.
저장되는 형태입니다.
일단 다른 것은 무시하고 매쉬에 집중해봅시다.
모델은 매쉬로 이루어져 있습니다. (1개 이상의 매쉬)
또 매쉬는 매쉬의 이름, 노말정보, 버텍스정보, 뼈정보, 면(face)정보로 이루어져 있습니다.
위의 그림에는 안나와있지만 텍스쳐 맵핑을 위한 정보 또한 가지고 있습니다.
이 데이터들은 우리가 모델데이터를 화면상에 랜더링하기 위해 필요한 정보들입니다.
먼저 이 정보를 저장하기 위한 구조체입니다.
위의 구조체는 버텍스정보, 노말정보, 텍스쳐매핑정보를 가지는 구조체입니다.
모델은 매쉬로 이루어져 있습니다. (1개 이상의 매쉬)
또 매쉬는 매쉬의 이름, 노말정보, 버텍스정보, 뼈정보, 면(face)정보로 이루어져 있습니다.
위의 그림에는 안나와있지만 텍스쳐 맵핑을 위한 정보 또한 가지고 있습니다.
이 데이터들은 우리가 모델데이터를 화면상에 랜더링하기 위해 필요한 정보들입니다.
먼저 이 정보를 저장하기 위한 구조체입니다.
struct vertexDatas
{
XMFLOAT3 m_pos;
XMFLOAT3 m_normal;
XMFLOAT2 m_tex;
vertexDatas() {}
vertexDatas(XMFLOAT3& pos, XMFLOAT3& normal, XMFLOAT2& tex) :
m_pos(pos), m_normal(normal), m_tex(tex)
{ }
}
| cs |
하지만 이것만으로는 부족하죠. 다이렉트상에서 모델을 랜더링하기 위해서는
버텍스 조합 순서, 즉 인덱스정보도 필요합니다.
버텍스 조합 순서, 즉 인덱스정보도 필요합니다.
struct mesh
{
vector<vertexDatas> m_vertices;
vector<int> m_indices;
UINT m_materialIndex;
mesh() {
m_materialIndex = 0;
}
};
| cs |
위의 구조체는 매쉬의 정보를 담는 구조체입니다.
(vector의 경우 stl의 그 vector 입니다.)
매쉬의 경우 버텍스로 이루어져 있고, 이 버텍스를 조합하기 위한 인덱스 정보 또한 가지고 있습니다.
추가로 매쉬를 위한 매터리얼까지 저장하는 형태로 설계를 합니다.
class LoadModel
{
private:
const aiScene* m_pScene; //모델 정보
vector<mesh> m_meshes; //매쉬 정보
vector<pair<string, Bone>> m_Bones; //뼈 정보
UINT m_numVertices;
UINT m_numMaterial;
public:
LoadModel(const string& fileName);
~LoadModel();
void InitScene();
void InitMesh(UINT index, const aiMesh* pMesh);
void SetMeshes(ID3D12Device *pd3dDevice, ID3D12GraphicsCommandList *pd3dCommandList);
ModelMesh** getMeshes() { return m_ModelMeshes.data(); }
UINT getNumMesh() const { return (UINT)m_meshes.size(); }
};
| cs |
LoadModel 클래스는 앞서 선언한 구조체를 기반으로 실제로 모델데이터를 읽어오기 위한 클래스입니다.
클래스를 살펴보면 크게
- 모델의 정보를 담기 위한 m_pScene
- 매쉬의 정보를 담기 위한 m_meshes
로 이루어져 있습니다.
LoadModel::LoadModel(const string& fileName)
{
m_pScene = aiImportFile(fileName.c_str(), aiProcess_JoinIdenticalVertices | // 동일한 꼭지점 결합, 인덱싱 최적화
aiProcess_ValidateDataStructure | // 로더의 출력을 검증
aiProcess_ImproveCacheLocality | // 출력 정점의 캐쉬위치를 개선
aiProcess_RemoveRedundantMaterials | // 중복된 매터리얼 제거
aiProcess_GenUVCoords | // 구형, 원통형, 상자 및 평면 매핑을 적절한 UV로 변환
aiProcess_TransformUVCoords | // UV 변환 처리기 (스케일링, 변환...)
aiProcess_FindInstances | // 인스턴스된 매쉬를 검색하여 하나의 마스터에 대한 참조로 제거
aiProcess_LimitBoneWeights | // 정점당 뼈의 가중치를 최대 4개로 제한
aiProcess_OptimizeMeshes | // 가능한 경우 작은 매쉬를 조인
aiProcess_GenSmoothNormals | // 부드러운 노말벡터(법선벡터) 생성
aiProcess_SplitLargeMeshes | // 거대한 하나의 매쉬를 하위매쉬들로 분활(나눔)
aiProcess_Triangulate | // 3개 이상의 모서리를 가진 다각형 면을 삼각형으로 만듬(나눔)
aiProcess_ConvertToLeftHanded | // D3D의 왼손좌표계로 변환
aiProcess_SortByPType); // 단일타입의 프리미티브로 구성된 '깨끗한' 매쉬를 만듬
if (m_pScene) {
m_meshes.resize(m_pScene->mNumMeshes);
m_numMaterial = m_pScene->mNumMaterials;
m_numBones = 0;
InitScene();
m_ModelMeshes.resize(m_meshes.size());
}
}
| cs |
생성자에서는 m_pScene에 실제 모델데이터를 불러와 임포트시켜줍니다.
이 때 사용하는 함수는 aiImportFile입니다.
이 때 사용하는 함수는 aiImportFile입니다.
인자값으로 경로값을 포함한 파일이름과 설정값을 가집니다.
(설정에 대해서는 위의 코드에 주석으로 달아놓았습니다.)
(설정에 대해서는 위의 코드에 주석으로 달아놓았습니다.)
이때 중요한 것은 반드시 aiProcess_Triangulat를 사용해야 합니다.
대부분의 모델러가 모델을 제작할 때 삼각형을 기준으로 제작하기에 일반적인 경우에문제가 없으나 특수한 경우를 위해서는 꼭 처리를 해주는 것이 좋습니다.
대부분의 모델러가 모델을 제작할 때 삼각형을 기준으로 제작하기에 일반적인 경우에문제가 없으나 특수한 경우를 위해서는 꼭 처리를 해주는 것이 좋습니다.
사용자가 DirectX 환경에서 작업을 하는 경우 aiProcess_ConvertToLeftHanded를 사용하여 왼손좌표계로 바꿔주는 것도 필요할 수 있습니다.
위의 함수를 이용하여 모델데이터를 불러오는 데 성공하였을 경우 m_pScene에는
실제 모델의 데이터가 저장되었을 것입니다.
실제 모델의 데이터가 저장되었을 것입니다.
혹여나 로딩을 못했을 경우 m_pScene은 nullptr일 것이고, 빈 포인터에서 의미없는 행위를 수행하지 않기 위해 if문을 통해 조건에 만족했을 경우에만 초기화작업을 수행하도록 설계를 해주었습니다.
여기까지 수행하였으면 모델데이터를 불러오기 위한 기본설정 및 클래스설계를
마치고, 실제로 모델데이터를 불러오는 데 성공한 것입니다.
마치고, 실제로 모델데이터를 불러오는 데 성공한 것입니다.
실제로 응용프로그램에서 필요한 데이터(버텍스, 인덱스 등...)를 불러오는 방법에
대해서는 다음 게시글에서 설명하도록 하겠습니다.
대해서는 다음 게시글에서 설명하도록 하겠습니다.
ㄴㅁㅇ
답글삭제잘 읽었습니다.
답글삭제좋은 글 포스팅 해주셔서 감사합니다.