aboutsummaryrefslogtreecommitdiff
path: root/NvBlast/tools/common/FbxFileWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NvBlast/tools/common/FbxFileWriter.cpp')
-rw-r--r--NvBlast/tools/common/FbxFileWriter.cpp645
1 files changed, 645 insertions, 0 deletions
diff --git a/NvBlast/tools/common/FbxFileWriter.cpp b/NvBlast/tools/common/FbxFileWriter.cpp
new file mode 100644
index 0000000..a71896e
--- /dev/null
+++ b/NvBlast/tools/common/FbxFileWriter.cpp
@@ -0,0 +1,645 @@
+#include "FbxFileWriter.h"
+#include "fbxsdk.h"
+#include "FbxUtils.h"
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include "NvBlastTypes.h"
+#include "NvBlastTkFramework.h"
+#include "NvBlast.h"
+#include "PxVec3.h"
+#include "NvBlastAssert.h"
+#include <unordered_set>
+#include <functional>
+
+
+FbxFileWriter::FbxFileWriter():
+ bOutputFBXAscii(false)
+{
+ // Wrap in a shared ptr so that when it deallocates we get an auto destroy and all of the other assets created don't leak.
+ sdkManager = std::shared_ptr<FbxManager>(FbxManager::Create(), [=](FbxManager* manager)
+ {
+ std::cout << "Deleting FbxManager" << std::endl;
+ manager->Destroy();
+ });
+
+ setConvertToUE4(false);
+}
+
+/*
+
+ Add the NvBlastAsset as a param
+ Walk the NvBlastChunk tree
+ -- Get the triangles for each chunk, however we do that
+ -- create a skin, clusters and bone node for each chunk, linked to their parent with the proper link mode
+
+*/
+bool FbxFileWriter::saveToFile(const NvBlastAsset* asset, std::vector<std::vector<Nv::Blast::Triangle>> chunksGeometry, std::string assetName, std::string outputPath)
+{
+
+ FbxIOSettings* ios = FbxIOSettings::Create(sdkManager.get(), IOSROOT);
+ // Set some properties on the io settings
+
+// ios->SetBoolProp(EXP_ASCIIFBX, true);
+
+ sdkManager->SetIOSettings(ios);
+
+ sdkManager->GetIOSettings()->SetBoolProp(EXP_ASCIIFBX, bOutputFBXAscii);
+
+ FbxScene* scene = FbxScene::Create(sdkManager.get(), "Export Scene");
+
+ if (getConvertToUE4())
+ {
+ FbxAxisSystem::EFrontVector FrontVector = (FbxAxisSystem::EFrontVector) - FbxAxisSystem::eParityOdd;
+ const FbxAxisSystem UnrealZUp(FbxAxisSystem::eZAxis, FrontVector, FbxAxisSystem::eRightHanded);
+
+ scene->GetGlobalSettings().SetAxisSystem(UnrealZUp);
+ }
+
+ // Otherwise default to Maya defaults
+
+ FbxMesh* mesh = FbxMesh::Create(sdkManager.get(), "meshgeo");
+
+ FbxGeometryElementNormal* geNormal = mesh->CreateElementNormal();
+ geNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
+ geNormal->SetReferenceMode(FbxGeometryElement::eDirect);
+
+ FbxGeometryElementUV* geUV = mesh->CreateElementUV("diffuseElement");
+ geUV->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
+ geUV->SetReferenceMode(FbxGeometryElement::eDirect);
+
+ // Get the triangles count for all of the mesh parts
+
+ size_t triangleCount = 0;
+ for (auto triangles : chunksGeometry)
+ {
+ triangleCount += triangles.size();
+ }
+
+ mesh->InitControlPoints((int)triangleCount * 3);
+
+ FbxNode* meshNode = FbxNode::Create(scene, "meshnode");
+ meshNode->SetNodeAttribute(mesh);
+ meshNode->SetShadingMode(FbxNode::eTextureShading);
+
+ FbxNode* lRootNode = scene->GetRootNode();
+ lRootNode->AddChild(meshNode);
+
+ FbxSkin* skin = FbxSkin::Create(sdkManager.get(), "Skin of the thing");
+ skin->SetGeometry(mesh);
+
+ mesh->AddDeformer(skin);
+
+ // Add a material otherwise UE4 freaks out on import
+
+ FbxGeometryElementMaterial* matElement = mesh->CreateElementMaterial();
+ matElement->SetMappingMode(FbxGeometryElement::eByPolygon);
+ matElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
+
+ FbxSurfacePhong* material = FbxSurfacePhong::Create(sdkManager.get(), "FirstExportMaterial");
+
+ material->Diffuse.Set(FbxDouble3(1.0, 1.0, 0));
+ material->DiffuseFactor.Set(1.0);
+
+ meshNode->AddMaterial(material);
+
+ FbxSurfacePhong* material2 = FbxSurfacePhong::Create(sdkManager.get(), "SecondExportMaterial");
+
+ material2->Diffuse.Set(FbxDouble3(1.0, 0.0, 1.0));
+ material2->DiffuseFactor.Set(1.0);
+
+ meshNode->AddMaterial(material2);
+
+ // Now walk the tree and create a skeleton with geometry at the same time
+ // Find a "root" chunk and walk the tree from there.
+ uint32_t chunkCount = NvBlastAssetGetChunkCount(asset, NvBlastTkFrameworkGet()->getLogFn());
+
+ auto chunks = NvBlastAssetGetChunks(asset, NvBlastTkFrameworkGet()->getLogFn());
+
+ currentDepth = 0;
+ uint32_t cpIdx = 0;
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ const NvBlastChunk* chunk = &chunks[i];
+
+ if (chunk->parentChunkIndex == UINT32_MAX)
+ {
+ uint32_t addedCps = createChunkRecursive(cpIdx, i, meshNode, lRootNode, skin, asset, chunksGeometry);
+
+ cpIdx += addedCps;
+ }
+ }
+
+ return finalizeFbxAndSave(scene, skin, outputPath, assetName);}
+
+/*
+ Recursive method that creates this chunk and all it's children.
+
+ This creates a FbxNode with an FbxCluster, and all of the geometry for this chunk.
+
+ Returns the number of added control points
+*/
+uint32_t FbxFileWriter::createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, FbxNode *meshNode, FbxNode* parentNode, FbxSkin* skin, const NvBlastAsset* asset, std::vector<std::vector<Nv::Blast::Triangle>> chunksGeometry)
+{
+ currentDepth++;
+
+// if (currentDepth >= 4)
+// {
+// return 0;
+// }
+
+ auto chunks = NvBlastAssetGetChunks(asset, NvBlastTkFrameworkGet()->getLogFn());
+ const NvBlastChunk* chunk = &chunks[chunkIndex];
+ auto triangles = chunksGeometry[chunkIndex];
+ physx::PxVec3 centroid = physx::PxVec3(chunk->centroid[0], chunk->centroid[1], chunk->centroid[2]);
+
+ std::ostringstream namestream;
+
+ //mesh->InitTextureUV(triangles.size() * 3);
+
+ std::ostringstream().swap(namestream); // Swap namestream with a default constructed ostringstream
+ namestream << "bone_" << chunkIndex;
+ std::string boneName = namestream.str();
+
+ FbxSkeleton* skelAttrib;
+ if (chunk->parentChunkIndex == UINT32_MAX)
+ {
+ skelAttrib = FbxSkeleton::Create(sdkManager.get(), "SkelRootAttrib");
+ skelAttrib->SetSkeletonType(FbxSkeleton::eRoot);
+
+ // Change the centroid to origin
+ centroid = physx::PxVec3(0.0f);
+ }
+ else
+ {
+ skelAttrib = FbxSkeleton::Create(sdkManager.get(), boneName.c_str());
+ skelAttrib->SetSkeletonType(FbxSkeleton::eLimbNode);
+ }
+
+ skelAttrib->Size.Set(1.0); // What's this for?
+
+
+ FbxNode* boneNode = FbxNode::Create(sdkManager.get(), boneName.c_str());
+ boneNode->SetNodeAttribute(skelAttrib);
+
+ auto mat = parentNode->EvaluateGlobalTransform().Inverse();
+
+ FbxVector4 vec(centroid.x, centroid.y, centroid.z, 0);
+ FbxVector4 c2 = mat.MultT(vec);
+
+ boneNode->LclTranslation.Set(c2);
+
+ parentNode->AddChild(boneNode);
+
+ std::ostringstream().swap(namestream); // Swap namestream with a default constructed ostringstream
+ namestream << "cluster_" << std::setw(5) << std::setfill('0') << chunkIndex;
+ std::string clusterName = namestream.str();
+
+ FbxCluster* cluster = FbxCluster::Create(sdkManager.get(), clusterName.c_str());
+ cluster->SetTransformMatrix(FbxAMatrix());
+ cluster->SetLink(boneNode);
+ cluster->SetLinkMode(FbxCluster::eTotalOne);
+
+ skin->AddCluster(cluster);
+
+ FbxMesh* mesh = static_cast<FbxMesh*>(meshNode->GetNodeAttribute());
+
+ FbxVector4* controlPoints = mesh->GetControlPoints();
+ auto geNormal = mesh->GetElementNormal();
+ auto geUV = mesh->GetElementUV("diffuseElement");
+ FbxGeometryElementMaterial* matElement = mesh->GetElementMaterial();
+
+ auto addVert = [&](Nv::Blast::Vertex vert, int controlPointIdx)
+ {
+ FbxVector4 vertex;
+ FbxVector4 normal;
+ FbxVector2 uv;
+
+ FbxUtils::VertexToFbx(vert, vertex, normal, uv);
+
+ controlPoints[controlPointIdx] = vertex;
+ geNormal->GetDirectArray().Add(normal);
+ geUV->GetDirectArray().Add(uv);
+ // Add this control point to the bone with weight 1.0
+ cluster->AddControlPointIndex(controlPointIdx, 1.0);
+ };
+
+ uint32_t cpIdx = 0;
+ uint32_t polyCount = mesh->GetPolygonCount();
+ for (auto tri : triangles)
+ {
+ addVert(tri.a, currentCpIdx + cpIdx + 0);
+ addVert(tri.b, currentCpIdx + cpIdx + 1);
+ addVert(tri.c, currentCpIdx + cpIdx + 2);
+
+ mesh->BeginPolygon();
+ mesh->AddPolygon(currentCpIdx + cpIdx + 0);
+ mesh->AddPolygon(currentCpIdx + cpIdx + 1);
+ mesh->AddPolygon(currentCpIdx + cpIdx + 2);
+ mesh->EndPolygon();
+ if (tri.userInfo == 0)
+ {
+ matElement->GetIndexArray().SetAt(polyCount, 0);
+ }
+ else
+ {
+ matElement->GetIndexArray().SetAt(polyCount, 1);
+ }
+ polyCount++;
+ cpIdx += 3;
+ }
+
+ mat = meshNode->EvaluateGlobalTransform();
+ cluster->SetTransformMatrix(mat);
+
+ mat = boneNode->EvaluateGlobalTransform();
+ cluster->SetTransformLinkMatrix(mat);
+
+ uint32_t addedCps = static_cast<uint32_t>(triangles.size() * 3);
+
+ for (uint32_t i = chunk->firstChildIndex; i < chunk->childIndexStop; i++)
+ {
+ addedCps += createChunkRecursive(currentCpIdx + addedCps, i, meshNode, boneNode, skin, asset, chunksGeometry);
+ }
+
+ return addedCps;
+}
+
+
+uint32_t FbxFileWriter::createChunkRecursive(uint32_t currentCpIdx, uint32_t chunkIndex, FbxNode *meshNode, FbxNode* parentNode, FbxSkin* skin, const NvBlastAsset* asset,
+ const std::vector<std::vector<std::vector<int32_t> > >& posIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& normIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& texIndex)
+{
+ currentDepth++;
+
+ // if (currentDepth >= 4)
+ // {
+ // return 0;
+ // }
+
+ auto chunks = NvBlastAssetGetChunks(asset, NvBlastTkFrameworkGet()->getLogFn());
+ const NvBlastChunk* chunk = &chunks[chunkIndex];
+ physx::PxVec3 centroid = physx::PxVec3(chunk->centroid[0], chunk->centroid[1], chunk->centroid[2]);
+
+ std::ostringstream namestream;
+
+ //mesh->InitTextureUV(triangles.size() * 3);
+
+ std::ostringstream().swap(namestream); // Swap namestream with a default constructed ostringstream
+ namestream << "bone_" << chunkIndex;
+ std::string boneName = namestream.str();
+
+ FbxSkeleton* skelAttrib;
+ if (chunk->parentChunkIndex == UINT32_MAX)
+ {
+ skelAttrib = FbxSkeleton::Create(sdkManager.get(), "SkelRootAttrib");
+ skelAttrib->SetSkeletonType(FbxSkeleton::eRoot);
+
+ // Change the centroid to origin
+ centroid = physx::PxVec3(0.0f);
+ }
+ else
+ {
+ skelAttrib = FbxSkeleton::Create(sdkManager.get(), boneName.c_str());
+ skelAttrib->SetSkeletonType(FbxSkeleton::eLimbNode);
+ }
+
+ skelAttrib->Size.Set(1.0); // What's this for?
+
+
+ FbxNode* boneNode = FbxNode::Create(sdkManager.get(), boneName.c_str());
+ boneNode->SetNodeAttribute(skelAttrib);
+
+ auto mat = parentNode->EvaluateGlobalTransform().Inverse();
+
+ FbxVector4 vec(centroid.x, centroid.y, centroid.z, 0);
+ FbxVector4 c2 = mat.MultT(vec);
+
+ boneNode->LclTranslation.Set(c2);
+
+ parentNode->AddChild(boneNode);
+
+ std::ostringstream().swap(namestream); // Swap namestream with a default constructed ostringstream
+ namestream << "cluster_" << std::setw(5) << std::setfill('0') << chunkIndex;
+ std::string clusterName = namestream.str();
+
+ FbxCluster* cluster = FbxCluster::Create(sdkManager.get(), clusterName.c_str());
+ cluster->SetTransformMatrix(FbxAMatrix());
+ cluster->SetLink(boneNode);
+ cluster->SetLinkMode(FbxCluster::eTotalOne);
+
+ skin->AddCluster(cluster);
+
+ FbxMesh* mesh = static_cast<FbxMesh*>(meshNode->GetNodeAttribute());
+
+ auto geNormal = mesh->GetElementNormal();
+ auto geUV = mesh->GetElementUV("diffuseElement");
+ auto matr = mesh->GetElementMaterial();
+
+
+
+ auto posIndices = posIndex[chunkIndex];
+ auto normIndices = normIndex[chunkIndex];
+ auto uvIndices = texIndex[chunkIndex];
+ uint32_t cPolygCount = mesh->GetPolygonCount();
+ int32_t addedVertices = 0;
+ for (uint32_t subMesh = 0; subMesh < posIndices.size(); ++subMesh)
+ {
+ for (uint32_t tr = 0; tr < posIndices[subMesh].size(); tr += 3)
+ {
+ mesh->BeginPolygon();
+ mesh->AddPolygon(posIndices[subMesh][tr + 0]);
+ mesh->AddPolygon(posIndices[subMesh][tr + 1]);
+ mesh->AddPolygon(posIndices[subMesh][tr + 2]);
+ mesh->EndPolygon();
+ geNormal->GetIndexArray().SetAt(currentCpIdx + addedVertices, normIndices[subMesh][tr + 0]);
+ geNormal->GetIndexArray().SetAt(currentCpIdx + addedVertices + 1, normIndices[subMesh][tr + 1]);
+ geNormal->GetIndexArray().SetAt(currentCpIdx + addedVertices + 2, normIndices[subMesh][tr + 2]);
+
+ geUV->GetIndexArray().SetAt(currentCpIdx + addedVertices, uvIndices[subMesh][tr + 0]);
+ geUV->GetIndexArray().SetAt(currentCpIdx + addedVertices + 1, uvIndices[subMesh][tr + 1]);
+ geUV->GetIndexArray().SetAt(currentCpIdx + addedVertices + 2, uvIndices[subMesh][tr + 2]);
+ if (subMesh == 0)
+ {
+ matr->GetIndexArray().SetAt(cPolygCount, 0);
+ }
+ else
+ {
+ matr->GetIndexArray().SetAt(cPolygCount, 1);
+ }
+ cPolygCount++;
+ addedVertices += 3;
+
+ cluster->AddControlPointIndex(posIndices[subMesh][tr + 0], 1.0);
+ cluster->AddControlPointIndex(posIndices[subMesh][tr + 1], 1.0);
+ cluster->AddControlPointIndex(posIndices[subMesh][tr + 2], 1.0);
+ }
+ }
+ mat = meshNode->EvaluateGlobalTransform();
+ cluster->SetTransformMatrix(mat);
+
+ mat = boneNode->EvaluateGlobalTransform();
+ cluster->SetTransformLinkMatrix(mat);
+
+
+ for (uint32_t i = chunk->firstChildIndex; i < chunk->childIndexStop; i++)
+ {
+ addedVertices +=createChunkRecursive(addedVertices, i, meshNode, boneNode, skin, asset, posIndex, normIndex, texIndex);
+ }
+
+ return addedVertices;
+
+}
+
+void FbxFileWriter::addControlPoints(FbxMesh* mesh, const std::vector<physx::PxVec3>& pos, std::vector<std::vector<std::vector<int32_t> > >& posIndex)
+{
+ std::vector<uint32_t> vertices;
+ std::cout << "Adding control points" << std::endl;
+ std::vector<int32_t> mapping(pos.size(), -1);
+ for (uint32_t ch = 0; ch < posIndex.size(); ++ch)
+ {
+ mapping.assign(pos.size(), -1);
+ for (uint32_t sb = 0; sb < posIndex[ch].size(); ++sb)
+ {
+ for (uint32_t pi = 0; pi < posIndex[ch][sb].size(); ++pi)
+ {
+ uint32_t p = posIndex[ch][sb][pi];
+ if (mapping[p] == -1)
+ {
+ mapping[p] = (int)vertices.size();
+ vertices.push_back(posIndex[ch][sb][pi]);
+ posIndex[ch][sb][pi] = mapping[p];
+ }
+ else
+ {
+ posIndex[ch][sb][pi] = mapping[p];
+ }
+ }
+ }
+ }
+ mesh->InitControlPoints((int)vertices.size());
+ FbxVector4* controlPoints = mesh->GetControlPoints();
+ for (auto v : vertices)
+ {
+ *controlPoints = FbxVector4(pos[v].x, pos[v].y, pos[v].z, 0);
+ ++controlPoints;
+ }
+ std::cout << "Adding control points: done" << std::endl;
+}
+
+bool FbxFileWriter::finalizeFbxAndSave(FbxScene* scene, FbxSkin* skin, const std::string& outputPath, const std::string& name)
+{
+ // Store the bind pose
+
+ std::unordered_set<FbxNode*> clusterNodes;
+
+ std::function<void(FbxNode*)> addRecursively = [&](FbxNode* node)
+ {
+ if (node)
+ {
+ addRecursively(node->GetParent());
+
+ clusterNodes.insert(node);
+ }
+ };
+
+ for (uint32_t i = 0; i < (uint32_t)skin->GetClusterCount(); i++)
+ {
+ FbxNode* clusterNode = skin->GetCluster(i)->GetLink();
+
+ addRecursively(clusterNode);
+ }
+
+ NVBLAST_ASSERT(clusterNodes.size() > 0);
+
+ FbxPose* pose = FbxPose::Create(sdkManager.get(), "BasePose");
+ pose->SetIsBindPose(true);
+
+ for (auto node : clusterNodes)
+ {
+ FbxMatrix bindMat = node->EvaluateGlobalTransform();
+
+ pose->Add(node, bindMat);
+ }
+
+ scene->AddPose(pose);
+
+ FbxExporter* exporter = FbxExporter::Create(sdkManager.get(), "Scene Exporter");
+
+ auto path = outputPath + "\\" + name + ".fbx";
+
+ int lFormat;
+
+ if (bOutputFBXAscii)
+ {
+ lFormat = sdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)");
+ }
+ else
+ {
+ lFormat = sdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX binary (*.fbx)");
+ }
+
+ bool exportStatus = exporter->Initialize(path.c_str(), lFormat, sdkManager->GetIOSettings());
+
+ if (!exportStatus)
+ {
+ std::cerr << "Call to FbxExporter::Initialize failed" << std::endl;
+ std::cerr << "Error returned: " << exporter->GetStatus().GetErrorString() << std::endl;
+ return false;
+ }
+
+ exportStatus = exporter->Export(scene);
+
+ if (!exportStatus)
+ {
+ auto fbxStatus = exporter->GetStatus();
+
+ std::cerr << "Call to FbxExporter::Export failed" << std::endl;
+ std::cerr << "Error returned: " << fbxStatus.GetErrorString() << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+bool FbxFileWriter::saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm,
+ const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& posIndexInp,
+ const std::vector<std::vector<std::vector<int32_t> > >& normIndex,
+ const std::vector<std::vector<std::vector<int32_t> > >& texIndex,
+ const std::vector<std::string>& texPathes,
+ const uint32_t submeshCount)
+{
+ NV_UNUSED(submeshCount);
+ NV_UNUSED(texPathes);
+
+ auto posIndex = posIndexInp;
+ /**
+ Get polygon count
+ */
+ uint32_t polygCount = 0;
+ for (uint32_t ch = 0; ch < posIndex.size(); ++ch)
+ {
+ for (uint32_t sbm = 0; sbm < posIndex[ch].size(); ++sbm)
+ {
+ polygCount += (uint32_t)posIndex[ch][sbm].size() / 3;
+ }
+ }
+
+ FbxIOSettings* ios = FbxIOSettings::Create(sdkManager.get(), IOSROOT);
+ // Set some properties on the io settings
+
+ // ios->SetBoolProp(EXP_ASCIIFBX, true);
+
+ sdkManager->SetIOSettings(ios);
+
+ sdkManager->GetIOSettings()->SetBoolProp(EXP_ASCIIFBX, bOutputFBXAscii);
+
+ FbxScene* scene = FbxScene::Create(sdkManager.get(), "Export Scene");
+
+ if (getConvertToUE4())
+ {
+ FbxAxisSystem::EFrontVector FrontVector = (FbxAxisSystem::EFrontVector) - FbxAxisSystem::eParityOdd;
+ const FbxAxisSystem UnrealZUp(FbxAxisSystem::eZAxis, FrontVector, FbxAxisSystem::eRightHanded);
+
+ scene->GetGlobalSettings().SetAxisSystem(UnrealZUp);
+ }
+
+ // Otherwise default to Maya defaults
+
+ FbxMesh* mesh = FbxMesh::Create(sdkManager.get(), "meshgeo");
+
+ FbxGeometryElementNormal* geNormal = mesh->CreateElementNormal();
+ geNormal->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
+ geNormal->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
+
+ FbxGeometryElementUV* geUV = mesh->CreateElementUV("diffuseElement");
+ geUV->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
+ geUV->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
+
+
+ FbxNode* meshNode = FbxNode::Create(scene, "meshnode");
+ meshNode->SetNodeAttribute(mesh);
+ meshNode->SetShadingMode(FbxNode::eTextureShading);
+
+ FbxNode* lRootNode = scene->GetRootNode();
+ lRootNode->AddChild(meshNode);
+
+ FbxSkin* skin = FbxSkin::Create(sdkManager.get(), "Skin of the thing");
+ skin->SetGeometry(mesh);
+
+ mesh->AddDeformer(skin);
+
+ /**
+ Create control points, copy data to buffers
+ */
+ addControlPoints(mesh, pos, posIndex);
+
+ auto normalsElem = mesh->GetElementNormal();
+ for (uint32_t i = 0; i < norm.size(); ++i)
+ {
+ normalsElem->GetDirectArray().Add(FbxVector4(norm[i].x, norm[i].y, norm[i].z, 0));
+ }
+ auto uvsElem = mesh->GetElementUV("diffuseElement");
+ for (uint32_t i = 0; i < uvs.size(); ++i)
+ {
+ uvsElem->GetDirectArray().Add(FbxVector2(uvs[i].x, uvs[i].y));
+ }
+
+
+ // Add a material otherwise UE4 freaks out on import
+
+ FbxGeometryElementMaterial* matElement = mesh->CreateElementMaterial();
+ matElement->SetMappingMode(FbxGeometryElement::eByPolygon);
+ matElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
+
+ FbxSurfacePhong* material = FbxSurfacePhong::Create(sdkManager.get(), "FirstExportMaterial");
+
+ material->Diffuse.Set(FbxDouble3(1.0, 1.0, 0));
+ material->DiffuseFactor.Set(1.0);
+
+ meshNode->AddMaterial(material);
+
+ FbxSurfacePhong* material2 = FbxSurfacePhong::Create(sdkManager.get(), "SecondExportMaterial");
+
+ material2->Diffuse.Set(FbxDouble3(1.0, 0.0, 1.0));
+ material2->DiffuseFactor.Set(1.0);
+
+ meshNode->AddMaterial(material2);
+
+
+ matElement->GetIndexArray().SetCount(polygCount);
+ normalsElem->GetIndexArray().SetCount(polygCount * 3);
+ uvsElem->GetIndexArray().SetCount(polygCount * 3);
+
+
+ std::cout << "Create chunks recursive" << std::endl;
+
+ // Now walk the tree and create a skeleton with geometry at the same time
+ // Find a "root" chunk and walk the tree from there.
+ uint32_t chunkCount = NvBlastAssetGetChunkCount(asset, NvBlastTkFrameworkGet()->getLogFn());
+ auto chunks = NvBlastAssetGetChunks(asset, NvBlastTkFrameworkGet()->getLogFn());
+ currentDepth = 0;
+ uint32_t cpIdx = 0;
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ const NvBlastChunk* chunk = &chunks[i];
+
+ if (chunk->parentChunkIndex == UINT32_MAX)
+ {
+ uint32_t addedCps = createChunkRecursive(cpIdx, i, meshNode, lRootNode, skin, asset, posIndex, normIndex, texIndex);
+ cpIdx += addedCps;
+ }
+ }
+
+ return finalizeFbxAndSave(scene, skin, outputPath, name);
+}
+
+bool FbxFileWriter::saveToFile(const NvBlastAsset* asset, const std::string& name, const std::string& outputPath, const std::vector<physx::PxVec3>& pos, const std::vector<physx::PxVec3>& norm, const std::vector<physx::PxVec2>& uvs,
+ const std::vector<std::vector<std::vector<int32_t> > >& indices)
+{
+ std::vector<std::string> matnames;
+ matnames.push_back("");
+ return saveToFile(asset, name, outputPath, pos, norm, uvs, indices, indices, indices, matnames, 1);
+} \ No newline at end of file