From b847e273987a15f29304d7a5a0d2f78388464f8c Mon Sep 17 00:00:00 2001 From: T-rvw <429601557@qq.com> Date: Fri, 12 Jan 2024 17:18:40 +0800 Subject: [PATCH 1/2] store vertex instance id in polygon data --- examples/VerifyData/CDToRenderData/Main.cpp | 40 ++++ private/Consumers/FbxConsumer/FbxConsumer.cpp | 15 ++ .../Consumers/FbxConsumer/FbxConsumerImpl.cpp | 211 ++++++++++++------ .../Consumers/FbxConsumer/FbxConsumerImpl.h | 22 +- .../Producers/FbxProducer/FbxProducerImpl.cpp | 7 +- .../Producers/FbxProducer/FbxProducerImpl.h | 6 +- private/Scene/Mesh.cpp | 8 +- private/Scene/MeshImpl.cpp | 39 ++-- private/Scene/MeshImpl.h | 21 +- private/Scene/SceneDatabaseImpl.cpp | 6 +- public/Consumers/FbxConsumer/FbxConsumer.h | 5 + .../FbxConsumer/FbxConsumerOptions.h | 22 ++ public/Scene/APITypeTraits.inl | 4 +- public/Scene/Mesh.h | 6 +- public/Utilities/MeshUtils.hpp | 36 +-- 15 files changed, 315 insertions(+), 133 deletions(-) create mode 100644 examples/VerifyData/CDToRenderData/Main.cpp create mode 100644 public/Consumers/FbxConsumer/FbxConsumerOptions.h diff --git a/examples/VerifyData/CDToRenderData/Main.cpp b/examples/VerifyData/CDToRenderData/Main.cpp new file mode 100644 index 00000000..2367bf8f --- /dev/null +++ b/examples/VerifyData/CDToRenderData/Main.cpp @@ -0,0 +1,40 @@ +#include "CDProducer.h" +#include "Framework/Processor.h" +#include "Scene/SceneDatabase.h" +#include "Utilities/MeshUtils.hpp" +#include "Utilities/PerformanceProfiler.h" + +int main(int argc, char** argv) +{ + // argv[0] : exe name + // argv[1] : input file path + if (argc != 2) + { + return 1; + } + + using namespace cdtools; + + PerformanceProfiler profiler("AssetPipeline"); + + const char* pInputFilePath = argv[1]; + + auto pSceneDatabase = std::make_unique(); + CDProducer producer(pInputFilePath); + Processor processor(&producer, nullptr, pSceneDatabase.get()); + processor.Run(); + + for (const auto& mesh : pSceneDatabase->GetMeshes()) + { + auto vb = cd::BuildVertexBufferForStaticMesh(mesh, mesh.GetVertexFormat()); + assert(vb.has_value()); + + auto ibs = cd::BuildIndexBufferesForMesh(mesh); + for (const auto& ib : ibs) + { + assert(ib.has_value()); + } + } + + return 0; +} \ No newline at end of file diff --git a/private/Consumers/FbxConsumer/FbxConsumer.cpp b/private/Consumers/FbxConsumer/FbxConsumer.cpp index 2d520d41..9b04ceaa 100644 --- a/private/Consumers/FbxConsumer/FbxConsumer.cpp +++ b/private/Consumers/FbxConsumer/FbxConsumer.cpp @@ -23,4 +23,19 @@ void FbxConsumer::Execute(const cd::SceneDatabase* pSceneDatabase) m_pFbxConsumerImpl->Execute(pSceneDatabase); } +void FbxConsumer::EnableOption(FbxConsumerOptions option) +{ + m_pFbxConsumerImpl->GetOptions().Enable(option); +} + +void FbxConsumer::DisableOption(FbxConsumerOptions option) +{ + m_pFbxConsumerImpl->GetOptions().Disable(option); +} + +bool FbxConsumer::IsOptionEnabled(FbxConsumerOptions option) const +{ + return m_pFbxConsumerImpl->GetOptions().IsEnabled(option); +} + } \ No newline at end of file diff --git a/private/Consumers/FbxConsumer/FbxConsumerImpl.cpp b/private/Consumers/FbxConsumer/FbxConsumerImpl.cpp index eda5ec36..d22c439f 100644 --- a/private/Consumers/FbxConsumer/FbxConsumerImpl.cpp +++ b/private/Consumers/FbxConsumer/FbxConsumerImpl.cpp @@ -6,24 +6,33 @@ #include #include -// C/C++ #include +namespace +{ + +void PrintLog(const std::string& msg) +{ + printf("[AssetPipeline][FbxConsumer] %s\n", msg.c_str()); +} + +} + namespace cdtools { -FbxConsumerImpl::~FbxConsumerImpl() +FbxConsumerImpl::FbxConsumerImpl(std::string filePath) : + m_filePath(cd::MoveTemp(filePath)) { - if(m_pSDKScene) - { - m_pSDKScene->Destroy(); - } + // Default + m_options.Enable(FbxConsumerOptions::SaveAsASCII); + m_options.Enable(FbxConsumerOptions::ExportMaterial); + m_options.Enable(FbxConsumerOptions::ExportTexture); + m_options.Enable(FbxConsumerOptions::ExportStaticMesh); +} - if(m_pSDKExporter) - { - m_pSDKExporter->Destroy(); - } - +FbxConsumerImpl::~FbxConsumerImpl() +{ if(m_pSDKManager) { m_pSDKManager->Destroy(); @@ -34,92 +43,152 @@ void FbxConsumerImpl::Execute(const cd::SceneDatabase* pSceneDatabase) { // Init settings m_pSDKManager = fbxsdk::FbxManager::Create(); - fbxsdk::FbxIOSettings* pIOSettings = fbxsdk::FbxIOSettings::Create(m_pSDKManager, "IOSROOT"); - pIOSettings->SetBoolProp(EXP_FBX_MODEL, true); - pIOSettings->SetBoolProp(EXP_FBX_MATERIAL, false); - pIOSettings->SetBoolProp(EXP_FBX_TEXTURE, false); - pIOSettings->SetBoolProp(EXP_FBX_EMBEDDED, false); + auto* pIOSettings = fbxsdk::FbxIOSettings::Create(m_pSDKManager, IOSROOT); m_pSDKManager->SetIOSettings(pIOSettings); - // Scene - m_pSDKScene = fbxsdk::FbxScene::Create(m_pSDKManager, pSceneDatabase->GetName()); + fbxsdk::FbxScene* pScene = CreateScene(pSceneDatabase); + assert(pScene); // Build fbx scene by converting SceneDatabase for (const auto& mesh : pSceneDatabase->GetMeshes()) { - fbxsdk::FbxMesh* pFbxMesh = fbxsdk::FbxMesh::Create(m_pSDKScene, mesh.GetName()); - pFbxMesh->InitControlPoints(mesh.GetVertexCount()); + ExportMesh(pScene, mesh, pSceneDatabase); + } - fbxsdk::FbxGeometryElementNormal* pNormalElement = pFbxMesh->CreateElementNormal(); - assert(pNormalElement && "Failed to create fbx normal element."); - pNormalElement->SetMappingMode(fbxsdk::FbxGeometryElement::eByControlPoint); - pNormalElement->SetReferenceMode(fbxsdk::FbxGeometryElement::eDirect); + if (!ExportFbxFile(pScene)) + { + PrintLog("Error : Failed to export fbx file."); + } +} + +fbxsdk::FbxScene* FbxConsumerImpl::CreateScene(const cd::SceneDatabase* pSceneDatabase) +{ + auto* pScene = fbxsdk::FbxScene::Create(m_pSDKManager, pSceneDatabase->GetName()); + + // Tag source information. + auto* pDocument = fbxsdk::FbxDocumentInfo::Create(m_pSDKManager, "Document"); + pDocument->mTitle = "FBX Exporter"; + pDocument->mSubject = "Export FBX"; + pScene->SetSceneInfo(pDocument); + + // Set AxisSystem and Unit. + auto frontVector = fbxsdk::FbxAxisSystem::eParityOdd; + fbxsdk::FbxAxisSystem axisSystem(fbxsdk::FbxAxisSystem::eYAxis, frontVector, fbxsdk::FbxAxisSystem::eLeftHanded); + auto& globalSettings = pScene->GetGlobalSettings(); + globalSettings.SetAxisSystem(axisSystem); + globalSettings.SetOriginalUpAxis(axisSystem); + globalSettings.SetSystemUnit(fbxsdk::FbxSystemUnit::cm); + globalSettings.SetTimeMode(fbxsdk::FbxTime::eDefaultMode); + + return pScene; +} + +void FbxConsumerImpl::ExportMesh(fbxsdk::FbxScene* pScene, const cd::Mesh& mesh, const cd::SceneDatabase* pSceneDatabase) +{ + uint32_t controlPointCount = mesh.GetVertexCount(); + assert(controlPointCount > 0U && mesh.GetPolygonCount() > 0U); + + auto* pFbxMesh = fbxsdk::FbxMesh::Create(pScene, mesh.GetName()); + + // Export position. + pFbxMesh->InitControlPoints(controlPointCount); + fbxsdk::FbxVector4* pFbxVertices = pFbxMesh->GetControlPoints(); + for (uint32_t vertexIndex = 0U; vertexIndex < controlPointCount; ++vertexIndex) + { + const cd::Point& position = mesh.GetVertexPosition(vertexIndex); + pFbxVertices[vertexIndex].Set(position.x(), position.y(), position.z(), 1.0f); + } - fbxsdk::FbxGeometryElementUV* pUVElement = nullptr; - if(mesh.GetVertexUVSetCount() > 0U) + // Export polygon indices. + for (const auto& polygonGroup : mesh.GetPolygonGroups()) + { + for (const auto& polygon : polygonGroup) { - pUVElement = pFbxMesh->CreateElementUV("BaseUV"); - assert(pUVElement && "Failed to create fbx uv element."); - pUVElement->SetMappingMode(fbxsdk::FbxGeometryElement::eByControlPoint); - pUVElement->SetReferenceMode(fbxsdk::FbxGeometryElement::eDirect); + } + } - fbxsdk::FbxVector4* pFbxVertices = pFbxMesh->GetControlPoints(); - for(uint32_t vertexIndex = 0U; vertexIndex < mesh.GetVertexCount(); ++vertexIndex) - { - const cd::Point& position = mesh.GetVertexPosition(vertexIndex); - pFbxVertices[vertexIndex].Set(position.x(), position.y(), position.z(), 1.0f); + int baseLayerIndex = pFbxMesh->CreateLayer(); + assert(0 == baseLayerIndex); + fbxsdk::FbxLayer* pBaseLayer = pFbxMesh->GetLayer(baseLayerIndex); - const cd::Direction& normal = mesh.GetVertexNormal(vertexIndex); - pNormalElement->GetDirectArray().Add(fbxsdk::FbxVector4(normal.x(), normal.y(), normal.z(), 0.0f)); + // Export normal. + fbxsdk::FbxGeometryElementNormal* pNormalElement = pFbxMesh->CreateElementNormal(); + assert(pNormalElement && "Failed to create fbx normal element."); + pNormalElement->SetMappingMode(fbxsdk::FbxGeometryElement::eByControlPoint); + pNormalElement->SetReferenceMode(fbxsdk::FbxGeometryElement::eDirect); - // Only the first channel now - if (pUVElement) - { - const cd::UV& uv = mesh.GetVertexUV(0)[vertexIndex]; - pUVElement->GetDirectArray().Add(fbxsdk::FbxVector2(uv.x(), uv.y())); - } + fbxsdk::FbxGeometryElementUV* pUVElement = nullptr; + if (mesh.GetVertexUVSetCount() > 0U) + { + pUVElement = pFbxMesh->CreateElementUV("BaseUV"); + assert(pUVElement && "Failed to create fbx uv element."); + pUVElement->SetMappingMode(fbxsdk::FbxGeometryElement::eByControlPoint); + pUVElement->SetReferenceMode(fbxsdk::FbxGeometryElement::eDirect); + } + + for (uint32_t vertexIndex = 0U; vertexIndex < controlPointCount; ++vertexIndex) + { + const cd::Direction& normal = mesh.GetVertexNormal(vertexIndex); + pNormalElement->GetDirectArray().Add(fbxsdk::FbxVector4(normal.x(), normal.y(), normal.z(), 0.0f)); + + if (pUVElement) + { + const cd::UV& uv = mesh.GetVertexUV(0)[vertexIndex]; + pUVElement->GetDirectArray().Add(fbxsdk::FbxVector2(uv.x(), uv.y())); } + } - pFbxMesh->ReservePolygonCount(mesh.GetPolygonCount()); - for (const auto& polygonGroup : mesh.GetPolygonGroups()) + + pFbxMesh->ReservePolygonCount(mesh.GetPolygonCount()); + for (const auto& polygonGroup : mesh.GetPolygonGroups()) + { + for (const auto& polygon : polygonGroup) { - for (const auto& polygon : polygonGroup) + pFbxMesh->BeginPolygon(-1, -1, -1, false); + for (uint32_t index = 0U; index < polygon.size(); ++index) { - pFbxMesh->BeginPolygon(-1, -1, -1, false); - for (uint32_t index = 0U; index < polygon.size(); ++index) - { - pFbxMesh->AddPolygon(polygon[index].Data()); - } - pFbxMesh->EndPolygon(); + pFbxMesh->AddPolygon(polygon[index].Data()); } + pFbxMesh->EndPolygon(); } - - fbxsdk::FbxNode* pFbxNode = fbxsdk::FbxNode::Create(m_pSDKScene, pFbxMesh->GetName()); - pFbxNode->SetNodeAttribute(pFbxMesh); - pFbxNode->SetShadingMode(fbxsdk::FbxNode::EShadingMode::eWireFrame); - - fbxsdk::FbxVector4 translation(0.0, 0.0, 0.0, 0.0); - fbxsdk::FbxVector4 rotation(0.0, 0.0, 0.0, 0.0); - fbxsdk::FbxVector4 scale(1.0, 1.0, 1.0, 1.0); - pFbxNode->LclTranslation.Set(translation); - pFbxNode->LclRotation.Set(rotation); - pFbxNode->LclScaling.Set(scale); - - m_pSDKScene->GetRootNode()->AddChild(pFbxNode); } - // Export - m_pSDKExporter = fbxsdk::FbxExporter::Create(m_pSDKManager, ""); - int fileFormat = m_pSDKManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)"); - if (m_pSDKExporter->Initialize(m_filePath.c_str(), fileFormat)) + auto* pFbxNode = fbxsdk::FbxNode::Create(pScene, pFbxMesh->GetName()); + pFbxNode->SetNodeAttribute(pFbxMesh); + pFbxNode->SetShadingMode(fbxsdk::FbxNode::EShadingMode::eWireFrame); + + fbxsdk::FbxVector4 translation(0.0, 0.0, 0.0, 0.0); + fbxsdk::FbxVector4 rotation(0.0, 0.0, 0.0, 0.0); + fbxsdk::FbxVector4 scale(1.0, 1.0, 1.0, 1.0); + pFbxNode->LclTranslation.Set(translation); + pFbxNode->LclRotation.Set(rotation); + pFbxNode->LclScaling.Set(scale); + + pScene->GetRootNode()->AddChild(pFbxNode); +} + +bool FbxConsumerImpl::ExportFbxFile(fbxsdk::FbxScene* pScene) +{ + auto* pExporter = fbxsdk::FbxExporter::Create(m_pSDKManager, ""); + + int fileFormat; + if (IsOptionEnabled(FbxConsumerOptions::SaveAsASCII)) { - m_pSDKExporter->Export(m_pSDKScene); + fileFormat = m_pSDKManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)"); } else { - assert("Failed to export fbx scene"); + fileFormat = m_pSDKManager->GetIOPluginRegistry()->GetNativeWriterFormat(); + } + + pExporter->SetFileExportVersion(FBX_2018_00_COMPATIBLE, fbxsdk::FbxSceneRenamer::eNone); + if (!pExporter->Initialize(m_filePath.c_str(), fileFormat)) + { + return false; } + + return pExporter->Export(pScene); } } \ No newline at end of file diff --git a/private/Consumers/FbxConsumer/FbxConsumerImpl.h b/private/Consumers/FbxConsumer/FbxConsumerImpl.h index 42e99094..5d534415 100644 --- a/private/Consumers/FbxConsumer/FbxConsumerImpl.h +++ b/private/Consumers/FbxConsumer/FbxConsumerImpl.h @@ -1,13 +1,13 @@ #pragma once #include "Base/Template.h" - -#include +#include "Base/BitFlags.h" +#include "Consumers/FbxConsumer/FbxConsumerOptions.h" +#include "Scene/SceneDatabase.h" namespace fbxsdk { -class FbxExporter; class FbxManager; class FbxScene; @@ -27,19 +27,27 @@ class FbxConsumerImpl final { public: FbxConsumerImpl() = delete; - explicit FbxConsumerImpl(std::string filePath) : m_filePath(cd::MoveTemp(filePath)) {} + explicit FbxConsumerImpl(std::string filePath); FbxConsumerImpl(const FbxConsumerImpl&) = delete; FbxConsumerImpl& operator=(const FbxConsumerImpl&) = delete; FbxConsumerImpl(FbxConsumerImpl&&) = delete; FbxConsumerImpl& operator=(FbxConsumerImpl&&) = delete; ~FbxConsumerImpl(); + void Execute(const cd::SceneDatabase* pSceneDatabase); + fbxsdk::FbxScene* CreateScene(const cd::SceneDatabase* pSceneDatabase); + void ExportMesh(fbxsdk::FbxScene* pScene, const cd::Mesh& mesh, const cd::SceneDatabase* pSceneDatabase); + bool ExportFbxFile(fbxsdk::FbxScene* pScene); + + cd::BitFlags& GetOptions() { return m_options; } + const cd::BitFlags& GetOptions() const { return m_options; } + bool IsOptionEnabled(FbxConsumerOptions option) const { return m_options.IsEnabled(option); } private: - fbxsdk::FbxManager* m_pSDKManager = nullptr; - fbxsdk::FbxScene* m_pSDKScene = nullptr; - fbxsdk::FbxExporter* m_pSDKExporter = nullptr; + cd::BitFlags m_options; std::string m_filePath; + + fbxsdk::FbxManager* m_pSDKManager = nullptr; }; } \ No newline at end of file diff --git a/private/Producers/FbxProducer/FbxProducerImpl.cpp b/private/Producers/FbxProducer/FbxProducerImpl.cpp index 392d8826..6fcdf009 100644 --- a/private/Producers/FbxProducer/FbxProducerImpl.cpp +++ b/private/Producers/FbxProducer/FbxProducerImpl.cpp @@ -1064,10 +1064,11 @@ cd::MeshID FbxProducerImpl::ParseMesh(const fbxsdk::FbxMesh* pFbxMesh, cd::Scene for (uint32_t polygonVertexIndex = 0U; polygonVertexIndex < polygonVertexCount; ++polygonVertexIndex) { uint32_t controlPointIndex = pFbxMesh->GetPolygonVertex(polygonIndex, polygonVertexIndex); - polygon.push_back(controlPointIndex); - uint32_t vertexInstanceID = polygonVertexBeginIndex + polygonVertexIndex; - mesh.SetVertexInstanceID(controlPointIndex, vertexInstanceID); + mesh.SetVertexIDToInstance(controlPointIndex, vertexInstanceID); + mesh.SetVertexInstanceToID(vertexInstanceID, controlPointIndex); + + polygon.push_back(vertexInstanceID); } // Add polygon to according group split by material. diff --git a/private/Producers/FbxProducer/FbxProducerImpl.h b/private/Producers/FbxProducer/FbxProducerImpl.h index 9ee7ebaf..450be796 100644 --- a/private/Producers/FbxProducer/FbxProducerImpl.h +++ b/private/Producers/FbxProducer/FbxProducerImpl.h @@ -2,9 +2,7 @@ #include "Base/Template.h" #include "Base/BitFlags.h" -#include "Math/Transform.hpp" #include "Producers/FbxProducer/FbxProducerOptions.h" -#include "Scene/MaterialTextureType.h" #include "Scene/ObjectIDGenerator.h" #include @@ -103,9 +101,9 @@ class FbxProducerImpl final void ParseAnimation(fbxsdk::FbxScene* scene, cd::SceneDatabase* pSceneDatabase); private: - std::string m_filePath; cd::BitFlags m_options; - + std::string m_filePath; + fbxsdk::FbxManager* m_pSDKManager = nullptr; std::unique_ptr m_pSDKGeometryConverter; diff --git a/private/Scene/Mesh.cpp b/private/Scene/Mesh.cpp index 2fa7b8cd..656d44c1 100644 --- a/private/Scene/Mesh.cpp +++ b/private/Scene/Mesh.cpp @@ -9,14 +9,14 @@ namespace cd PIMPL_SCENE_CLASS(Mesh); PIMPL_SIMPLE_TYPE_APIS(Mesh, ID); -PIMPL_SIMPLE_TYPE_APIS(Mesh, VertexAttributeCount); PIMPL_STRING_TYPE_APIS(Mesh, Name); PIMPL_COMPLEX_TYPE_APIS(Mesh, AABB); PIMPL_COMPLEX_TYPE_APIS(Mesh, VertexFormat); PIMPL_VECTOR_TYPE_APIS(Mesh, MaterialID); PIMPL_VECTOR_TYPE_APIS(Mesh, BlendShapeID); PIMPL_VECTOR_TYPE_APIS(Mesh, SkinID); -PIMPL_VECTOR_TYPE_APIS(Mesh, VertexInstanceID); +PIMPL_VECTOR_TYPE_APIS(Mesh, VertexInstanceToID); +PIMPL_VECTOR_TYPE_APIS(Mesh, VertexIDToInstance); PIMPL_VECTOR_TYPE_APIS(Mesh, VertexPosition); PIMPL_VECTOR_TYPE_APIS(Mesh, VertexNormal); PIMPL_VECTOR_TYPE_APIS(Mesh, VertexTangent); @@ -36,9 +36,9 @@ void Mesh::Init(uint32_t vertexCount) m_pMeshImpl->Init(vertexCount); } -void Mesh::Init(uint32_t vertexPositionCount, uint32_t vertexAttributeCount) +void Mesh::Init(uint32_t vertexCount, uint32_t vertexInstanceCount) { - m_pMeshImpl->Init(vertexPositionCount, vertexAttributeCount); + m_pMeshImpl->Init(vertexCount, vertexInstanceCount); } uint32_t Mesh::GetVertexCount() const diff --git a/private/Scene/MeshImpl.cpp b/private/Scene/MeshImpl.cpp index 50026973..c2da0ed3 100644 --- a/private/Scene/MeshImpl.cpp +++ b/private/Scene/MeshImpl.cpp @@ -158,41 +158,50 @@ void MeshImpl::FromHalfEdgeMesh(const HalfEdgeMesh& halfEdgeMesh, ConvertStrateg void MeshImpl::Init(uint32_t vertexCount) { SetVertexPositionCount(vertexCount); - SetVertexInstanceIDCount(0U); + SetVertexIDToInstanceCount(0U); + SetVertexInstanceToIDCount(0U); InitVertexAttributes(vertexCount); } -void MeshImpl::Init(uint32_t vertexPositionCount, uint32_t vertexAttributeCount) +void MeshImpl::Init(uint32_t vertexCount, uint32_t vertexInstanceCount) { - SetVertexPositionCount(vertexPositionCount); - SetVertexInstanceIDCount(vertexPositionCount); + if (0U == vertexInstanceCount) + { + Init(vertexCount); + } + else + { + SetVertexPositionCount(vertexCount); + SetVertexIDToInstanceCount(vertexCount); + SetVertexInstanceToIDCount(vertexInstanceCount); - InitVertexAttributes(vertexAttributeCount); + InitVertexAttributes(vertexInstanceCount); + } } -void MeshImpl::InitVertexAttributes(uint32_t vertexAttributeCount) +void MeshImpl::InitVertexAttributes(uint32_t vertexInstanceCount) { - SetVertexAttributeCount(vertexAttributeCount); - SetVertexNormalCount(GetVertexAttributeCount()); - SetVertexTangentCount(GetVertexAttributeCount()); - SetVertexBiTangentCount(GetVertexAttributeCount()); + SetVertexNormalCount(vertexInstanceCount); + SetVertexTangentCount(vertexInstanceCount); + SetVertexBiTangentCount(vertexInstanceCount); for (uint32_t setIndex = 0U; setIndex < GetVertexUVSetCount(); ++setIndex) { - m_vertexUVSets[setIndex].resize(GetVertexAttributeCount()); + m_vertexUVSets[setIndex].resize(vertexInstanceCount); } for (uint32_t setIndex = 0U; setIndex < m_vertexColorSetCount; ++setIndex) { - m_vertexColorSets[setIndex].resize(GetVertexAttributeCount()); + m_vertexColorSets[setIndex].resize(vertexInstanceCount); } } void MeshImpl::ShrinkToFit() { GetVertexPositions().shrink_to_fit(); - GetVertexInstanceIDs().shrink_to_fit(); + GetVertexInstanceToIDs().shrink_to_fit(); + GetVertexIDToInstances().shrink_to_fit(); GetVertexNormals().shrink_to_fit(); GetVertexTangents().shrink_to_fit(); @@ -348,7 +357,7 @@ void MeshImpl::SetVertexUVSetCount(uint32_t setCount) m_vertexUVSetCount = setCount; for(uint32_t setIndex = 0U; setIndex < m_vertexUVSetCount; ++setIndex) { - m_vertexUVSets[setIndex].resize(GetVertexAttributeCount()); + m_vertexUVSets[setIndex].resize(GetVertexInstanceToIDCount()); } } @@ -362,7 +371,7 @@ void MeshImpl::SetVertexColorSetCount(uint32_t setCount) m_vertexColorSetCount = setCount; for (uint32_t setIndex = 0U; setIndex < m_vertexColorSetCount; ++setIndex) { - m_vertexColorSets[setIndex].resize(GetVertexAttributeCount()); + m_vertexColorSets[setIndex].resize(GetVertexInstanceToIDCount()); } } diff --git a/private/Scene/MeshImpl.h b/private/Scene/MeshImpl.h index 4d239790..651804f9 100644 --- a/private/Scene/MeshImpl.h +++ b/private/Scene/MeshImpl.h @@ -27,14 +27,14 @@ class MeshImpl final DECLARE_SCENE_IMPL_CLASS(Mesh); IMPLEMENT_SIMPLE_TYPE_APIS(Mesh, ID); - IMPLEMENT_SIMPLE_TYPE_APIS(Mesh, VertexAttributeCount); IMPLEMENT_STRING_TYPE_APIS(Mesh, Name); IMPLEMENT_COMPLEX_TYPE_APIS(Mesh, AABB); IMPLEMENT_COMPLEX_TYPE_APIS(Mesh, VertexFormat); IMPLEMENT_VECTOR_TYPE_APIS(Mesh, MaterialID); IMPLEMENT_VECTOR_TYPE_APIS(Mesh, BlendShapeID); IMPLEMENT_VECTOR_TYPE_APIS(Mesh, SkinID); - IMPLEMENT_VECTOR_TYPE_APIS(Mesh, VertexInstanceID); + IMPLEMENT_VECTOR_TYPE_APIS(Mesh, VertexInstanceToID); + IMPLEMENT_VECTOR_TYPE_APIS(Mesh, VertexIDToInstance); IMPLEMENT_VECTOR_TYPE_APIS(Mesh, VertexPosition); IMPLEMENT_VECTOR_TYPE_APIS(Mesh, VertexNormal); IMPLEMENT_VECTOR_TYPE_APIS(Mesh, VertexTangent); @@ -42,8 +42,8 @@ class MeshImpl final IMPLEMENT_VECTOR_TYPE_APIS(Mesh, PolygonGroup); void Init(uint32_t vertexCount); - void Init(uint32_t vertexPositionCount, uint32_t vertexAttributeCount); - void InitVertexAttributes(uint32_t vertexAttributeCount); + void Init(uint32_t vertexCount, uint32_t vertexInstanceCount); + void InitVertexAttributes(uint32_t vertexInstanceCount); void ShrinkToFit(); uint32_t GetVertexCount() const { return GetVertexPositionCount(); } @@ -76,13 +76,14 @@ class MeshImpl final uint32_t blendShapeCount; uint32_t skinCount; uint32_t vertexCount; + uint32_t vertexInstanceCount; uint32_t vertexUVSetCount; uint32_t vertexColorSetCount; uint32_t polygonGroupCount; inputArchive >> GetName() >> GetID().Data() >> GetAABB() >> materialCount >> blendShapeCount >> skinCount - >> vertexCount >> GetVertexAttributeCount() >> vertexUVSetCount >> vertexColorSetCount + >> vertexCount >> vertexInstanceCount >> vertexUVSetCount >> vertexColorSetCount >> polygonGroupCount; GetVertexFormat() << inputArchive; @@ -96,9 +97,10 @@ class MeshImpl final SetSkinIDCount(skinCount); inputArchive.ImportBuffer(GetSkinIDs().data()); - Init(vertexCount, GetVertexAttributeCount()); + Init(vertexCount, vertexInstanceCount); + inputArchive.ImportBuffer(GetVertexInstanceToIDs().data()); + inputArchive.ImportBuffer(GetVertexIDToInstances().data()); inputArchive.ImportBuffer(GetVertexPositions().data()); - inputArchive.ImportBuffer(GetVertexInstanceIDs().data()); inputArchive.ImportBuffer(GetVertexNormals().data()); inputArchive.ImportBuffer(GetVertexTangents().data()); inputArchive.ImportBuffer(GetVertexBiTangents().data()); @@ -140,15 +142,16 @@ class MeshImpl final { outputArchive << GetName() << GetID().Data() << GetAABB() << GetMaterialIDCount() << GetBlendShapeIDCount() << GetSkinIDCount() - << GetVertexPositionCount() << GetVertexAttributeCount() << GetVertexUVSetCount() << GetVertexColorSetCount() + << GetVertexPositionCount() << GetVertexInstanceToIDCount() << GetVertexUVSetCount() << GetVertexColorSetCount() << GetPolygonGroupCount(); GetVertexFormat() >> outputArchive; outputArchive.ExportBuffer(GetMaterialIDs().data(), GetMaterialIDs().size()); outputArchive.ExportBuffer(GetBlendShapeIDs().data(), GetBlendShapeIDs().size()); outputArchive.ExportBuffer(GetSkinIDs().data(), GetSkinIDs().size()); + outputArchive.ExportBuffer(GetVertexInstanceToIDs().data(), GetVertexInstanceToIDs().size()); + outputArchive.ExportBuffer(GetVertexIDToInstances().data(), GetVertexIDToInstances().size()); outputArchive.ExportBuffer(GetVertexPositions().data(), GetVertexPositions().size()); - outputArchive.ExportBuffer(GetVertexInstanceIDs().data(), GetVertexInstanceIDs().size()); outputArchive.ExportBuffer(GetVertexNormals().data(), GetVertexNormals().size()); outputArchive.ExportBuffer(GetVertexTangents().data(), GetVertexTangents().size()); outputArchive.ExportBuffer(GetVertexBiTangents().data(), GetVertexBiTangents().size()); diff --git a/private/Scene/SceneDatabaseImpl.cpp b/private/Scene/SceneDatabaseImpl.cpp index 5bae53e9..2bd42d37 100644 --- a/private/Scene/SceneDatabaseImpl.cpp +++ b/private/Scene/SceneDatabaseImpl.cpp @@ -197,13 +197,15 @@ void SceneDatabaseImpl::Dump() const for (const auto& mesh : GetMeshes()) { printf("[Mesh %u] Name = %s, VertexCount = %u\n", mesh.GetID().Data(), mesh.GetName(), mesh.GetVertexCount()); + printf("\tPolygonCount = %u, VertexInstanceCount = %u\n", mesh.GetPolygonCount(), mesh.GetVertexInstanceToIDCount()); const auto& polygonGroups = mesh.GetPolygonGroups(); for (uint32_t polygonGroupIndex = 0U; polygonGroupIndex < polygonGroups.size(); ++polygonGroupIndex) { auto& polygonGroup = polygonGroups[polygonGroupIndex]; - auto materialID = mesh.GetMaterialID(polygonGroupIndex); printf("\t[PolygonGroup %u] PolygonCount = %u\n", polygonGroupIndex, static_cast(polygonGroup.size())); - printf("\t\t[Associated Material %u] Name = %s\n", materialID.Data(), GetMaterial(materialID.Data()).GetName()); + + auto materialID = mesh.GetMaterialID(polygonGroupIndex); + printf("\t\t[Associated Material %u] Name = %s\n", materialID.Data(), materialID.IsValid() ? GetMaterial(materialID.Data()).GetName() : ""); if (materialID.IsValid()) { materialDrawMeshPolygonGroupIDs[materialID][mesh.GetID()].push_back(polygonGroupIndex); diff --git a/public/Consumers/FbxConsumer/FbxConsumer.h b/public/Consumers/FbxConsumer/FbxConsumer.h index 5832a6e4..f18ecd51 100644 --- a/public/Consumers/FbxConsumer/FbxConsumer.h +++ b/public/Consumers/FbxConsumer/FbxConsumer.h @@ -1,5 +1,6 @@ #pragma once +#include "Consumers/FbxConsumer/FbxConsumerOptions.h" #include "Framework/IConsumer.h" namespace cd @@ -26,6 +27,10 @@ class TOOL_API FbxConsumer final : public IConsumer virtual ~FbxConsumer(); virtual void Execute(const cd::SceneDatabase* pSceneDatabase) override; + void EnableOption(FbxConsumerOptions option); + void DisableOption(FbxConsumerOptions option); + bool IsOptionEnabled(FbxConsumerOptions option) const; + private: FbxConsumerImpl* m_pFbxConsumerImpl; }; diff --git a/public/Consumers/FbxConsumer/FbxConsumerOptions.h b/public/Consumers/FbxConsumer/FbxConsumerOptions.h new file mode 100644 index 00000000..172a327e --- /dev/null +++ b/public/Consumers/FbxConsumer/FbxConsumerOptions.h @@ -0,0 +1,22 @@ +#pragma once + +namespace cdtools +{ + +enum class FbxConsumerOptions +{ + // File Format + SaveAsASCII, + + // Scene objects + ExportAnimation, + ExportBlendShape, + ExportMaterial, + ExportTexture, + ExportLight, + ExportSkeleton, + ExportSkeletalMesh, + ExportStaticMesh, +}; + +} \ No newline at end of file diff --git a/public/Scene/APITypeTraits.inl b/public/Scene/APITypeTraits.inl index 0f842fb3..2702ecb8 100644 --- a/public/Scene/APITypeTraits.inl +++ b/public/Scene/APITypeTraits.inl @@ -149,7 +149,6 @@ struct MeshTypeTraits { // Simple using ID = cd::MeshID; - using VertexAttributeCount = uint32_t; // String using Name = std::string; @@ -162,8 +161,9 @@ struct MeshTypeTraits using MaterialID = cd::MaterialID; using BlendShapeID = cd::BlendShapeID; using SkinID = cd::SkinID; + using VertexInstanceToID = uint32_t; + using VertexIDToInstance = uint32_t; using VertexPosition = cd::Point; - using VertexInstanceID = uint32_t; using VertexNormal = cd::Direction; using VertexTangent = cd::Direction; using VertexBiTangent = cd::Direction; diff --git a/public/Scene/Mesh.h b/public/Scene/Mesh.h index 49d36c4b..ec94ffc3 100644 --- a/public/Scene/Mesh.h +++ b/public/Scene/Mesh.h @@ -25,14 +25,14 @@ class CORE_API Mesh final DECLARE_SCENE_CLASS(Mesh); EXPORT_SIMPLE_TYPE_APIS(Mesh, ID); - EXPORT_SIMPLE_TYPE_APIS(Mesh, VertexAttributeCount); EXPORT_STRING_TYPE_APIS(Mesh, Name); EXPORT_COMPLEX_TYPE_APIS(Mesh, AABB); EXPORT_COMPLEX_TYPE_APIS(Mesh, VertexFormat); EXPORT_VECTOR_TYPE_APIS(Mesh, MaterialID); EXPORT_VECTOR_TYPE_APIS(Mesh, BlendShapeID); EXPORT_VECTOR_TYPE_APIS(Mesh, SkinID); - EXPORT_VECTOR_TYPE_APIS(Mesh, VertexInstanceID); + EXPORT_VECTOR_TYPE_APIS(Mesh, VertexInstanceToID); + EXPORT_VECTOR_TYPE_APIS(Mesh, VertexIDToInstance); EXPORT_VECTOR_TYPE_APIS(Mesh, VertexPosition); EXPORT_VECTOR_TYPE_APIS(Mesh, VertexNormal); EXPORT_VECTOR_TYPE_APIS(Mesh, VertexTangent); @@ -40,7 +40,7 @@ class CORE_API Mesh final EXPORT_VECTOR_TYPE_APIS(Mesh, PolygonGroup); void Init(uint32_t vertexCount); - void Init(uint32_t vertexPositionCount, uint32_t vertexAttributeCount); + void Init(uint32_t vertexCount, uint32_t vertexInstanceCount); uint32_t GetVertexCount() const; uint32_t GetPolygonCount() const; diff --git a/public/Utilities/MeshUtils.hpp b/public/Utilities/MeshUtils.hpp index 6b3f4fb9..9fc9adca 100644 --- a/public/Utilities/MeshUtils.hpp +++ b/public/Utilities/MeshUtils.hpp @@ -30,7 +30,7 @@ std::optional BuildVertexBufferForStaticMesh(const cd::Mesh& mesh, vbDataSize += dataSize; }; - bool mappingSurfaceAttributes = mesh.GetVertexInstanceIDCount() > 0U; + bool mappingSurfaceAttributes = mesh.GetVertexIDToInstanceCount() > 0U; for (uint32_t vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) { if (containsPosition) @@ -42,7 +42,7 @@ std::optional BuildVertexBufferForStaticMesh(const cd::Mesh& mesh, uint32_t vertexInstanceID = vertexIndex; if (mappingSurfaceAttributes) { - vertexInstanceID = mesh.GetVertexInstanceID(vertexIndex); + vertexInstanceID = mesh.GetVertexIDToInstance(vertexIndex); } if (containsNormal) @@ -147,7 +147,7 @@ std::optional BuildVertexBufferForSkeletalMesh(const cd::Mesh& mes vbDataSize += dataSize; }; - bool mappingSurfaceAttributes = mesh.GetVertexInstanceIDCount() > 0U; + bool mappingSurfaceAttributes = mesh.GetVertexIDToInstanceCount() > 0U; for (uint32_t vertexIndex = 0; vertexIndex < vertexCount; ++vertexIndex) { if (containsPosition) @@ -159,7 +159,7 @@ std::optional BuildVertexBufferForSkeletalMesh(const cd::Mesh& mes uint32_t vertexInstanceID = vertexIndex; if (mappingSurfaceAttributes) { - vertexInstanceID = mesh.GetVertexInstanceID(vertexIndex); + vertexInstanceID = mesh.GetVertexIDToInstance(vertexIndex); } if (containsNormal) @@ -246,24 +246,34 @@ std::optional BuildIndexBufferesForPolygonGroup(const cd::Mesh& mes ibDataSize += dataSize; }; + bool mappingInstanceToID = mesh.GetVertexInstanceToIDCount() > 0U; for (const auto& polygon : mesh.GetPolygonGroup(polygonGroupIndex)) { - if (useU16Index) + for (auto instanceID : polygon) { - // cd::Mesh always uses uint32_t to store index so it is not convenient to copy servals elements at the same time. - for (auto vertexID : polygon) + uint32_t vertexIndex; + if (mappingInstanceToID) + { + vertexIndex = mesh.GetVertexInstanceToID(instanceID.Data()); + } + else + { + vertexIndex = instanceID.Data(); + } + + if (useU16Index) + { + // Endian safe. Can optimize for little endian to avoid cast. + uint16_t vertexIndex16 = static_cast(vertexIndex); + FillIndexBuffer(&vertexIndex16, indexTypeSize); + } + else { - uint16_t vertexIndex = static_cast(vertexID.Data()); FillIndexBuffer(&vertexIndex, indexTypeSize); } } - else - { - FillIndexBuffer(polygon.data(), static_cast(polygon.size() * indexTypeSize)); - } } - return indexBuffer; } From 8161fd7786bf184c8e0a20a35a65c1ef958ec56a Mon Sep 17 00:00:00 2001 From: T-rvw <429601557@qq.com> Date: Mon, 15 Jan 2024 15:31:15 +0800 Subject: [PATCH 2/2] correct polygon group and materials --- .../Consumers/FbxConsumer/FbxConsumerImpl.cpp | 180 +++++++++++++----- .../Consumers/FbxConsumer/FbxConsumerImpl.h | 7 +- private/Scene/Mesh.cpp | 5 + private/Scene/MeshImpl.cpp | 22 ++- private/Scene/MeshImpl.h | 1 + public/Scene/Mesh.h | 1 + 6 files changed, 161 insertions(+), 55 deletions(-) diff --git a/private/Consumers/FbxConsumer/FbxConsumerImpl.cpp b/private/Consumers/FbxConsumer/FbxConsumerImpl.cpp index d22c439f..cc8be704 100644 --- a/private/Consumers/FbxConsumer/FbxConsumerImpl.cpp +++ b/private/Consumers/FbxConsumer/FbxConsumerImpl.cpp @@ -7,6 +7,7 @@ #include #include +#include namespace { @@ -49,10 +50,23 @@ void FbxConsumerImpl::Execute(const cd::SceneDatabase* pSceneDatabase) fbxsdk::FbxScene* pScene = CreateScene(pSceneDatabase); assert(pScene); + // Create a root fbx node. + auto* pRootNode = fbxsdk::FbxNode::Create(pScene, "Root"); + pRootNode->SetShadingMode(fbxsdk::FbxNode::EShadingMode::eTextureShading); + + fbxsdk::FbxVector4 translation(0.0, 0.0, 0.0, 0.0); + fbxsdk::FbxVector4 rotation(0.0, 0.0, 0.0, 0.0); + fbxsdk::FbxVector4 scale(1.0, 1.0, 1.0, 1.0); + pRootNode->LclTranslation.Set(translation); + pRootNode->LclRotation.Set(rotation); + pRootNode->LclScaling.Set(scale); + + pScene->GetRootNode()->AddChild(pRootNode); + // Build fbx scene by converting SceneDatabase for (const auto& mesh : pSceneDatabase->GetMeshes()) { - ExportMesh(pScene, mesh, pSceneDatabase); + ExportMesh(pScene, pRootNode, mesh, pSceneDatabase); } if (!ExportFbxFile(pScene)) @@ -83,89 +97,159 @@ fbxsdk::FbxScene* FbxConsumerImpl::CreateScene(const cd::SceneDatabase* pSceneDa return pScene; } -void FbxConsumerImpl::ExportMesh(fbxsdk::FbxScene* pScene, const cd::Mesh& mesh, const cd::SceneDatabase* pSceneDatabase) +fbxsdk::FbxFileTexture* FbxConsumerImpl::ExportTexture(fbxsdk::FbxScene* pScene, cd::TextureID textureID, const cd::SceneDatabase* pSceneDatabase) { - uint32_t controlPointCount = mesh.GetVertexCount(); - assert(controlPointCount > 0U && mesh.GetPolygonCount() > 0U); + if (!textureID.IsValid() || textureID.Data() >= pSceneDatabase->GetTextureCount()) + { + PrintLog(std::format("Warning : Texture missing at ID : {}", textureID.Data())); + return nullptr; + } - auto* pFbxMesh = fbxsdk::FbxMesh::Create(pScene, mesh.GetName()); + const cd::Texture& texture = pSceneDatabase->GetTexture(textureID.Data()); + const char* pTextureName = texture.GetName(); + auto* pTexture = static_cast(pScene->GetTexture(pTextureName)); + if (pTexture) + { + return pTexture; + } - // Export position. - pFbxMesh->InitControlPoints(controlPointCount); - fbxsdk::FbxVector4* pFbxVertices = pFbxMesh->GetControlPoints(); - for (uint32_t vertexIndex = 0U; vertexIndex < controlPointCount; ++vertexIndex) + // TODO : support other texture types. + pTexture = fbxsdk::FbxFileTexture::Create(pScene, pTextureName); + pTexture->SetFileName(texture.GetPath()); + pTexture->SetTextureUse(FbxTexture::eStandard); + pTexture->SetMappingType(FbxTexture::eUV); + return pTexture; +} + +fbxsdk::FbxSurfaceMaterial* FbxConsumerImpl::ExportMaterial(fbxsdk::FbxScene* pScene, fbxsdk::FbxNode* pNode, cd::MaterialID materialID, const cd::SceneDatabase* pSceneDatabase) +{ + bool useDefaultMaterial = !materialID.IsValid() || materialID.Data() >= pSceneDatabase->GetMaterialCount(); + if (useDefaultMaterial) { - const cd::Point& position = mesh.GetVertexPosition(vertexIndex); - pFbxVertices[vertexIndex].Set(position.x(), position.y(), position.z(), 1.0f); + constexpr const char* DefaultMaterialName = "Default"; + fbxsdk::FbxSurfaceMaterial* pFbxMaterial = pScene->GetMaterial(DefaultMaterialName); + if (!pFbxMaterial) + { + auto* pLambert = fbxsdk::FbxSurfaceLambert::Create(pScene, DefaultMaterialName); + pLambert->Diffuse.Set(fbxsdk::FbxDouble3(0.72)); + pFbxMaterial = pLambert; + } + + return pFbxMaterial; } - // Export polygon indices. - for (const auto& polygonGroup : mesh.GetPolygonGroups()) + const cd::Material& material = pSceneDatabase->GetMaterial(materialID.Data()); + const char* pMaterialName = material.GetName(); + fbxsdk::FbxSurfaceMaterial* pFbxMaterial = pScene->GetMaterial(pMaterialName); + if (pFbxMaterial) { - for (const auto& polygon : polygonGroup) + return pFbxMaterial; + } + + pFbxMaterial = fbxsdk::FbxSurfaceLambert::Create(m_pSDKManager, pMaterialName); + + // Fill parameter info. + // TODO. + + // Fill texture info. + static std::map MapTextureTypeToFbxPropertyName; + MapTextureTypeToFbxPropertyName[cd::MaterialTextureType::BaseColor] = fbxsdk::FbxSurfaceMaterial::sDiffuse; + MapTextureTypeToFbxPropertyName[cd::MaterialTextureType::Normal] = fbxsdk::FbxSurfaceMaterial::sNormalMap; + MapTextureTypeToFbxPropertyName[cd::MaterialTextureType::Emissive] = fbxsdk::FbxSurfaceMaterial::sEmissive; + for (int textureTypeValue = 0; textureTypeValue < nameof::enum_count(); ++textureTypeValue) + { + auto textureType = static_cast(textureTypeValue); + auto itProperty = MapTextureTypeToFbxPropertyName.find(textureType); + if (itProperty == MapTextureTypeToFbxPropertyName.end()) { + continue; + } + fbxsdk::FbxProperty textureProperty = pFbxMaterial->FindProperty(itProperty->second); + assert(textureProperty.IsValid()); // Wrong mapping? + if (material.IsTextureSetup(textureType)) + { + fbxsdk::FbxFileTexture* pFileTexture = ExportTexture(pScene, material.GetTextureID(textureType), pSceneDatabase); + if (pFileTexture) + { + pFileTexture->ConnectDstProperty(textureProperty); + } } } + return pFbxMaterial; +} + +void FbxConsumerImpl::ExportMesh(fbxsdk::FbxScene* pScene, fbxsdk::FbxNode* pNode, const cd::Mesh& mesh, const cd::SceneDatabase* pSceneDatabase) +{ + uint32_t vertexCount = mesh.GetVertexCount(); + uint32_t polygonCount = mesh.GetPolygonCount(); + assert(vertexCount > 0U && polygonCount > 0U); + + auto* pFbxMesh = fbxsdk::FbxMesh::Create(pScene, mesh.GetName()); + pNode->SetNodeAttribute(pFbxMesh); + + // Export position. + pFbxMesh->InitControlPoints(vertexCount); + fbxsdk::FbxVector4* pFbxVertices = pFbxMesh->GetControlPoints(); + for (uint32_t vertexIndex = 0U; vertexIndex < vertexCount; ++vertexIndex) + { + const cd::Point& position = mesh.GetVertexPosition(vertexIndex); + pFbxVertices[vertexIndex].Set(position.x(), -position.y(), position.z(), 1.0f); + } + + // Create mesh base layer. int baseLayerIndex = pFbxMesh->CreateLayer(); assert(0 == baseLayerIndex); fbxsdk::FbxLayer* pBaseLayer = pFbxMesh->GetLayer(baseLayerIndex); - // Export normal. - fbxsdk::FbxGeometryElementNormal* pNormalElement = pFbxMesh->CreateElementNormal(); - assert(pNormalElement && "Failed to create fbx normal element."); + // Create base normal for every vertex which directly maps to control point. + auto* pNormalElement = fbxsdk::FbxLayerElementNormal::Create(pFbxMesh, "BaseNormal"); pNormalElement->SetMappingMode(fbxsdk::FbxGeometryElement::eByControlPoint); pNormalElement->SetReferenceMode(fbxsdk::FbxGeometryElement::eDirect); + pBaseLayer->SetNormals(pNormalElement); - fbxsdk::FbxGeometryElementUV* pUVElement = nullptr; - if (mesh.GetVertexUVSetCount() > 0U) + for (uint32_t vertexIndex = 0U; vertexIndex < vertexCount; ++vertexIndex) { - pUVElement = pFbxMesh->CreateElementUV("BaseUV"); - assert(pUVElement && "Failed to create fbx uv element."); - pUVElement->SetMappingMode(fbxsdk::FbxGeometryElement::eByControlPoint); - pUVElement->SetReferenceMode(fbxsdk::FbxGeometryElement::eDirect); + const cd::Direction& normal = mesh.GetVertexNormal(vertexIndex); + pNormalElement->GetDirectArray().Add(fbxsdk::FbxVector4(normal.x(), normal.y(), normal.z(), 0.0f)); } - for (uint32_t vertexIndex = 0U; vertexIndex < controlPointCount; ++vertexIndex) + // Create base color uv. + if (mesh.GetVertexUVSetCount() > 0U) { - const cd::Direction& normal = mesh.GetVertexNormal(vertexIndex); - pNormalElement->GetDirectArray().Add(fbxsdk::FbxVector4(normal.x(), normal.y(), normal.z(), 0.0f)); + auto* pAlbedoUVElement = fbxsdk::FbxLayerElementUV::Create(pFbxMesh, "Albedo"); + pAlbedoUVElement->SetMappingMode(fbxsdk::FbxGeometryElement::eByControlPoint); + pAlbedoUVElement->SetReferenceMode(fbxsdk::FbxGeometryElement::eDirect); + pBaseLayer->SetUVs(pAlbedoUVElement, fbxsdk::FbxLayerElement::eTextureDiffuse); - if (pUVElement) + for (uint32_t vertexIndex = 0U; vertexIndex < vertexCount; ++vertexIndex) { - const cd::UV& uv = mesh.GetVertexUV(0)[vertexIndex]; - pUVElement->GetDirectArray().Add(fbxsdk::FbxVector2(uv.x(), uv.y())); + const cd::UV& uv = mesh.GetVertexUV(0U)[vertexIndex]; + pAlbedoUVElement->GetDirectArray().Add(fbxsdk::FbxVector2(uv.x(), 1.0f - uv.y())); } } - - pFbxMesh->ReservePolygonCount(mesh.GetPolygonCount()); - for (const auto& polygonGroup : mesh.GetPolygonGroups()) + // Export polygon indices per material. + pFbxMesh->ReservePolygonCount(polygonCount); + for (uint32_t materialIndex = 0U, materialCount = mesh.GetMaterialIDCount(); materialIndex < materialCount; ++materialIndex) { + cd::MaterialID materialID = mesh.GetMaterialID(materialIndex); + fbxsdk::FbxSurfaceMaterial* pMaterial = ExportMaterial(pScene, pNode, materialID, pSceneDatabase); + assert(pMaterial); // If nullptr, may cause a wrong mapping result. + uint32_t actualMaterialIndex = pNode->AddMaterial(pMaterial); + + const cd::PolygonGroup& polygonGroup = mesh.GetPolygonGroup(materialIndex); for (const auto& polygon : polygonGroup) { - pFbxMesh->BeginPolygon(-1, -1, -1, false); - for (uint32_t index = 0U; index < polygon.size(); ++index) + pFbxMesh->BeginPolygon(actualMaterialIndex); + for (auto vertexID : polygon) { - pFbxMesh->AddPolygon(polygon[index].Data()); + pFbxMesh->AddPolygon(vertexID.Data()); } pFbxMesh->EndPolygon(); } } - - auto* pFbxNode = fbxsdk::FbxNode::Create(pScene, pFbxMesh->GetName()); - pFbxNode->SetNodeAttribute(pFbxMesh); - pFbxNode->SetShadingMode(fbxsdk::FbxNode::EShadingMode::eWireFrame); - - fbxsdk::FbxVector4 translation(0.0, 0.0, 0.0, 0.0); - fbxsdk::FbxVector4 rotation(0.0, 0.0, 0.0, 0.0); - fbxsdk::FbxVector4 scale(1.0, 1.0, 1.0, 1.0); - pFbxNode->LclTranslation.Set(translation); - pFbxNode->LclRotation.Set(rotation); - pFbxNode->LclScaling.Set(scale); - - pScene->GetRootNode()->AddChild(pFbxNode); } bool FbxConsumerImpl::ExportFbxFile(fbxsdk::FbxScene* pScene) diff --git a/private/Consumers/FbxConsumer/FbxConsumerImpl.h b/private/Consumers/FbxConsumer/FbxConsumerImpl.h index 5d534415..555caba1 100644 --- a/private/Consumers/FbxConsumer/FbxConsumerImpl.h +++ b/private/Consumers/FbxConsumer/FbxConsumerImpl.h @@ -8,8 +8,11 @@ namespace fbxsdk { +class FbxFileTexture; class FbxManager; +class FbxNode; class FbxScene; +class FbxSurfaceMaterial; } @@ -36,7 +39,9 @@ class FbxConsumerImpl final void Execute(const cd::SceneDatabase* pSceneDatabase); fbxsdk::FbxScene* CreateScene(const cd::SceneDatabase* pSceneDatabase); - void ExportMesh(fbxsdk::FbxScene* pScene, const cd::Mesh& mesh, const cd::SceneDatabase* pSceneDatabase); + fbxsdk::FbxFileTexture* ExportTexture(fbxsdk::FbxScene* pScene, cd::TextureID textureID, const cd::SceneDatabase* pSceneDatabase); + fbxsdk::FbxSurfaceMaterial* ExportMaterial(fbxsdk::FbxScene* pScene, fbxsdk::FbxNode* pNode, cd::MaterialID materialID, const cd::SceneDatabase* pSceneDatabase); + void ExportMesh(fbxsdk::FbxScene* pScene, fbxsdk::FbxNode* pNode, const cd::Mesh& mesh, const cd::SceneDatabase* pSceneDatabase); bool ExportFbxFile(fbxsdk::FbxScene* pScene); cd::BitFlags& GetOptions() { return m_options; } diff --git a/private/Scene/Mesh.cpp b/private/Scene/Mesh.cpp index 656d44c1..4bc55d2b 100644 --- a/private/Scene/Mesh.cpp +++ b/private/Scene/Mesh.cpp @@ -46,6 +46,11 @@ uint32_t Mesh::GetVertexCount() const return m_pMeshImpl->GetVertexCount(); } +uint32_t Mesh::GetVertexAttributeCount() const +{ + return m_pMeshImpl->GetVertexAttributeCount(); +} + uint32_t Mesh::GetPolygonCount() const { return m_pMeshImpl->GetPolygonCount(); diff --git a/private/Scene/MeshImpl.cpp b/private/Scene/MeshImpl.cpp index c2da0ed3..afe72c12 100644 --- a/private/Scene/MeshImpl.cpp +++ b/private/Scene/MeshImpl.cpp @@ -206,22 +206,32 @@ void MeshImpl::ShrinkToFit() GetVertexNormals().shrink_to_fit(); GetVertexTangents().shrink_to_fit(); GetVertexBiTangents().shrink_to_fit(); - for (uint32_t setIndex = 0U; setIndex < GetVertexUVSetCount(); ++setIndex) + for (uint32_t setIndex = 0U, setCount = GetVertexUVSetCount(); setIndex < setCount; ++setIndex) { m_vertexUVSets[setIndex].shrink_to_fit(); } - for (uint32_t setIndex = 0U; setIndex < GetVertexColorSetCount(); ++setIndex) + for (uint32_t setIndex = 0U, setCount = GetVertexColorSetCount(); setIndex < setCount; ++setIndex) { m_vertexColorSets[setIndex].shrink_to_fit(); } GetPolygonGroups().shrink_to_fit(); - for (uint32_t polygonGroupIndex = 0U; polygonGroupIndex < GetPolygonGroupCount(); ++polygonGroupIndex) + for (auto& polygonGroup : GetPolygonGroups()) { - GetPolygonGroup(polygonGroupIndex).shrink_to_fit(); + polygonGroup.shrink_to_fit(); + for (auto& polygon : polygonGroup) + { + polygon.shrink_to_fit(); + } } } +uint32_t MeshImpl::GetVertexAttributeCount() const +{ + uint32_t vertexAttributeCount = GetVertexInstanceToIDCount(); + return vertexAttributeCount > 0U ? vertexAttributeCount : GetVertexPositionCount(); +} + uint32_t MeshImpl::GetPolygonCount() const { size_t polygonCount = 0U; @@ -357,7 +367,7 @@ void MeshImpl::SetVertexUVSetCount(uint32_t setCount) m_vertexUVSetCount = setCount; for(uint32_t setIndex = 0U; setIndex < m_vertexUVSetCount; ++setIndex) { - m_vertexUVSets[setIndex].resize(GetVertexInstanceToIDCount()); + m_vertexUVSets[setIndex].resize(GetVertexAttributeCount()); } } @@ -371,7 +381,7 @@ void MeshImpl::SetVertexColorSetCount(uint32_t setCount) m_vertexColorSetCount = setCount; for (uint32_t setIndex = 0U; setIndex < m_vertexColorSetCount; ++setIndex) { - m_vertexColorSets[setIndex].resize(GetVertexInstanceToIDCount()); + m_vertexColorSets[setIndex].resize(GetVertexAttributeCount()); } } diff --git a/private/Scene/MeshImpl.h b/private/Scene/MeshImpl.h index 651804f9..99744223 100644 --- a/private/Scene/MeshImpl.h +++ b/private/Scene/MeshImpl.h @@ -47,6 +47,7 @@ class MeshImpl final void ShrinkToFit(); uint32_t GetVertexCount() const { return GetVertexPositionCount(); } + uint32_t GetVertexAttributeCount() const; uint32_t GetPolygonCount() const; void UpdateAABB(); diff --git a/public/Scene/Mesh.h b/public/Scene/Mesh.h index ec94ffc3..178254d6 100644 --- a/public/Scene/Mesh.h +++ b/public/Scene/Mesh.h @@ -43,6 +43,7 @@ class CORE_API Mesh final void Init(uint32_t vertexCount, uint32_t vertexInstanceCount); uint32_t GetVertexCount() const; + uint32_t GetVertexAttributeCount() const; uint32_t GetPolygonCount() const; void UpdateAABB();