// メッシュ情報処理(再帰関数) void GetMeshData(FbxNode *parent, VertexDataArray& outVertexData) { // メッシュだけ処理 int numKids = parent->GetChildCount(); for(int i = 0; i < numKids; i++) { FbxNode *child = parent->GetChild(i); // メッシュを見つけたら if(child->GetMesh()) { FbxMesh* pMesh = child->GetMesh();// static_cast<FbxMesh*>(child->GetNodeAttribute()); printf("メッシュ発見\n"); printf("名前:%s\n", pMesh->GetName()); printf("ポリゴン数:%d\n", pMesh->GetPolygonCount()); printf("マテリアル数:%d\n", pMesh->GetElementMaterialCount()); printf("コントロールポイント数(頂点座標):%d\n", pMesh->GetControlPointsCount()); printf("UV数:%d\n", pMesh->GetTextureUVCount()); FbxArray<FbxVector4> normals; pMesh->GetPolygonVertexNormals(normals); printf("法線数:%d\n", normals.GetCount()); // 頂点情報取得 GetFBXVertexData(pMesh, outVertexData); } // マテリアル int numMat = child->GetMaterialCount(); for(int j = 0; j < numMat; ++j) { FbxSurfaceMaterial* mat = child->GetMaterial(j); if(mat) { GetMatrialData(mat); } } if(numMat == 0) { printf("マテリアルなし\n"); } child->GetChild(0); // 更に子を処理 GetMeshData(child, outVertexData); } }
void FBXImporter::LoadMaterials(FBXMeshData* fbxMeshData) { FbxNode* node = nullptr; FbxMesh* mesh = fbxMeshData->mMesh; int materialCount = 0; int polygonCount = mesh->GetPolygonCount(); if ((mesh != nullptr) && (mesh->GetNode() != nullptr)) { node = mesh->GetNode(); materialCount = node->GetMaterialCount(); } bool isAllSame = true; for (int i = 0; i < mesh->GetElementMaterialCount(); i++) { FbxGeometryElementMaterial* materialElement = mesh->GetElementMaterial(i); if (materialElement->GetMappingMode() == FbxGeometryElement::eByPolygon) { isAllSame = false; break; } } //For eAllSame mapping type, just out the material and texture mapping info once if (isAllSame) { for (int i = 0; i < mesh->GetElementMaterialCount(); i++) { FbxGeometryElementMaterial* materialElement = mesh->GetElementMaterial(i); if (materialElement->GetMappingMode() == FbxGeometryElement::eAllSame) { FbxSurfaceMaterial* material = mesh->GetNode()->GetMaterial(materialElement->GetIndexArray().GetAt(0)); fbxMeshData->mSurfaceMaterial = material; int materialId = materialElement->GetIndexArray().GetAt(0); if (materialId >= 0) { LoadMaterialTexture(fbxMeshData, FbxSurfaceMaterial::sDiffuse); LoadMaterialTexture(fbxMeshData, FbxSurfaceMaterial::sBump); vector<string>& textureFiles = mMeshData->textureFiles; auto iter = find(textureFiles.begin(), textureFiles.end(), fbxMeshData->getDiffuseTextureFile()); if (iter == textureFiles.end()) { textureFiles.push_back(fbxMeshData->getDiffuseTextureFile()); } if (fbxMeshData->getNormalMapTextureFile().size() > 0) { iter = find(textureFiles.begin(), textureFiles.end(), fbxMeshData->getNormalMapTextureFile()); if (iter == textureFiles.end()) { textureFiles.push_back(fbxMeshData->getNormalMapTextureFile()); } } } } } } //For eByPolygon mapping type, just out the material and texture mapping info once else { int materialId = 0; int polygonId = 0; polygonCount = 0; vector<string>& textureFiles = mMeshData->textureFiles; vector<MaterialIdOffset>& materialIdOffsets = mMeshData->materialIdOffsets; for (int i = 0; i < materialIdOffsets.size(); i++) { FbxGeometryElementMaterial* materialElement = mesh->GetElementMaterial(0); FbxSurfaceMaterial* material = NULL; materialId = mMeshData->materialIdOffsets[i].material->materialId; material = mesh->GetNode()->GetMaterial(materialElement->GetIndexArray().GetAt(polygonId)); polygonCount = materialIdOffsets[i].polygonCount; fbxMeshData->mSurfaceMaterial = material; fbxMeshData->mMaterial = new Material(); LoadMaterialTexture(fbxMeshData, FbxSurfaceMaterial::sDiffuse); LoadMaterialTexture(fbxMeshData, FbxSurfaceMaterial::sBump); materialIdOffsets[i].material = fbxMeshData->mMaterial; auto iter = find(textureFiles.begin(), textureFiles.end(), fbxMeshData->getDiffuseTextureFile()); if (iter == textureFiles.end()) { textureFiles.push_back(fbxMeshData->getDiffuseTextureFile()); } if (fbxMeshData->getNormalMapTextureFile().size() > 0) { iter = find(textureFiles.begin(), textureFiles.end(), fbxMeshData->getNormalMapTextureFile()); if (iter == textureFiles.end()) { textureFiles.push_back(fbxMeshData->getNormalMapTextureFile()); } } polygonId += polygonCount; } } }
//-------------------------------------------------------------------------- void SaveMesh(FbxNode* pNode, const VeDirectoryPtr& spDest) noexcept { Mesh kMesh; FbxMesh* pMesh = (FbxMesh*)pNode->GetNodeAttribute(); kMesh.m_kName = pNode->GetName(); kMesh.m_stFaces = pMesh->GetPolygonCount(); kMesh.m_stVerts = kMesh.m_stFaces * 3; kMesh.m_kIndices.resize(kMesh.m_stVerts); kMesh.m_kPosition.resize(kMesh.m_stVerts); kMesh.m_kNormals.resize(pMesh->GetElementNormalCount()); for (auto& v : kMesh.m_kNormals) { v.resize(kMesh.m_stVerts); } kMesh.m_kTexcoords.resize(pMesh->GetElementUVCount()); for (auto& v : kMesh.m_kTexcoords) { v.resize(kMesh.m_stVerts); } kMesh.m_kColors.resize(pMesh->GetElementVertexColorCount()); for (auto& v : kMesh.m_kColors) { v.resize(kMesh.m_stVerts); } int element_mat = -1; for (int i(0); i < pMesh->GetElementMaterialCount(); ++i) { FbxGeometryElementMaterial* lMaterialElement = pMesh->GetElementMaterial(i); if (lMaterialElement->GetMappingMode() == FbxGeometryElement::eByPolygon) { element_mat = i; break; } } if (element_mat >= 0) { kMesh.m_kAttributes.resize(kMesh.m_stFaces); } FbxVector4* lControlPoints = pMesh->GetControlPoints(); for (int i(0); i < (int)(kMesh.m_stFaces); ++i) { int lPolygonSize = pMesh->GetPolygonSize(i); VE_ASSERT_ALWAYS(lPolygonSize == 3); for (int j(0); j < lPolygonSize; ++j) { uint32_t u32Index = i * 3 + j; kMesh.m_kIndices[u32Index] = u32Index; int lControlPointIndex = pMesh->GetPolygonVertex(i, j); auto& pos = kMesh.m_kPosition[u32Index]; pos.x = (float)lControlPoints[lControlPointIndex][0]; pos.y = (float)lControlPoints[lControlPointIndex][1]; pos.z = (float)lControlPoints[lControlPointIndex][2]; for (int k(0); k < (int)(kMesh.m_kColors.size()); ++k) { FbxColor c; FbxGeometryElementVertexColor* leVtxc = pMesh->GetElementVertexColor(k); switch (leVtxc->GetMappingMode()) { default: break; case FbxGeometryElement::eByControlPoint: switch (leVtxc->GetReferenceMode()) { case FbxGeometryElement::eDirect: c = leVtxc->GetDirectArray().GetAt(lControlPointIndex); break; case FbxGeometryElement::eIndexToDirect: { int id = leVtxc->GetIndexArray().GetAt(lControlPointIndex); c = leVtxc->GetDirectArray().GetAt(id); } break; default: break; // other reference modes not shown here! } break; case FbxGeometryElement::eByPolygonVertex: { switch (leVtxc->GetReferenceMode()) { case FbxGeometryElement::eDirect: c = leVtxc->GetDirectArray().GetAt(u32Index); break; case FbxGeometryElement::eIndexToDirect: { int id = leVtxc->GetIndexArray().GetAt(u32Index); c = leVtxc->GetDirectArray().GetAt(id); } break; default: break; // other reference modes not shown here! } } break; case FbxGeometryElement::eByPolygon: // doesn't make much sense for UVs case FbxGeometryElement::eAllSame: // doesn't make much sense for UVs case FbxGeometryElement::eNone: // doesn't make much sense for UVs break; } auto& color = kMesh.m_kColors[k][u32Index]; color.x = (float)c[0]; color.y = (float)c[1]; color.z = (float)c[2]; color.w = (float)c[3]; } for (int k(0); k < (int)(kMesh.m_kTexcoords.size()); ++k) { FbxVector2 uv; FbxGeometryElementUV* leUV = pMesh->GetElementUV(k); switch (leUV->GetMappingMode()) { default: break; case FbxGeometryElement::eByControlPoint: switch (leUV->GetReferenceMode()) { case FbxGeometryElement::eDirect: uv = leUV->GetDirectArray().GetAt(lControlPointIndex); break; case FbxGeometryElement::eIndexToDirect: { int id = leUV->GetIndexArray().GetAt(lControlPointIndex); uv = leUV->GetDirectArray().GetAt(id); } break; default: break; // other reference modes not shown here! } break; case FbxGeometryElement::eByPolygonVertex: { int lTextureUVIndex = pMesh->GetTextureUVIndex(i, j); switch (leUV->GetReferenceMode()) { case FbxGeometryElement::eDirect: case FbxGeometryElement::eIndexToDirect: { uv = leUV->GetDirectArray().GetAt(lTextureUVIndex); } break; default: break; // other reference modes not shown here! } } break; case FbxGeometryElement::eByPolygon: // doesn't make much sense for UVs case FbxGeometryElement::eAllSame: // doesn't make much sense for UVs case FbxGeometryElement::eNone: // doesn't make much sense for UVs break; } auto& texcoord = kMesh.m_kTexcoords[k][u32Index]; texcoord.x = (float)uv[0]; texcoord.y = (float)uv[1]; } for (int k(0); k < (int)(kMesh.m_kNormals.size()); ++k) { FbxVector4 n; FbxGeometryElementNormal* leNormal = pMesh->GetElementNormal(k); if (leNormal->GetMappingMode() == FbxGeometryElement::eByPolygonVertex) { switch (leNormal->GetReferenceMode()) { case FbxGeometryElement::eDirect: n = leNormal->GetDirectArray().GetAt(u32Index); break; case FbxGeometryElement::eIndexToDirect: { int id = leNormal->GetIndexArray().GetAt(u32Index); n = leNormal->GetDirectArray().GetAt(id); } break; default: break; // other reference modes not shown here! } } auto& normal = kMesh.m_kNormals[k][u32Index]; normal.x = (float)n[0]; normal.y = (float)n[1]; normal.z = (float)n[2]; } if (element_mat >= 0) { FbxGeometryElementMaterial* lMaterialElement = pMesh->GetElementMaterial(element_mat); FbxSurfaceMaterial* lMaterial = NULL; int lMatId = -1; lMaterial = pMesh->GetNode()->GetMaterial(lMaterialElement->GetIndexArray().GetAt(i)); lMatId = lMaterialElement->GetIndexArray().GetAt(i); kMesh.m_kAttributes[i] = lMatId; } } } kMesh.Process(); kMesh.Save(spDest); }