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/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"); } diff --git a/code/AssetLib/MDL/MDLLoader.cpp b/code/AssetLib/MDL/MDLLoader.cpp index b60657805..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 = (size_t)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/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"); } diff --git a/code/AssetLib/SMD/SMDLoader.cpp b/code/AssetLib/SMD/SMDLoader.cpp index dd1f56dc3..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 = (size_t)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 868d9cbdf..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 = (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 = (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; diff --git a/code/PostProcessing/JoinVerticesProcess.cpp b/code/PostProcessing/JoinVerticesProcess.cpp index 3bf96afeb..d36915e0c 100644 --- a/code/PostProcessing/JoinVerticesProcess.cpp +++ b/code/PostProcessing/JoinVerticesProcess.cpp @@ -55,13 +55,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include using namespace Assimp; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -JoinVerticesProcess::JoinVerticesProcess() = default; - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -JoinVerticesProcess::~JoinVerticesProcess() = default; // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. @@ -251,6 +244,9 @@ private: unsigned mNumUVChannels; unsigned mNumColorChannels; }; + +static constexpr size_t JOINED_VERTICES_MARK = 0x80000000u; + // now start the JoinVerticesProcess int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { static_assert( AI_MAX_NUMBER_OF_COLOR_SETS == 8, "AI_MAX_NUMBER_OF_COLOR_SETS == 8"); @@ -357,7 +353,8 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { } } else{ // if the vertex is already there just find the replace index that is appropriate to it - replaceIndex[a] = it->second; + // mark it with JOINED_VERTICES_MARK + replaceIndex[a] = it->second | JOINED_VERTICES_MARK; } } @@ -386,7 +383,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { for( unsigned int a = 0; a < pMesh->mNumFaces; a++) { aiFace& face = pMesh->mFaces[a]; for( unsigned int b = 0; b < face.mNumIndices; b++) { - face.mIndices[b] = replaceIndex[face.mIndices[b]] & ~0x80000000; + face.mIndices[b] = replaceIndex[face.mIndices[b]] & ~JOINED_VERTICES_MARK; } } @@ -400,17 +397,8 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) { for ( unsigned int b = 0; b < bone->mNumWeights; b++ ) { const aiVertexWeight& ow = bone->mWeights[ b ]; // if the vertex is a unique one, translate it - if ( !( replaceIndex[ ow.mVertexId ] & 0x80000000 ) ) { - bool weightAlreadyExists = false; - for (std::vector::iterator vit = newWeights.begin(); vit != newWeights.end(); ++vit) { - if (vit->mVertexId == replaceIndex[ow.mVertexId]) { - weightAlreadyExists = true; - break; - } - } - if (weightAlreadyExists) { - continue; - } + // filter out joined vertices by JOINED_VERTICES_MARK. + if ( !( replaceIndex[ ow.mVertexId ] & JOINED_VERTICES_MARK ) ) { aiVertexWeight nw; nw.mVertexId = replaceIndex[ ow.mVertexId ]; nw.mWeight = ow.mWeight; diff --git a/code/PostProcessing/JoinVerticesProcess.h b/code/PostProcessing/JoinVerticesProcess.h index f95236e31..b05d74ef5 100644 --- a/code/PostProcessing/JoinVerticesProcess.h +++ b/code/PostProcessing/JoinVerticesProcess.h @@ -64,8 +64,13 @@ namespace Assimp */ class ASSIMP_API JoinVerticesProcess : public BaseProcess { public: - JoinVerticesProcess(); - ~JoinVerticesProcess(); + // ------------------------------------------------------------------- + /// @brief The default class constructor. + JoinVerticesProcess() = default; + + // ------------------------------------------------------------------- + /// @brief The default class destructor. + ~JoinVerticesProcess() = default; // ------------------------------------------------------------------- /** Returns whether the processing step is present in the given flag field. 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, 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) 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 + 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 { 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) {