Coverage Report

Created: 2026-01-07 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/assimp/code/PostProcessing/ProcessHelper.h
Line
Count
Source
1
/*
2
Open Asset Import Library (assimp)
3
----------------------------------------------------------------------
4
5
Copyright (c) 2006-2025, assimp team
6
7
All rights reserved.
8
9
Redistribution and use of this software in source and binary forms,
10
with or without modification, are permitted provided that the
11
following conditions are met:
12
13
* Redistributions of source code must retain the above
14
  copyright notice, this list of conditions and the
15
  following disclaimer.
16
17
* Redistributions in binary form must reproduce the above
18
  copyright notice, this list of conditions and the
19
  following disclaimer in the documentation and/or other
20
  materials provided with the distribution.
21
22
* Neither the name of the assimp team, nor the names of its
23
  contributors may be used to endorse or promote products
24
  derived from this software without specific prior
25
  written permission of the assimp team.
26
27
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39
----------------------------------------------------------------------
40
*/
41
42
#ifndef AI_PROCESS_HELPER_H_INCLUDED
43
#define AI_PROCESS_HELPER_H_INCLUDED
44
45
#include <assimp/anim.h>
46
#include <assimp/material.h>
47
#include <assimp/mesh.h>
48
#include <assimp/postprocess.h>
49
#include <assimp/scene.h>
50
#include <assimp/DefaultLogger.hpp>
51
52
#include "Common/BaseProcess.h"
53
#include <assimp/ParsingUtils.h>
54
#include <assimp/SpatialSort.h>
55
56
#include <list>
57
58
// -------------------------------------------------------------------------------
59
// Some extensions to std namespace. Mainly std::min and std::max for all
60
// flat data types in the aiScene. They're used to quickly determine the
61
// min/max bounds of data arrays.
62
#ifdef __cplusplus
63
namespace std {
64
65
// std::min for aiVector3D
66
template <typename TReal>
67
111k
inline ::aiVector3t<TReal> min(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
68
111k
    return ::aiVector3t<TReal>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
69
111k
}
aiVector3t<float> std::min<float>(aiVector3t<float> const&, aiVector3t<float> const&)
Line
Count
Source
67
111k
inline ::aiVector3t<TReal> min(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
68
111k
    return ::aiVector3t<TReal>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
69
111k
}
Unexecuted instantiation: aiVector3t<double> std::min<double>(aiVector3t<double> const&, aiVector3t<double> const&)
70
71
// std::max for aiVector3t<TReal>
72
template <typename TReal>
73
111k
inline ::aiVector3t<TReal> max(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
74
111k
    return ::aiVector3t<TReal>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
75
111k
}
aiVector3t<float> std::max<float>(aiVector3t<float> const&, aiVector3t<float> const&)
Line
Count
Source
73
111k
inline ::aiVector3t<TReal> max(const ::aiVector3t<TReal> &a, const ::aiVector3t<TReal> &b) {
74
111k
    return ::aiVector3t<TReal>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
75
111k
}
Unexecuted instantiation: aiVector3t<double> std::max<double>(aiVector3t<double> const&, aiVector3t<double> const&)
76
77
// std::min for aiVector2t<TReal>
78
template <typename TReal>
79
0
inline ::aiVector2t<TReal> min(const ::aiVector2t<TReal> &a, const ::aiVector2t<TReal> &b) {
80
0
    return ::aiVector2t<TReal>(min(a.x, b.x), min(a.y, b.y));
81
0
}
82
83
// std::max for aiVector2t<TReal>
84
template <typename TReal>
85
0
inline ::aiVector2t<TReal> max(const ::aiVector2t<TReal> &a, const ::aiVector2t<TReal> &b) {
86
0
    return ::aiVector2t<TReal>(max(a.x, b.x), max(a.y, b.y));
87
0
}
88
89
// std::min for aiColor4D
90
template <typename TReal>
91
0
inline ::aiColor4t<TReal> min(const ::aiColor4t<TReal> &a, const ::aiColor4t<TReal> &b) {
92
0
    return ::aiColor4t<TReal>(min(a.r, b.r), min(a.g, b.g), min(a.b, b.b), min(a.a, b.a));
93
0
}
94
95
// std::max for aiColor4D
96
template <typename TReal>
97
0
inline ::aiColor4t<TReal> max(const ::aiColor4t<TReal> &a, const ::aiColor4t<TReal> &b) {
98
0
    return ::aiColor4t<TReal>(max(a.r, b.r), max(a.g, b.g), max(a.b, b.b), max(a.a, b.a));
99
0
}
100
101
// std::min for aiQuaterniont<TReal>
102
template <typename TReal>
103
0
inline ::aiQuaterniont<TReal> min(const ::aiQuaterniont<TReal> &a, const ::aiQuaterniont<TReal> &b) {
104
0
    return ::aiQuaterniont<TReal>(min(a.w, b.w), min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
105
0
}
106
107
// std::max for aiQuaterniont<TReal>
108
template <typename TReal>
109
0
inline ::aiQuaterniont<TReal> max(const ::aiQuaterniont<TReal> &a, const ::aiQuaterniont<TReal> &b) {
110
0
    return ::aiQuaterniont<TReal>(max(a.w, b.w), max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
111
0
}
112
113
// std::min for aiVectorKey
114
0
inline ::aiVectorKey min(const ::aiVectorKey &a, const ::aiVectorKey &b) {
115
0
    return ::aiVectorKey(min(a.mTime, b.mTime), min(a.mValue, b.mValue));
116
0
}
117
118
// std::max for aiVectorKey
119
0
inline ::aiVectorKey max(const ::aiVectorKey &a, const ::aiVectorKey &b) {
120
0
    return ::aiVectorKey(max(a.mTime, b.mTime), max(a.mValue, b.mValue));
121
0
}
122
123
// std::min for aiQuatKey
124
0
inline ::aiQuatKey min(const ::aiQuatKey &a, const ::aiQuatKey &b) {
125
0
    return ::aiQuatKey(min(a.mTime, b.mTime), min(a.mValue, b.mValue));
126
0
}
127
128
// std::max for aiQuatKey
129
0
inline ::aiQuatKey max(const ::aiQuatKey &a, const ::aiQuatKey &b) {
130
0
    return ::aiQuatKey(max(a.mTime, b.mTime), max(a.mValue, b.mValue));
131
0
}
132
133
// std::min for aiVertexWeight
134
0
inline ::aiVertexWeight min(const ::aiVertexWeight &a, const ::aiVertexWeight &b) {
135
0
    return ::aiVertexWeight(min(a.mVertexId, b.mVertexId),static_cast<ai_real>(min(a.mWeight, b.mWeight)));
136
0
}
137
138
// std::max for aiVertexWeight
139
0
inline ::aiVertexWeight max(const ::aiVertexWeight &a, const ::aiVertexWeight &b) {
140
0
    return ::aiVertexWeight(max(a.mVertexId, b.mVertexId), static_cast<ai_real>(max(a.mWeight, b.mWeight)));
141
0
}
142
143
} // end namespace std
144
#endif // !! C++
145
146
namespace Assimp {
147
148
// -------------------------------------------------------------------------------
149
// Start points for ArrayBounds<T> for all supported Ts
150
template <typename T>
151
struct MinMaxChooser;
152
153
template <>
154
struct MinMaxChooser<float> {
155
0
    void operator()(float &min, float &max) {
156
0
        max = -1e10f;
157
0
        min = 1e10f;
158
0
    }
159
};
160
template <>
161
struct MinMaxChooser<double> {
162
0
    void operator()(double &min, double &max) {
163
0
        max = -1e10;
164
0
        min = 1e10;
165
0
    }
166
};
167
template <>
168
struct MinMaxChooser<unsigned int> {
169
0
    void operator()(unsigned int &min, unsigned int &max) {
170
0
        max = 0;
171
0
        min = (1u << (sizeof(unsigned int) * 8 - 1));
172
0
    }
173
};
174
175
template <typename T>
176
struct MinMaxChooser<aiVector3t<T>> {
177
1.30k
    void operator()(aiVector3t<T> &min, aiVector3t<T> &max) {
178
1.30k
        max = aiVector3t<T>(-1e10f, -1e10f, -1e10f);
179
1.30k
        min = aiVector3t<T>(1e10f, 1e10f, 1e10f);
180
1.30k
    }
Assimp::MinMaxChooser<aiVector3t<float> >::operator()(aiVector3t<float>&, aiVector3t<float>&)
Line
Count
Source
177
1.30k
    void operator()(aiVector3t<T> &min, aiVector3t<T> &max) {
178
1.30k
        max = aiVector3t<T>(-1e10f, -1e10f, -1e10f);
179
1.30k
        min = aiVector3t<T>(1e10f, 1e10f, 1e10f);
180
1.30k
    }
Unexecuted instantiation: Assimp::MinMaxChooser<aiVector3t<double> >::operator()(aiVector3t<double>&, aiVector3t<double>&)
181
};
182
template <typename T>
183
struct MinMaxChooser<aiVector2t<T>> {
184
0
    void operator()(aiVector2t<T> &min, aiVector2t<T> &max) {
185
0
        max = aiVector2t<T>(-1e10f, -1e10f);
186
0
        min = aiVector2t<T>(1e10f, 1e10f);
187
0
    }
188
};
189
template <typename T>
190
struct MinMaxChooser<aiColor4t<T>> {
191
0
    void operator()(aiColor4t<T> &min, aiColor4t<T> &max) {
192
0
        max = aiColor4t<T>(-1e10f, -1e10f, -1e10f, -1e10f);
193
0
        min = aiColor4t<T>(1e10f, 1e10f, 1e10f, 1e10f);
194
0
    }
195
};
196
197
template <typename T>
198
struct MinMaxChooser<aiQuaterniont<T>> {
199
0
    void operator()(aiQuaterniont<T> &min, aiQuaterniont<T> &max) {
200
0
        max = aiQuaterniont<T>(-1e10f, -1e10f, -1e10f, -1e10f);
201
0
        min = aiQuaterniont<T>(1e10f, 1e10f, 1e10f, 1e10f);
202
0
    }
203
};
204
205
template <>
206
struct MinMaxChooser<aiVectorKey> {
207
0
    void operator()(aiVectorKey &min, aiVectorKey &max) {
208
0
        MinMaxChooser<double>()(min.mTime, max.mTime);
209
0
        MinMaxChooser<aiVector3D>()(min.mValue, max.mValue);
210
0
    }
211
};
212
template <>
213
struct MinMaxChooser<aiQuatKey> {
214
0
    void operator()(aiQuatKey &min, aiQuatKey &max) {
215
0
        MinMaxChooser<double>()(min.mTime, max.mTime);
216
0
        MinMaxChooser<aiQuaternion>()(min.mValue, max.mValue);
217
0
    }
218
};
219
220
template <>
221
struct MinMaxChooser<aiVertexWeight> {
222
0
    void operator()(aiVertexWeight &min, aiVertexWeight &max) {
223
0
        MinMaxChooser<unsigned int>()(min.mVertexId, max.mVertexId);
224
0
        MinMaxChooser<ai_real>()(min.mWeight, max.mWeight);
225
0
    }
226
};
227
228
// -------------------------------------------------------------------------------
229
/** @brief Find the min/max values of an array of Ts
230
 *  @param in Input array
231
 *  @param size Number of elements to process
232
 *  @param[out] min minimum value
233
 *  @param[out] max maximum value
234
 */
235
template <typename T>
236
1.30k
inline void ArrayBounds(const T *in, unsigned int size, T &min, T &max) {
237
1.30k
    MinMaxChooser<T>()(min, max);
238
112k
    for (unsigned int i = 0; i < size; ++i) {
239
111k
        min = std::min(in[i], min);
240
111k
        max = std::max(in[i], max);
241
111k
    }
242
1.30k
}
void Assimp::ArrayBounds<aiVector3t<float> >(aiVector3t<float> const*, unsigned int, aiVector3t<float>&, aiVector3t<float>&)
Line
Count
Source
236
1.30k
inline void ArrayBounds(const T *in, unsigned int size, T &min, T &max) {
237
1.30k
    MinMaxChooser<T>()(min, max);
238
112k
    for (unsigned int i = 0; i < size; ++i) {
239
111k
        min = std::min(in[i], min);
240
111k
        max = std::max(in[i], max);
241
111k
    }
242
1.30k
}
Unexecuted instantiation: void Assimp::ArrayBounds<aiColor4t<float> >(aiColor4t<float> const*, unsigned int, aiColor4t<float>&, aiColor4t<float>&)
Unexecuted instantiation: void Assimp::ArrayBounds<aiVertexWeight>(aiVertexWeight const*, unsigned int, aiVertexWeight&, aiVertexWeight&)
Unexecuted instantiation: void Assimp::ArrayBounds<aiVectorKey>(aiVectorKey const*, unsigned int, aiVectorKey&, aiVectorKey&)
Unexecuted instantiation: void Assimp::ArrayBounds<aiQuatKey>(aiQuatKey const*, unsigned int, aiQuatKey&, aiQuatKey&)
Unexecuted instantiation: void Assimp::ArrayBounds<aiVector3t<double> >(aiVector3t<double> const*, unsigned int, aiVector3t<double>&, aiVector3t<double>&)
243
244
// -------------------------------------------------------------------------------
245
/** Little helper function to calculate the quadratic difference
246
 * of two colors.
247
 * @param pColor1 First color
248
 * @param pColor2 second color
249
 * @return Quadratic color difference */
250
750k
inline ai_real GetColorDifference(const aiColor4D &pColor1, const aiColor4D &pColor2) {
251
750k
    const aiColor4D c(pColor1.r - pColor2.r, pColor1.g - pColor2.g, pColor1.b - pColor2.b, pColor1.a - pColor2.a);
252
750k
    return c.r * c.r + c.g * c.g + c.b * c.b + c.a * c.a;
253
750k
}
254
255
// -------------------------------------------------------------------------------
256
/** @brief Extract single strings from a list of identifiers
257
 *  @param in Input string list.
258
 *  @param out Receives a list of clean output strings
259
 *  @sdee #AI_CONFIG_PP_OG_EXCLUDE_LIST */
260
void ConvertListToStrings(const std::string &in, std::list<std::string> &out);
261
262
// -------------------------------------------------------------------------------
263
/** @brief Compute the AABB of a mesh after applying a given transform
264
 *  @param mesh Input mesh
265
 *  @param[out] min Receives minimum transformed vertex
266
 *  @param[out] max Receives maximum transformed vertex
267
 *  @param m Transformation matrix to be applied */
268
void FindAABBTransformed(const aiMesh *mesh, aiVector3D &min, aiVector3D &max, const aiMatrix4x4 &m);
269
270
// -------------------------------------------------------------------------------
271
/** @brief Helper function to determine the 'real' center of a mesh
272
 *
273
 *  That is the center of its axis-aligned bounding box.
274
 *  @param mesh Input mesh
275
 *  @param[out] min Minimum vertex of the mesh
276
 *  @param[out] max maximum vertex of the mesh
277
 *  @param[out] out Center point */
278
void FindMeshCenter(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max);
279
280
// -------------------------------------------------------------------------------
281
/** @brief Helper function to determine the 'real' center of a scene
282
 *
283
 *  That is the center of its axis-aligned bounding box.
284
 *  @param scene Input scene
285
 *  @param[out] min Minimum vertex of the scene
286
 *  @param[out] max maximum vertex of the scene
287
 *  @param[out] out Center point */
288
void FindSceneCenter(aiScene *scene, aiVector3D &out, aiVector3D &min, aiVector3D &max);
289
290
// -------------------------------------------------------------------------------
291
// Helper function to determine the 'real' center of a mesh after applying a given transform
292
void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, aiVector3D &min, aiVector3D &max, const aiMatrix4x4 &m);
293
294
// -------------------------------------------------------------------------------
295
// Helper function to determine the 'real' center of a mesh
296
void FindMeshCenter(aiMesh *mesh, aiVector3D &out);
297
298
// -------------------------------------------------------------------------------
299
// Helper function to determine the 'real' center of a mesh after applying a given transform
300
void FindMeshCenterTransformed(aiMesh *mesh, aiVector3D &out, const aiMatrix4x4 &m);
301
302
// -------------------------------------------------------------------------------
303
// Compute a good epsilon value for position comparisons on a mesh
304
ai_real ComputePositionEpsilon(const aiMesh *pMesh);
305
306
// -------------------------------------------------------------------------------
307
// Compute a good epsilon value for position comparisons on a array of meshes
308
ai_real ComputePositionEpsilon(const aiMesh *const *pMeshes, size_t num);
309
310
// -------------------------------------------------------------------------------
311
// Compute an unique value for the vertex format of a mesh
312
unsigned int GetMeshVFormatUnique(const aiMesh *pcMesh);
313
314
// defs for ComputeVertexBoneWeightTable()
315
using PerVertexWeight = std::pair<unsigned int, float>;
316
using VertexWeightTable = std::vector<PerVertexWeight>;
317
318
// -------------------------------------------------------------------------------
319
// Compute a per-vertex bone weight table
320
VertexWeightTable *ComputeVertexBoneWeightTable(const aiMesh *pMesh);
321
322
// -------------------------------------------------------------------------------
323
// Get a string for a given aiTextureMapping
324
const char *MappingTypeToString(aiTextureMapping in);
325
326
// flags for MakeSubmesh()
327
0
#define AI_SUBMESH_FLAGS_SANS_BONES 0x1
328
329
// -------------------------------------------------------------------------------
330
// Split a mesh given a list of faces to be contained in the sub mesh
331
aiMesh *MakeSubmesh(const aiMesh *superMesh, const std::vector<unsigned int> &subMeshFaces, unsigned int subFlags);
332
333
// -------------------------------------------------------------------------------
334
// Utility post-process step to share the spatial sort tree between
335
// all steps which use it to speedup its computations.
336
class ComputeSpatialSortProcess : public BaseProcess {
337
93
    bool IsActive(unsigned int pFlags) const {
338
93
        return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
339
56
                                                           aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
340
93
    }
341
342
56
    void Execute(aiScene *pScene) {
343
56
        typedef std::pair<SpatialSort, ai_real> _Type;
344
56
        ASSIMP_LOG_DEBUG("Generate spatially-sorted vertex cache");
345
346
56
        std::vector<_Type> *p = new std::vector<_Type>(pScene->mNumMeshes);
347
56
        std::vector<_Type>::iterator it = p->begin();
348
349
1.36k
        for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it) {
350
1.30k
            aiMesh *mesh = pScene->mMeshes[i];
351
1.30k
            _Type &blubb = *it;
352
1.30k
            blubb.first.Fill(mesh->mVertices, mesh->mNumVertices, sizeof(aiVector3D));
353
1.30k
            blubb.second = ComputePositionEpsilon(mesh);
354
1.30k
        }
355
356
56
        shared->AddProperty(AI_SPP_SPATIAL_SORT, p);
357
56
    }
358
};
359
360
// -------------------------------------------------------------------------------
361
// ... and the same again to cleanup the whole stuff
362
class DestroySpatialSortProcess : public BaseProcess {
363
93
    bool IsActive(unsigned int pFlags) const {
364
93
        return nullptr != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace |
365
56
                                                        aiProcess_GenNormals | aiProcess_JoinIdenticalVertices));
366
93
    }
367
368
56
    void Execute(aiScene * /*pScene*/) {
369
56
        shared->RemoveProperty(AI_SPP_SPATIAL_SORT);
370
56
    }
371
};
372
373
} // namespace Assimp
374
375
#endif // !! AI_PROCESS_HELPER_H_INCLUDED