diff --git a/3rdParty/assimp/CMakeLists.txt b/3rdParty/assimp/CMakeLists.txt index 782c75b..76d83da 100644 --- a/3rdParty/assimp/CMakeLists.txt +++ b/3rdParty/assimp/CMakeLists.txt @@ -42,7 +42,7 @@ function(LinkAssimp TARGET) set(ASSIMP_LIB_NAME ${ASSIMP_LIBRARIES}) endif () else () - set(ASSIMP_LIB_NAME "assimp") + set(ASSIMP_LIB_NAME assimp) endif () if (assimp_FOUND OR ASSIMP_FOUND OR assimp_BUILT) message("Linking assimp: ${ASSIMP_LIB_NAME}") diff --git a/openVulkanoCpp/Scene/MeshWriter.cpp b/openVulkanoCpp/Scene/MeshWriter.cpp index 7ee4ab5..35be663 100644 --- a/openVulkanoCpp/Scene/MeshWriter.cpp +++ b/openVulkanoCpp/Scene/MeshWriter.cpp @@ -5,6 +5,7 @@ */ #include "MeshWriter.hpp" +#include "Base/Utils.hpp" #include "IO/MemMappedFile.hpp" #include "Scene/Geometry.hpp" #include "Scene/Vertex.hpp" @@ -16,6 +17,13 @@ #include #include +#if __has_include("assimp/Exporter.hpp") +#include +#include +#include +#include +#endif + namespace OpenVulkano::Scene { void MeshWriter::WriteAsOBJ(Geometry* geometry, const std::string& filePath) @@ -81,4 +89,100 @@ namespace OpenVulkano::Scene zipWriter.AddFile(texDesc, textureFile.Data()); } } + + void MeshWriter::WriteAsFBX(Geometry* geometry, const std::string& texturePath, const std::string& fbxPath) + { +#if __has_include("assimp/Exporter.hpp") + aiNode rootNode; + + aiScene scene; + scene.mRootNode = &rootNode; + + aiMesh mesh; + mesh.mNumVertices = geometry->vertexCount; + mesh.mMaterialIndex = 0; + mesh.mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + mesh.mNumUVComponents[0] = 2; + + std::unique_ptr vertices = std::make_unique(geometry->vertexCount); + mesh.mVertices = vertices.get(); + + std::unique_ptr normals = std::make_unique(geometry->vertexCount); + mesh.mNormals = normals.get(); + + std::unique_ptr texCoords = std::make_unique(geometry->vertexCount); + mesh.mTextureCoords[0] = texCoords.get(); + + float scaling = 100; // fbx units are centimeters... + for (uint32_t i = 0; i < geometry->vertexCount; ++i) + { + const Vertex& vertex = geometry->vertices[i]; + mesh.mVertices[i] = aiVector3D(vertex.position.x, vertex.position.y, vertex.position.z) * scaling; + mesh.mNormals[i] = aiVector3D(vertex.normal.x, vertex.normal.y, vertex.normal.z); + mesh.mTextureCoords[0][i] = aiVector3D(vertex.textureCoordinates.x, vertex.textureCoordinates.y, 0.0f); + } + + mesh.mNumFaces = geometry->indexCount / 3; + std::unique_ptr faces = std::make_unique(mesh.mNumFaces); + mesh.mFaces = faces.get(); + + std::unique_ptr indices = std::make_unique(geometry->indexCount); + size_t lastUsedIndex = 0; + + for (uint32_t i = 0; i < mesh.mNumFaces; ++i) + { + aiFace& face = mesh.mFaces[i]; + face.mNumIndices = 3; + face.mIndices = &indices[lastUsedIndex]; + + face.mIndices[0] = geometry->GetIndex(i * 3 + 0); + face.mIndices[1] = geometry->GetIndex(i * 3 + 1); + face.mIndices[2] = geometry->GetIndex(i * 3 + 2); + + lastUsedIndex += face.mNumIndices; + } + + aiMesh* meshes[1] = { &mesh }; + scene.mMeshes = meshes; + scene.mNumMeshes = 1; + + unsigned int meshIndices[1]; + scene.mRootNode->mMeshes = meshIndices; + scene.mRootNode->mMeshes[0] = 0; + scene.mRootNode->mNumMeshes = 1; + + aiMaterial material; + aiMaterial* materials[1] = { &material }; + scene.mMaterials = materials; + scene.mNumMaterials = 1; + + aiString externalPath(texturePath); + scene.mMaterials[0]->AddProperty(&externalPath, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + + Assimp::Exporter exporter; + aiReturn result = exporter.Export(&scene, "fbx", fbxPath); + + mesh.mVertices = nullptr; + mesh.mNormals = nullptr; + mesh.mTextureCoords[0] = nullptr; + for (uint32_t i = 0; i < mesh.mNumFaces; ++i) + { + aiFace& face = mesh.mFaces[i]; + face.mIndices = nullptr; + } + mesh.mFaces = nullptr; + + rootNode.mMeshes = nullptr; + scene.mRootNode = nullptr; + scene.mMeshes = nullptr; + scene.mMaterials = nullptr; + + if (result != aiReturn_SUCCESS) + { + throw std::runtime_error("Unable to write a fbx file to " + fbxPath + ": " + exporter.GetErrorString()); + } +#else + throw std::runtime_error("Unable to convert the scene to FBX: Assimp is not available!"); +#endif + } } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/MeshWriter.hpp b/openVulkanoCpp/Scene/MeshWriter.hpp index c484bee..ba24bce 100644 --- a/openVulkanoCpp/Scene/MeshWriter.hpp +++ b/openVulkanoCpp/Scene/MeshWriter.hpp @@ -18,5 +18,6 @@ namespace OpenVulkano::Scene static void WriteAsUSD(Geometry* geometry, const std::string& filePath); static void WriteObjAsZip(Geometry* geometry, const std::string& texturePath, const std::string& zipPath); static void WriteAsUSDZ(Geometry* geometry, const std::string& texturePath, const std::string& usdzPath); + static void WriteAsFBX(Geometry* geometry, const std::string& texturePath, const std::string& fbxPath); }; } \ No newline at end of file