1/*
2---------------------------------------------------------------------------
3Open Asset Import Library (assimp)
4---------------------------------------------------------------------------
5
6Copyright (c) 2006-2024, assimp team
7
8All rights reserved.
9
10Redistribution and use of this software in source and binary forms,
11with or without modification, are permitted provided that the following
12conditions are met:
13
14* Redistributions of source code must retain the above
15 copyright notice, this list of conditions and the
16 following disclaimer.
17
18* Redistributions in binary form must reproduce the above
19 copyright notice, this list of conditions and the
20 following disclaimer in the documentation and/or other
21 materials provided with the distribution.
22
23* Neither the name of the assimp team, nor the names of its
24 contributors may be used to endorse or promote products
25 derived from this software without specific prior
26 written permission of the assimp team.
27
28THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39---------------------------------------------------------------------------
40*/
41
42/** @file mesh.h
43 * @brief Declares the data structures in which the imported geometry is
44 returned by ASSIMP: aiMesh, aiFace and aiBone data structures.
45 */
46#pragma once
47#ifndef AI_MESH_H_INC
48#define AI_MESH_H_INC
49
50#ifdef __GNUC__
51#pragma GCC system_header
52#endif
53
54#ifdef _MSC_VER
55#pragma warning(disable : 4351)
56#endif // _MSC_VER
57
58#include <assimp/aabb.h>
59#include <assimp/types.h>
60
61#ifdef __cplusplus
62#include <unordered_set>
63
64extern "C" {
65#endif
66
67// ---------------------------------------------------------------------------
68// Limits. These values are required to match the settings Assimp was
69// compiled against. Therefore, do not redefine them unless you build the
70// library from source using the same definitions.
71// ---------------------------------------------------------------------------
72
73/** @def AI_MAX_FACE_INDICES
74 * Maximum number of indices per face (polygon). */
75
76#ifndef AI_MAX_FACE_INDICES
77#define AI_MAX_FACE_INDICES 0x7fff
78#endif
79
80/** @def AI_MAX_BONE_WEIGHTS
81 * Maximum number of indices per face (polygon). */
82
83#ifndef AI_MAX_BONE_WEIGHTS
84#define AI_MAX_BONE_WEIGHTS 0x7fffffff
85#endif
86
87/** @def AI_MAX_VERTICES
88 * Maximum number of vertices per mesh. */
89
90#ifndef AI_MAX_VERTICES
91#define AI_MAX_VERTICES 0x7fffffff
92#endif
93
94/** @def AI_MAX_FACES
95 * Maximum number of faces per mesh. */
96
97#ifndef AI_MAX_FACES
98#define AI_MAX_FACES 0x7fffffff
99#endif
100
101/** @def AI_MAX_NUMBER_OF_COLOR_SETS
102 * Supported number of vertex color sets per mesh. */
103
104#ifndef AI_MAX_NUMBER_OF_COLOR_SETS
105#define AI_MAX_NUMBER_OF_COLOR_SETS 0x8
106#endif // !! AI_MAX_NUMBER_OF_COLOR_SETS
107
108/** @def AI_MAX_NUMBER_OF_TEXTURECOORDS
109 * Supported number of texture coord sets (UV(W) channels) per mesh */
110
111#ifndef AI_MAX_NUMBER_OF_TEXTURECOORDS
112#define AI_MAX_NUMBER_OF_TEXTURECOORDS 0x8
113#endif // !! AI_MAX_NUMBER_OF_TEXTURECOORDS
114
115// ---------------------------------------------------------------------------
116/**
117 * @brief A single face in a mesh, referring to multiple vertices.
118 *
119 * If mNumIndices is 3, we call the face 'triangle', for mNumIndices > 3
120 * it's called 'polygon' (hey, that's just a definition!).
121 * <br>
122 * aiMesh::mPrimitiveTypes can be queried to quickly examine which types of
123 * primitive are actually present in a mesh. The #aiProcess_SortByPType flag
124 * executes a special post-processing algorithm which splits meshes with
125 * *different* primitive types mixed up (e.g. lines and triangles) in several
126 * 'clean' sub-meshes. Furthermore there is a configuration option (
127 * #AI_CONFIG_PP_SBP_REMOVE) to force #aiProcess_SortByPType to remove
128 * specific kinds of primitives from the imported scene, completely and forever.
129 * In many cases you'll probably want to set this setting to
130 * @code
131 * aiPrimitiveType_LINE|aiPrimitiveType_POINT
132 * @endcode
133 * Together with the #aiProcess_Triangulate flag you can then be sure that
134 * #aiFace::mNumIndices is always 3.
135 * @note Take a look at the @link data Data Structures page @endlink for
136 * more information on the layout and winding order of a face.
137 */
138struct aiFace {
139 //! Number of indices defining this face.
140 //! The maximum value for this member is #AI_MAX_FACE_INDICES.
141 unsigned int mNumIndices;
142
143 //! Pointer to the indices array. Size of the array is given in numIndices.
144 unsigned int *mIndices;
145
146#ifdef __cplusplus
147
148 //! @brief Default constructor.
149 aiFace() AI_NO_EXCEPT
150 : mNumIndices(0),
151 mIndices(nullptr) {
152 // empty
153 }
154
155 //! @brief Default destructor. Delete the index array
156 ~aiFace() {
157 delete[] mIndices;
158 }
159
160 //! @brief Copy constructor. Copy the index array
161 aiFace(const aiFace &o) :
162 mNumIndices(0), mIndices(nullptr) {
163 *this = o;
164 }
165
166 //! @brief Assignment operator. Copy the index array
167 aiFace &operator=(const aiFace &o) {
168 if (&o == this) {
169 return *this;
170 }
171
172 delete[] mIndices;
173 mNumIndices = o.mNumIndices;
174 if (mNumIndices) {
175 mIndices = new unsigned int[mNumIndices];
176 ::memcpy(dest: mIndices, src: o.mIndices, n: mNumIndices * sizeof(unsigned int));
177 } else {
178 mIndices = nullptr;
179 }
180
181 return *this;
182 }
183
184 //! @brief Comparison operator. Checks whether the index array of two faces is identical.
185 bool operator==(const aiFace &o) const {
186 if (mIndices == o.mIndices) {
187 return true;
188 }
189
190 if (nullptr != mIndices && mNumIndices != o.mNumIndices) {
191 return false;
192 }
193
194 if (nullptr == mIndices) {
195 return false;
196 }
197
198 for (unsigned int i = 0; i < this->mNumIndices; ++i) {
199 if (mIndices[i] != o.mIndices[i]) {
200 return false;
201 }
202 }
203
204 return true;
205 }
206
207 //! @brief Inverse comparison operator. Checks whether the index
208 //! array of two faces is NOT identical
209 bool operator!=(const aiFace &o) const {
210 return !(*this == o);
211 }
212#endif // __cplusplus
213}; // struct aiFace
214
215// ---------------------------------------------------------------------------
216/** @brief A single influence of a bone on a vertex.
217 */
218struct aiVertexWeight {
219 //! Index of the vertex which is influenced by the bone.
220 unsigned int mVertexId;
221
222 //! The strength of the influence in the range (0...1).
223 //! The influence from all bones at one vertex amounts to 1.
224 ai_real mWeight;
225
226#ifdef __cplusplus
227
228 //! @brief Default constructor
229 aiVertexWeight() AI_NO_EXCEPT
230 : mVertexId(0),
231 mWeight(0.0f) {
232 // empty
233 }
234
235 //! @brief Initialization from a given index and vertex weight factor
236 //! \param pID ID
237 //! \param pWeight Vertex weight factor
238 aiVertexWeight(unsigned int pID, float pWeight) :
239 mVertexId(pID), mWeight(pWeight) {
240 // empty
241 }
242
243 bool operator==(const aiVertexWeight &rhs) const {
244 return (mVertexId == rhs.mVertexId && mWeight == rhs.mWeight);
245 }
246
247 bool operator!=(const aiVertexWeight &rhs) const {
248 return (*this == rhs);
249 }
250
251#endif // __cplusplus
252};
253
254// Forward declare aiNode (pointer use only)
255struct aiNode;
256
257// ---------------------------------------------------------------------------
258/** @brief A single bone of a mesh.
259 *
260 * A bone has a name by which it can be found in the frame hierarchy and by
261 * which it can be addressed by animations. In addition it has a number of
262 * influences on vertices, and a matrix relating the mesh position to the
263 * position of the bone at the time of binding.
264 */
265struct aiBone {
266 /**
267 * The name of the bone.
268 */
269 C_STRUCT aiString mName;
270
271 /**
272 * The number of vertices affected by this bone.
273 * The maximum value for this member is #AI_MAX_BONE_WEIGHTS.
274 */
275 unsigned int mNumWeights;
276
277#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
278 /**
279 * The bone armature node - used for skeleton conversion
280 * you must enable aiProcess_PopulateArmatureData to populate this
281 */
282 C_STRUCT aiNode *mArmature;
283
284 /**
285 * The bone node in the scene - used for skeleton conversion
286 * you must enable aiProcess_PopulateArmatureData to populate this
287 */
288 C_STRUCT aiNode *mNode;
289
290#endif
291 /**
292 * The influence weights of this bone, by vertex index.
293 */
294 C_STRUCT aiVertexWeight *mWeights;
295
296 /**
297 * Matrix that transforms from mesh space to bone space in bind pose.
298 *
299 * This matrix describes the position of the mesh
300 * in the local space of this bone when the skeleton was bound.
301 * Thus it can be used directly to determine a desired vertex position,
302 * given the world-space transform of the bone when animated,
303 * and the position of the vertex in mesh space.
304 *
305 * It is sometimes called an inverse-bind matrix,
306 * or inverse bind pose matrix.
307 */
308 C_STRUCT aiMatrix4x4 mOffsetMatrix;
309
310#ifdef __cplusplus
311
312 /// @brief Default constructor
313 aiBone() AI_NO_EXCEPT
314 : mName(),
315 mNumWeights(0),
316#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
317 mArmature(nullptr),
318 mNode(nullptr),
319#endif
320 mWeights(nullptr),
321 mOffsetMatrix() {
322 // empty
323 }
324
325 /// @brief Copy constructor
326 aiBone(const aiBone &other) :
327 mName(other.mName),
328 mNumWeights(other.mNumWeights),
329#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
330 mArmature(nullptr),
331 mNode(nullptr),
332#endif
333 mWeights(nullptr),
334 mOffsetMatrix(other.mOffsetMatrix) {
335 copyVertexWeights(other);
336 }
337
338 void copyVertexWeights( const aiBone &other ) {
339 if (other.mWeights == nullptr || other.mNumWeights == 0) {
340 mWeights = nullptr;
341 mNumWeights = 0;
342 return;
343 }
344
345 mNumWeights = other.mNumWeights;
346 if (mWeights) {
347 delete[] mWeights;
348 }
349
350 mWeights = new aiVertexWeight[mNumWeights];
351 ::memcpy(dest: mWeights, src: other.mWeights, n: mNumWeights * sizeof(aiVertexWeight));
352 }
353
354 //! @brief Assignment operator
355 aiBone &operator = (const aiBone &other) {
356 if (this == &other) {
357 return *this;
358 }
359
360 mName = other.mName;
361 mNumWeights = other.mNumWeights;
362 mOffsetMatrix = other.mOffsetMatrix;
363 copyVertexWeights(other);
364
365 return *this;
366 }
367
368 /// @brief Compare operator.
369 bool operator==(const aiBone &rhs) const {
370 if (mName != rhs.mName || mNumWeights != rhs.mNumWeights ) {
371 return false;
372 }
373
374 for (size_t i = 0; i < mNumWeights; ++i) {
375 if (mWeights[i] != rhs.mWeights[i]) {
376 return false;
377 }
378 }
379
380 return true;
381 }
382 //! @brief Destructor - deletes the array of vertex weights
383 ~aiBone() {
384 delete[] mWeights;
385 }
386#endif // __cplusplus
387};
388
389// ---------------------------------------------------------------------------
390/** @brief Enumerates the types of geometric primitives supported by Assimp.
391 *
392 * @see aiFace Face data structure
393 * @see aiProcess_SortByPType Per-primitive sorting of meshes
394 * @see aiProcess_Triangulate Automatic triangulation
395 * @see AI_CONFIG_PP_SBP_REMOVE Removal of specific primitive types.
396 */
397enum aiPrimitiveType {
398 /**
399 * @brief A point primitive.
400 *
401 * This is just a single vertex in the virtual world,
402 * #aiFace contains just one index for such a primitive.
403 */
404 aiPrimitiveType_POINT = 0x1,
405
406 /**
407 * @brief A line primitive.
408 *
409 * This is a line defined through a start and an end position.
410 * #aiFace contains exactly two indices for such a primitive.
411 */
412 aiPrimitiveType_LINE = 0x2,
413
414 /**
415 * @brief A triangular primitive.
416 *
417 * A triangle consists of three indices.
418 */
419 aiPrimitiveType_TRIANGLE = 0x4,
420
421 /**
422 * @brief A higher-level polygon with more than 3 edges.
423 *
424 * A triangle is a polygon, but polygon in this context means
425 * "all polygons that are not triangles". The "Triangulate"-Step
426 * is provided for your convenience, it splits all polygons in
427 * triangles (which are much easier to handle).
428 */
429 aiPrimitiveType_POLYGON = 0x8,
430
431 /**
432 * @brief A flag to determine whether this triangles only mesh is NGON encoded.
433 *
434 * NGON encoding is a special encoding that tells whether 2 or more consecutive triangles
435 * should be considered as a triangle fan. This is identified by looking at the first vertex index.
436 * 2 consecutive triangles with the same 1st vertex index are part of the same
437 * NGON.
438 *
439 * At the moment, only quads (concave or convex) are supported, meaning that polygons are 'seen' as
440 * triangles, as usual after a triangulation pass.
441 *
442 * To get an NGON encoded mesh, please use the aiProcess_Triangulate post process.
443 *
444 * @see aiProcess_Triangulate
445 * @link https://github.com/KhronosGroup/glTF/pull/1620
446 */
447 aiPrimitiveType_NGONEncodingFlag = 0x10,
448
449 /**
450 * This value is not used. It is just here to force the
451 * compiler to map this enum to a 32 Bit integer.
452 */
453#ifndef SWIG
454 _aiPrimitiveType_Force32Bit = INT_MAX
455#endif
456}; //! enum aiPrimitiveType
457
458// Get the #aiPrimitiveType flag for a specific number of face indices
459#define AI_PRIMITIVE_TYPE_FOR_N_INDICES(n) \
460 ((n) > 3 ? aiPrimitiveType_POLYGON : (aiPrimitiveType)(1u << ((n)-1)))
461
462// ---------------------------------------------------------------------------
463/** @brief An AnimMesh is an attachment to an #aiMesh stores per-vertex
464 * animations for a particular frame.
465 *
466 * You may think of an #aiAnimMesh as a `patch` for the host mesh, which
467 * replaces only certain vertex data streams at a particular time.
468 * Each mesh stores n attached attached meshes (#aiMesh::mAnimMeshes).
469 * The actual relationship between the time line and anim meshes is
470 * established by #aiMeshAnim, which references singular mesh attachments
471 * by their ID and binds them to a time offset.
472*/
473struct aiAnimMesh {
474 /**Anim Mesh name */
475 C_STRUCT aiString mName;
476
477 /** Replacement for aiMesh::mVertices. If this array is non-nullptr,
478 * it *must* contain mNumVertices entries. The corresponding
479 * array in the host mesh must be non-nullptr as well - animation
480 * meshes may neither add or nor remove vertex components (if
481 * a replacement array is nullptr and the corresponding source
482 * array is not, the source data is taken instead)*/
483 C_STRUCT aiVector3D *mVertices;
484
485 /** Replacement for aiMesh::mNormals. */
486 C_STRUCT aiVector3D *mNormals;
487
488 /** Replacement for aiMesh::mTangents. */
489 C_STRUCT aiVector3D *mTangents;
490
491 /** Replacement for aiMesh::mBitangents. */
492 C_STRUCT aiVector3D *mBitangents;
493
494 /** Replacement for aiMesh::mColors */
495 C_STRUCT aiColor4D *mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
496
497 /** Replacement for aiMesh::mTextureCoords */
498 C_STRUCT aiVector3D *mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
499
500 /** The number of vertices in the aiAnimMesh, and thus the length of all
501 * the member arrays.
502 *
503 * This has always the same value as the mNumVertices property in the
504 * corresponding aiMesh. It is duplicated here merely to make the length
505 * of the member arrays accessible even if the aiMesh is not known, e.g.
506 * from language bindings.
507 */
508 unsigned int mNumVertices;
509
510 /**
511 * Weight of the AnimMesh.
512 */
513 float mWeight;
514
515#ifdef __cplusplus
516 /// @brief The class constructor.
517 aiAnimMesh() AI_NO_EXCEPT :
518 mVertices(nullptr),
519 mNormals(nullptr),
520 mTangents(nullptr),
521 mBitangents(nullptr),
522 mColors {nullptr},
523 mTextureCoords{nullptr},
524 mNumVertices(0),
525 mWeight(0.0f) {
526 // empty
527 }
528
529 /// @brief The class destructor.
530 ~aiAnimMesh() {
531 delete[] mVertices;
532 delete[] mNormals;
533 delete[] mTangents;
534 delete[] mBitangents;
535 for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
536 delete[] mTextureCoords[a];
537 }
538 for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
539 delete[] mColors[a];
540 }
541 }
542
543 /**
544 * @brief Check whether the anim-mesh overrides the vertex positions
545 * of its host mesh.
546 * @return true if positions are stored, false if not.
547 */
548 bool HasPositions() const {
549 return mVertices != nullptr;
550 }
551
552 /**
553 * @brief Check whether the anim-mesh overrides the vertex normals
554 * of its host mesh
555 * @return true if normals are stored, false if not.
556 */
557 bool HasNormals() const {
558 return mNormals != nullptr;
559 }
560
561 /**
562 * @brief Check whether the anim-mesh overrides the vertex tangents
563 * and bitangents of its host mesh. As for aiMesh,
564 * tangents and bitangents always go together.
565 * @return true if tangents and bi-tangents are stored, false if not.
566 */
567 bool HasTangentsAndBitangents() const {
568 return mTangents != nullptr;
569 }
570
571 /**
572 * @brief Check whether the anim mesh overrides a particular
573 * set of vertex colors on his host mesh.
574 * @param pIndex 0<index<AI_MAX_NUMBER_OF_COLOR_SETS
575 * @return true if vertex colors are stored, false if not.
576 */
577
578 bool HasVertexColors(unsigned int pIndex) const {
579 return pIndex >= AI_MAX_NUMBER_OF_COLOR_SETS ? false : mColors[pIndex] != nullptr;
580 }
581
582 /**
583 * @brief Check whether the anim mesh overrides a particular
584 * set of texture coordinates on his host mesh.
585 * @param pIndex 0<index<AI_MAX_NUMBER_OF_TEXTURECOORDS
586 * @return true if texture coordinates are stored, false if not.
587 */
588 bool HasTextureCoords(unsigned int pIndex) const {
589 return pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS ? false : mTextureCoords[pIndex] != nullptr;
590 }
591
592#endif
593};
594
595// ---------------------------------------------------------------------------
596/** @brief Enumerates the methods of mesh morphing supported by Assimp.
597 */
598enum aiMorphingMethod {
599 /** Morphing method to be determined */
600 aiMorphingMethod_UNKNOWN = 0x0,
601
602 /** Interpolation between morph targets */
603 aiMorphingMethod_VERTEX_BLEND = 0x1,
604
605 /** Normalized morphing between morph targets */
606 aiMorphingMethod_MORPH_NORMALIZED = 0x2,
607
608 /** Relative morphing between morph targets */
609 aiMorphingMethod_MORPH_RELATIVE = 0x3,
610
611/** This value is not used. It is just here to force the
612 * compiler to map this enum to a 32 Bit integer.
613 */
614#ifndef SWIG
615 _aiMorphingMethod_Force32Bit = INT_MAX
616#endif
617}; //! enum aiMorphingMethod
618
619// ---------------------------------------------------------------------------
620/** @brief A mesh represents a geometry or model with a single material.
621 *
622 * It usually consists of a number of vertices and a series of primitives/faces
623 * referencing the vertices. In addition there might be a series of bones, each
624 * of them addressing a number of vertices with a certain weight. Vertex data
625 * is presented in channels with each channel containing a single per-vertex
626 * information such as a set of texture coordinates or a normal vector.
627 * If a data pointer is non-null, the corresponding data stream is present.
628 * From C++-programs you can also use the comfort functions Has*() to
629 * test for the presence of various data streams.
630 *
631 * A Mesh uses only a single material which is referenced by a material ID.
632 * @note The mPositions member is usually not optional. However, vertex positions
633 * *could* be missing if the #AI_SCENE_FLAGS_INCOMPLETE flag is set in
634 * @code
635 * aiScene::mFlags
636 * @endcode
637 */
638struct aiMesh {
639 /**
640 * Bitwise combination of the members of the #aiPrimitiveType enum.
641 * This specifies which types of primitives are present in the mesh.
642 * The "SortByPrimitiveType"-Step can be used to make sure the
643 * output meshes consist of one primitive type each.
644 */
645 unsigned int mPrimitiveTypes;
646
647 /**
648 * The number of vertices in this mesh.
649 * This is also the size of all of the per-vertex data arrays.
650 * The maximum value for this member is #AI_MAX_VERTICES.
651 */
652 unsigned int mNumVertices;
653
654 /**
655 * The number of primitives (triangles, polygons, lines) in this mesh.
656 * This is also the size of the mFaces array.
657 * The maximum value for this member is #AI_MAX_FACES.
658 */
659 unsigned int mNumFaces;
660
661 /**
662 * @brief Vertex positions.
663 *
664 * This array is always present in a mesh. The array is
665 * mNumVertices in size.
666 */
667 C_STRUCT aiVector3D *mVertices;
668
669 /**
670 * @brief Vertex normals.
671 *
672 * The array contains normalized vectors, nullptr if not present.
673 * The array is mNumVertices in size. Normals are undefined for
674 * point and line primitives. A mesh consisting of points and
675 * lines only may not have normal vectors. Meshes with mixed
676 * primitive types (i.e. lines and triangles) may have normals,
677 * but the normals for vertices that are only referenced by
678 * point or line primitives are undefined and set to QNaN (WARN:
679 * qNaN compares to inequal to *everything*, even to qNaN itself.
680 * Using code like this to check whether a field is qnan is:
681 * @code
682 * #define IS_QNAN(f) (f != f)
683 * @endcode
684 * still dangerous because even 1.f == 1.f could evaluate to false! (
685 * remember the subtleties of IEEE754 artithmetics). Use stuff like
686 * @c fpclassify instead.
687 * @note Normal vectors computed by Assimp are always unit-length.
688 * However, this needn't apply for normals that have been taken
689 * directly from the model file.
690 */
691 C_STRUCT aiVector3D *mNormals;
692
693 /**
694 * @brief Vertex tangents.
695 *
696 * The tangent of a vertex points in the direction of the positive
697 * X texture axis. The array contains normalized vectors, nullptr if
698 * not present. The array is mNumVertices in size. A mesh consisting
699 * of points and lines only may not have normal vectors. Meshes with
700 * mixed primitive types (i.e. lines and triangles) may have
701 * normals, but the normals for vertices that are only referenced by
702 * point or line primitives are undefined and set to qNaN. See
703 * the #mNormals member for a detailed discussion of qNaNs.
704 * @note If the mesh contains tangents, it automatically also
705 * contains bitangents.
706 */
707 C_STRUCT aiVector3D *mTangents;
708
709 /**
710 * @brief Vertex bitangents.
711 *
712 * The bitangent of a vertex points in the direction of the positive
713 * Y texture axis. The array contains normalized vectors, nullptr if not
714 * present. The array is mNumVertices in size.
715 * @note If the mesh contains tangents, it automatically also contains
716 * bitangents.
717 */
718 C_STRUCT aiVector3D *mBitangents;
719
720 /**
721 * @brief Vertex color sets.
722 *
723 * A mesh may contain 0 to #AI_MAX_NUMBER_OF_COLOR_SETS vertex
724 * colors per vertex. nullptr if not present. Each array is
725 * mNumVertices in size if present.
726 */
727 C_STRUCT aiColor4D *mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
728
729 /**
730 * @brief Vertex texture coordinates, also known as UV channels.
731 *
732 * A mesh may contain 0 to AI_MAX_NUMBER_OF_TEXTURECOORDS channels per
733 * vertex. Used and unused (nullptr) channels may go in any order.
734 * The array is mNumVertices in size.
735 */
736 C_STRUCT aiVector3D *mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
737
738 /**
739 * @brief Specifies the number of components for a given UV channel.
740 *
741 * Up to three channels are supported (UVW, for accessing volume
742 * or cube maps). If the value is 2 for a given channel n, the
743 * component p.z of mTextureCoords[n][p] is set to 0.0f.
744 * If the value is 1 for a given channel, p.y is set to 0.0f, too.
745 * @note 4D coordinates are not supported
746 */
747 unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
748
749 /**
750 * @brief The faces the mesh is constructed from.
751 *
752 * Each face refers to a number of vertices by their indices.
753 * This array is always present in a mesh, its size is given
754 * in mNumFaces. If the #AI_SCENE_FLAGS_NON_VERBOSE_FORMAT
755 * is NOT set each face references an unique set of vertices.
756 */
757 C_STRUCT aiFace *mFaces;
758
759 /**
760 * The number of bones this mesh contains. Can be 0, in which case the mBones array is nullptr.
761 */
762 unsigned int mNumBones;
763
764 /**
765 * @brief The bones of this mesh.
766 *
767 * A bone consists of a name by which it can be found in the
768 * frame hierarchy and a set of vertex weights.
769 */
770 C_STRUCT aiBone **mBones;
771
772 /**
773 * @brief The material used by this mesh.
774 *
775 * A mesh uses only a single material. If an imported model uses
776 * multiple materials, the import splits up the mesh. Use this value
777 * as index into the scene's material list.
778 */
779 unsigned int mMaterialIndex;
780
781 /**
782 * Name of the mesh. Meshes can be named, but this is not a
783 * requirement and leaving this field empty is totally fine.
784 * There are mainly three uses for mesh names:
785 * - some formats name nodes and meshes independently.
786 * - importers tend to split meshes up to meet the
787 * one-material-per-mesh requirement. Assigning
788 * the same (dummy) name to each of the result meshes
789 * aids the caller at recovering the original mesh
790 * partitioning.
791 * - Vertex animations refer to meshes by their names.
792 */
793 C_STRUCT aiString mName;
794
795 /**
796 * The number of attachment meshes.
797 * Currently known to work with loaders:
798 * - Collada
799 * - gltf
800 */
801 unsigned int mNumAnimMeshes;
802
803 /**
804 * Attachment meshes for this mesh, for vertex-based animation.
805 * Attachment meshes carry replacement data for some of the
806 * mesh'es vertex components (usually positions, normals).
807 * Currently known to work with loaders:
808 * - Collada
809 * - gltf
810 */
811 C_STRUCT aiAnimMesh **mAnimMeshes;
812
813 /**
814 * Method of morphing when anim-meshes are specified.
815 * @see aiMorphingMethod to learn more about the provided morphing targets.
816 */
817 enum aiMorphingMethod mMethod;
818
819 /**
820 * The bounding box.
821 */
822 C_STRUCT aiAABB mAABB;
823
824 /**
825 * Vertex UV stream names. Pointer to array of size AI_MAX_NUMBER_OF_TEXTURECOORDS
826 */
827 C_STRUCT aiString **mTextureCoordsNames;
828
829#ifdef __cplusplus
830
831 //! The default class constructor.
832 aiMesh() AI_NO_EXCEPT
833 : mPrimitiveTypes(0),
834 mNumVertices(0),
835 mNumFaces(0),
836 mVertices(nullptr),
837 mNormals(nullptr),
838 mTangents(nullptr),
839 mBitangents(nullptr),
840 mColors{nullptr},
841 mTextureCoords{nullptr},
842 mNumUVComponents{0},
843 mFaces(nullptr),
844 mNumBones(0),
845 mBones(nullptr),
846 mMaterialIndex(0),
847 mNumAnimMeshes(0),
848 mAnimMeshes(nullptr),
849 mMethod(aiMorphingMethod_UNKNOWN),
850 mAABB(),
851 mTextureCoordsNames(nullptr) {
852 // empty
853 }
854
855 //! @brief The class destructor.
856 ~aiMesh() {
857 delete[] mVertices;
858 delete[] mNormals;
859 delete[] mTangents;
860 delete[] mBitangents;
861 for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
862 delete[] mTextureCoords[a];
863 }
864
865 if (mTextureCoordsNames) {
866 for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
867 delete mTextureCoordsNames[a];
868 }
869 delete[] mTextureCoordsNames;
870 }
871
872 for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) {
873 delete[] mColors[a];
874 }
875
876 // DO NOT REMOVE THIS ADDITIONAL CHECK
877 if (mNumBones && mBones) {
878 std::unordered_set<const aiBone *> bones;
879 for (unsigned int a = 0; a < mNumBones; a++) {
880 if (mBones[a]) {
881 bones.insert(x: mBones[a]);
882 }
883 }
884 for (const aiBone *bone: bones) {
885 delete bone;
886 }
887 delete[] mBones;
888 }
889
890 if (mNumAnimMeshes && mAnimMeshes) {
891 for (unsigned int a = 0; a < mNumAnimMeshes; a++) {
892 delete mAnimMeshes[a];
893 }
894 delete[] mAnimMeshes;
895 }
896
897 delete[] mFaces;
898 }
899
900 //! @brief Check whether the mesh contains positions. Provided no special
901 //! scene flags are set, this will always be true
902 //! @return true, if positions are stored, false if not.
903 bool HasPositions() const {
904 return mVertices != nullptr && mNumVertices > 0;
905 }
906
907 //! @brief Check whether the mesh contains faces. If no special scene flags
908 //! are set this should always return true
909 //! @return true, if faces are stored, false if not.
910 bool HasFaces() const {
911 return mFaces != nullptr && mNumFaces > 0;
912 }
913
914 //! @brief Check whether the mesh contains normal vectors
915 //! @return true, if normals are stored, false if not.
916 bool HasNormals() const {
917 return mNormals != nullptr && mNumVertices > 0;
918 }
919
920 //! @brief Check whether the mesh contains tangent and bitangent vectors.
921 //!
922 //! It is not possible that it contains tangents and no bitangents
923 //! (or the other way round). The existence of one of them
924 //! implies that the second is there, too.
925 //! @return true, if tangents and bi-tangents are stored, false if not.
926 bool HasTangentsAndBitangents() const {
927 return mTangents != nullptr && mBitangents != nullptr && mNumVertices > 0;
928 }
929
930 //! @brief Check whether the mesh contains a vertex color set
931 //! @param index Index of the vertex color set
932 //! @return true, if vertex colors are stored, false if not.
933 bool HasVertexColors(unsigned int index) const {
934 if (index >= AI_MAX_NUMBER_OF_COLOR_SETS) {
935 return false;
936 }
937 return mColors[index] != nullptr && mNumVertices > 0;
938 }
939
940 //! @brief Check whether the mesh contains a texture coordinate set
941 //! @param index Index of the texture coordinates set
942 //! @return true, if texture coordinates are stored, false if not.
943 bool HasTextureCoords(unsigned int index) const {
944 if (index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
945 return false;
946 }
947 return (mTextureCoords[index] != nullptr && mNumVertices > 0);
948 }
949
950 //! @brief Get the number of UV channels the mesh contains.
951 //! @return the number of stored uv-channels.
952 unsigned int GetNumUVChannels() const {
953 unsigned int n(0);
954 for (unsigned i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) {
955 if (mTextureCoords[i]) {
956 ++n;
957 }
958 }
959
960 return n;
961 }
962
963 //! @brief Get the number of vertex color channels the mesh contains.
964 //! @return The number of stored color channels.
965 unsigned int GetNumColorChannels() const {
966 unsigned int n(0);
967 while (n < AI_MAX_NUMBER_OF_COLOR_SETS && mColors[n]) {
968 ++n;
969 }
970 return n;
971 }
972
973 //! @brief Check whether the mesh contains bones.
974 //! @return true, if bones are stored.
975 bool HasBones() const {
976 return mBones != nullptr && mNumBones > 0;
977 }
978
979 //! @brief Check whether the mesh contains a texture coordinate set name
980 //! @param pIndex Index of the texture coordinates set
981 //! @return true, if texture coordinates for the index exists.
982 bool HasTextureCoordsName(unsigned int pIndex) const {
983 if (mTextureCoordsNames == nullptr || pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
984 return false;
985 }
986 return mTextureCoordsNames[pIndex] != nullptr;
987 }
988
989 //! @brief Set a texture coordinate set name
990 //! @param pIndex Index of the texture coordinates set
991 //! @param texCoordsName name of the texture coordinate set
992 void SetTextureCoordsName(unsigned int pIndex, const aiString &texCoordsName) {
993 if (pIndex >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
994 return;
995 }
996
997 if (mTextureCoordsNames == nullptr) {
998 // Construct and null-init array
999 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 */
1048struct 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 */
1140struct 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
1178

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtquick3d/src/3rdparty/assimp/src/include/assimp/mesh.h