model_loading
Assimp
Model-Loading/Assimp
지금까지 모든 씬에서 우리는 작은 컨테이너 친구와 광범위하게 놀아왔지만, 시간이 지나면서 가장 친한 친구조차도 조금 지루해질 수 있습니다. 더 큰 그래픽 응용 프로그램에는 일반적으로 정적 컨테이너보다 보기에 훨씬 더 예쁜 많은 복잡하고 흥미로운 모델들이 있습니다. 그러나 컨테이너 객체와 달리, 집, 차량 또는 인간과 같은 캐릭터와 같은 복잡한 형태의 모든 정점, 노말 및 텍스처 좌표를 수동으로 정의할 수는 없습니다. 대신 우리가 원하는 것은 이러한 모델을 응용 프로그램으로 가져오는 것입니다; Blender, 3DS Max 또는 Maya와 같은 도구에서 3D 아티스트가 신중하게 디자인한 모델입니다.
이러한 소위 3D 모델링 도구는 아티스트가 복잡한 형태를 만들 수 있게 하고 텍스처 매핑이라고 하는 과정을 통해 텍스처를 적용할 수 있게 합니다. 그런 다음 그들의 도구는 자동으로 모든 버텍스 좌표, 버텍스 노말 및 텍스처 좌표를 저장하여 이러한 모델을 내보낸 모델 파일로 생성합니다. 이러한 방식으로 아티스트는 광범위한 도구 세트를 가지고 있어 다시 버텍스를 신경 쓰지 않고도 고품질 모델을 만들 수 있습니다. 모든 기술적인 측면은 내보낸 모델 파일에 숨겨져 있습니다. 우리 프로그래머들은 이러한 내보낸 모델 파일을 관리해야 합니다.
이러한 내보낸 모델 파일을 구문 분석하고 모든 관련 정보를 추출하여 OpenGL이 이해하는 형식으로 저장할 수 있도록 하는 것이 우리의 임무입니다. 일반적인 문제는 각각 자체적인 고유한 방식으로 모델 데이터를 내보내는 수십 가지 다른 파일 형식이 있다는 것입니다. Wavefront .obj와 같은 모델 형식은 모델 색상 및 디퓨즈/스페큘러 맵과 같은 사소한 재질 정보만 포함된 모델 데이터만 포함하는 반면, XML 기반 Collada 파일 형식과 같은 모델 형식은 극도로 광범위하며 모델, 조명, 여러 유형의 재질, 애니메이션 데이터, 카메라, 완전한 씬 정보 등을 포함합니다. Wavefront 객체 형식은 일반적으로 구문 분석하기 쉬운 모델 형식으로 간주됩니다. 이러한 파일 형식의 데이터가 어떻게 구조화되어 있는지 보려면 적어도 한 번은 Wavefront의 위키 페이지를 방문하는 것이 좋습니다. 이것은 모델 파일 형식이 일반적으로 어떻게 구조화되어 있는지에 대한 기본적인 인식을 제공할 것입니다.
전반적으로 많은 다른 파일 형식이 있으며 그들 사이에 일반적인 공통 구조가 일반적으로 존재하지 않습니다. 따라서 이러한 파일 형식에서 모델을 가져오려면 가져오려는 각 파일 형식에 대해 직접 임포터를 작성해야 합니다. 다행히도, 이를 위한 라이브러리가 있습니다.
모델 로딩 라이브러리
매우 인기 있는 모델 가져오기 라이브러리 중 하나는 Open Asset Import Library의 약자인 Assimp라고 불립니다. Assimp는 모든 모델의 데이터를 Assimp의 일반화된 데이터 구조로 로드하여 수십 가지 다른 모델 파일 형식을 가져올 수 있습니다(일부는 내보내기도 할 수 있습니다). Assimp가 모델을 로드하자마자 Assimp의 데이터 구조에서 필요한 모든 데이터를 검색할 수 있습니다. Assimp의 데이터 구조는 가져온 파일 형식의 유형과 관계없이 동일하게 유지되기 때문에 모든 다른 파일 형식으로부터 우리를 추상화합니다.
Assimp를 통해 모델을 가져올 때 가져온 모델/씬의 모든 데이터를 포함하는 씬 객체에 전체 모델을 로드합니다. 그런 다음 Assimp는 각 노드가 씬 객체에 저장된 데이터에 대한 인덱스를 포함하는 노드 모음을 가지며, 각 노드는 임의 개수의 자식을 가질 수 있습니다. Assimp 구조의 (단순화된) 모델은 아래와 같습니다:

