rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 /** @file Defines a post processing step to search an importer's output
|
nuclear@0
|
43 for data that is obviously invalid */
|
nuclear@0
|
44
|
nuclear@0
|
45 #include "AssimpPCH.h"
|
nuclear@0
|
46
|
nuclear@0
|
47 #ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
|
nuclear@0
|
48
|
nuclear@0
|
49 // internal headers
|
nuclear@0
|
50 #include "FindInvalidDataProcess.h"
|
nuclear@0
|
51 #include "ProcessHelper.h"
|
nuclear@0
|
52
|
nuclear@0
|
53 using namespace Assimp;
|
nuclear@0
|
54
|
nuclear@0
|
55 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
56 // Constructor to be privately used by Importer
|
nuclear@0
|
57 FindInvalidDataProcess::FindInvalidDataProcess()
|
nuclear@0
|
58 {
|
nuclear@0
|
59 // nothing to do here
|
nuclear@0
|
60 }
|
nuclear@0
|
61
|
nuclear@0
|
62 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
63 // Destructor, private as well
|
nuclear@0
|
64 FindInvalidDataProcess::~FindInvalidDataProcess()
|
nuclear@0
|
65 {
|
nuclear@0
|
66 // nothing to do here
|
nuclear@0
|
67 }
|
nuclear@0
|
68
|
nuclear@0
|
69 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
70 // Returns whether the processing step is present in the given flag field.
|
nuclear@0
|
71 bool FindInvalidDataProcess::IsActive( unsigned int pFlags) const
|
nuclear@0
|
72 {
|
nuclear@0
|
73 return 0 != (pFlags & aiProcess_FindInvalidData);
|
nuclear@0
|
74 }
|
nuclear@0
|
75
|
nuclear@0
|
76 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
77 // Setup import configuration
|
nuclear@0
|
78 void FindInvalidDataProcess::SetupProperties(const Importer* pImp)
|
nuclear@0
|
79 {
|
nuclear@0
|
80 // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY
|
nuclear@0
|
81 configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY,0.f));
|
nuclear@0
|
82 }
|
nuclear@0
|
83
|
nuclear@0
|
84 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
85 // Update mesh references in the node graph
|
nuclear@0
|
86 void UpdateMeshReferences(aiNode* node, const std::vector<unsigned int>& meshMapping)
|
nuclear@0
|
87 {
|
nuclear@0
|
88 if (node->mNumMeshes) {
|
nuclear@0
|
89 unsigned int out = 0;
|
nuclear@0
|
90 for (unsigned int a = 0; a < node->mNumMeshes;++a) {
|
nuclear@0
|
91
|
nuclear@0
|
92 register unsigned int ref = node->mMeshes[a];
|
nuclear@0
|
93 if (UINT_MAX != (ref = meshMapping[ref])) {
|
nuclear@0
|
94 node->mMeshes[out++] = ref;
|
nuclear@0
|
95 }
|
nuclear@0
|
96 }
|
nuclear@0
|
97 // just let the members that are unused, that's much cheaper
|
nuclear@0
|
98 // than a full array realloc'n'copy party ...
|
nuclear@0
|
99 if(!(node->mNumMeshes = out)) {
|
nuclear@0
|
100
|
nuclear@0
|
101 delete[] node->mMeshes;
|
nuclear@0
|
102 node->mMeshes = NULL;
|
nuclear@0
|
103 }
|
nuclear@0
|
104 }
|
nuclear@0
|
105 // recursively update all children
|
nuclear@0
|
106 for (unsigned int i = 0; i < node->mNumChildren;++i) {
|
nuclear@0
|
107 UpdateMeshReferences(node->mChildren[i],meshMapping);
|
nuclear@0
|
108 }
|
nuclear@0
|
109 }
|
nuclear@0
|
110
|
nuclear@0
|
111 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
112 // Executes the post processing step on the given imported data.
|
nuclear@0
|
113 void FindInvalidDataProcess::Execute( aiScene* pScene)
|
nuclear@0
|
114 {
|
nuclear@0
|
115 DefaultLogger::get()->debug("FindInvalidDataProcess begin");
|
nuclear@0
|
116
|
nuclear@0
|
117 bool out = false;
|
nuclear@0
|
118 std::vector<unsigned int> meshMapping(pScene->mNumMeshes);
|
nuclear@0
|
119 unsigned int real = 0;
|
nuclear@0
|
120
|
nuclear@0
|
121 // Process meshes
|
nuclear@0
|
122 for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
|
nuclear@0
|
123
|
nuclear@0
|
124 int result;
|
nuclear@0
|
125 if ((result = ProcessMesh( pScene->mMeshes[a]))) {
|
nuclear@0
|
126 out = true;
|
nuclear@0
|
127
|
nuclear@0
|
128 if (2 == result) {
|
nuclear@0
|
129 // remove this mesh
|
nuclear@0
|
130 delete pScene->mMeshes[a];
|
nuclear@0
|
131 AI_DEBUG_INVALIDATE_PTR(pScene->mMeshes[a]);
|
nuclear@0
|
132
|
nuclear@0
|
133 meshMapping[a] = UINT_MAX;
|
nuclear@0
|
134 continue;
|
nuclear@0
|
135 }
|
nuclear@0
|
136 }
|
nuclear@0
|
137 pScene->mMeshes[real] = pScene->mMeshes[a];
|
nuclear@0
|
138 meshMapping[a] = real++;
|
nuclear@0
|
139 }
|
nuclear@0
|
140
|
nuclear@0
|
141 // Process animations
|
nuclear@0
|
142 for (unsigned int a = 0; a < pScene->mNumAnimations;++a) {
|
nuclear@0
|
143 ProcessAnimation( pScene->mAnimations[a]);
|
nuclear@0
|
144 }
|
nuclear@0
|
145
|
nuclear@0
|
146
|
nuclear@0
|
147 if (out) {
|
nuclear@0
|
148 if ( real != pScene->mNumMeshes) {
|
nuclear@0
|
149 if (!real) {
|
nuclear@0
|
150 throw DeadlyImportError("No meshes remaining");
|
nuclear@0
|
151 }
|
nuclear@0
|
152
|
nuclear@0
|
153 // we need to remove some meshes.
|
nuclear@0
|
154 // therefore we'll also need to remove all references
|
nuclear@0
|
155 // to them from the scenegraph
|
nuclear@0
|
156 UpdateMeshReferences(pScene->mRootNode,meshMapping);
|
nuclear@0
|
157 pScene->mNumMeshes = real;
|
nuclear@0
|
158 }
|
nuclear@0
|
159
|
nuclear@0
|
160 DefaultLogger::get()->info("FindInvalidDataProcess finished. Found issues ...");
|
nuclear@0
|
161 }
|
nuclear@0
|
162 else DefaultLogger::get()->debug("FindInvalidDataProcess finished. Everything seems to be OK.");
|
nuclear@0
|
163 }
|
nuclear@0
|
164
|
nuclear@0
|
165 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
166 template <typename T>
|
nuclear@0
|
167 inline const char* ValidateArrayContents(const T* arr, unsigned int size,
|
nuclear@0
|
168 const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true)
|
nuclear@0
|
169 {
|
nuclear@0
|
170 return NULL;
|
nuclear@0
|
171 }
|
nuclear@0
|
172
|
nuclear@0
|
173 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
174 template <>
|
nuclear@0
|
175 inline const char* ValidateArrayContents<aiVector3D>(const aiVector3D* arr, unsigned int size,
|
nuclear@0
|
176 const std::vector<bool>& dirtyMask, bool mayBeIdentical , bool mayBeZero )
|
nuclear@0
|
177 {
|
nuclear@0
|
178 bool b = false;
|
nuclear@0
|
179 unsigned int cnt = 0;
|
nuclear@0
|
180 for (unsigned int i = 0; i < size;++i) {
|
nuclear@0
|
181
|
nuclear@0
|
182 if (dirtyMask.size() && dirtyMask[i]) {
|
nuclear@0
|
183 continue;
|
nuclear@0
|
184 }
|
nuclear@0
|
185 ++cnt;
|
nuclear@0
|
186
|
nuclear@0
|
187 const aiVector3D& v = arr[i];
|
nuclear@0
|
188 if (is_special_float(v.x) || is_special_float(v.y) || is_special_float(v.z)) {
|
nuclear@0
|
189 return "INF/NAN was found in a vector component";
|
nuclear@0
|
190 }
|
nuclear@0
|
191 if (!mayBeZero && !v.x && !v.y && !v.z ) {
|
nuclear@0
|
192 return "Found zero-length vector";
|
nuclear@0
|
193 }
|
nuclear@0
|
194 if (i && v != arr[i-1])b = true;
|
nuclear@0
|
195 }
|
nuclear@0
|
196 if (cnt > 1 && !b && !mayBeIdentical) {
|
nuclear@0
|
197 return "All vectors are identical";
|
nuclear@0
|
198 }
|
nuclear@0
|
199 return NULL;
|
nuclear@0
|
200 }
|
nuclear@0
|
201
|
nuclear@0
|
202 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
203 template <typename T>
|
nuclear@0
|
204 inline bool ProcessArray(T*& in, unsigned int num,const char* name,
|
nuclear@0
|
205 const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true)
|
nuclear@0
|
206 {
|
nuclear@0
|
207 const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero);
|
nuclear@0
|
208 if (err) {
|
nuclear@0
|
209 DefaultLogger::get()->error(std::string("FindInvalidDataProcess fails on mesh ") + name + ": " + err);
|
nuclear@0
|
210
|
nuclear@0
|
211 delete[] in;
|
nuclear@0
|
212 in = NULL;
|
nuclear@0
|
213 return true;
|
nuclear@0
|
214 }
|
nuclear@0
|
215 return false;
|
nuclear@0
|
216 }
|
nuclear@0
|
217
|
nuclear@0
|
218 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
219 template <typename T>
|
nuclear@0
|
220 AI_FORCE_INLINE bool EpsilonCompare(const T& n, const T& s, float epsilon);
|
nuclear@0
|
221
|
nuclear@0
|
222 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
223 AI_FORCE_INLINE bool EpsilonCompare(float n, float s, float epsilon) {
|
nuclear@0
|
224 return fabs(n-s)>epsilon;
|
nuclear@0
|
225 }
|
nuclear@0
|
226
|
nuclear@0
|
227 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
228 template <>
|
nuclear@0
|
229 bool EpsilonCompare<aiVectorKey>(const aiVectorKey& n, const aiVectorKey& s, float epsilon) {
|
nuclear@0
|
230 return
|
nuclear@0
|
231 EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
|
nuclear@0
|
232 EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
|
nuclear@0
|
233 EpsilonCompare(n.mValue.z,s.mValue.z,epsilon);
|
nuclear@0
|
234 }
|
nuclear@0
|
235
|
nuclear@0
|
236 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
237 template <>
|
nuclear@0
|
238 bool EpsilonCompare<aiQuatKey>(const aiQuatKey& n, const aiQuatKey& s, float epsilon) {
|
nuclear@0
|
239 return
|
nuclear@0
|
240 EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) &&
|
nuclear@0
|
241 EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) &&
|
nuclear@0
|
242 EpsilonCompare(n.mValue.z,s.mValue.z,epsilon) &&
|
nuclear@0
|
243 EpsilonCompare(n.mValue.w,s.mValue.w,epsilon);
|
nuclear@0
|
244 }
|
nuclear@0
|
245
|
nuclear@0
|
246 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
247 template <typename T>
|
nuclear@0
|
248 inline bool AllIdentical(T* in, unsigned int num, float epsilon)
|
nuclear@0
|
249 {
|
nuclear@0
|
250 if (num <= 1) {
|
nuclear@0
|
251 return true;
|
nuclear@0
|
252 }
|
nuclear@0
|
253
|
nuclear@0
|
254 if (epsilon > 0.f) {
|
nuclear@0
|
255 for (unsigned int i = 0; i < num-1;++i) {
|
nuclear@0
|
256
|
nuclear@0
|
257 if (!EpsilonCompare(in[i],in[i+1],epsilon)) {
|
nuclear@0
|
258 return false;
|
nuclear@0
|
259 }
|
nuclear@0
|
260 }
|
nuclear@0
|
261 }
|
nuclear@0
|
262 else {
|
nuclear@0
|
263 for (unsigned int i = 0; i < num-1;++i) {
|
nuclear@0
|
264
|
nuclear@0
|
265 if (in[i] != in[i+1]) {
|
nuclear@0
|
266 return false;
|
nuclear@0
|
267 }
|
nuclear@0
|
268 }
|
nuclear@0
|
269 }
|
nuclear@0
|
270 return true;
|
nuclear@0
|
271 }
|
nuclear@0
|
272
|
nuclear@0
|
273 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
274 // Search an animation for invalid content
|
nuclear@0
|
275 void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim)
|
nuclear@0
|
276 {
|
nuclear@0
|
277 // Process all animation channels
|
nuclear@0
|
278 for (unsigned int a = 0; a < anim->mNumChannels;++a) {
|
nuclear@0
|
279 ProcessAnimationChannel( anim->mChannels[a]);
|
nuclear@0
|
280 }
|
nuclear@0
|
281 }
|
nuclear@0
|
282
|
nuclear@0
|
283 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
284 void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
|
nuclear@0
|
285 {
|
nuclear@0
|
286 int i = 0;
|
nuclear@0
|
287
|
nuclear@0
|
288 // ScenePreprocessor's work ...
|
nuclear@0
|
289 ai_assert((0 != anim->mPositionKeys && 0 != anim->mRotationKeys && 0 != anim->mScalingKeys));
|
nuclear@0
|
290
|
nuclear@0
|
291 // Check whether all values in a tracks are identical - in this case
|
nuclear@0
|
292 // we can remove al keys except one.
|
nuclear@0
|
293 // POSITIONS
|
nuclear@0
|
294 if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys,configEpsilon))
|
nuclear@0
|
295 {
|
nuclear@0
|
296 aiVectorKey v = anim->mPositionKeys[0];
|
nuclear@0
|
297
|
nuclear@0
|
298 // Reallocate ... we need just ONE element, it makes no sense to reuse the array
|
nuclear@0
|
299 delete[] anim->mPositionKeys;
|
nuclear@0
|
300 anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys = 1];
|
nuclear@0
|
301 anim->mPositionKeys[0] = v;
|
nuclear@0
|
302 i = 1;
|
nuclear@0
|
303 }
|
nuclear@0
|
304
|
nuclear@0
|
305 // ROTATIONS
|
nuclear@0
|
306 if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys,configEpsilon))
|
nuclear@0
|
307 {
|
nuclear@0
|
308 aiQuatKey v = anim->mRotationKeys[0];
|
nuclear@0
|
309
|
nuclear@0
|
310 // Reallocate ... we need just ONE element, it makes no sense to reuse the array
|
nuclear@0
|
311 delete[] anim->mRotationKeys;
|
nuclear@0
|
312 anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys = 1];
|
nuclear@0
|
313 anim->mRotationKeys[0] = v;
|
nuclear@0
|
314 i = 1;
|
nuclear@0
|
315 }
|
nuclear@0
|
316
|
nuclear@0
|
317 // SCALINGS
|
nuclear@0
|
318 if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys,configEpsilon))
|
nuclear@0
|
319 {
|
nuclear@0
|
320 aiVectorKey v = anim->mScalingKeys[0];
|
nuclear@0
|
321
|
nuclear@0
|
322 // Reallocate ... we need just ONE element, it makes no sense to reuse the array
|
nuclear@0
|
323 delete[] anim->mScalingKeys;
|
nuclear@0
|
324 anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys = 1];
|
nuclear@0
|
325 anim->mScalingKeys[0] = v;
|
nuclear@0
|
326 i = 1;
|
nuclear@0
|
327 }
|
nuclear@0
|
328 if (1 == i)
|
nuclear@0
|
329 DefaultLogger::get()->warn("Simplified dummy tracks with just one key");
|
nuclear@0
|
330 }
|
nuclear@0
|
331
|
nuclear@0
|
332 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
333 // Search a mesh for invalid contents
|
nuclear@0
|
334 int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
|
nuclear@0
|
335 {
|
nuclear@0
|
336 bool ret = false;
|
nuclear@0
|
337 std::vector<bool> dirtyMask(pMesh->mNumVertices,(pMesh->mNumFaces ? true : false));
|
nuclear@0
|
338
|
nuclear@0
|
339 // Ignore elements that are not referenced by vertices.
|
nuclear@0
|
340 // (they are, for example, caused by the FindDegenerates step)
|
nuclear@0
|
341 for (unsigned int m = 0; m < pMesh->mNumFaces;++m) {
|
nuclear@0
|
342 const aiFace& f = pMesh->mFaces[m];
|
nuclear@0
|
343
|
nuclear@0
|
344 for (unsigned int i = 0; i < f.mNumIndices;++i) {
|
nuclear@0
|
345 dirtyMask[f.mIndices[i]] = false;
|
nuclear@0
|
346 }
|
nuclear@0
|
347 }
|
nuclear@0
|
348
|
nuclear@0
|
349 // Process vertex positions
|
nuclear@0
|
350 if(pMesh->mVertices && ProcessArray(pMesh->mVertices,pMesh->mNumVertices,"positions",dirtyMask)) {
|
nuclear@0
|
351 DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions");
|
nuclear@0
|
352 return 2;
|
nuclear@0
|
353 }
|
nuclear@0
|
354
|
nuclear@0
|
355 // process texture coordinates
|
nuclear@0
|
356 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i];++i) {
|
nuclear@0
|
357 if (ProcessArray(pMesh->mTextureCoords[i],pMesh->mNumVertices,"uvcoords",dirtyMask)) {
|
nuclear@0
|
358
|
nuclear@0
|
359 // delete all subsequent texture coordinate sets.
|
nuclear@0
|
360 for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
|
nuclear@0
|
361 delete[] pMesh->mTextureCoords[a]; pMesh->mTextureCoords[a] = NULL;
|
nuclear@0
|
362 }
|
nuclear@0
|
363 ret = true;
|
nuclear@0
|
364 }
|
nuclear@0
|
365 }
|
nuclear@0
|
366
|
nuclear@0
|
367 // -- we don't validate vertex colors, it's difficult to say whether
|
nuclear@0
|
368 // they are invalid or not.
|
nuclear@0
|
369
|
nuclear@0
|
370 // Normals and tangents are undefined for point and line faces.
|
nuclear@0
|
371 if (pMesh->mNormals || pMesh->mTangents) {
|
nuclear@0
|
372
|
nuclear@0
|
373 if (aiPrimitiveType_POINT & pMesh->mPrimitiveTypes ||
|
nuclear@0
|
374 aiPrimitiveType_LINE & pMesh->mPrimitiveTypes)
|
nuclear@0
|
375 {
|
nuclear@0
|
376 if (aiPrimitiveType_TRIANGLE & pMesh->mPrimitiveTypes ||
|
nuclear@0
|
377 aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes)
|
nuclear@0
|
378 {
|
nuclear@0
|
379 // We need to update the lookup-table
|
nuclear@0
|
380 for (unsigned int m = 0; m < pMesh->mNumFaces;++m)
|
nuclear@0
|
381 {
|
nuclear@0
|
382 const aiFace& f = pMesh->mFaces[m];
|
nuclear@0
|
383
|
nuclear@0
|
384 if (f.mNumIndices < 3) {
|
nuclear@0
|
385 dirtyMask[f.mIndices[0]] = true;
|
nuclear@0
|
386
|
nuclear@0
|
387 if (f.mNumIndices == 2) {
|
nuclear@0
|
388 dirtyMask[f.mIndices[1]] = true;
|
nuclear@0
|
389 }
|
nuclear@0
|
390 }
|
nuclear@0
|
391 }
|
nuclear@0
|
392 }
|
nuclear@0
|
393 // Normals, tangents and bitangents are undefined for
|
nuclear@0
|
394 // the whole mesh (and should not even be there)
|
nuclear@0
|
395 else return ret;
|
nuclear@0
|
396 }
|
nuclear@0
|
397
|
nuclear@0
|
398 // Process mesh normals
|
nuclear@0
|
399 if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices,
|
nuclear@0
|
400 "normals",dirtyMask,true,false))
|
nuclear@0
|
401 ret = true;
|
nuclear@0
|
402
|
nuclear@0
|
403 // Process mesh tangents
|
nuclear@0
|
404 if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices,"tangents",dirtyMask)) {
|
nuclear@0
|
405 delete[] pMesh->mBitangents; pMesh->mBitangents = NULL;
|
nuclear@0
|
406 ret = true;
|
nuclear@0
|
407 }
|
nuclear@0
|
408
|
nuclear@0
|
409 // Process mesh bitangents
|
nuclear@0
|
410 if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices,"bitangents",dirtyMask)) {
|
nuclear@0
|
411 delete[] pMesh->mTangents; pMesh->mTangents = NULL;
|
nuclear@0
|
412 ret = true;
|
nuclear@0
|
413 }
|
nuclear@0
|
414 }
|
nuclear@0
|
415 return ret ? 1 : 0;
|
nuclear@0
|
416 }
|
nuclear@0
|
417
|
nuclear@0
|
418
|
nuclear@0
|
419 #endif // !! ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS
|