framework2

Форк
0
1343 строки · 58.4 Кб
1
//
2
//  ofxFBXScene.h
3
//  ofxFBX-Example-Importer
4
//
5
//  Created by Nick Hardeman on 10/31/13.
6
//
7
//
8

9
#include "ofxFBXSrcScene.h"
10
#include "Common/Common.h"
11

12
FbxSystemUnit ofxFBXSource::Scene::FbxUnits = FbxSystemUnit::cm;
13

14
using namespace ofxFBXSource;
15

16
//--------------------------------------------------------------
17
Scene::Scene() {
18
    lSdkManager = NULL;
19
    lScene      = NULL;
20
    currentFbxAnimationLayer = NULL;
21
    fbxFilePath = "";
22
}
23

24
//--------------------------------------------------------------
25
Scene::~Scene() {
26
    
27
	if (currentFbxAnimationLayer != NULL) {
28
		currentFbxAnimationLayer->Destroy();
29
	}
30

31
    if(lScene != NULL ) {
32
        deleteCachedTexturesInScene( lScene );
33
        deleteCachedMaterialsRecursive( lScene->GetRootNode() );
34
		lScene->Destroy(true);
35
    }
36

37
	
38
    
39
    if(lSdkManager != NULL) {
40
		bool lResult;
41
		// Destroy all objects created by the FBX SDK.
42
		//DestroySdkObjects(lSdkManager, lResult);
43
		//lSdkManager->Destroy();
44
		//delete lSdkManager;
45
       // lSdkManager = NULL;
46
    }
47
}
48

49
//--------------------------------------------------------------
50
bool Scene::load( Settings aSettings ) {
51
    if( aSettings.filePath == "" ) {
52
        ofLogError("ofxFBXSource::Scene::load()") << " file path not set in settings!! " << " :(";
53
        return false;
54
    }
55
    return load( aSettings.filePath, aSettings );
56
}
57

58
//--------------------------------------------------------------
59
bool Scene::load( string path, Scene::Settings aSettings ) {
60
    
61
    if( !ofFile::doesFileExist(path)) {
62
        ofLogError("ofxFBXSource::Scene::load()") << " File does not exist!!: " << path << " :(";
63
        return false;
64
    }
65
    
66
    bool lResult = false;
67
    
68
	// Prepare the FBX SDK.
69
	InitializeSdkObjects(lSdkManager, lScene);
70
    
71
    // make sure to import bones if we have animations. Since some animations are bone based.
72
    if(aSettings.importAnimations) {
73
        // make sure to import the bones / known as links in the FBX SDK
74
        aSettings.importBones   = true;
75
        aSettings.importShapes  = true; // i think this is referring to blend shapes?
76
    }
77
    
78
    _settings = aSettings;
79
    
80
    // load only what is requested //
81
    (*(lSdkManager->GetIOSettings())).SetBoolProp(IMP_FBX_MATERIAL,        _settings.importMaterials );
82
    // load in the texture file locations information, _settings.importTextures determines if pixel data is loaded //
83
    (*(lSdkManager->GetIOSettings())).SetBoolProp(IMP_FBX_TEXTURE,         true );//_settings.importTextures );
84
    (*(lSdkManager->GetIOSettings())).SetBoolProp(IMP_FBX_LINK,            _settings.importBones );
85
    (*(lSdkManager->GetIOSettings())).SetBoolProp(IMP_FBX_SHAPE,           _settings.importShapes );
86
    (*(lSdkManager->GetIOSettings())).SetBoolProp(IMP_FBX_GOBO,            _settings.importGobos );
87
    (*(lSdkManager->GetIOSettings())).SetBoolProp(IMP_FBX_ANIMATION,       _settings.importAnimations );
88
    
89
	lResult = LoadScene(lSdkManager, lScene, ofToDataPath(path).c_str());
90
    
91
	if(!lResult || !lScene ) {
92
        ofLogError("ofxFBXSource::Scene") << "An error occurred while loading the scene... :(";
93
        return false;
94
	}
95
    
96
    fbxFilePath = ofToDataPath(path);
97
    
98
    if(aSettings.printInfo) cout << "ofxFBXSrcScene :: loading fbx file from " << fbxFilePath << endl;
99
    
100
    // Convert Axis System to what is used in this example, if needed
101
    FbxAxisSystem SceneAxisSystem = lScene->GetGlobalSettings().GetAxisSystem();
102
//    FbxAxisSystem OurAxisSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eRightHanded);
103
    FbxAxisSystem OurAxisSystem( FbxAxisSystem::OpenGL );
104
    if( SceneAxisSystem != OurAxisSystem ) {
105
        OurAxisSystem.ConvertScene(lScene);
106
    }
107
    
108
    // Convert Unit System to what is used in this example, if needed
109
    FbxSystemUnit SceneSystemUnit = lScene->GetGlobalSettings().GetSystemUnit();
110
    ofLogVerbose("ofxFBXSource::Scene") << "SceneSystemUnit = " << SceneSystemUnit.GetScaleFactor() << " " << SceneSystemUnit.GetScaleFactorAsString_Plurial();
111
    
112
    if( ofxFBXSource::Scene::FbxUnits.GetScaleFactor() == 0 ) {
113
        // setting to the default cm //
114
        ofxFBXSource::Scene::FbxUnits = FbxSystemUnit::cm;
115
    }
116
    
117
    if( SceneSystemUnit.GetScaleFactor() != ofxFBXSource::Scene::FbxUnits.GetScaleFactor() ) {
118
        ofLogVerbose("ofxFBXSource::Scene") << "coverting scene from " << SceneSystemUnit.GetScaleFactorAsString_Plurial() << " to " << ofxFBXSource::Scene::FbxUnits.GetScaleFactorAsString_Plurial();
119
        ofxFBXSource::Scene::FbxUnits.ConvertScene( lScene );
120
    }
121
    
122
//    FbxGeometryConverter lGeomConverter( lSdkManager );
123
//    lGeomConverter.Triangulate(lScene, /*replace*/true);
124
    
125
    // Split meshes per material, so that we only have one material per mesh (for VBO support)
126
//    if(!lGeomConverter.SplitMeshesPerMaterial(lScene, /*replace*/true)) {
127
//        cout << "There was an error splitting the meshes per material" << endl;
128
//    }
129
    
130
    // cache all of the textures by loading them from disk //
131
    cacheTexturesInScene( lScene );
132
    // cache all of the materials in the scene as ofxFBXMeshMaterial //
133
    if( _settings.importMaterials ) {
134
        cacheMaterialsRecursive( lScene->GetRootNode() );
135
    }
136
    
137
    // Initialize the frame period.
138
    fbxFrameTime.SetTime(0, 0, 0, 1, 0, lScene->GetGlobalSettings().GetTimeMode());
139
//    fbxFrameTime.Set( lScene->GetGlobalSettings().GetFrameRate() );
140
//    fbxFrameTime.SetTime(0, 0, 0, 1, 0, FbxTime::eFrames24 );
141
//    fbxFrameTime.SetSecondDouble( 1.f / 24.f );
142
    ofLogVerbose() << "ofxFBXSource::Scene :: time mode: " << lScene->GetGlobalSettings().GetTimeMode() << endl;
143
    
144
    // Get the list of all the animation stack.
145
    if( areAnimationsEnabled() ) {
146
        populateAnimationInformation();
147
    }
148
    
149
    if(animations.size() > 0) {
150
        FbxAnimStack * lCurrentAnimationStack = lScene->FindMember<FbxAnimStack>( (&animations[0].fbxname)->Buffer());
151
        if (lCurrentAnimationStack == NULL) {
152
            ofLogError("ofxFBXSource::Scene :: ") << "this is a problem. The anim stack should be found in the scene!" << endl;
153
            // this is a problem. The anim stack should be found in the scene!
154
            return false;
155
        }
156
        
157
        // we assume that the first animation layer connected to the animation stack is the base layer
158
        // (this is the assumption made in the FBXSDK)
159
        currentFbxAnimationLayer = lCurrentAnimationStack->GetMember<FbxAnimLayer>();
160
    }
161
    
162
    _parseNodesRecursive( lScene->GetRootNode() );
163
    
164
    // populate bones //
165
    if( _settings.importBones ) {
166
        _constructSkeletons( lScene->GetRootNode() );
167
    }
168
    
169
    // add in the keyframe information //
170
    if( areAnimationsEnabled() && _settings.useKeyFrames ) {
171
        // politely inform the skeletons that we will be using keyframes //
172
//        for( auto& skel : skeletons ) {
173
//            skel->setUseKeyFrames( true );
174
//        }
175
//
176
//        for( auto& mesh : meshes ) {
177
//            mesh->setUseKeyFrames( true );
178
//        }
179
        for( auto& node : mSrcNodes ) {
180
            node->setUseKeyFrames(true);
181
        }
182
        
183
        for( int i = 0; i < getNumAnimations(); i++ ) {
184
            
185
            FbxAnimStack* currentAnimationStack = getFBXScene()->FindMember<FbxAnimStack>( (&animations[i].fbxname)->Buffer() );
186
            if (currentAnimationStack == NULL) {
187
                // this is a problem. The anim stack should be found in the scene!
188
                ofLogWarning("ofxFBXSource::Scene :: setAnimation : the anim stack was not found in the scene!");
189
                continue;
190
            }
191
            currentFbxAnimationLayer = currentAnimationStack->GetMember<FbxAnimLayer>();
192
            getFBXScene()->SetCurrentAnimationStack( currentAnimationStack );
193
            
194
            populateKeyFrames( lScene->GetRootNode(), i );
195
        }
196
    }
197
    
198
    if(animations.size() > 0) {
199
        FbxAnimStack * lCurrentAnimationStack = lScene->FindMember<FbxAnimStack>( (&animations[0].fbxname)->Buffer());
200
        if (lCurrentAnimationStack == NULL) {
201
            ofLogError("ofxFBXSource::Scene :: ") << "this is a problem. The anim stack should be found in the scene!" << endl;
202
            // this is a problem. The anim stack should be found in the scene!
203
            return false;
204
        }
205
        
206
        // we assume that the first animation layer connected to the animation stack is the base layer
207
        // (this is the assumption made in the FBXSDK)
208
        currentFbxAnimationLayer = lCurrentAnimationStack->GetMember<FbxAnimLayer>();
209
    }
210
    
211
    _parentNodesRecursive(lScene->GetRootNode());
212
    
213
    if( _settings.printInfo ) {
214
        cout << getInfoString() << endl;
215
    }
216
    
217
    return true;
218
}
219