- 씬/모델의 모든 데이터는 모든 재질과 메시와 같은 Scene 객체에 포함되어 있습니다. 또한 씬의 루트 노드에 대한 참조를 포함합니다.
- 씬의 루트 노드는 자식 노드를 포함할 수 있으며(다른 모든 노드와 마찬가지로) 씬 객체의 mMeshes 배열에 있는 메시 데이터를 가리키는 인덱스 세트를 가질 수 있습니다. 씬의 mMeshes 배열은 실제 Mesh 객체를 포함하며, 노드의 mMeshes 배열에 있는 값은 씬의 메시 배열에 대한 인덱스일 뿐입니다.
- Mesh 객체 자체는 렌더링에 필요한 모든 관련 데이터를 포함합니다. 버텍스 위치, 노말 벡터, 텍스처 좌표, 면 및 객체의 재질을 생각해보세요.
- 메시는 여러 면을 포함합니다. Face는 객체의 렌더 프리미티브(삼각형, 사각형, 점)를 나타냅니다. 면은 프리미티브를 형성하는 버텍스의 인덱스를 포함합니다. 버텍스와 인덱스가 분리되어 있기 때문에 인덱스 버퍼를 통해 쉽게 렌더링할 수 있습니다(Hello Triangle 참조).
- 마지막으로 메시는 객체의 재질 속성을 검색하는 여러 함수를 호스팅하는 Material 객체에도 연결됩니다. 색상 및/또는 텍스처 맵(디퓨즈 및 스페큘러 맵과 같은)을 생각해보세요.
우리가 하고 싶은 것은: 먼저 객체를 Scene 객체로 로드하고, 각 노드에서 해당 Mesh 객체를 재귀적으로 검색하고(각 노드의 자식을 재귀적으로 검색), 각 Mesh 객체를 처리하여 버텍스 데이터, 인덱스 및 재질 속성을 검색하는 것입니다. 그런 다음 결과는 단일 Model 객체에 포함하려는 메시 데이터 모음입니다.
메시
모델링 툴킷에서 객체를 모델링할 때, 아티스트는 일반적으로 단일 형태로 전체 모델을 만들지 않습니다. 일반적으로 각 모델에는 구성되는 여러 하위 모델/형태가 있습니다. 이러한 단일 형태 각각을 메시라고 합니다. 예를 들어 인간형 캐릭터를 생각해보세요: 아티스트는 일반적으로 머리, 사지, 옷, 무기를 모두 별도의 구성 요소로 모델링하고 결합된 모든 메시가 최종 모델을 나타냅니다. 단일 메시는 OpenGL에서 그릴 수 있는 단일 엔티티에 필요한 최소 데이터(버텍스 데이터, 인덱스 및 재질 속성)입니다. 모델(일반적으로) 여러 메시로 구성됩니다.
다음 챕터에서는 우리 자신의 Mesh 및 Model 클래스를 만들어 Assimp의 인터페이스를 사용하여 모델을 쉽게 로드하고 렌더링할 것입니다. Assimp로 모델을 로드할 때 여러 메시 객체로 분해하려면 검색된 각 메시를 자체 Mesh 객체로 변환해야 합니다. 다음 챕터에서 할 일은 바로 그것입니다.
Assimp 빌드하기
GitHub 페이지에서 Assimp를 다운로드하고 해당 버전을 선택할 수 있습니다. 이 글을 쓰는 시점에 사용된 Assimp 버전은 버전 3.1.1이었습니다. 미리 컴파일된 라이브러리가 모든 시스템에서 항상 작동하지 않기 때문에 라이브러리를 직접 컴파일하는 것이 좋습니다. CMake를 통해 라이브러리를 직접 컴파일하는 방법을 잊어버렸다면 Creating a window 챕터를 검토하십시오.
Assimp를 빌드하는 동안 몇 가지 문제가 발생할 수 있으므로, 여러분 중 일부가 동일한 오류를 겪을 경우를 대비하여 솔루션과 함께 여기에 적어두겠습니다:
- CMake가 DirectX 라이브러리 누락에 대한 구성 목록을 검색하는 동안 계속 오류를 제공하며 다음과 같은 메시지가 나타납니다:
Could not locate DirectX
CMake Error at cmake-modules/FindPkgMacros.cmake:110 (message): Required library DirectX not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.
여기서 해결책은 이전에 설치하지 않은 경우 DirectX SDK를 설치하는 것입니다. 여기에서 SDK를 다운로드할 수 있습니다.
- DirectX SDK를 설치하는 동안
s1023의 가능한 오류 코드가 나타날 수 있습니다. 그 경우 SDK를 설치하기 전에 먼저 C++ 재배포 가능 패키지를 제거해야 합니다.
구성이 완료되면 솔루션 파일을 생성하고, 열고, 라이브러리를 컴파일할 수 있습니다(릴리스 버전이든 디버그 버전이든 원하는 대로). 모든 LearnOpenGL 코드가 64비트이므로 64비트용으로 컴파일해야 합니다.
기본 구성은 Assimp를 동적 라이브러리로 빌드하므로 응용 프로그램의 바이너리와 함께 assimp.dll(또는 일부 접미사가 붙은)이라는 결과 DLL을 포함해야 합니다. 응용 프로그램의 실행 파일이 있는 동일한 폴더에 DLL을 복사하기만 하면 됩니다.
생성된 솔루션을 컴파일한 후 결과 라이브러리 및 DLL 파일은 code/Debug 또는 code/Release 폴더에 있습니다. 그런 다음 lib와 DLL을 적절한 위치로 이동하고 솔루션에서 링크하고 Assimp의 헤더를 include 디렉토리로 복사해야 합니다(헤더 파일은 Assimp에서 다운로드한 파일의 include 폴더에 있습니다).
지금까지 Assimp를 컴파일하고 응용 프로그램에 연결했어야 합니다. 아직도 보고되지 않은 오류가 발생하면 언제든지 댓글에서 도움을 요청하십시오.