1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
4
5 Copyright (c) 2006-2015, assimp team
6 All rights reserved.
7
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:
11
12 * Redistributions of source code must retain the above
13 copyright notice, this list of conditions and the
14 following disclaimer.
15
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.
20
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.
25
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.
37
38 ----------------------------------------------------------------------
39 */
40
41
42 /** @file Implementation of the SplitLargeMeshes postprocessing step
43 */
44
45
46
47 // internal headers of the post-processing framework
48 #include "SplitLargeMeshes.h"
49 #include "ProcessHelper.h"
50
51 using namespace Assimp;
52
53
54 // ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Triangle()55 SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle()
56 {
57 LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES;
58 }
59
60 // ------------------------------------------------------------------------------------------------
~SplitLargeMeshesProcess_Triangle()61 SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle()
62 {
63 // nothing to do here
64 }
65
66 // ------------------------------------------------------------------------------------------------
67 // Returns whether the processing step is present in the given flag field.
IsActive(unsigned int pFlags) const68 bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const
69 {
70 return (pFlags & aiProcess_SplitLargeMeshes) != 0;
71 }
72
73 // ------------------------------------------------------------------------------------------------
74 // Executes the post processing step on the given imported data.
Execute(aiScene * pScene)75 void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene)
76 {
77 if (0xffffffff == this->LIMIT)return;
78
79 DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin");
80 std::vector<std::pair<aiMesh*, unsigned int> > avList;
81
82 for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
83 this->SplitMesh(a, pScene->mMeshes[a],avList);
84
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()];
91
92 for (unsigned int i = 0; i < avList.size();++i)
93 pScene->mMeshes[i] = avList[i].first;
94
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 }
102
103 // ------------------------------------------------------------------------------------------------
104 // Setup properties
SetupProperties(const Importer * pImp)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 }
110
111 // ------------------------------------------------------------------------------------------------
112 // Update a node after some meshes have been split
UpdateNode(aiNode * pcNode,const std::vector<std::pair<aiMesh *,unsigned int>> & avList)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 }
129
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];
134
135 for (unsigned int b = 0; b < pcNode->mNumMeshes;++b)
136 pcNode->mMeshes[b] = aiEntries[b];
137
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 }
145
146 // ------------------------------------------------------------------------------------------------
147 // Executes the post processing step on the given imported data.
SplitMesh(unsigned int a,aiMesh * pMesh,std::vector<std::pair<aiMesh *,unsigned int>> & avList)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 ...");
156
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;
160
161 const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes;
162 const unsigned int iOutVertexNum = iOutFaceNum * 3;
163
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;
170
171 // the name carries the adjacency information between the meshes
172 pcMesh->mName = pMesh->mName;
173
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];
181
182 const unsigned int iBase = iOutFaceNum * i;
183
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;
191
192 // allocate storage
193 if (pMesh->mVertices != NULL)
194 pcMesh->mVertices = new aiVector3D[iCnt];
195
196 if (pMesh->HasNormals())
197 pcMesh->mNormals = new aiVector3D[iCnt];
198
199 if (pMesh->HasTangentsAndBitangents())
200 {
201 pcMesh->mTangents = new aiVector3D[iCnt];
202 pcMesh->mBitangents = new aiVector3D[iCnt];
203 }
204
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 }
214
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 }
223
224 if (pMesh->HasBones())
225 {
226 // assume the number of bones won't change in most cases
227 pcMesh->mBones = new aiBone*[pMesh->mNumBones];
228
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);
237
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 }
248
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;
257
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];
267
268 // copy the weights
269 ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights);
270 }
271 }
272 }
273
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;
282
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];
287
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 }
303
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;
310
311 // copy positions
312 if (pMesh->mVertices != NULL)
313 pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex];
314
315 // copy normals
316 if (pMesh->HasNormals())
317 pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex];
318
319 // copy tangents/bitangents
320 if (pMesh->HasTangentsAndBitangents())
321 {
322 pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex];
323 pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex];
324 }
325
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 }
340
341 // add the newly created mesh to the list
342 avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
343 }
344
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 }
351
352 // ------------------------------------------------------------------------------------------------
SplitLargeMeshesProcess_Vertex()353 SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex()
354 {
355 LIMIT = AI_SLM_DEFAULT_MAX_VERTICES;
356 }
357
358 // ------------------------------------------------------------------------------------------------
~SplitLargeMeshesProcess_Vertex()359 SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex()
360 {
361 // nothing to do here
362 }
363
364 // ------------------------------------------------------------------------------------------------
365 // Returns whether the processing step is present in the given flag field.
IsActive(unsigned int pFlags) const366 bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const
367 {
368 return (pFlags & aiProcess_SplitLargeMeshes) != 0;
369 }
370
371 // ------------------------------------------------------------------------------------------------
372 // Executes the post processing step on the given imported data.
Execute(aiScene * pScene)373 void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene)
374 {
375 std::vector<std::pair<aiMesh*, unsigned int> > avList;
376
377 if (0xffffffff == this->LIMIT)return;
378
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);
382
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()];
389
390 for (unsigned int i = 0; i < avList.size();++i)
391 pScene->mMeshes[i] = avList[i].first;
392
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 }
400
401 // ------------------------------------------------------------------------------------------------
402 // Setup properties
SetupProperties(const Importer * pImp)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 }
407
408 // ------------------------------------------------------------------------------------------------
409 // Executes the post processing step on the given imported data.
SplitMesh(unsigned int a,aiMesh * pMesh,std::vector<std::pair<aiMesh *,unsigned int>> & avList)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;
418
419 // build a per-vertex weight list if necessary
420 VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(pMesh);
421
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;
427
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);
432
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;
437
438 // now generate all submeshes
439 unsigned int iBase = 0;
440 while (true)
441 {
442 const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT;
443
444 aiMesh* pcMesh = new aiMesh;
445 pcMesh->mNumVertices = 0;
446 pcMesh->mMaterialIndex = pMesh->mMaterialIndex;
447
448 // the name carries the adjacency information between the meshes
449 pcMesh->mName = pMesh->mName;
450
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 }
457
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 }
469
470 // output vectors
471 std::vector<aiFace> vFaces;
472
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);
497
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;
503
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];
509
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 }
521
522 vFaces.push_back(aiFace());
523 aiFace& rFace = vFaces.back();
524
525 // setup face type and number of indices
526 rFace.mNumIndices = iNumIndices;
527 rFace.mIndices = new unsigned int[iNumIndices];
528
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 }
544
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];
549
550 // check whether we do already have this vertex
551 if (0xFFFFFFFF != avWasCopied[iIndex])
552 {
553 rFace.mIndices[v] = avWasCopied[iIndex];
554 continue;
555 }
556
557 // copy positions
558 pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]);
559
560 // copy normals
561 if (pMesh->HasNormals())
562 {
563 pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]);
564 }
565
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 }
572
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 }
610
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 }
621
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];
639
640 // copy the vertex weights
641 ::memcpy(pcOut->mWeights,&pcWeightList->operator[](0),
642 pcOut->mNumWeights * sizeof(aiVertexWeight));
643
644 // delete the temporary bone weight list
645 delete pcWeightList;
646 pcMesh->mNumBones++;
647 }
648 }
649 }
650
651 // copy the face list to the mesh
652 pcMesh->mFaces = new aiFace[vFaces.size()];
653 pcMesh->mNumFaces = (unsigned int)vFaces.size();
654
655 for (unsigned int p = 0; p < pcMesh->mNumFaces;++p)
656 pcMesh->mFaces[p] = vFaces[p];
657
658 // add the newly created mesh to the list
659 avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a));
660
661 if (iBase == pMesh->mNumFaces)
662 {
663 // have all faces ... finish the outer loop, too
664 break;
665 }
666 }
667
668 // delete the per-vertex weight list again
669 delete[] avPerVertexWeights;
670
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 }
678