framework2
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
12FbxSystemUnit ofxFBXSource::Scene::FbxUnits = FbxSystemUnit::cm;
13
14using namespace ofxFBXSource;
15
16//--------------------------------------------------------------
17Scene::Scene() {
18lSdkManager = NULL;
19lScene = NULL;
20currentFbxAnimationLayer = NULL;
21fbxFilePath = "";
22}
23
24//--------------------------------------------------------------
25Scene::~Scene() {
26
27if (currentFbxAnimationLayer != NULL) {
28currentFbxAnimationLayer->Destroy();
29}
30
31if(lScene != NULL ) {
32deleteCachedTexturesInScene( lScene );
33deleteCachedMaterialsRecursive( lScene->GetRootNode() );
34lScene->Destroy(true);
35}
36
37
38
39if(lSdkManager != NULL) {
40bool 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//--------------------------------------------------------------
50bool Scene::load( Settings aSettings ) {
51if( aSettings.filePath == "" ) {
52ofLogError("ofxFBXSource::Scene::load()") << " file path not set in settings!! " << " :(";
53return false;
54}
55return load( aSettings.filePath, aSettings );
56}
57
58//--------------------------------------------------------------
59bool Scene::load( string path, Scene::Settings aSettings ) {
60
61if( !ofFile::doesFileExist(path)) {
62ofLogError("ofxFBXSource::Scene::load()") << " File does not exist!!: " << path << " :(";
63return false;
64}
65
66bool lResult = false;
67
68// Prepare the FBX SDK.
69InitializeSdkObjects(lSdkManager, lScene);
70
71// make sure to import bones if we have animations. Since some animations are bone based.
72if(aSettings.importAnimations) {
73// make sure to import the bones / known as links in the FBX SDK
74aSettings.importBones = true;
75aSettings.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
89lResult = LoadScene(lSdkManager, lScene, ofToDataPath(path).c_str());
90
91if(!lResult || !lScene ) {
92ofLogError("ofxFBXSource::Scene") << "An error occurred while loading the scene... :(";
93return false;
94}
95
96fbxFilePath = ofToDataPath(path);
97
98if(aSettings.printInfo) cout << "ofxFBXSrcScene :: loading fbx file from " << fbxFilePath << endl;
99
100// Convert Axis System to what is used in this example, if needed
101FbxAxisSystem SceneAxisSystem = lScene->GetGlobalSettings().GetAxisSystem();
102// FbxAxisSystem OurAxisSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eRightHanded);
103FbxAxisSystem OurAxisSystem( FbxAxisSystem::OpenGL );
104if( SceneAxisSystem != OurAxisSystem ) {
105OurAxisSystem.ConvertScene(lScene);
106}
107
108// Convert Unit System to what is used in this example, if needed
109FbxSystemUnit SceneSystemUnit = lScene->GetGlobalSettings().GetSystemUnit();
110ofLogVerbose("ofxFBXSource::Scene") << "SceneSystemUnit = " << SceneSystemUnit.GetScaleFactor() << " " << SceneSystemUnit.GetScaleFactorAsString_Plurial();
111
112if( ofxFBXSource::Scene::FbxUnits.GetScaleFactor() == 0 ) {
113// setting to the default cm //
114ofxFBXSource::Scene::FbxUnits = FbxSystemUnit::cm;
115}
116
117if( SceneSystemUnit.GetScaleFactor() != ofxFBXSource::Scene::FbxUnits.GetScaleFactor() ) {
118ofLogVerbose("ofxFBXSource::Scene") << "coverting scene from " << SceneSystemUnit.GetScaleFactorAsString_Plurial() << " to " << ofxFBXSource::Scene::FbxUnits.GetScaleFactorAsString_Plurial();
119ofxFBXSource::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 //
131cacheTexturesInScene( lScene );
132// cache all of the materials in the scene as ofxFBXMeshMaterial //
133if( _settings.importMaterials ) {
134cacheMaterialsRecursive( lScene->GetRootNode() );
135}
136
137// Initialize the frame period.
138fbxFrameTime.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 );
142ofLogVerbose() << "ofxFBXSource::Scene :: time mode: " << lScene->GetGlobalSettings().GetTimeMode() << endl;
143
144// Get the list of all the animation stack.
145if( areAnimationsEnabled() ) {
146populateAnimationInformation();
147}
148
149if(animations.size() > 0) {
150FbxAnimStack * lCurrentAnimationStack = lScene->FindMember<FbxAnimStack>( (&animations[0].fbxname)->Buffer());
151if (lCurrentAnimationStack == NULL) {
152ofLogError("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!
154return 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)
159currentFbxAnimationLayer = lCurrentAnimationStack->GetMember<FbxAnimLayer>();
160}
161
162_parseNodesRecursive( lScene->GetRootNode() );
163
164// populate bones //
165if( _settings.importBones ) {
166_constructSkeletons( lScene->GetRootNode() );
167}
168
169// add in the keyframe information //
170if( 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// }
179for( auto& node : mSrcNodes ) {
180node->setUseKeyFrames(true);
181}
182
183for( int i = 0; i < getNumAnimations(); i++ ) {
184
185FbxAnimStack* currentAnimationStack = getFBXScene()->FindMember<FbxAnimStack>( (&animations[i].fbxname)->Buffer() );
186if (currentAnimationStack == NULL) {
187// this is a problem. The anim stack should be found in the scene!
188ofLogWarning("ofxFBXSource::Scene :: setAnimation : the anim stack was not found in the scene!");
189continue;
190}
191currentFbxAnimationLayer = currentAnimationStack->GetMember<FbxAnimLayer>();
192getFBXScene()->SetCurrentAnimationStack( currentAnimationStack );
193
194populateKeyFrames( lScene->GetRootNode(), i );
195}
196}
197
198if(animations.size() > 0) {
199FbxAnimStack * lCurrentAnimationStack = lScene->FindMember<FbxAnimStack>( (&animations[0].fbxname)->Buffer());
200if (lCurrentAnimationStack == NULL) {
201ofLogError("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!
203return 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)
208currentFbxAnimationLayer = lCurrentAnimationStack->GetMember<FbxAnimLayer>();
209}
210
211_parentNodesRecursive(lScene->GetRootNode());
212
213if( _settings.printInfo ) {
214cout << getInfoString() << endl;
215}
216
217return true;
218}
219
220
221#pragma mark - Getters
222// ---------------------------------------------- getters
223FbxScene* Scene::getFBXScene() {
224return lScene;
225}
226
227// ---------------------------------------------- utils
228string Scene::getFbxFilePath() {
229return fbxFilePath;
230}
231
232//--------------------------------------------------------------
233string Scene::getFbxFolderPath() {
234if(fbxFilePath == "") return "";
235const FbxString lAbsFbxFileName = FbxPathUtils::Resolve( getFbxFilePath().c_str() );
236return (string)FbxPathUtils::GetFolderName(lAbsFbxFileName);
237}
238
239//--------------------------------------------------------------
240ofxFBXSource::Node::NodeType Scene::getOFXNodeType( FbxNode* aNode ) {
241FbxNodeAttribute* lNodeAttribute = aNode->GetNodeAttribute();
242if( lNodeAttribute ) {
243FbxNodeAttribute::EType et = lNodeAttribute->GetAttributeType();
244if (et == FbxNodeAttribute::eMesh ||
245et == FbxNodeAttribute::eNurbs ||
246et == FbxNodeAttribute::ePatch ||
247et == FbxNodeAttribute::eNurbsSurface) {
248return ofxFBXSource::Node::OFX_FBX_MESH;
249} else if( et == FbxNodeAttribute::eNurbsCurve ) {
250return ofxFBXSource::Node::OFX_FBX_NURBS_CURVE;
251} else if( et == FbxNodeAttribute::eNull ) {
252return ofxFBXSource::Node::OFX_FBX_NULL;
253} else if( et == FbxNodeAttribute::eSkeleton ) {
254if( aNode->GetSkeleton() && aNode->GetSkeleton()->IsSkeletonRoot() ) {
255return ofxFBXSource::Node::OFX_FBX_SKELETON;
256}
257return ofxFBXSource::Node::OFX_FBX_BONE;
258}
259}
260
261return ofxFBXSource::Node::OFX_FBX_NULL;
262}
263
264//--------------------------------------------------------------
265vector< shared_ptr<ofxFBXSource::Node> > Scene::getSceneNodes() {
266return mSceneNodes;
267}
268
269//--------------------------------------------------------------
270string Scene::getInfoString() {
271stringstream ss;
272ss << "ofxFBXSource::Scene : " << ofFilePath::getBaseName(fbxFilePath)<<"."<<ofFilePath::getFileExt(fbxFilePath) << endl;
273for( auto& sn : mSceneNodes ) {
274ss << sn->getAsString();
275}
276return ss.str();
277}
278
279#pragma mark - Textures
280// ---------------------------------------------- animation
281void Scene::cacheTexturesInScene( FbxScene* pScene ) {
282// Load the textures into GPU, only for file texture now
283const int lTextureCount = pScene->GetTextureCount();
284for (int lTextureIndex = 0; lTextureIndex < lTextureCount; ++lTextureIndex) {
285FbxTexture * lTexture = pScene->GetTexture(lTextureIndex);
286FbxFileTexture * lFileTexture = FbxCast<FbxFileTexture>(lTexture);
287if (lFileTexture && !lFileTexture->GetUserDataPtr()) {
288// Try to load the texture from absolute path
289const FbxString lFileName = lFileTexture->GetFileName();
290
291GLuint lTextureObject = 0;
292bool bFoundTexture = false;
293string filepath = (string)lFileName;
294bFoundTexture = isValidTexturePath( filepath );
295
296const FbxString lAbsFbxFileName = FbxPathUtils::Resolve( fbxFilePath.c_str() );
297const FbxString lAbsFolderName = FbxPathUtils::GetFolderName(lAbsFbxFileName);
298
299if( !bFoundTexture ) {
300// Load texture from relative file name (relative to FBX file)
301const FbxString lResolvedFileName = FbxPathUtils::Bind(lAbsFolderName, lFileTexture->GetRelativeFileName());
302filepath = (string)lResolvedFileName;
303bFoundTexture = isValidTexturePath( filepath );
304}
305
306if(!bFoundTexture) {
307// Load texture from file name only (relative to FBX file)
308const FbxString lTextureFileName = FbxPathUtils::GetFileName(lFileName);
309const FbxString lResolvedFileName = FbxPathUtils::Bind(lAbsFolderName, lTextureFileName);
310filepath = (string)lResolvedFileName;
311bFoundTexture = isValidTexturePath( filepath );
312}
313
314if(!bFoundTexture) {
315ofLogWarning("ofxFBXSource::Scene :: Could not find texture ") << filepath;
316continue;
317}
318
319if (bFoundTexture) {
320// ofxFBXSource::MeshTexture* texture = new ofxFBXSource::MeshTexture();
321auto texture = make_shared<ofxFBXSource::MeshTexture>();
322
323if( _settings.importTextures ) {
324ofPixels pixels;
325bool loaded = ofLoadImage(pixels, filepath);
326if(loaded){
327texture->allocate(pixels.getWidth(), pixels.getHeight(), ofGetGLInternalFormat(pixels), false);
328pixels.mirror(true, false);
329texture->loadData(pixels);
330}
331if(loaded) {
332ofLogVerbose("ofxFBXSource::Scene :: Loaded the texture from ") << filepath << endl;
333
334texture->getTextureData().bFlipTexture = true;
335texture->disableTextureMatrix();
336texture->filePath = filepath;
337
338lFileTexture->SetUserDataPtr( texture.get() );
339} else {
340ofLogError("ofxFBXSource::Scene :: Failed to load texture for ") << lFileName;
341//delete texture;
342//texture = NULL;
343texture.reset();
344}
345} else {
346ofLogVerbose("ofxFBXSource::Scene :: found texture, but not loading pixel data ") << filepath << endl;
347texture->filePath = filepath;
348lFileTexture->SetUserDataPtr( texture.get() );
349}
350if( texture ) {
351mTextures.push_back(texture);
352}
353}
354}
355}
356}
357
358void Scene::deleteCachedTexturesInScene( FbxScene* pScene ) {
359const int lTextureCount = pScene->GetTextureCount();
360for (int lTextureIndex = 0; lTextureIndex < lTextureCount; ++lTextureIndex) {
361FbxTexture* lTexture = pScene->GetTexture(lTextureIndex);
362FbxFileTexture* lFileTexture = FbxCast<FbxFileTexture>(lTexture);
363if (lFileTexture && lFileTexture->GetUserDataPtr()) {
364// ofxFBXSource::MeshTexture* texture = static_cast<ofxFBXSource::MeshTexture *>( lFileTexture->GetUserDataPtr() );
365//auto texture = static_cast< shared_ptr<ofxFBXSource::MeshTexture>* >(lFileTexture->GetUserDataPtr());
366lFileTexture->SetUserDataPtr(NULL);
367//delete texture;
368//texture = NULL;
369}
370}
371mTextures.clear();
372}
373
374bool Scene::isValidTexturePath( string aPathToTexture ) {
375ofFile tfile( (string)aPathToTexture );
376if(!tfile.exists()) return false;
377bool bGoodToGo = false;
378if(tfile.getExtension() == "tga") bGoodToGo = true;
379if(tfile.getExtension() == "jpg") bGoodToGo = true;
380if(tfile.getExtension() == "png") bGoodToGo = true;
381if(tfile.getExtension() == "bmp") bGoodToGo = true;
382if(tfile.getExtension() == "tif") bGoodToGo = true;
383if(tfile.getExtension() == "tiff") bGoodToGo = true;
384return bGoodToGo;
385}
386
387#pragma mark - Materials
388// ---------------------------------------------- materials
389void Scene::cacheMaterialsRecursive( FbxNode* pNode ) {
390// Bake material and hook as user data.
391const int lMaterialCount = pNode->GetMaterialCount();
392for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) {
393FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex);
394if (lMaterial && !lMaterial->GetUserDataPtr()) {
395ofxFBXSource::MeshMaterial* materialCache = new ofxFBXSource::MeshMaterial();
396ofLogVerbose("ofxFBXSource::Scene") << "found a material :: " << lMaterial->GetName();
397// ofLogNotice("ofxFBXScene") << "found a material :: " << lMaterial->GetName();
398materialCache->setup( lMaterial );
399lMaterial->SetUserDataPtr( materialCache );
400}
401}
402
403const int lChildCount = pNode->GetChildCount();
404for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
405cacheMaterialsRecursive( pNode->GetChild(lChildIndex) );
406}
407}
408
409void Scene::deleteCachedMaterialsRecursive( FbxNode* pNode ) {
410const int lMaterialCount = pNode->GetMaterialCount();
411for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) {
412FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex);
413if (lMaterial && lMaterial->GetUserDataPtr()) {
414ofxFBXSource::MeshMaterial* materialCache = static_cast<ofxFBXSource::MeshMaterial *>(lMaterial->GetUserDataPtr());
415lMaterial->SetUserDataPtr(NULL);
416delete materialCache;
417materialCache = NULL;
418}
419}
420
421const int lChildCount = pNode->GetChildCount();
422for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
423deleteCachedMaterialsRecursive( pNode->GetChild(lChildIndex) );
424}
425}
426
427#pragma mark - Animation
428// ---------------------------------------------- animation
429int Scene::getNumAnimations() {
430return animations.size();
431}
432
433//--------------------------------------------------------------
434bool Scene::areAnimationsEnabled() {
435return _settings.importAnimations;
436}
437
438//--------------------------------------------------------------
439void Scene::populateAnimationInformation() {
440FbxArray<FbxString*> mAnimStackNameArray;
441lScene->FillAnimStackNameArray(mAnimStackNameArray);
442// animations.resize( mAnimStackNameArray.GetCount() );
443for(int i = 0; i < mAnimStackNameArray.GetCount(); i++ ) {
444
445FbxAnimStack* lCurrentAnimationStack = lScene->FindMember<FbxAnimStack>(mAnimStackNameArray[i]->Buffer());
446FbxTakeInfo* lCurrentTakeInfo = lScene->GetTakeInfo(*(mAnimStackNameArray[i]));
447
448FbxTime startTime, endTime;
449
450if (lCurrentTakeInfo) {
451startTime = lCurrentTakeInfo->mLocalTimeSpan.GetStart();
452endTime = lCurrentTakeInfo->mLocalTimeSpan.GetStop();
453} else {
454// Take the time line value
455FbxTimeSpan lTimeLineTimeSpan;
456lScene->GetGlobalSettings().GetTimelineDefaultTimeSpan(lTimeLineTimeSpan);
457startTime = lTimeLineTimeSpan.GetStart();
458endTime = lTimeLineTimeSpan.GetStop();
459}
460ofxFBXAnimation animation;
461animation.setup( startTime, endTime, fbxFrameTime );
462animation.fbxCurrentTime = animation.fbxStartTime;
463FbxString tfbxName = FbxString(*mAnimStackNameArray[i]);
464animation.fbxname = tfbxName;
465animation.index = i;
466animation.name = FbxString(*mAnimStackNameArray[i]);
467animations.push_back( animation );
468//FbxString ostr = startTime;
469//startTime.
470ofLogVerbose("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
485FbxArrayDelete(mAnimStackNameArray);
486
487// check if there is an xml file //
488if( fbxFilePath != "" && _settings.useKeyFrames ) {
489string tencDir = ofFilePath::addTrailingSlash( ofFilePath::getEnclosingDirectory( fbxFilePath ) );
490string txmlPath = tencDir + ofFilePath::getBaseName(fbxFilePath)+".xml";
491if( ofFile::doesFileExist(txmlPath)) {
492ofXml txml;
493if( txml.load(txmlPath)) {
494ofLogVerbose("ofxFBXSource::Source : populateAnimationInformation : found animation file: ") << txmlPath;
495auto animationClipsXml = txml.find("//AnimationClip");
496if( animationClipsXml.size() > 0 ) {
497clearAnimations();
498for( int i = 0; i < animationClipsXml.size(); i++ ) {
499string tname = animationClipsXml[i].getAttribute("name").getValue();
500int sframe = animationClipsXml[i].getAttribute("startFrame").getIntValue();
501int eframe = animationClipsXml[i].getAttribute("endFrame" ).getIntValue();
502string loopStr = animationClipsXml[i].getAttribute("loops").getValue();
503bool bLoops = false;
504if( ofToLower(loopStr) == "true" ) {
505bLoops = true;
506}
507auto& tanim = addAnimation( tname, sframe, eframe );
508tanim.setLoops( bLoops );
509
510ofLogVerbose("ofxFBXSource::Source : adding animation: ") << i << " name: " << tanim.name << " num frames: " << tanim.getTotalNumFrames() << " loops: " << tanim.getLoops();
511}
512}
513}
514}
515}
516}
517
518//--------------------------------------------------------------
519void Scene::clearAnimations() {
520animations.clear();
521
522if( 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
532for( auto& node : mSrcNodes ) {
533node->clearKeyFrames();
534}
535}
536bMeshKeyframesCached = false;
537
538}
539
540//--------------------------------------------------------------
541ofxFBXAnimation& Scene::addAnimation( string aname, int aFrameBegin, int aFrameEnd, int aAnimStackIndex ) {
542FbxArray<FbxString*> mAnimStackNameArray;
543lScene->FillAnimStackNameArray(mAnimStackNameArray);
544//animations.resize( mAnimStackNameArray.GetCount() );
545
546if( mAnimStackNameArray.GetCount() < 1 ) {
547ofLogError("ofxFBXSource::Scene :: addAnimation : no animations in file found" );
548return dummyAnimation;
549}
550if( aAnimStackIndex >= mAnimStackNameArray.GetCount()) {
551ofLogError("ofxFBXSource::Scene :: addAnimation : anim stack index" ) << " ("<<aAnimStackIndex<<") is out of bounds";
552return dummyAnimation;
553}
554
555FbxAnimStack* lCurrentAnimationStack = lScene->FindMember<FbxAnimStack>(mAnimStackNameArray[aAnimStackIndex]->Buffer());
556FbxTakeInfo* lCurrentTakeInfo = lScene->GetTakeInfo(*(mAnimStackNameArray[aAnimStackIndex]));
557
558FbxTime startTime, endTime;
559
560if (lCurrentTakeInfo) {
561startTime = lCurrentTakeInfo->mLocalTimeSpan.GetStart();
562endTime = lCurrentTakeInfo->mLocalTimeSpan.GetStop();
563} else {
564// Take the time line value
565FbxTimeSpan lTimeLineTimeSpan;
566lScene->GetGlobalSettings().GetTimelineDefaultTimeSpan(lTimeLineTimeSpan);
567startTime = lTimeLineTimeSpan.GetStart();
568endTime = lTimeLineTimeSpan.GetStop();
569}
570
571int 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
576FbxTime startFrameTime = startTime + fbxFrameTime * aFrameBegin;
577FbxTime endFrameTime = startTime + fbxFrameTime * aFrameEnd;
578
579startFrameTime.SetMilliSeconds( (int)ofMap((float)aFrameBegin / (float)totalFrames, 0.f, 1.f, startTime.GetMilliSeconds(), endTime.GetMilliSeconds(), true ));
580endFrameTime.SetMilliSeconds( (int)ofMap((float)aFrameEnd / (float)totalFrames, 0.f, 1.f, startTime.GetMilliSeconds(), endTime.GetMilliSeconds(), true ));
581
582if( startFrameTime > endTime ) startFrameTime = endTime;
583if( endFrameTime > endTime ) endFrameTime = endTime;
584// fbxCurrentTime = fbxStartTime + fbxFrameTime * tframe;
585
586ofxFBXAnimation animation;
587animation.setup( startFrameTime, endFrameTime, fbxFrameTime );
588animation.fbxCurrentTime = animation.fbxStartTime;
589FbxString tfbxName = FbxString(*mAnimStackNameArray[aAnimStackIndex]);
590animation.fbxname = tfbxName;
591animation.index = animations.size();
592animation.name = aname;//FbxString(*mAnimStackNameArray[i]);
593animations.push_back( animation );
594ofLogVerbose("ofxFBXSource::Scene") << " Adding animation :: name: " << animation.name << " starttime: " << startFrameTime.GetTimeString() << " end time: " << endFrameTime.GetTimeString() << " num frames: " << animation.getTotalNumFrames() << endl;
595
596if( areAnimationsEnabled() && _settings.useKeyFrames ) {
597FbxAnimStack* currentAnimationStack = getFBXScene()->FindMember<FbxAnimStack>( (&animation.fbxname)->Buffer() );
598if (currentAnimationStack != NULL) {
599getFBXScene()->SetCurrentAnimationStack( currentAnimationStack );
600populateKeyFrames( lScene->GetRootNode(), animation.index );
601} else {
602// this is a problem. The anim stack should be found in the scene!
603ofLogWarning("ofxFBXSource::Scene :: addAnimation : the anim stack was not found in the scene!");
604}
605}
606
607FbxArrayDelete(mAnimStackNameArray);
608return animations.back();
609}
610
611//--------------------------------------------------------------
612void Scene::populateAnimations( vector<ofxFBXAnimation>& aInVector) {
613for(int i = 0; i < animations.size(); i++ ) {
614aInVector.push_back(animations[i]);
615}
616}
617
618#pragma mark - Bones / Skeleton
619//--------------------------------------------------------------
620void Scene::constructSkeletonsRecursive( ofxFBXSource::Skeleton* aSkeleton, FbxNode* pNode, int aBoneLevel ) {
621FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute();
622if (lNodeAttribute && lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton) {
623if(pNode->GetParent() && pNode->GetParent()->GetNodeAttribute()) {
624if(pNode->GetParent()->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eSkeleton) {
625if(pNode->GetParent()->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eSkeleton) {
626ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>(pNode->GetUserDataPtr());
627ofxFBXSource::Bone* bonePtrParent = static_cast<ofxFBXSource::Bone *>(pNode->GetParent()->GetUserDataPtr());
628
629bonePtr->parentBoneName = bonePtrParent->getName();
630bonePtr->setParent( *bonePtrParent, true );
631
632bonePtr->setLocalTransformMatrix( GetGlobalPosition(pNode, FBXSDK_TIME_INFINITE, NULL ) );
633bonePtr->cacheStartTransforms();
634
635if( 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());
639shared_ptr<ofxFBXSource::Bone> cbone;
640for( auto& tm : mSrcNodes ) {
641if( tm.get() == bonePtr ) {
642cbone = dynamic_pointer_cast<ofxFBXSource::Bone>(tm);
643break;
644}
645}
646if( cbone ) {
647bonePtrParent->childBones[ bonePtr->getName() ] = cbone;
648}
649}
650}
651}
652}
653}
654
655const int lChildCount = pNode->GetChildCount();
656for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
657constructSkeletonsRecursive( aSkeleton, pNode->GetChild(lChildIndex), aBoneLevel+1 );
658}
659}
660
661#pragma mark - Poses
662//--------------------------------------------------------------
663int Scene::getNumPoses() {
664if( lScene == NULL ) return 0;
665return lScene->GetPoseCount();
666}
667
668//--------------------------------------------------------------
669void Scene::populatePoses( vector< shared_ptr<ofxFBXSource::Pose> >& aInPoses ) {
670
671for( int i = 0; i < lScene->GetPoseCount(); i++ ) {
672aInPoses.push_back( shared_ptr<ofxFBXSource::Pose>( new ofxFBXSource::Pose() ));
673shared_ptr< ofxFBXSource::Pose > pose = aInPoses.back();
674pose->setup( lScene->GetPose(i), i );
675}
676
677}
678
679#pragma mark - Private
680//--------------------------------------------------------------
681void Scene::_parseNodesRecursive( FbxNode* aNode ) {
682if( aNode == NULL ) { return; }
683
684// FbxNodeAttribute* lNodeAttribute = aNode->GetNodeAttribute();
685ofxFBXSource::Node::NodeType ftype = getOFXNodeType( aNode );
686if (ftype == ofxFBXSource::Node::OFX_FBX_MESH) {
687auto tmesh = _getMeshForNode( aNode );
688if( tmesh ) {
689// meshes.push_back( tmesh );
690mSrcNodes.push_back(tmesh);
691}
692} else if(ftype == ofxFBXSource::Node::OFX_FBX_NURBS_CURVE) {
693if( _settings.importNurbsCurves ) {
694auto tcurve = _getNurbsCurveForNode( aNode );
695if( tcurve ) {
696// mNurbsCurves.push_back(tcurve);
697mSrcNodes.push_back(tcurve);
698}
699}
700} else if(ftype == ofxFBXSource::Node::OFX_FBX_NULL ) {
701auto tnull = _getNullForNode( aNode );
702if( tnull ) {
703// mNullNodes.push_back(tnull);
704mSrcNodes.push_back(tnull);
705}
706} else if( ftype == ofxFBXSource::Node::OFX_FBX_SKELETON || ftype == ofxFBXSource::Node::OFX_FBX_BONE ) {
707if( _settings.importBones ) {
708auto tbone = _getBoneForNode(aNode);
709if( tbone ) {
710// bones.push_back( tbone );
711mSrcNodes.push_back(tbone);
712}
713}
714}
715
716
717const int lChildCount = aNode->GetChildCount();
718for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
719_parseNodesRecursive( aNode->GetChild(lChildIndex) );
720}
721}
722
723//--------------------------------------------------------------
724void Scene::_constructSkeletons( FbxNode* aNode ) {
725list<FbxNode*> skeletonBases;
726
727_getSkeletonBases( aNode, skeletonBases );
728
729list<FbxNode*>::iterator it;
730for(it = skeletonBases.begin(); it != skeletonBases.end(); ++it ) {
731
732auto skeletonPtr = make_shared<ofxFBXSource::Skeleton>();
733// skeletons.push_back( skeletonPtr );
734mSrcNodes.push_back( skeletonPtr );
735FbxNode* skeletonNode = *it;
736//auto bonePtr = static_cast<ofxFBXSource::Bone *>( skeletonNode->GetUserDataPtr() );
737
738// auto cbone = dynamic_pointer_cast<ofxFBXSource::Bone>(_getOfxNodeFromNodeUserData(skeletonNode));
739ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>( skeletonNode->GetUserDataPtr() );
740shared_ptr<ofxFBXSource::Bone> cbone;
741for( auto& tm : mSrcNodes ) {
742if( tm.get() == bonePtr ) {
743cbone = dynamic_pointer_cast<ofxFBXSource::Bone>(tm);
744break;
745}
746}
747
748// cout << "ofxFBXSrcScene :: _constructSkeletons : we have a bone " << (cbone ? "Good" : "Bad" ) << endl;
749
750if( cbone ) {
751skeletonPtr->root = cbone;//static_cast<ofxFBXSource::Bone *>( skeletonNode->GetUserDataPtr() );
752skeletonPtr->setup( skeletonNode );
753
754constructSkeletonsRecursive( skeletonPtr.get(), skeletonNode, 0 );
755}
756}
757}
758
759//--------------------------------------------------------------
760void Scene::_getSkeletonBases( FbxNode* aNode, list<FbxNode*>& aSkeletonBases ) {
761ofxFBXSource::Node::NodeType ftype = getOFXNodeType( aNode );
762if( ftype == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
763aSkeletonBases.push_back( aNode );
764}
765
766const int lChildCount = aNode->GetChildCount();
767for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
768_getSkeletonBases( aNode->GetChild(lChildIndex), aSkeletonBases );
769}
770}
771
772//--------------------------------------------------------------
773shared_ptr<ofxFBXSource::Mesh> Scene::_getMeshForNode( FbxNode* aNode ) {
774shared_ptr<ofxFBXSource::Mesh> tmesh;
775if( aNode == NULL ) return tmesh;
776
777if(aNode->GetMesh()) {
778FbxGeometryConverter lGeomConverter( lSdkManager );
779lGeomConverter.Triangulate( aNode->GetMesh(), true );
780
781tmesh = make_shared<ofxFBXSource::Mesh>();
782tmesh->setup( aNode );
783
784if( !aNode->GetUserDataPtr() ) {
785aNode->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
791FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
792if( !aNode->GetParent() ) {
793tmesh->setLocalTransformMatrix(lGlobalPosition);
794} else {
795FbxAMatrix lLocalPosition = GetLocalPositionForNode(aNode, FBXSDK_TIME_INFINITE, NULL );
796tmesh->setLocalTransformMatrix(lLocalPosition);
797}
798tmesh->cacheStartTransforms();
799
800// Associtate the clusters with some user data so that we can move them around //
801int lSkinCount = aNode->GetMesh()->GetDeformerCount(FbxDeformer::eSkin);
802
803if( lSkinCount > 0 && _settings.importBones ) {
804
805for ( int lSkinIndex=0; lSkinIndex<lSkinCount; ++lSkinIndex) {
806FbxSkin * lSkinDeformer = (FbxSkin *)aNode->GetMesh()->GetDeformer(lSkinIndex, FbxDeformer::eSkin);
807
808int lClusterCount = lSkinDeformer->GetClusterCount();
809for ( int lClusterIndex=0; lClusterIndex<lClusterCount; ++lClusterIndex) {
810FbxCluster* lCluster = lSkinDeformer->GetCluster(lClusterIndex);
811if (!lCluster->GetLink())
812continue;
813
814if ( !lCluster->GetUserDataPtr() ) {
815auto fcluster = make_shared<ofxFBXSource::Cluster>();
816clusters.push_back( fcluster );
817// mSrcNodes.push_back(fcluster);
818fcluster->setup( lGlobalPosition, aNode->GetMesh(), lCluster );
819lCluster->SetUserDataPtr( fcluster.get() );
820}
821}
822}
823}
824}
825
826
827return tmesh;
828}
829
830//--------------------------------------------------------------
831shared_ptr<ofxFBXSource::NurbsCurve> Scene::_getNurbsCurveForNode( FbxNode* aNode ) {
832shared_ptr<ofxFBXSource::NurbsCurve> tc;
833if( aNode == NULL ) return tc;
834
835if(aNode->GetNurbsCurve() != NULL) {
836
837tc = make_shared<ofxFBXSource::NurbsCurve>();
838// mNurbsCurves.push_back(curve);
839tc->setup( aNode );
840
841if( !aNode->GetUserDataPtr() ) {
842aNode->SetUserDataPtr( tc.get() );
843}
844
845// FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
846// tc->setLocalTransformMatrix(lGlobalPosition);
847
848FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
849if( !aNode->GetParent() ) {
850tc->setLocalTransformMatrix(lGlobalPosition);
851} else {
852FbxAMatrix lLocalPosition = GetLocalPositionForNode(aNode, FBXSDK_TIME_INFINITE, NULL );
853tc->setLocalTransformMatrix(lLocalPosition);
854}
855tc->cacheStartTransforms();
856}
857
858return tc;
859}
860
861//--------------------------------------------------------------
862shared_ptr<ofxFBXSource::Node> Scene::_getNullForNode( FbxNode* aNode ) {
863shared_ptr<ofxFBXSource::Node> tn;
864if( aNode == NULL ) return tn;
865
866// if( aNode->GetNull() != NULL ) {
867tn = make_shared<ofxFBXSource::Node>();
868tn->setup(aNode);
869if( !aNode->GetUserDataPtr() ) {
870aNode->SetUserDataPtr( tn.get() );
871}
872
873// FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
874// tn->setLocalTransformMatrix(lGlobalPosition);
875
876FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, FBXSDK_TIME_INFINITE, NULL );
877if( !aNode->GetParent() ) {
878tn->setLocalTransformMatrix(lGlobalPosition);
879} else {
880FbxAMatrix lLocalPosition = GetLocalPositionForNode(aNode, FBXSDK_TIME_INFINITE, NULL );
881tn->setLocalTransformMatrix(lLocalPosition);
882}
883tn->cacheStartTransforms();
884
885return tn;
886}
887
888//--------------------------------------------------------------
889shared_ptr<ofxFBXSource::Bone> Scene::_getBoneForNode( FbxNode* aNode ) {
890shared_ptr<ofxFBXSource::Bone> tbone;
891if( aNode == NULL ) return tbone;
892
893if ( !aNode->GetUserDataPtr() ) {
894tbone = make_shared<ofxFBXSource::Bone>();
895// bones.push_back( tbone );
896tbone->setup( aNode );
897aNode->SetUserDataPtr( tbone.get() );
898}
899
900return tbone;
901}
902
903//--------------------------------------------------------------
904shared_ptr<ofxFBXSource::Node> Scene::_getOfxNodeFromNodeUserData( FbxNode* aNode ) {
905shared_ptr<ofxFBXSource::Node> fnode;
906if( aNode == NULL ) { return fnode; }
907
908ofxFBXSource::Node::NodeType ftype = getOFXNodeType( aNode );
909if(aNode->GetUserDataPtr() != NULL) {
910if (ftype == ofxFBXSource::Node::OFX_FBX_MESH) {
911ofxFBXSource::Mesh* nodePtr = static_cast<ofxFBXSource::Mesh *>(aNode->GetUserDataPtr());
912// try to find it in the meshes vector //
913for( auto& tm : mSrcNodes ) {
914if( tm.get() == nodePtr ) {
915fnode = tm;
916break;
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) {
925ofxFBXSource::NurbsCurve* nodePtr = static_cast<ofxFBXSource::NurbsCurve *>(aNode->GetUserDataPtr());
926for( auto& tm : mSrcNodes ) {
927if( tm.get() == nodePtr ) {
928fnode = tm;
929break;
930}
931}
932
933} else if(ftype == ofxFBXSource::Node::OFX_FBX_NULL ) {
934ofxFBXSource::Node* nodePtr = static_cast<ofxFBXSource::Node *>(aNode->GetUserDataPtr());
935for( auto& tm : mSrcNodes ) {
936if( tm.get() == nodePtr ) {
937fnode = tm;
938break;
939}
940}
941} else if(ftype == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
942ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>(aNode->GetUserDataPtr());
943for( auto& tm : mSrcNodes ) {
944if( tm->getType() == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
945auto tskel = dynamic_pointer_cast<ofxFBXSource::Skeleton>(tm);
946if( tskel->root.get() == bonePtr ) {
947fnode = tm;
948break;
949}
950}
951}
952} else if(ftype == ofxFBXSource::Node::OFX_FBX_BONE ) {
953ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>(aNode->GetUserDataPtr());
954for( auto& tm : mSrcNodes ) {
955if( tm.get() == bonePtr ) {
956fnode = tm;
957break;
958}
959}
960}
961}
962
963
964return fnode;
965}
966
967//--------------------------------------------------------------
968void Scene::_parentNodesRecursive( FbxNode* aNode ) {
969if( 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
983shared_ptr<ofxFBXSource::Node> cnode = _getOfxNodeFromNodeUserData( aNode );
984
985// if( cnode ) {
986//
987// }
988
989if( aNode->GetParent() && aNode->GetParent() != lScene->GetRootNode() ) {
990shared_ptr<ofxFBXSource::Node> pnode = _getOfxNodeFromNodeUserData( aNode->GetParent() );
991if( pnode && cnode ) {
992pnode->addChild(cnode);
993}
994} else {
995if(cnode) {
996mSceneNodes.push_back( cnode );
997}
998}
999
1000const int lChildCount = aNode->GetChildCount();
1001for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
1002_parentNodesRecursive( aNode->GetChild(lChildIndex) );
1003}
1004}
1005
1006#pragma mark - Keyframes
1007//--------------------------------------------------------------
1008void Scene::populateKeyFrames( FbxNode* pNode, int aAnimIndex ) {
1009
1010if( !pNode ) return;
1011
1012// cout << pNode->GetName() << " - populateKeyFrames animation index : " << aAnimIndex << endl;
1013
1014// populate the position first //
1015
1016ofxFBXSource::Node* fnode = nullptr;
1017
1018ofxFBXSource::Node::NodeType ftype = getOFXNodeType( pNode );
1019if( ftype != ofxFBXSource::Node::OFX_FBX_UNKNOWN && pNode->GetUserDataPtr() ) {
1020if( ftype == ofxFBXSource::Node::OFX_FBX_BONE || ftype == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
1021ofxFBXSource::Bone* bonePtr = static_cast<ofxFBXSource::Bone *>(pNode->GetUserDataPtr());
1022fnode = bonePtr;
1023} else if( ftype == ofxFBXSource::Node::OFX_FBX_MESH ) {
1024ofxFBXSource::Mesh* meshPtr = static_cast<ofxFBXSource::Mesh *>(pNode->GetUserDataPtr());
1025fnode = meshPtr;
1026}
1027}
1028
1029if( !fnode ) {
1030ofLogVerbose("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
1051if( fnode ) {
1052bool bGrabGlobalTransform = false;
1053FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute();
1054if ( lNodeAttribute && lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton ) {
1055if(pNode->GetSkeleton() && pNode->GetSkeleton()->IsSkeletonRoot() ) {
1056bGrabGlobalTransform = true;
1057// cout << "ofxFBXSrcScene :: skeleton global transform : " << pNode->GetName() << endl;
1058}
1059}
1060if( ftype != ofxFBXSource::Node::OFX_FBX_SKELETON && ftype != ofxFBXSource::Node::OFX_FBX_BONE ) {
1061if( !pNode->GetParent() ) {
1062bGrabGlobalTransform = true;
1063}
1064}
1065
1066// figure out the parsing //
1067ofxFBXAnimation& tanim = animations[ aAnimIndex ];
1068ofxFBXSource::AnimKeyCollection& kcollection = fnode->getKeyCollection( aAnimIndex );
1069
1070
1071FbxAnimCurve* lPosCurveX = pNode->LclTranslation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_X);
1072FbxAnimCurve* lPosCurveY = pNode->LclTranslation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1073FbxAnimCurve* lPosCurveZ = pNode->LclTranslation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1074auto posXKeys = getFloatKeys( lPosCurveX );
1075auto posYKeys = getFloatKeys( lPosCurveY );
1076auto posZKeys = getFloatKeys( lPosCurveZ );
1077
1078FbxAnimCurve* lScaleCurveX = pNode->LclScaling.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_X);
1079FbxAnimCurve* lScaleCurveY = pNode->LclScaling.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1080FbxAnimCurve* lScaleCurveZ = pNode->LclScaling.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1081auto scaleXKeys = getFloatKeys( lScaleCurveX );
1082auto scaleYKeys = getFloatKeys( lScaleCurveY );
1083auto scaleZKeys = getFloatKeys( lScaleCurveZ );
1084
1085FbxAnimCurve* lRotCurveX = pNode->LclRotation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_X);
1086FbxAnimCurve* lRotCurveY = pNode->LclRotation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Y);
1087FbxAnimCurve* lRotCurveZ = pNode->LclRotation.GetCurve(currentFbxAnimationLayer, FBXSDK_CURVENODE_COMPONENT_Z);
1088
1089auto rotXKeys = getFloatKeys( lRotCurveX );
1090auto rotYKeys = getFloatKeys( lRotCurveY );
1091auto rotZKeys = getFloatKeys( lRotCurveZ );
1092
1093int numPosKeys = 0;
1094int numScaleKeys = 0;
1095int numRotKeys = 0;
1096
1097for( int i = 0; i < tanim.getTotalNumFrames(); i++ ) {
1098tanim.setFrame(i);
1099
1100signed long long cmillis = tanim.fbxCurrentTime.GetMilliSeconds();
1101signed long long nmillis = tanim.fbxCurrentTime.GetMilliSeconds() + fbxFrameTime.GetMilliSeconds();
1102
1103// now get the information //
1104bool bHasPosKey = false;
1105bool bHasScaleKey = false;
1106bool bHasRotKey = false;
1107
1108if( i == 0 || i == tanim.getTotalNumFrames()-1 ) {
1109bHasPosKey = true; bHasScaleKey = true; bHasRotKey = true;
1110}
1111
1112// check if there are no keys, if not, then force add some keys for proper animation //
1113if( posXKeys.size() == 0 || posYKeys.size() == 0 || posZKeys.size() == 0 ) {
1114bHasPosKey = true;
1115}
1116
1117if( scaleXKeys.size() == 0 || scaleYKeys.size() == 0 || scaleZKeys.size() == 0 ) {
1118bHasScaleKey = true;
1119}
1120
1121if( rotXKeys.size() == 0 || rotYKeys.size() == 0 || rotZKeys.size() == 0 ) {
1122bHasRotKey=true;
1123}
1124
1125
1126// check position //
1127if( !bHasPosKey && requiresKeyForTime(posXKeys, cmillis, nmillis )) bHasPosKey=true;
1128if( !bHasPosKey && requiresKeyForTime(posYKeys, cmillis, nmillis )) bHasPosKey=true;
1129if( !bHasPosKey && requiresKeyForTime(posZKeys, cmillis, nmillis )) bHasPosKey=true;
1130
1131// check scale //
1132if( !bHasScaleKey && requiresKeyForTime(scaleXKeys, cmillis, nmillis )) bHasScaleKey=true;
1133if( !bHasScaleKey && requiresKeyForTime(scaleYKeys, cmillis, nmillis )) bHasScaleKey=true;
1134if( !bHasScaleKey && requiresKeyForTime(scaleZKeys, cmillis, nmillis )) bHasScaleKey=true;
1135
1136// check rotation //
1137if( !bHasRotKey && requiresKeyForTime(rotXKeys, cmillis, nmillis )) bHasRotKey=true;
1138if( !bHasRotKey && requiresKeyForTime(rotYKeys, cmillis, nmillis )) bHasRotKey=true;
1139if( !bHasRotKey && requiresKeyForTime(rotZKeys, cmillis, nmillis )) bHasRotKey=true;
1140
1141// cout << pNode->GetName() << " : " << i << " - " << bHasScaleKey << endl;
1142
1143glm::vec3 tpos, tscale;
1144glm::quat tquat;
1145//fbxToGlmComponents(FbxAMatrix& ainput, glm::vec3& apos, glm::quat& aquat, glm::vec3& ascale)
1146
1147// if( pNode->GetParent() ) {
1148if( bHasPosKey || bHasScaleKey || bHasRotKey ) {
1149
1150if( !bGrabGlobalTransform ) {
1151//setTransformMatrix( ofGetLocalTransform( fbxNode, pTime, pPose, NULL ));
1152FbxAMatrix& tmatrix = pNode->EvaluateLocalTransform( tanim.fbxCurrentTime );
1153//tmat = ( fbxToOf(tmatrix) );
1154fbxToGlmComponents(tmatrix, tpos, tquat, tscale);
1155} else {
1156FbxAMatrix& tmatrix = pNode->EvaluateGlobalTransform( tanim.fbxCurrentTime );
1157// tmat = ( fbxToOf(tmatrix) );
1158fbxToGlmComponents(tmatrix, tpos, tquat, tscale);
1159}
1160
1161if( bHasPosKey ) {
1162ofxFBXSource::AnimKey<float> tkeyPosX;
1163tkeyPosX.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1164tkeyPosX.value = tpos.x;
1165kcollection.posKeysX.push_back( tkeyPosX );
1166ofxFBXSource::AnimKey<float> tkeyPosY;
1167tkeyPosY.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1168tkeyPosY.value = tpos.y;
1169kcollection.posKeysY.push_back( tkeyPosY );
1170ofxFBXSource::AnimKey<float> tkeyPosZ;
1171tkeyPosZ.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1172tkeyPosZ.value = tpos.z;
1173kcollection.posKeysZ.push_back( tkeyPosZ );
1174
1175numPosKeys++;
1176}
1177
1178if( bHasScaleKey ) {
1179ofxFBXSource::AnimKey<float> tkeyScaleX;
1180tkeyScaleX.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1181tkeyScaleX.value = tscale.x;
1182kcollection.scaleKeysX.push_back( tkeyScaleX );
1183ofxFBXSource::AnimKey<float> tkeyScaleY;
1184tkeyScaleY.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1185tkeyScaleY.value = tscale.y;
1186kcollection.scaleKeysY.push_back( tkeyScaleY );
1187ofxFBXSource::AnimKey<float> tkeyScaleZ;
1188tkeyScaleZ.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1189tkeyScaleZ.value = tscale.z;
1190kcollection.scaleKeysZ.push_back( tkeyScaleZ );
1191
1192numScaleKeys++;
1193}
1194
1195if( bHasRotKey ) {
1196ofxFBXSource::AnimKey<ofQuaternion> tRotKey;
1197tRotKey.millis = tanim.fbxCurrentTime.GetMilliSeconds();
1198tRotKey.value = tquat;
1199kcollection.rotKeys.push_back( tRotKey );
1200
1201numRotKeys++;
1202}
1203
1204}
1205
1206}
1207
1208ofLogVerbose("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 //
1306const int lChildCount = pNode->GetChildCount();
1307for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) {
1308populateKeyFrames( pNode->GetChild(lChildIndex), aAnimIndex );
1309}
1310}
1311
1312//--------------------------------------------------------------
1313vector< ofxFBXSource::AnimKey<float> > Scene::getFloatKeys( FbxAnimCurve* pCurve ) {
1314vector< ofxFBXSource::AnimKey<float> > tkeys;
1315
1316FbxTime lKeyTime;
1317float lKeyValue;
1318int lKeyCount, lCount;
1319
1320if( pCurve ) {
1321lKeyCount = pCurve->KeyGetCount();
1322for(lCount = 0; lCount < lKeyCount; lCount++) {
1323lKeyValue = static_cast<float>(pCurve->KeyGetValue(lCount));
1324lKeyTime = pCurve->KeyGetTime(lCount);
1325ofxFBXSource::AnimKey<float> tkey;
1326tkey.value = lKeyValue;
1327tkey.millis = lKeyTime.GetMilliSeconds();
1328tkeys.push_back( tkey );
1329}
1330}
1331
1332return tkeys;
1333}
1334
1335//--------------------------------------------------------------
1336bool Scene::requiresKeyForTime( vector< ofxFBXSource::AnimKey<float> >& tkeys, signed long amillis1, signed long amillis2 ) {
1337for( int i = 0; i < tkeys.size(); i++ ) {
1338if(tkeys[i].millis >= amillis1 && tkeys[i].millis < amillis2 ) {
1339return true;
1340}
1341}
1342return false;
1343}
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358