220

221
#pragma mark - Getters
222
// ---------------------------------------------- getters
223
FbxScene* Scene::getFBXScene() {
224
    return lScene;
225
}
226

227
// ---------------------------------------------- utils
228
string Scene::getFbxFilePath() {
229
    return fbxFilePath;
230
}
231

232
//--------------------------------------------------------------
233
string Scene::getFbxFolderPath() {
234
    if(fbxFilePath == "") return "";
235
    const FbxString lAbsFbxFileName = FbxPathUtils::Resolve( getFbxFilePath().c_str() );
236
    return  (string)FbxPathUtils::GetFolderName(lAbsFbxFileName);
237
}
238

239
//--------------------------------------------------------------
240
ofxFBXSource::Node::NodeType Scene::getOFXNodeType( FbxNode* aNode ) {
241
    FbxNodeAttribute* lNodeAttribute = aNode->GetNodeAttribute();
242
    if( lNodeAttribute ) {
243
        FbxNodeAttribute::EType et = lNodeAttribute->GetAttributeType();
244
        if (et == FbxNodeAttribute::eMesh ||
245
            et == FbxNodeAttribute::eNurbs ||
246
            et == FbxNodeAttribute::ePatch ||
247
            et == FbxNodeAttribute::eNurbsSurface) {
248
            return ofxFBXSource::Node::OFX_FBX_MESH;
249
        } else if( et == FbxNodeAttribute::eNurbsCurve ) {
250
            return ofxFBXSource::Node::OFX_FBX_NURBS_CURVE;
251
        } else if( et == FbxNodeAttribute::eNull ) {
252
            return ofxFBXSource::Node::OFX_FBX_NULL;
253
        } else if( et == FbxNodeAttribute::eSkeleton ) {
254
            if( aNode->GetSkeleton() && aNode->GetSkeleton()->IsSkeletonRoot() ) {
255
                return ofxFBXSource::Node::OFX_FBX_SKELETON;
256
            }
257
            return ofxFBXSource::Node::OFX_FBX_BONE;
258
        }
259
    }
260
    
261
    return ofxFBXSource::Node::OFX_FBX_NULL;
262
}
263

264
//--------------------------------------------------------------
265
vector< shared_ptr<ofxFBXSource::Node> > Scene::getSceneNodes() {
266
    return mSceneNodes;
267
}
268

269
//--------------------------------------------------------------
270
string Scene::getInfoString() {
271
    stringstream ss;
272
    ss << "ofxFBXSource::Scene : " << ofFilePath::getBaseName(fbxFilePath)<<"."<<ofFilePath::getFileExt(fbxFilePath) << endl;
273
    for( auto& sn : mSceneNodes ) {
274
        ss << sn->getAsString();
275
    }
276
    return ss.str();
277
}
278

279
#pragma mark - Textures
280
// ---------------------------------------------- animation
281
void Scene::cacheTexturesInScene( FbxScene* pScene ) {
282
    // Load the textures into GPU, only for file texture now
283
    const int lTextureCount = pScene->GetTextureCount();
284
    for (int lTextureIndex = 0; lTextureIndex < lTextureCount; ++lTextureIndex) {
285
        FbxTexture * lTexture = pScene->GetTexture(lTextureIndex);
286
        FbxFileTexture * lFileTexture = FbxCast<FbxFileTexture>(lTexture);
287
        if (lFileTexture && !lFileTexture->GetUserDataPtr()) {
288
            // Try to load the texture from absolute path
289
            const FbxString lFileName = lFileTexture->GetFileName();
290
            
291
            GLuint lTextureObject = 0;
292
            bool bFoundTexture = false;
293
            string filepath  = (string)lFileName;
294
            bFoundTexture = isValidTexturePath( filepath );
295
            
296
            const FbxString lAbsFbxFileName = FbxPathUtils::Resolve( fbxFilePath.c_str() );
297
            const FbxString lAbsFolderName = FbxPathUtils::GetFolderName(lAbsFbxFileName);
298
            
299
            if( !bFoundTexture ) {
300
                // Load texture from relative file name (relative to FBX file)
301
                const FbxString lResolvedFileName = FbxPathUtils::Bind(lAbsFolderName, lFileTexture->GetRelativeFileName());
302
                filepath = (string)lResolvedFileName;
303
                bFoundTexture = isValidTexturePath( filepath );
304
            }
305
            
306
            if(!bFoundTexture) {
307
                // Load texture from file name only (relative to FBX file)
308
                const FbxString lTextureFileName = FbxPathUtils::GetFileName(lFileName);
309
                const FbxString lResolvedFileName = FbxPathUtils::Bind(lAbsFolderName, lTextureFileName);
310
                filepath = (string)lResolvedFileName;
311
                bFoundTexture = isValidTexturePath( filepath );
312
            }
313
            
314
            if(!bFoundTexture) {
315
                ofLogWarning("ofxFBXSource::Scene :: Could not find texture ") << filepath;
316
                continue;
317
            }
318
            
319
            if (bFoundTexture) {
320
//                ofxFBXSource::MeshTexture* texture = new ofxFBXSource::MeshTexture();
321
                auto texture = make_shared<ofxFBXSource::MeshTexture>();
322
                
323
                if( _settings.importTextures ) {
324
                    ofPixels pixels;
325
                    bool loaded = ofLoadImage(pixels, filepath);
326
                    if(loaded){
327
                        texture->allocate(pixels.getWidth(), pixels.getHeight(), ofGetGLInternalFormat(pixels), false);
328
                        pixels.mirror(true, false);
329
                        texture->loadData(pixels);
330
                    }
331
                    if(loaded) {
332
                        ofLogVerbose("ofxFBXSource::Scene :: Loaded the texture from ") << filepath << endl;
333
                        
334
                        texture->getTextureData().bFlipTexture = true;
335
                        texture->disableTextureMatrix();
336
                        texture->filePath = filepath;
337
                        
338
                        lFileTexture->SetUserDataPtr( texture.get() );
339
                    } else {
340
                        ofLogError("ofxFBXSource::Scene :: Failed to load texture for ") << lFileName;
341
                        //delete texture;
342
                        //texture = NULL;
343
                        texture.reset();
344
                    }
345
                } else {
346
                    ofLogVerbose("ofxFBXSource::Scene :: found texture, but not loading pixel data ") << filepath << endl;
347
                    texture->filePath = filepath;
348
                    lFileTexture->SetUserDataPtr( texture.get() );
349
                }
350
                if( texture ) {
351
                    mTextures.push_back(texture);
352
                }
353
            }
354
        }
355
    }
356
}
357

