1. FBX SDK

  1. FBX SDK 설치 경로

    C:\Program Files\Autodesk\FBX\FBX SDK\2020.3.1

  2. FBX SDK 사용 방법

    1. 오즈라엘 : FBX SDK 이용 방법 #1 (How to Work with FBX SDK 번역) (egloos.com)
    2. How to Work with FBX SDK - Graphics and GPU Programming - Tutorials - GameDev.net
    3. DirectX Part 4: Loading FBX Models | The walkerb.net Blog
  3. 위 설치 경로에 있는 lib와 include를 프로젝트에 포함하여 사용.

  4. 다음 코드는 3D 모델 데이터를 로드하여 모든 정점(vertex)의 로컬 좌표를 출력한다.

    #include <iostream>
    #include <fbxsdk.h>
    #include <vector>
    #include <Winerror.h>
    #include <cassert>
    #include <DirectXMath.h>
    
    struct MyVertex
    {
    	float pos[3];
    };
    
    FbxManager* g_pFbxSdkManager = nullptr;
    
    HRESULT LoadFBX(std::vector<MyVertex>* pOutVertexVector)
    {
    	if (g_pFbxSdkManager == nullptr)
    	{
    		g_pFbxSdkManager = FbxManager::Create();
    
    		FbxIOSettings* pIOsettings = FbxIOSettings::Create(g_pFbxSdkManager, IOSROOT);
    		g_pFbxSdkManager->SetIOSettings(pIOsettings);
    	}
    
    	FbxImporter* pImporter = FbxImporter::Create(g_pFbxSdkManager, "");
    	FbxScene* pFbxScene = FbxScene::Create(g_pFbxSdkManager, "");
    
        bool bSuccess = pImporter->Initialize("C:\\\\Users\\\\USER\\\\Desktop\\\\untitled.fbx", -1, g_pFbxSdkManager->GetIOSettings());
        if (!bSuccess) return E_FAIL;
    
        bSuccess = pImporter->Import(pFbxScene);
        if (!bSuccess) return E_FAIL;
    
        pImporter->Destroy();
    
        FbxNode* pFbxRootNode = pFbxScene->GetRootNode();
    
        if (pFbxRootNode)
        {
            for (int i = 0; i < pFbxRootNode->GetChildCount(); i++)
            {
                FbxNode* pFbxChildNode = pFbxRootNode->GetChild(i);
    
                if (pFbxChildNode->GetNodeAttribute() == NULL)
                    continue;
    
                FbxNodeAttribute::EType AttributeType = pFbxChildNode->GetNodeAttribute()->GetAttributeType();
    
                if (AttributeType != FbxNodeAttribute::eMesh)
                    continue;
    
                FbxMesh* pMesh = (FbxMesh*)pFbxChildNode->GetNodeAttribute();
    
                FbxVector4* pVertices = pMesh->GetControlPoints();
    
                for (int j = 0; j < pMesh->GetPolygonCount(); j++)
                {
                    int iNumVertices = pMesh->GetPolygonSize(j);
                    assert(iNumVertices == 3);
    
                    for (int k = 0; k < iNumVertices; k++) {
                        int iControlPointIndex = pMesh->GetPolygonVertex(j, k);
    
                        MyVertex vertex;
                        vertex.pos[0] = (float)pVertices[iControlPointIndex].mData[0];
                        vertex.pos[1] = (float)pVertices[iControlPointIndex].mData[1];
                        vertex.pos[2] = (float)pVertices[iControlPointIndex].mData[2];
                        pOutVertexVector->push_back(vertex);
                    }
                }
    
            }
    
        }
        return S_OK;
    }
    
    int main()
    {
        std::vector<MyVertex> Vertices;
        LoadFBX(&Vertices);
    
        for (auto& v : Vertices)
        {
            std::cout << "(" << v.pos[0] << ", " << v.pos[1] << ", " << v.pos[2] << ")" << std::endl;
        }
        std::cout << "Vertices vector size: " << Vertices.size() << std::endl;
    
        return 0;
    }
    

2. Open Asset Import Library (assimp)

  1. 빌드 방법

    1. 라이브러리 다운로드
    2. CMake를 사용하여 프로젝트 generate
    3. 빌드
  2. 사용법 및 참고

    1. include, lib 폴더와 bin에 있는 assimp-vcXXX-mtd.dll 파일을 개인 프로젝트 폴더에 복사
    2. Visual Studio 프로젝트 속성 설정
    3. [Learn OpenGL 번역] 4-1. 모델 불러오기 - Assimp (tistory.com)
    4. assimp/Build.md at master · assimp/assimp (github.com)
  3. 다음 코드는 3D 모델 데이터를 로드하여 모든 정점(vertex)의 로컬 좌표를 출력한다

    #define NOMINMAX
    #include <windows.h>
    
    #include <iostream>
    #include <vector>
    
    #include <assimp/Importer.hpp>      // C++ importer interface
    #include <assimp/scene.h>           // Output data structure
    #include <assimp/postprocess.h>     // Post processing flags
    
    #pragma comment(lib, "assimp-vc143-mtd.lib")
    
    struct VERTEX
    {
    	float X;
    	float Y;
    	float Z;
    };
    
    void PrintVertexAndIndex(std::vector<VERTEX>& vs, std::vector<UINT>& is)
    {
    	for (auto& v : vs)
    	{
    		std::cout << v.X << ',' << v.Y << ',' << v.Z << std::endl;
    	}
    	std::cout << "========================================" << std::endl;
    	for (auto& i : is)
    	{
    		std::cout << i << std::endl;
    	}
    	std::cout << "========================================" << std::endl;
    }
    
    void processMesh(aiMesh* mesh, const aiScene* scene) 
    {
    	// Data to fill
    	std::vector<VERTEX> vertices;
    	std::vector<UINT> indices;
    
    	// Walk through each of the mesh's vertices
    	for (UINT i = 0; i < mesh->mNumVertices; i++) {
    		VERTEX vertex;
    
    		vertex.X = mesh->mVertices[i].x;
    		vertex.Y = mesh->mVertices[i].y;
    		vertex.Z = mesh->mVertices[i].z;
    
    		vertices.push_back(vertex);
    	}
    
    	for (UINT i = 0; i < mesh->mNumFaces; i++) {
    		aiFace face = mesh->mFaces[i];
    
    		for (UINT j = 0; j < face.mNumIndices; j++)
    			indices.push_back(face.mIndices[j]);
    	}
    
    	PrintVertexAndIndex(vertices, indices);
    }
    
    void processNode(aiNode* node, const aiScene* scene)
    {
    	for (UINT i = 0; i < node->mNumMeshes; i++) {
    		aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
    		processMesh(mesh, scene);
    	}
    
    	for (UINT i = 0; i < node->mNumChildren; i++) {
    		processNode(node->mChildren[i], scene);
    	}
    }
    
    bool Load(std::string filename) 
    {
    	Assimp::Importer importer;
    	const aiScene* pScene = importer.ReadFile(filename,
    		aiProcess_Triangulate |
    		aiProcess_ConvertToLeftHanded);
    
    	if (pScene == nullptr)
    		return false;
    
    	processNode(pScene->mRootNode, pScene);
    
    	return true;
    }
    
    int main()
    {
    	std::string fn("C:\\\\Users\\\\USER\\\\Desktop\\\\untitled.fbx");
    	Load(fn);
    	return 0;
    }