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