From 73ce105328e32d15397a2a74f103b3b56819700a Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Fri, 13 Dec 2024 12:12:09 +0200 Subject: [PATCH 1/6] Basic FBX export (without attached textures) --- openVulkanoCpp/Scene/MeshWriter.cpp | 148 ++++++++++++++++++++++++++++ openVulkanoCpp/Scene/MeshWriter.hpp | 1 + 2 files changed, 149 insertions(+) diff --git a/openVulkanoCpp/Scene/MeshWriter.cpp b/openVulkanoCpp/Scene/MeshWriter.cpp index 7ee4ab5..16e4f85 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" @@ -14,7 +15,13 @@ #include "IO/Archive/ZipWriter.hpp" #include +#include #include +#include +#include +#include +#include +#include namespace OpenVulkano::Scene { @@ -81,4 +88,145 @@ namespace OpenVulkano::Scene zipWriter.AddFile(texDesc, textureFile.Data()); } } + + void MeshWriter::WriteAsFBX(Geometry* geometry, const std::string& texturePath, const std::string& fbxPath) + { + aiScene scene; + scene.mRootNode = new aiNode(); + + aiMesh* mesh = new aiMesh(); + mesh->mNumVertices = geometry->vertexCount; + mesh->mVertices = new aiVector3D[geometry->vertexCount]; + mesh->mNormals = new aiVector3D[geometry->vertexCount]; + mesh->mTextureCoords[0] = new aiVector3D[geometry->vertexCount]; + mesh->mMaterialIndex = 0; + mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + + 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); + 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; + mesh->mFaces = new aiFace[mesh->mNumFaces]; + + for (uint32_t i = 0; i < mesh->mNumFaces; ++i) + { + aiFace& face = mesh->mFaces[i]; + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + + face.mIndices[0] = geometry->GetIndex(i * 3 + 0); + face.mIndices[1] = geometry->GetIndex(i * 3 + 1); + face.mIndices[2] = geometry->GetIndex(i * 3 + 2); + } + + scene.mMeshes = new aiMesh*[1]; + scene.mMeshes[0] = mesh; + scene.mNumMeshes = 1; + scene.mRootNode->mMeshes = new unsigned int[1]; + scene.mRootNode->mMeshes[0] = 0; + scene.mRootNode->mNumMeshes = 1; + + aiMaterial* material = new aiMaterial(); + scene.mMaterials = new aiMaterial*[1]; + scene.mMaterials[0] = material; + scene.mNumMaterials = 1; + + // aiColor3D diffuseColor(1.0f, 1.0f, 1.0f); + // material->AddProperty(&diffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE); + + Array textureData = Utils::ReadFile(texturePath); + + aiTexture* texture = new aiTexture(); + texture->mWidth = static_cast(textureData.Size()); + texture->mHeight = 0; // indicates that this is compressed texture and the pcData has size mWidth + texture->pcData = reinterpret_cast(new uint8_t[textureData.Size()]); + std::memcpy(texture->pcData, textureData.Data(), textureData.Size()); + + scene.mTextures = new aiTexture*[1]; + scene.mTextures[0] = texture; + scene.mNumTextures = 1; + + std::string ext = texturePath.substr(texturePath.find_last_of('.') + 1); + if (ext == "png") + { + std::memcpy(texture->achFormatHint, "png", 3); + } + else if (ext == "jpg" || ext == "jpeg") + { + std::memcpy(texture->achFormatHint, "jpg", 3); + } + texture->achFormatHint[3] = '\0'; + + aiString texName = aiString("*0"); + material->AddProperty(&texName, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + + // Validation + for (uint32_t i = 0; i < geometry->indexCount; ++i) { + if (geometry->GetIndex(i) >= geometry->vertexCount) { + std::cerr << "Invalid index at position " << i << ": " + << geometry->GetIndex(i) << " (vertex count: " + << geometry->vertexCount << ")" << std::endl; + assert(false); + } + } + + if (geometry->indexCount % 3 != 0) { + std::cerr << "Invalid index count: " << geometry->indexCount + << " (not divisible by 3)" << std::endl; + assert(false); + } + + // + //aiString externalPath(texturePath); + //scene.mMaterials[0]->AddProperty(&externalPath, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + + // Export + + Assimp::Exporter exporter; + aiReturn result = exporter.Export(&scene, "fbx", fbxPath); + +#define SAFE_DELETE_ARRAY(arr) \ + do \ + { \ + if (arr) \ + delete[] arr; \ + arr = nullptr; \ + } while (0) + + SAFE_DELETE_ARRAY(mesh->mVertices); + SAFE_DELETE_ARRAY(mesh->mNormals); + SAFE_DELETE_ARRAY(mesh->mTextureCoords[0]); + + for (uint32_t i = 0; i < mesh->mNumFaces; ++i) + { + SAFE_DELETE_ARRAY(mesh->mFaces[i].mIndices); + } + + SAFE_DELETE_ARRAY(mesh->mFaces); + + delete mesh; + mesh = nullptr; + + delete material; + material = nullptr; + + SAFE_DELETE_ARRAY(scene.mMeshes); + SAFE_DELETE_ARRAY(scene.mRootNode->mMeshes); + SAFE_DELETE_ARRAY(scene.mMaterials); + SAFE_DELETE_ARRAY(scene.mTextures); + SAFE_DELETE_ARRAY(texture->pcData); + delete scene.mRootNode; + scene.mRootNode = nullptr; +#undef SAFE_DELETE_ARRAY + + if (result != aiReturn_SUCCESS) + { + throw std::runtime_error("Unable to write a fbx file to " + fbxPath + ": " + exporter.GetErrorString()); + } + } } \ 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 From 972df913c0bd7775fefc3d960f2832ce5ea718fb Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Wed, 18 Dec 2024 12:48:11 +0200 Subject: [PATCH 2/6] Fixed texture appearance, added scaling, removed unused code --- openVulkanoCpp/Scene/MeshWriter.cpp | 60 +++-------------------------- 1 file changed, 6 insertions(+), 54 deletions(-) diff --git a/openVulkanoCpp/Scene/MeshWriter.cpp b/openVulkanoCpp/Scene/MeshWriter.cpp index 16e4f85..64ad450 100644 --- a/openVulkanoCpp/Scene/MeshWriter.cpp +++ b/openVulkanoCpp/Scene/MeshWriter.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include namespace OpenVulkano::Scene { @@ -101,11 +101,13 @@ namespace OpenVulkano::Scene mesh->mTextureCoords[0] = new aiVector3D[geometry->vertexCount]; mesh->mMaterialIndex = 0; mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + mesh->mNumUVComponents[0] = 2; + 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); + 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); } @@ -136,56 +138,8 @@ namespace OpenVulkano::Scene scene.mMaterials[0] = material; scene.mNumMaterials = 1; - // aiColor3D diffuseColor(1.0f, 1.0f, 1.0f); - // material->AddProperty(&diffuseColor, 1, AI_MATKEY_COLOR_DIFFUSE); - - Array textureData = Utils::ReadFile(texturePath); - - aiTexture* texture = new aiTexture(); - texture->mWidth = static_cast(textureData.Size()); - texture->mHeight = 0; // indicates that this is compressed texture and the pcData has size mWidth - texture->pcData = reinterpret_cast(new uint8_t[textureData.Size()]); - std::memcpy(texture->pcData, textureData.Data(), textureData.Size()); - - scene.mTextures = new aiTexture*[1]; - scene.mTextures[0] = texture; - scene.mNumTextures = 1; - - std::string ext = texturePath.substr(texturePath.find_last_of('.') + 1); - if (ext == "png") - { - std::memcpy(texture->achFormatHint, "png", 3); - } - else if (ext == "jpg" || ext == "jpeg") - { - std::memcpy(texture->achFormatHint, "jpg", 3); - } - texture->achFormatHint[3] = '\0'; - - aiString texName = aiString("*0"); - material->AddProperty(&texName, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); - - // Validation - for (uint32_t i = 0; i < geometry->indexCount; ++i) { - if (geometry->GetIndex(i) >= geometry->vertexCount) { - std::cerr << "Invalid index at position " << i << ": " - << geometry->GetIndex(i) << " (vertex count: " - << geometry->vertexCount << ")" << std::endl; - assert(false); - } - } - - if (geometry->indexCount % 3 != 0) { - std::cerr << "Invalid index count: " << geometry->indexCount - << " (not divisible by 3)" << std::endl; - assert(false); - } - - // - //aiString externalPath(texturePath); - //scene.mMaterials[0]->AddProperty(&externalPath, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); - - // Export + aiString externalPath(texturePath); + scene.mMaterials[0]->AddProperty(&externalPath, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); Assimp::Exporter exporter; aiReturn result = exporter.Export(&scene, "fbx", fbxPath); @@ -218,8 +172,6 @@ namespace OpenVulkano::Scene SAFE_DELETE_ARRAY(scene.mMeshes); SAFE_DELETE_ARRAY(scene.mRootNode->mMeshes); SAFE_DELETE_ARRAY(scene.mMaterials); - SAFE_DELETE_ARRAY(scene.mTextures); - SAFE_DELETE_ARRAY(texture->pcData); delete scene.mRootNode; scene.mRootNode = nullptr; #undef SAFE_DELETE_ARRAY From 6c31d97271b7314a2ad8929b61426b6a11ffd39a Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Wed, 18 Dec 2024 14:28:33 +0200 Subject: [PATCH 3/6] Stack-allocating things, removed cleanup code --- openVulkanoCpp/Scene/MeshWriter.cpp | 90 +++++++++++------------------ 1 file changed, 34 insertions(+), 56 deletions(-) diff --git a/openVulkanoCpp/Scene/MeshWriter.cpp b/openVulkanoCpp/Scene/MeshWriter.cpp index 64ad450..b1fe6ea 100644 --- a/openVulkanoCpp/Scene/MeshWriter.cpp +++ b/openVulkanoCpp/Scene/MeshWriter.cpp @@ -15,13 +15,11 @@ #include "IO/Archive/ZipWriter.hpp" #include -#include #include #include #include #include #include -#include namespace OpenVulkano::Scene { @@ -91,51 +89,58 @@ namespace OpenVulkano::Scene void MeshWriter::WriteAsFBX(Geometry* geometry, const std::string& texturePath, const std::string& fbxPath) { + aiNode rootNode; + aiScene scene; - scene.mRootNode = new aiNode(); - - aiMesh* mesh = new aiMesh(); - mesh->mNumVertices = geometry->vertexCount; - mesh->mVertices = new aiVector3D[geometry->vertexCount]; - mesh->mNormals = new aiVector3D[geometry->vertexCount]; - mesh->mTextureCoords[0] = new aiVector3D[geometry->vertexCount]; - mesh->mMaterialIndex = 0; - mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - mesh->mNumUVComponents[0] = 2; + scene.mRootNode = &rootNode; + aiMesh mesh; + mesh.mNumVertices = geometry->vertexCount; + mesh.mMaterialIndex = 0; + mesh.mPrimitiveTypes = aiPrimitiveType_TRIANGLE; + mesh.mNumUVComponents[0] = 2; + + mesh.mVertices = new aiVector3D[geometry->vertexCount]; + mesh.mNormals = new aiVector3D[geometry->vertexCount]; + mesh.mTextureCoords[0] = new aiVector3D[geometry->vertexCount]; + 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.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; - mesh->mFaces = new aiFace[mesh->mNumFaces]; + mesh.mNumFaces = geometry->indexCount / 3; + mesh.mFaces = new aiFace[mesh.mNumFaces]; - for (uint32_t i = 0; i < mesh->mNumFaces; ++i) + for (uint32_t i = 0; i < mesh.mNumFaces; ++i) { - aiFace& face = mesh->mFaces[i]; + aiFace& face = mesh.mFaces[i]; face.mNumIndices = 3; - face.mIndices = new unsigned int[3]; + face.mIndices = new unsigned int[face.mNumIndices]; face.mIndices[0] = geometry->GetIndex(i * 3 + 0); face.mIndices[1] = geometry->GetIndex(i * 3 + 1); face.mIndices[2] = geometry->GetIndex(i * 3 + 2); } - scene.mMeshes = new aiMesh*[1]; - scene.mMeshes[0] = mesh; + aiMesh* meshes[1]; + scene.mMeshes = meshes; + scene.mMeshes[0] = &mesh; scene.mNumMeshes = 1; - scene.mRootNode->mMeshes = new unsigned int[1]; + + unsigned int meshIndices[1]; + scene.mRootNode->mMeshes = meshIndices; scene.mRootNode->mMeshes[0] = 0; scene.mRootNode->mNumMeshes = 1; - aiMaterial* material = new aiMaterial(); - scene.mMaterials = new aiMaterial*[1]; - scene.mMaterials[0] = material; + aiMaterial material; + aiMaterial* materials[1]; + scene.mMaterials = materials; + scene.mMaterials[0] = &material; scene.mNumMaterials = 1; aiString externalPath(texturePath); @@ -144,37 +149,10 @@ namespace OpenVulkano::Scene Assimp::Exporter exporter; aiReturn result = exporter.Export(&scene, "fbx", fbxPath); -#define SAFE_DELETE_ARRAY(arr) \ - do \ - { \ - if (arr) \ - delete[] arr; \ - arr = nullptr; \ - } while (0) - - SAFE_DELETE_ARRAY(mesh->mVertices); - SAFE_DELETE_ARRAY(mesh->mNormals); - SAFE_DELETE_ARRAY(mesh->mTextureCoords[0]); - - for (uint32_t i = 0; i < mesh->mNumFaces; ++i) - { - SAFE_DELETE_ARRAY(mesh->mFaces[i].mIndices); - } - - SAFE_DELETE_ARRAY(mesh->mFaces); - - delete mesh; - mesh = nullptr; - - delete material; - material = nullptr; - - SAFE_DELETE_ARRAY(scene.mMeshes); - SAFE_DELETE_ARRAY(scene.mRootNode->mMeshes); - SAFE_DELETE_ARRAY(scene.mMaterials); - delete scene.mRootNode; scene.mRootNode = nullptr; -#undef SAFE_DELETE_ARRAY + rootNode.mMeshes = nullptr; + scene.mMeshes = nullptr; + scene.mMaterials = nullptr; if (result != aiReturn_SUCCESS) { From 2e36d8b20eb3fec5423dfadf5208b24c81c83e62 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Wed, 18 Dec 2024 22:58:24 +0200 Subject: [PATCH 4/6] Storing mesh members using smart pointers --- openVulkanoCpp/Scene/MeshWriter.cpp | 39 +++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/openVulkanoCpp/Scene/MeshWriter.cpp b/openVulkanoCpp/Scene/MeshWriter.cpp index b1fe6ea..556743c 100644 --- a/openVulkanoCpp/Scene/MeshWriter.cpp +++ b/openVulkanoCpp/Scene/MeshWriter.cpp @@ -100,9 +100,14 @@ namespace OpenVulkano::Scene mesh.mPrimitiveTypes = aiPrimitiveType_TRIANGLE; mesh.mNumUVComponents[0] = 2; - mesh.mVertices = new aiVector3D[geometry->vertexCount]; - mesh.mNormals = new aiVector3D[geometry->vertexCount]; - mesh.mTextureCoords[0] = new aiVector3D[geometry->vertexCount]; + 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) @@ -114,22 +119,27 @@ namespace OpenVulkano::Scene } mesh.mNumFaces = geometry->indexCount / 3; - mesh.mFaces = new aiFace[mesh.mNumFaces]; + 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 = new unsigned int[face.mNumIndices]; + 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]; + aiMesh* meshes[1] = { &mesh }; scene.mMeshes = meshes; - scene.mMeshes[0] = &mesh; scene.mNumMeshes = 1; unsigned int meshIndices[1]; @@ -138,9 +148,8 @@ namespace OpenVulkano::Scene scene.mRootNode->mNumMeshes = 1; aiMaterial material; - aiMaterial* materials[1]; + aiMaterial* materials[1] = { &material }; scene.mMaterials = materials; - scene.mMaterials[0] = &material; scene.mNumMaterials = 1; aiString externalPath(texturePath); @@ -149,8 +158,18 @@ namespace OpenVulkano::Scene Assimp::Exporter exporter; aiReturn result = exporter.Export(&scene, "fbx", fbxPath); - scene.mRootNode = nullptr; + 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; From 308c361d8993c49bd98be492ac3a006c407f7b7a Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Thu, 19 Dec 2024 17:04:50 +0200 Subject: [PATCH 5/6] Guarded assimp-related code --- openVulkanoCpp/Scene/MeshWriter.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openVulkanoCpp/Scene/MeshWriter.cpp b/openVulkanoCpp/Scene/MeshWriter.cpp index 556743c..35be663 100644 --- a/openVulkanoCpp/Scene/MeshWriter.cpp +++ b/openVulkanoCpp/Scene/MeshWriter.cpp @@ -16,10 +16,13 @@ #include #include + +#if __has_include("assimp/Exporter.hpp") #include #include #include #include +#endif namespace OpenVulkano::Scene { @@ -89,6 +92,7 @@ namespace OpenVulkano::Scene void MeshWriter::WriteAsFBX(Geometry* geometry, const std::string& texturePath, const std::string& fbxPath) { +#if __has_include("assimp/Exporter.hpp") aiNode rootNode; aiScene scene; @@ -177,5 +181,8 @@ namespace OpenVulkano::Scene { 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 From b6b32ecbf571976052ec580074614a660ec676f9 Mon Sep 17 00:00:00 2001 From: Vladyslav Baranovskyi Date: Thu, 19 Dec 2024 17:05:08 +0200 Subject: [PATCH 6/6] Fixed assimp dependency linking --- 3rdParty/assimp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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}")