OpenGL 3.3+에서 PMX와 FBX 렌더링
해당 프로젝트와 블로그는 OBJ, PMX, FBX 파일을 렌더링하는 방법에 대해서 설명합니다.
최근 반년동안 삽질한 내용을 정리하고, 새로 프로젝트를 해보려고 합니다. 그전에 일단 삽질했던 내용을 공유합니다. OBJ, MMD(PMX), FBX 파일을 직접 렌더링해보고 싶으신 분들이 저와 같은 시행착오를 겪지 않기를 바랍니다. 해당 코드는
https://github.com/hyunjun529/SECA/releases/tag/1.0에서 받아서 실행해보실 수 있습니다.
SubMesh(서브메시)
PMX 렌더링
FBX 렌더링
해당 부분 구현 코드는 아래 링크에서 확인할 수 있습니다.
https://github.com/hyunjun529/SECA/tree/release/v1.0/Engine/format/FBX
공식 문서는 일단 아래 링크들을 참조했습니다. 먼저 해당 문서들을 간략히 보시는 것을 추천드립니다.
FBX Scene,
FBX nodes,
FBX Mesh
앞으로 사용할 용어, FBX SDK 내의 클래스들을 먼저 정리합니다.
FbxManager : FBX SDK를 사용하는 컨텍스트입니다.
FbxIOSettings : FBX SDK가 파일을 읽어올 때 사용합니다.
FbxScene : 한 Scene으로, 일반적인 Scene을 생각하시면 됩니다.
FbxAxisSystem : 좌표 시스템을 변환해준다고 합니다(실제로 동작이 잘 안됩니다)
FbxNode : FBX 파일을 이루고 있는 한 단위입니다.
FbxMesh : FBX Node의 일종으로 Mesh입니다.
FbxGeometryElement : Mesh 내에 Vertex Position, Normal, Indices 등의 타입을 지정합니다. 열거형입니다.
FbxGeometryElementUV : Texture, Coord나 각 메시의 마테리얼 관련된 부분이 여기 들어 있습니다. 이건 열거형이 아니라 클래스입니다.
그리고 변수 중에 이런 녀석들이 있는데, 이건 FBX가 단순히 게임 엔진에서만 사용되는게 아니라 다양한 곳에서 사용되어 왔기 때문으로 추정됩니다. 같은 메모리를 참조하면서도 접근하는 클래스나 인터페이스에 따라서 각기 다르게 불리는 경우가 있으니 주의해주세요.
제 경험상 Polygon과 ControlPoint의 Triangle Mesh는 동일한 Scene내 메모리 영역을 사용했습니다.
애니메이션(AnimStack)이 적용되지 않은 기본 자세는 Geometry Deformations이 적용되지 않은 기본 스켈레톤으로 부릅시다. 기본적으로 FBX는 애니메이션을 위한 포맷이기 때문에 Mesh 하나를 부를려고 해도 PMX와 달리 복잡한 구조를 갖습니다. 예를들어 Mesh를 렌더링하기 위해 Mesh, Texture, Material, Element Indices를 불러오는 부분이 전부 다릅니다.
Axis에 대해서는 아래 그림을 참조
포기하시면 편합니다. 실제로 구현해보면 MMD, OBJ, FBX, OpenGL이 다 꼬여서 조금 힘들겠지만 중요한 부분은 FbxAxisSystem에 의존하지 않는게 편합니다. 특정 부분에서 적용되지 않는 버그가 존재합니다. 아마 Scene으로 재생을 해야 적용되는거 같습니다.
제가 구현한 부분에 대해서 정리하자면 Geometry Deformation이 적용되지 않은 기본 Mesh를 렌더링했다고 볼 수 있습니다.
MMD에 대해서
pmx의 라이센스에 관해서는 아래 정보들을 참조하세요.
공식 사이트 :
https://www6.atwiki.jp/vpvpwiki/pages/13.html
MMD는 VPVP Wiki 기준으로 상업적 이용 및 재배포를 금지한다. 그리고 배포된 모델(pmx)나 애니메이션(vmd)은 창작자가 같이 동봉한 readme.txt에 따른다.
MMD, Unity 관련 저작권 사건 :
http://creativefreaks.net/?p=1705
readme.txt를 읽기 힘들게 만든 점이 문제가 된 사례입니. 또 모델러나 애니메이터의 저작권이 파일 포맷을 변환하거나 개조할 경우 미묘해지는데, 이 부분은 아직 회색지대로 남아있다고 하니 조심하셔야 할 것 같습니다.
라이센스에 비교적 자유롭거나 가장 널리 사용되는 PMX는 아래와 같습니다.
먼저 츠미식과 Tda식이 가장 널리 쓰입니다. 대부분 개조 파일도 해당 식을 개조한 버전인 경우가 많습니다.
그리고 가장 가벼운 파일은 three.js의 LowPoly 미쿠입니다. :
https://github.com/mrdoob/three.js/tree/master/examples/models/mmd#readme
해당 파일이 라이센스에 가장 자유롭습니다.
또 비상업적 목적, 개인 목적으로는 키즈나 아이가 퀄리티가 제일 높습니다. :
https://kizunaai.com/ 그리고 Tda 본인이 감수를 한다는 이야기도 있고 구조가 워낙 깔금하고 "영어"로 되어있어서 매우 유용합니다.
pmd 포맷은 아래 링크에서 분석된 파일이 있습니다.
http://mikumikudance.wikia.com/wiki/MMD:Polygon_Model_Data
pmx 포맷은 아래 링크를 참조해주세요, 단 실제로 거의 사용되지 않는 내용들도 있습니다.
PMX 2.0 :
https://gist.github.com/DeXP/16ccdd09841bdc1961e0
PMX 2.1 :
https://gist.github.com/felixjones/f8a06bd48f9da9a4539f
PMX weight map은 아래 링크를 참조해주세요. 실제로 사용되지 않는 방식이 같이 설명되어 있습니다.
https://learnmmd.com/http:/learnmmd.com/pmxe-weight-painting/
VMD 포맷은 MMD에서 애니메이션을 담당하는 부분인데, FBX의 경우 한 파일내 AnimStack으로 관리되지만, MMD는 이 구조가 분리되어 있어서 더 사용하기 쉽습니다. 카메라도 여기에 포함되어 있음을 주의해주세요.
http://mikumikudance.wikia.com/wiki/VMD_file_format
C++, WebGL에서 실제로 구현하는 방법에 대해서는 saba나 three.js를 참조하시면 좋습니다. 그리고 MMD에선 강체와 유체가 사용되는데, 이는 Bullet Physics를 사용합니다. 하지만 강체만 사용하는데다가 Bullet의 버전 문제도 있으니 MMD 프로그램의 라이브러리 부분을 확인해보시면 됩니다. MMM의 경우 MMD와 다른 버전을 사용하고 있어 결과의 차이가 발생하기도 합니다. MMD Bridge와 IM4U를 사용한 UE4와 Unity Mechanim, 그리고 three.js 의 경우 방식이 제각각입니다.
UE4 : Bullet Phtysics를 백그라운드 재생, 머리카락 등의 강체를 FBX 애니메이션으로 변환.
Unity : 메카님으로 직접 변환, 강체와 유체를 제외한 스켈레탈만 전송. 단 Unity 물리를 Bullet으로 바꾸던가 후처리 가공 필요.
three.js : Bullet Physics의 강체와 유체를 간단하게 직접 구현해놓은 형태
MMD의 경우 좀 복잡한 느낌이지만, 이에 대한 역사를 조금 살펴보시면 감을 잡으실 수 있을 것 같습니다.
FBX SDK에 대해서
빌드 세팅이 복잡할 수 있지만, 제 프로젝트 설정을 확인하시면 됩니다. FBX SDK를 직접 빌드해보면 여러가지 문제가 발생할 수 있는데 이 부분은 따로 설명하지 않습니다.
1996년 1.0버전, kaydara's Filmbox로 시작,
1999년 2.0버전
2001년 3.0버전
2002년 Filmbox에서 MotionBuilder로 이름이 바뀜
2003년 4.0버전
2004년 Apple's QuickTime Viewer
2005년 SDK 표준 모델 발표
2006년 Autodesk가 관리 시작
이후 Autodesk의 fbx sdk로 표준을 관리하고 있습니다.
fbx는 현재 game을 위한 기술로 분류되지만 최초엔 모션 캡처 데이터에 사용되었었습니다.
그리고 FBX SDK 라이센스는 GPL이며 이를 사용한 엔진들은 모두 코드를 공개하고 있습니다. 그래서 UE4나 Unity에서도 해당 내용을 확인할 수 있죠. 이에 대해서는 다시 설명합니다. 하지만 FBX 포맷을 활용한 저작물(모델링, 애니메이션 파일)은 생산자가 GPL과 별도로 저작권을 가집니다.
오픈소스 FBX들은 Assimp, Ozz, Blender에서 사용되고 있습니다. 하지만 현시점에선 전부 2015~2014년 버전을 기준으로 하고 있으며 2018에 도입할 경우 조금씩 깨지거나 의도치 않은 결과를 가져옵니다. Assimp의 경우 PMX와 FBX를 지원하지만 실제로 작업을 하다보면 꽤 많은 오류가 발생하고, OZZ는 2017년을 마지막으로 지원이 끊겼는데 Assimp보단 나은 결과를 보여줍니다. 마지막으로 Blender는 FBX 7.3과 7.4를 기준으로 하는데 제일 잘 동작하지만 UE4나 Unity에 적용하기 위해서는 Skeleton이나 Export 옵션에 많은 수정을 필요로 합니다. 대신 Import 부분은 매우 훌륭하게 동작합니다.
FBX SDK는 FBX 포맷을 다루기 위한 툴인데, FBX 포맷에 관해서는 설명되어 있지 않습니다. 부분적이고 추상적으로 설명되어 있어서 바이너리 구조는 직접 알아봐야하는데 아래 링크들은 FBX File format에 관한 Blender의 문서들이 도움이 됩니다. 하지만 구버전을 기준으로 함을 주의해주세요.
2018년 7월 8일을 기준으로 Unreal Engine 4(4.19)와
Unity(2018.1.4) 최신 버전은 FBX SDK 2018.1을 사용하고 있습니다. 즉 2018.1로 변환만 성공하면 각 엔진이나 마야 등의 편집 툴에서 범용적으로 쓸 수 있습니다. 꽤 매력적이지만 함정이라면 FBX SDK가 쓰기 어렵습니다.
FBX의 애니메이션 관련 공식 문서는 예제 코드부터 오류가 존재합니다, doxygen과 실제 코드를 intellisence로 찍어본 결과도 제각각입니다. 제가 이 프로젝트에서 애니메이션을 포기한 이유기도 한데요[..] 이 부분은 나중에 필요해지면 다시 해볼 예정입니다.
차라리 공식 문서보다
How to work with FBX SDK 글이 큰 도움이 됬습니다. 해당 글의 코드들을 살펴보면 꽤 많은 리비전이 존재합니다. 13, 14 버전이 혼용되어 있으니 참고하세요. 2018.1로 돌릴려면 조금 손봐줘야 합니다.
번외로 MMD에서 FBX로 변환하는 C++ 툴, 오픈소스로 이미
pmx2fbx라는 툴이 있습니다. 당시 FBX SDK 2013인가 2015버전 기준인데 2018로 변경해서 빌드하고 실행시켜보니 돌아갑니다. 다만 UE4나 Unity에 넣을 때 루트 본이 하나가 아니라던가 pmx 파일에 따라서 오류가 발생합니다. 하지만 이 코드는 FBX SDK와 PMX 간 스켈레톤 구조를 공유하는 방식에 대해서 참고할 때 도움이 됬습니다.
후기, 다음 작업
원래는 MMD(PMX)에서 FBX로 변환하는 프로그램을 개발하고 있었는데 처음 생각보다 너무 일이 커졌습니다. 아마 잘 모르는 상황에서 일의 크기를 몰라서 견적을 잘 못 잡은거 같습니다.
아마 다음에 할 일은 애니메이션을 포함한 추출이 아니라 먼저 MMD(PMX)에서 FBX나 COLLADA로 스켈레톤 구조, 강체 등만 먼저 추출 해봐야 할 것 같습니다.
그리고 원래 목표였던 IK를 이용해서 애니메이션을 재생하는 예제는 따로 작성해봐야 할 것 같습니다. 지금 관심있게 보면서 참고 중인 프로젝트는 아래와 같습니다.
- WebGL로 MMD 재생 :
three.js,
MMD 예제
- C++에서 MMD 재생 :
saba
-
Assimp
-
Ozz
제 경우 캐릭터 애니메이션 포맷이나 렌더링, 애니메이션 재생을 공부하는건 수단이고 최종 목표는 AR이나 RL 등에 적용해보는 것 입니다. 취미로 계속 하는 중이고 아마 다음에는 좀 더 단기간에 할 수 있는, 작은 규모로 프로젝트를 해볼 것 같습니다.