358
void Scene::deleteCachedTexturesInScene( FbxScene* pScene ) {
359
    const int lTextureCount = pScene->GetTextureCount();
360
    for (int lTextureIndex = 0; lTextureIndex < lTextureCount; ++lTextureIndex) {
361
        FbxTexture* lTexture = pScene->GetTexture(lTextureIndex);
362
        FbxFileTexture* lFileTexture = FbxCast<FbxFileTexture>(lTexture);
363
        if (lFileTexture && lFileTexture->GetUserDataPtr()) {
364
//            ofxFBXSource::MeshTexture* texture = static_cast<ofxFBXSource::MeshTexture *>( lFileTexture->GetUserDataPtr() );
365
            //auto texture = static_cast< shared_ptr<ofxFBXSource::MeshTexture>* >(lFileTexture->GetUserDataPtr());
366
            lFileTexture->SetUserDataPtr(NULL);
367
            //delete texture;
368
            //texture = NULL;
369
        }
370
    }
371
    mTextures.clear();
372
}
373

374
bool Scene::isValidTexturePath( string aPathToTexture ) {
375
    ofFile tfile( (string)aPathToTexture );
376
    if(!tfile.exists()) return false;
377
    bool bGoodToGo = false;
378
    if(tfile.getExtension() == "tga") bGoodToGo = true;
379
    if(tfile.getExtension() == "jpg") bGoodToGo = true;
380
    if(tfile.getExtension() == "png") bGoodToGo = true;
381
    if(tfile.getExtension() == "bmp") bGoodToGo = true;
382
    if(tfile.getExtension() == "tif") bGoodToGo = true;
383
    if(tfile.getExtension() == "tiff") bGoodToGo = true;
384
    return bGoodToGo;
385
}
386

387
#pragma mark - Materials
388
// ---------------------------------------------- materials
389
void Scene::cacheMaterialsRecursive( FbxNode* pNode ) {
390
    // Bake material and hook as user data.
391
    const int lMaterialCount = pNode->GetMaterialCount();
392
    for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) {
393
        FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex);
394
        if (lMaterial && !lMaterial->GetUserDataPtr()) {
395
            ofxFBXSource::MeshMaterial* materialCache = new ofxFBXSource::MeshMaterial();
396
            ofLogVerbose("ofxFBXSource::Scene") << "found a material :: " << lMaterial->GetName();
397
//            ofLogNotice("ofxFBXScene") << "found a material :: " << lMaterial->GetName();
398
            materialCache->setup( lMaterial );
399
            lMaterial->SetUserDataPtr( materialCache );
400
        }
401
    }
402
    
403
    const int lChildCount = pNode->GetChildCount();
404
    for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
405
        cacheMaterialsRecursive( pNode->GetChild(lChildIndex) );
406
    }
407
}
408

409
void Scene::deleteCachedMaterialsRecursive( FbxNode* pNode ) {
410
    const int lMaterialCount = pNode->GetMaterialCount();
411
    for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) {
412
        FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex);
413
        if (lMaterial && lMaterial->GetUserDataPtr()) {
414
            ofxFBXSource::MeshMaterial* materialCache = static_cast<ofxFBXSource::MeshMaterial *>(lMaterial->GetUserDataPtr());
415
            lMaterial->SetUserDataPtr(NULL);
416
            delete materialCache;
417
			materialCache = NULL;
418
        }
419
    }
420
    
421
    const int lChildCount = pNode->GetChildCount();
422
    for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
423
        deleteCachedMaterialsRecursive( pNode->GetChild(lChildIndex) );
424
    }
425
}
426

427
#pragma mark - Animation
428
// ---------------------------------------------- animation
429
int Scene::getNumAnimations() {
430
    return animations.size();
431
}
432

433
//--------------------------------------------------------------
434
bool Scene::areAnimationsEnabled() {
435
    return _settings.importAnimations;
436
}
437

438
//--------------------------------------------------------------
439
void Scene::populateAnimationInformation() {
440
    FbxArray<FbxString*> mAnimStackNameArray;
441
    lScene->FillAnimStackNameArray(mAnimStackNameArray);
442
//    animations.resize( mAnimStackNameArray.GetCount() );
443
    for(int i = 0; i < mAnimStackNameArray.GetCount(); i++ ) {
444
        
445
        FbxAnimStack* lCurrentAnimationStack    = lScene->FindMember<FbxAnimStack>(mAnimStackNameArray[i]->Buffer());
446
        FbxTakeInfo* lCurrentTakeInfo           = lScene->GetTakeInfo(*(mAnimStackNameArray[i]));
447
        
448
        FbxTime startTime, endTime;
449
        
450
        if (lCurrentTakeInfo) {
451
            startTime   = lCurrentTakeInfo->mLocalTimeSpan.GetStart();
452
            endTime     = lCurrentTakeInfo->mLocalTimeSpan.GetStop();
453
        } else {
454
            // Take the time line value
455
            FbxTimeSpan lTimeLineTimeSpan;
456
            lScene->GetGlobalSettings().GetTimelineDefaultTimeSpan(lTimeLineTimeSpan);
457
            startTime   = lTimeLineTimeSpan.GetStart();
458
            endTime     = lTimeLineTimeSpan.GetStop();
459
        }
460
        ofxFBXAnimation animation;
461
        animation.setup( startTime, endTime, fbxFrameTime );
462
        animation.fbxCurrentTime = animation.fbxStartTime;
463
        FbxString tfbxName      = FbxString(*mAnimStackNameArray[i]);
464
        animation.fbxname   = tfbxName;
465
        animation.index     = i;
466
        animation.name      = FbxString(*mAnimStackNameArray[i]);
467
        animations.push_back( animation );
468
        //FbxString ostr = startTime;
469
        //startTime.
470
        ofLogVerbose("ofxFBXSource::Scene") << i << " - " << " ofxFBXSource::Scene :: animations[" << i << "].name: " << animations[i].name << " starttime: " << startTime.GetTimeString() << " end time: " << endTime.GetTimeString() << endl;
471
        
472
//        int l;
473
//        int nbAnimLayers = lCurrentAnimationStack->GetMemberCount<FbxAnimLayer>();
474
        
475
//        cout << "ofxFBXScene :: animation: " << animations[i].name << " num layers: " << nbAnimLayers << " | " << ofGetFrameNum() << endl;
476
        
477
//        for (l = 0; l < nbAnimLayers; l++) {
478
//            FbxAnimLayer* lAnimLayer = lCurrentAnimationStack->GetMember<FbxAnimLayer>(l);
479
//            populateKeyFrames( FbxNode* pNode, FbxAnimLayer* pAnimLayer, int aAnimIndex ) {
480
            
481
//        }
482
//        cout << i << " - ofxFBXScene :: name " << animations[i].name << "| fbxname: " << FbxString(*mAnimStackNameArray[i]) << endl;
483
    }
484
    
485
    FbxArrayDelete(mAnimStackNameArray);
486
    
487
    // check if there is an xml file //
488
    if( fbxFilePath != "" && _settings.useKeyFrames ) {
489
        string tencDir = ofFilePath::addTrailingSlash( ofFilePath::getEnclosingDirectory( fbxFilePath ) );
490
        string txmlPath = tencDir + ofFilePath::getBaseName(fbxFilePath)+".xml";
491
        if( ofFile::doesFileExist(txmlPath)) {
492
            ofXml txml;
493
            if( txml.load(txmlPath)) {
494
                ofLogVerbose("ofxFBXSource::Source : populateAnimationInformation : found animation file: ") << txmlPath;
495
                auto animationClipsXml = txml.find("//AnimationClip");
496
                if( animationClipsXml.size() > 0 ) {
497
                    clearAnimations();
498
                    for( int i = 0; i < animationClipsXml.size(); i++ ) {
499
                        string tname = animationClipsXml[i].getAttribute("name").getValue();
500
                        int sframe = animationClipsXml[i].getAttribute("startFrame").getIntValue();
501
                        int eframe = animationClipsXml[i].getAttribute("endFrame" ).getIntValue();
502
                        string loopStr = animationClipsXml[i].getAttribute("loops").getValue();
503
                        bool bLoops = false;
504
                        if( ofToLower(loopStr) == "true" ) {
505
                            bLoops = true;
506
                        }
507
                        auto& tanim = addAnimation( tname, sframe, eframe );
508
                        tanim.setLoops( bLoops );
509
                        
510
                        ofLogVerbose("ofxFBXSource::Source : adding animation: ") << i << " name: " << tanim.name << " num frames: " << tanim.getTotalNumFrames() << " loops: " << tanim.getLoops();
511
                    }
512
                }
513
            }
514
        }
515
    }
516
}
517

518
//--------------------------------------------------------------
519
void Scene::clearAnimations() {
520
    animations.clear();
521
    
522
    if( areAnimationsEnabled() && _settings.useKeyFrames ) {
523
        // politely inform the skeletons that we will be using keyframes //
524
//        for( auto& skel : skeletons ) {
525
//            skel->clearKeyFrames();
526
//        }
527
//
528
//        for( auto& mesh : meshes ) {
529
//            mesh->clearKeyFrames();
530
//        }
531
        
532
        for( auto& node : mSrcNodes ) {
533
            node->clearKeyFrames();
534
        }
535
    }
536
    bMeshKeyframesCached = false;
537
    
538
}
539

540
//--------------------------------------------------------------
541
ofxFBXAnimation& Scene::addAnimation( string aname, int aFrameBegin, int aFrameEnd, int aAnimStackIndex ) {
542
    FbxArray<FbxString*> mAnimStackNameArray;
543
    lScene->FillAnimStackNameArray(mAnimStackNameArray);
544
    //animations.resize( mAnimStackNameArray.GetCount() );
545
    
546
    if( mAnimStackNameArray.GetCount() < 1 ) {
547
        ofLogError("ofxFBXSource::Scene :: addAnimation : no animations in file found" );
548
        return dummyAnimation;
549
    }
550
    if( aAnimStackIndex >= mAnimStackNameArray.GetCount()) {
551
        ofLogError("ofxFBXSource::Scene :: addAnimation : anim stack index" ) << " ("<<aAnimStackIndex<<")  is out of bounds";
552
        return dummyAnimation;
553
    }
554
    
555
    FbxAnimStack* lCurrentAnimationStack    = lScene->FindMember<FbxAnimStack>(mAnimStackNameArray[aAnimStackIndex]->Buffer());
556
    FbxTakeInfo* lCurrentTakeInfo           = lScene->GetTakeInfo(*(mAnimStackNameArray[aAnimStackIndex]));
557
    
558
    FbxTime startTime, endTime;
559
    
560
    if (lCurrentTakeInfo) {
561
        startTime   = lCurrentTakeInfo->mLocalTimeSpan.GetStart();
562
        endTime     = lCurrentTakeInfo->mLocalTimeSpan.GetStop();
563
    } else {
564
        // Take the time line value
565
        FbxTimeSpan lTimeLineTimeSpan;
566
        lScene->GetGlobalSettings().GetTimelineDefaultTimeSpan(lTimeLineTimeSpan);
567
        startTime   = lTimeLineTimeSpan.GetStart();
568
        endTime     = lTimeLineTimeSpan.GetStop();
569
    }
570
    
571
    int totalFrames = ceil( (endTime.GetMilliSeconds() - startTime.GetMilliSeconds()) / fbxFrameTime.GetMilliSeconds() );
572
    
573
//    int ttime = ofMap(aPct, 0.f, 1.f, startTimeMillis, stopTimeMillis, true );
574
//    fbxCurrentTime.SetMilliSeconds(ttime);
575
    
576
    FbxTime startFrameTime = startTime + fbxFrameTime * aFrameBegin;
577
    FbxTime endFrameTime = startTime + fbxFrameTime * aFrameEnd;
578
    
579
    startFrameTime.SetMilliSeconds( (int)ofMap((float)aFrameBegin / (float)totalFrames, 0.f, 1.f, startTime.GetMilliSeconds(), endTime.GetMilliSeconds(), true ));
580
    endFrameTime.SetMilliSeconds( (int)ofMap((float)aFrameEnd / (float)totalFrames, 0.f, 1.f, startTime.GetMilliSeconds(), endTime.GetMilliSeconds(), true ));
581
    
582
    if( startFrameTime > endTime ) startFrameTime = endTime;
583
    if( endFrameTime > endTime ) endFrameTime = endTime;
584
//    fbxCurrentTime  = fbxStartTime + fbxFrameTime * tframe;
585
    
586
    ofxFBXAnimation animation;
587
    animation.setup( startFrameTime, endFrameTime, fbxFrameTime );
588
    animation.fbxCurrentTime = animation.fbxStartTime;
589
    FbxString tfbxName      = FbxString(*mAnimStackNameArray[aAnimStackIndex]);
590
    animation.fbxname   = tfbxName;
591
    animation.index     = animations.size();
592
    animation.name      = aname;//FbxString(*mAnimStackNameArray[i]);
593
    animations.push_back( animation );
594
    ofLogVerbose("ofxFBXSource::Scene") << " Adding animation :: name: " << animation.name << " starttime: " << startFrameTime.GetTimeString() << " end time: " << endFrameTime.GetTimeString() << " num frames: " << animation.getTotalNumFrames() << endl;
595
    
596
    if( areAnimationsEnabled() && _settings.useKeyFrames ) {
597
        FbxAnimStack* currentAnimationStack = getFBXScene()->FindMember<FbxAnimStack>( (&animation.fbxname)->Buffer() );
598
        if (currentAnimationStack != NULL) {
599
            getFBXScene()->SetCurrentAnimationStack( currentAnimationStack );
600
            populateKeyFrames( lScene->GetRootNode(), animation.index );
601
        } else {
602
            // this is a problem. The anim stack should be found in the scene!
603
            ofLogWarning("ofxFBXSource::Scene :: addAnimation : the anim stack was not found in the scene!");
604
        }
605
    }
606
    
607
    FbxArrayDelete(mAnimStackNameArray);
608
    return animations.back();
609
}
610

611
//--------------------------------------------------------------
612
void Scene::populateAnimations( vector<ofxFBXAnimation>& aInVector) {
613
    for(int i = 0; i < animations.size(); i++ ) {
614
        aInVector.push_back(animations[i]);
615
    }
616
}
617

618
#pragma mark - Bones / Skeleton
619
//--------------------------------------------------------------
620
void Scene::constructSkeletonsRecursive( ofxFBXSource::Skeleton* aSkeleton, FbxNode* pNode, int aBoneLevel ) {
621
    FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute();
622
    if (lNodeAttribute && lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton) {
623
        if(pNode->GetParent() && pNode->GetParent()->GetNodeAttribute()) {
624
            if(pNode->GetParent()->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eSkeleton) {
625
                if(pNode->GetParent()->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eSkeleton) {
626
                    ofxFBXSource::Bone* bonePtr         = static_cast<ofxFBXSource::Bone *>(pNode->GetUserDataPtr());
627
                    ofxFBXSource::Bone* bonePtrParent   = static_cast<ofxFBXSource::Bone *>(pNode->GetParent()->GetUserDataPtr());
628
                    
629
                    bonePtr->parentBoneName     = bonePtrParent->getName();
630
                    bonePtr->setParent( *bonePtrParent, true );
631
                    
632
                    bonePtr->setLocalTransformMatrix( GetGlobalPosition(pNode, FBXSDK_TIME_INFINITE, NULL ) );
633
                    bonePtr->cacheStartTransforms();
634
                    
635
                    if( bonePtrParent ) {
636
                        //                        bonePtrParent->childBones[ bonePtr->getName() ] = bonePtr;
637
                        //                        auto cbone = dynamic_pointer_cast<ofxFBXSource::Bone>(_getOfxNodeFromNodeUserData(pNode));
638
                        //                        ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>(aNode->GetUserDataPtr());
639
                        shared_ptr<ofxFBXSource::Bone> cbone;
640
                        for( auto& tm : mSrcNodes ) {
641
                            if( tm.get() == bonePtr ) {
642
                                cbone = dynamic_pointer_cast<ofxFBXSource::Bone>(tm);
643
                                break;
644
                            }
645
                        }
646
                        if( cbone ) {
647
                            bonePtrParent->childBones[ bonePtr->getName() ] = cbone;
648
                        }
649
                    }
650
                }
651
            }
652
        }
653
    }
654
    
655
    const int lChildCount = pNode->GetChildCount();
656
    for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
657
        constructSkeletonsRecursive( aSkeleton, pNode->GetChild(lChildIndex), aBoneLevel+1 );
658
    }
659
}
660

661
#pragma mark - Poses
662
//--------------------------------------------------------------
663
int Scene::getNumPoses() {
664
    if( lScene == NULL ) return 0;
665
    return lScene->GetPoseCount();
666
}
667

668
//--------------------------------------------------------------
669
void Scene::populatePoses( vector< shared_ptr<ofxFBXSource::Pose> >& aInPoses ) {
670
    
671
    for( int i = 0; i < lScene->GetPoseCount(); i++ ) {
672
        aInPoses.push_back( shared_ptr<ofxFBXSource::Pose>( new ofxFBXSource::Pose() ));
673
        shared_ptr< ofxFBXSource::Pose > pose = aInPoses.back();
674
        pose->setup( lScene->GetPose(i), i );
675
    }
676
    
677
}
678

679
#pragma mark - Private
680
//--------------------------------------------------------------
681
void Scene::_parseNodesRecursive( FbxNode* aNode ) {
682
    if( aNode == NULL ) { return; }
683
    
684
//    FbxNodeAttribute* lNodeAttribute = aNode->GetNodeAttribute();
685
    ofxFBXSource::Node::NodeType ftype = getOFXNodeType( aNode );
686
    if (ftype == ofxFBXSource::Node::OFX_FBX_MESH) {
687
        auto tmesh = _getMeshForNode( aNode );
688
        if( tmesh ) {
689
//            meshes.push_back( tmesh );
690
            mSrcNodes.push_back(tmesh);
691
        }
692
    } else if(ftype == ofxFBXSource::Node::OFX_FBX_NURBS_CURVE) {
693
        if( _settings.importNurbsCurves ) {
694
            auto tcurve = _getNurbsCurveForNode( aNode );
695
            if( tcurve ) {
696
//                mNurbsCurves.push_back(tcurve);
697
                mSrcNodes.push_back(tcurve);
698
            }
699
        }
700
    } else if(ftype == ofxFBXSource::Node::OFX_FBX_NULL ) {
701
        auto tnull = _getNullForNode( aNode );
702
        if( tnull ) {
703
//            mNullNodes.push_back(tnull);
704
            mSrcNodes.push_back(tnull);
705
        }
706
    } else if( ftype == ofxFBXSource::Node::OFX_FBX_SKELETON || ftype == ofxFBXSource::Node::OFX_FBX_BONE ) {
707
        if( _settings.importBones ) {
708
            auto tbone = _getBoneForNode(aNode);
709
            if( tbone ) {
710
//                bones.push_back( tbone );
711
                mSrcNodes.push_back(tbone);
712
            }
713
        }
714
    }
715
    
716
    
717
    const int lChildCount = aNode->GetChildCount();
718
    for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
719
        _parseNodesRecursive( aNode->GetChild(lChildIndex) );
720
    }
721
}
722

723
//--------------------------------------------------------------
724
void Scene::_constructSkeletons( FbxNode* aNode ) {
725
    list<FbxNode*> skeletonBases;
726
    
727
    _getSkeletonBases( aNode, skeletonBases );
728
    
729
    list<FbxNode*>::iterator it;
730
    for(it = skeletonBases.begin(); it != skeletonBases.end(); ++it ) {
731
        
732
        auto skeletonPtr = make_shared<ofxFBXSource::Skeleton>();
733
//        skeletons.push_back( skeletonPtr );
734
        mSrcNodes.push_back( skeletonPtr );
735
        FbxNode* skeletonNode = *it;
736
        //auto bonePtr = static_cast<ofxFBXSource::Bone *>( skeletonNode->GetUserDataPtr() );
737
        
738
//        auto cbone = dynamic_pointer_cast<ofxFBXSource::Bone>(_getOfxNodeFromNodeUserData(skeletonNode));
739
        ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>( skeletonNode->GetUserDataPtr() );
740
        shared_ptr<ofxFBXSource::Bone> cbone;
741
        for( auto& tm : mSrcNodes ) {
742
            if( tm.get() == bonePtr ) {
743
                cbone = dynamic_pointer_cast<ofxFBXSource::Bone>(tm);
744
                break;
745
            }
746
        }
747
        
748
//        cout << "ofxFBXSrcScene :: _constructSkeletons : we have a bone " << (cbone ? "Good" : "Bad" ) << endl;
749
        
750
        if( cbone ) {
751
            skeletonPtr->root = cbone;//static_cast<ofxFBXSource::Bone *>( skeletonNode->GetUserDataPtr() );
752
            skeletonPtr->setup( skeletonNode );
753
        
754
            constructSkeletonsRecursive( skeletonPtr.get(), skeletonNode, 0 );
755
        }
756
    }
757
}
758

759
//--------------------------------------------------------------
760
void Scene::_getSkeletonBases( FbxNode* aNode, list<FbxNode*>& aSkeletonBases ) {
761
    ofxFBXSource::Node::NodeType ftype = getOFXNodeType( aNode );
762
    if( ftype == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
763
        aSkeletonBases.push_back( aNode );
764
    }
765
    
766
    const int lChildCount = aNode->GetChildCount();
767
    for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
768
        _getSkeletonBases( aNode->GetChild(lChildIndex), aSkeletonBases );
769
    }
770
}
771

772
//--------------------------------------------------------------
773
shared_ptr<ofxFBXSource::Mesh> Scene::_getMeshForNode( FbxNode* aNode ) {
774
    shared_ptr<ofxFBXSource::Mesh> tmesh;
775
    if( aNode == NULL ) return tmesh;
776
    
777
    if(aNode->GetMesh()) {
778
        FbxGeometryConverter lGeomConverter( lSdkManager );
779
        lGeomConverter.Triangulate( aNode->GetMesh(), true );
780
        
781
        tmesh = make_shared<ofxFBXSource::Mesh>();
782
        tmesh->setup( aNode );
783
        
784
        if( !aNode->GetUserDataPtr() ) {
785
            aNode->SetUserDataPtr( tmesh.get() );
786
        }
787
        
788
//        cout << "ofxFBXScene :: _getMeshForNode : name = " << ofxFBXNode::getFbxTypeStringFromNode( aNode ) << endl;
789
//        cout << "ofxFBXScene :: GetShapeCount " << aNode->GetSubdiv() << " patch: " << aNode->GetPatch() << endl;
790
        
791
        FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
792
        if( !aNode->GetParent() ) {
793
            tmesh->setLocalTransformMatrix(lGlobalPosition);
794
        } else {
795
            FbxAMatrix lLocalPosition = GetLocalPositionForNode(aNode, FBXSDK_TIME_INFINITE, NULL );
796
            tmesh->setLocalTransformMatrix(lLocalPosition);
797
        }
798
        tmesh->cacheStartTransforms();
799
        
800
        // Associtate the clusters with some user data so that we can move them around //
801
        int lSkinCount = aNode->GetMesh()->GetDeformerCount(FbxDeformer::eSkin);
802
        
803
        if( lSkinCount > 0 && _settings.importBones ) {
804
            
805
            for ( int lSkinIndex=0; lSkinIndex<lSkinCount; ++lSkinIndex) {
806
                FbxSkin * lSkinDeformer = (FbxSkin *)aNode->GetMesh()->GetDeformer(lSkinIndex, FbxDeformer::eSkin);
807
                
808
                int lClusterCount = lSkinDeformer->GetClusterCount();
809
                for ( int lClusterIndex=0; lClusterIndex<lClusterCount; ++lClusterIndex) {
810
                    FbxCluster* lCluster = lSkinDeformer->GetCluster(lClusterIndex);
811
                    if (!lCluster->GetLink())
812
                        continue;
813
                    
814
                    if ( !lCluster->GetUserDataPtr() ) {
815
                        auto fcluster = make_shared<ofxFBXSource::Cluster>();
816
                        clusters.push_back( fcluster );
817
//                        mSrcNodes.push_back(fcluster);
818
                        fcluster->setup( lGlobalPosition, aNode->GetMesh(), lCluster );
819
                        lCluster->SetUserDataPtr( fcluster.get() );
820
                    }
821
                }
822
            }
823
        }
824
    }
825
    
826
    
827
    return tmesh;
828
}
829

830
//--------------------------------------------------------------
831
shared_ptr<ofxFBXSource::NurbsCurve> Scene::_getNurbsCurveForNode( FbxNode* aNode ) {
832
    shared_ptr<ofxFBXSource::NurbsCurve> tc;
833
    if( aNode == NULL ) return tc;
834
    
835
    if(aNode->GetNurbsCurve() != NULL) {
836
        
837
        tc = make_shared<ofxFBXSource::NurbsCurve>();
838
//            mNurbsCurves.push_back(curve);
839
        tc->setup( aNode );
840
        
841
        if( !aNode->GetUserDataPtr() ) {
842
            aNode->SetUserDataPtr( tc.get() );
843
        }
844
        
845
//        FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
846
//        tc->setLocalTransformMatrix(lGlobalPosition);
847
        
848
        FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
849
        if( !aNode->GetParent() ) {
850
            tc->setLocalTransformMatrix(lGlobalPosition);
851
        } else {
852
            FbxAMatrix lLocalPosition = GetLocalPositionForNode(aNode, FBXSDK_TIME_INFINITE, NULL );
853
            tc->setLocalTransformMatrix(lLocalPosition);
854
        }
855
        tc->cacheStartTransforms();
856
    }
857
    
858
    return tc;
859
}
860

