framework2
933 строки · 30.1 Кб
1//
2// ofxFBXManager.cpp
3// ScenesSetup_Nick
4//
5// Created by Nick Hardeman on 12/20/13.
6//
7//
8
9#include "ofxFBX.h"
10
11ofxFBXAnimation dummyAnimation;
12
13vector< shared_ptr<ofxFBXSource::Scene> > ofxFBX::mCachedScenes;
14
15//--------------------------------------------------------------
16ofxFBX::ofxFBX() {
17bAnimationsEnabled = true;
18animationIndex = 0;
19dummyAnimation.name = "dummy";
20poseIndex = 0;
21bPosesEnabled = false;
22currentAnimationStack = NULL;
23}
24
25//--------------------------------------------------------------
26ofxFBX::~ofxFBX() {
27clear();
28// for( int i = 0; i < mSkeletons.size(); i++ ) {
29// mSkeletons[i]->clearParent();
30//// skeletons[i]->root.clearParent();
31// }
32// mSkeletons.clear();
33//
34// if( mSceneInternal ) {
35// if( fbxScene != NULL && fbxScene->getSettings().unloadIfUnused ) {
36// mSceneInternal.reset();
37// ofRemove( mCachedScenes, shouldRemoveScene );
38//
39// ofLogVerbose("~ofxFBXManager :: mCachedScenes : size(): ") << mCachedScenes.size();
40// }
41// }
42}
43
44//--------------------------------------------------------------
45bool ofxFBX::shouldRemoveScene( const shared_ptr<ofxFBXSource::Scene>& ascene ) {
46return (!ascene || ascene.use_count() <= 1); // only stored in the cache //
47}
48
49//--------------------------------------------------------------
50bool ofxFBX::load(ofxFBXSource::Scene::Settings aSettings ) {
51return load( aSettings.filePath, aSettings );
52}
53
54//--------------------------------------------------------------
55void ofxFBX::clear() {
56for( auto node : mAllNodes ) {
57node->clearParent();
58}
59
60mSkeletons.clear();
61poses.clear();
62meshes.clear();
63mNurbsCurves.clear();
64mNullNodes.clear();
65animations.clear();
66mRootNodes.clear();
67mAllNodes.clear();
68
69// for( int i = 0; i < mSkeletons.size(); i++ ) {
70// mSkeletons[i]->clearParent();
71//// skeletons[i]->root.clearParent();
72// }
73// mSkeletons.clear();
74
75if( mSceneInternal ) {
76if( fbxScene != NULL && fbxScene->getSettings().unloadIfUnused ) {
77mSceneInternal.reset();
78ofRemove( mCachedScenes, shouldRemoveScene );
79ofLogVerbose("~ofxFBXManager :: mCachedScenes : size(): ") << mCachedScenes.size();
80}
81}
82}
83
84//--------------------------------------------------------------
85bool ofxFBX::load( string path, ofxFBXSource::Scene::Settings aSettings ) {
86
87if( !ofFile::doesFileExist(path)) {
88ofLogError("ofxFBX::load()") << " File does not exist!!: " << path << " :(";
89return false;
90}
91
92// check to see if we already have a scene cached //
93string fpath = ofToDataPath(path);
94if( mSceneInternal && mSceneInternal->getFbxFilePath() == fpath ) {
95ofLogNotice("ofxFBX::load() already have this scene loaded") << mSceneInternal->getFbxFilePath();
96return true;
97}
98
99// clean up the internal scene if it is present //
100clear();
101
102for( auto scene : mCachedScenes ) {
103if( scene->getFbxFilePath() == fpath ) {
104mSceneInternal = scene;
105break;
106}
107}
108if( !mSceneInternal ) {
109mSceneInternal = make_shared<ofxFBXSource::Scene>();
110if( mSceneInternal->load( path, aSettings )) {
111mCachedScenes.push_back( mSceneInternal );
112} else {
113mSceneInternal.reset();
114}
115}
116// for( int i = 0; i < mCachedScenes.size(); i++ ) {
117// cout << i << " - " << "ofxFBXManager :: load : " << mCachedScenes[i]->getFbxFilePath() << endl;
118// }
119
120
121if( mSceneInternal ) {
122setup( mSceneInternal.get() );
123return true;
124}
125
126return false;
127}
128
129//--------------------------------------------------------------
130void ofxFBX::setup( ofxFBXSource::Scene* aScene ) {
131fbxScene = aScene;
132if(fbxScene == NULL ) {
133ofLogError("ofxFBXManager::setup : ofxFBXScene is NULL, make sure set and load the ofxFBXScene!");
134return;
135}
136if(fbxScene->getFBXScene() == NULL) {
137ofLogWarning("ofxFBXManager::setup : FbxScene is NULL, make sure to not unload the ofxFBXScene!");
138return;
139}
140
141// cout << "ofxFBX::setup : parsing ofxFBXSource :: " << fbxScene->getFbxFilePath() << endl;
142
143// clear out any existing data //
144mSkeletons.clear();
145poses.clear();
146meshes.clear();
147mNurbsCurves.clear();
148mNullNodes.clear();
149animations.clear();
150mRootNodes.clear();
151mAllNodes.clear();
152
153// see if we are using keyframes //
154bUsingKeyframes = fbxScene->getSettings().useKeyFrames;
155
156aScene->populateAnimations( animations );
157
158// we need to parse the nodes from the scene to preserve the hierarchy //
159vector< shared_ptr<ofxFBXSource::Node> > fsceneNodes = fbxScene->getSceneNodes();
160shared_ptr<ofxFBXNode> tempParentNode;
161for( auto snode : fsceneNodes ) {
162_parseSceneNodesRecursive( snode, tempParentNode );
163}
164
165for( auto& tskel : mSkeletons ) {
166tskel->setupRoot(tskel);
167}
168
169aScene->populatePoses( poses );
170
171// check the fbx scene if the mesh keyframes have been cached //
172if( aScene->getSettings().cacheMeshKeyframes ) {
173cacheMeshKeyframes( aScene->getSettings().blendCachedMeshKeyframes );
174}
175
176if( hasAnimations() ) {
177// set to the first animation
178setAnimation(0);
179}
180
181}
182
183//--------------------------------------------------------------
184void ofxFBX::_parseSceneNodesRecursive( shared_ptr<ofxFBXSource::Node> anode, shared_ptr<ofxFBXNode> aParentNode ) {
185if( !anode ) return;
186
187shared_ptr<ofxFBXNode> newNode;
188ofxFBXSource::Node::NodeType ftype = anode->getType();
189if (ftype == ofxFBXSource::Node::OFX_FBX_MESH) {
190auto tmesh = make_shared<ofxFBXMesh>();
191if( tmesh ) {
192meshes.push_back( tmesh );
193newNode = tmesh;
194}
195} else if(ftype == ofxFBXSource::Node::OFX_FBX_NURBS_CURVE) {
196auto tcurve = make_shared<ofxFBXNurbsCurve>();
197if( tcurve ) {
198mNurbsCurves.push_back(tcurve);
199newNode = tcurve;
200}
201} else if(ftype == ofxFBXSource::Node::OFX_FBX_NULL ) {
202auto tnull = make_shared<ofxFBXNode>();
203if( tnull ) {
204mNullNodes.push_back(tnull);
205newNode = tnull;
206}
207} else if( ftype == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
208auto tskel = make_shared<ofxFBXSkeleton>();
209if( tskel ) {
210mSkeletons.push_back( tskel );
211newNode = tskel;
212}
213}
214
215if( newNode ) {
216if( aParentNode ) {
217aParentNode->addChild( newNode );
218newNode->setParent( *aParentNode );
219newNode->setParentNode( aParentNode );
220} else {
221newNode->setParent( *this );
222mRootNodes.push_back( newNode );
223}
224newNode->setup( anode );
225mAllNodes.push_back( newNode );
226}
227
228for( int i = 0; i < anode->getNumChildren(); i++ ) {
229_parseSceneNodesRecursive( anode->getChildren()[i], newNode );
230}
231}
232
233//--------------------------------------------------------------
234void ofxFBX::earlyUpdate(float aElapsedSeconds) {
235FbxPose * lPose = NULL;
236// poses will override the animations and the settings of the bones //
237if( arePosesEnabled() && hasPoses() && (poseIndex >= 0 && poseIndex < getNumPoses() ) ) {
238cout << "Got a pose | " << ofGetFrameNum() << endl;
239lPose = fbxScene->getFBXScene()->GetPose( poseIndex );
240}
241
242if( !areAnimationsEnabled() || !hasAnimations() ) {
243if( bFirstRun ) {
244FbxTime ttime(FBXSDK_TIME_INFINITE);
245// cout << "Calling update bones: " << " | " << ofGetElapsedTimef() << endl;
246for( auto& node : mAllNodes ) {
247// if( node->getType() == ofxFBXSource::Node::OFX_FBX_SKELETON ) {
248node->update( ttime, lPose );
249node->update();
250// }
251}
252}
253
254}
255
256if(animations.size() < 1) return;
257if(!areAnimationsEnabled()) return;
258
259
260float etimef = aElapsedSeconds;//ofGetElapsedTimef();
261if (etimef < 0) {
262etimef = ofGetElapsedTimef();
263}
264// cout << "Should not be reaching here: ofxFBXManager :: update | " << ofGetFrameNum() << endl;
265
266animations[animationIndex].update(etimef);
267if( mAnimTrans.bActive ) {
268animations[mAnimTrans.animIndex2].update(etimef);
269}
270
271
272
273if( currentAnimationStack != NULL ) {
274fbxScene->getFBXScene()->SetCurrentAnimationStack( currentAnimationStack );
275}
276
277// cout << "ofxFBXManager :: update : animations | " << ofGetElapsedTimef() << endl;
278// TODO: is there a way to check if we need to update the bone positions? Right now it always updates.
279// If other fbxManagers are playing animations at different times or moving around bones, then it will get weird if it doesn't
280// update. //
281// if(animations[animationIndex].isFrameNew() || animations[animationIndex].isPaused() ) {
282signed long tFbxAnimTime = (signed long)animations[animationIndex].fbxCurrentTime.GetMilliSeconds();
283signed long tFbxAnimTime2 = 0;
284if( mAnimTrans.bActive ) {
285tFbxAnimTime2 = (signed long)animations[mAnimTrans.animIndex2].fbxCurrentTime.GetMilliSeconds();
286}
287
288for( auto& node : mAllNodes ) {
289if( bUsingKeyframes ) {
290if( mAnimTrans.bActive ) {
291node->update( mAnimTrans.animIndex1, tFbxAnimTime, mAnimTrans.animIndex2, tFbxAnimTime2, mAnimTrans.percent );
292} else {
293node->update( animationIndex, tFbxAnimTime );
294}
295} else {
296node->update( animations[animationIndex].fbxCurrentTime, lPose );
297}
298node->update();
299}
300
301if( mAnimTrans.bActive ) {
302// float etimef = aElapsedSeconds;//ofGetElapsedTimef();
303// if (etimef < 0) {
304// etimef = ofGetElapsedTimef();
305// }
306mAnimTrans.percent = (etimef - mAnimTrans.startTime) / mAnimTrans.duration;
307if( mAnimTrans.percent >= 1.f ) {
308mAnimTrans.percent = 1.0;
309animationIndex = mAnimTrans.animIndex2; // switch to the targeted animation
310mAnimTrans.bActive = false;
311}
312}
313}
314
315//--------------------------------------------------------------
316void ofxFBX::update(float aElapsedSeconds) {
317earlyUpdate(aElapsedSeconds);
318lateUpdate();
319}
320
321//--------------------------------------------------------------
322void ofxFBX::lateUpdate() {
323
324if( !areAnimationsEnabled() || !hasAnimations() ) {
325if( bFirstRun ) {
326FbxTime ttime(FBXSDK_TIME_INFINITE);
327for( auto& node : mAllNodes ) {
328node->lateUpdate(ttime, currentFbxAnimationLayer, NULL);
329}
330}
331}
332
333if(animations.size() > 0 && areAnimationsEnabled() ) {
334for( auto& node : mAllNodes ) {
335node->lateUpdate(animations[animationIndex].fbxCurrentTime, currentFbxAnimationLayer, NULL);
336}
337}
338
339if(!bUpdateMeshVbo) {
340// tell all of the meshes not to update the vbo //
341for( auto& m : meshes ) {
342m->setMeshDirty(false);
343}
344}
345
346bFirstRun = false;
347}
348
349#pragma mark - Draw
350//--------------------------------------------------------------
351void ofxFBX::draw() {
352drawMeshes();
353drawCurves();
354}
355
356//--------------------------------------------------------------
357void ofxFBX::drawMesh(int aindex) {
358if (aindex < 0 || aindex >= meshes.size()) {
359return;
360}
361meshes[aindex]->draw();
362}
363
364//--------------------------------------------------------------
365void ofxFBX::drawMeshWireframe(int aindex) {
366if (aindex < 0 || aindex >= meshes.size()) {
367return;
368}
369meshes[aindex]->drawWireframe();
370}
371
372//--------------------------------------------------------------
373void ofxFBX::drawMeshes() {
374for( auto& tmesh : meshes ) {
375tmesh->draw();
376}
377}
378
379//--------------------------------------------------------------
380void ofxFBX::drawMeshWireframes() {
381for( auto& tmesh : meshes ) {
382tmesh->drawWireframe();
383}
384}
385
386//--------------------------------------------------------------
387void ofxFBX::drawMeshNormals( float aLen, bool aBFaceNormals ) {
388for( auto& tmesh : meshes ) {
389tmesh->drawNormals(aLen, aBFaceNormals);
390}
391}
392
393//--------------------------------------------------------------
394void ofxFBX::drawSkeletons( float aLen, bool aBDrawAxes ) {
395for(int i = 0; i < mSkeletons.size(); i++ ) {
396mSkeletons[i]->draw( aLen, aBDrawAxes );
397}
398}
399
400//--------------------------------------------------------------
401void ofxFBX::drawCurves() {
402for( auto& nc : mNurbsCurves ) {
403nc->draw();
404}
405}
406
407#pragma mark - Getters
408
409//--------------------------------------------------------------
410string ofxFBX::getInfoString() {
411stringstream ss;
412if(fbxScene) {
413ss << "ofxFBX :: " << ofFilePath::getBaseName(fbxScene->getFbxFilePath())<<"."<<ofFilePath::getFileExt(fbxScene->getFbxFilePath()) << endl;
414}
415for( auto& sn : mRootNodes ) {
416ss << sn->getAsString();
417}
418return ss.str();
419}
420
421//--------------------------------------------------------------
422ofxFBXSource::Scene* ofxFBX::getFbxScene() {
423return fbxScene;
424}
425
426//--------------------------------------------------------------
427string ofxFBX::getFbxFilePath() {
428if( fbxScene ) {
429return fbxScene->getFbxFilePath();
430}
431return "";
432}
433
434#pragma mark Null Nodes
435//--------------------------------------------------------------
436vector< shared_ptr<ofxFBXNode> >& ofxFBX::getNullNodes() {
437return mNullNodes;
438}
439
440//--------------------------------------------------------------
441int ofxFBX::getNumNullNodes() {
442return mNullNodes.size();
443}
444
445#pragma mark Meshes
446//--------------------------------------------------------------
447vector< shared_ptr<ofxFBXMesh> >& ofxFBX::getMeshes() {
448return meshes;
449}
450
451//--------------------------------------------------------------
452int ofxFBX::getNumMeshes() {
453return (int)meshes.size();
454}
455
456//--------------------------------------------------------------
457string ofxFBX::getMeshName( int aMeshIndex ) {
458return meshes[aMeshIndex]->getName();//fbxScene->getMeshes()[aMeshIndex]->getName();
459}
460
461//--------------------------------------------------------------
462void ofxFBX::setMaterialsEnabled( bool ab ) {
463for( auto mesh : meshes ) {
464mesh->setMaterialsEnabled( ab );
465}
466}
467
468//--------------------------------------------------------------
469vector< shared_ptr<ofxFBXSource::MeshTexture> > ofxFBX::getSourceTextures() {
470vector< shared_ptr<ofxFBXSource::MeshTexture> > rtexs;
471for( auto mesh : meshes ) {
472auto mats = mesh->getMaterials();
473for( auto mat : mats ) {
474if( mat->hasSourceTexture() ) {
475rtexs.push_back( mat->getSrcTexture() );
476}
477}
478}
479return rtexs;
480}
481
482//--------------------------------------------------------------
483int ofxFBX::getNumSourceTextures() {
484int tnum = 0;
485for( auto mesh : meshes ) {
486auto mats = mesh->getMaterials();
487for( auto mat : mats ) {
488if( mat->hasSourceTexture() ) {
489tnum++;
490}
491}
492}
493return tnum;
494}
495
496//--------------------------------------------------------------
497void ofxFBX::setMeshesDirty( bool ab ) {
498for( auto mesh : meshes ) {
499mesh->setMeshDirty( ab );
500}
501}
502
503//--------------------------------------------------------------
504void ofxFBX::cacheMeshKeyframes( bool aBlendMeshKeys ) {
505if( fbxScene == NULL ) return;
506
507if( !fbxScene->getSettings().useKeyFrames ) {
508ofLogWarning("ofxFBX :: cacheMeshKeyframes : must use .useKeyFrames when loading scene in Settings ");
509return;
510}
511
512// if( fbxScene->areMeshKeyframesCached() ) {
513// return;
514// }
515
516if( !fbxScene->areMeshKeyframesCached() ) {
517
518ofLogNotice(" ofxFBX :: cacheMeshKeyframes : ") << getFbxFilePath();
519
520// one mesh per keyframe per animation //
521for( int ia = 0; ia < animations.size(); ia++ ) {
522setAnimation(ia);
523auto& tanim = getCurrentAnimation();
524
525ofLogNotice( "ofxFBX :: cacheMeshKeyframes : animation: " ) << tanim.name << " num key frames: " << tanim.getTotalNumFrames();
526
527for( int i = 0; i < tanim.getTotalNumFrames(); i++ ) {
528tanim.setFrame(i);
529signed long tFbxAnimTime = (signed long)tanim.fbxCurrentTime.GetMilliSeconds();
530// update all the nodes //
531for( auto& node : mAllNodes ) {
532if( bUsingKeyframes ) {
533node->update( ia, tFbxAnimTime );
534} else {
535node->update( tanim.fbxCurrentTime, NULL );
536}
537node->update();
538}
539
540for( auto& node : mAllNodes ) {
541node->lateUpdate( tanim.fbxCurrentTime, currentFbxAnimationLayer, NULL );
542// now we need to cache the meshes in the meshes //
543if( node->getType() == ofxFBXSource::Node::OFX_FBX_MESH && node->getofxFbxSrcNode() ) {
544// now lets cache the mesh //
545shared_ptr<ofxFBXMesh> meshNode = dynamic_pointer_cast<ofxFBXMesh>(node);
546shared_ptr<ofxFBXSource::Mesh> tSrcMesh = dynamic_pointer_cast<ofxFBXSource::Mesh>(node->getofxFbxSrcNode());
547auto& kMeshKeyCollection = tSrcMesh->getMeshKeyCollection(ia);
548ofxFBXSource::MeshAnimKey meshKey;
549meshKey.mesh = meshNode->getMesh();
550meshKey.millis = tFbxAnimTime;
551kMeshKeyCollection.meshKeys.push_back( meshKey );
552}
553}
554}
555}
556}
557
558// disable all of the bones, since the meshes are cached, it will not be influenced by the bones anymore //
559for( auto& node : mAllNodes ) {
560if( node->getType() == ofxFBXSource::Node::OFX_FBX_BONE ) {
561auto bone = dynamic_pointer_cast<ofxFBXBone>(node);
562bone->disableAnimation( true );
563
564if(node->getofxFbxSrcNode()) {
565// now disable the source bones //
566auto sbone = dynamic_pointer_cast<ofxFBXSource::Bone>(node->getofxFbxSrcNode());
567if( sbone ) sbone->disableAnimation(true);
568}
569}
570}
571
572for( int i = 0; i < mSkeletons.size(); i++ ) {
573mSkeletons[i]->disableAnimation();
574if( mSkeletons[i]->getofxFbxSrcNode() ) {
575auto sskel = dynamic_pointer_cast<ofxFBXSource::Skeleton>(mSkeletons[i]->getofxFbxSrcNode());
576if( sskel->root ) {
577sskel->root->disableAnimation(true);
578}
579}
580
581}
582
583
584// let the source meshes know that they are cached //
585for( auto& node : mAllNodes ) {
586if( node->getType() == ofxFBXSource::Node::OFX_FBX_MESH && node->getofxFbxSrcNode() ) {
587auto mesh = dynamic_pointer_cast<ofxFBXMesh>(node);
588if( mesh ) {
589mesh->setBlendMeshFrames( aBlendMeshKeys );
590}
591auto tSrcMesh = dynamic_pointer_cast<ofxFBXSource::Mesh>(node->getofxFbxSrcNode());
592if(tSrcMesh) tSrcMesh->setUsingCachedMeshes(true);
593}
594}
595fbxScene->getSettings().cacheMeshKeyframes = true;
596fbxScene->setMeshKeyframesCached( true );
597}
598
599//--------------------------------------------------------------
600void ofxFBX::setMeshVboUpdate(bool ab) {
601bUpdateMeshVbo=ab;
602}
603
604#pragma mark Curves
605//--------------------------------------------------------------
606vector< shared_ptr<ofxFBXNurbsCurve> >& ofxFBX::getNurbsCurves() {
607return mNurbsCurves;
608}
609
610//--------------------------------------------------------------
611int ofxFBX::getNumNurbsCurves() {
612return mNurbsCurves.size();
613}
614
615#pragma mark Skeletons
616//--------------------------------------------------------------
617vector< shared_ptr<ofxFBXSkeleton> >& ofxFBX::getSkeletons() {
618return mSkeletons;
619}
620
621//--------------------------------------------------------------
622bool ofxFBX::hasBones() {
623return getNumBones() > 0;
624}
625
626//--------------------------------------------------------------
627int ofxFBX::getNumSkeletons() {
628return mSkeletons.size();
629}
630
631//--------------------------------------------------------------
632int ofxFBX::getNumBones() {
633int tNumBones = 0;
634for( int i = 0; i < mSkeletons.size(); i++ ) {
635tNumBones += mSkeletons[i]->getNumBones();
636}
637return tNumBones;
638}
639
640//--------------------------------------------------------------
641shared_ptr<ofxFBXBone> ofxFBX::getBone( string aBoneName, int aSkeletonIndex ) {
642if( aSkeletonIndex < 0 ) return NULL;
643if( aSkeletonIndex >= mSkeletons.size() ) return NULL;
644return mSkeletons[ aSkeletonIndex ]->getBone( aBoneName );
645}
646
647//--------------------------------------------------------------
648string ofxFBX::getSkeletonInfo() {
649string retStr = "";
650for( int i = 0; i < mSkeletons.size(); i++ ) {
651retStr += ofToString(i,0)+" - " + mSkeletons[i]->getAsString();
652}
653return retStr;
654}
655
656#pragma mark - Poses
657//--------------------------------------------------------------
658bool ofxFBX::hasPoses() {
659return getNumPoses() > 0;
660}
661
662//--------------------------------------------------------------
663bool ofxFBX::arePosesEnabled() {
664return bPosesEnabled;
665}
666
667//--------------------------------------------------------------
668void ofxFBX::enablePoses() {
669bPosesEnabled = true;
670}
671
672//--------------------------------------------------------------
673void ofxFBX::disablePoses() {
674bPosesEnabled = false;
675}
676
677//--------------------------------------------------------------
678void ofxFBX::togglePosesEnabled() {
679if( arePosesEnabled() ) disablePoses();
680else enablePoses();
681}
682
683//--------------------------------------------------------------
684int ofxFBX::getNumPoses() {
685return (int)poses.size();
686}
687
688//--------------------------------------------------------------
689void ofxFBX::setPoseIndex( int aIndex ) {
690aIndex = ofClamp( aIndex, 0, getNumPoses()-1 );
691poseIndex = aIndex;
692}
693
694//--------------------------------------------------------------
695shared_ptr< ofxFBXSource::Pose > ofxFBX::getCurrentPose() {
696if( hasPoses() && (poseIndex >= 0 && poseIndex < getNumPoses() ) ) {
697return poses[ poseIndex ];
698}
699shared_ptr<ofxFBXSource::Pose> tpose;
700return tpose;
701}
702
703//--------------------------------------------------------------
704vector< shared_ptr<ofxFBXSource::Pose> > ofxFBX::getPoses() {
705return poses;
706}
707
708#pragma mark - Animation
709//--------------------------------------------------------------
710int ofxFBX::getNumAnimations() {
711return animations.size();
712}
713
714//--------------------------------------------------------------
715int ofxFBX::getCurrentAnimationIndex() {
716return animationIndex;
717}
718
719//--------------------------------------------------------------
720ofxFBXAnimation& ofxFBX::getCurrentAnimation() {
721if(animations.size() < 1) {
722ofLogWarning("ofxFBXAnimation :: return dummy animation, there are no animations");
723return dummyAnimation;
724}
725return animations[ animationIndex ];
726}
727
728//--------------------------------------------------------------
729int ofxFBX::getAnimationIndex( string aname ) {
730int findex = -1;
731for( int i = 0; i < animations.size(); i++ ) {
732if( animations[i].name == aname ) {
733findex = i;
734break;
735}
736}
737return findex;
738}
739
740//--------------------------------------------------------------
741ofxFBXAnimation& ofxFBX::getAnimation( int aIndex ) {
742if( aIndex > animations.size() -1 ) {
743ofLogWarning( "ofxFBXManager :: getAnimation : index is too high " ) << aIndex;
744aIndex = ofClamp(aIndex, 0, animations.size()-1);
745}
746
747if( aIndex < 0 ) {
748ofLogWarning( "ofxFBXManager :: getAnimation : index is too low " ) << aIndex;
749return dummyAnimation;
750}
751
752if( animations.size() == 0 ) {
753aIndex = 0;
754animations.push_back( dummyAnimation );
755}
756
757return animations[ aIndex ];
758}
759
760//--------------------------------------------------------------
761ofxFBXAnimation& ofxFBX::getAnimation( string aname ) {
762return getAnimation( getAnimationIndex( aname ) );
763}
764
765//--------------------------------------------------------------
766bool ofxFBX::hasAnimation( string aname ) {
767return (getAnimationIndex(aname) > -1);
768}
769
770//--------------------------------------------------------------
771void ofxFBX::setAnimation( int aIndex ) {
772
773if( aIndex < 0) {
774ofLogWarning("ofxFBXManager :: setAnimation : returning because the index is less than 0!");
775return;
776}
777
778if(animations.size() < 1) {
779ofLogWarning("ofxFBXManager :: setAnimation : returning because there are no animations!");
780return;
781}
782if(aIndex >= animations.size()) {
783aIndex = ofClamp(aIndex, 0, animations.size()-1);
784ofLogWarning("ofxFBXManager :: setAnimation : index to high, clamping to ") << aIndex;
785}
786currentAnimationStack = fbxScene->getFBXScene()->FindMember<FbxAnimStack>( (&animations[aIndex].fbxname)->Buffer() );
787if (currentAnimationStack == NULL) {
788// this is a problem. The anim stack should be found in the scene!
789ofLogWarning("ofxFBXManager :: setAnimation : the anim stack was not found in the scene!");
790return;
791}
792// int numAnimLayers = lCurrentAnimationStack->GetMemberCount<FbxAnimLayer>();
793// cout << "Number of animation layers= " << numAnimLayers << endl;
794currentFbxAnimationLayer = currentAnimationStack->GetMember<FbxAnimLayer>();
795fbxScene->getFBXScene()->SetCurrentAnimationStack( currentAnimationStack );
796
797animationIndex = aIndex;
798}
799
800//--------------------------------------------------------------
801void ofxFBX::setAnimation( string aname ) {
802setAnimation( getAnimationIndex( aname ) );
803}
804
805//--------------------------------------------------------------
806void ofxFBX::enableAnimations() {
807if(!hasAnimations()) {
808ofLogWarning("ofxFBXManager :: enableAnimations : there are no animations in this scene. Disabling.");
809disableAnimations();
810return;
811}
812bAnimationsEnabled = true;
813for( int i = 0; i < mSkeletons.size(); i++ ) {
814mSkeletons[i]->enableAnimation();
815}
816}
817
818//--------------------------------------------------------------
819void ofxFBX::disableAnimations() {
820bAnimationsEnabled = false;
821for( int i = 0; i < mSkeletons.size(); i++ ) {
822mSkeletons[i]->disableAnimation();
823}
824bFirstRun=true;
825}
826
827//--------------------------------------------------------------
828void ofxFBX::toggleAnimationsEnabled() {
829if( bAnimationsEnabled ) {
830disableAnimations();
831} else {
832enableAnimations();
833}
834}
835
836//--------------------------------------------------------------
837bool ofxFBX::areAnimationsEnabled() {
838return (bAnimationsEnabled && hasAnimations());
839}
840
841//--------------------------------------------------------------
842bool ofxFBX::hasAnimations() {
843if( animations.size() > 1 ) return true;
844if( animations.size() == 1 ) {
845if( animations[0].name == "dummyAnimation" ) {
846return false;
847} else {
848return true;
849}
850}
851return false;
852}
853
854//--------------------------------------------------------------
855void ofxFBX::reloadAnimationsFromScene() {
856if( getFbxScene() ) {
857animations.clear();
858getFbxScene()->populateAnimations( animations );
859}
860}
861
862//--------------------------------------------------------------
863void ofxFBX::transition( int aAnimIndex1, int aNumIndex2, float aduration ) {
864if( !bUsingKeyframes ) {
865ofLogError("ofxFbxManager :: transition : not transitioning, must be using keyframes. Set ofxFBXSceneSettings.useKeyFrames to true when loading the fbx scene" );
866return;
867}
868if( !hasAnimations() ) {
869ofLogError("ofxFbxManager :: transition : not transitioning, no animations" );
870return;
871}
872if( !areAnimationsEnabled() ) {
873ofLogError("ofxFbxManager :: transition : not transitioning, animations disabled" );
874return;
875}
876if( aAnimIndex1 < 0 || aNumIndex2 < 0 || aAnimIndex1 >= getNumAnimations() || aNumIndex2 >= getNumAnimations() ) {
877ofLogError("ofxFbxManager :: transition : invalid index: " ) << aAnimIndex1 << " index2: " << aNumIndex2 << " num animations: " << getNumAnimations();
878return;
879}
880mAnimTrans.animIndex1 = aAnimIndex1;
881mAnimTrans.animIndex2 = aNumIndex2;
882mAnimTrans.duration = aduration;
883mAnimTrans.percent = 0.f;
884mAnimTrans.startTime = ofGetElapsedTimef();
885mAnimTrans.bActive = true;
886}
887
888//--------------------------------------------------------------
889void ofxFBX::transition( string aAnimName1, string aNumName2, float aduration ) {
890transition( getAnimationIndex( aAnimName1 ), getAnimationIndex( aNumName2 ), aduration );
891}
892
893//--------------------------------------------------------------
894void ofxFBX::transition( string aToAnimName, float aduration ) {
895transition( getCurrentAnimationIndex(), getAnimationIndex(aToAnimName), aduration );
896}
897
898//--------------------------------------------------------------
899void ofxFBX::transition( int aToAnimIndex, float aduration ) {
900transition( getCurrentAnimationIndex(), aToAnimIndex, aduration );
901}
902
903//--------------------------------------------------------------
904bool ofxFBX::isTransitioning() {
905return mAnimTrans.bActive;
906}
907
908//--------------------------------------------------------------
909float ofxFBX::getTransitionPercent() {
910return mAnimTrans.percent;
911}
912
913#pragma mark Hierarchy
914//--------------------------------------------------------------
915shared_ptr<ofxFBXNode> ofxFBX::getNodeForName( string aPath, bool bStrict) {
916shared_ptr<ofxFBXNode> temp;
917for( auto& sn : mRootNodes ) {
918temp = sn->getNodeforName( sn, aPath, bStrict );
919if( temp ) break;
920}
921return temp;
922}
923
924// Flattens out scene hierarchy //
925//--------------------------------------------------------------
926vector< shared_ptr<ofxFBXNode> > ofxFBX::getAllNodes() {
927return mAllNodes;
928}
929
930//--------------------------------------------------------------
931vector< shared_ptr<ofxFBXNode> > ofxFBX::getRootNodes() {
932return mRootNodes;
933}
934
935
936
937
938
939
940
941
942
943
944
945
946
947