From b170370e5cd02b2f2e5abdf873537c97455a2ea7 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 8 Feb 2023 21:29:54 +0100 Subject: [PATCH 01/15] Fix: Fix memleak when exiting method by exception --- code/Common/Importer.cpp | 54 ++++++++++++++++++-------------- fuzz/assimp_fuzzer.cc | 7 +++-- include/assimp/MemoryIOWrapper.h | 12 +++---- 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index df2895eef..b66059397 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -482,37 +482,43 @@ bool Importer::ValidateFlags(unsigned int pFlags) const { } // ------------------------------------------------------------------------------------------------ -const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, - size_t pLength, - unsigned int pFlags, - const char* pHint /*= ""*/) { +const aiScene* Importer::ReadFileFromMemory(const void* pBuffer, size_t pLength, unsigned int pFlags, const char* pHint ) { ai_assert(nullptr != pimpl); - ASSIMP_BEGIN_EXCEPTION_REGION(); - if (!pHint) { - pHint = ""; - } - - if (!pBuffer || !pLength || strlen(pHint) > MaxLenHint ) { - pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()"; - return nullptr; - } - - // prevent deletion of the previous IOHandler IOSystem* io = pimpl->mIOHandler; - pimpl->mIOHandler = nullptr; + try { + if (pHint == nullptr) { + pHint = ""; + } + if (!pBuffer || !pLength || strlen(pHint) > MaxLenHint ) { + pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()"; + return nullptr; + } + // prevent deletion of the previous IOHandler + pimpl->mIOHandler = nullptr; - SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength,io)); + SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength,io)); - // read the file and recover the previous IOSystem - static const size_t BufSize(Importer::MaxLenHint + 28); - char fbuff[BufSize]; - ai_snprintf(fbuff, BufSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint); + // read the file and recover the previous IOSystem + static const size_t BufSize(Importer::MaxLenHint + 28); + char fbuff[BufSize]; + ai_snprintf(fbuff, BufSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint); - ReadFile(fbuff,pFlags); - SetIOHandler(io); + ReadFile(fbuff,pFlags); + SetIOHandler(io); + } catch(const DeadlyImportError &e) { + pimpl->mErrorString = e.what(); + pimpl->mException = std::current_exception(); + SetIOHandler(io); + return ExceptionSwallower()(); \ + } catch(...) { + pimpl->mErrorString = "Unknown exception"; + pimpl->mException = std::current_exception(); + SetIOHandler(io); + return ExceptionSwallower()(); \ + + } - ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString, pimpl->mException); return pimpl->mScene; } diff --git a/fuzz/assimp_fuzzer.cc b/fuzz/assimp_fuzzer.cc index 33748c10f..edb5fdbb5 100644 --- a/fuzz/assimp_fuzzer.cc +++ b/fuzz/assimp_fuzzer.cc @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2020, assimp team +Copyright (c) 2006-2023, assimp team All rights reserved. @@ -46,8 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) { - aiLogStream stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); - aiAttachLogStream(&stream); + aiLogStream stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); + aiAttachLogStream(&stream); Importer importer; const aiScene *sc = importer.ReadFileFromMemory(data, dataSize, @@ -57,3 +57,4 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataSize) { return 0; } + diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 0bd3bc108..d52c4384f 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -153,11 +152,7 @@ private: class MemoryIOSystem : public IOSystem { public: /** Constructor. */ - MemoryIOSystem(const uint8_t* buff, size_t len, IOSystem* io) - : buffer(buff) - , length(len) - , existing_io(io) - , created_streams() { + MemoryIOSystem(const uint8_t* buff, size_t len, IOSystem* io) : buffer(buff), length(len), existing_io(io) { // empty } @@ -167,6 +162,7 @@ public: // ------------------------------------------------------------------- /** Tests for the existence of a file at the given path. */ bool Exists(const char* pFile) const override { + printf("Exists\n"); if (0 == strncmp( pFile, AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH ) ) { return true; } @@ -187,7 +183,7 @@ public: created_streams.emplace_back(new MemoryIOStream(buffer, length)); return created_streams.back(); } - return existing_io ? existing_io->Open(pFile, pMode) : NULL; + return existing_io ? existing_io->Open(pFile, pMode) : nullptr; } // ------------------------------------------------------------------- @@ -246,4 +242,4 @@ private: } // end namespace Assimp -#endif +#endif // AI_MEMORYIOSTREAM_H_INC From b7d08fc8f2f9250de3ecefef49a26367e8ad141a Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 8 Feb 2023 21:48:55 +0100 Subject: [PATCH 02/15] Fix review findings. --- include/assimp/MemoryIOWrapper.h | 61 +++++++++++++++----------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index d52c4384f..720fd8424 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -65,23 +65,21 @@ namespace Assimp { // ---------------------------------------------------------------------------------- class MemoryIOStream : public IOStream { public: - MemoryIOStream (const uint8_t* buff, size_t len, bool own = false) - : buffer (buff) - , length(len) - , pos((size_t)0) - , own(own) { + MemoryIOStream (const uint8_t* buff, size_t len, bool own = false) : + buffer (buff), + length(len), + pos(static_cast(0)), + own(own) { // empty } - ~MemoryIOStream () { + ~MemoryIOStream() override { if(own) { delete[] buffer; } } - // ------------------------------------------------------------------- - // Read from stream - size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { + size_t Read(void* pvBuffer, size_t pSize, size_t pCount) override { ai_assert(nullptr != pvBuffer); ai_assert(0 != pSize); @@ -94,16 +92,12 @@ public: return cnt; } - // ------------------------------------------------------------------- - // Write to stream - size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/,size_t /*pCount*/) { + size_t Write(const void*, size_t, size_t ) override { ai_assert(false); // won't be needed return 0; } - // ------------------------------------------------------------------- - // Seek specific position - aiReturn Seek(size_t pOffset, aiOrigin pOrigin) { + aiReturn Seek(size_t pOffset, aiOrigin pOrigin) override { if (aiOrigin_SET == pOrigin) { if (pOffset > length) { return AI_FAILURE; @@ -123,20 +117,14 @@ public: return AI_SUCCESS; } - // ------------------------------------------------------------------- - // Get current seek position - size_t Tell() const { + size_t Tell() const override { return pos; } - // ------------------------------------------------------------------- - // Get size of file - size_t FileSize() const { + size_t FileSize() const override { return length; } - // ------------------------------------------------------------------- - // Flush file contents void Flush() { ai_assert(false); // won't be needed } @@ -148,19 +136,19 @@ private: }; // --------------------------------------------------------------------------- -/** Dummy IO system to read from a memory buffer */ +/// @brief Dummy IO system to read from a memory buffer. class MemoryIOSystem : public IOSystem { public: - /** Constructor. */ + /// @brief Constructor. MemoryIOSystem(const uint8_t* buff, size_t len, IOSystem* io) : buffer(buff), length(len), existing_io(io) { // empty } - /** Destructor. */ + /// @brief Destructor. ~MemoryIOSystem() = default; // ------------------------------------------------------------------- - /** Tests for the existence of a file at the given path. */ + /// @brief Tests for the existence of a file at the given path. bool Exists(const char* pFile) const override { printf("Exists\n"); if (0 == strncmp( pFile, AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH ) ) { @@ -170,14 +158,14 @@ public: } // ------------------------------------------------------------------- - /** Returns the directory separator. */ + /// @brief Returns the directory separator. char getOsSeparator() const override { return existing_io ? existing_io->getOsSeparator() : '/'; // why not? it doesn't care } // ------------------------------------------------------------------- - /** Open a new file with a given path. */ + /// @brief Open a new file with a given path. IOStream* Open(const char* pFile, const char* pMode = "rb") override { if ( 0 == strncmp( pFile, AI_MEMORYIO_MAGIC_FILENAME, AI_MEMORYIO_MAGIC_FILENAME_LENGTH ) ) { created_streams.emplace_back(new MemoryIOStream(buffer, length)); @@ -187,7 +175,7 @@ public: } // ------------------------------------------------------------------- - /** Closes the given file and releases all resources associated with it. */ + /// @brief Closes the given file and releases all resources associated with it. void Close( IOStream* pFile) override { auto it = std::find(created_streams.begin(), created_streams.end(), pFile); if (it != created_streams.end()) { @@ -199,36 +187,43 @@ public: } // ------------------------------------------------------------------- - /** Compare two paths */ + /// @brief Compare two paths bool ComparePaths(const char* one, const char* second) const override { return existing_io ? existing_io->ComparePaths(one, second) : false; } - + + /// @brief Will push the directory. bool PushDirectory( const std::string &path ) override { return existing_io ? existing_io->PushDirectory(path) : false; } + /// @brief Will return the current directory from the stack top. const std::string &CurrentDirectory() const override { static std::string empty; return existing_io ? existing_io->CurrentDirectory() : empty; } + /// @brief Returns the stack size. size_t StackSize() const override { return existing_io ? existing_io->StackSize() : 0; } + /// @brief Will pop the upper directory. bool PopDirectory() override { return existing_io ? existing_io->PopDirectory() : false; } + /// @brief Will create the directory. bool CreateDirectory( const std::string &path ) override { return existing_io ? existing_io->CreateDirectory(path) : false; } - + + /// @brief Will change the directory. bool ChangeDirectory( const std::string &path ) override { return existing_io ? existing_io->ChangeDirectory(path) : false; } + /// @brief Will delete the file. bool DeleteFile( const std::string &file ) override { return existing_io ? existing_io->DeleteFile(file) : false; } From 2390822baff6283c8ee2dacb1f5392645487f423 Mon Sep 17 00:00:00 2001 From: jiannanya Date: Thu, 9 Feb 2023 21:30:36 +0800 Subject: [PATCH 03/15] Fix: the member function 'Flush()' of class 'MemoryIOStream' need to be marked as override for msvc clang compiling --- include/assimp/MemoryIOWrapper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/MemoryIOWrapper.h b/include/assimp/MemoryIOWrapper.h index 720fd8424..77071e96f 100644 --- a/include/assimp/MemoryIOWrapper.h +++ b/include/assimp/MemoryIOWrapper.h @@ -125,7 +125,7 @@ public: return length; } - void Flush() { + void Flush() override{ ai_assert(false); // won't be needed } From 7b3f70a08bfd192242914e25ca9ed482552256eb Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 9 Feb 2023 21:12:21 +0100 Subject: [PATCH 04/15] Add skeleton doc --- include/assimp/mesh.h | 44 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 16cd4fa3c..fd2f3218e 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -952,17 +952,32 @@ struct aiMesh { #endif // __cplusplus }; +* + * @brief A skeleton bone represents a single bone is a skeleton structure. + * + * Skeleton-Animations can be represented via a skeleton struct, which describes + * a hierarchical tree assembled from skeleton bones. A bone is linked to a mesh. + * The bone knows its parent bone. If there is no parent bone the parent id is + * marked with -1. + * The skeleton-bone stores a pointer to its used armature. If there is no + * armature this value if set to nullptr. + * A skeleton bone stores its offset-matrix, which is the absolute transformation + * for the bone. The bone stores the locale transformation to its parent as well. + * You can compute the offset matrix by multiplying the hierarchy like: + * Tree: s1 -> s2 -> s3 + * Offset-Matrix s3 = locale-s3 * locale-s2 * locale-s1 + */ struct aiSkeletonBone { /// The parent bone index, is -1 one if this bone represents the root bone. int mParent; #ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS - /// The bone armature node - used for skeleton conversion + /// @brief The bone armature node - used for skeleton conversion /// you must enable aiProcess_PopulateArmatureData to populate this C_STRUCT aiNode *mArmature; - /// The bone node in the scene - used for skeleton conversion + /// @brief The bone node in the scene - used for skeleton conversion /// you must enable aiProcess_PopulateArmatureData to populate this C_STRUCT aiNode *mNode; @@ -993,6 +1008,7 @@ struct aiSkeletonBone { C_STRUCT aiMatrix4x4 mLocalMatrix; #ifdef __cplusplus + /// @brief The class constructor. aiSkeletonBone() : mParent(-1), #ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS @@ -1007,6 +1023,7 @@ struct aiSkeletonBone { // empty } + /// @brief The class destructor. ~aiSkeletonBone() { delete[] mWeights; mWeights = nullptr; @@ -1014,34 +1031,45 @@ struct aiSkeletonBone { #endif // __cplusplus }; /** - * @brief + * @brief A skeleton represents the bone hierarchy of an animation. + * + * Skeleton animations can be described as a tree of bones: + * root + * | + * node1 + * / \ + * node3 node4 + * If you want to calculate the transformation of node three you need to compute the + * transformation hierarchy for the transformation chain of node3: + * root->node1->node3 + * Each node is represented as a skeleton instance. */ struct aiSkeleton { /** - * + * @brief The name of the skeleton instance. */ C_STRUCT aiString mName; /** - * + * @brief The number of bones in the skeleton. */ unsigned int mNumBones; /** - * + * @brief The bone instance in the skeleton. */ C_STRUCT aiSkeletonBone **mBones; #ifdef __cplusplus /** - * + * @brief The class constructor. */ aiSkeleton() AI_NO_EXCEPT : mName(), mNumBones(0), mBones(nullptr) { // empty } /** - * + * @brief The class destructor. */ ~aiSkeleton() { delete[] mBones; From bde9a6a3c384f2c721692ba69915401e80d66ac3 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 9 Feb 2023 22:36:06 +0100 Subject: [PATCH 05/15] Update mesh.h --- include/assimp/mesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index fd2f3218e..0f2c4588e 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -952,7 +952,7 @@ struct aiMesh { #endif // __cplusplus }; -* +/** * @brief A skeleton bone represents a single bone is a skeleton structure. * * Skeleton-Animations can be represented via a skeleton struct, which describes From 156a393b84fd28fa1923bddf2655bacdcb061f56 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Fri, 10 Feb 2023 08:07:09 +0100 Subject: [PATCH 06/15] Fix a typo --- include/assimp/mesh.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 0f2c4588e..65507532c 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -631,7 +631,9 @@ struct aiMesh { */ C_STRUCT aiVector3D *mVertices; - /** Vertex normals. + /** + * @brief Vertex normals. + * * The array contains normalized vectors, nullptr if not present. * The array is mNumVertices in size. Normals are undefined for * point and line primitives. A mesh consisting of points and @@ -770,7 +772,7 @@ struct aiMesh { #ifdef __cplusplus - //! Default constructor. Initializes all members to 0 + //! The default class constructor. aiMesh() AI_NO_EXCEPT : mPrimitiveTypes(0), mNumVertices(0), @@ -953,7 +955,7 @@ struct aiMesh { }; /** - * @brief A skeleton bone represents a single bone is a skeleton structure. + * @brief A skeleton bone represents a single bone in a aiSkeleton instance. * * Skeleton-Animations can be represented via a skeleton struct, which describes * a hierarchical tree assembled from skeleton bones. A bone is linked to a mesh. From 4c723a4ec862b2c500a82c5ca8b7dbfadd8cf451 Mon Sep 17 00:00:00 2001 From: Shammel Lee Date: Tue, 14 Feb 2023 20:21:33 -0500 Subject: [PATCH 07/15] Fix PyAssimp README typo --- port/PyAssimp/README.md | 2 +- port/PyAssimp/README.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index c9944f717..900003be4 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -76,7 +76,7 @@ $ python setup.py install ``` PyAssimp requires a assimp dynamic library (`DLL` on windows, -`.so` on linux, `.dynlib` on macOS) in order to work. The default search directories are: +`.so` on linux, `.dylib` on macOS) in order to work. The default search directories are: - the current directory - on linux additionally: `/usr/lib`, `/usr/local/lib`, `/usr/lib/x86_64-linux-gnu` diff --git a/port/PyAssimp/README.rst b/port/PyAssimp/README.rst index 03b7968f1..45624145f 100644 --- a/port/PyAssimp/README.rst +++ b/port/PyAssimp/README.rst @@ -81,7 +81,7 @@ Install ``pyassimp`` by running: $ python setup.py install PyAssimp requires a assimp dynamic library (``DLL`` on windows, ``.so`` -on linux, ``.dynlib`` on macOS) in order to work. The default search +on linux, ``.dylib`` on macOS) in order to work. The default search directories are: - the current directory From 9898138516083380e16b7f19c28bac9d0fd7fe58 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Wed, 15 Feb 2023 21:02:03 +0100 Subject: [PATCH 08/15] Update mesh.h --- include/assimp/mesh.h | 527 ++++++++++++++++++++++++------------------ 1 file changed, 304 insertions(+), 223 deletions(-) diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 65507532c..878620e4c 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2022, assimp team +Copyright (c) 2006-2023, assimp team All rights reserved. @@ -111,7 +111,8 @@ extern "C" { #endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS // --------------------------------------------------------------------------- -/** @brief A single face in a mesh, referring to multiple vertices. +/** + * @brief A single face in a mesh, referring to multiple vertices. * * If mNumIndices is 3, we call the face 'triangle', for mNumIndices > 3 * it's called 'polygon' (hey, that's just a definition!). @@ -142,25 +143,25 @@ struct aiFace { #ifdef __cplusplus - //! Default constructor + //! @brief Default constructor. aiFace() AI_NO_EXCEPT : mNumIndices(0), mIndices(nullptr) { // empty } - //! Default destructor. Delete the index array + //! @brief Default destructor. Delete the index array ~aiFace() { delete[] mIndices; } - //! Copy constructor. Copy the index array + //! @brief Copy constructor. Copy the index array aiFace(const aiFace &o) : mNumIndices(0), mIndices(nullptr) { *this = o; } - //! Assignment operator. Copy the index array + //! @brief Assignment operator. Copy the index array aiFace &operator=(const aiFace &o) { if (&o == this) { return *this; @@ -178,8 +179,7 @@ struct aiFace { return *this; } - //! Comparison operator. Checks whether the index array - //! of two faces is identical + //! @brief Comparison operator. Checks whether the index array of two faces is identical. bool operator==(const aiFace &o) const { if (mIndices == o.mIndices) { return true; @@ -202,7 +202,7 @@ struct aiFace { return true; } - //! Inverse comparison operator. Checks whether the index + //! @brief Inverse comparison operator. Checks whether the index //! array of two faces is NOT identical bool operator!=(const aiFace &o) const { return !(*this == o); @@ -223,14 +223,14 @@ struct aiVertexWeight { #ifdef __cplusplus - //! Default constructor + //! @brief Default constructor aiVertexWeight() AI_NO_EXCEPT : mVertexId(0), mWeight(0.0f) { // empty } - //! Initialization from a given index and vertex weight factor + //! @brief Initialization from a given index and vertex weight factor //! \param pID ID //! \param pWeight Vertex weight factor aiVertexWeight(unsigned int pID, float pWeight) : @@ -261,27 +261,38 @@ struct aiNode; * position of the bone at the time of binding. */ struct aiBone { - //! The name of the bone. + /** + * The name of the bone. + */ C_STRUCT aiString mName; - //! The number of vertices affected by this bone. - //! The maximum value for this member is #AI_MAX_BONE_WEIGHTS. + /** + * The number of vertices affected by this bone. + * The maximum value for this member is #AI_MAX_BONE_WEIGHTS. + */ unsigned int mNumWeights; #ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS - /// The bone armature node - used for skeleton conversion - /// you must enable aiProcess_PopulateArmatureData to populate this + /** + * The bone armature node - used for skeleton conversion + * you must enable aiProcess_PopulateArmatureData to populate this + */ C_STRUCT aiNode *mArmature; - /// The bone node in the scene - used for skeleton conversion - /// you must enable aiProcess_PopulateArmatureData to populate this + /** + * The bone node in the scene - used for skeleton conversion + * you must enable aiProcess_PopulateArmatureData to populate this + */ C_STRUCT aiNode *mNode; #endif - //! The influence weights of this bone, by vertex index. + /** + * The influence weights of this bone, by vertex index. + */ C_STRUCT aiVertexWeight *mWeights; - /** Matrix that transforms from mesh space to bone space in bind pose. + /** + * Matrix that transforms from mesh space to bone space in bind pose. * * This matrix describes the position of the mesh * in the local space of this bone when the skeleton was bound. @@ -338,7 +349,7 @@ struct aiBone { ::memcpy(mWeights, other.mWeights, mNumWeights * sizeof(aiVertexWeight)); } - //! Assignment operator + //! @brief Assignment operator aiBone &operator = (const aiBone &other) { if (this == &other) { return *this; @@ -352,6 +363,7 @@ struct aiBone { return *this; } + /// @brief Compare operator. bool operator==(const aiBone &rhs) const { if (mName != rhs.mName || mNumWeights != rhs.mNumWeights ) { return false; @@ -365,7 +377,7 @@ struct aiBone { return true; } - //! Destructor - deletes the array of vertex weights + //! @brief Destructor - deletes the array of vertex weights ~aiBone() { delete[] mWeights; } @@ -381,27 +393,31 @@ struct aiBone { * @see AI_CONFIG_PP_SBP_REMOVE Removal of specific primitive types. */ enum aiPrimitiveType { - /** A point primitive. + /** + * @brief A point primitive. * * This is just a single vertex in the virtual world, * #aiFace contains just one index for such a primitive. */ aiPrimitiveType_POINT = 0x1, - /** A line primitive. + /** + * @brief A line primitive. * * This is a line defined through a start and an end position. * #aiFace contains exactly two indices for such a primitive. */ aiPrimitiveType_LINE = 0x2, - /** A triangular primitive. + /** + * @brief A triangular primitive. * * A triangle consists of three indices. */ aiPrimitiveType_TRIANGLE = 0x4, - /** A higher-level polygon with more than 3 edges. + /** + * @brief A higher-level polygon with more than 3 edges. * * A triangle is a polygon, but polygon in this context means * "all polygons that are not triangles". The "Triangulate"-Step @@ -411,7 +427,7 @@ enum aiPrimitiveType { aiPrimitiveType_POLYGON = 0x8, /** - * A flag to determine whether this triangles only mesh is NGON encoded. + * @brief A flag to determine whether this triangles only mesh is NGON encoded. * * NGON encoding is a special encoding that tells whether 2 or more consecutive triangles * should be considered as a triangle fan. This is identified by looking at the first vertex index. @@ -428,8 +444,9 @@ enum aiPrimitiveType { */ aiPrimitiveType_NGONEncodingFlag = 0x10, -/** This value is not used. It is just here to force the - * compiler to map this enum to a 32 Bit integer. + /** + * This value is not used. It is just here to force the + * compiler to map this enum to a 32 Bit integer. */ #ifndef SWIG _aiPrimitiveType_Force32Bit = INT_MAX @@ -494,25 +511,20 @@ struct aiAnimMesh { float mWeight; #ifdef __cplusplus - - aiAnimMesh() AI_NO_EXCEPT - : mVertices(nullptr), - mNormals(nullptr), - mTangents(nullptr), - mBitangents(nullptr), - mColors(), - mTextureCoords(), - mNumVertices(0), - mWeight(0.0f) { - // fixme consider moving this to the ctor initializer list as well - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) { - mTextureCoords[a] = nullptr; - } - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) { - mColors[a] = nullptr; - } + /// @brief The class constructor. + aiAnimMesh() AI_NO_EXCEPT : + mVertices(nullptr), + mNormals(nullptr), + mTangents(nullptr), + mBitangents(nullptr), + mColors {nullptr}, + mTextureCoords{nullptr}, + mNumVertices(0), + mWeight(0.0f) { + // empty } + /// @brief The class destructor. ~aiAnimMesh() { delete[] mVertices; delete[] mNormals; @@ -526,35 +538,51 @@ struct aiAnimMesh { } } - /** Check whether the anim mesh overrides the vertex positions - * of its host mesh*/ + /** + * @brief Check whether the anim-mesh overrides the vertex positions + * of its host mesh. + * @return true if positions are stored, false if not. + */ bool HasPositions() const { return mVertices != nullptr; } - /** Check whether the anim mesh overrides the vertex normals - * of its host mesh*/ + /** + * @brief Check whether the anim-mesh overrides the vertex normals + * of its host mesh + * @return true if normals are stored, false if not. + */ bool HasNormals() const { return mNormals != nullptr; } - /** Check whether the anim mesh overrides the vertex tangents - * and bitangents of its host mesh. As for aiMesh, - * tangents and bitangents always go together. */ + /** + * @brief Check whether the anim-mesh overrides the vertex tangents + * and bitangents of its host mesh. As for aiMesh, + * tangents and bitangents always go together. + * @return true if tangents and bi-tangents are stored, false if not. + */ bool HasTangentsAndBitangents() const { return mTangents != nullptr; } - /** Check whether the anim mesh overrides a particular - * set of vertex colors on his host mesh. - * @param pIndex 0= AI_MAX_NUMBER_OF_COLOR_SETS ? false : mColors[pIndex] != nullptr; } - /** Check whether the anim mesh overrides a particular - * set of texture coordinates on his host mesh. - * @param pIndex 0= AI_MAX_NUMBER_OF_TEXTURECOORDS ? false : mTextureCoords[pIndex] != nullptr; } @@ -588,145 +616,167 @@ enum aiMorphingMethod { // --------------------------------------------------------------------------- /** @brief A mesh represents a geometry or model with a single material. -* -* It usually consists of a number of vertices and a series of primitives/faces -* referencing the vertices. In addition there might be a series of bones, each -* of them addressing a number of vertices with a certain weight. Vertex data -* is presented in channels with each channel containing a single per-vertex -* information such as a set of texture coordinates or a normal vector. -* If a data pointer is non-null, the corresponding data stream is present. -* From C++-programs you can also use the comfort functions Has*() to -* test for the presence of various data streams. -* -* A Mesh uses only a single material which is referenced by a material ID. -* @note The mPositions member is usually not optional. However, vertex positions -* *could* be missing if the #AI_SCENE_FLAGS_INCOMPLETE flag is set in -* @code -* aiScene::mFlags -* @endcode -*/ + * + * It usually consists of a number of vertices and a series of primitives/faces + * referencing the vertices. In addition there might be a series of bones, each + * of them addressing a number of vertices with a certain weight. Vertex data + * is presented in channels with each channel containing a single per-vertex + * information such as a set of texture coordinates or a normal vector. + * If a data pointer is non-null, the corresponding data stream is present. + * From C++-programs you can also use the comfort functions Has*() to + * test for the presence of various data streams. + * + * A Mesh uses only a single material which is referenced by a material ID. + * @note The mPositions member is usually not optional. However, vertex positions + * *could* be missing if the #AI_SCENE_FLAGS_INCOMPLETE flag is set in + * @code + * aiScene::mFlags + * @endcode + */ struct aiMesh { - /** Bitwise combination of the members of the #aiPrimitiveType enum. + /** + * Bitwise combination of the members of the #aiPrimitiveType enum. * This specifies which types of primitives are present in the mesh. * The "SortByPrimitiveType"-Step can be used to make sure the * output meshes consist of one primitive type each. */ unsigned int mPrimitiveTypes; - /** The number of vertices in this mesh. - * This is also the size of all of the per-vertex data arrays. - * The maximum value for this member is #AI_MAX_VERTICES. - */ + /** + * The number of vertices in this mesh. + * This is also the size of all of the per-vertex data arrays. + * The maximum value for this member is #AI_MAX_VERTICES. + */ unsigned int mNumVertices; - /** The number of primitives (triangles, polygons, lines) in this mesh. - * This is also the size of the mFaces array. - * The maximum value for this member is #AI_MAX_FACES. - */ + /** + * The number of primitives (triangles, polygons, lines) in this mesh. + * This is also the size of the mFaces array. + * The maximum value for this member is #AI_MAX_FACES. + */ unsigned int mNumFaces; - /** Vertex positions. - * This array is always present in a mesh. The array is - * mNumVertices in size. - */ + /** + * @brief Vertex positions. + * + * This array is always present in a mesh. The array is + * mNumVertices in size. + */ C_STRUCT aiVector3D *mVertices; - /** - * @brief Vertex normals. - * - * The array contains normalized vectors, nullptr if not present. - * The array is mNumVertices in size. Normals are undefined for - * point and line primitives. A mesh consisting of points and - * lines only may not have normal vectors. Meshes with mixed - * primitive types (i.e. lines and triangles) may have normals, - * but the normals for vertices that are only referenced by - * point or line primitives are undefined and set to QNaN (WARN: - * qNaN compares to inequal to *everything*, even to qNaN itself. - * Using code like this to check whether a field is qnan is: - * @code - * #define IS_QNAN(f) (f != f) - * @endcode - * still dangerous because even 1.f == 1.f could evaluate to false! ( - * remember the subtleties of IEEE754 artithmetics). Use stuff like - * @c fpclassify instead. - * @note Normal vectors computed by Assimp are always unit-length. - * However, this needn't apply for normals that have been taken - * directly from the model file. - */ + /** + * @brief Vertex normals. + * + * The array contains normalized vectors, nullptr if not present. + * The array is mNumVertices in size. Normals are undefined for + * point and line primitives. A mesh consisting of points and + * lines only may not have normal vectors. Meshes with mixed + * primitive types (i.e. lines and triangles) may have normals, + * but the normals for vertices that are only referenced by + * point or line primitives are undefined and set to QNaN (WARN: + * qNaN compares to inequal to *everything*, even to qNaN itself. + * Using code like this to check whether a field is qnan is: + * @code + * #define IS_QNAN(f) (f != f) + * @endcode + * still dangerous because even 1.f == 1.f could evaluate to false! ( + * remember the subtleties of IEEE754 artithmetics). Use stuff like + * @c fpclassify instead. + * @note Normal vectors computed by Assimp are always unit-length. + * However, this needn't apply for normals that have been taken + * directly from the model file. + */ C_STRUCT aiVector3D *mNormals; - /** Vertex tangents. - * The tangent of a vertex points in the direction of the positive - * X texture axis. The array contains normalized vectors, nullptr if - * not present. The array is mNumVertices in size. A mesh consisting - * of points and lines only may not have normal vectors. Meshes with - * mixed primitive types (i.e. lines and triangles) may have - * normals, but the normals for vertices that are only referenced by - * point or line primitives are undefined and set to qNaN. See - * the #mNormals member for a detailed discussion of qNaNs. - * @note If the mesh contains tangents, it automatically also - * contains bitangents. - */ + /** + * @brief Vertex tangents. + * + * The tangent of a vertex points in the direction of the positive + * X texture axis. The array contains normalized vectors, nullptr if + * not present. The array is mNumVertices in size. A mesh consisting + * of points and lines only may not have normal vectors. Meshes with + * mixed primitive types (i.e. lines and triangles) may have + * normals, but the normals for vertices that are only referenced by + * point or line primitives are undefined and set to qNaN. See + * the #mNormals member for a detailed discussion of qNaNs. + * @note If the mesh contains tangents, it automatically also + * contains bitangents. + */ C_STRUCT aiVector3D *mTangents; - /** Vertex bitangents. - * The bitangent of a vertex points in the direction of the positive - * Y texture axis. The array contains normalized vectors, nullptr if not - * present. The array is mNumVertices in size. - * @note If the mesh contains tangents, it automatically also contains - * bitangents. - */ + /** + * @brief Vertex bitangents. + * + * The bitangent of a vertex points in the direction of the positive + * Y texture axis. The array contains normalized vectors, nullptr if not + * present. The array is mNumVertices in size. + * @note If the mesh contains tangents, it automatically also contains + * bitangents. + */ C_STRUCT aiVector3D *mBitangents; - /** Vertex color sets. - * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex - * colors per vertex. nullptr if not present. Each array is - * mNumVertices in size if present. - */ + /** + * @brief Vertex color sets. + * + * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex + * colors per vertex. nullptr if not present. Each array is + * mNumVertices in size if present. + */ C_STRUCT aiColor4D *mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; - /** Vertex texture coordinates, also known as UV channels. - * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per - * vertex. nullptr if not present. The array is mNumVertices in size. - */ + /** + * @brief Vertex texture coordinates, also known as UV channels. + * + * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per + * vertex. nullptr if not present. The array is mNumVertices in size. + */ C_STRUCT aiVector3D *mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - /** Specifies the number of components for a given UV channel. - * Up to three channels are supported (UVW, for accessing volume - * or cube maps). If the value is 2 for a given channel n, the - * component p.z of mTextureCoords[n][p] is set to 0.0f. - * If the value is 1 for a given channel, p.y is set to 0.0f, too. - * @note 4D coordinates are not supported - */ + /** + * @brief Specifies the number of components for a given UV channel. + * + * Up to three channels are supported (UVW, for accessing volume + * or cube maps). If the value is 2 for a given channel n, the + * component p.z of mTextureCoords[n][p] is set to 0.0f. + * If the value is 1 for a given channel, p.y is set to 0.0f, too. + * @note 4D coordinates are not supported + */ unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - /** The faces the mesh is constructed from. - * Each face refers to a number of vertices by their indices. - * This array is always present in a mesh, its size is given - * in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT - * is NOT set each face references an unique set of vertices. - */ + /** + * @brief The faces the mesh is constructed from. + * + * Each face refers to a number of vertices by their indices. + * This array is always present in a mesh, its size is given + * in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT + * is NOT set each face references an unique set of vertices. + */ C_STRUCT aiFace *mFaces; - /** The number of bones this mesh contains. - * Can be 0, in which case the mBones array is nullptr. + /** + * The number of bones this mesh contains. Can be 0, in which case the mBones array is nullptr. */ unsigned int mNumBones; - /** The bones of this mesh. - * A bone consists of a name by which it can be found in the - * frame hierarchy and a set of vertex weights. - */ + /** + * @brief The bones of this mesh. + * + * A bone consists of a name by which it can be found in the + * frame hierarchy and a set of vertex weights. + */ C_STRUCT aiBone **mBones; - /** The material used by this mesh. + /** + * @brief The material used by this mesh. + * * A mesh uses only a single material. If an imported model uses * multiple materials, the import splits up the mesh. Use this value * as index into the scene's material list. */ unsigned int mMaterialIndex; - /** Name of the mesh. Meshes can be named, but this is not a + /** + * Name of the mesh. Meshes can be named, but this is not a * requirement and leaving this field empty is totally fine. * There are mainly three uses for mesh names: * - some formats name nodes and meshes independently. @@ -736,22 +786,24 @@ struct aiMesh { * aids the caller at recovering the original mesh * partitioning. * - Vertex animations refer to meshes by their names. - **/ + */ C_STRUCT aiString mName; - /** The number of attachment meshes. - * Currently known to work with loaders: - * - Collada - * - gltf + /** + * The number of attachment meshes. + * Currently known to work with loaders: + * - Collada + * - gltf */ unsigned int mNumAnimMeshes; - /** Attachment meshes for this mesh, for vertex-based animation. - * Attachment meshes carry replacement data for some of the - * mesh'es vertex components (usually positions, normals). - * Currently known to work with loaders: - * - Collada - * - gltf + /** + * Attachment meshes for this mesh, for vertex-based animation. + * Attachment meshes carry replacement data for some of the + * mesh'es vertex components (usually positions, normals). + * Currently known to work with loaders: + * - Collada + * - gltf */ C_STRUCT aiAnimMesh **mAnimMeshes; @@ -766,7 +818,8 @@ struct aiMesh { */ C_STRUCT aiAABB mAABB; - /** Vertex UV stream names. Pointer to array of size AI_MAX_NUMBER_OF_TEXTURECOORDS + /** + * Vertex UV stream names. Pointer to array of size AI_MAX_NUMBER_OF_TEXTURECOORDS */ C_STRUCT aiString **mTextureCoordsNames; @@ -781,9 +834,9 @@ struct aiMesh { mNormals(nullptr), mTangents(nullptr), mBitangents(nullptr), - mColors(), - mTextureCoords(), - mNumUVComponents(), + mColors{nullptr}, + mTextureCoords{nullptr}, + mNumUVComponents{0}, mFaces(nullptr), mNumBones(0), mBones(nullptr), @@ -793,17 +846,10 @@ struct aiMesh { mMethod(aiMorphingMethod_UNKNOWN), mAABB(), mTextureCoordsNames(nullptr) { - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { - mNumUVComponents[a] = 0; - mTextureCoords[a] = nullptr; - } - - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) { - mColors[a] = nullptr; - } + // empty } - //! Deletes all storage allocated for the mesh + //! @brief The class destructor. ~aiMesh() { delete[] mVertices; delete[] mNormals; @@ -844,44 +890,58 @@ struct aiMesh { delete[] mFaces; } - //! Check whether the mesh contains positions. Provided no special - //! scene flags are set, this will always be true - bool HasPositions() const { return mVertices != nullptr && mNumVertices > 0; } + //! @brief Check whether the mesh contains positions. Provided no special + //! scene flags are set, this will always be true + //! @return true, if positions are stored, false if not. + bool HasPositions() const { + return mVertices != nullptr && mNumVertices > 0; + } - //! Check whether the mesh contains faces. If no special scene flags - //! are set this should always return true - bool HasFaces() const { return mFaces != nullptr && mNumFaces > 0; } + //! @brief Check whether the mesh contains faces. If no special scene flags + //! are set this should always return true + //! @return true, if faces are stored, false if not. + bool HasFaces() const { + return mFaces != nullptr && mNumFaces > 0; + } - //! Check whether the mesh contains normal vectors - bool HasNormals() const { return mNormals != nullptr && mNumVertices > 0; } + //! @brief Check whether the mesh contains normal vectors + //! @return true, if normals are stored, false if not. + bool HasNormals() const { + return mNormals != nullptr && mNumVertices > 0; + } - //! Check whether the mesh contains tangent and bitangent vectors + //! @brief Check whether the mesh contains tangent and bitangent vectors. + //! //! It is not possible that it contains tangents and no bitangents //! (or the other way round). The existence of one of them //! implies that the second is there, too. - bool HasTangentsAndBitangents() const { return mTangents != nullptr && mBitangents != nullptr && mNumVertices > 0; } - - //! Check whether the mesh contains a vertex color set - //! \param pIndex Index of the vertex color set - bool HasVertexColors(unsigned int pIndex) const { - if (pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS) { - return false; - } else { - return mColors[pIndex] != nullptr && mNumVertices > 0; - } + //! @return true, if tangents and bi-tangents are stored, false if not. + bool HasTangentsAndBitangents() const { + return mTangents != nullptr && mBitangents != nullptr && mNumVertices > 0; } - //! Check whether the mesh contains a texture coordinate set - //! \param pIndex Index of the texture coordinates set - bool HasTextureCoords(unsigned int pIndex) const { - if (pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { + //! @brief Check whether the mesh contains a vertex color set + //! @param index Index of the vertex color set + //! @return true, if vertex colors are stored, false if not. + bool HasVertexColors(unsigned int index) const { + if (index >= AI_MAX_NUMBER_OF_COLOR_SETS) { return false; - } else { - return mTextureCoords[pIndex] != nullptr && mNumVertices > 0; } + return mColors[index] != nullptr && mNumVertices > 0; } - //! Get the number of UV channels the mesh contains + //! @brief Check whether the mesh contains a texture coordinate set + //! @param index Index of the texture coordinates set + //! @return true, if texture coordinates are stored, false if not. + bool HasTextureCoords(unsigned int index) const { + if (index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { + return false; + } + return (mTextureCoords[index] != nullptr && mNumVertices > 0); + } + + //! @brief Get the number of UV channels the mesh contains. + //! @return the number of stored uv-channels. unsigned int GetNumUVChannels() const { unsigned int n(0); while (n < AI_MAX_NUMBER_OF_TEXTURECOORDS && mTextureCoords[n]) { @@ -891,7 +951,8 @@ struct aiMesh { return n; } - //! Get the number of vertex color channels the mesh contains + //! @brief Get the number of vertex color channels the mesh contains. + //! @return The number of stored color channels. unsigned int GetNumColorChannels() const { unsigned int n(0); while (n < AI_MAX_NUMBER_OF_COLOR_SETS && mColors[n]) { @@ -900,13 +961,15 @@ struct aiMesh { return n; } - //! Check whether the mesh contains bones + //! @brief Check whether the mesh contains bones. + //! @return true, if bones are stored. bool HasBones() const { return mBones != nullptr && mNumBones > 0; } - //! Check whether the mesh contains a texture coordinate set name - //! \param pIndex Index of the texture coordinates set + //! @brief Check whether the mesh contains a texture coordinate set name + //! @param pIndex Index of the texture coordinates set + //! @return true, if texture coordinates for the index exists. bool HasTextureCoordsName(unsigned int pIndex) const { if (mTextureCoordsNames == nullptr || pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { return false; @@ -914,9 +977,9 @@ struct aiMesh { return mTextureCoordsNames[pIndex] != nullptr; } - //! Set a texture coordinate set name - //! \param pIndex Index of the texture coordinates set - //! \param texCoordsName name of the texture coordinate set + //! @brief Set a texture coordinate set name + //! @param pIndex Index of the texture coordinates set + //! @param texCoordsName name of the texture coordinate set void SetTextureCoordsName(unsigned int pIndex, const aiString &texCoordsName) { if (pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { return; @@ -941,21 +1004,22 @@ struct aiMesh { *mTextureCoordsNames[pIndex] = texCoordsName; } - //! Get a texture coordinate set name - //! \param pIndex Index of the texture coordinates set - const aiString *GetTextureCoordsName(unsigned int pIndex) const { - if (mTextureCoordsNames == nullptr || pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { + //! @brief Get a texture coordinate set name + //! @param pIndex Index of the texture coordinates set + //! @return The texture coordinate name. + const aiString *GetTextureCoordsName(unsigned int index) const { + if (mTextureCoordsNames == nullptr || index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { return nullptr; } - return mTextureCoordsNames[pIndex]; + return mTextureCoordsNames[index]; } #endif // __cplusplus }; /** - * @brief A skeleton bone represents a single bone in a aiSkeleton instance. + * @brief A skeleton bone represents a single bone is a skeleton structure. * * Skeleton-Animations can be represented via a skeleton struct, which describes * a hierarchical tree assembled from skeleton bones. A bone is linked to a mesh. @@ -1025,6 +1089,21 @@ struct aiSkeletonBone { // empty } + /// @brief The class constructor with its parent + /// @param parent The parent node index. + aiSkeletonBone(unsigned int parent) : + mParent(parent), +#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS + mArmature(nullptr), + mNode(nullptr), +#endif + mNumnWeights(0), + mMeshId(nullptr), + mWeights(nullptr), + mOffsetMatrix(), + mLocalMatrix() { + // empty + } /// @brief The class destructor. ~aiSkeletonBone() { delete[] mWeights; @@ -1081,4 +1160,6 @@ struct aiSkeleton { #ifdef __cplusplus } #endif //! extern "C" + #endif // AI_MESH_H_INC + From e4386d3013ab9d3a9b33988918aa74e5c5efe2a0 Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Thu, 16 Feb 2023 15:16:54 -0800 Subject: [PATCH 09/15] Fix implicit conversion errors on macOS --- code/AssetLib/MDL/MDLLoader.cpp | 2 +- code/AssetLib/SMD/SMDLoader.cpp | 2 +- code/AssetLib/glTF2/glTF2AssetWriter.inl | 4 ++-- contrib/zip/src/miniz.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/AssetLib/MDL/MDLLoader.cpp b/code/AssetLib/MDL/MDLLoader.cpp index b60657805..d862ccaf4 100644 --- a/code/AssetLib/MDL/MDLLoader.cpp +++ b/code/AssetLib/MDL/MDLLoader.cpp @@ -975,7 +975,7 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones) } // store the name of the bone - pcOutBone->mName.length = (size_t)iMaxLen; + pcOutBone->mName.length = (ai_uint32)iMaxLen; ::memcpy(pcOutBone->mName.data, pcBone->name, pcOutBone->mName.length); pcOutBone->mName.data[pcOutBone->mName.length] = '\0'; } diff --git a/code/AssetLib/SMD/SMDLoader.cpp b/code/AssetLib/SMD/SMDLoader.cpp index dd1f56dc3..bb26eb88c 100644 --- a/code/AssetLib/SMD/SMDLoader.cpp +++ b/code/AssetLib/SMD/SMDLoader.cpp @@ -590,7 +590,7 @@ void SMDImporter::CreateOutputMaterials() { pScene->mMaterials[iMat] = pcMat; aiString szName; - szName.length = (size_t)ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat); + szName.length = (ai_uint32)ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat); pcMat->AddProperty(&szName,AI_MATKEY_NAME); if (aszTextures[iMat].length()) diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 868d9cbdf..6bec0fb55 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -836,7 +836,7 @@ namespace glTF2 { throw DeadlyExportError("Failed to write scene data!"); } - uint32_t jsonChunkLength = (docBuffer.GetSize() + 3) & ~3; // Round up to next multiple of 4 + uint32_t jsonChunkLength = (uint32_t)((docBuffer.GetSize() + 3) & ~3); // Round up to next multiple of 4 auto paddingLength = jsonChunkLength - docBuffer.GetSize(); GLB_Chunk jsonChunk; @@ -862,7 +862,7 @@ namespace glTF2 { int GLB_Chunk_count = 1; uint32_t binaryChunkLength = 0; if (bodyBuffer->byteLength > 0) { - binaryChunkLength = (bodyBuffer->byteLength + 3) & ~3; // Round up to next multiple of 4 + binaryChunkLength = (uint32_t)((bodyBuffer->byteLength + 3) & ~3); // Round up to next multiple of 4 auto curPaddingLength = binaryChunkLength - bodyBuffer->byteLength; ++GLB_Chunk_count; diff --git a/contrib/zip/src/miniz.h b/contrib/zip/src/miniz.h index 0a5560b24..7a6ff8d1a 100644 --- a/contrib/zip/src/miniz.h +++ b/contrib/zip/src/miniz.h @@ -6092,8 +6092,8 @@ mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) { if (!pZip->m_file_offset_alignment) return 0; n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); - return (pZip->m_file_offset_alignment - n) & - (pZip->m_file_offset_alignment - 1); + return (mz_uint)((pZip->m_file_offset_alignment - n) & + (pZip->m_file_offset_alignment - 1)); } static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, From 53e5f19b14acb4f0dd4c123f607b256e51923f4a Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Fri, 17 Feb 2023 11:20:00 -0800 Subject: [PATCH 10/15] Use C++ style casts --- code/AssetLib/MDL/MDLLoader.cpp | 2 +- code/AssetLib/SMD/SMDLoader.cpp | 2 +- code/AssetLib/glTF2/glTF2AssetWriter.inl | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/AssetLib/MDL/MDLLoader.cpp b/code/AssetLib/MDL/MDLLoader.cpp index d862ccaf4..76b61cda5 100644 --- a/code/AssetLib/MDL/MDLLoader.cpp +++ b/code/AssetLib/MDL/MDLLoader.cpp @@ -975,7 +975,7 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones) } // store the name of the bone - pcOutBone->mName.length = (ai_uint32)iMaxLen; + pcOutBone->mName.length = static_cast(iMaxLen); ::memcpy(pcOutBone->mName.data, pcBone->name, pcOutBone->mName.length); pcOutBone->mName.data[pcOutBone->mName.length] = '\0'; } diff --git a/code/AssetLib/SMD/SMDLoader.cpp b/code/AssetLib/SMD/SMDLoader.cpp index bb26eb88c..1c73c7e66 100644 --- a/code/AssetLib/SMD/SMDLoader.cpp +++ b/code/AssetLib/SMD/SMDLoader.cpp @@ -590,7 +590,7 @@ void SMDImporter::CreateOutputMaterials() { pScene->mMaterials[iMat] = pcMat; aiString szName; - szName.length = (ai_uint32)ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat); + szName.length = static_cast(ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat)); pcMat->AddProperty(&szName,AI_MATKEY_NAME); if (aszTextures[iMat].length()) diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 6bec0fb55..6f6eda502 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -836,7 +836,7 @@ namespace glTF2 { throw DeadlyExportError("Failed to write scene data!"); } - uint32_t jsonChunkLength = (uint32_t)((docBuffer.GetSize() + 3) & ~3); // Round up to next multiple of 4 + uint32_t jsonChunkLength = static_cast((docBuffer.GetSize() + 3) & ~3); // Round up to next multiple of 4 auto paddingLength = jsonChunkLength - docBuffer.GetSize(); GLB_Chunk jsonChunk; @@ -862,7 +862,7 @@ namespace glTF2 { int GLB_Chunk_count = 1; uint32_t binaryChunkLength = 0; if (bodyBuffer->byteLength > 0) { - binaryChunkLength = (uint32_t)((bodyBuffer->byteLength + 3) & ~3); // Round up to next multiple of 4 + binaryChunkLength = static_cast((bodyBuffer->byteLength + 3) & ~3); // Round up to next multiple of 4 auto curPaddingLength = binaryChunkLength - bodyBuffer->byteLength; ++GLB_Chunk_count; From 3ad67771fe036c0027c5512d58c02a7c179b9941 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 18 Feb 2023 17:09:14 +0100 Subject: [PATCH 11/15] Add missing pod types. --- CMakeLists.txt | 16 ++++++++++++---- include/assimp/metadata.h | 38 +++++++++++++++++++++++++++++++++++++- test/unit/utMetadata.cpp | 36 ++++++++++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e859986b7..0f0e5a793 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,10 +84,6 @@ OPTION( ASSIMP_NO_EXPORT "Disable Assimp's export functionality." OFF ) -OPTION( ASSIMP_BUILD_ZLIB - "Build your own zlib" - OFF -) OPTION( ASSIMP_BUILD_ASSIMP_TOOLS "If the supplementary tools for Assimp are built in addition to the library." OFF @@ -134,6 +130,18 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH OFF ) +IF (WIN32) + OPTION( ASSIMP_BUILD_ZLIB + "Build your own zlib" + ON + ) +ELSE() + OPTION( ASSIMP_BUILD_ZLIB + "Build your own zlib" + OFF + ) +ENDIF() + IF (WIN32) # Use subset of Windows.h ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN ) diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index d2ec837e9..c766d0ae2 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -56,6 +56,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #endif +#include + // ------------------------------------------------------------------------------- /** * Enum used to distinguish data types @@ -70,7 +72,9 @@ typedef enum aiMetadataType { AI_AISTRING = 5, AI_AIVECTOR3D = 6, AI_AIMETADATA = 7, - AI_META_MAX = 8, + AI_INT64 = 8, + AI_UINT32 = 9, + AI_META_MAX = 10, #ifndef SWIG FORCE_32BIT = INT_MAX @@ -133,6 +137,12 @@ inline aiMetadataType GetAiType(const aiVector3D &) { inline aiMetadataType GetAiType(const aiMetadata &) { return AI_AIMETADATA; } +inline aiMetadataType GetAiType(int64_t) { + return AI_INT64; +} +inline aiMetadataType GetAiType(uint32_t) { + return AI_UINT32; +} #endif // __cplusplus @@ -215,6 +225,16 @@ struct aiMetadata { rhs.Get(static_cast(i), v); mValues[i].mData = new aiMetadata(v); } break; + case AI_INT64: { + int64_t v; + ::memcpy(&v, rhs.mValues[i].mData, sizeof(int64_t)); + mValues[i].mData = new int64_t(v); + } break; + case AI_UINT32: { + uint32_t v; + ::memcpy(&v, rhs.mValues[i].mData, sizeof(uint32_t)); + mValues[i].mData = new uint32_t(v); + } break; #ifndef SWIG case FORCE_32BIT: #endif @@ -267,6 +287,12 @@ struct aiMetadata { case AI_AIMETADATA: delete static_cast(data); break; + case AI_INT64: + delete static_cast(data); + break; + case AI_UINT32: + delete static_cast(data); + break; #ifndef SWIG case FORCE_32BIT: #endif @@ -510,6 +536,16 @@ struct aiMetadata { return false; } } break; + case AI_INT64: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; + case AI_UINT32: { + if (*static_cast(lhs.mValues[i].mData) != *static_cast(rhs.mValues[i].mData)) { + return false; + } + } break; #ifndef SWIG case FORCE_32BIT: #endif diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index 514b1a4a4..676404c3c 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -5,8 +5,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -84,7 +82,7 @@ TEST_F( utMetadata, allocTest ) { } TEST_F( utMetadata, get_set_pod_Test ) { - m_data = aiMetadata::Alloc( 5 ); + m_data = aiMetadata::Alloc( 7 ); // int, 32 bit unsigned int index( 0 ); @@ -137,6 +135,28 @@ TEST_F( utMetadata, get_set_pod_Test ) { EXPECT_TRUE( success ); EXPECT_DOUBLE_EQ( 3.0, result_double ); + // int64_t + index++; + const std::string key_int64 = "test_int64"; + int64_t val_int64 = 64; + success = m_data->Set(index, key_int64, val_int64); + EXPECT_TRUE(success); + int64_t result_int64(0); + success = m_data->Get(key_int64, result_int64); + EXPECT_TRUE(success); + EXPECT_EQ(result_int64, val_int64); + + // uint32 + index++; + const std::string key_uint32 = "test_uint32"; + int64_t val_uint32 = 32; + success = m_data->Set(index, key_uint32, val_uint32); + EXPECT_TRUE(success); + int64_t result_uint32(0); + success = m_data->Get(key_uint32, result_uint32); + EXPECT_TRUE(success); + EXPECT_EQ(result_uint32, val_uint32); + // error int result; success = m_data->Get( "bla", result ); @@ -181,6 +201,7 @@ TEST_F( utMetadata, get_set_aiVector3D_Test ) { EXPECT_TRUE( success ); } + TEST_F( utMetadata, copy_test ) { m_data = aiMetadata::Alloc( AI_META_MAX ); bool bv = true; @@ -199,9 +220,12 @@ TEST_F( utMetadata, copy_test ) { m_data->Set( 6, "aiVector3D", vecVal ); aiMetadata metaVal; m_data->Set( 7, "aiMetadata", metaVal ); - - aiMetadata copy( *m_data ); - EXPECT_EQ( 8u, copy.mNumProperties ); + int64_t i64 = 64; + m_data->Set(8, "int64_t", i64); + uint32_t ui32 = 32; + m_data->Set(9, "uint32_t", ui32); + aiMetadata copy(*m_data); + EXPECT_EQ( 10u, copy.mNumProperties ); // bool test { From f8132bf17cf4ba605a3dedbc3f8318c9eb8c78c4 Mon Sep 17 00:00:00 2001 From: Johan Mattsson <39247600+mjunix@users.noreply.github.com> Date: Mon, 20 Feb 2023 19:50:06 +0100 Subject: [PATCH 12/15] Fix index out of bounds --- code/AssetLib/B3D/B3DImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/AssetLib/B3D/B3DImporter.cpp b/code/AssetLib/B3D/B3DImporter.cpp index d970ecabb..e87744603 100644 --- a/code/AssetLib/B3D/B3DImporter.cpp +++ b/code/AssetLib/B3D/B3DImporter.cpp @@ -150,7 +150,7 @@ AI_WONT_RETURN void B3DImporter::Fail(const string &str) { // ------------------------------------------------------------------------------------------------ int B3DImporter::ReadByte() { - if (_pos > _buf.size()) { + if (_pos >= _buf.size()) { Fail("EOF"); } From fa4273ee1f069058a9bc151465d10726fc128986 Mon Sep 17 00:00:00 2001 From: Johan Mattsson <39247600+mjunix@users.noreply.github.com> Date: Mon, 20 Feb 2023 19:56:57 +0100 Subject: [PATCH 13/15] Fix index out of bounds --- code/AssetLib/MS3D/MS3DLoader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/AssetLib/MS3D/MS3DLoader.cpp b/code/AssetLib/MS3D/MS3DLoader.cpp index 577078158..d4dd2be75 100644 --- a/code/AssetLib/MS3D/MS3DLoader.cpp +++ b/code/AssetLib/MS3D/MS3DLoader.cpp @@ -486,7 +486,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile, for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) { aiFace& f = m->mFaces[j]; - if (g.triangles[j]>triangles.size()) { + if (g.triangles[j] >= triangles.size()) { throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed"); } @@ -494,7 +494,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile, f.mIndices = new unsigned int[f.mNumIndices=3]; for (unsigned int k = 0; k < 3; ++k,++n) { - if (t.indices[k]>vertices.size()) { + if (t.indices[k] >= vertices.size()) { throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed"); } From 2d448616d03f584cb4fa0becf02a03359db2bfad Mon Sep 17 00:00:00 2001 From: Turo Lamminen Date: Mon, 20 Feb 2023 14:53:45 +0200 Subject: [PATCH 14/15] Move string definitions into conditional block to fix unused variable warnings --- tools/assimp_cmd/Info.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index a21a39201..d67974269 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -55,26 +55,28 @@ constexpr char AICMD_MSG_INFO_HELP_E[] = "\t-v,--verbose: Print verbose info such as node transform data\n" "\t-s, --silent: Print only minimal info\n"; -constexpr char TREE_BRANCH_ASCII[] = "|-"; -constexpr char TREE_BRANCH_UTF8[] = "\xe2\x94\x9c\xe2\x95\xb4"; -constexpr char TREE_STOP_ASCII[] = "'-"; -constexpr char TREE_STOP_UTF8[] = "\xe2\x94\x94\xe2\x95\xb4"; -constexpr char TREE_CONTINUE_ASCII[] = "| "; -constexpr char TREE_CONTINUE_UTF8[] = "\xe2\x94\x82 "; // note: by default this is using utf-8 text. // this is well supported on pretty much any linux terminal. // if this causes problems on some platform, // put an #ifdef to use the ascii version for that platform. #ifdef _WIN32 +constexpr char TREE_BRANCH_ASCII[] = "|-"; +constexpr char TREE_STOP_ASCII[] = "'-"; +constexpr char TREE_CONTINUE_ASCII[] = "| "; + const char *TREE_BRANCH = TREE_BRANCH_ASCII; const char *TREE_STOP = TREE_STOP_ASCII; const char *TREE_CONTINUE = TREE_CONTINUE_ASCII; -#else +#else // _WIN32 +constexpr char TREE_BRANCH_UTF8[] = "\xe2\x94\x9c\xe2\x95\xb4"; +constexpr char TREE_STOP_UTF8[] = "\xe2\x94\x94\xe2\x95\xb4"; +constexpr char TREE_CONTINUE_UTF8[] = "\xe2\x94\x82 "; + const char *TREE_BRANCH = TREE_BRANCH_UTF8; const char *TREE_STOP = TREE_STOP_UTF8; const char *TREE_CONTINUE = TREE_CONTINUE_UTF8; -#endif +#endif // _WIN32 // ----------------------------------------------------------------------------------- unsigned int CountNodes(const aiNode *root) { From 6aac7a2458730dace3631f3924906c885931ed3b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 21 Feb 2023 21:34:49 +0100 Subject: [PATCH 15/15] Fix: Fix typo in doc - closes https://github.com/assimp/assimp/issues/4973 --- doc/Fileformats.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Fileformats.md b/doc/Fileformats.md index 89b68e17f..118d798f2 100644 --- a/doc/Fileformats.md +++ b/doc/Fileformats.md @@ -14,7 +14,7 @@ __Importers__: - B3D - [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format)) - [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy) -- CMS +- CSM - COB - [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA) - [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF)