From 945c77d699c0911fabff1e1264e86010b91d0707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mar=C4=8Dinkovi=C4=87?= Date: Thu, 9 Feb 2023 12:23:43 +0100 Subject: [PATCH 01/11] Fix double free when the mesh contains duplicate bones. --- include/assimp/mesh.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 3ef94e606..45f50d5a5 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -59,6 +59,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #ifdef __cplusplus +#include + extern "C" { #endif @@ -872,11 +874,15 @@ struct aiMesh { // DO NOT REMOVE THIS ADDITIONAL CHECK if (mNumBones && mBones) { + std::unordered_set bones; for (unsigned int a = 0; a < mNumBones; a++) { if (mBones[a]) { - delete mBones[a]; + bones.insert(mBones[a]); } } + for (const aiBone *bone: bones) { + delete bone; + } delete[] mBones; } From 1169d3bc8cdd3a8c1abfce90491c57e0186ed4cc Mon Sep 17 00:00:00 2001 From: julianknodt Date: Mon, 23 Oct 2023 22:14:18 -0700 Subject: [PATCH 02/11] Fix spelling error --- code/AssetLib/IFC/IFCOpenings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/AssetLib/IFC/IFCOpenings.cpp b/code/AssetLib/IFC/IFCOpenings.cpp index 48b843aa1..c47446dda 100644 --- a/code/AssetLib/IFC/IFCOpenings.cpp +++ b/code/AssetLib/IFC/IFCOpenings.cpp @@ -1372,7 +1372,7 @@ std::vector GetContourInPlane2D(const std::shared_ptr& mes const std::vector& va = mesh->mVerts; if(va.size() <= 2) { std::stringstream msg; - msg << "Skipping: Only " << va.size() << " verticies in opening mesh."; + msg << "Skipping: Only " << va.size() << " vertices in opening mesh."; IFCImporter::LogDebug(msg.str().c_str()); ok = false; return contour; From c44e3427aa58fd77cefd3b2b847b279085dc9fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 10 Oct 2023 12:44:34 -0700 Subject: [PATCH 03/11] use size in order to be compatible with float and double --- code/AssetLib/Irr/IRRLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/Irr/IRRLoader.cpp b/code/AssetLib/Irr/IRRLoader.cpp index ba6ebc964..f841cd876 100644 --- a/code/AssetLib/Irr/IRRLoader.cpp +++ b/code/AssetLib/Irr/IRRLoader.cpp @@ -575,8 +575,8 @@ void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis m->mSemantic = prop->mSemantic; m->mType = aiPTI_Float; - m->mDataLength = 12; - m->mData = new char[12]; + m->mDataLength = sizeof(aiVector3D); + m->mData = new char[m->mDataLength]; *((aiVector3D *)m->mData) = axis; p.push_back(m); } From 25aee03f6626c93a0b188a6291c4bf7ff88b2cb7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 29 Oct 2023 09:44:23 +0100 Subject: [PATCH 04/11] Fix: Add missing transformation for normalized normals. --- code/PostProcessing/PretransformVertices.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/code/PostProcessing/PretransformVertices.cpp b/code/PostProcessing/PretransformVertices.cpp index 87af2297d..aff6e535a 100644 --- a/code/PostProcessing/PretransformVertices.cpp +++ b/code/PostProcessing/PretransformVertices.cpp @@ -290,12 +290,6 @@ void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) { } } -static void normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors) { - for (size_t i=0; iHasNormals()) { - normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices); + for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { + mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize(); + } } + if (mesh->HasTangentsAndBitangents()) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); From c1deb808faadd85a7a007447b62ae238a4be2337 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sun, 29 Oct 2023 09:47:02 +0100 Subject: [PATCH 05/11] Fix: Remove incorrect final statements --- test/unit/utBlendImportAreaLight.cpp | 3 +++ test/unit/utBlenderWork.cpp | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/unit/utBlendImportAreaLight.cpp b/test/unit/utBlendImportAreaLight.cpp index 4a16e662c..470d80737 100644 --- a/test/unit/utBlendImportAreaLight.cpp +++ b/test/unit/utBlendImportAreaLight.cpp @@ -48,6 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class BlendImportAreaLight : public ::testing::Test { public: + BlendImportAreaLight() : + im(nullptr) {} + ~BlendImportAreaLight() override = default; void SetUp() override { im = new Assimp::Importer(); } diff --git a/test/unit/utBlenderWork.cpp b/test/unit/utBlenderWork.cpp index b20720521..977877250 100644 --- a/test/unit/utBlenderWork.cpp +++ b/test/unit/utBlenderWork.cpp @@ -48,11 +48,14 @@ using namespace ::Assimp; class BlenderWorkTest : public ::testing::Test { public: - virtual void SetUp() { + BlenderWorkTest() : im(nullptr) {} + ~BlenderWorkTest() override = default; + + void SetUp() override { im = new Assimp::Importer(); } - virtual void TearDown() { + void TearDown() override { delete im; } From a7cfa3264a9ab2b6694fc79f09b14494921b2e04 Mon Sep 17 00:00:00 2001 From: Pavel Lukandiy Date: Wed, 11 Oct 2023 11:44:22 +0700 Subject: [PATCH 06/11] Fix: Implicit Conversion Error --- code/AssetLib/IFC/IFCLoader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/AssetLib/IFC/IFCLoader.cpp b/code/AssetLib/IFC/IFCLoader.cpp index 89012902c..990986b62 100644 --- a/code/AssetLib/IFC/IFCLoader.cpp +++ b/code/AssetLib/IFC/IFCLoader.cpp @@ -185,7 +185,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy size_t total = 0; int read = 0; do { - int bufferSize = fileInfo.uncompressed_size < INT16_MAX ? fileInfo.uncompressed_size : INT16_MAX; + unsigned bufferSize = fileInfo.uncompressed_size < INT16_MAX ? static_cast(fileInfo.uncompressed_size) : INT16_MAX; void *buffer = malloc(bufferSize); read = unzReadCurrentFile(zip, buffer, bufferSize); if (read > 0) { From f844c3397d7726477ab0fdca8efd3df56c18366b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 3 Nov 2023 11:47:13 +0100 Subject: [PATCH 07/11] Fix add checks for indices --- code/AssetLib/X/XFileImporter.cpp | 432 +++++++++++++++--------------- code/AssetLib/X/XFileImporter.h | 2 +- 2 files changed, 216 insertions(+), 218 deletions(-) diff --git a/code/AssetLib/X/XFileImporter.cpp b/code/AssetLib/X/XFileImporter.cpp index 1474ad808..271812859 100644 --- a/code/AssetLib/X/XFileImporter.cpp +++ b/code/AssetLib/X/XFileImporter.cpp @@ -57,7 +57,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -using namespace Assimp; +namespace Assimp { + using namespace Assimp::Formatter; static const aiImporterDesc desc = { @@ -73,142 +74,137 @@ static const aiImporterDesc desc = { "x" }; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -XFileImporter::XFileImporter() = default; - // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { +bool XFileImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { static const uint32_t token[] = { AI_MAKE_MAGIC("xof ") }; - return CheckMagicToken(pIOHandler,pFile,token,AI_COUNT_OF(token)); + return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token)); } // ------------------------------------------------------------------------------------------------ // Get file extension list -const aiImporterDesc* XFileImporter::GetInfo () const { +const aiImporterDesc *XFileImporter::GetInfo() const { return &desc; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { +void XFileImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { // read file into memory - std::unique_ptr file( pIOHandler->Open( pFile)); + std::unique_ptr file(pIOHandler->Open(pFile)); if (file == nullptr) { - throw DeadlyImportError( "Failed to open file ", pFile, "." ); + throw DeadlyImportError("Failed to open file ", pFile, "."); } static const size_t MinSize = 16; size_t fileSize = file->FileSize(); - if ( fileSize < MinSize ) { - throw DeadlyImportError( "XFile is too small." ); + if (fileSize < MinSize) { + throw DeadlyImportError("XFile is too small."); } // in the hope that binary files will never start with a BOM ... - mBuffer.resize( fileSize + 1); - file->Read( &mBuffer.front(), 1, fileSize); + mBuffer.resize(fileSize + 1); + file->Read(&mBuffer.front(), 1, fileSize); ConvertToUTF8(mBuffer); // parse the file into a temporary representation - XFileParser parser( mBuffer); + XFileParser parser(mBuffer); // and create the proper return structures out of it - CreateDataRepresentationFromImport( pScene, parser.GetImportedData()); + CreateDataRepresentationFromImport(pScene, parser.GetImportedData()); // if nothing came from it, report it as error - if ( !pScene->mRootNode ) { - throw DeadlyImportError( "XFile is ill-formatted - no content imported." ); + if (!pScene->mRootNode) { + throw DeadlyImportError("XFile is ill-formatted - no content imported."); } } // ------------------------------------------------------------------------------------------------ // Constructs the return data structure out of the imported data. -void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData) -{ +void XFileImporter::CreateDataRepresentationFromImport(aiScene *pScene, XFile::Scene *pData) { // Read the global materials first so that meshes referring to them can find them later - ConvertMaterials( pScene, pData->mGlobalMaterials); + ConvertMaterials(pScene, pData->mGlobalMaterials); // copy nodes, extracting meshes and materials on the way - pScene->mRootNode = CreateNodes( pScene, nullptr, pData->mRootNode); + pScene->mRootNode = CreateNodes(pScene, nullptr, pData->mRootNode); // extract animations - CreateAnimations( pScene, pData); + CreateAnimations(pScene, pData); // read the global meshes that were stored outside of any node - if( !pData->mGlobalMeshes.empty() ) { + if (!pData->mGlobalMeshes.empty()) { // create a root node to hold them if there isn't any, yet - if( pScene->mRootNode == nullptr ) { + if (pScene->mRootNode == nullptr) { pScene->mRootNode = new aiNode; - pScene->mRootNode->mName.Set( "$dummy_node"); + pScene->mRootNode->mName.Set("$dummy_node"); } // convert all global meshes and store them in the root node. // If there was one before, the global meshes now suddenly have its transformation matrix... // Don't know what to do there, I don't want to insert another node under the present root node // just to avoid this. - CreateMeshes( pScene, pScene->mRootNode, pData->mGlobalMeshes); + CreateMeshes(pScene, pScene->mRootNode, pData->mGlobalMeshes); } if (!pScene->mRootNode) { - throw DeadlyImportError( "No root node" ); + throw DeadlyImportError("No root node"); } // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly MakeLeftHandedProcess convertProcess; - convertProcess.Execute( pScene); + convertProcess.Execute(pScene); FlipWindingOrderProcess flipper; flipper.Execute(pScene); // finally: create a dummy material if not material was imported - if( pScene->mNumMaterials == 0) { + if (pScene->mNumMaterials == 0) { pScene->mNumMaterials = 1; // create the Material - aiMaterial* mat = new aiMaterial; - int shadeMode = (int) aiShadingMode_Gouraud; - mat->AddProperty( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); + aiMaterial *mat = new aiMaterial; + int shadeMode = (int)aiShadingMode_Gouraud; + mat->AddProperty(&shadeMode, 1, AI_MATKEY_SHADING_MODEL); // material colours int specExp = 1; - aiColor3D clr = aiColor3D( 0, 0, 0); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_EMISSIVE); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_SPECULAR); + aiColor3D clr = aiColor3D(0, 0, 0); + mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_EMISSIVE); + mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); - clr = aiColor3D( 0.5f, 0.5f, 0.5f); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS); + clr = aiColor3D(0.5f, 0.5f, 0.5f); + mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); + mat->AddProperty(&specExp, 1, AI_MATKEY_SHININESS); - pScene->mMaterials = new aiMaterial*[1]; + pScene->mMaterials = new aiMaterial *[1]; pScene->mMaterials[0] = mat; } } // ------------------------------------------------------------------------------------------------ // Recursively creates scene nodes from the imported hierarchy. -aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFile::Node* pNode) { - if ( !pNode ) { +aiNode *XFileImporter::CreateNodes(aiScene *pScene, aiNode *pParent, const XFile::Node *pNode) { + if (!pNode) { return nullptr; } // create node - aiNode* node = new aiNode; + aiNode *node = new aiNode; node->mName.length = (ai_uint32)pNode->mName.length(); node->mParent = pParent; - memcpy( node->mName.data, pNode->mName.c_str(), pNode->mName.length()); + memcpy(node->mName.data, pNode->mName.c_str(), pNode->mName.length()); node->mName.data[node->mName.length] = 0; node->mTransformation = pNode->mTrafoMatrix; // convert meshes from the source node - CreateMeshes( pScene, node, pNode->mMeshes); + CreateMeshes(pScene, node, pNode->mMeshes); // handle children - if( !pNode->mChildren.empty() ) { + if (!pNode->mChildren.empty()) { node->mNumChildren = (unsigned int)pNode->mChildren.size(); - node->mChildren = new aiNode* [node->mNumChildren]; + node->mChildren = new aiNode *[node->mNumChildren]; - for ( unsigned int a = 0; a < pNode->mChildren.size(); ++a ) { - node->mChildren[ a ] = CreateNodes( pScene, node, pNode->mChildren[ a ] ); + for (unsigned int a = 0; a < pNode->mChildren.size(); ++a) { + node->mChildren[a] = CreateNodes(pScene, node, pNode->mChildren[a]); } } @@ -217,55 +213,55 @@ aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFil // ------------------------------------------------------------------------------------------------ // Creates the meshes for the given node. -void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector& pMeshes) { +void XFileImporter::CreateMeshes(aiScene *pScene, aiNode *pNode, const std::vector &pMeshes) { if (pMeshes.empty()) { return; } // create a mesh for each mesh-material combination in the source node - std::vector meshes; - for( unsigned int a = 0; a < pMeshes.size(); ++a ) { - XFile::Mesh* sourceMesh = pMeshes[a]; - if ( nullptr == sourceMesh ) { + std::vector meshes; + for (unsigned int a = 0; a < pMeshes.size(); ++a) { + XFile::Mesh *sourceMesh = pMeshes[a]; + if (nullptr == sourceMesh) { continue; } // first convert its materials so that we can find them with their index afterwards - ConvertMaterials( pScene, sourceMesh->mMaterials); + ConvertMaterials(pScene, sourceMesh->mMaterials); - unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u); - for( unsigned int b = 0; b < numMaterials; ++b ) { + unsigned int numMaterials = std::max((unsigned int)sourceMesh->mMaterials.size(), 1u); + for (unsigned int b = 0; b < numMaterials; ++b) { // collect the faces belonging to this material std::vector faces; unsigned int numVertices = 0; - if( !sourceMesh->mFaceMaterials.empty() ) { + if (!sourceMesh->mFaceMaterials.empty()) { // if there is a per-face material defined, select the faces with the corresponding material - for( unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); ++c ) { - if( sourceMesh->mFaceMaterials[c] == b) { - faces.push_back( c); + for (unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); ++c) { + if (sourceMesh->mFaceMaterials[c] == b) { + faces.push_back(c); numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); } } } else { // if there is no per-face material, place everything into one mesh - for( unsigned int c = 0; c < sourceMesh->mPosFaces.size(); ++c ) { - faces.push_back( c); + for (unsigned int c = 0; c < sourceMesh->mPosFaces.size(); ++c) { + faces.push_back(c); numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); } } // no faces/vertices using this material? strange... - if ( numVertices == 0 ) { + if (numVertices == 0) { continue; } // create a submesh using this material - aiMesh* mesh = new aiMesh; - meshes.push_back( mesh); + aiMesh *mesh = new aiMesh; + meshes.push_back(mesh); // find the material in the scene's material list. Either own material // or referenced material, it should already have a valid index - if( !sourceMesh->mFaceMaterials.empty() ) { + if (!sourceMesh->mFaceMaterials.empty()) { mesh->mMaterialIndex = static_cast(sourceMesh->mMaterials[b].sceneIndex); } else { mesh->mMaterialIndex = 0; @@ -282,41 +278,41 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec mesh->mName.Set(sourceMesh->mName); // normals? - if ( sourceMesh->mNormals.size() > 0 ) { - mesh->mNormals = new aiVector3D[ numVertices ]; + if (sourceMesh->mNormals.size() > 0) { + mesh->mNormals = new aiVector3D[numVertices]; } // texture coords - for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c ) { - if ( !sourceMesh->mTexCoords[ c ].empty() ) { - mesh->mTextureCoords[ c ] = new aiVector3D[ numVertices ]; + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) { + if (!sourceMesh->mTexCoords[c].empty()) { + mesh->mTextureCoords[c] = new aiVector3D[numVertices]; } } // vertex colors - for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c ) { - if ( !sourceMesh->mColors[ c ].empty() ) { - mesh->mColors[ c ] = new aiColor4D[ numVertices ]; + for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) { + if (!sourceMesh->mColors[c].empty()) { + mesh->mColors[c] = new aiColor4D[numVertices]; } } // now collect the vertex data of all data streams present in the imported mesh - unsigned int newIndex( 0 ); + unsigned int newIndex(0); std::vector orgPoints; // from which original point each new vertex stems - orgPoints.resize( numVertices, 0); + orgPoints.resize(numVertices, 0); - for( unsigned int c = 0; c < faces.size(); ++c ) { + for (unsigned int c = 0; c < faces.size(); ++c) { unsigned int f = faces[c]; // index of the source face - const XFile::Face& pf = sourceMesh->mPosFaces[f]; // position source face + const XFile::Face &pf = sourceMesh->mPosFaces[f]; // position source face // create face. either triangle or triangle fan depending on the index count - aiFace& df = mesh->mFaces[c]; // destination face + aiFace &df = mesh->mFaces[c]; // destination face df.mNumIndices = (unsigned int)pf.mIndices.size(); - df.mIndices = new unsigned int[ df.mNumIndices]; + df.mIndices = new unsigned int[df.mNumIndices]; // collect vertex data for indices of this face - for( unsigned int d = 0; d < df.mNumIndices; ++d ) { - df.mIndices[ d ] = newIndex; - const unsigned int newIdx( pf.mIndices[ d ] ); - if ( newIdx > sourceMesh->mPositions.size() ) { + for (unsigned int d = 0; d < df.mNumIndices; ++d) { + df.mIndices[d] = newIndex; + const unsigned int newIdx = pf.mIndices[d]; + if (newIdx >= sourceMesh->mPositions.size()) { continue; } @@ -325,24 +321,26 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec // Position mesh->mVertices[newIndex] = sourceMesh->mPositions[pf.mIndices[d]]; // Normal, if present - if ( mesh->HasNormals() ) { - if ( sourceMesh->mNormFaces[ f ].mIndices.size() > d ) { - const size_t idx( sourceMesh->mNormFaces[ f ].mIndices[ d ] ); - mesh->mNormals[ newIndex ] = sourceMesh->mNormals[ idx ]; + if (mesh->HasNormals()) { + if (sourceMesh->mNormFaces[f].mIndices.size() > d) { + const size_t idx(sourceMesh->mNormFaces[f].mIndices[d]); + if (idx < sourceMesh->mNormals.size()) { + mesh->mNormals[newIndex] = sourceMesh->mNormals[idx]; + } } } // texture coord sets - for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++e ) { - if( mesh->HasTextureCoords( e)) { + for (unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++e) { + if (mesh->HasTextureCoords(e)) { aiVector2D tex = sourceMesh->mTexCoords[e][pf.mIndices[d]]; - mesh->mTextureCoords[e][newIndex] = aiVector3D( tex.x, 1.0f - tex.y, 0.0f); + mesh->mTextureCoords[e][newIndex] = aiVector3D(tex.x, 1.0f - tex.y, 0.0f); } } // vertex color sets - for ( unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; ++e ) { - if ( mesh->HasVertexColors( e ) ) { - mesh->mColors[ e ][ newIndex ] = sourceMesh->mColors[ e ][ pf.mIndices[ d ] ]; + for (unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; ++e) { + if (mesh->HasVertexColors(e)) { + mesh->mColors[e][newIndex] = sourceMesh->mColors[e][pf.mIndices[d]]; } } @@ -351,63 +349,66 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec } // there should be as much new vertices as we calculated before - ai_assert( newIndex == numVertices); + ai_assert(newIndex == numVertices); // convert all bones of the source mesh which influence vertices in this newly created mesh - const std::vector& bones = sourceMesh->mBones; - std::vector newBones; - for( unsigned int c = 0; c < bones.size(); ++c ) { - const XFile::Bone& obone = bones[c]; + const std::vector &bones = sourceMesh->mBones; + std::vector newBones; + for (unsigned int c = 0; c < bones.size(); ++c) { + const XFile::Bone &obone = bones[c]; // set up a vertex-linear array of the weights for quick searching if a bone influences a vertex - std::vector oldWeights( sourceMesh->mPositions.size(), 0.0); - for ( unsigned int d = 0; d < obone.mWeights.size(); ++d ) { - oldWeights[ obone.mWeights[ d ].mVertex ] = obone.mWeights[ d ].mWeight; + std::vector oldWeights(sourceMesh->mPositions.size(), 0.0); + for (unsigned int d = 0; d < obone.mWeights.size(); ++d) { + const unsigned int boneIdx = obone.mWeights[d].mVertex; + if (boneIdx < obone.mWeights.size()) { + oldWeights[obone.mWeights[d].mVertex] = obone.mWeights[d].mWeight; + } } // collect all vertex weights that influence a vertex in the new mesh std::vector newWeights; - newWeights.reserve( numVertices); - for( unsigned int d = 0; d < orgPoints.size(); ++d ) { + newWeights.reserve(numVertices); + for (unsigned int d = 0; d < orgPoints.size(); ++d) { // does the new vertex stem from an old vertex which was influenced by this bone? ai_real w = oldWeights[orgPoints[d]]; - if ( w > 0.0 ) { - newWeights.emplace_back( d, w ); + if (w > 0.0) { + newWeights.emplace_back(d, w); } } // if the bone has no weights in the newly created mesh, ignore it - if ( newWeights.empty() ) { + if (newWeights.empty()) { continue; } // create - aiBone* nbone = new aiBone; - newBones.push_back( nbone); + aiBone *nbone = new aiBone; + newBones.push_back(nbone); // copy name and matrix - nbone->mName.Set( obone.mName); + nbone->mName.Set(obone.mName); nbone->mOffsetMatrix = obone.mOffsetMatrix; nbone->mNumWeights = (unsigned int)newWeights.size(); nbone->mWeights = new aiVertexWeight[nbone->mNumWeights]; - for ( unsigned int d = 0; d < newWeights.size(); ++d ) { - nbone->mWeights[ d ] = newWeights[ d ]; + for (unsigned int d = 0; d < newWeights.size(); ++d) { + nbone->mWeights[d] = newWeights[d]; } } // store the bones in the mesh mesh->mNumBones = (unsigned int)newBones.size(); - if( !newBones.empty()) { - mesh->mBones = new aiBone*[mesh->mNumBones]; - std::copy( newBones.begin(), newBones.end(), mesh->mBones); + if (!newBones.empty()) { + mesh->mBones = new aiBone *[mesh->mNumBones]; + std::copy(newBones.begin(), newBones.end(), mesh->mBones); } } } // reallocate scene mesh array to be large enough - aiMesh** prevArray = pScene->mMeshes; - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes + meshes.size()]; - if( prevArray) { - memcpy( pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof( aiMesh*)); - delete [] prevArray; + aiMesh **prevArray = pScene->mMeshes; + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes + meshes.size()]; + if (prevArray) { + memcpy(pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof(aiMesh *)); + delete[] prevArray; } // allocate mesh index array in the node @@ -415,7 +416,7 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec pNode->mMeshes = new unsigned int[pNode->mNumMeshes]; // store all meshes in the mesh library of the scene and store their indices in the node - for( unsigned int a = 0; a < meshes.size(); a++) { + for (unsigned int a = 0; a < meshes.size(); a++) { pScene->mMeshes[pScene->mNumMeshes] = meshes[a]; pNode->mMeshes[a] = pScene->mNumMeshes; pScene->mNumMeshes++; @@ -424,35 +425,34 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec // ------------------------------------------------------------------------------------------------ // Converts the animations from the given imported data and creates them in the scene. -void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData) { - std::vector newAnims; +void XFileImporter::CreateAnimations(aiScene *pScene, const XFile::Scene *pData) { + std::vector newAnims; - for( unsigned int a = 0; a < pData->mAnims.size(); ++a ) { - const XFile::Animation* anim = pData->mAnims[a]; + for (unsigned int a = 0; a < pData->mAnims.size(); ++a) { + const XFile::Animation *anim = pData->mAnims[a]; // some exporters mock me with empty animation tags. - if ( anim->mAnims.empty() ) { + if (anim->mAnims.empty()) { continue; } // create a new animation to hold the data - aiAnimation* nanim = new aiAnimation; - newAnims.push_back( nanim); - nanim->mName.Set( anim->mName); + aiAnimation *nanim = new aiAnimation; + newAnims.push_back(nanim); + nanim->mName.Set(anim->mName); // duration will be determined by the maximum length nanim->mDuration = 0; nanim->mTicksPerSecond = pData->mAnimTicksPerSecond; nanim->mNumChannels = (unsigned int)anim->mAnims.size(); - nanim->mChannels = new aiNodeAnim*[nanim->mNumChannels]; + nanim->mChannels = new aiNodeAnim *[nanim->mNumChannels]; - for( unsigned int b = 0; b < anim->mAnims.size(); ++b ) { - const XFile::AnimBone* bone = anim->mAnims[b]; - aiNodeAnim* nbone = new aiNodeAnim; - nbone->mNodeName.Set( bone->mBoneName); + for (unsigned int b = 0; b < anim->mAnims.size(); ++b) { + const XFile::AnimBone *bone = anim->mAnims[b]; + aiNodeAnim *nbone = new aiNodeAnim; + nbone->mNodeName.Set(bone->mBoneName); nanim->mChannels[b] = nbone; // key-frames are given as combined transformation matrix keys - if( !bone->mTrafoKeys.empty() ) - { + if (!bone->mTrafoKeys.empty()) { nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size(); nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; nbone->mNumRotationKeys = (unsigned int)bone->mTrafoKeys.size(); @@ -460,44 +460,44 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData nbone->mNumScalingKeys = (unsigned int)bone->mTrafoKeys.size(); nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; - for( unsigned int c = 0; c < bone->mTrafoKeys.size(); ++c) { + for (unsigned int c = 0; c < bone->mTrafoKeys.size(); ++c) { // deconstruct each matrix into separate position, rotation and scaling double time = bone->mTrafoKeys[c].mTime; aiMatrix4x4 trafo = bone->mTrafoKeys[c].mMatrix; // extract position - aiVector3D pos( trafo.a4, trafo.b4, trafo.c4); + aiVector3D pos(trafo.a4, trafo.b4, trafo.c4); nbone->mPositionKeys[c].mTime = time; nbone->mPositionKeys[c].mValue = pos; // extract scaling aiVector3D scale; - scale.x = aiVector3D( trafo.a1, trafo.b1, trafo.c1).Length(); - scale.y = aiVector3D( trafo.a2, trafo.b2, trafo.c2).Length(); - scale.z = aiVector3D( trafo.a3, trafo.b3, trafo.c3).Length(); + scale.x = aiVector3D(trafo.a1, trafo.b1, trafo.c1).Length(); + scale.y = aiVector3D(trafo.a2, trafo.b2, trafo.c2).Length(); + scale.z = aiVector3D(trafo.a3, trafo.b3, trafo.c3).Length(); nbone->mScalingKeys[c].mTime = time; nbone->mScalingKeys[c].mValue = scale; // reconstruct rotation matrix without scaling aiMatrix3x3 rotmat( - trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z, - trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z, - trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z); + trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z, + trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z, + trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z); // and convert it into a quaternion nbone->mRotationKeys[c].mTime = time; - nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); + nbone->mRotationKeys[c].mValue = aiQuaternion(rotmat); } // longest lasting key sequence determines duration - nanim->mDuration = std::max( nanim->mDuration, bone->mTrafoKeys.back().mTime); + nanim->mDuration = std::max(nanim->mDuration, bone->mTrafoKeys.back().mTime); } else { // separate key sequences for position, rotation, scaling nbone->mNumPositionKeys = (unsigned int)bone->mPosKeys.size(); if (nbone->mNumPositionKeys != 0) { nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; - for( unsigned int c = 0; c < nbone->mNumPositionKeys; ++c ) { + for (unsigned int c = 0; c < nbone->mNumPositionKeys; ++c) { aiVector3D pos = bone->mPosKeys[c].mValue; nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime; @@ -509,11 +509,11 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData nbone->mNumRotationKeys = (unsigned int)bone->mRotKeys.size(); if (nbone->mNumRotationKeys != 0) { nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys]; - for( unsigned int c = 0; c < nbone->mNumRotationKeys; ++c ) { + for (unsigned int c = 0; c < nbone->mNumRotationKeys; ++c) { aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix(); nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime; - nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); + nbone->mRotationKeys[c].mValue = aiQuaternion(rotmat); nbone->mRotationKeys[c].mValue.w *= -1.0f; // needs quat inversion } } @@ -522,153 +522,149 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData nbone->mNumScalingKeys = (unsigned int)bone->mScaleKeys.size(); if (nbone->mNumScalingKeys != 0) { nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; - for( unsigned int c = 0; c < nbone->mNumScalingKeys; c++) + for (unsigned int c = 0; c < nbone->mNumScalingKeys; c++) nbone->mScalingKeys[c] = bone->mScaleKeys[c]; } // longest lasting key sequence determines duration - if( bone->mPosKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mPosKeys.back().mTime); - if( bone->mRotKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mRotKeys.back().mTime); - if( bone->mScaleKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mScaleKeys.back().mTime); + if (bone->mPosKeys.size() > 0) + nanim->mDuration = std::max(nanim->mDuration, bone->mPosKeys.back().mTime); + if (bone->mRotKeys.size() > 0) + nanim->mDuration = std::max(nanim->mDuration, bone->mRotKeys.back().mTime); + if (bone->mScaleKeys.size() > 0) + nanim->mDuration = std::max(nanim->mDuration, bone->mScaleKeys.back().mTime); } } } // store all converted animations in the scene - if( newAnims.size() > 0) - { + if (newAnims.size() > 0) { pScene->mNumAnimations = (unsigned int)newAnims.size(); - pScene->mAnimations = new aiAnimation* [pScene->mNumAnimations]; - for( unsigned int a = 0; a < newAnims.size(); a++) + pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations]; + for (unsigned int a = 0; a < newAnims.size(); a++) pScene->mAnimations[a] = newAnims[a]; } } // ------------------------------------------------------------------------------------------------ // Converts all materials in the given array and stores them in the scene's material list. -void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector& pMaterials) -{ +void XFileImporter::ConvertMaterials(aiScene *pScene, std::vector &pMaterials) { // count the non-referrer materials in the array - unsigned int numNewMaterials( 0 ); - for ( unsigned int a = 0; a < pMaterials.size(); ++a ) { - if ( !pMaterials[ a ].mIsReference ) { + unsigned int numNewMaterials(0); + for (unsigned int a = 0; a < pMaterials.size(); ++a) { + if (!pMaterials[a].mIsReference) { ++numNewMaterials; } } // resize the scene's material list to offer enough space for the new materials - if( numNewMaterials > 0 ) { - aiMaterial** prevMats = pScene->mMaterials; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numNewMaterials]; - if( nullptr != prevMats) { - ::memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*)); - delete [] prevMats; + if (numNewMaterials > 0) { + aiMaterial **prevMats = pScene->mMaterials; + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials + numNewMaterials]; + if (nullptr != prevMats) { + ::memcpy(pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof(aiMaterial *)); + delete[] prevMats; } } // convert all the materials given in the array - for( unsigned int a = 0; a < pMaterials.size(); ++a ) { - XFile::Material& oldMat = pMaterials[a]; - if( oldMat.mIsReference) { + for (unsigned int a = 0; a < pMaterials.size(); ++a) { + XFile::Material &oldMat = pMaterials[a]; + if (oldMat.mIsReference) { // find the material it refers to by name, and store its index - for( size_t b = 0; b < pScene->mNumMaterials; ++b ) { + for (size_t b = 0; b < pScene->mNumMaterials; ++b) { aiString name; - pScene->mMaterials[b]->Get( AI_MATKEY_NAME, name); - if( strcmp( name.C_Str(), oldMat.mName.data()) == 0 ) { + pScene->mMaterials[b]->Get(AI_MATKEY_NAME, name); + if (strcmp(name.C_Str(), oldMat.mName.data()) == 0) { oldMat.sceneIndex = b; break; } } - if( oldMat.sceneIndex == SIZE_MAX ) { - ASSIMP_LOG_WARN( "Could not resolve global material reference \"", oldMat.mName, "\"" ); + if (oldMat.sceneIndex == SIZE_MAX) { + ASSIMP_LOG_WARN("Could not resolve global material reference \"", oldMat.mName, "\""); oldMat.sceneIndex = 0; } continue; } - aiMaterial* mat = new aiMaterial; + aiMaterial *mat = new aiMaterial; aiString name; - name.Set( oldMat.mName); - mat->AddProperty( &name, AI_MATKEY_NAME); + name.Set(oldMat.mName); + mat->AddProperty(&name, AI_MATKEY_NAME); // Shading model: hard-coded to PHONG, there is no such information in an XFile // FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix // for some models in the SDK (e.g. good old tiny.x) - int shadeMode = (int)oldMat.mSpecularExponent == 0.0f - ? aiShadingMode_Gouraud : aiShadingMode_Phong; + int shadeMode = (int)oldMat.mSpecularExponent == 0.0f ? aiShadingMode_Gouraud : aiShadingMode_Phong; - mat->AddProperty( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); + mat->AddProperty(&shadeMode, 1, AI_MATKEY_SHADING_MODEL); // material colours // Unclear: there's no ambient colour, but emissive. What to put for ambient? // Probably nothing at all, let the user select a suitable default. - mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); - mat->AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - mat->AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); - + mat->AddProperty(&oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); + mat->AddProperty(&oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + mat->AddProperty(&oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); + mat->AddProperty(&oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); // texture, if there is one - if (1 == oldMat.mTextures.size() ) { - const XFile::TexEntry& otex = oldMat.mTextures.back(); + if (1 == oldMat.mTextures.size()) { + const XFile::TexEntry &otex = oldMat.mTextures.back(); if (otex.mName.length()) { // if there is only one texture assume it contains the diffuse color - aiString tex( otex.mName); - if ( otex.mIsNormalMap ) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS( 0 ) ); + aiString tex(otex.mName); + if (otex.mIsNormalMap) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(0)); } else { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(0)); } } } else { // Otherwise ... try to search for typical strings in the // texture's file name like 'bump' or 'diffuse' - unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0; - for( unsigned int b = 0; b < oldMat.mTextures.size(); ++b ) { - const XFile::TexEntry& otex = oldMat.mTextures[b]; + unsigned int iHM = 0, iNM = 0, iDM = 0, iSM = 0, iAM = 0, iEM = 0; + for (unsigned int b = 0; b < oldMat.mTextures.size(); ++b) { + const XFile::TexEntry &otex = oldMat.mTextures[b]; std::string sz = otex.mName; - if ( !sz.length() ) { + if (!sz.length()) { continue; } // find the file name std::string::size_type s = sz.find_last_of("\\/"); - if ( std::string::npos == s ) { + if (std::string::npos == s) { s = 0; } // cut off the file extension std::string::size_type sExt = sz.find_last_of('.'); - if (std::string::npos != sExt){ + if (std::string::npos != sExt) { sz[sExt] = '\0'; } // convert to lower case for easier comparison - for ( unsigned int c = 0; c < sz.length(); ++c ) { - sz[ c ] = (char) tolower( (unsigned char) sz[ c ] ); + for (unsigned int c = 0; c < sz.length(); ++c) { + sz[c] = (char)tolower((unsigned char)sz[c]); } // Place texture filename property under the corresponding name - aiString tex( oldMat.mTextures[b].mName); + aiString tex(oldMat.mTextures[b].mName); // bump map if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++)); - } else if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(iNM++)); - } else if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++)); - } else if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++)); - } else if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s)) { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++)); + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++)); + } else if (otex.mIsNormalMap || std::string::npos != sz.find("normal", s) || std::string::npos != sz.find("nm", s)) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(iNM++)); + } else if (std::string::npos != sz.find("spec", s) || std::string::npos != sz.find("glanz", s)) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++)); + } else if (std::string::npos != sz.find("ambi", s) || std::string::npos != sz.find("env", s)) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++)); + } else if (std::string::npos != sz.find("emissive", s) || std::string::npos != sz.find("self", s)) { + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++)); } else { // Assume it is a diffuse texture - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++)); + mat->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++)); } } } @@ -679,4 +675,6 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector Date: Sun, 5 Nov 2023 17:32:18 +0100 Subject: [PATCH 08/11] Update FBXBinaryTokenizer.cpp - closes https://github.com/assimp/assimp/issues/5072 --- code/AssetLib/FBX/FBXBinaryTokenizer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp index 8d79e2339..55424a6a8 100644 --- a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp +++ b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXUtil.h" #include #include +#include #include #include #include From a521b23ab5ca49ddfd0ce0e3fbd0704725287417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Aumu=CC=88ller?= Date: Sat, 14 Oct 2023 14:49:41 +0200 Subject: [PATCH 09/11] link to external minizip with full path This let's cmake create config files that allow linking to minizip even when in an unrelated prefix. This can happen with package managers that install every package into their own prefix, such as [Spack](https://spack.io). --- code/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 0fe2291f8..3be1004a7 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1380,7 +1380,12 @@ ENDIF() IF(NOT ASSIMP_HUNTER_ENABLED) if (UNZIP_FOUND) INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS}) - TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES}) + # TODO if cmake required version has been updated to >3.12.0, collapse this to the second case only + if(${CMAKE_VERSION} VERSION_LESS "3.12.0") + TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES}) + else() + TARGET_LINK_LIBRARIES(assimp ${UNZIP_LINK_LIBRARIES}) + endif() else () INCLUDE_DIRECTORIES("../") endif () From 46b19cc6a4cc4129d996614591e91c2cf165d5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=A1rcio=20Vin=C3=ADcius?= Date: Sun, 15 Oct 2023 17:48:38 -0300 Subject: [PATCH 10/11] utf8 header not found --- code/CMakeLists.txt | 2 +- samples/SimpleTexturedDirectx11/CMakeLists.txt | 1 + .../SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp | 1 + samples/SimpleTexturedOpenGL/CMakeLists.txt | 1 + .../SimpleTexturedOpenGL/src/model_loading.cpp | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 3be1004a7..9b0b964c0 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -923,7 +923,7 @@ IF(ASSIMP_HUNTER_ENABLED) hunter_add_package(utf8) find_package(utf8cpp CONFIG REQUIRED) ELSE() - # utf8 is header-only, so Assimp doesn't need to do anything. + INCLUDE_DIRECTORIES("../contrib/utf8cpp/source") ENDIF() # polyclipping diff --git a/samples/SimpleTexturedDirectx11/CMakeLists.txt b/samples/SimpleTexturedDirectx11/CMakeLists.txt index de83734ba..f64923179 100644 --- a/samples/SimpleTexturedDirectx11/CMakeLists.txt +++ b/samples/SimpleTexturedDirectx11/CMakeLists.txt @@ -19,6 +19,7 @@ INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/code ${SAMPLES_SHARED_CODE_DIR} + ${Assimp_SOURCE_DIR}/contrib/utf8cpp/source ) LINK_DIRECTORIES( diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp index 4da5820a1..ec031a594 100644 --- a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "ModelLoader.h" #include "SafeRelease.hpp" diff --git a/samples/SimpleTexturedOpenGL/CMakeLists.txt b/samples/SimpleTexturedOpenGL/CMakeLists.txt index 70837e87c..a10a15101 100644 --- a/samples/SimpleTexturedOpenGL/CMakeLists.txt +++ b/samples/SimpleTexturedOpenGL/CMakeLists.txt @@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES( ${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${SAMPLES_SHARED_CODE_DIR} + ${Assimp_SOURCE_DIR}/contrib/utf8cpp/source ) LINK_DIRECTORIES( diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index 7d730a630..f6d3097fe 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef _MSC_VER #pragma warning(disable: 4100) // Disable warning 'unreferenced formal parameter' From 28ab0a094a66474f0379d004671c3d6a26457c38 Mon Sep 17 00:00:00 2001 From: julianknodt Date: Sun, 15 Oct 2023 22:03:31 -0700 Subject: [PATCH 11/11] Fix incorrect deg->radian conversion It seems that rotation matrices later expect radians. This conversion breaks it, and was validated on the conversion of `cesium_man.glb` --> `cesium_man.fbx` --- code/AssetLib/FBX/FBXConverter.cpp | 21 +++++++++++---------- code/AssetLib/FBX/FBXExporter.cpp | 10 ++++------ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 498da43ca..3538e84a8 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -577,16 +577,17 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot bool is_id[3] = { true, true, true }; aiMatrix4x4 temp[3]; - if (std::fabs(rotation.z) > angle_epsilon) { - aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]); + const auto rot = AI_DEG_TO_RAD(rotation); + if (std::fabs(rot.z) > angle_epsilon) { + aiMatrix4x4::RotationZ(rot.z, temp[2]); is_id[2] = false; } - if (std::fabs(rotation.y) > angle_epsilon) { - aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]); + if (std::fabs(rot.y) > angle_epsilon) { + aiMatrix4x4::RotationY(rot.y, temp[1]); is_id[1] = false; } - if (std::fabs(rotation.x) > angle_epsilon) { - aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]); + if (std::fabs(rot.x) > angle_epsilon) { + aiMatrix4x4::RotationX(rot.x, temp[0]); is_id[0] = false; } @@ -3225,7 +3226,6 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f)); aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)); aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f)); - aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder); aiVectorKey* outTranslations = new aiVectorKey[keyCount]; aiQuatKey* outRotations = new aiQuatKey[keyCount]; @@ -3241,8 +3241,9 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, } if (keyframeLists[TransformationComp_Rotation].size() > 0) { - InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder); + InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], AI_DEG_TO_RAD(defRotation), maxTime, minTime, rotOrder); } else { + aiQuaternion defQuat = EulerToQuaternion(AI_DEG_TO_RAD(defRotation), rotOrder); for (size_t i = 0; i < keyCount; ++i) { outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; outRotations[i].mValue = defQuat; @@ -3264,7 +3265,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, const aiVector3D& preRotation = PropertyGet(props, "PreRotation", ok); if (ok && preRotation.SquareLength() > zero_epsilon) { - const aiQuaternion preQuat = EulerToQuaternion(preRotation, Model::RotOrder_EulerXYZ); + const aiQuaternion preQuat = EulerToQuaternion(AI_DEG_TO_RAD(preRotation), Model::RotOrder_EulerXYZ); for (size_t i = 0; i < keyCount; ++i) { outRotations[i].mValue = preQuat * outRotations[i].mValue; } @@ -3272,7 +3273,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, const aiVector3D& postRotation = PropertyGet(props, "PostRotation", ok); if (ok && postRotation.SquareLength() > zero_epsilon) { - const aiQuaternion postQuat = EulerToQuaternion(postRotation, Model::RotOrder_EulerXYZ); + const aiQuaternion postQuat = EulerToQuaternion(AI_DEG_TO_RAD(postRotation), Model::RotOrder_EulerXYZ); for (size_t i = 0; i < keyCount; ++i) { outRotations[i].mValue = outRotations[i].mValue * postQuat; } diff --git a/code/AssetLib/FBX/FBXExporter.cpp b/code/AssetLib/FBX/FBXExporter.cpp index 9da713e5d..2ea505618 100644 --- a/code/AssetLib/FBX/FBXExporter.cpp +++ b/code/AssetLib/FBX/FBXExporter.cpp @@ -74,8 +74,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // https://code.blender.org/2013/08/fbx-binary-file-format-specification/ // https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure -const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian - using namespace Assimp; using namespace Assimp::FBX; @@ -2434,7 +2432,7 @@ void FBXExporter::WriteObjects () aiMatrix4x4 m(k.mValue.GetMatrix()); aiVector3D qs, qr, qt; m.Decompose(qs, qr, qt); - qr *= DEG; + qr = AI_RAD_TO_DEG(qr); xval.push_back(qr.x); yval.push_back(qr.y); zval.push_back(qr.z); @@ -2515,9 +2513,10 @@ void FBXExporter::WriteModelNode( ); } if (r != zero) { + r = AI_RAD_TO_DEG(r); p.AddP70( "Lcl Rotation", "Lcl Rotation", "", "A", - double(DEG*r.x), double(DEG*r.y), double(DEG*r.z) + double(r.x), double(r.y), double(r.z) ); } if (s != one) { @@ -2601,8 +2600,7 @@ void FBXExporter::WriteModelNodes( transform_chain.emplace_back(elem->first, t); break; case 'r': // rotation - r *= float(DEG); - transform_chain.emplace_back(elem->first, r); + transform_chain.emplace_back(elem->first, AI_RAD_TO_DEG(r)); break; case 's': // scale transform_chain.emplace_back(elem->first, s);