861
//--------------------------------------------------------------
862
shared_ptr<ofxFBXSource::Node> Scene::_getNullForNode( FbxNode* aNode ) {
863
    shared_ptr<ofxFBXSource::Node> tn;
864
    if( aNode == NULL ) return tn;
865
    
866
//    if( aNode->GetNull() != NULL ) {
867
    tn = make_shared<ofxFBXSource::Node>();
868
    tn->setup(aNode);
869
    if( !aNode->GetUserDataPtr() ) {
870
        aNode->SetUserDataPtr( tn.get() );
871
    }
872
    
873
//    FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
874
//    tn->setLocalTransformMatrix(lGlobalPosition);
875
    
876
    FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
877
    if( !aNode->GetParent() ) {
878
        tn->setLocalTransformMatrix(lGlobalPosition);
879
    } else {
880
        FbxAMatrix lLocalPosition = GetLocalPositionForNode(aNode, FBXSDK_TIME_INFINITE, NULL );
881
        tn->setLocalTransformMatrix(lLocalPosition);
882
    }
883
    tn->cacheStartTransforms();
884
    
885
    return tn;
886
}
887

888
//--------------------------------------------------------------
889
shared_ptr<ofxFBXSource::Bone> Scene::_getBoneForNode( FbxNode* aNode ) {
890
    shared_ptr<ofxFBXSource::Bone> tbone;
891
    if( aNode == NULL ) return tbone;
892
    
893
    if ( !aNode->GetUserDataPtr() ) {
894
        tbone = make_shared<ofxFBXSource::Bone>();
895
//        bones.push_back( tbone );
896
        tbone->setup( aNode );
897
        aNode->SetUserDataPtr( tbone.get() );
898
    }
899
    
900
    return tbone;
901
}
902

903
//--------------------------------------------------------------
904
shared_ptr<ofxFBXSource::Node> Scene::_getOfxNodeFromNodeUserData( FbxNode* aNode ) {
905
    shared_ptr<ofxFBXSource::Node> fnode;
906
    if( aNode == NULL ) { return fnode; }
907
    
908
    ofxFBXSource::Node::NodeType ftype = getOFXNodeType( aNode );
909
    if(aNode->GetUserDataPtr() != NULL) {
910
        if (ftype == ofxFBXSource::Node::OFX_FBX_MESH) {
911
            ofxFBXSource::Mesh* nodePtr = static_cast<ofxFBXSource::Mesh *>(aNode->GetUserDataPtr());
912
            // try to find it in the meshes vector //
913
            for( auto& tm : mSrcNodes ) {
914
                if( tm.get() == nodePtr ) {
915
                    fnode = tm;
916
                    break;
917
                }
918
            }
919
//            auto tmesh = _getMeshForNode( aNode );
920
//                fnode = make_shared<ofxFBXMesh>(static_cast<ofxFBXMesh *>(aNode->GetUserDataPtr()));
921
//                std::shared_ptr<disk_node>* u_poi
922
//                = static_cast< std::shared_ptr<disk_node>* >(RayCallback.m_collisionObject->getUserPointer());
923
//                fnode = *static_cast< std::shared_ptr<ofxFBXMesh>* >(aNode->GetUserDataPtr());
924
        } else if(ftype == ofxFBXSource::Node::OFX_FBX_NURBS_CURVE) {
925
            ofxFBXSource::NurbsCurve* nodePtr = static_cast<ofxFBXSource::NurbsCurve *>(aNode->GetUserDataPtr());
926
            for( auto& tm : mSrcNodes ) {
927
                if( tm.get() == nodePtr ) {
928
                    fnode = tm;
929
                    break;
930
                }
931
            }
932
            
933
        } else if(ftype == ofxFBXSource::Node::OFX_FBX_NULL ) {
934
            ofxFBXSource::Node* nodePtr = static_cast<ofxFBXSource::Node *>(aNode->GetUserDataPtr());
935
            for( auto& tm : mSrcNodes ) {
936
                if( tm.get() == nodePtr ) {
937
                    fnode = tm;
938
                    break;
939
                }
940
            }
941
        } else if(ftype == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
942
            ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>(aNode->GetUserDataPtr());
943
            for( auto& tm : mSrcNodes ) {
944
                if( tm->getType() == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
945
                    auto tskel = dynamic_pointer_cast<ofxFBXSource::Skeleton>(tm);
946
                    if( tskel->root.get() == bonePtr ) {
947
                        fnode = tm;
948
                        break;
949
                    }
950
                }
951
            }
952
        } else if(ftype == ofxFBXSource::Node::OFX_FBX_BONE ) {
953
            ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>(aNode->GetUserDataPtr());
954
            for( auto& tm : mSrcNodes ) {
955
                if( tm.get() == bonePtr ) {
956
                    fnode = tm;
957
                    break;
958
                }
959
            }
960
        }
961
    }
962
    
963
    
964
    return fnode;
965
}
966

967
//--------------------------------------------------------------
968
void Scene::_parentNodesRecursive( FbxNode* aNode ) {
969
    if( aNode == NULL ) { return; }
970
    
971
//    cout << "_parentNodesRecursive " << mSceneNodes.size() << " name: " << aNode->GetName() << " type: " << getTypeStringFromNode(aNode) << endl;
972
//    if( aNode->GetParent() ) {
973
//        cout << "  -- parent name: " << aNode->GetParent()->GetName() << endl;
974
//    }
975
//    if(pNode->GetParent()) {
976
//        if(pNode->GetParent()->GetNodeAttribute()) {
977
//            if(pNode->GetParent()->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eSkeleton) {
978
//                ofxFBXBone* bonePtr         = static_cast<ofxFBXBone *>(pNode->GetUserDataPtr());
979
//                ofxFBXBone* bonePtrParent   = static_cast<ofxFBXBone *>(pNode->GetParent()->GetUserDataPtr());
980
    
981
//    FbxNodeAttribute* lNodeAttribute = aNode->GetNodeAttribute();
982
    
983
    shared_ptr<ofxFBXSource::Node> cnode = _getOfxNodeFromNodeUserData( aNode );
984
    
985
//    if( cnode ) {
986
//
987
//    }
988
    
989
    if( aNode->GetParent() && aNode->GetParent() != lScene->GetRootNode() ) {
990
        shared_ptr<ofxFBXSource::Node> pnode = _getOfxNodeFromNodeUserData( aNode->GetParent() );
991
        if( pnode && cnode ) {
992
            pnode->addChild(cnode);
993
        }
994
    } else {
995
        if(cnode) {
996
            mSceneNodes.push_back( cnode );
997
        }
998
    }
999
    
1000
    const int lChildCount = aNode->GetChildCount();
1001
    for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
1002
        _parentNodesRecursive( aNode->GetChild(lChildIndex) );
1003
    }
1004
}
1005

