Merge branch 'master' into fix-fbx-document-duplicate-id-leak

pull/4963/head
Kim Kulling 2023-02-23 10:39:52 +01:00 committed by GitHub
commit eb73464055
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 418 additions and 274 deletions

View File

@ -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 )

View File

@ -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");
}

View File

@ -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<ai_uint32>(iMaxLen);
::memcpy(pcOutBone->mName.data, pcBone->name, pcOutBone->mName.length);
pcOutBone->mName.data[pcOutBone->mName.length] = '\0';
}

View File

@ -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");
}

View File

@ -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_uint32>(ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat));
pcMat->AddProperty(&szName,AI_MATKEY_NAME);
if (aszTextures[iMat].length())

View File

@ -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<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 = static_cast<uint32_t>((bodyBuffer->byteLength + 3) & ~3); // Round up to next multiple of 4
auto curPaddingLength = binaryChunkLength - bodyBuffer->byteLength;
++GLB_Chunk_count;

View File

@ -55,13 +55,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <unordered_map>
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<aiVertexWeight>::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;

View File

@ -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.

View File

@ -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,

View File

@ -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)

View File

@ -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<index<AI_MAX_NUMBER_OF_COLOR_SETS */
/**
* @brief Check whether the anim mesh overrides a particular
* set of vertex colors on his host mesh.
* @param pIndex 0<index<AI_MAX_NUMBER_OF_COLOR_SETS
* @return true if vertex colors are stored, false if not.
*/
bool HasVertexColors(unsigned int pIndex) const {
return pIndex >= 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<index<AI_MAX_NUMBER_OF_TEXTURECOORDS */
/**
* @brief Check whether the anim mesh overrides a particular
* set of texture coordinates on his host mesh.
* @param pIndex 0<index<AI_MAX_NUMBER_OF_TEXTURECOORDS
* @return true if texture coordinates are stored, false if not.
*/
bool HasTextureCoords(unsigned int pIndex) const {
return pIndex >= 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

View File

@ -56,6 +56,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h>
#endif
#include <assimp/quaternion.h>
// -------------------------------------------------------------------------------
/**
* 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<aiMetadata>(static_cast<unsigned int>(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<aiMetadata *>(data);
break;
case AI_INT64:
delete static_cast<int64_t *>(data);
break;
case AI_UINT32:
delete static_cast<uint32_t *>(data);
break;
#ifndef SWIG
case FORCE_32BIT:
#endif
@ -510,6 +536,16 @@ struct aiMetadata {
return false;
}
} break;
case AI_INT64: {
if (*static_cast<int64_t *>(lhs.mValues[i].mData) != *static_cast<int64_t *>(rhs.mValues[i].mData)) {
return false;
}
} break;
case AI_UINT32: {
if (*static_cast<uint32_t *>(lhs.mValues[i].mData) != *static_cast<uint32_t *>(rhs.mValues[i].mData)) {
return false;
}
} break;
#ifndef SWIG
case FORCE_32BIT:
#endif

View File

@ -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
{

View File

@ -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) {