/************************************************************************************** Copyright (C) 2009 - 2010 Autodesk, Inc. and/or its licensors. All Rights Reserved. The coded instructions, statements, computer programs, and/or related material (collectively the "Data") in these files contain unpublished information proprietary to Autodesk, Inc. and/or its licensors, which is protected by Canada and United States of America federal copyright law and by international treaties. The Data may not be disclosed or distributed to third parties, in whole or in part, without the prior written consent of Autodesk, Inc. ("Autodesk"). THE DATA IS PROVIDED "AS IS" AND WITHOUT WARRANTY. ALL WARRANTIES ARE EXPRESSLY EXCLUDED AND DISCLAIMED. AUTODESK MAKES NO WARRANTY OF ANY KIND WITH RESPECT TO THE DATA, EXPRESS, IMPLIED OR ARISING BY CUSTOM OR TRADE USAGE, AND DISCLAIMS ANY IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR USE. WITHOUT LIMITING THE FOREGOING, AUTODESK DOES NOT WARRANT THAT THE OPERATION OF THE DATA WILL BE UNINTERRUPTED OR ERROR FREE. IN NO EVENT SHALL AUTODESK, ITS AFFILIATES, PARENT COMPANIES, LICENSORS OR SUPPLIERS ("AUTODESK GROUP") BE LIABLE FOR ANY LOSSES, DAMAGES OR EXPENSES OF ANY KIND (INCLUDING WITHOUT LIMITATION PUNITIVE OR MULTIPLE DAMAGES OR OTHER SPECIAL, DIRECT, INDIRECT, EXEMPLARY, INCIDENTAL, LOSS OF PROFITS, REVENUE OR DATA, COST OF COVER OR CONSEQUENTIAL LOSSES OR DAMAGES OF ANY KIND), HOWEVER CAUSED, AND REGARDLESS OF THE THEORY OF LIABILITY, WHETHER DERIVED FROM CONTRACT, TORT (INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE), OR OTHERWISE, ARISING OUT OF OR RELATING TO THE DATA OR ITS USE OR ANY OTHER PERFORMANCE, WHETHER OR NOT AUTODESK HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS OR DAMAGE. **************************************************************************************/ // // Illustrates the use of animation stacks, layers, curvenodes and curves. // #include <fbxsdk.h> #include "../Common/Common.h" // Function prototypes. bool CreateScene(KFbxSdkManager* pSdkManager, KFbxScene* pScene); int main(int argc, char** argv) { KFbxSdkManager* lSdkManager = NULL; KFbxScene* lScene = NULL; bool lResult; // Prepare the FBX SDK. InitializeSdkObjects(lSdkManager, lScene); // Create the scene. lResult = CreateScene(lSdkManager, lScene); if(lResult == false) { printf("\n\nAn error occurred while creating the scene...\n"); DestroySdkObjects(lSdkManager); return 0; } // Destroy all objects created by the FBX SDK. DestroySdkObjects(lSdkManager); return 0; } bool CreateScene(KFbxSdkManager* pSdkManager, KFbxScene* pScene) { int i; KTime lTime; KFbxAnimCurveKey key; KFbxAnimCurve* lCurve = NULL; // Create one animation stack KFbxAnimStack* lAnimStack = KFbxAnimStack::Create(pScene, "Stack001"); // this stack animation range is limited from 0 to 1 second KFbxSet<KTime>(lAnimStack->LocalStop, KTIME_ONE_SECOND); KFbxSet<fbxString>(lAnimStack->Description, "This is the animation stack description field."); // all animation stacks need, at least, one layer. KFbxAnimLayer* lAnimLayer = KFbxAnimLayer::Create(pScene, "Base Layer"); // the AnimLayer object name is "Base Layer" lAnimStack->AddMember(lAnimLayer); // add the layer to the stack // Set and get the blend mode bypass of the layer bool val; lAnimLayer->SetBlendModeBypass(eMAX_TYPES, true); // set the bypass to all the datatypes. val = lAnimLayer->GetBlendModeBypass(eBOOL1); // val = true lAnimLayer->SetBlendModeBypass(eBOOL1, false); // overwrite just for the bool datatype. val = lAnimLayer->GetBlendModeBypass(eBOOL1); // val = false val = lAnimLayer->GetBlendModeBypass(eBYTE1); // val = true val = lAnimLayer->GetBlendModeBypass(eDATETIME); // val = true val = lAnimLayer->GetBlendModeBypass((EFbxType)-1); // invalid type, val = false val = lAnimLayer->GetBlendModeBypass((EFbxType)120); // invalid type (>MAX_TYPES), val = false // we want to animate the layer's weight property. KFbxAnimCurveNode* wcn = lAnimLayer->CreateCurveNode(lAnimLayer->Weight); if (wcn) { // the curve node from the Weight property already contains 1 channel (Weight). i = wcn->GetChannelsCount(); // i = 1 // Now, let's add a second channel to the animation node. Note that this code // is useless and has only been provided to show the usage of the AddChannel and // ResetChannels bool ret; ret = wcn->AddChannel<int>("MyAddedIntChannel", 99); // this call will succed i = wcn->GetChannelsCount(); // i = 2 ret = wcn->AddChannel<int>("MyAddedIntChannel", 10); // this call will fail, since the channel already exists. i = wcn->GetChannelsCount(); // i = 2 wcn->ResetChannels(); // remove any added channels i = wcn->GetChannelsCount(); // i = 1 } // get the Weight curve (and create it if it does not exist, wich is the case!) lCurve = lAnimLayer->Weight.GetCurve<KFbxAnimCurve>(lAnimLayer, true); if (lCurve) { // add two keys at time 0 sec and 1 sec with values 0 and 100 respectively. for (i = 0; i < 2; i++) { lTime.SetSecondDouble((float)i); key.Set(lTime, i*100.0f); lCurve->KeyAdd(lTime, key); } } // // now create a 3 components curvenode and animate two of the three channels. // // first, we need a "dummy" property so we can call the CreateTypedCurveNode KFbxProperty p = KFbxProperty::Create(pScene, DTDouble3, "Vector3Property"); KFbxSet<fbxDouble3>(p, fbxDouble3(1.1, 2.2, 3.3)); KFbxAnimCurveNode* lCurveNode = KFbxAnimCurveNode::CreateTypedCurveNode(p, pScene); // let's make sure the curveNode is added to the animation layer. lAnimLayer->AddMember(lCurveNode); // and to the "Vector3Property" since CreateTypedCurveNode does not make any connection p.ConnectSrcObject(lCurveNode); double v1 = lCurveNode->GetChannelValue<double>(0U, 0.0); // v1 = 1.1 float v2 = lCurveNode->GetChannelValue<float> (1U, 0.0f); // v2 = 2.2 int v3 = lCurveNode->GetChannelValue<int> (2U, 0); // v3 = 3 // // create two free curves (not connected to anything) // // first curve lCurve = KFbxAnimCurve::Create(pScene, "curve1"); if (lCurve) { // add two keys at time 0 sec and 1 sec with values 0 and 10 respectively. for (i = 0; i < 2; i++) { lTime.SetSecondDouble((float)i); key.Set(lTime, i*10.0f); lCurve->KeyAdd(lTime, key); } } // connect it to the second channel lCurveNode->ConnectToChannel(lCurve, 1); // second curve lCurve = KFbxAnimCurve::Create(pScene, "curve2"); if (lCurve) { // add three keys for (i = 1; i < 4; i++) { lTime.SetSecondDouble((float)i); key.Set(lTime, i*3.33f); lCurve->KeyAdd(lTime, key); } } // connect it to the third channel lCurveNode->ConnectToChannel(lCurve, "Z"); // for backward compatibility, string identifier are still // allowed for the X,Y,Z and W components or "0", "1", ... "9", "A", "B", ... "F" for the Matrix44 datatype // ====================================================================== // // Add a second animation layer and evaluate using the KFbxAnimEvaluator // // ====================================================================== lAnimLayer = KFbxAnimLayer::Create(pScene, "Layer2"); lAnimStack->AddMember(lAnimLayer); // get the number of animation layers in the stack int nbLayers = lAnimStack->GetMemberCount(FBX_TYPE(KFbxAnimLayer)); // nblayers = 2 lAnimLayer = lAnimStack->GetMember(FBX_TYPE(KFbxAnimLayer), 1); // get the second layer // set its blend mode to Additive lAnimLayer->BlendMode.Set(KFbxAnimLayer::eBlendModeAdditive); // Now, let's animate the firrt channel of the "Vector3Property" (remember, we animated the second and // third on the base layer) // but firs, make sure the property is animatable otherwise the creation of the curveNode is prohibited. p.ModifyFlag(KFbxProperty::eANIMATABLE, true); lCurveNode = p.GetCurveNode(lAnimLayer, true); // create it since it does not exist yet // use "curve2" to animate it lCurveNode->ConnectToChannel(lCurve, 0U); // and set the other two channels values lCurveNode->SetChannelValue<double>(1U, 5.0); lCurveNode->SetChannelValue<double>(2U, 0.0); // evaluate the "Vector3Property" value at three different times // with the use of the KFbxAnimEvaluator so we take into account the two layers // make sure the evaluator is using the correct context (context == animstack) pScene->GetEvaluator()->SetContext(lAnimStack); for (i = 0; i < 3; i++) { lTime.SetSecondDouble((float)i*0.33f); KFbxAnimCurveNode& val = pScene->GetEvaluator()->GetPropertyValue(p, lTime); double v[3]; v[0] = val.GetChannelValue<double>(0U, 0.0); v[1] = val.GetChannelValue<double>(1U, 0.0); v[2] = val.GetChannelValue<double>(2U, 0.0); } /* the evaluated values for v at 0, .333 and .999 seconds are: time | 0.0 | 0.33 | 0.99 | val +-------------+----------------+--------------| 0 | 3.33 | 3.69 | 4.05 | 1 | 5.0 | 6.08 | 9.35 | 2 | 0.0 | 1.098 | 2.19 | +-------------+----------------+--------------| */ return true; }