vrshoot
view libs/assimp/SplitLargeMeshes.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 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
5 Copyright (c) 2006-2012, assimp team
6 All rights reserved.
8 Redistribution and use of this software in source and binary forms,
9 with or without modification, are permitted provided that the
10 following conditions are met:
12 * Redistributions of source code must retain the above
13 copyright notice, this list of conditions and the
14 following disclaimer.
16 * Redistributions in binary form must reproduce the above
17 copyright notice, this list of conditions and the
18 following disclaimer in the documentation and/or other
19 materials provided with the distribution.
21 * Neither the name of the assimp team, nor the names of its
22 contributors may be used to endorse or promote products
23 derived from this software without specific prior
24 written permission of the assimp team.
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 ----------------------------------------------------------------------
39 */
42 /** @file Implementation of the SplitLargeMeshes postprocessing step
43 */
45 #include "AssimpPCH.h"
47 // internal headers of the post-processing framework
48 #include "SplitLargeMeshes.h"
49 #include "ProcessHelper.h"
51 using namespace Assimp;
54 // ------------------------------------------------------------------------------------------------
55 SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle()
56 {
57 LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
58 }
60 // ------------------------------------------------------------------------------------------------
61 SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle()
62 {
63 // nothing to do here
64 }
66 // ------------------------------------------------------------------------------------------------
67 // Returns whether the processing step is present in the given flag field.
68 bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const
69 {
70 return (pFlags & aiProcess_SplitLargeMeshes) != 0;
71 }
73 // ------------------------------------------------------------------------------------------------
74 // Executes the post processing step on the given imported data.
75 void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
76 {
77 if (0xffffffff == this->LIMIT)return;
79 DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin");
80 std::vector<std::pair<aiMesh*, unsigned int> > avList;
82 for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
83 this->SplitMesh(a, pScene->mMeshes[a],avList);
85 if (avList.size() != pScene->mNumMeshes)
86 {
87 // it seems something has been split. rebuild the mesh list
88 delete[] pScene->mMeshes;
89 pScene->mNumMeshes = (unsigned int)avList.size();
90 pScene->mMeshes = new aiMesh*[avList.size()];
92 for (unsigned int i = 0; i < avList.size();++i)
93 pScene->mMeshes[i] = avList[i].first;
95 // now we need to update all nodes
96 this->UpdateNode(pScene->mRootNode,avList);
97 DefaultLogger::get()->info("SplitLargeMeshesProcess_Triangle finished. Meshes have been split");
98 }
99 else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle finished. There was nothing to do");
100 return;
101 }
103 // ------------------------------------------------------------------------------------------------
104 // Setup properties
105 void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp)
106 {
107 // get the current value of the split property
108 this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
109 }
111 // ------------------------------------------------------------------------------------------------
112 // Update a node after some meshes have been split
113 void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode,
114 const std::vector<std::pair<aiMesh*, unsigned int> >& avList)
115 {
116 // for every index in out list build a new entry
117 std::vector<unsigned int> aiEntries;
118 aiEntries.reserve(pcNode->mNumMeshes + 1);
119 for (unsigned int i = 0; i < pcNode->mNumMeshes;++i)
120 {
121 for (unsigned int a = 0; a < avList.size();++a)
122 {
123 if (avList[a].second == pcNode->mMeshes[i])
124 {
125 aiEntries.push_back(a);
126 }
127 }
128 }
130 // now build the new list
131 delete pcNode->mMeshes;
132 pcNode->mNumMeshes = (unsigned int)aiEntries.size();
133 pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
135 for (unsigned int b = 0; b < pcNode->mNumMeshes;++b)
136 pcNode->mMeshes[b] = aiEntries[b];
138 // recusively update all other nodes
139 for (unsigned int i = 0; i < pcNode->mNumChildren;++i)
140 {
141 UpdateNode ( pcNode->mChildren[i], avList );
142 }
143 return;
144 }
146 // ------------------------------------------------------------------------------------------------
147 // Executes the post processing step on the given imported data.
148 void SplitLargeMeshesProcess_Triangle::SplitMesh(
149 unsigned int a,
150 aiMesh* pMesh,
151 std::vector<std::pair<aiMesh*, unsigned int> >& avList)
152 {
153 if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT)
154 {
155 DefaultLogger::get()->info("Mesh exceeds the triangle limit. It will be split ...");
157 // we need to split this mesh into sub meshes
158 // determine the size of a submesh
159 const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1;
161 const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes;
162 const unsigned int iOutVertexNum = iOutFaceNum * 3;
164 // now generate all submeshes
165 for (unsigned int i = 0; i < iSubMeshes;++i)
166 {
167 aiMesh* pcMesh = new aiMesh;
168 pcMesh->mNumFaces = iOutFaceNum;
169 pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
171 // the name carries the adjacency information between the meshes
172 pcMesh->mName = pMesh->mName;
174 if (i == iSubMeshes-1)
175 {
176 pcMesh->mNumFaces = iOutFaceNum + (
177 pMesh->mNumFaces - iOutFaceNum * iSubMeshes);
178 }
179 // copy the list of faces
180 pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
182 const unsigned int iBase = iOutFaceNum * i;
184 // get the total number of indices
185 unsigned int iCnt = 0;
186 for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p)
187 {
188 iCnt += pMesh->mFaces[p].mNumIndices;
189 }
190 pcMesh->mNumVertices = iCnt;
192 // allocate storage
193 if (pMesh->mVertices != NULL)
194 pcMesh->mVertices = new aiVector3D[iCnt];
196 if (pMesh->HasNormals())
197 pcMesh->mNormals = new aiVector3D[iCnt];
199 if (pMesh->HasTangentsAndBitangents())
200 {
201 pcMesh->mTangents = new aiVector3D[iCnt];
202 pcMesh->mBitangents = new aiVector3D[iCnt];
203 }
205 // texture coordinates
206 for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
207 {
208 pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
209 if (pMesh->HasTextureCoords( c))
210 {
211 pcMesh->mTextureCoords[c] = new aiVector3D[iCnt];
212 }
213 }
215 // vertex colors
216 for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
217 {
218 if (pMesh->HasVertexColors( c))
219 {
220 pcMesh->mColors[c] = new aiColor4D[iCnt];
221 }
222 }
224 if (pMesh->HasBones())
225 {
226 // assume the number of bones won't change in most cases
227 pcMesh->mBones = new aiBone*[pMesh->mNumBones];
229 // iterate through all bones of the mesh and find those which
230 // need to be copied to the split mesh
231 std::vector<aiVertexWeight> avTempWeights;
232 for (unsigned int p = 0; p < pcMesh->mNumBones;++p)
233 {
234 aiBone* const bone = pcMesh->mBones[p];
235 avTempWeights.clear();
236 avTempWeights.reserve(bone->mNumWeights / iSubMeshes);
238 for (unsigned int q = 0; q < bone->mNumWeights;++q)
239 {
240 aiVertexWeight& weight = bone->mWeights[q];
241 if(weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum)
242 {
243 avTempWeights.push_back(weight);
244 weight = avTempWeights.back();
245 weight.mVertexId -= iBase;
246 }
247 }
249 if (!avTempWeights.empty())
250 {
251 // we'll need this bone. Copy it ...
252 aiBone* pc = new aiBone();
253 pcMesh->mBones[pcMesh->mNumBones++] = pc;
254 pc->mName = aiString(bone->mName);
255 pc->mNumWeights = (unsigned int)avTempWeights.size();
256 pc->mOffsetMatrix = bone->mOffsetMatrix;
258 // no need to reallocate the array for the last submesh.
259 // Here we can reuse the (large) source array, although
260 // we'll waste some memory
261 if (iSubMeshes-1 == i)
262 {
263 pc->mWeights = bone->mWeights;
264 bone->mWeights = NULL;
265 }
266 else pc->mWeights = new aiVertexWeight[pc->mNumWeights];
268 // copy the weights
269 ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights);
270 }
271 }
272 }
274 // (we will also need to copy the array of indices)
275 unsigned int iCurrent = 0;
276 for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
277 {
278 pcMesh->mFaces[p].mNumIndices = 3;
279 // allocate a new array
280 const unsigned int iTemp = p + iBase;
281 const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices;
283 // setup face type and number of indices
284 pcMesh->mFaces[p].mNumIndices = iNumIndices;
285 unsigned int* pi = pMesh->mFaces[iTemp].mIndices;
286 unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices];
288 // need to update the output primitive types
289 switch (iNumIndices)
290 {
291 case 1:
292 pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
293 break;
294 case 2:
295 pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
296 break;
297 case 3:
298 pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
299 break;
300 default:
301 pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
302 }
304 // and copy the contents of the old array, offset by current base
305 for (unsigned int v = 0; v < iNumIndices;++v)
306 {
307 unsigned int iIndex = pi[v];
308 unsigned int iIndexOut = iCurrent++;
309 piOut[v] = iIndexOut;
311 // copy positions
312 if (pMesh->mVertices != NULL)
313 pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex];
315 // copy normals
316 if (pMesh->HasNormals())
317 pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex];
319 // copy tangents/bitangents
320 if (pMesh->HasTangentsAndBitangents())
321 {
322 pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex];
323 pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex];
324 }
326 // texture coordinates
327 for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
328 {
329 if (pMesh->HasTextureCoords( c))
330 pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex];
331 }
332 // vertex colors
333 for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
334 {
335 if (pMesh->HasVertexColors( c))
336 pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex];
337 }
338 }
339 }
341 // add the newly created mesh to the list
342 avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
343 }
345 // now delete the old mesh data
346 delete pMesh;
347 }
348 else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
349 return;
350 }
352 // ------------------------------------------------------------------------------------------------
353 SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex()
354 {
355 LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
356 }
358 // ------------------------------------------------------------------------------------------------
359 SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex()
360 {
361 // nothing to do here
362 }
364 // ------------------------------------------------------------------------------------------------
365 // Returns whether the processing step is present in the given flag field.
366 bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const
367 {
368 return (pFlags & aiProcess_SplitLargeMeshes) != 0;
369 }
371 // ------------------------------------------------------------------------------------------------
372 // Executes the post processing step on the given imported data.
373 void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
374 {
375 std::vector<std::pair<aiMesh*, unsigned int> > avList;
377 if (0xffffffff == this->LIMIT)return;
379 DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex begin");
380 for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
381 this->SplitMesh(a, pScene->mMeshes[a],avList);
383 if (avList.size() != pScene->mNumMeshes)
384 {
385 // it seems something has been split. rebuild the mesh list
386 delete[] pScene->mMeshes;
387 pScene->mNumMeshes = (unsigned int)avList.size();
388 pScene->mMeshes = new aiMesh*[avList.size()];
390 for (unsigned int i = 0; i < avList.size();++i)
391 pScene->mMeshes[i] = avList[i].first;
393 // now we need to update all nodes
394 SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList);
395 DefaultLogger::get()->info("SplitLargeMeshesProcess_Vertex finished. Meshes have been split");
396 }
397 else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex finished. There was nothing to do");
398 return;
399 }
401 // ------------------------------------------------------------------------------------------------
402 // Setup properties
403 void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp)
404 {
405 this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
406 }
408 // ------------------------------------------------------------------------------------------------
409 // Executes the post processing step on the given imported data.
410 void SplitLargeMeshesProcess_Vertex::SplitMesh(
411 unsigned int a,
412 aiMesh* pMesh,
413 std::vector<std::pair<aiMesh*, unsigned int> >& avList)
414 {
415 if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT)
416 {
417 typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable;
419 // build a per-vertex weight list if necessary
420 VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(pMesh);
422 // we need to split this mesh into sub meshes
423 // determine the estimated size of a submesh
424 // (this could be too large. Max waste is a single digit percentage)
425 const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1;
426 //const unsigned int iOutVertexNum2 = pMesh->mNumVertices /iSubMeshes;
428 // create a std::vector<unsigned int> to indicate which vertices
429 // have already been copied
430 std::vector<unsigned int> avWasCopied;
431 avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF);
433 // try to find a good estimate for the number of output faces
434 // per mesh. Add 12.5% as buffer
435 unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes;
436 iEstimatedSize += iEstimatedSize >> 3;
438 // now generate all submeshes
439 unsigned int iBase = 0;
440 while (true)
441 {
442 const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT;
444 aiMesh* pcMesh = new aiMesh;
445 pcMesh->mNumVertices = 0;
446 pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
448 // the name carries the adjacency information between the meshes
449 pcMesh->mName = pMesh->mName;
451 typedef std::vector<aiVertexWeight> BoneWeightList;
452 if (pMesh->HasBones())
453 {
454 pcMesh->mBones = new aiBone*[pMesh->mNumBones];
455 ::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones);
456 }
458 // clear the temporary helper array
459 if (iBase)
460 {
461 // we can't use memset here we unsigned int needn' be 32 bits
462 for (std::vector<unsigned int>::iterator
463 iter = avWasCopied.begin(),end = avWasCopied.end();
464 iter != end;++iter)
465 {
466 (*iter) = 0xffffffff;
467 }
468 }
470 // output vectors
471 std::vector<aiFace> vFaces;
473 // reserve enough storage for most cases
474 if (pMesh->HasPositions())
475 {
476 pcMesh->mVertices = new aiVector3D[iOutVertexNum];
477 }
478 if (pMesh->HasNormals())
479 {
480 pcMesh->mNormals = new aiVector3D[iOutVertexNum];
481 }
482 if (pMesh->HasTangentsAndBitangents())
483 {
484 pcMesh->mTangents = new aiVector3D[iOutVertexNum];
485 pcMesh->mBitangents = new aiVector3D[iOutVertexNum];
486 }
487 for (unsigned int c = 0; pMesh->HasVertexColors(c);++c)
488 {
489 pcMesh->mColors[c] = new aiColor4D[iOutVertexNum];
490 }
491 for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c)
492 {
493 pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c];
494 pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum];
495 }
496 vFaces.reserve(iEstimatedSize);
498 // (we will also need to copy the array of indices)
499 while (iBase < pMesh->mNumFaces)
500 {
501 // allocate a new array
502 const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices;
504 // doesn't catch degenerates but is quite fast
505 unsigned int iNeed = 0;
506 for (unsigned int v = 0; v < iNumIndices;++v)
507 {
508 unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
510 // check whether we do already have this vertex
511 if (0xFFFFFFFF == avWasCopied[iIndex])
512 {
513 iNeed++;
514 }
515 }
516 if (pcMesh->mNumVertices + iNeed > iOutVertexNum)
517 {
518 // don't use this face
519 break;
520 }
522 vFaces.push_back(aiFace());
523 aiFace& rFace = vFaces.back();
525 // setup face type and number of indices
526 rFace.mNumIndices = iNumIndices;
527 rFace.mIndices = new unsigned int[iNumIndices];
529 // need to update the output primitive types
530 switch (rFace.mNumIndices)
531 {
532 case 1:
533 pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
534 break;
535 case 2:
536 pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
537 break;
538 case 3:
539 pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
540 break;
541 default:
542 pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
543 }
545 // and copy the contents of the old array, offset by current base
546 for (unsigned int v = 0; v < iNumIndices;++v)
547 {
548 unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v];
550 // check whether we do already have this vertex
551 if (0xFFFFFFFF != avWasCopied[iIndex])
552 {
553 rFace.mIndices[v] = avWasCopied[iIndex];
554 continue;
555 }
557 // copy positions
558 pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]);
560 // copy normals
561 if (pMesh->HasNormals())
562 {
563 pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]);
564 }
566 // copy tangents/bitangents
567 if (pMesh->HasTangentsAndBitangents())
568 {
569 pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]);
570 pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]);
571 }
573 // texture coordinates
574 for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
575 {
576 if (pMesh->HasTextureCoords( c))
577 {
578 pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex];
579 }
580 }
581 // vertex colors
582 for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c)
583 {
584 if (pMesh->HasVertexColors( c))
585 {
586 pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex];
587 }
588 }
589 // check whether we have bone weights assigned to this vertex
590 rFace.mIndices[v] = pcMesh->mNumVertices;
591 if (avPerVertexWeights)
592 {
593 VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ];
594 if( !table.empty() )
595 {
596 for (VertexWeightTable::const_iterator
597 iter = table.begin();
598 iter != table.end();++iter)
599 {
600 // allocate the bone weight array if necessary
601 BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first];
602 if (!pcWeightList)
603 {
604 pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList());
605 }
606 pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second));
607 }
608 }
609 }
611 avWasCopied[iIndex] = pcMesh->mNumVertices;
612 pcMesh->mNumVertices++;
613 }
614 iBase++;
615 if(pcMesh->mNumVertices == iOutVertexNum)
616 {
617 // break here. The face is only added if it was complete
618 break;
619 }
620 }
622 // check which bones we'll need to create for this submesh
623 if (pMesh->HasBones())
624 {
625 aiBone** ppCurrent = pcMesh->mBones;
626 for (unsigned int k = 0; k < pMesh->mNumBones;++k)
627 {
628 // check whether the bone is existing
629 BoneWeightList* pcWeightList;
630 if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k]))
631 {
632 aiBone* pcOldBone = pMesh->mBones[k];
633 aiBone* pcOut;
634 *ppCurrent++ = pcOut = new aiBone();
635 pcOut->mName = aiString(pcOldBone->mName);
636 pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix;
637 pcOut->mNumWeights = (unsigned int)pcWeightList->size();
638 pcOut->mWeights = new aiVertexWeight[pcOut->mNumWeights];
640 // copy the vertex weights
641 ::memcpy(pcOut->mWeights,&pcWeightList->operator[](0),
642 pcOut->mNumWeights * sizeof(aiVertexWeight));
644 // delete the temporary bone weight list
645 delete pcWeightList;
646 pcMesh->mNumBones++;
647 }
648 }
649 }
651 // copy the face list to the mesh
652 pcMesh->mFaces = new aiFace[vFaces.size()];
653 pcMesh->mNumFaces = (unsigned int)vFaces.size();
655 for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
656 pcMesh->mFaces[p] = vFaces[p];
658 // add the newly created mesh to the list
659 avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
661 if (iBase == pMesh->mNumFaces)
662 {
663 // have all faces ... finish the outer loop, too
664 break;
665 }
666 }
668 // delete the per-vertex weight list again
669 delete[] avPerVertexWeights;
671 // now delete the old mesh data
672 delete pMesh;
673 return;
674 }
675 avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a));
676 return;
677 }