diff --git a/openVulkanoCpp/Scene/Export/MeshWriter.cpp b/openVulkanoCpp/Scene/Export/MeshWriter.cpp index 399c1ca..47da6f5 100644 --- a/openVulkanoCpp/Scene/Export/MeshWriter.cpp +++ b/openVulkanoCpp/Scene/Export/MeshWriter.cpp @@ -90,180 +90,90 @@ namespace OpenVulkano::Scene } } - void MeshWriter::WriteAsFBX(Geometry* geometry, const std::string& texturePath, const std::string& fbxPath) - { #if __has_include("assimp/Exporter.hpp") - aiNode rootNode; + void MeshWriter::SetupAssimpScene(Geometry* geometry, aiScene& scene, aiNode& rootNode, aiMesh& mesh, + bool withTexCoords, float scaling) + { + mesh.mVertices = nullptr; + mesh.mNormals = nullptr; + mesh.mTangents = nullptr; + mesh.mBitangents = nullptr; + mesh.mFaces = nullptr; + for(unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + mesh.mTextureCoords[i] = nullptr; + mesh.mNumUVComponents[i] = 0; + } + for(unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { + mesh.mColors[i] = nullptr; + } - aiScene scene; + rootNode.mName = aiString("RootNode"); + rootNode.mChildren = nullptr; + rootNode.mNumChildren = 0; scene.mRootNode = &rootNode; - aiMesh mesh; + mesh.mName = aiString("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(); + mesh.mVertices = new aiVector3D[geometry->vertexCount]; + mesh.mNormals = new aiVector3D[geometry->vertexCount]; - 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) + if (withTexCoords) + { + mesh.mNumUVComponents[0] = 2; + mesh.mTextureCoords[0] = new aiVector3D[geometry->vertexCount]; + } + + for (int 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); + if (withTexCoords) + { + 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(); + mesh.mFaces = new aiFace[mesh.mNumFaces]; - std::unique_ptr indices = std::make_unique(geometry->indexCount); - size_t lastUsedIndex = 0; - - for (uint32_t i = 0; i < mesh.mNumFaces; ++i) + for (unsigned int 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; + mesh.mFaces[i].mNumIndices = 3; + mesh.mFaces[i].mIndices = new unsigned int[3]; + mesh.mFaces[i].mIndices[0] = geometry->GetIndex(i * 3 + 0); + mesh.mFaces[i].mIndices[1] = geometry->GetIndex(i * 3 + 1); + mesh.mFaces[i].mIndices[2] = geometry->GetIndex(i * 3 + 2); } - aiMesh* meshes[1] = { &mesh }; - scene.mMeshes = meshes; scene.mNumMeshes = 1; + scene.mMeshes = new aiMesh*[1] { &mesh }; - 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; + scene.mMaterials = new aiMaterial*[1] { new aiMaterial() }; - 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 + rootNode.mNumMeshes = 1; + rootNode.mMeshes = new unsigned int[1] { 0 }; } void MeshWriter::WriteAsSTL(Geometry* geometry, const std::string& filePath, bool binary) { #if __has_include("assimp/Exporter.hpp") - aiNode rootNode; + std::unique_ptr scene(new aiScene()); + std::unique_ptr rootNode(new aiNode()); + std::unique_ptr mesh(new aiMesh()); - aiScene scene; - scene.mRootNode = &rootNode; - - aiMesh mesh; - mesh.mNumVertices = geometry->vertexCount; - mesh.mMaterialIndex = 0; - mesh.mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - 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(); - - for (int 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); - mesh.mNormals[i] = aiVector3D(vertex.normal.x, vertex.normal.y, vertex.normal.z); - } - - 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 (int 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; - - // STL doesn't use materials, but Assimp requires at least one - aiMaterial material; - aiMaterial* materials[1] = { &material }; - scene.mMaterials = materials; - scene.mNumMaterials = 1; + SetupAssimpScene(geometry, *scene, *rootNode, *mesh, false, 1.0f); Assimp::Exporter exporter; const char* formatId = binary ? "stlb" : "stl"; - aiReturn result = exporter.Export(&scene, formatId, filePath); + aiReturn result = exporter.Export(scene.get(), formatId, filePath); - mesh.mVertices = nullptr; - mesh.mNormals = nullptr; - for (int 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; + scene->mRootNode = nullptr; + scene->mMeshes = nullptr; if (result != aiReturn_SUCCESS) { @@ -273,4 +183,35 @@ namespace OpenVulkano::Scene throw std::runtime_error("Unable to export to STL: Assimp is not available!"); #endif } + + void MeshWriter::WriteAsFBX(Geometry* geometry, const std::string& texturePath, const std::string& fbxPath) + { +#if __has_include("assimp/Exporter.hpp") + std::unique_ptr scene(new aiScene()); + std::unique_ptr rootNode(new aiNode()); + std::unique_ptr mesh(new aiMesh()); + + SetupAssimpScene(geometry, *scene, *rootNode, *mesh, true, 100.0f); + + if (!texturePath.empty()) + { + aiString externalPath(texturePath); + scene->mMaterials[0]->AddProperty(&externalPath, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + } + + Assimp::Exporter exporter; + aiReturn result = exporter.Export(scene.get(), "fbx", fbxPath); + + scene->mRootNode = nullptr; + scene->mMeshes = 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 + } +#endif } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/Export/MeshWriter.hpp b/openVulkanoCpp/Scene/Export/MeshWriter.hpp index 3b9255b..0439dff 100644 --- a/openVulkanoCpp/Scene/Export/MeshWriter.hpp +++ b/openVulkanoCpp/Scene/Export/MeshWriter.hpp @@ -8,6 +8,10 @@ #include +#if __has_include("assimp/Exporter.hpp") +#include +#endif + namespace OpenVulkano::Scene { class Geometry; @@ -20,5 +24,10 @@ namespace OpenVulkano::Scene 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); static void WriteAsSTL(Geometry* geometry, const std::string& filePath, bool binary); + private: +#if __has_include("assimp/Exporter.hpp") + static void SetupAssimpScene(Geometry* geometry, aiScene& scene, aiNode& rootNode, aiMesh& mesh, + bool withTexCoords, float scaling); +#endif }; } \ No newline at end of file