Merge pull request 'FBX exporter' (#171) from fbx into master
Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/171 Reviewed-by: Georg Hagen <georg.hagen@madvoxel.com>
This commit is contained in:
2
3rdParty/assimp/CMakeLists.txt
vendored
2
3rdParty/assimp/CMakeLists.txt
vendored
@@ -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}")
|
||||
|
||||
@@ -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 <fstream>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#if __has_include("assimp/Exporter.hpp")
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/Exporter.hpp>
|
||||
#include <assimp/mesh.h>
|
||||
#include <assimp/material.h>
|
||||
#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<aiVector3D[]> vertices = std::make_unique<aiVector3D[]>(geometry->vertexCount);
|
||||
mesh.mVertices = vertices.get();
|
||||
|
||||
std::unique_ptr<aiVector3D[]> normals = std::make_unique<aiVector3D[]>(geometry->vertexCount);
|
||||
mesh.mNormals = normals.get();
|
||||
|
||||
std::unique_ptr<aiVector3D[]> texCoords = std::make_unique<aiVector3D[]>(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<aiFace[]> faces = std::make_unique<aiFace[]>(mesh.mNumFaces);
|
||||
mesh.mFaces = faces.get();
|
||||
|
||||
std::unique_ptr<unsigned int[]> indices = std::make_unique<unsigned int[]>(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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user