reMaterial* reFBXAsset::getMaterial( FbxMesh* fmesh, int i, reMaterialSet& set) { reMaterial* mat = NULL; for (int l = 0; l < fmesh->GetElementMaterialCount(); l++) { FbxGeometryElementMaterial* lMaterialElement = fmesh->GetElementMaterial(l); int lMatId = lMaterialElement->GetIndexArray().GetAt(i); if(lMatId >= 0) { if (mat = set.materialById(lMatId)) return mat; mat = new reMaterial; mat->id = lMatId; set.addMetarial(mat); FbxSurfaceMaterial* lMaterial = fmesh->GetNode()->GetMaterial(lMaterialElement->GetIndexArray().GetAt(i)); if (!lMaterial) { continue; } ////////////////////////////////////////////////////////////////////////// FbxProperty lProperty = lMaterial->FindProperty(FbxSurfaceMaterial::sDiffuse); if (lMaterial->GetClassId().Is(FbxSurfacePhong::ClassId)) { FbxDouble3 lFbxDouble3; lFbxDouble3 =((FbxSurfacePhong *)lMaterial)->Diffuse; mat->diffuseColor = reColor4(lFbxDouble3[0], lFbxDouble3[1], lFbxDouble3[2], 1); } if (lMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId)) { FbxDouble3 lFbxDouble3; lFbxDouble3 =((FbxSurfaceLambert *)lMaterial)->Diffuse; mat->diffuseColor = reColor4(lFbxDouble3[0], lFbxDouble3[1], lFbxDouble3[2], 1); } ////////////////////////////////////////////////////////////////////////// read texture int lNbTextures = lProperty.GetSrcObjectCount(FbxTexture::ClassId); if (lNbTextures) { mat->diffuseTexture = new reTexture; FbxTexture* lTexture = FbxCast <FbxTexture> (lProperty.GetSrcObject(FbxTexture::ClassId,0)); qDebug() << "map: " << lTexture->GetName(); FbxFileTexture *lFileTexture = FbxCast<FbxFileTexture>(lTexture); if (lFileTexture) { mat->diffuseTexture->fileName(lFileTexture->GetFileName()); } } ////////////////////////////////////////////////////////////////////////// } } return mat; }
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; } } }
Mesh* FBXSceneEncoder::loadMesh(FbxMesh* fbxMesh) { // Check if this mesh has already been loaded. Mesh* mesh = getMesh(fbxMesh->GetUniqueID()); if (mesh) { return mesh; } mesh = new Mesh(); // GamePlay requires that a mesh have a unique ID but FbxMesh doesn't have a string ID. const char* name = fbxMesh->GetNode()->GetName(); if (name) { string id(name); id.append("_Mesh"); mesh->setId(id); } // The number of mesh parts is equal to the number of materials that affect this mesh. // There is always at least one mesh part. vector<MeshPart*> meshParts; const int materialCount = fbxMesh->GetNode()->GetMaterialCount(); int meshPartSize = (materialCount > 0) ? materialCount : 1; for (int i = 0; i < meshPartSize; ++i) { meshParts.push_back(new MeshPart()); } // Find the blend weights and blend indices if this mesh is skinned. vector<vector<Vector2> > weights; bool hasSkin = loadBlendWeights(fbxMesh, weights); // Get list of uv sets for mesh FbxStringList uvSetNameList; fbxMesh->GetUVSetNames(uvSetNameList); const int uvSetCount = uvSetNameList.GetCount(); int vertexIndex = 0; FbxVector4* controlPoints = fbxMesh->GetControlPoints(); const int polygonCount = fbxMesh->GetPolygonCount(); for (int polyIndex = 0; polyIndex < polygonCount; ++polyIndex) { const int polygonSize = fbxMesh->GetPolygonSize(polyIndex); for (int posInPoly = 0; posInPoly < polygonSize; ++posInPoly) { int controlPointIndex = fbxMesh->GetPolygonVertex(polyIndex, posInPoly); Vertex vertex; FbxVector4& position = controlPoints[controlPointIndex]; vertex.position.x = (float)position[0]; vertex.position.y = (float)position[1]; vertex.position.z = (float)position[2]; // Load tex coords for all uv sets for (int uvSetIndex = 0; uvSetIndex < uvSetCount; ++uvSetIndex) { const FbxGeometryElementUV* uvElement = fbxMesh->GetElementUV(uvSetNameList.GetStringAt(uvSetIndex)); if (uvElement) loadTextureCoords(fbxMesh, uvElement, uvSetIndex, polyIndex, posInPoly, vertexIndex, &vertex); } // Load other data loadNormal(fbxMesh, vertexIndex, controlPointIndex, &vertex); loadTangent(fbxMesh, vertexIndex, controlPointIndex, &vertex); loadBinormal(fbxMesh, vertexIndex, controlPointIndex, &vertex); loadVertexColor(fbxMesh, vertexIndex, controlPointIndex, &vertex); if (hasSkin) { loadBlendData(weights[controlPointIndex], &vertex); } // Determine which mesh part this vertex index should be added to based on the material that affects it. int meshPartIndex = 0; const int elementMatrialCount = fbxMesh->GetElementMaterialCount(); for (int k = 0; k < elementMatrialCount; ++k) { FbxGeometryElementMaterial* elementMaterial = fbxMesh->GetElementMaterial(k); meshPartIndex = elementMaterial->GetIndexArray().GetAt(polyIndex); } // Add the vertex to the mesh if it hasn't already been added and find the vertex index. unsigned int index; if (mesh->contains(vertex)) { index = mesh->getVertexIndex(vertex); } else { index = mesh->addVertex(vertex); } meshParts[meshPartIndex]->addIndex(index); vertexIndex++; } } const size_t meshpartsSize = meshParts.size(); for (size_t i = 0; i < meshpartsSize; ++i) { mesh->addMeshPart(meshParts[i]); } // The order that the vertex elements are add to the list matters. // It should be the same order as how the Vertex data is written. // Position mesh->addVetexAttribute(POSITION, Vertex::POSITION_COUNT); const Vertex& vertex = mesh->vertices[0]; // Normals if (vertex.hasNormal) { mesh->addVetexAttribute(NORMAL, Vertex::NORMAL_COUNT); } // Tangents if (vertex.hasTangent) { mesh->addVetexAttribute(TANGENT, Vertex::TANGENT_COUNT); } // Binormals if (vertex.hasBinormal) { mesh->addVetexAttribute(BINORMAL, Vertex::BINORMAL_COUNT); } // Texture Coordinates for (unsigned int i = 0; i < MAX_UV_SETS; ++i) { if (vertex.hasTexCoord[i]) { mesh->addVetexAttribute(TEXCOORD0 + i, Vertex::TEXCOORD_COUNT); } } // Diffuse Color if (vertex.hasDiffuse) { mesh->addVetexAttribute(COLOR, Vertex::DIFFUSE_COUNT); } // Skinning BlendWeights BlendIndices if (vertex.hasWeights) { mesh->addVetexAttribute(BLENDWEIGHTS, Vertex::BLEND_WEIGHTS_COUNT); mesh->addVetexAttribute(BLENDINDICES, Vertex::BLEND_INDICES_COUNT); } _gamePlayFile.addMesh(mesh); saveMesh(fbxMesh->GetUniqueID(), mesh); return mesh; }
//-------------------------------------------------------------------------- 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); }