1006
#pragma mark - Keyframes
1007
//--------------------------------------------------------------
1008
void Scene::populateKeyFrames( FbxNode* pNode, int aAnimIndex ) {
1009
    
1010
    if( !pNode ) return;
1011
    
1012
//    cout << pNode->GetName() << " - populateKeyFrames animation index : " << aAnimIndex << endl;
1013
    
1014
    // populate the position first //
1015
    
1016
    ofxFBXSource::Node* fnode = nullptr;
1017
    
1018
    ofxFBXSource::Node::NodeType ftype = getOFXNodeType( pNode );
1019
    if( ftype != ofxFBXSource::Node::OFX_FBX_UNKNOWN && pNode->GetUserDataPtr() ) {
1020
        if( ftype == ofxFBXSource::Node::OFX_FBX_BONE || ftype == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
1021
            ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>(pNode->GetUserDataPtr());
1022
            fnode = bonePtr;
1023
        } else if( ftype == ofxFBXSource::Node::OFX_FBX_MESH ) {
1024
            ofxFBXSource::Mesh* meshPtr = static_cast<ofxFBXSource::Mesh *>(pNode->GetUserDataPtr());
1025
            fnode = meshPtr;
1026
        }
1027
    }
1028
    
1029
    if( !fnode ) {
1030
        ofLogVerbose("Scene::populateKeyFrames : could not parse keyframes for node: ") << pNode->GetName();
1031
    }
1032
    
1033
//    FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute();
1034
//    if (lNodeAttribute) {
1035
//        if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton) {
1036
//            if ( pNode->GetUserDataPtr() ) {
1037
//                ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>(pNode->GetUserDataPtr());
1038
//                fnode = bonePtr;
1039
//            }
1040
//        } else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh ||
1041
//                   lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbs ||
1042
//                   lNodeAttribute->GetAttributeType() == FbxNodeAttribute::ePatch ||
1043
//                   lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbsSurface) {
1044
//            if( pNode->GetUserDataPtr() ) {
1045
//                ofxFBXSource::Mesh* meshPtr = static_cast<ofxFBXSource::Mesh *>(pNode->GetUserDataPtr());
1046
//                fnode = meshPtr;
1047
//            }
1048
//        }
1049
//    }
1050
    
1051
    if( fnode ) {
1052
        bool bGrabGlobalTransform = false;
1053
        FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute();
1054
        if ( lNodeAttribute && lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton ) {
1055
            if(pNode->GetSkeleton() && pNode->GetSkeleton()->IsSkeletonRoot() ) {
1056
                bGrabGlobalTransform = true;
1057
//                cout << "ofxFBXSrcScene :: skeleton global transform : " << pNode->GetName() << endl;
1058
            }
1059
        }
1060
        if( ftype != ofxFBXSource::Node::OFX_FBX_SKELETON && ftype != ofxFBXSource::Node::OFX_FBX_BONE ) {
1061
            if( !pNode->GetParent() ) {
1062
                bGrabGlobalTransform = true;
1063
            }
1064
        }
1065
        
1066
        // figure out the parsing //
1067
        ofxFBXAnimation& tanim = animations[ aAnimIndex ];
1068
        ofxFBXSource::AnimKeyCollection& kcollection = fnode->getKeyCollection( aAnimIndex );
1069
        
1070
        
1071
        FbxAnimCurve* lPosCurveX = pNode->LclTranslation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_X);
1072
        FbxAnimCurve* lPosCurveY = pNode->LclTranslation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1073
        FbxAnimCurve* lPosCurveZ = pNode->LclTranslation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1074
        auto posXKeys = getFloatKeys( lPosCurveX );
1075
        auto posYKeys = getFloatKeys( lPosCurveY );
1076
        auto posZKeys = getFloatKeys( lPosCurveZ );
1077
        
1078
        FbxAnimCurve* lScaleCurveX = pNode->LclScaling.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_X);
1079
        FbxAnimCurve* lScaleCurveY = pNode->LclScaling.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1080
        FbxAnimCurve* lScaleCurveZ = pNode->LclScaling.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1081
        auto scaleXKeys = getFloatKeys( lScaleCurveX );
1082
        auto scaleYKeys = getFloatKeys( lScaleCurveY );
1083
        auto scaleZKeys = getFloatKeys( lScaleCurveZ );
1084
        
1085
        FbxAnimCurve* lRotCurveX = pNode->LclRotation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_X);
1086
        FbxAnimCurve* lRotCurveY = pNode->LclRotation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1087
        FbxAnimCurve* lRotCurveZ = pNode->LclRotation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1088
        
1089
        auto rotXKeys = getFloatKeys( lRotCurveX );
1090
        auto rotYKeys = getFloatKeys( lRotCurveY );
1091
        auto rotZKeys = getFloatKeys( lRotCurveZ );
1092
        
1093
        int numPosKeys = 0;
1094
        int numScaleKeys = 0;
1095
        int numRotKeys = 0;
1096
        
1097
        for( int i = 0; i < tanim.getTotalNumFrames(); i++ ) {
1098
            tanim.setFrame(i);
1099
            
1100
            signed long long cmillis = tanim.fbxCurrentTime.GetMilliSeconds();
1101
            signed long long nmillis = tanim.fbxCurrentTime.GetMilliSeconds() + fbxFrameTime.GetMilliSeconds();
1102
            
1103
            // now get the information //
1104
            bool bHasPosKey = false;
1105
            bool bHasScaleKey = false;
1106
            bool bHasRotKey = false;
1107
            
1108
            if( i == 0 || i == tanim.getTotalNumFrames()-1 ) {
1109
                bHasPosKey = true; bHasScaleKey = true; bHasRotKey = true;
1110
            }
1111
            
1112
            // check if there are no keys, if not, then force add some keys for proper animation //
1113
            if( posXKeys.size() == 0 || posYKeys.size() == 0 || posZKeys.size() == 0 ) {
1114
                bHasPosKey = true;
1115
            }
1116
            
1117
            if( scaleXKeys.size() == 0 || scaleYKeys.size() == 0 || scaleZKeys.size() == 0 ) {
1118
                bHasScaleKey = true;
1119
            }
1120
            
1121
            if( rotXKeys.size() == 0 || rotYKeys.size() == 0 || rotZKeys.size() == 0 ) {
1122
                bHasRotKey=true;
1123
            }
1124
            
1125
            
1126
            // check position //
1127
            if( !bHasPosKey && requiresKeyForTime(posXKeys, cmillis, nmillis )) bHasPosKey=true;
1128
            if( !bHasPosKey && requiresKeyForTime(posYKeys, cmillis, nmillis )) bHasPosKey=true;
1129
            if( !bHasPosKey && requiresKeyForTime(posZKeys, cmillis, nmillis )) bHasPosKey=true;
1130
            
1131
            // check scale //
1132
            if( !bHasScaleKey && requiresKeyForTime(scaleXKeys, cmillis, nmillis )) bHasScaleKey=true;
1133
            if( !bHasScaleKey && requiresKeyForTime(scaleYKeys, cmillis, nmillis )) bHasScaleKey=true;
1134
            if( !bHasScaleKey && requiresKeyForTime(scaleZKeys, cmillis, nmillis )) bHasScaleKey=true;
1135
            
1136
            // check rotation //
1137
            if( !bHasRotKey && requiresKeyForTime(rotXKeys, cmillis, nmillis )) bHasRotKey=true;
1138
            if( !bHasRotKey && requiresKeyForTime(rotYKeys, cmillis, nmillis )) bHasRotKey=true;
1139
            if( !bHasRotKey && requiresKeyForTime(rotZKeys, cmillis, nmillis )) bHasRotKey=true;
1140
            
1141
//            cout << pNode->GetName() << " : " << i << " - " << bHasScaleKey << endl;
1142

1143
			glm::vec3 tpos, tscale;
1144
			glm::quat tquat;
1145
			//fbxToGlmComponents(FbxAMatrix& ainput, glm::vec3& apos, glm::quat& aquat, glm::vec3& ascale)
1146

1147
//            if( pNode->GetParent() ) {
1148
            if( bHasPosKey || bHasScaleKey || bHasRotKey ) {
1149
                
1150
                if( !bGrabGlobalTransform ) {
1151
                    //setTransformMatrix( ofGetLocalTransform( fbxNode, pTime, pPose, NULL ));
1152
                    FbxAMatrix& tmatrix = pNode->EvaluateLocalTransform( tanim.fbxCurrentTime );
1153
                    //tmat = ( fbxToOf(tmatrix) );
1154
                    fbxToGlmComponents(tmatrix, tpos, tquat, tscale);
1155
                } else {
1156
                    FbxAMatrix& tmatrix = pNode->EvaluateGlobalTransform( tanim.fbxCurrentTime );
1157
                   // tmat = ( fbxToOf(tmatrix) );
1158
                    fbxToGlmComponents(tmatrix, tpos, tquat, tscale);
1159
                }
1160
                
1161
                if( bHasPosKey ) {
1162
                    ofxFBXSource::AnimKey<float> tkeyPosX;
1163
                    tkeyPosX.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1164
                    tkeyPosX.value = tpos.x;
1165
                    kcollection.posKeysX.push_back( tkeyPosX );
1166
                    ofxFBXSource::AnimKey<float> tkeyPosY;
1167
                    tkeyPosY.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1168
                    tkeyPosY.value = tpos.y;
1169
                    kcollection.posKeysY.push_back( tkeyPosY );
1170
                    ofxFBXSource::AnimKey<float> tkeyPosZ;
1171
                    tkeyPosZ.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1172
                    tkeyPosZ.value = tpos.z;
1173
                    kcollection.posKeysZ.push_back( tkeyPosZ );
1174
                    
1175
                    numPosKeys++;
1176
                }
1177
                
1178
                if( bHasScaleKey ) {
1179
                    ofxFBXSource::AnimKey<float> tkeyScaleX;
1180
                    tkeyScaleX.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1181
                    tkeyScaleX.value = tscale.x;
1182
                    kcollection.scaleKeysX.push_back( tkeyScaleX );
1183
                    ofxFBXSource::AnimKey<float> tkeyScaleY;
1184
                    tkeyScaleY.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1185
                    tkeyScaleY.value = tscale.y;
1186
                    kcollection.scaleKeysY.push_back( tkeyScaleY );
1187
                    ofxFBXSource::AnimKey<float> tkeyScaleZ;
1188
                    tkeyScaleZ.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1189
                    tkeyScaleZ.value = tscale.z;
1190
                    kcollection.scaleKeysZ.push_back( tkeyScaleZ );
1191
                    
1192
                    numScaleKeys++;
1193
                }
1194
                
1195
                if( bHasRotKey ) {
1196
                    ofxFBXSource::AnimKey<ofQuaternion> tRotKey;
1197
                    tRotKey.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1198
                    tRotKey.value = tquat;
1199
                    kcollection.rotKeys.push_back( tRotKey );
1200
                    
1201
                    numRotKeys++;
1202
                }
1203
                
1204
            }
1205
            
1206
        }
