Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 09:30:09

0001 /*
0002 ---------------------------------------------------------------------------
0003 Open Asset Import Library (assimp)
0004 ---------------------------------------------------------------------------
0005 
0006 Copyright (c) 2006-2024, assimp team
0007 
0008 All rights reserved.
0009 
0010 Redistribution and use of this software in source and binary forms,
0011 with or without modification, are permitted provided that the following
0012 conditions are met:
0013 
0014 * Redistributions of source code must retain the above
0015   copyright notice, this list of conditions and the
0016   following disclaimer.
0017 
0018 * Redistributions in binary form must reproduce the above
0019   copyright notice, this list of conditions and the
0020   following disclaimer in the documentation and/or other
0021   materials provided with the distribution.
0022 
0023 * Neither the name of the assimp team, nor the names of its
0024   contributors may be used to endorse or promote products
0025   derived from this software without specific prior
0026   written permission of the assimp team.
0027 
0028 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0029 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0030 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0031 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0032 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0033 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0034 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0035 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0036 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0037 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0038 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0039 ---------------------------------------------------------------------------
0040 */
0041 
0042 /** @file mesh.h
0043  *  @brief Declares the data structures in which the imported geometry is
0044     returned by ASSIMP: aiMesh, aiFace and aiBone data structures.
0045  */
0046 #pragma once
0047 #ifndef AI_MESH_H_INC
0048 #define AI_MESH_H_INC
0049 
0050 #ifdef __GNUC__
0051 #pragma GCC system_header
0052 #endif
0053 
0054 #ifdef _MSC_VER
0055 #pragma warning(disable : 4351)
0056 #endif // _MSC_VER
0057 
0058 #include <assimp/aabb.h>
0059 #include <assimp/types.h>
0060 
0061 #ifdef __cplusplus
0062 #include <unordered_set>
0063 
0064 extern "C" {
0065 #endif
0066 
0067 // ---------------------------------------------------------------------------
0068 // Limits. These values are required to match the settings Assimp was
0069 // compiled against. Therefore, do not redefine them unless you build the
0070 // library from source using the same definitions.
0071 // ---------------------------------------------------------------------------
0072 
0073 /** @def AI_MAX_FACE_INDICES
0074  *  Maximum number of indices per face (polygon). */
0075 
0076 #ifndef AI_MAX_FACE_INDICES
0077 #define AI_MAX_FACE_INDICES 0x7fff
0078 #endif
0079 
0080 /** @def AI_MAX_BONE_WEIGHTS
0081  *  Maximum number of indices per face (polygon). */
0082 
0083 #ifndef AI_MAX_BONE_WEIGHTS
0084 #define AI_MAX_BONE_WEIGHTS 0x7fffffff
0085 #endif
0086 
0087 /** @def AI_MAX_VERTICES
0088  *  Maximum number of vertices per mesh.  */
0089 
0090 #ifndef AI_MAX_VERTICES
0091 #define AI_MAX_VERTICES 0x7fffffff
0092 #endif
0093 
0094 /** @def AI_MAX_FACES
0095  *  Maximum number of faces per mesh. */
0096 
0097 #ifndef AI_MAX_FACES
0098 #define AI_MAX_FACES 0x7fffffff
0099 #endif
0100 
0101 /** @def AI_MAX_NUMBER_OF_COLOR_SETS
0102  *  Supported number of vertex color sets per mesh. */
0103 
0104 #ifndef AI_MAX_NUMBER_OF_COLOR_SETS
0105 #define AI_MAX_NUMBER_OF_COLOR_SETS 0x8
0106 #endif // !! AI_MAX_NUMBER_OF_COLOR_SETS
0107 
0108 /** @def AI_MAX_NUMBER_OF_TEXTURECOORDS
0109  *  Supported number of texture coord sets (UV(W) channels) per mesh */
0110 
0111 #ifndef AI_MAX_NUMBER_OF_TEXTURECOORDS
0112 #define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x8
0113 #endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
0114 
0115 // ---------------------------------------------------------------------------
0116 /**
0117  * @brief A single face in a mesh, referring to multiple vertices.
0118  *
0119  * If mNumIndices is 3, we call the face 'triangle', for mNumIndices > 3
0120  * it's called 'polygon' (hey, that's just a definition!).
0121  * <br>
0122  * aiMesh::mPrimitiveTypes can be queried to quickly examine which types of
0123  * primitive are actually present in a mesh. The #aiProcess_SortByPType flag
0124  * executes a special post-processing algorithm which splits meshes with
0125  * *different* primitive types mixed up (e.g. lines and triangles) in several
0126  * 'clean' sub-meshes. Furthermore there is a configuration option (
0127  * #AI_CONFIG_PP_SBP_REMOVE) to force #aiProcess_SortByPType to remove
0128  * specific kinds of primitives from the imported scene, completely and forever.
0129  * In many cases you'll probably want to set this setting to
0130  * @code
0131  * aiPrimitiveType_LINE|aiPrimitiveType_POINT
0132  * @endcode
0133  * Together with the #aiProcess_Triangulate flag you can then be sure that
0134  * #aiFace::mNumIndices is always 3.
0135  * @note Take a look at the @link data Data Structures page @endlink for
0136  * more information on the layout and winding order of a face.
0137  */
0138 struct aiFace {
0139     //! Number of indices defining this face.
0140     //! The maximum value for this member is #AI_MAX_FACE_INDICES.
0141     unsigned int mNumIndices;
0142 
0143     //! Pointer to the indices array. Size of the array is given in numIndices.
0144     unsigned int *mIndices;
0145 
0146 #ifdef __cplusplus
0147 
0148     //! @brief Default constructor.
0149     aiFace() AI_NO_EXCEPT
0150             : mNumIndices(0),
0151               mIndices(nullptr) {
0152         // empty
0153     }
0154 
0155     //! @brief Default destructor. Delete the index array
0156     ~aiFace() {
0157         delete[] mIndices;
0158     }
0159 
0160     //! @brief Copy constructor. Copy the index array
0161     aiFace(const aiFace &o) :
0162             mNumIndices(0), mIndices(nullptr) {
0163         *this = o;
0164     }
0165 
0166     //! @brief Assignment operator. Copy the index array
0167     aiFace &operator=(const aiFace &o) {
0168         if (&o == this) {
0169             return *this;
0170         }
0171 
0172         delete[] mIndices;
0173         mNumIndices = o.mNumIndices;
0174         if (mNumIndices) {
0175             mIndices = new unsigned int[mNumIndices];
0176             ::memcpy(mIndices, o.mIndices, mNumIndices * sizeof(unsigned int));
0177         } else {
0178             mIndices = nullptr;
0179         }
0180 
0181         return *this;
0182     }
0183 
0184     //! @brief Comparison operator. Checks whether the index array of two faces is identical.
0185     bool operator==(const aiFace &o) const {
0186         if (mIndices == o.mIndices) {
0187             return true;
0188         }
0189 
0190         if (nullptr != mIndices && mNumIndices != o.mNumIndices) {
0191             return false;
0192         }
0193 
0194         if (nullptr == mIndices) {
0195             return false;
0196         }
0197 
0198         for (unsigned int i = 0; i < this->mNumIndices; ++i) {
0199             if (mIndices[i] != o.mIndices[i]) {
0200                 return false;
0201             }
0202         }
0203 
0204         return true;
0205     }
0206 
0207     //! @brief Inverse comparison operator. Checks whether the index
0208     //! array of two faces is NOT identical
0209     bool operator!=(const aiFace &o) const {
0210         return !(*this == o);
0211     }
0212 #endif // __cplusplus
0213 }; // struct aiFace
0214 
0215 // ---------------------------------------------------------------------------
0216 /** @brief A single influence of a bone on a vertex.
0217  */
0218 struct aiVertexWeight {
0219     //! Index of the vertex which is influenced by the bone.
0220     unsigned int mVertexId;
0221 
0222     //! The strength of the influence in the range (0...1).
0223     //! The influence from all bones at one vertex amounts to 1.
0224     ai_real mWeight;
0225 
0226 #ifdef __cplusplus
0227 
0228     //! @brief Default constructor
0229     aiVertexWeight() AI_NO_EXCEPT
0230             : mVertexId(0),
0231               mWeight(0.0f) {
0232         // empty
0233     }
0234 
0235     //! @brief Initialization from a given index and vertex weight factor
0236     //! \param pID ID
0237     //! \param pWeight Vertex weight factor
0238     aiVertexWeight(unsigned int pID, float pWeight) :
0239             mVertexId(pID), mWeight(pWeight) {
0240         // empty
0241     }
0242 
0243     bool operator==(const aiVertexWeight &rhs) const {
0244         return (mVertexId == rhs.mVertexId && mWeight == rhs.mWeight);
0245     }
0246 
0247     bool operator!=(const aiVertexWeight &rhs) const {
0248         return (*this == rhs);
0249     }
0250 
0251 #endif // __cplusplus
0252 };
0253 
0254 // Forward declare aiNode (pointer use only)
0255 struct aiNode;
0256 
0257 // ---------------------------------------------------------------------------
0258 /** @brief A single bone of a mesh.
0259  *
0260  *  A bone has a name by which it can be found in the frame hierarchy and by
0261  *  which it can be addressed by animations. In addition it has a number of
0262  *  influences on vertices, and a matrix relating the mesh position to the
0263  *  position of the bone at the time of binding.
0264  */
0265 struct aiBone {
0266     /**
0267      * The name of the bone.
0268      */
0269     C_STRUCT aiString mName;
0270 
0271     /**
0272      * The number of vertices affected by this bone.
0273      * The maximum value for this member is #AI_MAX_BONE_WEIGHTS.
0274      */
0275     unsigned int mNumWeights;
0276 
0277 #ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
0278     /**
0279      * The bone armature node - used for skeleton conversion
0280      * you must enable aiProcess_PopulateArmatureData to populate this
0281      */
0282     C_STRUCT aiNode *mArmature;
0283 
0284     /**
0285      * The bone node in the scene - used for skeleton conversion
0286      * you must enable aiProcess_PopulateArmatureData to populate this
0287      */
0288     C_STRUCT aiNode *mNode;
0289 
0290 #endif
0291     /**
0292      * The influence weights of this bone, by vertex index.
0293      */
0294     C_STRUCT aiVertexWeight *mWeights;
0295 
0296     /**
0297      * Matrix that transforms from mesh space to bone space in bind pose.
0298      *
0299      * This matrix describes the position of the mesh
0300      * in the local space of this bone when the skeleton was bound.
0301      * Thus it can be used directly to determine a desired vertex position,
0302      * given the world-space transform of the bone when animated,
0303      * and the position of the vertex in mesh space.
0304      *
0305      * It is sometimes called an inverse-bind matrix,
0306      * or inverse bind pose matrix.
0307      */
0308     C_STRUCT aiMatrix4x4 mOffsetMatrix;
0309 
0310 #ifdef __cplusplus
0311 
0312     /// @brief  Default constructor
0313     aiBone() AI_NO_EXCEPT
0314             : mName(),
0315               mNumWeights(0),
0316 #ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
0317               mArmature(nullptr),
0318               mNode(nullptr),
0319 #endif
0320               mWeights(nullptr),
0321               mOffsetMatrix() {
0322         // empty
0323     }
0324 
0325     /// @brief  Copy constructor
0326     aiBone(const aiBone &other) :
0327             mName(other.mName),
0328             mNumWeights(other.mNumWeights),
0329 #ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
0330               mArmature(nullptr),
0331               mNode(nullptr),
0332 #endif
0333             mWeights(nullptr),
0334             mOffsetMatrix(other.mOffsetMatrix) {
0335         copyVertexWeights(other);
0336     }
0337 
0338     void copyVertexWeights( const aiBone &other ) {
0339         if (other.mWeights == nullptr || other.mNumWeights == 0) {
0340             mWeights = nullptr;
0341             mNumWeights = 0;
0342             return;
0343         }
0344 
0345         mNumWeights = other.mNumWeights;
0346         if (mWeights) {
0347             delete[] mWeights;
0348         }
0349 
0350         mWeights = new aiVertexWeight[mNumWeights];
0351         ::memcpy(mWeights, other.mWeights, mNumWeights * sizeof(aiVertexWeight));
0352     }
0353 
0354     //! @brief Assignment operator
0355     aiBone &operator = (const aiBone &other) {
0356         if (this == &other) {
0357             return *this;
0358         }
0359 
0360         mName = other.mName;
0361         mNumWeights = other.mNumWeights;
0362         mOffsetMatrix = other.mOffsetMatrix;
0363         copyVertexWeights(other);
0364 
0365         return *this;
0366     }
0367 
0368     /// @brief Compare operator.
0369     bool operator==(const aiBone &rhs) const {
0370         if (mName != rhs.mName || mNumWeights != rhs.mNumWeights ) {
0371             return false;
0372         }
0373 
0374         for (size_t i = 0; i < mNumWeights; ++i) {
0375             if (mWeights[i] != rhs.mWeights[i]) {
0376                 return false;
0377             }
0378         }
0379 
0380         return true;
0381     }
0382     //! @brief Destructor - deletes the array of vertex weights
0383     ~aiBone() {
0384         delete[] mWeights;
0385     }
0386 #endif // __cplusplus
0387 };
0388 
0389 // ---------------------------------------------------------------------------
0390 /** @brief Enumerates the types of geometric primitives supported by Assimp.
0391  *
0392  *  @see aiFace Face data structure
0393  *  @see aiProcess_SortByPType Per-primitive sorting of meshes
0394  *  @see aiProcess_Triangulate Automatic triangulation
0395  *  @see AI_CONFIG_PP_SBP_REMOVE Removal of specific primitive types.
0396  */
0397 enum aiPrimitiveType {
0398     /**
0399      * @brief A point primitive.
0400      *
0401      * This is just a single vertex in the virtual world,
0402      * #aiFace contains just one index for such a primitive.
0403      */
0404     aiPrimitiveType_POINT = 0x1,
0405 
0406     /**
0407      * @brief A line primitive.
0408      *
0409      * This is a line defined through a start and an end position.
0410      * #aiFace contains exactly two indices for such a primitive.
0411      */
0412     aiPrimitiveType_LINE = 0x2,
0413 
0414     /**
0415      * @brief A triangular primitive.
0416      *
0417      * A triangle consists of three indices.
0418      */
0419     aiPrimitiveType_TRIANGLE = 0x4,
0420 
0421     /**
0422      * @brief A higher-level polygon with more than 3 edges.
0423      *
0424      * A triangle is a polygon, but polygon in this context means
0425      * "all polygons that are not triangles". The "Triangulate"-Step
0426      * is provided for your convenience, it splits all polygons in
0427      * triangles (which are much easier to handle).
0428      */
0429     aiPrimitiveType_POLYGON = 0x8,
0430 
0431     /**
0432      * @brief A flag to determine whether this triangles only mesh is NGON encoded.
0433      *
0434      * NGON encoding is a special encoding that tells whether 2 or more consecutive triangles
0435      * should be considered as a triangle fan. This is identified by looking at the first vertex index.
0436      * 2 consecutive triangles with the same 1st vertex index are part of the same
0437      * NGON.
0438      *
0439      * At the moment, only quads (concave or convex) are supported, meaning that polygons are 'seen' as
0440      * triangles, as usual after a triangulation pass.
0441      *
0442      * To get an NGON encoded mesh, please use the aiProcess_Triangulate post process.
0443      *
0444      * @see aiProcess_Triangulate
0445      * @link https://github.com/KhronosGroup/glTF/pull/1620
0446      */
0447     aiPrimitiveType_NGONEncodingFlag = 0x10,
0448 
0449     /**
0450      * This value is not used. It is just here to force the
0451      * compiler to map this enum to a 32 Bit integer.
0452      */
0453 #ifndef SWIG
0454     _aiPrimitiveType_Force32Bit = INT_MAX
0455 #endif
0456 }; //! enum aiPrimitiveType
0457 
0458 // Get the #aiPrimitiveType flag for a specific number of face indices
0459 #define AI_PRIMITIVE_TYPE_FOR_N_INDICES(n) \
0460     ((n) > 3 ? aiPrimitiveType_POLYGON : (aiPrimitiveType)(1u << ((n)-1)))
0461 
0462 // ---------------------------------------------------------------------------
0463 /** @brief An AnimMesh is an attachment to an #aiMesh stores per-vertex
0464  *  animations for a particular frame.
0465  *
0466  *  You may think of an #aiAnimMesh as a `patch` for the host mesh, which
0467  *  replaces only certain vertex data streams at a particular time.
0468  *  Each mesh stores n attached attached meshes (#aiMesh::mAnimMeshes).
0469  *  The actual relationship between the time line and anim meshes is
0470  *  established by #aiMeshAnim, which references singular mesh attachments
0471  *  by their ID and binds them to a time offset.
0472 */
0473 struct aiAnimMesh {
0474     /**Anim Mesh name */
0475     C_STRUCT aiString mName;
0476 
0477     /** Replacement for aiMesh::mVertices. If this array is non-nullptr,
0478      *  it *must* contain mNumVertices entries. The corresponding
0479      *  array in the host mesh must be non-nullptr as well - animation
0480      *  meshes may neither add or nor remove vertex components (if
0481      *  a replacement array is nullptr and the corresponding source
0482      *  array is not, the source data is taken instead)*/
0483     C_STRUCT aiVector3D *mVertices;
0484 
0485     /** Replacement for aiMesh::mNormals.  */
0486     C_STRUCT aiVector3D *mNormals;
0487 
0488     /** Replacement for aiMesh::mTangents. */
0489     C_STRUCT aiVector3D *mTangents;
0490 
0491     /** Replacement for aiMesh::mBitangents. */
0492     C_STRUCT aiVector3D *mBitangents;
0493 
0494     /** Replacement for aiMesh::mColors */
0495     C_STRUCT aiColor4D *mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
0496 
0497     /** Replacement for aiMesh::mTextureCoords */
0498     C_STRUCT aiVector3D *mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
0499 
0500     /** The number of vertices in the aiAnimMesh, and thus the length of all
0501      * the member arrays.
0502      *
0503      * This has always the same value as the mNumVertices property in the
0504      * corresponding aiMesh. It is duplicated here merely to make the length
0505      * of the member arrays accessible even if the aiMesh is not known, e.g.
0506      * from language bindings.
0507      */
0508     unsigned int mNumVertices;
0509 
0510     /**
0511      * Weight of the AnimMesh.
0512      */
0513     float mWeight;
0514 
0515 #ifdef __cplusplus
0516     /// @brief  The class constructor.
0517     aiAnimMesh() AI_NO_EXCEPT :
0518             mVertices(nullptr),
0519             mNormals(nullptr),
0520             mTangents(nullptr),
0521             mBitangents(nullptr),
0522             mColors {nullptr},
0523             mTextureCoords{nullptr},
0524             mNumVertices(0),
0525             mWeight(0.0f) {
0526         // empty
0527     }
0528 
0529     /// @brief The class destructor.
0530     ~aiAnimMesh() {
0531         delete[] mVertices;
0532         delete[] mNormals;
0533         delete[] mTangents;
0534         delete[] mBitangents;
0535         for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
0536             delete[] mTextureCoords[a];
0537         }
0538         for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
0539             delete[] mColors[a];
0540         }
0541     }
0542 
0543     /**
0544      *  @brief Check whether the anim-mesh overrides the vertex positions
0545      *         of its host mesh.
0546      *  @return true if positions are stored, false if not.
0547      */
0548     bool HasPositions() const {
0549         return mVertices != nullptr;
0550     }
0551 
0552     /**
0553      *  @brief Check whether the anim-mesh overrides the vertex normals
0554      *         of its host mesh
0555      *  @return true if normals are stored, false if not.
0556      */
0557     bool HasNormals() const {
0558         return mNormals != nullptr;
0559     }
0560 
0561     /**
0562      *  @brief Check whether the anim-mesh overrides the vertex tangents
0563      *         and bitangents of its host mesh. As for aiMesh,
0564      *         tangents and bitangents always go together.
0565      *  @return true if tangents and bi-tangents are stored, false if not.
0566      */
0567     bool HasTangentsAndBitangents() const {
0568         return mTangents != nullptr;
0569     }
0570 
0571     /**
0572      *  @brief Check whether the anim mesh overrides a particular
0573      *         set of vertex colors on his host mesh.
0574      *  @param pIndex 0<index<AI_MAX_NUMBER_OF_COLOR_SETS
0575      *  @return true if vertex colors are stored, false if not.
0576      */
0577 
0578     bool HasVertexColors(unsigned int pIndex) const {
0579         return pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS ? false : mColors[pIndex] != nullptr;
0580     }
0581 
0582     /**
0583      *  @brief Check whether the anim mesh overrides a particular
0584      *        set of texture coordinates on his host mesh.
0585      *  @param pIndex 0<index<AI_MAX_NUMBER_OF_TEXTURECOORDS
0586      *  @return true if texture coordinates are stored, false if not.
0587      */
0588     bool HasTextureCoords(unsigned int pIndex) const {
0589         return pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? false : mTextureCoords[pIndex] != nullptr;
0590     }
0591 
0592 #endif
0593 };
0594 
0595 // ---------------------------------------------------------------------------
0596 /** @brief Enumerates the methods of mesh morphing supported by Assimp.
0597  */
0598 enum aiMorphingMethod {
0599     /** Morphing method to be determined */
0600     aiMorphingMethod_UNKNOWN = 0x0,
0601 
0602     /** Interpolation between morph targets */
0603     aiMorphingMethod_VERTEX_BLEND = 0x1,
0604 
0605     /** Normalized morphing between morph targets  */
0606     aiMorphingMethod_MORPH_NORMALIZED = 0x2,
0607 
0608     /** Relative morphing between morph targets  */
0609     aiMorphingMethod_MORPH_RELATIVE = 0x3,
0610 
0611 /** This value is not used. It is just here to force the
0612      *  compiler to map this enum to a 32 Bit integer.
0613      */
0614 #ifndef SWIG
0615     _aiMorphingMethod_Force32Bit = INT_MAX
0616 #endif
0617 }; //! enum aiMorphingMethod
0618 
0619 // ---------------------------------------------------------------------------
0620 /** @brief A mesh represents a geometry or model with a single material.
0621  *
0622  * It usually consists of a number of vertices and a series of primitives/faces
0623  * referencing the vertices. In addition there might be a series of bones, each
0624  * of them addressing a number of vertices with a certain weight. Vertex data
0625  * is presented in channels with each channel containing a single per-vertex
0626  * information such as a set of texture coordinates or a normal vector.
0627  * If a data pointer is non-null, the corresponding data stream is present.
0628  * From C++-programs you can also use the comfort functions Has*() to
0629  * test for the presence of various data streams.
0630  *
0631  * A Mesh uses only a single material which is referenced by a material ID.
0632  * @note The mPositions member is usually not optional. However, vertex positions
0633  * *could* be missing if the #AI_SCENE_FLAGS_INCOMPLETE flag is set in
0634  * @code
0635  * aiScene::mFlags
0636  * @endcode
0637  */
0638 struct aiMesh {
0639     /**
0640      * Bitwise combination of the members of the #aiPrimitiveType enum.
0641      * This specifies which types of primitives are present in the mesh.
0642      * The "SortByPrimitiveType"-Step can be used to make sure the
0643      * output meshes consist of one primitive type each.
0644      */
0645     unsigned int mPrimitiveTypes;
0646 
0647     /**
0648      * The number of vertices in this mesh.
0649      * This is also the size of all of the per-vertex data arrays.
0650      * The maximum value for this member is #AI_MAX_VERTICES.
0651      */
0652     unsigned int mNumVertices;
0653 
0654     /**
0655      * The number of primitives (triangles, polygons, lines) in this  mesh.
0656      * This is also the size of the mFaces array.
0657      * The maximum value for this member is #AI_MAX_FACES.
0658      */
0659     unsigned int mNumFaces;
0660 
0661     /**
0662      * @brief Vertex positions.
0663      * 
0664      * This array is always present in a mesh. The array is
0665      * mNumVertices in size.
0666      */
0667     C_STRUCT aiVector3D *mVertices;
0668 
0669     /**
0670      * @brief Vertex normals.
0671      * 
0672      * The array contains normalized vectors, nullptr if not present.
0673      * The array is mNumVertices in size. Normals are undefined for
0674      * point and line primitives. A mesh consisting of points and
0675      * lines only may not have normal vectors. Meshes with mixed
0676      * primitive types (i.e. lines and triangles) may have normals,
0677      * but the normals for vertices that are only referenced by
0678      * point or line primitives are undefined and set to QNaN (WARN:
0679      * qNaN compares to inequal to *everything*, even to qNaN itself.
0680      * Using code like this to check whether a field is qnan is:
0681      * @code
0682      * #define IS_QNAN(f) (f != f)
0683      * @endcode
0684      * still dangerous because even 1.f == 1.f could evaluate to false! (
0685      * remember the subtleties of IEEE754 artithmetics). Use stuff like
0686      * @c fpclassify instead.
0687      * @note Normal vectors computed by Assimp are always unit-length.
0688      * However, this needn't apply for normals that have been taken
0689      * directly from the model file.
0690      */
0691     C_STRUCT aiVector3D *mNormals;
0692 
0693     /**
0694      * @brief Vertex tangents.
0695      * 
0696      * The tangent of a vertex points in the direction of the positive
0697      * X texture axis. The array contains normalized vectors, nullptr if
0698      * not present. The array is mNumVertices in size. A mesh consisting
0699      * of points and lines only may not have normal vectors. Meshes with
0700      * mixed primitive types (i.e. lines and triangles) may have
0701      * normals, but the normals for vertices that are only referenced by
0702      * point or line primitives are undefined and set to qNaN.  See
0703      * the #mNormals member for a detailed discussion of qNaNs.
0704      * @note If the mesh contains tangents, it automatically also
0705      * contains bitangents.
0706      */
0707     C_STRUCT aiVector3D *mTangents;
0708 
0709     /**
0710      * @brief Vertex bitangents.
0711      * 
0712      * The bitangent of a vertex points in the direction of the positive
0713      * Y texture axis. The array contains normalized vectors, nullptr if not
0714      * present. The array is mNumVertices in size.
0715      * @note If the mesh contains tangents, it automatically also contains
0716      * bitangents.
0717      */
0718     C_STRUCT aiVector3D *mBitangents;
0719 
0720     /**
0721      * @brief Vertex color sets.
0722      * 
0723      * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex
0724      * colors per vertex. nullptr if not present. Each array is
0725      * mNumVertices in size if present.
0726      */
0727     C_STRUCT aiColor4D *mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
0728 
0729     /**
0730      * @brief Vertex texture coordinates, also known as UV channels.
0731      * 
0732      * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS channels per
0733      * vertex. Used and unused (nullptr) channels may go in any order.
0734      * The array is mNumVertices in size.
0735      */
0736     C_STRUCT aiVector3D *mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
0737 
0738     /**
0739      * @brief Specifies the number of components for a given UV channel.
0740      * 
0741      * Up to three channels are supported (UVW, for accessing volume
0742      * or cube maps). If the value is 2 for a given channel n, the
0743      * component p.z of mTextureCoords[n][p] is set to 0.0f.
0744      * If the value is 1 for a given channel, p.y is set to 0.0f, too.
0745      * @note 4D coordinates are not supported
0746      */
0747     unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
0748 
0749     /**
0750      * @brief The faces the mesh is constructed from.
0751      * 
0752      * Each face refers to a number of vertices by their indices.
0753      * This array is always present in a mesh, its size is given
0754      *  in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
0755      * is NOT set each face references an unique set of vertices.
0756      */
0757     C_STRUCT aiFace *mFaces;
0758 
0759     /**
0760     * The number of bones this mesh contains. Can be 0, in which case the mBones array is nullptr.
0761     */
0762     unsigned int mNumBones;
0763 
0764     /**
0765      * @brief The bones of this mesh.
0766      * 
0767      * A bone consists of a name by which it can be found in the
0768      * frame hierarchy and a set of vertex weights.
0769      */
0770     C_STRUCT aiBone **mBones;
0771 
0772     /**
0773      * @brief The material used by this mesh.
0774      * 
0775      * A mesh uses only a single material. If an imported model uses
0776      * multiple materials, the import splits up the mesh. Use this value
0777      * as index into the scene's material list.
0778      */
0779     unsigned int mMaterialIndex;
0780 
0781     /**
0782      *  Name of the mesh. Meshes can be named, but this is not a
0783      *  requirement and leaving this field empty is totally fine.
0784      *  There are mainly three uses for mesh names:
0785      *   - some formats name nodes and meshes independently.
0786      *   - importers tend to split meshes up to meet the
0787      *      one-material-per-mesh requirement. Assigning
0788      *      the same (dummy) name to each of the result meshes
0789      *      aids the caller at recovering the original mesh
0790      *      partitioning.
0791      *   - Vertex animations refer to meshes by their names.
0792      */
0793     C_STRUCT aiString mName;
0794 
0795     /**
0796      * The number of attachment meshes.
0797      * Currently known to work with loaders:
0798      * - Collada
0799      * - gltf
0800      */
0801     unsigned int mNumAnimMeshes;
0802 
0803     /**
0804      * Attachment meshes for this mesh, for vertex-based animation.
0805      * Attachment meshes carry replacement data for some of the
0806      * mesh'es vertex components (usually positions, normals).
0807      * Currently known to work with loaders:
0808      * - Collada
0809      * - gltf
0810      */
0811     C_STRUCT aiAnimMesh **mAnimMeshes;
0812 
0813     /**
0814      *  Method of morphing when anim-meshes are specified.
0815      *  @see aiMorphingMethod to learn more about the provided morphing targets.
0816      */
0817     enum aiMorphingMethod mMethod;
0818 
0819     /**
0820      *  The bounding box.
0821      */
0822     C_STRUCT aiAABB mAABB;
0823 
0824     /**
0825      * Vertex UV stream names. Pointer to array of size AI_MAX_NUMBER_OF_TEXTURECOORDS
0826      */
0827     C_STRUCT aiString **mTextureCoordsNames;
0828 
0829 #ifdef __cplusplus
0830 
0831     //! The default class constructor.
0832     aiMesh() AI_NO_EXCEPT
0833             : mPrimitiveTypes(0),
0834               mNumVertices(0),
0835               mNumFaces(0),
0836               mVertices(nullptr),
0837               mNormals(nullptr),
0838               mTangents(nullptr),
0839               mBitangents(nullptr),
0840               mColors{nullptr},
0841               mTextureCoords{nullptr},
0842               mNumUVComponents{0},
0843               mFaces(nullptr),
0844               mNumBones(0),
0845               mBones(nullptr),
0846               mMaterialIndex(0),
0847               mNumAnimMeshes(0),
0848               mAnimMeshes(nullptr),
0849               mMethod(aiMorphingMethod_UNKNOWN),
0850               mAABB(),
0851               mTextureCoordsNames(nullptr) {
0852         // empty
0853     }
0854 
0855     //! @brief The class destructor.
0856     ~aiMesh() {
0857         delete[] mVertices;
0858         delete[] mNormals;
0859         delete[] mTangents;
0860         delete[] mBitangents;
0861         for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
0862             delete[] mTextureCoords[a];
0863         }
0864 
0865         if (mTextureCoordsNames) {
0866             for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
0867                 delete mTextureCoordsNames[a];
0868             }
0869             delete[] mTextureCoordsNames;
0870         }
0871 
0872         for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
0873             delete[] mColors[a];
0874         }
0875 
0876         // DO NOT REMOVE THIS ADDITIONAL CHECK
0877         if (mNumBones && mBones) {
0878             std::unordered_set<const aiBone *> bones;
0879             for (unsigned int a = 0; a < mNumBones; a++) {
0880                 if (mBones[a]) {
0881                     bones.insert(mBones[a]);
0882                 }
0883             }
0884             for (const aiBone *bone: bones) {
0885                 delete bone;
0886             }
0887             delete[] mBones;
0888         }
0889 
0890         if (mNumAnimMeshes && mAnimMeshes) {
0891             for (unsigned int a = 0; a < mNumAnimMeshes; a++) {
0892                 delete mAnimMeshes[a];
0893             }
0894             delete[] mAnimMeshes;
0895         }
0896 
0897         delete[] mFaces;
0898     }
0899 
0900     //! @brief Check whether the mesh contains positions. Provided no special
0901     //!        scene flags are set, this will always be true
0902     //! @return true, if positions are stored, false if not.
0903     bool HasPositions() const {
0904         return mVertices != nullptr && mNumVertices > 0;
0905     }
0906 
0907     //! @brief Check whether the mesh contains faces. If no special scene flags
0908     //!        are set this should always return true
0909     //! @return true, if faces are stored, false if not.
0910     bool HasFaces() const {
0911         return mFaces != nullptr && mNumFaces > 0;
0912     }
0913 
0914     //! @brief Check whether the mesh contains normal vectors
0915     //! @return true, if normals are stored, false if not.
0916     bool HasNormals() const {
0917         return mNormals != nullptr && mNumVertices > 0;
0918     }
0919 
0920     //! @brief Check whether the mesh contains tangent and bitangent vectors.
0921     //! 
0922     //! It is not possible that it contains tangents and no bitangents
0923     //! (or the other way round). The existence of one of them
0924     //! implies that the second is there, too.
0925     //! @return true, if tangents and bi-tangents are stored, false if not.
0926     bool HasTangentsAndBitangents() const {
0927         return mTangents != nullptr && mBitangents != nullptr && mNumVertices > 0;
0928     }
0929 
0930     //! @brief Check whether the mesh contains a vertex color set
0931     //! @param index    Index of the vertex color set
0932     //! @return true, if vertex colors are stored, false if not.
0933     bool HasVertexColors(unsigned int index) const {
0934         if (index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
0935             return false;
0936         }
0937         return mColors[index] != nullptr && mNumVertices > 0;        
0938     }
0939 
0940     //! @brief Check whether the mesh contains a texture coordinate set
0941     //! @param index    Index of the texture coordinates set
0942     //! @return true, if texture coordinates are stored, false if not.
0943     bool HasTextureCoords(unsigned int index) const {
0944         if (index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
0945             return false;
0946         }
0947         return (mTextureCoords[index] != nullptr && mNumVertices > 0);
0948     }
0949 
0950     //! @brief Get the number of UV channels the mesh contains.
0951     //! @return the number of stored uv-channels.
0952     unsigned int GetNumUVChannels() const {
0953         unsigned int n(0);
0954         for (unsigned i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) {
0955             if (mTextureCoords[i]) {
0956                 ++n;
0957             }
0958         }
0959 
0960         return n;
0961     }
0962 
0963     //! @brief Get the number of vertex color channels the mesh contains.
0964     //! @return The number of stored color channels.
0965     unsigned int GetNumColorChannels() const {
0966         unsigned int n(0);
0967         while (n < AI_MAX_NUMBER_OF_COLOR_SETS && mColors[n]) {
0968             ++n;
0969         }
0970         return n;
0971     }
0972 
0973     //! @brief Check whether the mesh contains bones.
0974     //! @return true, if bones are stored.
0975     bool HasBones() const {
0976         return mBones != nullptr && mNumBones > 0;
0977     }
0978 
0979     //! @brief  Check whether the mesh contains a texture coordinate set name
0980     //! @param pIndex Index of the texture coordinates set
0981     //! @return true, if texture coordinates for the index exists.
0982     bool HasTextureCoordsName(unsigned int pIndex) const {
0983         if (mTextureCoordsNames == nullptr || pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
0984             return false;
0985         }
0986         return mTextureCoordsNames[pIndex] != nullptr;
0987     }
0988 
0989     //! @brief  Set a texture coordinate set name
0990     //! @param pIndex Index of the texture coordinates set
0991     //! @param texCoordsName name of the texture coordinate set
0992     void SetTextureCoordsName(unsigned int pIndex, const aiString &texCoordsName) {
0993         if (pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
0994             return;
0995         }
0996 
0997         if (mTextureCoordsNames == nullptr) {
0998             // Construct and null-init array
0999             mTextureCoordsNames = new aiString *[AI_MAX_NUMBER_OF_TEXTURECOORDS];
1000             for (size_t i=0; i<AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
1001                 mTextureCoordsNames[i] = nullptr;
1002             }
1003         }
1004 
1005         if (texCoordsName.length == 0) {
1006             delete mTextureCoordsNames[pIndex];
1007             mTextureCoordsNames[pIndex] = nullptr;
1008             return;
1009         }
1010 
1011         if (mTextureCoordsNames[pIndex] == nullptr) {
1012             mTextureCoordsNames[pIndex] = new aiString(texCoordsName);
1013             return;
1014         }
1015 
1016         *mTextureCoordsNames[pIndex] = texCoordsName;
1017     }
1018 
1019     //! @brief  Get a texture coordinate set name
1020     //! @param  pIndex Index of the texture coordinates set
1021     //! @return The texture coordinate name.
1022     const aiString *GetTextureCoordsName(unsigned int index) const {
1023         if (mTextureCoordsNames == nullptr || index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
1024             return nullptr;
1025         }
1026 
1027         return mTextureCoordsNames[index];
1028     }
1029 
1030 #endif // __cplusplus
1031 };
1032 
1033 /**
1034  * @brief  A skeleton bone represents a single bone is a skeleton structure.
1035  *
1036  * Skeleton-Animations can be represented via a skeleton struct, which describes
1037  * a hierarchical tree assembled from skeleton bones. A bone is linked to a mesh.
1038  * The bone knows its parent bone. If there is no parent bone the parent id is
1039  * marked with -1.
1040  * The skeleton-bone stores a pointer to its used armature. If there is no
1041  * armature this value if set to nullptr.
1042  * A skeleton bone stores its offset-matrix, which is the absolute transformation
1043  * for the bone. The bone stores the locale transformation to its parent as well.
1044  * You can compute the offset matrix by multiplying the hierarchy like:
1045  * Tree: s1 -> s2 -> s3
1046  * Offset-Matrix s3 = locale-s3 * locale-s2 * locale-s1
1047  */
1048 struct aiSkeletonBone {
1049     /// The parent bone index, is -1 one if this bone represents the root bone.
1050     int mParent;
1051 
1052 
1053 #ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
1054     /// @brief The bone armature node - used for skeleton conversion
1055     /// you must enable aiProcess_PopulateArmatureData to populate this
1056     C_STRUCT aiNode *mArmature;
1057 
1058     /// @brief The bone node in the scene - used for skeleton conversion
1059     /// you must enable aiProcess_PopulateArmatureData to populate this
1060     C_STRUCT aiNode *mNode;
1061 
1062 #endif
1063     /// @brief The number of weights
1064     unsigned int mNumnWeights;
1065 
1066     /// The mesh index, which will get influenced by the weight.
1067     C_STRUCT aiMesh *mMeshId;
1068 
1069     /// The influence weights of this bone, by vertex index.
1070     C_STRUCT aiVertexWeight *mWeights;
1071 
1072     /** Matrix that transforms from bone space to mesh space in bind pose.
1073      *
1074      * This matrix describes the position of the mesh
1075      * in the local space of this bone when the skeleton was bound.
1076      * Thus it can be used directly to determine a desired vertex position,
1077      * given the world-space transform of the bone when animated,
1078      * and the position of the vertex in mesh space.
1079      *
1080      * It is sometimes called an inverse-bind matrix,
1081      * or inverse bind pose matrix.
1082      */
1083     C_STRUCT aiMatrix4x4 mOffsetMatrix;
1084 
1085     /// Matrix that transforms the locale bone in bind pose.
1086     C_STRUCT aiMatrix4x4 mLocalMatrix;
1087 
1088 #ifdef __cplusplus
1089     /// @brief The class constructor.
1090     aiSkeletonBone() :
1091             mParent(-1),
1092 #ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
1093             mArmature(nullptr),
1094             mNode(nullptr),
1095 #endif
1096             mNumnWeights(0),
1097             mMeshId(nullptr),
1098             mWeights(nullptr),
1099             mOffsetMatrix(),
1100             mLocalMatrix() {
1101         // empty
1102     }
1103 
1104     /// @brief The class constructor with its parent
1105     /// @param  parent      The parent node index.
1106     aiSkeletonBone(unsigned int parent) :
1107             mParent(parent),
1108 #ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
1109             mArmature(nullptr),
1110             mNode(nullptr),
1111 #endif
1112             mNumnWeights(0),
1113             mMeshId(nullptr),
1114             mWeights(nullptr),
1115             mOffsetMatrix(),
1116             mLocalMatrix() {
1117         // empty
1118     }
1119     /// @brief The class destructor.
1120     ~aiSkeletonBone() {
1121         delete[] mWeights;
1122         mWeights = nullptr;
1123     }
1124 #endif // __cplusplus
1125 };
1126 /**
1127  * @brief A skeleton represents the bone hierarchy of an animation.
1128  *
1129  * Skeleton animations can be described as a tree of bones:
1130  *                  root
1131  *                    |
1132  *                  node1
1133  *                  /   \
1134  *               node3  node4
1135  * If you want to calculate the transformation of node three you need to compute the
1136  * transformation hierarchy for the transformation chain of node3:
1137  * root->node1->node3
1138  * Each node is represented as a skeleton instance.
1139  */
1140 struct aiSkeleton {
1141     /**
1142      *  @brief The name of the skeleton instance.
1143      */
1144     C_STRUCT aiString mName;
1145 
1146     /**
1147      *  @brief  The number of bones in the skeleton.
1148      */
1149     unsigned int mNumBones;
1150 
1151     /**
1152      *  @brief The bone instance in the skeleton.
1153      */
1154     C_STRUCT aiSkeletonBone **mBones;
1155 
1156 #ifdef __cplusplus
1157     /**
1158      *  @brief The class constructor.
1159      */
1160     aiSkeleton() AI_NO_EXCEPT : mName(), mNumBones(0), mBones(nullptr) {
1161         // empty
1162     }
1163 
1164     /**
1165      *  @brief  The class destructor.
1166      */
1167     ~aiSkeleton() {
1168         delete[] mBones;
1169     }
1170 #endif // __cplusplus
1171 };
1172 #ifdef __cplusplus
1173 }
1174 #endif //! extern "C"
1175 
1176 #endif // AI_MESH_H_INC
1177