FBX C++ API Reference
ImportScene/DisplayAnimation.cxx
/****************************************************************************************
Copyright (C) 2017 Autodesk, Inc.
All rights reserved.
Use of this software is subject to the terms of the Autodesk license agreement
provided at the time of installation or download, or which otherwise accompanies
this software in either electronic or hard copy form.
****************************************************************************************/
#include "DisplayCommon.h"
#include "DisplayAnimation.h"
#if defined (FBXSDK_ENV_MAC)
// disable the �format not a string literal and no format arguments� warning since
// the FBXSDK_printf calls made here are all valid calls and there is no secuity risk
#pragma GCC diagnostic ignored "-Wformat-security"
#endif
void DisplayAnimation(FbxAnimStack* pAnimStack, FbxNode* pNode, bool isSwitcher = false);
void DisplayAnimation(FbxAnimLayer* pAnimLayer, FbxNode* pNode, bool isSwitcher = false);
void DisplayAnimation(FbxAudioLayer* pAudioLayer, bool isSwitcher = false);
void DisplayChannels(FbxNode* pNode, FbxAnimLayer* pAnimLayer, void (*DisplayCurve) (FbxAnimCurve* pCurve), void (*DisplayListCurve) (FbxAnimCurve* pCurve, FbxProperty* pProperty), bool isSwitcher);
void DisplayCurveKeys(FbxAnimCurve* pCurve);
void DisplayListCurveKeys(FbxAnimCurve* pCurve, FbxProperty* pProperty);
void DisplayAnimation(FbxScene* pScene)
{
int i;
for (i = 0; i < pScene->GetSrcObjectCount<FbxAnimStack>(); i++)
{
FbxAnimStack* lAnimStack = pScene->GetSrcObject<FbxAnimStack>(i);
FbxString lOutputString = "Animation Stack Name: ";
lOutputString += lAnimStack->GetName();
lOutputString += "\n";
FBXSDK_printf(lOutputString);
DisplayAnimation(lAnimStack, pScene->GetRootNode());
}
}
void DisplayAnimation(FbxAnimStack* pAnimStack, FbxNode* pNode, bool isSwitcher)
{
int l;
int nbAnimLayers = pAnimStack->GetMemberCount<FbxAnimLayer>();
int nbAudioLayers = pAnimStack->GetMemberCount<FbxAudioLayer>();
FbxString lOutputString;
lOutputString = " contains ";
if (nbAnimLayers==0 && nbAudioLayers==0)
lOutputString += "no layers";
if (nbAnimLayers)
{
lOutputString += nbAnimLayers;
lOutputString += " Animation Layer";
if (nbAnimLayers > 1)
lOutputString += "s";
}
if (nbAudioLayers)
{
if (nbAnimLayers)
lOutputString += " and ";
lOutputString += nbAudioLayers;
lOutputString += " Audio Layer";
if (nbAudioLayers > 1)
lOutputString += "s";
}
lOutputString += "\n\n";
FBXSDK_printf(lOutputString);
for (l = 0; l < nbAnimLayers; l++)
{
FbxAnimLayer* lAnimLayer = pAnimStack->GetMember<FbxAnimLayer>(l);
lOutputString = "AnimLayer ";
lOutputString += l;
lOutputString += "\n";
FBXSDK_printf(lOutputString);
DisplayAnimation(lAnimLayer, pNode, isSwitcher);
}
for (l = 0; l < nbAudioLayers; l++)
{
FbxAudioLayer* lAudioLayer = pAnimStack->GetMember<FbxAudioLayer>(l);
lOutputString = "AudioLayer ";
lOutputString += l;
lOutputString += "\n";
FBXSDK_printf(lOutputString);
DisplayAnimation(lAudioLayer, isSwitcher);
FBXSDK_printf("\n");
}
}
void DisplayAnimation(FbxAudioLayer* pAudioLayer, bool )
{
int lClipCount;
FbxString lOutputString;
lClipCount = pAudioLayer->GetMemberCount<FbxAudio>();
lOutputString = " Name: ";
lOutputString += pAudioLayer->GetName();
lOutputString += "\n\n";
lOutputString += " Nb Audio Clips: ";
lOutputString += lClipCount;
lOutputString += "\n";
FBXSDK_printf(lOutputString);
for (int i = 0; i < lClipCount; i++)
{
FbxAudio* lClip = pAudioLayer->GetMember<FbxAudio>(i);
lOutputString = " Clip[";
lOutputString += i;
lOutputString += "]:\t";
lOutputString += lClip->GetName();
lOutputString += "\n";
FBXSDK_printf(lOutputString);
}
}
void DisplayAnimation(FbxAnimLayer* pAnimLayer, FbxNode* pNode, bool isSwitcher)
{
int lModelCount;
FbxString lOutputString;
lOutputString = " Node Name: ";
lOutputString += pNode->GetName();
lOutputString += "\n\n";
FBXSDK_printf(lOutputString);
DisplayChannels(pNode, pAnimLayer, DisplayCurveKeys, DisplayListCurveKeys, isSwitcher);
FBXSDK_printf ("\n");
for(lModelCount = 0; lModelCount < pNode->GetChildCount(); lModelCount++)
{
DisplayAnimation(pAnimLayer, pNode->GetChild(lModelCount), isSwitcher);
}
}
void DisplayChannels(FbxNode* pNode, FbxAnimLayer* pAnimLayer, void (*DisplayCurve) (FbxAnimCurve* pCurve), void (*DisplayListCurve) (FbxAnimCurve* pCurve, FbxProperty* pProperty), bool isSwitcher)
{
FbxAnimCurve* lAnimCurve = NULL;
// Display general curves.
if (!isSwitcher)
{
lAnimCurve = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X);
if (lAnimCurve)
{
FBXSDK_printf(" TX\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y);
if (lAnimCurve)
{
FBXSDK_printf(" TY\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z);
if (lAnimCurve)
{
FBXSDK_printf(" TZ\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = pNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X);
if (lAnimCurve)
{
FBXSDK_printf(" RX\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = pNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y);
if (lAnimCurve)
{
FBXSDK_printf(" RY\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = pNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z);
if (lAnimCurve)
{
FBXSDK_printf(" RZ\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = pNode->LclScaling.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X);
if (lAnimCurve)
{
FBXSDK_printf(" SX\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = pNode->LclScaling.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y);
if (lAnimCurve)
{
FBXSDK_printf(" SY\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = pNode->LclScaling.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z);
if (lAnimCurve)
{
FBXSDK_printf(" SZ\n");
DisplayCurve(lAnimCurve);
}
}
// Display curves specific to a light or marker.
FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute();
if (lNodeAttribute)
{
lAnimCurve = lNodeAttribute->Color.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COLOR_RED);
if (lAnimCurve)
{
FBXSDK_printf(" Red\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = lNodeAttribute->Color.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COLOR_GREEN);
if (lAnimCurve)
{
FBXSDK_printf(" Green\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = lNodeAttribute->Color.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COLOR_BLUE);
if (lAnimCurve)
{
FBXSDK_printf(" Blue\n");
DisplayCurve(lAnimCurve);
}
// Display curves specific to a light.
FbxLight* light = pNode->GetLight();
if (light)
{
lAnimCurve = light->Intensity.GetCurve(pAnimLayer);
if (lAnimCurve)
{
FBXSDK_printf(" Intensity\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = light->OuterAngle.GetCurve(pAnimLayer);
if (lAnimCurve)
{
FBXSDK_printf(" Outer Angle\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = light->Fog.GetCurve(pAnimLayer);
if (lAnimCurve)
{
FBXSDK_printf(" Fog\n");
DisplayCurve(lAnimCurve);
}
}
// Display curves specific to a camera.
FbxCamera* camera = pNode->GetCamera();
if (camera)
{
lAnimCurve = camera->FieldOfView.GetCurve(pAnimLayer);
if (lAnimCurve)
{
FBXSDK_printf(" Field of View\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = camera->FieldOfViewX.GetCurve(pAnimLayer);
if (lAnimCurve)
{
FBXSDK_printf(" Field of View X\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = camera->FieldOfViewY.GetCurve(pAnimLayer);
if (lAnimCurve)
{
FBXSDK_printf(" Field of View Y\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = camera->OpticalCenterX.GetCurve(pAnimLayer);
if (lAnimCurve)
{
FBXSDK_printf(" Optical Center X\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = camera->OpticalCenterY.GetCurve(pAnimLayer);
if(lAnimCurve)
{
FBXSDK_printf(" Optical Center Y\n");
DisplayCurve(lAnimCurve);
}
lAnimCurve = camera->Roll.GetCurve(pAnimLayer);
if(lAnimCurve)
{
FBXSDK_printf(" Roll\n");
DisplayCurve(lAnimCurve);
}
}
// Display curves specific to a geometry.
if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh ||
{
FbxGeometry* lGeometry = (FbxGeometry*) lNodeAttribute;
int lBlendShapeDeformerCount = lGeometry->GetDeformerCount(FbxDeformer::eBlendShape);
for(int lBlendShapeIndex = 0; lBlendShapeIndex<lBlendShapeDeformerCount; ++lBlendShapeIndex)
{
FbxBlendShape* lBlendShape = (FbxBlendShape*)lGeometry->GetDeformer(lBlendShapeIndex, FbxDeformer::eBlendShape);
int lBlendShapeChannelCount = lBlendShape->GetBlendShapeChannelCount();
for(int lChannelIndex = 0; lChannelIndex<lBlendShapeChannelCount; ++lChannelIndex)
{
FbxBlendShapeChannel* lChannel = lBlendShape->GetBlendShapeChannel(lChannelIndex);
const char* lChannelName = lChannel->GetName();
lAnimCurve = lGeometry->GetShapeChannel(lBlendShapeIndex, lChannelIndex, pAnimLayer, true);
if(lAnimCurve)
{
FBXSDK_printf(" Shape %s\n", lChannelName);
DisplayCurve(lAnimCurve);
}
}
}
}
}
// Display curves specific to properties
FbxProperty lProperty = pNode->GetFirstProperty();
while (lProperty.IsValid())
{
{
FbxString lFbxFCurveNodeName = lProperty.GetName();
FbxAnimCurveNode* lCurveNode = lProperty.GetCurveNode(pAnimLayer);
if (!lCurveNode){
lProperty = pNode->GetNextProperty(lProperty);
continue;
}
FbxDataType lDataType = lProperty.GetPropertyDataType();
if (lDataType.GetType() == eFbxBool || lDataType.GetType() == eFbxDouble || lDataType.GetType() == eFbxFloat || lDataType.GetType() == eFbxInt)
{
FbxString lMessage;
lMessage = " Property ";
lMessage += lProperty.GetName();
if (lProperty.GetLabel().GetLen() > 0)
{
lMessage += " (Label: ";
lMessage += lProperty.GetLabel();
lMessage += ")";
};
DisplayString(lMessage.Buffer());
for( int c = 0; c < lCurveNode->GetCurveCount(0U); c++ )
{
lAnimCurve = lCurveNode->GetCurve(0U, c);
if (lAnimCurve)
DisplayCurve(lAnimCurve);
}
}
else if(lDataType.GetType() == eFbxDouble3 || lDataType.GetType() == eFbxDouble4 || lDataType.Is(FbxColor3DT) || lDataType.Is(FbxColor4DT))
{
char* lComponentName1 = (lDataType.Is(FbxColor3DT) ||lDataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_RED : (char*)"X";
char* lComponentName2 = (lDataType.Is(FbxColor3DT) ||lDataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_GREEN : (char*)"Y";
char* lComponentName3 = (lDataType.Is(FbxColor3DT) ||lDataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_BLUE : (char*)"Z";
FbxString lMessage;
lMessage = " Property ";
lMessage += lProperty.GetName();
if (lProperty.GetLabel().GetLen() > 0)
{
lMessage += " (Label: ";
lMessage += lProperty.GetLabel();
lMessage += ")";
}
DisplayString(lMessage.Buffer());
for( int c = 0; c < lCurveNode->GetCurveCount(0U); c++ )
{
lAnimCurve = lCurveNode->GetCurve(0U, c);
if (lAnimCurve)
{
DisplayString(" Component ", lComponentName1);
DisplayCurve(lAnimCurve);
}
}
for( int c = 0; c < lCurveNode->GetCurveCount(1U); c++ )
{
lAnimCurve = lCurveNode->GetCurve(1U, c);
if (lAnimCurve)
{
DisplayString(" Component ", lComponentName2);
DisplayCurve(lAnimCurve);
}
}
for( int c = 0; c < lCurveNode->GetCurveCount(2U); c++ )
{
lAnimCurve = lCurveNode->GetCurve(2U, c);
if (lAnimCurve)
{
DisplayString(" Component ", lComponentName3);
DisplayCurve(lAnimCurve);
}
}
}
else if (lDataType.GetType() == eFbxEnum)
{
FbxString lMessage;
lMessage = " Property ";
lMessage += lProperty.GetName();
if (lProperty.GetLabel().GetLen() > 0)
{
lMessage += " (Label: ";
lMessage += lProperty.GetLabel();
lMessage += ")";
};
DisplayString(lMessage.Buffer());
for( int c = 0; c < lCurveNode->GetCurveCount(0U); c++ )
{
lAnimCurve = lCurveNode->GetCurve(0U, c);
if (lAnimCurve)
DisplayListCurve(lAnimCurve, &lProperty);
}
}
}
lProperty = pNode->GetNextProperty(lProperty);
} // while
}
static int InterpolationFlagToIndex(int flags)
{
if( (flags & FbxAnimCurveDef::eInterpolationConstant) == FbxAnimCurveDef::eInterpolationConstant ) return 1;
if( (flags & FbxAnimCurveDef::eInterpolationLinear) == FbxAnimCurveDef::eInterpolationLinear ) return 2;
if( (flags & FbxAnimCurveDef::eInterpolationCubic) == FbxAnimCurveDef::eInterpolationCubic ) return 3;
return 0;
}
static int ConstantmodeFlagToIndex(int flags)
{
if( (flags & FbxAnimCurveDef::eConstantStandard) == FbxAnimCurveDef::eConstantStandard ) return 1;
if( (flags & FbxAnimCurveDef::eConstantNext) == FbxAnimCurveDef::eConstantNext ) return 2;
return 0;
}
static int TangentmodeFlagToIndex(int flags)
{
if( (flags & FbxAnimCurveDef::eTangentAuto) == FbxAnimCurveDef::eTangentAuto ) return 1;
if( (flags & FbxAnimCurveDef::eTangentAutoBreak)== FbxAnimCurveDef::eTangentAutoBreak ) return 2;
if( (flags & FbxAnimCurveDef::eTangentTCB) == FbxAnimCurveDef::eTangentTCB ) return 3;
if( (flags & FbxAnimCurveDef::eTangentUser) == FbxAnimCurveDef::eTangentUser ) return 4;
if( (flags & FbxAnimCurveDef::eTangentGenericBreak) == FbxAnimCurveDef::eTangentGenericBreak ) return 5;
if( (flags & FbxAnimCurveDef::eTangentBreak) == FbxAnimCurveDef::eTangentBreak ) return 6;
return 0;
}
static int TangentweightFlagToIndex(int flags)
{
if( (flags & FbxAnimCurveDef::eWeightedNone) == FbxAnimCurveDef::eWeightedNone ) return 1;
if( (flags & FbxAnimCurveDef::eWeightedRight) == FbxAnimCurveDef::eWeightedRight ) return 2;
if( (flags & FbxAnimCurveDef::eWeightedNextLeft) == FbxAnimCurveDef::eWeightedNextLeft ) return 3;
return 0;
}
static int TangentVelocityFlagToIndex(int flags)
{
if( (flags & FbxAnimCurveDef::eVelocityNone) == FbxAnimCurveDef::eVelocityNone ) return 1;
if( (flags & FbxAnimCurveDef::eVelocityRight) == FbxAnimCurveDef::eVelocityRight ) return 2;
if( (flags & FbxAnimCurveDef::eVelocityNextLeft) == FbxAnimCurveDef::eVelocityNextLeft ) return 3;
return 0;
}
void DisplayCurveKeys(FbxAnimCurve* pCurve)
{
static const char* interpolation[] = { "?", "constant", "linear", "cubic"};
static const char* constantMode[] = { "?", "Standard", "Next" };
static const char* cubicMode[] = { "?", "Auto", "Auto break", "Tcb", "User", "Break", "User break" };
static const char* tangentWVMode[] = { "?", "None", "Right", "Next left" };
FbxTime lKeyTime;
float lKeyValue;
char lTimeString[256];
FbxString lOutputString;
int lCount;
int lKeyCount = pCurve->KeyGetCount();
for(lCount = 0; lCount < lKeyCount; lCount++)
{
lKeyValue = static_cast<float>(pCurve->KeyGetValue(lCount));
lKeyTime = pCurve->KeyGetTime(lCount);
lOutputString = " Key Time: ";
lOutputString += lKeyTime.GetTimeString(lTimeString, FbxUShort(256));
lOutputString += ".... Key Value: ";
lOutputString += lKeyValue;
lOutputString += " [ ";
lOutputString += interpolation[ InterpolationFlagToIndex(pCurve->KeyGetInterpolation(lCount)) ];
if ((pCurve->KeyGetInterpolation(lCount)&FbxAnimCurveDef::eInterpolationConstant) == FbxAnimCurveDef::eInterpolationConstant)
{
lOutputString += " | ";
lOutputString += constantMode[ ConstantmodeFlagToIndex(pCurve->KeyGetConstantMode(lCount)) ];
}
{
lOutputString += " | ";
lOutputString += cubicMode[ TangentmodeFlagToIndex(pCurve->KeyGetTangentMode(lCount)) ];
lOutputString += " | ";
lOutputString += tangentWVMode[ TangentweightFlagToIndex(pCurve->KeyGet(lCount).GetTangentWeightMode()) ];
lOutputString += " | ";
lOutputString += tangentWVMode[ TangentVelocityFlagToIndex(pCurve->KeyGet(lCount).GetTangentVelocityMode()) ];
}
lOutputString += " ]";
lOutputString += "\n";
FBXSDK_printf (lOutputString);
}
}
void DisplayListCurveKeys(FbxAnimCurve* pCurve, FbxProperty* pProperty)
{
FbxTime lKeyTime;
int lKeyValue;
char lTimeString[256];
FbxString lListValue;
FbxString lOutputString;
int lCount;
int lKeyCount = pCurve->KeyGetCount();
for(lCount = 0; lCount < lKeyCount; lCount++)
{
lKeyValue = static_cast<int>(pCurve->KeyGetValue(lCount));
lKeyTime = pCurve->KeyGetTime(lCount);
lOutputString = " Key Time: ";
lOutputString += lKeyTime.GetTimeString(lTimeString, FbxUShort(256));
lOutputString += ".... Key Value: ";
lOutputString += lKeyValue;
lOutputString += " (";
lOutputString += pProperty->GetEnumValue(lKeyValue);
lOutputString += ")";
lOutputString += "\n";
FBXSDK_printf (lOutputString);
}
}