# 项目1,北京市科委研发项目 需要在虚幻里访问api获得模型文件(fbx模型 png贴图)和场景描述(json) 在runtime下加载后,用于扣绿虚拍系统 # 项目2,国家数字资产平台 根据访问需求,接通云游戏(使用蔚领云游戏SDK),然后收到前端的资产uuid,加载资产渲染。 ## 第一阶段 用户访问一个web平台,点击某个资产(模型or场景) 会弹出一个页面,页面类似虚幻metahuman编辑器一样,是视频流的形式 在视频流中,是一个runtime窗口,可以渲染目标资产 ## 第二阶段 可以在前端点击资产添加,runtime窗口里会添加资产,然后runtime窗口里有简单编辑器可以摆镜头,可以简单摆放资产 # Default材质 标准pbr(半透明) 提供参数 1. base color (tex) 2. basecolor tilt (v3) 乘basevolor 4. opacity(tex linear) 5. opacity power(scale)乘到opacity 6. roughness(tex linear color) 7. roughness tilt(scale) 乘roughness 8. metalic (tex linear color) 9. metalic tilt(scale) 10. ao (tex linear color) 11. emisive(tex) 12. emisive power(scale) 乘emisive 13. normal(tex) # FaceSet https://github.com/zenustech/zeno/blob/b4ed8740810f20cf0612d615d9505468b2d2a4d1/projects/FBX/FBXSDK.cpp#L477 ```c++ int mat_count = 0; if (pMesh->GetElementMaterialCount() > 0) { for (auto i = 0; i < numPolygons; ++i) { faceset[i] = pMesh->GetElementMaterial()->GetIndexArray().GetAt(i); } mat_count = pNode->GetMaterialCount(); for (auto i = 0; i < mat_count; i++) { FbxSurfaceMaterial* material = pNode->GetMaterial(i); ud.set2(format("faceset_{}", i), material->GetName()); } } ``` UE中相关逻辑位于FbxMesh.cpp ```c++ void ExtractMeshMaterials(FFbxParser& Parser, FbxMesh* Mesh, FbxNode* MeshNode, TFunction CollectMaterial) { if (!Mesh || !MeshNode) { return; } //Grab all Material indexes use by the mesh TArray MaterialIndexes; int32 PolygonCount = Mesh->GetPolygonCount(); if (FbxGeometryElementMaterial* GeometryElementMaterial = Mesh->GetElementMaterial()) { FbxLayerElementArrayTemplate& IndexArray = GeometryElementMaterial->GetIndexArray(); switch (GeometryElementMaterial->GetMappingMode()) { case FbxGeometryElement::eByPolygon: { if (IndexArray.GetCount() == PolygonCount) { for (int32 PolygonIndex = 0; PolygonIndex < PolygonCount; ++PolygonIndex) { MaterialIndexes.AddUnique(IndexArray.GetAt(PolygonIndex)); } } } break; case FbxGeometryElement::eAllSame: { if (IndexArray.GetCount() > 0) { MaterialIndexes.AddUnique(IndexArray.GetAt(0)); } } break; } } const int32 MaterialCount = MeshNode->GetMaterialCount(); TMap UniqueSlotNames; UniqueSlotNames.Reserve(MaterialCount); bool bAddAllNodeMaterials = (MaterialIndexes.Num() == 0); for (int32 MaterialIndex = 0; MaterialIndex < MaterialCount; ++MaterialIndex) { if (FbxSurfaceMaterial* FbxMaterial = MeshNode->GetMaterial(MaterialIndex)) { int32& SlotMaterialCount = UniqueSlotNames.FindOrAdd(FbxMaterial); FString MaterialName = Parser.GetFbxHelper()->GetFbxObjectName(FbxMaterial); FString MaterialUid = TEXT("\\Material\\") + MaterialName; if (bAddAllNodeMaterials || MaterialIndexes.Contains(MaterialIndex)) { if (SlotMaterialCount > 0) { MaterialName += TEXT("_Section") + FString::FromInt(SlotMaterialCount); } SlotMaterialCount++; CollectMaterial(MaterialName, MaterialUid, MaterialIndex); } } } } ``` # AFBXMeshActor::AddMesh UFBXSceneImporter::ImportFBX() => UFBXSceneImporter::ProcessNode() => UFBXSceneImporter::ProcessMesh() => UFBXSceneImporter::CreateNodeMaterials() => FBXImportSettings->GetMaterialProperties(FbxMaterial, Node->GetName()); ## FaceSet FbxGeometryElementMaterial* GetElementMaterial FbxGeometryElementMaterial(FbxLayerElementMaterial),