1207
        
1208
        ofLogVerbose("ofxFBXScene :: ") << fnode->getName() << " num pos keys: " << numPosKeys << " scale: " << numScaleKeys << " rot: " << numRotKeys << " total: " << tanim.getTotalNumFrames();
1209
        
1210
        // rotation //
1211
//        FbxAnimCurve* lRotCurveX = pNode->LclRotation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_X);
1212
//        FbxTime lKeyTime;
1213
//        int lCount, lKeyCount;
1214
//        if(lRotCurveX) {
1215
//            lKeyCount = lRotCurveX->KeyGetCount();
1216
//            cout << "ofxFBXScene :: PopulateKeyFrames " << fnode->getName() << " num keys: " << lKeyCount << endl;
1217
//        }
1218
        
1219
        
1220
//        cout << "ofxFBXScene :: adding keyframes for : " << pNode->GetName() << " is root: " << (fnode->isRoot()) << " num pos keys: " << kcollection.posKeysX.size() << endl;
1221
        
1222
    }
1223
    
1224
    
1225
    
1226
//    if( fnode && false ) {
1227
//        FbxAnimCurve* lAnimCurveX = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X);
1228
//        FbxAnimCurve* lAnimCurveY = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1229
//        FbxAnimCurve* lAnimCurveZ = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1230
//
1231
//        ofxFBXKeyCollection& kcollection = fnode->getKeyCollection( aAnimIndex );
1232
//        kcollection.posKeysX = getFloatKeys( lAnimCurveX );
1233
//        kcollection.posKeysY = getFloatKeys( lAnimCurveY );
1234
//        kcollection.posKeysZ = getFloatKeys( lAnimCurveZ );
1235
//
1236
//        FbxAnimCurve* lScaleCurveX = pNode->LclScaling.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X);
1237
//        FbxAnimCurve* lScaleCurveY = pNode->LclScaling.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1238
//        FbxAnimCurve* lScaleCurveZ = pNode->LclScaling.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1239
//        kcollection.scaleKeysX = getFloatKeys( lScaleCurveX );
1240
//        kcollection.scaleKeysY = getFloatKeys( lScaleCurveY );
1241
//        kcollection.scaleKeysZ = getFloatKeys( lScaleCurveZ );
1242
//
1243
//
1244
//        // rotation //
1245
//        FbxAnimCurve* lRotCurveX = pNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X);
1246
//        FbxAnimCurve* lRotCurveY = pNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1247
//        FbxAnimCurve* lRotCurveZ = pNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1248
//
1249
//        map< signed long, int > mTimeCount;
1250
//        vector< ofxFBXKey<ofQuaternion> > newRotKeys;
1251
//        int xKeyCount = lRotCurveX ? lRotCurveX->KeyGetCount() : 0;
1252
//        int yKeyCount = lRotCurveY ? lRotCurveY->KeyGetCount() : 0;
1253
//        int zKeyCount = lRotCurveZ ? lRotCurveZ->KeyGetCount() : 0;
1254
//
1255
//        FbxTime lKeyTime;
1256
//        int lCount, lKeyCount;
1257
//        if(lRotCurveX) {
1258
//            lKeyCount = lRotCurveX->KeyGetCount();
1259
//            for(lCount = 0; lCount < lKeyCount; lCount++) {
1260
//                lKeyTime  = lRotCurveX->KeyGetTime(lCount);
1261
//                if( mTimeCount.count(lKeyTime.GetMilliSeconds()) == 0 ) {
1262
//                    mTimeCount[lKeyTime.GetMilliSeconds()] += 1;
1263
//
1264
//                    ofxFBXKey<ofQuaternion> tkey;
1265
//                    //glm::mat4 tOfMat;
1266
//                    glm::vec3 translation, scale;
1267
//                    glm::quat rotation;
1268
//                    if( pNode->GetParent() ) {
1269
//                        FbxAMatrix& tmatrix = pNode->EvaluateLocalTransform( lKeyTime );
1270
//                        //tOfMat = fbxToOf( tmatrix );
1271
//                        fbxToGlmComponents(tmatrix, translation, rotation, scale);
1272
//                    } else {
1273
//                        FbxAMatrix& tmatrix = pNode->EvaluateGlobalTransform( lKeyTime );
1274
//                        //tOfMat = fbxToOf( tmatrix );
1275
//                        fbxToGlmComponents(tmatrix, translation, rotation, scale);
1276
//                    }
1277
//
1278
//                    //glm::vec3 scale;
1279
//                   // glm::quat rotation;
1280
//                   // glm::vec3 translation;
1281
//                    //glm::vec3 skew;
1282
//                    //glm::vec4 perspective;
1283
//
1284
//                    //glm::decompose(tOfMat, scale, rotation, translation, skew, perspective);
1285
//
1286
//                    tkey.value = rotation;
1287
////                    ofVec3f t,s;
1288
////                    ofQuaternion so;
1289
////
1290
////                    tOfMat.decompose( t, tkey.value, s, so);
1291
//
1292
//                    tkey.millis = lKeyTime.GetMilliSeconds();
1293
//                    newRotKeys.push_back( tkey );
1294
//                }
1295
//            }
1296
//        }
1297
//
1298
//        if( newRotKeys.size() ) {
1299
//            kcollection.rotKeys = newRotKeys;
1300
//        }
1301
//
1302
//        ofLogVerbose("ofxFBX :: populateKeyFrames : ") << "anim: " << aAnimIndex << " node: " << fnode->getName() << " num pos keys: " << kcollection.posKeysX.size() << " num rot keys: " << kcollection.rotKeys.size() << " num scale keys: " << kcollection.scaleKeysX.size() << " | " << ofGetFrameNum() << endl;
1303
//    }
1304
    
1305
    // cycle through the children //
1306
    const int lChildCount = pNode->GetChildCount();
1307
    for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
1308
        populateKeyFrames( pNode->GetChild(lChildIndex), aAnimIndex );
1309
    }
1310
}
1311

1312
//--------------------------------------------------------------
1313
vector< ofxFBXSource::AnimKey<float> > Scene::getFloatKeys( FbxAnimCurve* pCurve ) {
1314
    vector< ofxFBXSource::AnimKey<float> > tkeys;
1315
    
1316
    FbxTime lKeyTime;
1317
    float lKeyValue;
1318
    int lKeyCount, lCount;
1319
    
1320
    if( pCurve ) {
1321
        lKeyCount = pCurve->KeyGetCount();
1322
        for(lCount = 0; lCount < lKeyCount; lCount++) {
1323
            lKeyValue = static_cast<float>(pCurve->KeyGetValue(lCount));
1324
            lKeyTime  = pCurve->KeyGetTime(lCount);
1325
            ofxFBXSource::AnimKey<float> tkey;
1326
            tkey.value = lKeyValue;
1327
            tkey.millis = lKeyTime.GetMilliSeconds();
1328
            tkeys.push_back( tkey );
1329
        }
1330
    }
1331
    
1332
    return tkeys;
1333
}
1334

1335
//--------------------------------------------------------------
1336
bool Scene::requiresKeyForTime( vector< ofxFBXSource::AnimKey<float> >& tkeys, signed long amillis1, signed long amillis2 ) {
1337
    for( int i = 0; i < tkeys.size(); i++ ) {
1338
        if(tkeys[i].millis >= amillis1 && tkeys[i].millis < amillis2 ) {
1339
            return true;
1340
        }
1341
    }
1342
    return false;
1343
}
1344

1345

1346

1347

1348

1349

1350

1351

1352

1353

1354

1355

1356

1357

1358

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.