vrshoot

view libs/assimp/SortByPTypeProcess.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line source
1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
6 Copyright (c) 2006-2012, assimp team
8 All rights reserved.
10 Redistribution and use of this software in source and binary forms,
11 with or without modification, are permitted provided that the following
12 conditions are met:
14 * Redistributions of source code must retain the above
15 copyright notice, this list of conditions and the
16 following disclaimer.
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.
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.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 ---------------------------------------------------------------------------
40 */
42 /** @file Implementation of the DeterminePTypeHelperProcess and
43 * SortByPTypeProcess post-process steps.
44 */
46 #include "AssimpPCH.h"
48 // internal headers
49 #include "ProcessHelper.h"
50 #include "SortByPTypeProcess.h"
52 using namespace Assimp;
54 // ------------------------------------------------------------------------------------------------
55 // Constructor to be privately used by Importer
56 SortByPTypeProcess::SortByPTypeProcess()
57 {
58 configRemoveMeshes = 0;
59 }
61 // ------------------------------------------------------------------------------------------------
62 // Destructor, private as well
63 SortByPTypeProcess::~SortByPTypeProcess()
64 {
65 // nothing to do here
66 }
68 // ------------------------------------------------------------------------------------------------
69 // Returns whether the processing step is present in the given flag field.
70 bool SortByPTypeProcess::IsActive( unsigned int pFlags) const
71 {
72 return (pFlags & aiProcess_SortByPType) != 0;
73 }
75 // ------------------------------------------------------------------------------------------------
76 void SortByPTypeProcess::SetupProperties(const Importer* pImp)
77 {
78 configRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0);
79 }
81 // ------------------------------------------------------------------------------------------------
82 // Update changed meshes in all nodes
83 void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node)
84 {
85 // std::vector<unsigned int>::const_iterator it;
87 if (node->mNumMeshes)
88 {
89 unsigned int newSize = 0;
90 for (unsigned int m = 0; m< node->mNumMeshes; ++m)
91 {
92 unsigned int add = node->mMeshes[m]<<2;
93 for (unsigned int i = 0; i < 4;++i)
94 {
95 if (UINT_MAX != replaceMeshIndex[add+i])++newSize;
96 }
97 }
98 if (!newSize)
99 {
100 delete[] node->mMeshes;
101 node->mNumMeshes = 0;
102 node->mMeshes = NULL;
103 }
104 else
105 {
106 // Try to reuse the old array if possible
107 unsigned int* newMeshes = (newSize > node->mNumMeshes
108 ? new unsigned int[newSize] : node->mMeshes);
110 for (unsigned int m = 0; m< node->mNumMeshes; ++m)
111 {
112 unsigned int add = node->mMeshes[m]<<2;
113 for (unsigned int i = 0; i < 4;++i)
114 {
115 if (UINT_MAX != replaceMeshIndex[add+i])
116 *newMeshes++ = replaceMeshIndex[add+i];
117 }
118 }
119 if (newSize > node->mNumMeshes)
120 delete[] node->mMeshes;
122 node->mMeshes = newMeshes-(node->mNumMeshes = newSize);
123 }
124 }
126 // call all subnodes recursively
127 for (unsigned int m = 0; m < node->mNumChildren; ++m)
128 UpdateNodes(replaceMeshIndex,node->mChildren[m]);
129 }
131 // ------------------------------------------------------------------------------------------------
132 // Executes the post processing step on the given imported data.
133 void SortByPTypeProcess::Execute( aiScene* pScene)
134 {
135 if (!pScene->mNumMeshes)
136 {
137 DefaultLogger::get()->debug("SortByPTypeProcess skipped, there are no meshes");
138 return;
139 }
141 DefaultLogger::get()->debug("SortByPTypeProcess begin");
143 unsigned int aiNumMeshesPerPType[4] = {0,0,0,0};
145 std::vector<aiMesh*> outMeshes;
146 outMeshes.reserve(pScene->mNumMeshes<<1u);
148 bool bAnyChanges = false;
150 std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,UINT_MAX);
151 std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin();
152 for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
153 {
154 aiMesh* mesh = pScene->mMeshes[i];
155 ai_assert(0 != mesh->mPrimitiveTypes);
157 // if there's just one primitive type in the mesh there's nothing to do for us
158 unsigned int num = 0;
159 if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT)
160 {
161 ++aiNumMeshesPerPType[0];
162 ++num;
163 }
164 if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE)
165 {
166 ++aiNumMeshesPerPType[1];
167 ++num;
168 }
169 if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)
170 {
171 ++aiNumMeshesPerPType[2];
172 ++num;
173 }
174 if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)
175 {
176 ++aiNumMeshesPerPType[3];
177 ++num;
178 }
180 if (1 == num)
181 {
182 if (!(configRemoveMeshes & mesh->mPrimitiveTypes))
183 {
184 *meshIdx = (unsigned int) outMeshes.size();
185 outMeshes.push_back(mesh);
186 }
187 else bAnyChanges = true;
189 meshIdx += 4;
190 continue;
191 }
192 bAnyChanges = true;
194 // reuse our current mesh arrays for the submesh
195 // with the largest numer of primitives
196 unsigned int aiNumPerPType[4] = {0,0,0,0};
197 aiFace* pFirstFace = mesh->mFaces;
198 aiFace* const pLastFace = pFirstFace + mesh->mNumFaces;
200 unsigned int numPolyVerts = 0;
201 for (;pFirstFace != pLastFace; ++pFirstFace)
202 {
203 if (pFirstFace->mNumIndices <= 3)
204 ++aiNumPerPType[pFirstFace->mNumIndices-1];
205 else
206 {
207 ++aiNumPerPType[3];
208 numPolyVerts += pFirstFace-> mNumIndices;
209 }
210 }
212 VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh);
213 for (unsigned int real = 0; real < 4; ++real,++meshIdx)
214 {
215 if ( !aiNumPerPType[real] || configRemoveMeshes & (1u << real))
216 {
217 continue;
218 }
220 *meshIdx = (unsigned int) outMeshes.size();
221 outMeshes.push_back(new aiMesh());
222 aiMesh* out = outMeshes.back();
224 // the name carries the adjacency information between the meshes
225 out->mName = mesh->mName;
227 // copy data members
228 out->mPrimitiveTypes = 1u << real;
229 out->mMaterialIndex = mesh->mMaterialIndex;
231 // allocate output storage
232 out->mNumFaces = aiNumPerPType[real];
233 aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces];
235 out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1));
237 aiVector3D *vert(NULL), *nor(NULL), *tan(NULL), *bit(NULL);
238 aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS];
239 aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS];
241 if (mesh->mVertices)
242 vert = out->mVertices = new aiVector3D[out->mNumVertices];
244 if (mesh->mNormals)
245 nor = out->mNormals = new aiVector3D[out->mNumVertices];
247 if (mesh->mTangents)
248 {
249 tan = out->mTangents = new aiVector3D[out->mNumVertices];
250 bit = out->mBitangents = new aiVector3D[out->mNumVertices];
251 }
253 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
254 {
255 if (mesh->mTextureCoords[i])
256 uv[i] = out->mTextureCoords[i] = new aiVector3D[out->mNumVertices];
257 else uv[i] = NULL;
259 out->mNumUVComponents[i] = mesh->mNumUVComponents[i];
260 }
262 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
263 {
264 if (mesh->mColors[i])
265 cols[i] = out->mColors[i] = new aiColor4D[out->mNumVertices];
266 else cols[i] = NULL;
267 }
269 typedef std::vector< aiVertexWeight > TempBoneInfo;
270 std::vector< TempBoneInfo > tempBones(mesh->mNumBones);
272 // try to guess how much storage we'll need
273 for (unsigned int q = 0; q < mesh->mNumBones;++q)
274 {
275 tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1));
276 }
278 unsigned int outIdx = 0;
279 for (unsigned int m = 0; m < mesh->mNumFaces; ++m)
280 {
281 aiFace& in = mesh->mFaces[m];
282 if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1))
283 {
284 continue;
285 }
287 outFaces->mNumIndices = in.mNumIndices;
288 outFaces->mIndices = in.mIndices;
290 for (unsigned int q = 0; q < in.mNumIndices; ++q)
291 {
292 register unsigned int idx = in.mIndices[q];
294 // process all bones of this index
295 if (avw)
296 {
297 VertexWeightTable& tbl = avw[idx];
298 for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end();
299 it != end; ++it)
300 {
301 tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) );
302 }
303 }
305 if (vert)
306 {
307 *vert++ = mesh->mVertices[idx];
308 //mesh->mVertices[idx].x = get_qnan();
309 }
310 if (nor )*nor++ = mesh->mNormals[idx];
311 if (tan )
312 {
313 *tan++ = mesh->mTangents[idx];
314 *bit++ = mesh->mBitangents[idx];
315 }
317 for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp)
318 {
319 if (!uv[pp])break;
320 *uv[pp]++ = mesh->mTextureCoords[pp][idx];
321 }
323 for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp)
324 {
325 if (!cols[pp])break;
326 *cols[pp]++ = mesh->mColors[pp][idx];
327 }
329 in.mIndices[q] = outIdx++;
330 }
332 in.mIndices = NULL;
333 ++outFaces;
334 }
335 ai_assert(outFaces == out->mFaces + out->mNumFaces);
337 // now generate output bones
338 for (unsigned int q = 0; q < mesh->mNumBones;++q)
339 if (!tempBones[q].empty())++out->mNumBones;
341 if (out->mNumBones)
342 {
343 out->mBones = new aiBone*[out->mNumBones];
344 for (unsigned int q = 0, real = 0; q < mesh->mNumBones;++q)
345 {
346 TempBoneInfo& in = tempBones[q];
347 if (in.empty())continue;
349 aiBone* srcBone = mesh->mBones[q];
350 aiBone* bone = out->mBones[real] = new aiBone();
352 bone->mName = srcBone->mName;
353 bone->mOffsetMatrix = srcBone->mOffsetMatrix;
355 bone->mNumWeights = (unsigned int)in.size();
356 bone->mWeights = new aiVertexWeight[bone->mNumWeights];
358 ::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight));
360 ++real;
361 }
362 }
363 }
365 // delete the per-vertex bone weights table
366 delete[] avw;
368 // delete the input mesh
369 delete mesh;
370 }
372 if (outMeshes.empty())
373 {
374 // This should not occur
375 throw DeadlyImportError("No meshes remaining");
376 }
378 // If we added at least one mesh process all nodes in the node
379 // graph and update their respective mesh indices.
380 if (bAnyChanges)
381 {
382 UpdateNodes(replaceMeshIndex,pScene->mRootNode);
383 }
385 if (outMeshes.size() != pScene->mNumMeshes)
386 {
387 delete[] pScene->mMeshes;
388 pScene->mNumMeshes = (unsigned int)outMeshes.size();
389 pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
390 }
391 ::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*));
393 if (!DefaultLogger::isNullLogger())
394 {
395 char buffer[1024];
396 ::sprintf(buffer,"Points: %i%s, Lines: %i%s, Triangles: %i%s, Polygons: %i%s (Meshes, X = removed)",
397 aiNumMeshesPerPType[0], (configRemoveMeshes & aiPrimitiveType_POINT ? "X" : ""),
398 aiNumMeshesPerPType[1], (configRemoveMeshes & aiPrimitiveType_LINE ? "X" : ""),
399 aiNumMeshesPerPType[2], (configRemoveMeshes & aiPrimitiveType_TRIANGLE ? "X" : ""),
400 aiNumMeshesPerPType[3], (configRemoveMeshes & aiPrimitiveType_POLYGON ? "X" : ""));
401 DefaultLogger::get()->info(buffer);
402 DefaultLogger::get()->debug("SortByPTypeProcess finished");
403 }
404 }