Mesh


Mesh


  • 今日のターゲットFBXファイルを読んで、スクリーンに置いてください!

  • これまで,表現の対象はハードコーディングで直接成形されたものであった.

  • しかし、実際の作業では、このような場合は、予め作成されたオブジェクトを読むことでほとんど使われています.

  • FBXファイルには、Material、Mesh、Animation、Bone、Skinなど様々なモデルに関する情報が含まれています.

  • FBXライブラリからFBXファイルを読み込みます.
  • void FBXLoader::LoadFbx(const wstring& path)
    {
    	// 파일 데이터 로드
    	Import(path);
    
    	// Animation	
    	//LoadBones(_scene->GetRootNode());
    	//LoadAnimationInfo();
    
    	// 로드된 데이터 파싱 (Mesh/Material/Skin)
    	ParseNode(_scene->GetRootNode());
    
    	// 우리 구조에 맞게 Texture / Material 생성
    	CreateTextures();
    	CreateMaterials();
    }
    
    
    void FBXLoader::Import(const wstring& path)
    {
    	// FBX SDK 관리자 객체 생성
    	_manager = FbxManager::Create();
    
    	// IOSettings 객체 생성 및 설정
    	FbxIOSettings* settings = FbxIOSettings::Create(_manager, IOSROOT);
    	_manager->SetIOSettings(settings);
    
    	// FbxImporter 객체 생성
    	_scene = FbxScene::Create(_manager, "");
    
    	// 나중에 Texture 경로 계산할 때 쓸 것
    	_resourceDirectory = fs::path(path).parent_path().wstring() + L"\\" + fs::path(path).filename().stem().wstring() + L".fbm";
    
    	_importer = FbxImporter::Create(_manager, "");
    
    	string strPath = ws2s(path);
    	_importer->Initialize(strPath.c_str(), -1, _manager->GetIOSettings());
    
    	_importer->Import(_scene);
    
    	_scene->GetGlobalSettings().SetAxisSystem(FbxAxisSystem::DirectX);
    
    	// 씬 내에서 삼각형화 할 수 있는 모든 노드를 삼각형화 시킨다.
    	FbxGeometryConverter geometryConverter(_manager);
    	geometryConverter.Triangulate(_scene, true);
    
    	_importer->Destroy();
    }
    
    void FBXLoader::ParseNode(FbxNode* node)
    {
    	FbxNodeAttribute* attribute = node->GetNodeAttribute();
    
    	if (attribute)
    	{
    		switch (attribute->GetAttributeType())
    		{
    		case FbxNodeAttribute::eMesh:
    			LoadMesh(node->GetMesh());
    			break;
    		}
    	}
    
    	// Material 로드
    	const uint32 materialCount = node->GetMaterialCount();
    	for (uint32 i = 0; i < materialCount; ++i)
    	{
    		FbxSurfaceMaterial* surfaceMaterial = node->GetMaterial(i);
    		LoadMaterial(surfaceMaterial);
    	}
    
    	// Tree 구조 재귀 호출
    	const int32 childCount = node->GetChildCount();
    	for (int32 i = 0; i < childCount; ++i)
    		ParseNode(node->GetChild(i));
    }
    
    void FBXLoader::LoadMesh(FbxMesh* mesh)
    {
    	_meshes.push_back(FbxMeshInfo());
    	FbxMeshInfo& meshInfo = _meshes.back();
    
    	meshInfo.name = s2ws(mesh->GetName());
    
    	const int32 vertexCount = mesh->GetControlPointsCount();
    	meshInfo.vertices.resize(vertexCount);
    	meshInfo.boneWeights.resize(vertexCount);
    
    	// Position
    	FbxVector4* controlPoints = mesh->GetControlPoints();
    	for (int32 i = 0; i < vertexCount; ++i)
    	{
    		meshInfo.vertices[i].pos.x = static_cast<float>(controlPoints[i].mData[0]);
    		meshInfo.vertices[i].pos.y = static_cast<float>(controlPoints[i].mData[2]);
    		meshInfo.vertices[i].pos.z = static_cast<float>(controlPoints[i].mData[1]);
    	}
    
    	const int32 materialCount = mesh->GetNode()->GetMaterialCount();
    	meshInfo.indices.resize(materialCount);
    
    	FbxGeometryElementMaterial* geometryElementMaterial = mesh->GetElementMaterial();
    
    	const int32 polygonSize = mesh->GetPolygonSize(0);
    	assert(polygonSize == 3);
    
    	uint32 arrIdx[3];
    	uint32 vertexCounter = 0; // 정점의 개수
    
    	const int32 triCount = mesh->GetPolygonCount(); // 메쉬의 삼각형 개수를 가져온다
    	for (int32 i = 0; i < triCount; i++) // 삼각형의 개수
    	{
    		for (int32 j = 0; j < 3; j++) // 삼각형은 세 개의 정점으로 구성
    		{
    			int32 controlPointIndex = mesh->GetPolygonVertex(i, j); // 제어점의 인덱스 추출
    			arrIdx[j] = controlPointIndex;
    
    			GetNormal(mesh, &meshInfo, controlPointIndex, vertexCounter);
    			GetTangent(mesh, &meshInfo, controlPointIndex, vertexCounter);
    			GetUV(mesh, &meshInfo, controlPointIndex, mesh->GetTextureUVIndex(i, j));
    
    			vertexCounter++;
    		}
    
    		const uint32 subsetIdx = geometryElementMaterial->GetIndexArray().GetAt(i);
    		meshInfo.indices[subsetIdx].push_back(arrIdx[0]);
    		meshInfo.indices[subsetIdx].push_back(arrIdx[2]);
    		meshInfo.indices[subsetIdx].push_back(arrIdx[1]);
    	}
    
    	// Animation
    	LoadAnimationData(mesh, &meshInfo);
    }
    
    結果