10.28

신승빈·2022년 10월 28일
0

KGCA 수업

목록 보기
59/128

FBX

대표적인 3D Object 표현방식
잘 알려진 Format으로 순수한 FBX를 쓸 경우 외부의 제 3자가 게임의 Resource에 쉽게 접근할 수 있음
또한, Game에 필요없는 부가적인 정보도 가지고 있을 수 있어서 Game이나 Engine에 Import시 최적화 작업 필요
Custom Exporter, Importer를 이용하여 최적화 진행
Exporter를 통해 3D Object를 출력할 경우 Viewer를 추가로 제작하여 외부에서 쉽게 확인할 수 있도록 제작

Reference : https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-2020-2-1

예시 코드

void Load()
{
	// FbxManager : System같은 역할
	m_pFbxManager = FbxManager::Create();
    // FbxImporter : 파일을 읽어오는 역할
	m_pFbxImporter = FbxImporter::Create(m_pFbxManager, "");
    // FbxScene : 3D OBject를 구성하는 1개의 Scene.
    // Scene에 있는 모든 정보를 읽어오면 3D Max의 화면을 구현할 수 있음
    // Tree Graph의 구조를 가지고 있으며, Tree의 Node마다 Texture, Vertex, Normal등 component 정보가 저장되어 있음
	m_pFbxScene = FbxScene::Create(m_pFbxManager, "");

	m_pFbxImporter->Initialize(filename.c_str());
	m_pFbxImporter->Import(m_pFbxScene);
    // FbxNode : Tree를 구성하는 Node
	m_pRootNode = m_pFbxScene->GetRootNode();
	PreProcess(m_pRootNode);
    
	for (auto mesh : m_pFbxMeshList)
	{
		ParseMesh(mesh);
	}
}
// Tree 순회
void TFbxLoader::PreProcess(FbxNode* pFbxNode)
{
	if (pFbxNode == nullptr) return;
    // Mesh정보를 가지고 있는 Node 검색
    // Mesh = Rendering가능한 정보
	FbxMesh* pFbxMesh = pFbxNode->GetMesh();
	if (pFbxMesh)
	{
		m_pFbxMeshList.push_back(pFbxMesh);
	}
	int iNumChild = pFbxNode->GetChildCount();
	for( int iChild=0; iChild < iNumChild; iChild++)
	{
		FbxNode* pChild = pFbxNode->GetChild(iChild);
		PreProcess(pChild);
	}
}
// Mesh 정보를 내 Engine에 맞도록 수정
void TFbxLoader::ParseMesh(FbxMesh* pFbxMesh)
{
	TFbxObject* pObject = new TFbxObject;
	
	FbxLayerElementUV* VertexUVSet=nullptr;
	// Layer 개념
    // 1개의 Mesh는 다수의 Layer로 이루어져있을 수 있음
	FbxLayer* pFbxLayer  = pFbxMesh->GetLayer(0);
	if (pFbxLayer->GetUVs() != nullptr)
	{
    	// Layer 단위로 정보를 읽어와야 한다
		VertexUVSet=pFbxLayer->GetUVs();
	}
	
	int iNumPolyCount = pFbxMesh->GetPolygonCount();
    
	int iNumFace = 0;

	// 제어점. 정점 위치 원본인듯
	FbxVector4* pVertexPositions = pFbxMesh->GetControlPoints();
	for (int iPoly = 0; iPoly < iNumPolyCount; iPoly++)
	{
		int iPolySize = pFbxMesh->GetPolygonSize(iPoly);
    	// 3D Object는 1개의 폴리곤을 이루고있는 정점의 개수가 다를 수 있음
		// 3 정점 -> 1폴리곤( 삼각형)
		// 4 정점 -> 1폴리곤( 쿼드 )
		iNumFace = iPolySize - 2;
		for (int iFace = 0; iFace < iNumFace; iFace++)
		{
			int iCornerIndex[3];
            // FBX와 Direct3D는 사용하는 좌표계가 다름
			iCornerIndex[0] = pFbxMesh->GetPolygonVertex(iPoly, 0);
            // 4개 정점 폴리곤도 정상적으로 작동하는가?
			iCornerIndex[1] = pFbxMesh->GetPolygonVertex(iPoly, iFace+2);
			iCornerIndex[2] = pFbxMesh->GetPolygonVertex(iPoly, iFace+1);
			for (int iIndex = 0; iIndex < 3; iIndex++)
			{
				int vertexID = iCornerIndex[iIndex];
				FbxVector4 v = pVertexPositions[vertexID];
				SimpleVertex tVertex;
            	// FBX와 Direct3D는 사용하는 좌표계가 다름
				tVertex.p.x = v.mData[0];
				tVertex.p.y = v.mData[2];
				tVertex.p.z = v.mData[1];
				tVertex.c = { 1,1,1,1 };
				FbxVector2 t = ReadTextureCoord(pFbxMesh, VertexUVSet);
				tVertex.t.x = t.mData[0];
				tVertex.t.y = 1.0f-t.mData[1];

				pObject->m_VertexList.push_back(tVertex);
			}
		}
	}

	m_pDrawObjList.push_back(pObject);
}

FBX의 좌표계

FBX 파일은 오른손 Y-up 방식을 사용하기 때문에 왼손 Z-up을 사용하는 현 Engine에서는 읽어올 때 좌표축에 변환이 필요하다

Reference : https://help.autodesk.com/view/FBX/2016/ENU/?guid=__files_GUID_CC93340E_C4A1_49EE_B048_E898F856CFBF_htm

또한 FBX의 UV좌표는 좌하단을 원점으로 잡는다

Layer

1개의 3D Object는 다수의 Mesh와 다수의 Texture로 이루어져 있을 수 있고 1개의 Mesh역시 다수의 Texture를 통해 출력될 수 있음
1개의 Mesh가 다수의 Texture를 1개씩 여러번 출력하면 Multi Pass Rendering
다수의 Texture를 합쳐서 1번 Rendering하면 Multi Texture Rendering

런타임 라이브러리 컴파일-링크 옵션

MD : MultiThreadDLL
MT : MultiThread
DLL 여부에 따른 차이인 듯
뒤에 소문자 d는 debug유무

Reference : https://itisguide.tistory.com/19

재배포 패키지가 무엇일까?

그래픽 디버깅

Device Shader에서 처리되는 정보를 확인할 수 있음

Visual Studio Installer

볼만한 글

반복에 대하여 : https://velog.io/@hyemin916/%EB%B0%98%EB%B3%B5%EC%9D%84-%EC%A4%84%EC%9D%B4%EB%8A%94%EA%B2%8C-%EC%A0%95%EB%A7%90-%EC%A2%8B%EC%9D%80%EA%B0%80%EC%9A%94

마무리 3문장이 상당히 인상깊음

profile
이상을 길잡이 삼아 로망을 추구합니다.

0개의 댓글