nuclear@0: /*
nuclear@0: ---------------------------------------------------------------------------
nuclear@0: Open Asset Import Library (assimp)
nuclear@0: ---------------------------------------------------------------------------
nuclear@0:
nuclear@0: Copyright (c) 2006-2018, assimp team
nuclear@0:
nuclear@0:
nuclear@0: All rights reserved.
nuclear@0:
nuclear@0: Redistribution and use of this software in source and binary forms,
nuclear@0: with or without modification, are permitted provided that the following
nuclear@0: conditions are met:
nuclear@0:
nuclear@0: * Redistributions of source code must retain the above
nuclear@0: copyright notice, this list of conditions and the
nuclear@0: following disclaimer.
nuclear@0:
nuclear@0: * Redistributions in binary form must reproduce the above
nuclear@0: copyright notice, this list of conditions and the
nuclear@0: following disclaimer in the documentation and/or other
nuclear@0: materials provided with the distribution.
nuclear@0:
nuclear@0: * Neither the name of the assimp team, nor the names of its
nuclear@0: contributors may be used to endorse or promote products
nuclear@0: derived from this software without specific prior
nuclear@0: written permission of the assimp team.
nuclear@0:
nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0: ---------------------------------------------------------------------------
nuclear@0: */
nuclear@0:
nuclear@0: /** @file mesh.h
nuclear@0: * @brief Declares the data structures in which the imported geometry is
nuclear@0: returned by ASSIMP: aiMesh, aiFace and aiBone data structures.
nuclear@0: */
nuclear@0: #pragma once
nuclear@0: #ifndef AI_MESH_H_INC
nuclear@0: #define AI_MESH_H_INC
nuclear@0:
nuclear@0: #include "types.h"
nuclear@0:
nuclear@0: #ifdef __cplusplus
nuclear@0: extern "C" {
nuclear@0: #endif
nuclear@0:
nuclear@0: // ---------------------------------------------------------------------------
nuclear@0: // Limits. These values are required to match the settings Assimp was
nuclear@0: // compiled against. Therefore, do not redefine them unless you build the
nuclear@0: // library from source using the same definitions.
nuclear@0: // ---------------------------------------------------------------------------
nuclear@0:
nuclear@0: /** @def AI_MAX_FACE_INDICES
nuclear@0: * Maximum number of indices per face (polygon). */
nuclear@0:
nuclear@0: #ifndef AI_MAX_FACE_INDICES
nuclear@0: # define AI_MAX_FACE_INDICES 0x7fff
nuclear@0: #endif
nuclear@0:
nuclear@0: /** @def AI_MAX_BONE_WEIGHTS
nuclear@0: * Maximum number of indices per face (polygon). */
nuclear@0:
nuclear@0: #ifndef AI_MAX_BONE_WEIGHTS
nuclear@0: # define AI_MAX_BONE_WEIGHTS 0x7fffffff
nuclear@0: #endif
nuclear@0:
nuclear@0: /** @def AI_MAX_VERTICES
nuclear@0: * Maximum number of vertices per mesh. */
nuclear@0:
nuclear@0: #ifndef AI_MAX_VERTICES
nuclear@0: # define AI_MAX_VERTICES 0x7fffffff
nuclear@0: #endif
nuclear@0:
nuclear@0: /** @def AI_MAX_FACES
nuclear@0: * Maximum number of faces per mesh. */
nuclear@0:
nuclear@0: #ifndef AI_MAX_FACES
nuclear@0: # define AI_MAX_FACES 0x7fffffff
nuclear@0: #endif
nuclear@0:
nuclear@0: /** @def AI_MAX_NUMBER_OF_COLOR_SETS
nuclear@0: * Supported number of vertex color sets per mesh. */
nuclear@0:
nuclear@0: #ifndef AI_MAX_NUMBER_OF_COLOR_SETS
nuclear@0: # define AI_MAX_NUMBER_OF_COLOR_SETS 0x8
nuclear@0: #endif // !! AI_MAX_NUMBER_OF_COLOR_SETS
nuclear@0:
nuclear@0: /** @def AI_MAX_NUMBER_OF_TEXTURECOORDS
nuclear@0: * Supported number of texture coord sets (UV(W) channels) per mesh */
nuclear@0:
nuclear@0: #ifndef AI_MAX_NUMBER_OF_TEXTURECOORDS
nuclear@0: # define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x8
nuclear@0: #endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
nuclear@0:
nuclear@0: // ---------------------------------------------------------------------------
nuclear@0: /** @brief A single face in a mesh, referring to multiple vertices.
nuclear@0: *
nuclear@0: * If mNumIndices is 3, we call the face 'triangle', for mNumIndices > 3
nuclear@0: * it's called 'polygon' (hey, that's just a definition!).
nuclear@0: *
nuclear@0: * aiMesh::mPrimitiveTypes can be queried to quickly examine which types of
nuclear@0: * primitive are actually present in a mesh. The #aiProcess_SortByPType flag
nuclear@0: * executes a special post-processing algorithm which splits meshes with
nuclear@0: * *different* primitive types mixed up (e.g. lines and triangles) in several
nuclear@0: * 'clean' submeshes. Furthermore there is a configuration option (
nuclear@0: * #AI_CONFIG_PP_SBP_REMOVE) to force #aiProcess_SortByPType to remove
nuclear@0: * specific kinds of primitives from the imported scene, completely and forever.
nuclear@0: * In many cases you'll probably want to set this setting to
nuclear@0: * @code
nuclear@0: * aiPrimitiveType_LINE|aiPrimitiveType_POINT
nuclear@0: * @endcode
nuclear@0: * Together with the #aiProcess_Triangulate flag you can then be sure that
nuclear@0: * #aiFace::mNumIndices is always 3.
nuclear@0: * @note Take a look at the @link data Data Structures page @endlink for
nuclear@0: * more information on the layout and winding order of a face.
nuclear@0: */
nuclear@0: struct aiFace
nuclear@0: {
nuclear@0: //! Number of indices defining this face.
nuclear@0: //! The maximum value for this member is #AI_MAX_FACE_INDICES.
nuclear@0: unsigned int mNumIndices;
nuclear@0:
nuclear@0: //! Pointer to the indices array. Size of the array is given in numIndices.
nuclear@0: unsigned int* mIndices;
nuclear@0:
nuclear@0: #ifdef __cplusplus
nuclear@0:
nuclear@0: //! Default constructor
nuclear@0: aiFace() AI_NO_EXCEPT
nuclear@0: : mNumIndices( 0 )
nuclear@0: , mIndices( 0 ) {
nuclear@0: // empty
nuclear@0: }
nuclear@0:
nuclear@0: //! Default destructor. Delete the index array
nuclear@0: ~aiFace()
nuclear@0: {
nuclear@0: delete [] mIndices;
nuclear@0: }
nuclear@0:
nuclear@0: //! Copy constructor. Copy the index array
nuclear@0: aiFace( const aiFace& o)
nuclear@0: : mNumIndices(0)
nuclear@0: , mIndices( 0 ) {
nuclear@0: *this = o;
nuclear@0: }
nuclear@0:
nuclear@0: //! Assignment operator. Copy the index array
nuclear@0: aiFace& operator = ( const aiFace& o) {
nuclear@0: if (&o == this) {
nuclear@0: return *this;
nuclear@0: }
nuclear@0:
nuclear@0: delete[] mIndices;
nuclear@0: mNumIndices = o.mNumIndices;
nuclear@0: if (mNumIndices) {
nuclear@0: mIndices = new unsigned int[mNumIndices];
nuclear@0: ::memcpy( mIndices, o.mIndices, mNumIndices * sizeof( unsigned int));
nuclear@0: } else {
nuclear@0: mIndices = 0;
nuclear@0: }
nuclear@0:
nuclear@0: return *this;
nuclear@0: }
nuclear@0:
nuclear@0: //! Comparison operator. Checks whether the index array
nuclear@0: //! of two faces is identical
nuclear@0: bool operator== (const aiFace& o) const {
nuclear@0: if (mIndices == o.mIndices) {
nuclear@0: return true;
nuclear@0: }
nuclear@0:
nuclear@0: if (0 != mIndices && mNumIndices != o.mNumIndices) {
nuclear@0: return false;
nuclear@0: }
nuclear@0:
nuclear@0: if (0 == mIndices) {
nuclear@0: return false;
nuclear@0: }
nuclear@0:
nuclear@0: for (unsigned int i = 0; i < this->mNumIndices; ++i) {
nuclear@0: if (mIndices[i] != o.mIndices[i]) {
nuclear@0: return false;
nuclear@0: }
nuclear@0: }
nuclear@0:
nuclear@0: return true;
nuclear@0: }
nuclear@0:
nuclear@0: //! Inverse comparison operator. Checks whether the index
nuclear@0: //! array of two faces is NOT identical
nuclear@0: bool operator != (const aiFace& o) const {
nuclear@0: return !(*this == o);
nuclear@0: }
nuclear@0: #endif // __cplusplus
nuclear@0: }; // struct aiFace
nuclear@0:
nuclear@0:
nuclear@0: // ---------------------------------------------------------------------------
nuclear@0: /** @brief A single influence of a bone on a vertex.
nuclear@0: */
nuclear@0: struct aiVertexWeight {
nuclear@0: //! Index of the vertex which is influenced by the bone.
nuclear@0: unsigned int mVertexId;
nuclear@0:
nuclear@0: //! The strength of the influence in the range (0...1).
nuclear@0: //! The influence from all bones at one vertex amounts to 1.
nuclear@0: float mWeight;
nuclear@0:
nuclear@0: #ifdef __cplusplus
nuclear@0:
nuclear@0: //! Default constructor
nuclear@0: aiVertexWeight() AI_NO_EXCEPT
nuclear@0: : mVertexId(0)
nuclear@0: , mWeight(0.0f) {
nuclear@0: // empty
nuclear@0: }
nuclear@0:
nuclear@0: //! Initialization from a given index and vertex weight factor
nuclear@0: //! \param pID ID
nuclear@0: //! \param pWeight Vertex weight factor
nuclear@0: aiVertexWeight( unsigned int pID, float pWeight )
nuclear@0: : mVertexId( pID )
nuclear@0: , mWeight( pWeight ) {
nuclear@0: // empty
nuclear@0: }
nuclear@0:
nuclear@0: bool operator == ( const aiVertexWeight &rhs ) const {
nuclear@0: return ( mVertexId == rhs.mVertexId && mWeight == rhs.mWeight );
nuclear@0: }
nuclear@0:
nuclear@0: bool operator != ( const aiVertexWeight &rhs ) const {
nuclear@0: return ( *this == rhs );
nuclear@0: }
nuclear@0:
nuclear@0: #endif // __cplusplus
nuclear@0: };
nuclear@0:
nuclear@0:
nuclear@0: // ---------------------------------------------------------------------------
nuclear@0: /** @brief A single bone of a mesh.
nuclear@0: *
nuclear@0: * A bone has a name by which it can be found in the frame hierarchy and by
nuclear@0: * which it can be addressed by animations. In addition it has a number of
nuclear@0: * influences on vertices, and a matrix relating the mesh position to the
nuclear@0: * position of the bone at the time of binding.
nuclear@0: */
nuclear@0: struct aiBone {
nuclear@0: //! The name of the bone.
nuclear@0: C_STRUCT aiString mName;
nuclear@0:
nuclear@0: //! The number of vertices affected by this bone.
nuclear@0: //! The maximum value for this member is #AI_MAX_BONE_WEIGHTS.
nuclear@0: unsigned int mNumWeights;
nuclear@0:
nuclear@0: //! The influence weights of this bone, by vertex index.
nuclear@0: C_STRUCT aiVertexWeight* mWeights;
nuclear@0:
nuclear@0: /** Matrix that transforms from bone space to mesh space in bind pose.
nuclear@0: *
nuclear@0: * This matrix describes the position of the mesh
nuclear@0: * in the local space of this bone when the skeleton was bound.
nuclear@0: * Thus it can be used directly to determine a desired vertex position,
nuclear@0: * given the world-space transform of the bone when animated,
nuclear@0: * and the position of the vertex in mesh space.
nuclear@0: *
nuclear@0: * It is sometimes called an inverse-bind matrix,
nuclear@0: * or inverse bind pose matrix.
nuclear@0: */
nuclear@0: C_STRUCT aiMatrix4x4 mOffsetMatrix;
nuclear@0:
nuclear@0: #ifdef __cplusplus
nuclear@0:
nuclear@0: //! Default constructor
nuclear@0: aiBone() AI_NO_EXCEPT
nuclear@0: : mName()
nuclear@0: , mNumWeights( 0 )
nuclear@0: , mWeights( 0 )
nuclear@0: , mOffsetMatrix() {
nuclear@0: // empty
nuclear@0: }
nuclear@0:
nuclear@0: //! Copy constructor
nuclear@0: aiBone(const aiBone& other)
nuclear@0: : mName( other.mName )
nuclear@0: , mNumWeights( other.mNumWeights )
nuclear@0: , mWeights(0)
nuclear@0: , mOffsetMatrix( other.mOffsetMatrix ) {
nuclear@0: if (other.mWeights && other.mNumWeights) {
nuclear@0: mWeights = new aiVertexWeight[mNumWeights];
nuclear@0: ::memcpy(mWeights,other.mWeights,mNumWeights * sizeof(aiVertexWeight));
nuclear@0: }
nuclear@0: }
nuclear@0:
nuclear@0:
nuclear@0: //! Assignment operator
nuclear@0: aiBone &operator=(const aiBone& other) {
nuclear@0: if (this == &other) {
nuclear@0: return *this;
nuclear@0: }
nuclear@0:
nuclear@0: mName = other.mName;
nuclear@0: mNumWeights = other.mNumWeights;
nuclear@0: mOffsetMatrix = other.mOffsetMatrix;
nuclear@0:
nuclear@0: if (other.mWeights && other.mNumWeights)
nuclear@0: {
nuclear@0: if (mWeights) {
nuclear@0: delete[] mWeights;
nuclear@0: }
nuclear@0:
nuclear@0: mWeights = new aiVertexWeight[mNumWeights];
nuclear@0: ::memcpy(mWeights,other.mWeights,mNumWeights * sizeof(aiVertexWeight));
nuclear@0: }
nuclear@0:
nuclear@0: return *this;
nuclear@0: }
nuclear@0:
nuclear@0: bool operator == ( const aiBone &rhs ) const {
nuclear@0: if ( mName != rhs.mName || mNumWeights != rhs.mNumWeights ) {
nuclear@0: return false;
nuclear@0: }
nuclear@0:
nuclear@0: for ( size_t i = 0; i < mNumWeights; ++i ) {
nuclear@0: if ( mWeights[ i ] != rhs.mWeights[ i ] ) {
nuclear@0: return false;
nuclear@0: }
nuclear@0: }
nuclear@0:
nuclear@0: return true;
nuclear@0: }
nuclear@0: //! Destructor - deletes the array of vertex weights
nuclear@0: ~aiBone() {
nuclear@0: delete [] mWeights;
nuclear@0: }
nuclear@0: #endif // __cplusplus
nuclear@0: };
nuclear@0:
nuclear@0:
nuclear@0: // ---------------------------------------------------------------------------
nuclear@0: /** @brief Enumerates the types of geometric primitives supported by Assimp.
nuclear@0: *
nuclear@0: * @see aiFace Face data structure
nuclear@0: * @see aiProcess_SortByPType Per-primitive sorting of meshes
nuclear@0: * @see aiProcess_Triangulate Automatic triangulation
nuclear@0: * @see AI_CONFIG_PP_SBP_REMOVE Removal of specific primitive types.
nuclear@0: */
nuclear@0: enum aiPrimitiveType
nuclear@0: {
nuclear@0: /** A point primitive.
nuclear@0: *
nuclear@0: * This is just a single vertex in the virtual world,
nuclear@0: * #aiFace contains just one index for such a primitive.
nuclear@0: */
nuclear@0: aiPrimitiveType_POINT = 0x1,
nuclear@0:
nuclear@0: /** A line primitive.
nuclear@0: *
nuclear@0: * This is a line defined through a start and an end position.
nuclear@0: * #aiFace contains exactly two indices for such a primitive.
nuclear@0: */
nuclear@0: aiPrimitiveType_LINE = 0x2,
nuclear@0:
nuclear@0: /** A triangular primitive.
nuclear@0: *
nuclear@0: * A triangle consists of three indices.
nuclear@0: */
nuclear@0: aiPrimitiveType_TRIANGLE = 0x4,
nuclear@0:
nuclear@0: /** A higher-level polygon with more than 3 edges.
nuclear@0: *
nuclear@0: * A triangle is a polygon, but polygon in this context means
nuclear@0: * "all polygons that are not triangles". The "Triangulate"-Step
nuclear@0: * is provided for your convenience, it splits all polygons in
nuclear@0: * triangles (which are much easier to handle).
nuclear@0: */
nuclear@0: aiPrimitiveType_POLYGON = 0x8,
nuclear@0:
nuclear@0:
nuclear@0: /** This value is not used. It is just here to force the
nuclear@0: * compiler to map this enum to a 32 Bit integer.
nuclear@0: */
nuclear@0: #ifndef SWIG
nuclear@0: _aiPrimitiveType_Force32Bit = INT_MAX
nuclear@0: #endif
nuclear@0: }; //! enum aiPrimitiveType
nuclear@0:
nuclear@0: // Get the #aiPrimitiveType flag for a specific number of face indices
nuclear@0: #define AI_PRIMITIVE_TYPE_FOR_N_INDICES(n) \
nuclear@0: ((n) > 3 ? aiPrimitiveType_POLYGON : (aiPrimitiveType)(1u << ((n)-1)))
nuclear@0:
nuclear@0:
nuclear@0:
nuclear@0: // ---------------------------------------------------------------------------
nuclear@0: /** @brief An AnimMesh is an attachment to an #aiMesh stores per-vertex
nuclear@0: * animations for a particular frame.
nuclear@0: *
nuclear@0: * You may think of an #aiAnimMesh as a `patch` for the host mesh, which
nuclear@0: * replaces only certain vertex data streams at a particular time.
nuclear@0: * Each mesh stores n attached attached meshes (#aiMesh::mAnimMeshes).
nuclear@0: * The actual relationship between the time line and anim meshes is
nuclear@0: * established by #aiMeshAnim, which references singular mesh attachments
nuclear@0: * by their ID and binds them to a time offset.
nuclear@0: */
nuclear@0: struct aiAnimMesh
nuclear@0: {
nuclear@0: /**Anim Mesh name */
nuclear@0: C_STRUCT aiString mName;
nuclear@0:
nuclear@0: /** Replacement for aiMesh::mVertices. If this array is non-NULL,
nuclear@0: * it *must* contain mNumVertices entries. The corresponding
nuclear@0: * array in the host mesh must be non-NULL as well - animation
nuclear@0: * meshes may neither add or nor remove vertex components (if
nuclear@0: * a replacement array is NULL and the corresponding source
nuclear@0: * array is not, the source data is taken instead)*/
nuclear@0: C_STRUCT aiVector3D* mVertices;
nuclear@0:
nuclear@0: /** Replacement for aiMesh::mNormals. */
nuclear@0: C_STRUCT aiVector3D* mNormals;
nuclear@0:
nuclear@0: /** Replacement for aiMesh::mTangents. */
nuclear@0: C_STRUCT aiVector3D* mTangents;
nuclear@0:
nuclear@0: /** Replacement for aiMesh::mBitangents. */
nuclear@0: C_STRUCT aiVector3D* mBitangents;
nuclear@0:
nuclear@0: /** Replacement for aiMesh::mColors */
nuclear@0: C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
nuclear@0:
nuclear@0: /** Replacement for aiMesh::mTextureCoords */
nuclear@0: C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
nuclear@0:
nuclear@0: /** The number of vertices in the aiAnimMesh, and thus the length of all
nuclear@0: * the member arrays.
nuclear@0: *
nuclear@0: * This has always the same value as the mNumVertices property in the
nuclear@0: * corresponding aiMesh. It is duplicated here merely to make the length
nuclear@0: * of the member arrays accessible even if the aiMesh is not known, e.g.
nuclear@0: * from language bindings.
nuclear@0: */
nuclear@0: unsigned int mNumVertices;
nuclear@0:
nuclear@0: /**
nuclear@0: * Weight of the AnimMesh.
nuclear@0: */
nuclear@0: float mWeight;
nuclear@0:
nuclear@0: #ifdef __cplusplus
nuclear@0:
nuclear@0: aiAnimMesh() AI_NO_EXCEPT
nuclear@0: : mVertices( 0 )
nuclear@0: , mNormals(0)
nuclear@0: , mTangents(0)
nuclear@0: , mBitangents(0)
nuclear@0: , mColors()
nuclear@0: , mTextureCoords()
nuclear@0: , mNumVertices( 0 )
nuclear@0: , mWeight( 0.0f )
nuclear@0: {
nuclear@0: // fixme consider moving this to the ctor initializer list as well
nuclear@0: for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++){
nuclear@0: mTextureCoords[a] = NULL;
nuclear@0: }
nuclear@0: for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
nuclear@0: mColors[a] = NULL;
nuclear@0: }
nuclear@0: }
nuclear@0:
nuclear@0: ~aiAnimMesh()
nuclear@0: {
nuclear@0: delete [] mVertices;
nuclear@0: delete [] mNormals;
nuclear@0: delete [] mTangents;
nuclear@0: delete [] mBitangents;
nuclear@0: for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
nuclear@0: delete [] mTextureCoords[a];
nuclear@0: }
nuclear@0: for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
nuclear@0: delete [] mColors[a];
nuclear@0: }
nuclear@0: }
nuclear@0:
nuclear@0: /** Check whether the anim mesh overrides the vertex positions
nuclear@0: * of its host mesh*/
nuclear@0: bool HasPositions() const {
nuclear@0: return mVertices != NULL;
nuclear@0: }
nuclear@0:
nuclear@0: /** Check whether the anim mesh overrides the vertex normals
nuclear@0: * of its host mesh*/
nuclear@0: bool HasNormals() const {
nuclear@0: return mNormals != NULL;
nuclear@0: }
nuclear@0:
nuclear@0: /** Check whether the anim mesh overrides the vertex tangents
nuclear@0: * and bitangents of its host mesh. As for aiMesh,
nuclear@0: * tangents and bitangents always go together. */
nuclear@0: bool HasTangentsAndBitangents() const {
nuclear@0: return mTangents != NULL;
nuclear@0: }
nuclear@0:
nuclear@0: /** Check whether the anim mesh overrides a particular
nuclear@0: * set of vertex colors on his host mesh.
nuclear@0: * @param pIndex 0= AI_MAX_NUMBER_OF_COLOR_SETS ? false : mColors[pIndex] != NULL;
nuclear@0: }
nuclear@0:
nuclear@0: /** Check whether the anim mesh overrides a particular
nuclear@0: * set of texture coordinates on his host mesh.
nuclear@0: * @param pIndex 0= AI_MAX_NUMBER_OF_TEXTURECOORDS ? false : mTextureCoords[pIndex] != NULL;
nuclear@0: }
nuclear@0:
nuclear@0: #endif
nuclear@0: };
nuclear@0:
nuclear@0: // ---------------------------------------------------------------------------
nuclear@0: /** @brief Enumerates the methods of mesh morphing supported by Assimp.
nuclear@0: */
nuclear@0: enum aiMorphingMethod
nuclear@0: {
nuclear@0: /** Interpolation between morph targets */
nuclear@0: aiMorphingMethod_VERTEX_BLEND = 0x1,
nuclear@0:
nuclear@0: /** Normalized morphing between morph targets */
nuclear@0: aiMorphingMethod_MORPH_NORMALIZED = 0x2,
nuclear@0:
nuclear@0: /** Relative morphing between morph targets */
nuclear@0: aiMorphingMethod_MORPH_RELATIVE = 0x3,
nuclear@0:
nuclear@0: /** This value is not used. It is just here to force the
nuclear@0: * compiler to map this enum to a 32 Bit integer.
nuclear@0: */
nuclear@0: #ifndef SWIG
nuclear@0: _aiMorphingMethod_Force32Bit = INT_MAX
nuclear@0: #endif
nuclear@0: }; //! enum aiMorphingMethod
nuclear@0:
nuclear@0: // ---------------------------------------------------------------------------
nuclear@0: /** @brief A mesh represents a geometry or model with a single material.
nuclear@0: *
nuclear@0: * It usually consists of a number of vertices and a series of primitives/faces
nuclear@0: * referencing the vertices. In addition there might be a series of bones, each
nuclear@0: * of them addressing a number of vertices with a certain weight. Vertex data
nuclear@0: * is presented in channels with each channel containing a single per-vertex
nuclear@0: * information such as a set of texture coords or a normal vector.
nuclear@0: * If a data pointer is non-null, the corresponding data stream is present.
nuclear@0: * From C++-programs you can also use the comfort functions Has*() to
nuclear@0: * test for the presence of various data streams.
nuclear@0: *
nuclear@0: * A Mesh uses only a single material which is referenced by a material ID.
nuclear@0: * @note The mPositions member is usually not optional. However, vertex positions
nuclear@0: * *could* be missing if the #AI_SCENE_FLAGS_INCOMPLETE flag is set in
nuclear@0: * @code
nuclear@0: * aiScene::mFlags
nuclear@0: * @endcode
nuclear@0: */
nuclear@0: struct aiMesh
nuclear@0: {
nuclear@0: /** Bitwise combination of the members of the #aiPrimitiveType enum.
nuclear@0: * This specifies which types of primitives are present in the mesh.
nuclear@0: * The "SortByPrimitiveType"-Step can be used to make sure the
nuclear@0: * output meshes consist of one primitive type each.
nuclear@0: */
nuclear@0: unsigned int mPrimitiveTypes;
nuclear@0:
nuclear@0: /** The number of vertices in this mesh.
nuclear@0: * This is also the size of all of the per-vertex data arrays.
nuclear@0: * The maximum value for this member is #AI_MAX_VERTICES.
nuclear@0: */
nuclear@0: unsigned int mNumVertices;
nuclear@0:
nuclear@0: /** The number of primitives (triangles, polygons, lines) in this mesh.
nuclear@0: * This is also the size of the mFaces array.
nuclear@0: * The maximum value for this member is #AI_MAX_FACES.
nuclear@0: */
nuclear@0: unsigned int mNumFaces;
nuclear@0:
nuclear@0: /** Vertex positions.
nuclear@0: * This array is always present in a mesh. The array is
nuclear@0: * mNumVertices in size.
nuclear@0: */
nuclear@0: C_STRUCT aiVector3D* mVertices;
nuclear@0:
nuclear@0: /** Vertex normals.
nuclear@0: * The array contains normalized vectors, NULL if not present.
nuclear@0: * The array is mNumVertices in size. Normals are undefined for
nuclear@0: * point and line primitives. A mesh consisting of points and
nuclear@0: * lines only may not have normal vectors. Meshes with mixed
nuclear@0: * primitive types (i.e. lines and triangles) may have normals,
nuclear@0: * but the normals for vertices that are only referenced by
nuclear@0: * point or line primitives are undefined and set to QNaN (WARN:
nuclear@0: * qNaN compares to inequal to *everything*, even to qNaN itself.
nuclear@0: * Using code like this to check whether a field is qnan is:
nuclear@0: * @code
nuclear@0: * #define IS_QNAN(f) (f != f)
nuclear@0: * @endcode
nuclear@0: * still dangerous because even 1.f == 1.f could evaluate to false! (
nuclear@0: * remember the subtleties of IEEE754 artithmetics). Use stuff like
nuclear@0: * @c fpclassify instead.
nuclear@0: * @note Normal vectors computed by Assimp are always unit-length.
nuclear@0: * However, this needn't apply for normals that have been taken
nuclear@0: * directly from the model file.
nuclear@0: */
nuclear@0: C_STRUCT aiVector3D* mNormals;
nuclear@0:
nuclear@0: /** Vertex tangents.
nuclear@0: * The tangent of a vertex points in the direction of the positive
nuclear@0: * X texture axis. The array contains normalized vectors, NULL if
nuclear@0: * not present. The array is mNumVertices in size. A mesh consisting
nuclear@0: * of points and lines only may not have normal vectors. Meshes with
nuclear@0: * mixed primitive types (i.e. lines and triangles) may have
nuclear@0: * normals, but the normals for vertices that are only referenced by
nuclear@0: * point or line primitives are undefined and set to qNaN. See
nuclear@0: * the #mNormals member for a detailed discussion of qNaNs.
nuclear@0: * @note If the mesh contains tangents, it automatically also
nuclear@0: * contains bitangents.
nuclear@0: */
nuclear@0: C_STRUCT aiVector3D* mTangents;
nuclear@0:
nuclear@0: /** Vertex bitangents.
nuclear@0: * The bitangent of a vertex points in the direction of the positive
nuclear@0: * Y texture axis. The array contains normalized vectors, NULL if not
nuclear@0: * present. The array is mNumVertices in size.
nuclear@0: * @note If the mesh contains tangents, it automatically also contains
nuclear@0: * bitangents.
nuclear@0: */
nuclear@0: C_STRUCT aiVector3D* mBitangents;
nuclear@0:
nuclear@0: /** Vertex color sets.
nuclear@0: * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex
nuclear@0: * colors per vertex. NULL if not present. Each array is
nuclear@0: * mNumVertices in size if present.
nuclear@0: */
nuclear@0: C_STRUCT aiColor4D* mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
nuclear@0:
nuclear@0: /** Vertex texture coords, also known as UV channels.
nuclear@0: * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS per
nuclear@0: * vertex. NULL if not present. The array is mNumVertices in size.
nuclear@0: */
nuclear@0: C_STRUCT aiVector3D* mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
nuclear@0:
nuclear@0: /** Specifies the number of components for a given UV channel.
nuclear@0: * Up to three channels are supported (UVW, for accessing volume
nuclear@0: * or cube maps). If the value is 2 for a given channel n, the
nuclear@0: * component p.z of mTextureCoords[n][p] is set to 0.0f.
nuclear@0: * If the value is 1 for a given channel, p.y is set to 0.0f, too.
nuclear@0: * @note 4D coords are not supported
nuclear@0: */
nuclear@0: unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
nuclear@0:
nuclear@0: /** The faces the mesh is constructed from.
nuclear@0: * Each face refers to a number of vertices by their indices.
nuclear@0: * This array is always present in a mesh, its size is given
nuclear@0: * in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
nuclear@0: * is NOT set each face references an unique set of vertices.
nuclear@0: */
nuclear@0: C_STRUCT aiFace* mFaces;
nuclear@0:
nuclear@0: /** The number of bones this mesh contains.
nuclear@0: * Can be 0, in which case the mBones array is NULL.
nuclear@0: */
nuclear@0: unsigned int mNumBones;
nuclear@0:
nuclear@0: /** The bones of this mesh.
nuclear@0: * A bone consists of a name by which it can be found in the
nuclear@0: * frame hierarchy and a set of vertex weights.
nuclear@0: */
nuclear@0: C_STRUCT aiBone** mBones;
nuclear@0:
nuclear@0: /** The material used by this mesh.
nuclear@0: * A mesh uses only a single material. If an imported model uses
nuclear@0: * multiple materials, the import splits up the mesh. Use this value
nuclear@0: * as index into the scene's material list.
nuclear@0: */
nuclear@0: unsigned int mMaterialIndex;
nuclear@0:
nuclear@0: /** Name of the mesh. Meshes can be named, but this is not a
nuclear@0: * requirement and leaving this field empty is totally fine.
nuclear@0: * There are mainly three uses for mesh names:
nuclear@0: * - some formats name nodes and meshes independently.
nuclear@0: * - importers tend to split meshes up to meet the
nuclear@0: * one-material-per-mesh requirement. Assigning
nuclear@0: * the same (dummy) name to each of the result meshes
nuclear@0: * aids the caller at recovering the original mesh
nuclear@0: * partitioning.
nuclear@0: * - Vertex animations refer to meshes by their names.
nuclear@0: **/
nuclear@0: C_STRUCT aiString mName;
nuclear@0:
nuclear@0:
nuclear@0: /** The number of attachment meshes. Note! Currently only works with Collada loader. */
nuclear@0: unsigned int mNumAnimMeshes;
nuclear@0:
nuclear@0: /** Attachment meshes for this mesh, for vertex-based animation.
nuclear@0: * Attachment meshes carry replacement data for some of the
nuclear@0: * mesh'es vertex components (usually positions, normals).
nuclear@0: * Note! Currently only works with Collada loader.*/
nuclear@0: C_STRUCT aiAnimMesh** mAnimMeshes;
nuclear@0:
nuclear@0: /**
nuclear@0: * Method of morphing when animeshes are specified.
nuclear@0: */
nuclear@0: unsigned int mMethod;
nuclear@0:
nuclear@0: #ifdef __cplusplus
nuclear@0:
nuclear@0: //! Default constructor. Initializes all members to 0
nuclear@0: aiMesh() AI_NO_EXCEPT
nuclear@0: : mPrimitiveTypes( 0 )
nuclear@0: , mNumVertices( 0 )
nuclear@0: , mNumFaces( 0 )
nuclear@0: , mVertices( 0 )
nuclear@0: , mNormals(0)
nuclear@0: , mTangents(0)
nuclear@0: , mBitangents(0)
nuclear@0: , mColors()
nuclear@0: , mTextureCoords()
nuclear@0: , mNumUVComponents()
nuclear@0: , mFaces(0)
nuclear@0: , mNumBones( 0 )
nuclear@0: , mBones(0)
nuclear@0: , mMaterialIndex( 0 )
nuclear@0: , mNumAnimMeshes( 0 )
nuclear@0: , mAnimMeshes(0)
nuclear@0: , mMethod( 0 ) {
nuclear@0: for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) {
nuclear@0: mNumUVComponents[a] = 0;
nuclear@0: mTextureCoords[a] = 0;
nuclear@0: }
nuclear@0:
nuclear@0: for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) {
nuclear@0: mColors[a] = 0;
nuclear@0: }
nuclear@0: }
nuclear@0:
nuclear@0: //! Deletes all storage allocated for the mesh
nuclear@0: ~aiMesh() {
nuclear@0: delete [] mVertices;
nuclear@0: delete [] mNormals;
nuclear@0: delete [] mTangents;
nuclear@0: delete [] mBitangents;
nuclear@0: for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
nuclear@0: delete [] mTextureCoords[a];
nuclear@0: }
nuclear@0: for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
nuclear@0: delete [] mColors[a];
nuclear@0: }
nuclear@0:
nuclear@0: // DO NOT REMOVE THIS ADDITIONAL CHECK
nuclear@0: if (mNumBones && mBones) {
nuclear@0: for( unsigned int a = 0; a < mNumBones; a++) {
nuclear@0: delete mBones[a];
nuclear@0: }
nuclear@0: delete [] mBones;
nuclear@0: }
nuclear@0:
nuclear@0: if (mNumAnimMeshes && mAnimMeshes) {
nuclear@0: for( unsigned int a = 0; a < mNumAnimMeshes; a++) {
nuclear@0: delete mAnimMeshes[a];
nuclear@0: }
nuclear@0: delete [] mAnimMeshes;
nuclear@0: }
nuclear@0:
nuclear@0: delete [] mFaces;
nuclear@0: }
nuclear@0:
nuclear@0: //! Check whether the mesh contains positions. Provided no special
nuclear@0: //! scene flags are set, this will always be true
nuclear@0: bool HasPositions() const
nuclear@0: { return mVertices != 0 && mNumVertices > 0; }
nuclear@0:
nuclear@0: //! Check whether the mesh contains faces. If no special scene flags
nuclear@0: //! are set this should always return true
nuclear@0: bool HasFaces() const
nuclear@0: { return mFaces != 0 && mNumFaces > 0; }
nuclear@0:
nuclear@0: //! Check whether the mesh contains normal vectors
nuclear@0: bool HasNormals() const
nuclear@0: { return mNormals != 0 && mNumVertices > 0; }
nuclear@0:
nuclear@0: //! Check whether the mesh contains tangent and bitangent vectors
nuclear@0: //! It is not possible that it contains tangents and no bitangents
nuclear@0: //! (or the other way round). The existence of one of them
nuclear@0: //! implies that the second is there, too.
nuclear@0: bool HasTangentsAndBitangents() const
nuclear@0: { return mTangents != 0 && mBitangents != 0 && mNumVertices > 0; }
nuclear@0:
nuclear@0: //! Check whether the mesh contains a vertex color set
nuclear@0: //! \param pIndex Index of the vertex color set
nuclear@0: bool HasVertexColors( unsigned int pIndex) const {
nuclear@0: if (pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS) {
nuclear@0: return false;
nuclear@0: } else {
nuclear@0: return mColors[pIndex] != 0 && mNumVertices > 0;
nuclear@0: }
nuclear@0: }
nuclear@0:
nuclear@0: //! Check whether the mesh contains a texture coordinate set
nuclear@0: //! \param pIndex Index of the texture coordinates set
nuclear@0: bool HasTextureCoords( unsigned int pIndex) const {
nuclear@0: if (pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
nuclear@0: return false;
nuclear@0: } else {
nuclear@0: return mTextureCoords[pIndex] != 0 && mNumVertices > 0;
nuclear@0: }
nuclear@0: }
nuclear@0:
nuclear@0: //! Get the number of UV channels the mesh contains
nuclear@0: unsigned int GetNumUVChannels() const {
nuclear@0: unsigned int n( 0 );
nuclear@0: while (n < AI_MAX_NUMBER_OF_TEXTURECOORDS && mTextureCoords[n]) {
nuclear@0: ++n;
nuclear@0: }
nuclear@0:
nuclear@0: return n;
nuclear@0: }
nuclear@0:
nuclear@0: //! Get the number of vertex color channels the mesh contains
nuclear@0: unsigned int GetNumColorChannels() const {
nuclear@0: unsigned int n(0);
nuclear@0: while (n < AI_MAX_NUMBER_OF_COLOR_SETS && mColors[n]) {
nuclear@0: ++n;
nuclear@0: }
nuclear@0: return n;
nuclear@0: }
nuclear@0:
nuclear@0: //! Check whether the mesh contains bones
nuclear@0: bool HasBones() const {
nuclear@0: return mBones != 0 && mNumBones > 0;
nuclear@0: }
nuclear@0:
nuclear@0: #endif // __cplusplus
nuclear@0: };
nuclear@0:
nuclear@0: #ifdef __cplusplus
nuclear@0: }
nuclear@0: #endif //! extern "C"
nuclear@0: #endif // AI_MESH_H_INC
nuclear@0: