rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 Open Asset Import Library (assimp)
|
nuclear@0
|
3 ----------------------------------------------------------------------
|
nuclear@0
|
4
|
nuclear@0
|
5 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
6 All rights reserved.
|
nuclear@0
|
7
|
nuclear@0
|
8 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
9 with or without modification, are permitted provided that the
|
nuclear@0
|
10 following conditions are met:
|
nuclear@0
|
11
|
nuclear@0
|
12 * Redistributions of source code must retain the above
|
nuclear@0
|
13 copyright notice, this list of conditions and the
|
nuclear@0
|
14 following disclaimer.
|
nuclear@0
|
15
|
nuclear@0
|
16 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
17 copyright notice, this list of conditions and the
|
nuclear@0
|
18 following disclaimer in the documentation and/or other
|
nuclear@0
|
19 materials provided with the distribution.
|
nuclear@0
|
20
|
nuclear@0
|
21 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
22 contributors may be used to endorse or promote products
|
nuclear@0
|
23 derived from this software without specific prior
|
nuclear@0
|
24 written permission of the assimp team.
|
nuclear@0
|
25
|
nuclear@0
|
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
37
|
nuclear@0
|
38 ----------------------------------------------------------------------
|
nuclear@0
|
39 */
|
nuclear@0
|
40
|
nuclear@0
|
41
|
nuclear@0
|
42 /// @file SplitByBoneCountProcess.cpp
|
nuclear@0
|
43 /// Implementation of the SplitByBoneCount postprocessing step
|
nuclear@0
|
44
|
nuclear@0
|
45 #include "AssimpPCH.h"
|
nuclear@0
|
46
|
nuclear@0
|
47 // internal headers of the post-processing framework
|
nuclear@0
|
48 #include "SplitByBoneCountProcess.h"
|
nuclear@0
|
49
|
nuclear@0
|
50 #include <limits>
|
nuclear@0
|
51
|
nuclear@0
|
52 using namespace Assimp;
|
nuclear@0
|
53
|
nuclear@0
|
54 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
55 // Constructor
|
nuclear@0
|
56 SplitByBoneCountProcess::SplitByBoneCountProcess()
|
nuclear@0
|
57 {
|
nuclear@0
|
58 // set default, might be overriden by importer config
|
nuclear@0
|
59 mMaxBoneCount = AI_SBBC_DEFAULT_MAX_BONES;
|
nuclear@0
|
60 }
|
nuclear@0
|
61
|
nuclear@0
|
62 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
63 // Destructor
|
nuclear@0
|
64 SplitByBoneCountProcess::~SplitByBoneCountProcess()
|
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.
|
nuclear@0
|
71 bool SplitByBoneCountProcess::IsActive( unsigned int pFlags) const
|
nuclear@0
|
72 {
|
nuclear@0
|
73 return !!(pFlags & aiProcess_SplitByBoneCount);
|
nuclear@0
|
74 }
|
nuclear@0
|
75
|
nuclear@0
|
76 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
77 // Updates internal properties
|
nuclear@0
|
78 void SplitByBoneCountProcess::SetupProperties(const Importer* pImp)
|
nuclear@0
|
79 {
|
nuclear@0
|
80 mMaxBoneCount = pImp->GetPropertyInteger(AI_CONFIG_PP_SBBC_MAX_BONES,AI_SBBC_DEFAULT_MAX_BONES);
|
nuclear@0
|
81 }
|
nuclear@0
|
82
|
nuclear@0
|
83 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
84 // Executes the post processing step on the given imported data.
|
nuclear@0
|
85 void SplitByBoneCountProcess::Execute( aiScene* pScene)
|
nuclear@0
|
86 {
|
nuclear@0
|
87 DefaultLogger::get()->debug("SplitByBoneCountProcess begin");
|
nuclear@0
|
88
|
nuclear@0
|
89 // early out
|
nuclear@0
|
90 bool isNecessary = false;
|
nuclear@0
|
91 for( size_t a = 0; a < pScene->mNumMeshes; ++a)
|
nuclear@0
|
92 if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount )
|
nuclear@0
|
93 isNecessary = true;
|
nuclear@0
|
94
|
nuclear@0
|
95 if( !isNecessary )
|
nuclear@0
|
96 {
|
nuclear@0
|
97 DefaultLogger::get()->debug( boost::str( boost::format( "SplitByBoneCountProcess early-out: no meshes with more than %d bones.") % mMaxBoneCount));
|
nuclear@0
|
98 return;
|
nuclear@0
|
99 }
|
nuclear@0
|
100
|
nuclear@0
|
101 // we need to do something. Let's go.
|
nuclear@0
|
102 mSubMeshIndices.clear();
|
nuclear@0
|
103 mSubMeshIndices.resize( pScene->mNumMeshes);
|
nuclear@0
|
104
|
nuclear@0
|
105 // build a new array of meshes for the scene
|
nuclear@0
|
106 std::vector<aiMesh*> meshes;
|
nuclear@0
|
107
|
nuclear@0
|
108 for( size_t a = 0; a < pScene->mNumMeshes; ++a)
|
nuclear@0
|
109 {
|
nuclear@0
|
110 aiMesh* srcMesh = pScene->mMeshes[a];
|
nuclear@0
|
111
|
nuclear@0
|
112 std::vector<aiMesh*> newMeshes;
|
nuclear@0
|
113 SplitMesh( pScene->mMeshes[a], newMeshes);
|
nuclear@0
|
114
|
nuclear@0
|
115 // mesh was split
|
nuclear@0
|
116 if( !newMeshes.empty() )
|
nuclear@0
|
117 {
|
nuclear@0
|
118 // store new meshes and indices of the new meshes
|
nuclear@0
|
119 for( size_t b = 0; b < newMeshes.size(); ++b)
|
nuclear@0
|
120 {
|
nuclear@0
|
121 mSubMeshIndices[a].push_back( meshes.size());
|
nuclear@0
|
122 meshes.push_back( newMeshes[b]);
|
nuclear@0
|
123 }
|
nuclear@0
|
124
|
nuclear@0
|
125 // and destroy the source mesh. It should be completely contained inside the new submeshes
|
nuclear@0
|
126 delete srcMesh;
|
nuclear@0
|
127 }
|
nuclear@0
|
128 else
|
nuclear@0
|
129 {
|
nuclear@0
|
130 // Mesh is kept unchanged - store it's new place in the mesh array
|
nuclear@0
|
131 mSubMeshIndices[a].push_back( meshes.size());
|
nuclear@0
|
132 meshes.push_back( srcMesh);
|
nuclear@0
|
133 }
|
nuclear@0
|
134 }
|
nuclear@0
|
135
|
nuclear@0
|
136 // rebuild the scene's mesh array
|
nuclear@0
|
137 pScene->mNumMeshes = meshes.size();
|
nuclear@0
|
138 delete [] pScene->mMeshes;
|
nuclear@0
|
139 pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
nuclear@0
|
140 std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
|
nuclear@0
|
141
|
nuclear@0
|
142 // recurse through all nodes and translate the node's mesh indices to fit the new mesh array
|
nuclear@0
|
143 UpdateNode( pScene->mRootNode);
|
nuclear@0
|
144
|
nuclear@0
|
145 DefaultLogger::get()->debug( boost::str( boost::format( "SplitByBoneCountProcess end: split %d meshes into %d submeshes.") % mSubMeshIndices.size() % meshes.size()));
|
nuclear@0
|
146 }
|
nuclear@0
|
147
|
nuclear@0
|
148 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
149 // Splits the given mesh by bone count.
|
nuclear@0
|
150 void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh*>& poNewMeshes) const
|
nuclear@0
|
151 {
|
nuclear@0
|
152 // skip if not necessary
|
nuclear@0
|
153 if( pMesh->mNumBones <= mMaxBoneCount )
|
nuclear@0
|
154 return;
|
nuclear@0
|
155
|
nuclear@0
|
156 // necessary optimisation: build a list of all affecting bones for each vertex
|
nuclear@0
|
157 // TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays
|
nuclear@0
|
158 typedef std::pair<size_t, float> BoneWeight;
|
nuclear@0
|
159 std::vector< std::vector<BoneWeight> > vertexBones( pMesh->mNumVertices);
|
nuclear@0
|
160 for( size_t a = 0; a < pMesh->mNumBones; ++a)
|
nuclear@0
|
161 {
|
nuclear@0
|
162 const aiBone* bone = pMesh->mBones[a];
|
nuclear@0
|
163 for( size_t b = 0; b < bone->mNumWeights; ++b)
|
nuclear@0
|
164 vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
|
nuclear@0
|
165 }
|
nuclear@0
|
166
|
nuclear@0
|
167 size_t numFacesHandled = 0;
|
nuclear@0
|
168 std::vector<bool> isFaceHandled( pMesh->mNumFaces, false);
|
nuclear@0
|
169 while( numFacesHandled < pMesh->mNumFaces )
|
nuclear@0
|
170 {
|
nuclear@0
|
171 // which bones are used in the current submesh
|
nuclear@0
|
172 size_t numBones = 0;
|
nuclear@0
|
173 std::vector<bool> isBoneUsed( pMesh->mNumBones, false);
|
nuclear@0
|
174 // indices of the faces which are going to go into this submesh
|
nuclear@0
|
175 std::vector<size_t> subMeshFaces;
|
nuclear@0
|
176 subMeshFaces.reserve( pMesh->mNumFaces);
|
nuclear@0
|
177 // accumulated vertex count of all the faces in this submesh
|
nuclear@0
|
178 size_t numSubMeshVertices = 0;
|
nuclear@0
|
179 // a small local array of new bones for the current face. State of all used bones for that face
|
nuclear@0
|
180 // can only be updated AFTER the face is completely analysed. Thanks to imre for the fix.
|
nuclear@0
|
181 std::vector<size_t> newBonesAtCurrentFace;
|
nuclear@0
|
182
|
nuclear@0
|
183 // add faces to the new submesh as long as all bones affecting the faces' vertices fit in the limit
|
nuclear@0
|
184 for( size_t a = 0; a < pMesh->mNumFaces; ++a)
|
nuclear@0
|
185 {
|
nuclear@0
|
186 // skip if the face is already stored in a submesh
|
nuclear@0
|
187 if( isFaceHandled[a] )
|
nuclear@0
|
188 continue;
|
nuclear@0
|
189
|
nuclear@0
|
190 const aiFace& face = pMesh->mFaces[a];
|
nuclear@0
|
191 // check every vertex if its bones would still fit into the current submesh
|
nuclear@0
|
192 for( size_t b = 0; b < face.mNumIndices; ++b )
|
nuclear@0
|
193 {
|
nuclear@0
|
194 const std::vector<BoneWeight>& vb = vertexBones[face.mIndices[b]];
|
nuclear@0
|
195 for( size_t c = 0; c < vb.size(); ++c)
|
nuclear@0
|
196 {
|
nuclear@0
|
197 size_t boneIndex = vb[c].first;
|
nuclear@0
|
198 // if the bone is already used in this submesh, it's ok
|
nuclear@0
|
199 if( isBoneUsed[boneIndex] )
|
nuclear@0
|
200 continue;
|
nuclear@0
|
201
|
nuclear@0
|
202 // if it's not used, yet, we would need to add it. Store its bone index
|
nuclear@0
|
203 if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
|
nuclear@0
|
204 newBonesAtCurrentFace.push_back( boneIndex);
|
nuclear@0
|
205 }
|
nuclear@0
|
206 }
|
nuclear@0
|
207
|
nuclear@0
|
208 // leave out the face if the new bones required for this face don't fit the bone count limit anymore
|
nuclear@0
|
209 if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
|
nuclear@0
|
210 continue;
|
nuclear@0
|
211
|
nuclear@0
|
212 // mark all new bones as necessary
|
nuclear@0
|
213 while( !newBonesAtCurrentFace.empty() )
|
nuclear@0
|
214 {
|
nuclear@0
|
215 size_t newIndex = newBonesAtCurrentFace.back();
|
nuclear@0
|
216 newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
|
nuclear@0
|
217 if( isBoneUsed[newIndex] )
|
nuclear@0
|
218 continue;
|
nuclear@0
|
219
|
nuclear@0
|
220 isBoneUsed[newIndex] = true;
|
nuclear@0
|
221 numBones++;
|
nuclear@0
|
222 }
|
nuclear@0
|
223
|
nuclear@0
|
224 // store the face index and the vertex count
|
nuclear@0
|
225 subMeshFaces.push_back( a);
|
nuclear@0
|
226 numSubMeshVertices += face.mNumIndices;
|
nuclear@0
|
227
|
nuclear@0
|
228 // remember that this face is handled
|
nuclear@0
|
229 isFaceHandled[a] = true;
|
nuclear@0
|
230 numFacesHandled++;
|
nuclear@0
|
231 }
|
nuclear@0
|
232
|
nuclear@0
|
233 // create a new mesh to hold this subset of the source mesh
|
nuclear@0
|
234 aiMesh* newMesh = new aiMesh;
|
nuclear@0
|
235 if( pMesh->mName.length > 0 )
|
nuclear@0
|
236 newMesh->mName.Set( boost::str( boost::format( "%s_sub%d") % pMesh->mName.data % poNewMeshes.size()));
|
nuclear@0
|
237 newMesh->mMaterialIndex = pMesh->mMaterialIndex;
|
nuclear@0
|
238 newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
|
nuclear@0
|
239 poNewMeshes.push_back( newMesh);
|
nuclear@0
|
240
|
nuclear@0
|
241 // create all the arrays for this mesh if the old mesh contained them
|
nuclear@0
|
242 newMesh->mNumVertices = numSubMeshVertices;
|
nuclear@0
|
243 newMesh->mNumFaces = subMeshFaces.size();
|
nuclear@0
|
244 newMesh->mVertices = new aiVector3D[newMesh->mNumVertices];
|
nuclear@0
|
245 if( pMesh->HasNormals() )
|
nuclear@0
|
246 newMesh->mNormals = new aiVector3D[newMesh->mNumVertices];
|
nuclear@0
|
247 if( pMesh->HasTangentsAndBitangents() )
|
nuclear@0
|
248 {
|
nuclear@0
|
249 newMesh->mTangents = new aiVector3D[newMesh->mNumVertices];
|
nuclear@0
|
250 newMesh->mBitangents = new aiVector3D[newMesh->mNumVertices];
|
nuclear@0
|
251 }
|
nuclear@0
|
252 for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
|
nuclear@0
|
253 {
|
nuclear@0
|
254 if( pMesh->HasTextureCoords( a) )
|
nuclear@0
|
255 newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices];
|
nuclear@0
|
256 newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
|
nuclear@0
|
257 }
|
nuclear@0
|
258 for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
|
nuclear@0
|
259 {
|
nuclear@0
|
260 if( pMesh->HasVertexColors( a) )
|
nuclear@0
|
261 newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices];
|
nuclear@0
|
262 }
|
nuclear@0
|
263
|
nuclear@0
|
264 // and copy over the data, generating faces with linear indices along the way
|
nuclear@0
|
265 newMesh->mFaces = new aiFace[subMeshFaces.size()];
|
nuclear@0
|
266 size_t nvi = 0; // next vertex index
|
nuclear@0
|
267 std::vector<size_t> previousVertexIndices( numSubMeshVertices, std::numeric_limits<size_t>::max()); // per new vertex: its index in the source mesh
|
nuclear@0
|
268 for( size_t a = 0; a < subMeshFaces.size(); ++a )
|
nuclear@0
|
269 {
|
nuclear@0
|
270 const aiFace& srcFace = pMesh->mFaces[subMeshFaces[a]];
|
nuclear@0
|
271 aiFace& dstFace = newMesh->mFaces[a];
|
nuclear@0
|
272 dstFace.mNumIndices = srcFace.mNumIndices;
|
nuclear@0
|
273 dstFace.mIndices = new unsigned int[dstFace.mNumIndices];
|
nuclear@0
|
274
|
nuclear@0
|
275 // accumulate linearly all the vertices of the source face
|
nuclear@0
|
276 for( size_t b = 0; b < dstFace.mNumIndices; ++b )
|
nuclear@0
|
277 {
|
nuclear@0
|
278 size_t srcIndex = srcFace.mIndices[b];
|
nuclear@0
|
279 dstFace.mIndices[b] = nvi;
|
nuclear@0
|
280 previousVertexIndices[nvi] = srcIndex;
|
nuclear@0
|
281
|
nuclear@0
|
282 newMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
|
nuclear@0
|
283 if( pMesh->HasNormals() )
|
nuclear@0
|
284 newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
|
nuclear@0
|
285 if( pMesh->HasTangentsAndBitangents() )
|
nuclear@0
|
286 {
|
nuclear@0
|
287 newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
|
nuclear@0
|
288 newMesh->mBitangents[nvi] = pMesh->mBitangents[srcIndex];
|
nuclear@0
|
289 }
|
nuclear@0
|
290 for( size_t c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c )
|
nuclear@0
|
291 {
|
nuclear@0
|
292 if( pMesh->HasTextureCoords( c) )
|
nuclear@0
|
293 newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
|
nuclear@0
|
294 }
|
nuclear@0
|
295 for( size_t c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c )
|
nuclear@0
|
296 {
|
nuclear@0
|
297 if( pMesh->HasVertexColors( c) )
|
nuclear@0
|
298 newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
|
nuclear@0
|
299 }
|
nuclear@0
|
300
|
nuclear@0
|
301 nvi++;
|
nuclear@0
|
302 }
|
nuclear@0
|
303 }
|
nuclear@0
|
304
|
nuclear@0
|
305 ai_assert( nvi == numSubMeshVertices );
|
nuclear@0
|
306
|
nuclear@0
|
307 // Create the bones for the new submesh: first create the bone array
|
nuclear@0
|
308 newMesh->mNumBones = 0;
|
nuclear@0
|
309 newMesh->mBones = new aiBone*[numBones];
|
nuclear@0
|
310
|
nuclear@0
|
311 std::vector<size_t> mappedBoneIndex( pMesh->mNumBones, std::numeric_limits<size_t>::max());
|
nuclear@0
|
312 for( size_t a = 0; a < pMesh->mNumBones; ++a )
|
nuclear@0
|
313 {
|
nuclear@0
|
314 if( !isBoneUsed[a] )
|
nuclear@0
|
315 continue;
|
nuclear@0
|
316
|
nuclear@0
|
317 // create the new bone
|
nuclear@0
|
318 const aiBone* srcBone = pMesh->mBones[a];
|
nuclear@0
|
319 aiBone* dstBone = new aiBone;
|
nuclear@0
|
320 mappedBoneIndex[a] = newMesh->mNumBones;
|
nuclear@0
|
321 newMesh->mBones[newMesh->mNumBones++] = dstBone;
|
nuclear@0
|
322 dstBone->mName = srcBone->mName;
|
nuclear@0
|
323 dstBone->mOffsetMatrix = srcBone->mOffsetMatrix;
|
nuclear@0
|
324 dstBone->mNumWeights = 0;
|
nuclear@0
|
325 }
|
nuclear@0
|
326
|
nuclear@0
|
327 ai_assert( newMesh->mNumBones == numBones );
|
nuclear@0
|
328
|
nuclear@0
|
329 // iterate over all new vertices and count which bones affected its old vertex in the source mesh
|
nuclear@0
|
330 for( size_t a = 0; a < numSubMeshVertices; ++a )
|
nuclear@0
|
331 {
|
nuclear@0
|
332 size_t oldIndex = previousVertexIndices[a];
|
nuclear@0
|
333 const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[oldIndex];
|
nuclear@0
|
334
|
nuclear@0
|
335 for( size_t b = 0; b < bonesOnThisVertex.size(); ++b )
|
nuclear@0
|
336 {
|
nuclear@0
|
337 size_t newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
|
nuclear@0
|
338 if( newBoneIndex != std::numeric_limits<size_t>::max() )
|
nuclear@0
|
339 newMesh->mBones[newBoneIndex]->mNumWeights++;
|
nuclear@0
|
340 }
|
nuclear@0
|
341 }
|
nuclear@0
|
342
|
nuclear@0
|
343 // allocate all bone weight arrays accordingly
|
nuclear@0
|
344 for( size_t a = 0; a < newMesh->mNumBones; ++a )
|
nuclear@0
|
345 {
|
nuclear@0
|
346 aiBone* bone = newMesh->mBones[a];
|
nuclear@0
|
347 ai_assert( bone->mNumWeights > 0 );
|
nuclear@0
|
348 bone->mWeights = new aiVertexWeight[bone->mNumWeights];
|
nuclear@0
|
349 bone->mNumWeights = 0; // for counting up in the next step
|
nuclear@0
|
350 }
|
nuclear@0
|
351
|
nuclear@0
|
352 // now copy all the bone vertex weights for all the vertices which made it into the new submesh
|
nuclear@0
|
353 for( size_t a = 0; a < numSubMeshVertices; ++a)
|
nuclear@0
|
354 {
|
nuclear@0
|
355 // find the source vertex for it in the source mesh
|
nuclear@0
|
356 size_t previousIndex = previousVertexIndices[a];
|
nuclear@0
|
357 // these bones were affecting it
|
nuclear@0
|
358 const std::vector<BoneWeight>& bonesOnThisVertex = vertexBones[previousIndex];
|
nuclear@0
|
359 // all of the bones affecting it should be present in the new submesh, or else
|
nuclear@0
|
360 // the face it comprises shouldn't be present
|
nuclear@0
|
361 for( size_t b = 0; b < bonesOnThisVertex.size(); ++b)
|
nuclear@0
|
362 {
|
nuclear@0
|
363 size_t newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
|
nuclear@0
|
364 ai_assert( newBoneIndex != std::numeric_limits<size_t>::max() );
|
nuclear@0
|
365 aiVertexWeight* dstWeight = newMesh->mBones[newBoneIndex]->mWeights + newMesh->mBones[newBoneIndex]->mNumWeights;
|
nuclear@0
|
366 newMesh->mBones[newBoneIndex]->mNumWeights++;
|
nuclear@0
|
367
|
nuclear@0
|
368 dstWeight->mVertexId = a;
|
nuclear@0
|
369 dstWeight->mWeight = bonesOnThisVertex[b].second;
|
nuclear@0
|
370 }
|
nuclear@0
|
371 }
|
nuclear@0
|
372
|
nuclear@0
|
373 // I have the strange feeling that this will break apart at some point in time...
|
nuclear@0
|
374 }
|
nuclear@0
|
375 }
|
nuclear@0
|
376
|
nuclear@0
|
377 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
378 // Recursively updates the node's mesh list to account for the changed mesh list
|
nuclear@0
|
379 void SplitByBoneCountProcess::UpdateNode( aiNode* pNode) const
|
nuclear@0
|
380 {
|
nuclear@0
|
381 // rebuild the node's mesh index list
|
nuclear@0
|
382 if( pNode->mNumMeshes > 0 )
|
nuclear@0
|
383 {
|
nuclear@0
|
384 std::vector<size_t> newMeshList;
|
nuclear@0
|
385 for( size_t a = 0; a < pNode->mNumMeshes; ++a)
|
nuclear@0
|
386 {
|
nuclear@0
|
387 size_t srcIndex = pNode->mMeshes[a];
|
nuclear@0
|
388 const std::vector<size_t>& replaceMeshes = mSubMeshIndices[srcIndex];
|
nuclear@0
|
389 newMeshList.insert( newMeshList.end(), replaceMeshes.begin(), replaceMeshes.end());
|
nuclear@0
|
390 }
|
nuclear@0
|
391
|
nuclear@0
|
392 delete pNode->mMeshes;
|
nuclear@0
|
393 pNode->mNumMeshes = newMeshList.size();
|
nuclear@0
|
394 pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
|
nuclear@0
|
395 std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
|
nuclear@0
|
396 }
|
nuclear@0
|
397
|
nuclear@0
|
398 // do that also recursively for all children
|
nuclear@0
|
399 for( size_t a = 0; a < pNode->mNumChildren; ++a )
|
nuclear@0
|
400 {
|
nuclear@0
|
401 UpdateNode( pNode->mChildren[a]);
|
nuclear@0
|
402 }
|
nuclear@0
|
403 }
|