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 /// @file DeboneProcess.cpp
|
nuclear@0
|
42 /** Implementation of the DeboneProcess post processing step */
|
nuclear@0
|
43
|
nuclear@0
|
44 #include "AssimpPCH.h"
|
nuclear@0
|
45
|
nuclear@0
|
46 // internal headers of the post-processing framework
|
nuclear@0
|
47 #include "ProcessHelper.h"
|
nuclear@0
|
48 #include "DeboneProcess.h"
|
nuclear@0
|
49
|
nuclear@0
|
50
|
nuclear@0
|
51 using namespace Assimp;
|
nuclear@0
|
52
|
nuclear@0
|
53 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
54 // Constructor to be privately used by Importer
|
nuclear@0
|
55 DeboneProcess::DeboneProcess()
|
nuclear@0
|
56 {
|
nuclear@0
|
57 mNumBones = 0;
|
nuclear@0
|
58 mNumBonesCanDoWithout = 0;
|
nuclear@0
|
59
|
nuclear@0
|
60 mThreshold = AI_DEBONE_THRESHOLD;
|
nuclear@0
|
61 mAllOrNone = false;
|
nuclear@0
|
62 }
|
nuclear@0
|
63
|
nuclear@0
|
64 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
65 // Destructor, private as well
|
nuclear@0
|
66 DeboneProcess::~DeboneProcess()
|
nuclear@0
|
67 {
|
nuclear@0
|
68 // nothing to do here
|
nuclear@0
|
69 }
|
nuclear@0
|
70
|
nuclear@0
|
71 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
72 // Returns whether the processing step is present in the given flag field.
|
nuclear@0
|
73 bool DeboneProcess::IsActive( unsigned int pFlags) const
|
nuclear@0
|
74 {
|
nuclear@0
|
75 return (pFlags & aiProcess_Debone) != 0;
|
nuclear@0
|
76 }
|
nuclear@0
|
77
|
nuclear@0
|
78 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
79 // Executes the post processing step on the given imported data.
|
nuclear@0
|
80 void DeboneProcess::SetupProperties(const Importer* pImp)
|
nuclear@0
|
81 {
|
nuclear@0
|
82 // get the current value of the property
|
nuclear@0
|
83 mAllOrNone = pImp->GetPropertyInteger(AI_CONFIG_PP_DB_ALL_OR_NONE,0)?true:false;
|
nuclear@0
|
84 mThreshold = pImp->GetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD,AI_DEBONE_THRESHOLD);
|
nuclear@0
|
85 }
|
nuclear@0
|
86
|
nuclear@0
|
87 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
88 // Executes the post processing step on the given imported data.
|
nuclear@0
|
89 void DeboneProcess::Execute( aiScene* pScene)
|
nuclear@0
|
90 {
|
nuclear@0
|
91 DefaultLogger::get()->debug("DeboneProcess begin");
|
nuclear@0
|
92
|
nuclear@0
|
93 if(!pScene->mNumMeshes) {
|
nuclear@0
|
94 return;
|
nuclear@0
|
95 }
|
nuclear@0
|
96
|
nuclear@0
|
97 std::vector<bool> splitList(pScene->mNumMeshes);
|
nuclear@0
|
98 for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
|
nuclear@0
|
99 splitList[a] = ConsiderMesh( pScene->mMeshes[a] );
|
nuclear@0
|
100 }
|
nuclear@0
|
101
|
nuclear@0
|
102 int numSplits = 0;
|
nuclear@0
|
103
|
nuclear@0
|
104 if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones)) {
|
nuclear@0
|
105 for(unsigned int a = 0; a < pScene->mNumMeshes; a++) {
|
nuclear@0
|
106 if(splitList[a]) {
|
nuclear@0
|
107 numSplits++;
|
nuclear@0
|
108 }
|
nuclear@0
|
109 }
|
nuclear@0
|
110 }
|
nuclear@0
|
111
|
nuclear@0
|
112 if(numSplits) {
|
nuclear@0
|
113 // we need to do something. Let's go.
|
nuclear@0
|
114 mSubMeshIndices.clear();
|
nuclear@0
|
115 mSubMeshIndices.resize(pScene->mNumMeshes);
|
nuclear@0
|
116
|
nuclear@0
|
117 // build a new array of meshes for the scene
|
nuclear@0
|
118 std::vector<aiMesh*> meshes;
|
nuclear@0
|
119
|
nuclear@0
|
120 for(unsigned int a=0;a<pScene->mNumMeshes;a++)
|
nuclear@0
|
121 {
|
nuclear@0
|
122 aiMesh* srcMesh = pScene->mMeshes[a];
|
nuclear@0
|
123
|
nuclear@0
|
124 std::vector<std::pair<aiMesh*,const aiBone*> > newMeshes;
|
nuclear@0
|
125
|
nuclear@0
|
126 if(splitList[a]) {
|
nuclear@0
|
127 SplitMesh(srcMesh,newMeshes);
|
nuclear@0
|
128 }
|
nuclear@0
|
129
|
nuclear@0
|
130 // mesh was split
|
nuclear@0
|
131 if(!newMeshes.empty()) {
|
nuclear@0
|
132 unsigned int out = 0, in = srcMesh->mNumBones;
|
nuclear@0
|
133
|
nuclear@0
|
134 // store new meshes and indices of the new meshes
|
nuclear@0
|
135 for(unsigned int b=0;b<newMeshes.size();b++) {
|
nuclear@0
|
136 const aiString *find = newMeshes[b].second?&newMeshes[b].second->mName:0;
|
nuclear@0
|
137
|
nuclear@0
|
138 aiNode *theNode = find?pScene->mRootNode->FindNode(*find):0;
|
nuclear@0
|
139 std::pair<unsigned int,aiNode*> push_pair(meshes.size(),theNode);
|
nuclear@0
|
140
|
nuclear@0
|
141 mSubMeshIndices[a].push_back(push_pair);
|
nuclear@0
|
142 meshes.push_back(newMeshes[b].first);
|
nuclear@0
|
143
|
nuclear@0
|
144 out+=newMeshes[b].first->mNumBones;
|
nuclear@0
|
145 }
|
nuclear@0
|
146
|
nuclear@0
|
147 if(!DefaultLogger::isNullLogger()) {
|
nuclear@0
|
148 char buffer[1024];
|
nuclear@0
|
149 ::sprintf(buffer,"Removed %i bones. Input bones: %i. Output bones: %i",in-out,in,out);
|
nuclear@0
|
150 DefaultLogger::get()->info(buffer);
|
nuclear@0
|
151 }
|
nuclear@0
|
152
|
nuclear@0
|
153 // and destroy the source mesh. It should be completely contained inside the new submeshes
|
nuclear@0
|
154 delete srcMesh;
|
nuclear@0
|
155 }
|
nuclear@0
|
156 else {
|
nuclear@0
|
157 // Mesh is kept unchanged - store it's new place in the mesh array
|
nuclear@0
|
158 mSubMeshIndices[a].push_back(std::pair<unsigned int,aiNode*>(meshes.size(),(aiNode*)0));
|
nuclear@0
|
159 meshes.push_back(srcMesh);
|
nuclear@0
|
160 }
|
nuclear@0
|
161 }
|
nuclear@0
|
162
|
nuclear@0
|
163 // rebuild the scene's mesh array
|
nuclear@0
|
164 pScene->mNumMeshes = meshes.size();
|
nuclear@0
|
165 delete [] pScene->mMeshes;
|
nuclear@0
|
166 pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
nuclear@0
|
167 std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
|
nuclear@0
|
168
|
nuclear@0
|
169 // recurse through all nodes and translate the node's mesh indices to fit the new mesh array
|
nuclear@0
|
170 UpdateNode( pScene->mRootNode);
|
nuclear@0
|
171 }
|
nuclear@0
|
172
|
nuclear@0
|
173 DefaultLogger::get()->debug("DeboneProcess end");
|
nuclear@0
|
174 }
|
nuclear@0
|
175
|
nuclear@0
|
176 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
177 // Counts bones total/removable in a given mesh.
|
nuclear@0
|
178 bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh)
|
nuclear@0
|
179 {
|
nuclear@0
|
180 if(!pMesh->HasBones()) {
|
nuclear@0
|
181 return false;
|
nuclear@0
|
182 }
|
nuclear@0
|
183
|
nuclear@0
|
184 bool split = false;
|
nuclear@0
|
185
|
nuclear@0
|
186 //interstitial faces not permitted
|
nuclear@0
|
187 bool isInterstitialRequired = false;
|
nuclear@0
|
188
|
nuclear@0
|
189 std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
|
nuclear@0
|
190 std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
|
nuclear@0
|
191
|
nuclear@0
|
192 const unsigned int cUnowned = UINT_MAX;
|
nuclear@0
|
193 const unsigned int cCoowned = UINT_MAX-1;
|
nuclear@0
|
194
|
nuclear@0
|
195 for(unsigned int i=0;i<pMesh->mNumBones;i++) {
|
nuclear@0
|
196 for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
|
nuclear@0
|
197 float w = pMesh->mBones[i]->mWeights[j].mWeight;
|
nuclear@0
|
198
|
nuclear@0
|
199 if(w==0.0f) {
|
nuclear@0
|
200 continue;
|
nuclear@0
|
201 }
|
nuclear@0
|
202
|
nuclear@0
|
203 unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
|
nuclear@0
|
204 if(w>=mThreshold) {
|
nuclear@0
|
205
|
nuclear@0
|
206 if(vertexBones[vid]!=cUnowned) {
|
nuclear@0
|
207 if(vertexBones[vid]==i) //double entry
|
nuclear@0
|
208 {
|
nuclear@0
|
209 DefaultLogger::get()->warn("Encountered double entry in bone weights");
|
nuclear@0
|
210 }
|
nuclear@0
|
211 else //TODO: track attraction in order to break tie
|
nuclear@0
|
212 {
|
nuclear@0
|
213 vertexBones[vid] = cCoowned;
|
nuclear@0
|
214 }
|
nuclear@0
|
215 }
|
nuclear@0
|
216 else vertexBones[vid] = i;
|
nuclear@0
|
217 }
|
nuclear@0
|
218
|
nuclear@0
|
219 if(!isBoneNecessary[i]) {
|
nuclear@0
|
220 isBoneNecessary[i] = w<mThreshold;
|
nuclear@0
|
221 }
|
nuclear@0
|
222 }
|
nuclear@0
|
223
|
nuclear@0
|
224 if(!isBoneNecessary[i]) {
|
nuclear@0
|
225 isInterstitialRequired = true;
|
nuclear@0
|
226 }
|
nuclear@0
|
227 }
|
nuclear@0
|
228
|
nuclear@0
|
229 if(isInterstitialRequired) {
|
nuclear@0
|
230 for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
|
nuclear@0
|
231 unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
|
nuclear@0
|
232
|
nuclear@0
|
233 for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
|
nuclear@0
|
234 unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
|
nuclear@0
|
235
|
nuclear@0
|
236 if(v!=w) {
|
nuclear@0
|
237 if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
|
nuclear@0
|
238 if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
|
nuclear@0
|
239 }
|
nuclear@0
|
240 }
|
nuclear@0
|
241 }
|
nuclear@0
|
242 }
|
nuclear@0
|
243
|
nuclear@0
|
244 for(unsigned int i=0;i<pMesh->mNumBones;i++) {
|
nuclear@0
|
245 if(!isBoneNecessary[i]) {
|
nuclear@0
|
246 mNumBonesCanDoWithout++;
|
nuclear@0
|
247 split = true;
|
nuclear@0
|
248 }
|
nuclear@0
|
249
|
nuclear@0
|
250 mNumBones++;
|
nuclear@0
|
251 }
|
nuclear@0
|
252 return split;
|
nuclear@0
|
253 }
|
nuclear@0
|
254
|
nuclear@0
|
255 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
256 // Splits the given mesh by bone count.
|
nuclear@0
|
257 void DeboneProcess::SplitMesh( const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const
|
nuclear@0
|
258 {
|
nuclear@0
|
259 // same deal here as ConsiderMesh basically
|
nuclear@0
|
260
|
nuclear@0
|
261 std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
|
nuclear@0
|
262 std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
|
nuclear@0
|
263
|
nuclear@0
|
264 const unsigned int cUnowned = UINT_MAX;
|
nuclear@0
|
265 const unsigned int cCoowned = UINT_MAX-1;
|
nuclear@0
|
266
|
nuclear@0
|
267 for(unsigned int i=0;i<pMesh->mNumBones;i++) {
|
nuclear@0
|
268 for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
|
nuclear@0
|
269 float w = pMesh->mBones[i]->mWeights[j].mWeight;
|
nuclear@0
|
270
|
nuclear@0
|
271 if(w==0.0f) {
|
nuclear@0
|
272 continue;
|
nuclear@0
|
273 }
|
nuclear@0
|
274
|
nuclear@0
|
275 unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
|
nuclear@0
|
276
|
nuclear@0
|
277 if(w>=mThreshold) {
|
nuclear@0
|
278 if(vertexBones[vid]!=cUnowned) {
|
nuclear@0
|
279 if(vertexBones[vid]==i) //double entry
|
nuclear@0
|
280 {
|
nuclear@0
|
281 //DefaultLogger::get()->warn("Encountered double entry in bone weights");
|
nuclear@0
|
282 }
|
nuclear@0
|
283 else //TODO: track attraction in order to break tie
|
nuclear@0
|
284 {
|
nuclear@0
|
285 vertexBones[vid] = cCoowned;
|
nuclear@0
|
286 }
|
nuclear@0
|
287 }
|
nuclear@0
|
288 else vertexBones[vid] = i;
|
nuclear@0
|
289 }
|
nuclear@0
|
290
|
nuclear@0
|
291 if(!isBoneNecessary[i]) {
|
nuclear@0
|
292 isBoneNecessary[i] = w<mThreshold;
|
nuclear@0
|
293 }
|
nuclear@0
|
294 }
|
nuclear@0
|
295 }
|
nuclear@0
|
296
|
nuclear@0
|
297 unsigned int nFacesUnowned = 0;
|
nuclear@0
|
298
|
nuclear@0
|
299 std::vector<unsigned int> faceBones(pMesh->mNumFaces,UINT_MAX);
|
nuclear@0
|
300 std::vector<unsigned int> facesPerBone(pMesh->mNumBones,0);
|
nuclear@0
|
301
|
nuclear@0
|
302 for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
|
nuclear@0
|
303 unsigned int nInterstitial = 1;
|
nuclear@0
|
304
|
nuclear@0
|
305 unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
|
nuclear@0
|
306
|
nuclear@0
|
307 for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
|
nuclear@0
|
308 unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
|
nuclear@0
|
309
|
nuclear@0
|
310 if(v!=w) {
|
nuclear@0
|
311 if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
|
nuclear@0
|
312 if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
|
nuclear@0
|
313 }
|
nuclear@0
|
314 else nInterstitial++;
|
nuclear@0
|
315 }
|
nuclear@0
|
316
|
nuclear@0
|
317 if(v<pMesh->mNumBones &&nInterstitial==pMesh->mFaces[i].mNumIndices) {
|
nuclear@0
|
318 faceBones[i] = v; //primitive belongs to bone #v
|
nuclear@0
|
319 facesPerBone[v]++;
|
nuclear@0
|
320 }
|
nuclear@0
|
321 else nFacesUnowned++;
|
nuclear@0
|
322 }
|
nuclear@0
|
323
|
nuclear@0
|
324 // invalidate any "cojoined" faces
|
nuclear@0
|
325 for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
|
nuclear@0
|
326 if(faceBones[i]<pMesh->mNumBones&&isBoneNecessary[faceBones[i]])
|
nuclear@0
|
327 {
|
nuclear@0
|
328 ai_assert(facesPerBone[faceBones[i]]>0);
|
nuclear@0
|
329 facesPerBone[faceBones[i]]--;
|
nuclear@0
|
330
|
nuclear@0
|
331 nFacesUnowned++;
|
nuclear@0
|
332 faceBones[i] = cUnowned;
|
nuclear@0
|
333 }
|
nuclear@0
|
334 }
|
nuclear@0
|
335
|
nuclear@0
|
336 if(nFacesUnowned) {
|
nuclear@0
|
337 std::vector<unsigned int> subFaces;
|
nuclear@0
|
338
|
nuclear@0
|
339 for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
|
nuclear@0
|
340 if(faceBones[i]==cUnowned) {
|
nuclear@0
|
341 subFaces.push_back(i);
|
nuclear@0
|
342 }
|
nuclear@0
|
343 }
|
nuclear@0
|
344
|
nuclear@0
|
345 aiMesh *baseMesh = MakeSubmesh(pMesh,subFaces,0);
|
nuclear@0
|
346 std::pair<aiMesh*,const aiBone*> push_pair(baseMesh,(const aiBone*)0);
|
nuclear@0
|
347
|
nuclear@0
|
348 poNewMeshes.push_back(push_pair);
|
nuclear@0
|
349 }
|
nuclear@0
|
350
|
nuclear@0
|
351 for(unsigned int i=0;i<pMesh->mNumBones;i++) {
|
nuclear@0
|
352
|
nuclear@0
|
353 if(!isBoneNecessary[i]&&facesPerBone[i]>0) {
|
nuclear@0
|
354 std::vector<unsigned int> subFaces;
|
nuclear@0
|
355
|
nuclear@0
|
356 for(unsigned int j=0;j<pMesh->mNumFaces;j++) {
|
nuclear@0
|
357 if(faceBones[j]==i) {
|
nuclear@0
|
358 subFaces.push_back(j);
|
nuclear@0
|
359 }
|
nuclear@0
|
360 }
|
nuclear@0
|
361
|
nuclear@0
|
362 unsigned int f = AI_SUBMESH_FLAGS_SANS_BONES;
|
nuclear@0
|
363 aiMesh *subMesh =MakeSubmesh(pMesh,subFaces,f);
|
nuclear@0
|
364
|
nuclear@0
|
365 //Lifted from PretransformVertices.cpp
|
nuclear@0
|
366 ApplyTransform(subMesh,pMesh->mBones[i]->mOffsetMatrix);
|
nuclear@0
|
367 std::pair<aiMesh*,const aiBone*> push_pair(subMesh,pMesh->mBones[i]);
|
nuclear@0
|
368
|
nuclear@0
|
369 poNewMeshes.push_back(push_pair);
|
nuclear@0
|
370 }
|
nuclear@0
|
371 }
|
nuclear@0
|
372 }
|
nuclear@0
|
373
|
nuclear@0
|
374 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
375 // Recursively updates the node's mesh list to account for the changed mesh list
|
nuclear@0
|
376 void DeboneProcess::UpdateNode(aiNode* pNode) const
|
nuclear@0
|
377 {
|
nuclear@0
|
378 // rebuild the node's mesh index list
|
nuclear@0
|
379
|
nuclear@0
|
380 std::vector<unsigned int> newMeshList;
|
nuclear@0
|
381
|
nuclear@0
|
382 // this will require two passes
|
nuclear@0
|
383
|
nuclear@0
|
384 unsigned int m = pNode->mNumMeshes, n = mSubMeshIndices.size();
|
nuclear@0
|
385
|
nuclear@0
|
386 // first pass, look for meshes which have not moved
|
nuclear@0
|
387
|
nuclear@0
|
388 for(unsigned int a=0;a<m;a++) {
|
nuclear@0
|
389
|
nuclear@0
|
390 unsigned int srcIndex = pNode->mMeshes[a];
|
nuclear@0
|
391 const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex];
|
nuclear@0
|
392 unsigned int nSubmeshes = subMeshes.size();
|
nuclear@0
|
393
|
nuclear@0
|
394 for(unsigned int b=0;b<nSubmeshes;b++) {
|
nuclear@0
|
395 if(!subMeshes[b].second) {
|
nuclear@0
|
396 newMeshList.push_back(subMeshes[b].first);
|
nuclear@0
|
397 }
|
nuclear@0
|
398 }
|
nuclear@0
|
399 }
|
nuclear@0
|
400
|
nuclear@0
|
401 // second pass, collect deboned meshes
|
nuclear@0
|
402
|
nuclear@0
|
403 for(unsigned int a=0;a<n;a++)
|
nuclear@0
|
404 {
|
nuclear@0
|
405 const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a];
|
nuclear@0
|
406 unsigned int nSubmeshes = subMeshes.size();
|
nuclear@0
|
407
|
nuclear@0
|
408 for(unsigned int b=0;b<nSubmeshes;b++) {
|
nuclear@0
|
409 if(subMeshes[b].second == pNode) {
|
nuclear@0
|
410 newMeshList.push_back(subMeshes[b].first);
|
nuclear@0
|
411 }
|
nuclear@0
|
412 }
|
nuclear@0
|
413 }
|
nuclear@0
|
414
|
nuclear@0
|
415 if( pNode->mNumMeshes > 0 ) {
|
nuclear@0
|
416 delete [] pNode->mMeshes; pNode->mMeshes = NULL;
|
nuclear@0
|
417 }
|
nuclear@0
|
418
|
nuclear@0
|
419 pNode->mNumMeshes = newMeshList.size();
|
nuclear@0
|
420
|
nuclear@0
|
421 if(pNode->mNumMeshes) {
|
nuclear@0
|
422 pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
|
nuclear@0
|
423 std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
|
nuclear@0
|
424 }
|
nuclear@0
|
425
|
nuclear@0
|
426 // do that also recursively for all children
|
nuclear@0
|
427 for( unsigned int a = 0; a < pNode->mNumChildren; ++a ) {
|
nuclear@0
|
428 UpdateNode( pNode->mChildren[a]);
|
nuclear@0
|
429 }
|
nuclear@0
|
430 }
|
nuclear@0
|
431
|
nuclear@0
|
432 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
433 // Apply the node transformation to a mesh
|
nuclear@0
|
434 void DeboneProcess::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const
|
nuclear@0
|
435 {
|
nuclear@0
|
436 // Check whether we need to transform the coordinates at all
|
nuclear@0
|
437 if (!mat.IsIdentity()) {
|
nuclear@0
|
438
|
nuclear@0
|
439 if (mesh->HasPositions()) {
|
nuclear@0
|
440 for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
nuclear@0
|
441 mesh->mVertices[i] = mat * mesh->mVertices[i];
|
nuclear@0
|
442 }
|
nuclear@0
|
443 }
|
nuclear@0
|
444 if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
|
nuclear@0
|
445 aiMatrix4x4 mWorldIT = mat;
|
nuclear@0
|
446 mWorldIT.Inverse().Transpose();
|
nuclear@0
|
447
|
nuclear@0
|
448 // TODO: implement Inverse() for aiMatrix3x3
|
nuclear@0
|
449 aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
|
nuclear@0
|
450
|
nuclear@0
|
451 if (mesh->HasNormals()) {
|
nuclear@0
|
452 for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
nuclear@0
|
453 mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
|
nuclear@0
|
454 }
|
nuclear@0
|
455 }
|
nuclear@0
|
456 if (mesh->HasTangentsAndBitangents()) {
|
nuclear@0
|
457 for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
|
nuclear@0
|
458 mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
|
nuclear@0
|
459 mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
|
nuclear@0
|
460 }
|
nuclear@0
|
461 }
|
nuclear@0
|
462 }
|
nuclear@0
|
463 }
|
nuclear@0
|
464 }
|