#include <fbxsdk.h>
#include "../Common/Common.h"
#define SAMPLE_FILENAME "UserProperties.fbx"
#define ANIM_STACK_ANIMATE_LIST "Animate Cube List"
#define ANIM_STACK_ANIMATE_CUBE "Animate Cube"
#define ANIM_STACK_ANIMATE_PYRAMID "Animate Pyramid"
FbxNode* CreateCube(FbxScene* pScene, const char* pName);
FbxNode* CreatePyramid(FbxScene* pScene, const char* pName);
void CreateUserProperties(FbxNode *pNode);
void AnimateList(FbxScene* pScene, FbxProperty* pList);
FbxConstraintPosition* CreatePositionConstraint(FbxScene* pScene, FbxNode* pSourceNode, FbxNode* pConstrainedNode);
void AnimateCube(FbxScene* pScene, FbxNode* pNode);
void AnimatePyramid(FbxScene* pScene, FbxNode* pNode);
void AnimateNode(FbxNode* pNode, FbxAnimLayer* pAnimLayer);
int main(int argc, char** argv)
{
FbxManager* lSdkManager = NULL;
FbxScene* lScene = NULL;
bool lResult;
InitializeSdkObjects(lSdkManager, lScene);
FbxNode* lCube = CreateCube(lScene, "Cube");
FbxNode* lPyramid = CreatePyramid(lScene, "Pyramid");
FbxNode* lRootNode = lScene->GetRootNode();
lRootNode->AddChild(lCube);
lRootNode->AddChild(lPyramid);
CreateUserProperties(lCube);
FbxProperty p6 = lCube->FindProperty("MyList", false);
AnimateList(lScene, &p6);
FbxConstraintPosition* lPositionConstraint = (FbxConstraintPosition*)CreatePositionConstraint(lScene, lCube, lPyramid);
if( lPositionConstraint ) lPositionConstraint->ConnectDstObject(lScene);
AnimateCube(lScene, lCube);
AnimatePyramid(lScene, lPyramid);
const char* lSampleFileName = NULL;
for( int i = 1; i < argc; ++i )
{
if( FBXSDK_stricmp(argv[i], "-test") == 0 ) continue;
else if( !lSampleFileName ) lSampleFileName = argv[i];
}
if( !lSampleFileName ) lSampleFileName = SAMPLE_FILENAME;
lResult = SaveScene(lSdkManager, lScene, lSampleFileName, lSdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)") );
if(lResult == false)
{
FBXSDK_printf("\n\nAn error occurred while saving the scene...\n");
DestroySdkObjects(lSdkManager, lResult);
return 0;
}
DestroySdkObjects(lSdkManager, lResult);
return 0;
}
FbxNode* CreateCube(FbxScene* pScene, const char* pName)
{
typedef double Vector4[4];
typedef double Vector2[2];
static int vtxId[24] = {
0,1,2,3,
1,5,6,2,
5,4,7,6,
4,0,3,7,
0,4,5,1,
3,2,6,7
};
static Vector4 lControlPoints[8] = {
{ -50.0, 0.0, 50.0, 1.0}, { 50.0, 0.0, 50.0, 1.0}, { 50.0,100.0, 50.0, 1.0}, { -50.0,100.0, 50.0, 1.0},
{ -50.0, 0.0, -50.0, 1.0}, { 50.0, 0.0, -50.0, 1.0}, { 50.0,100.0, -50.0, 1.0}, { -50.0,100.0, -50.0, 1.0}
};
static Vector4 lNormals[8] = {
{-0.577350258827209,-0.577350258827209, 0.577350258827209, 1.0},
{ 0.577350258827209,-0.577350258827209, 0.577350258827209, 1.0},
{ 0.577350258827209, 0.577350258827209, 0.577350258827209, 1.0},
{-0.577350258827209, 0.577350258827209, 0.577350258827209, 1.0},
{-0.577350258827209,-0.577350258827209,-0.577350258827209, 1.0},
{ 0.577350258827209,-0.577350258827209,-0.577350258827209, 1.0},
{ 0.577350258827209, 0.577350258827209,-0.577350258827209, 1.0},
{-0.577350258827209, 0.577350258827209,-0.577350258827209, 1.0}
};
static Vector2 lUVs[14] = {
{ 0.0, 0.0},
{ 1.0, 0.0},
{ 0.0, 1.0},
{ 1.0, 1.0},
{ 0.0, 2.0},
{ 1.0, 2.0},
{ 0.0, 3.0},
{ 1.0, 3.0},
{ 0.0, 4.0},
{ 1.0, 4.0},
{ 2.0, 0.0},
{ 2.0, 1.0},
{-1.0, 0.0},
{-1.0, 1.0}
};
FbxMesh* lMesh = FbxMesh::Create(pScene,"");
lMesh->InitControlPoints(8);
FbxVector4* vertex = lMesh->GetControlPoints();
memcpy((void*)vertex, (void*)lControlPoints, 8*sizeof(FbxVector4));
int vId = 0;
for (int f=0; f<6; f++)
{
lMesh->BeginPolygon();
for (int v=0; v<4; v++)
lMesh->AddPolygon(vtxId[vId++]);
lMesh->EndPolygon();
}
FbxGeometryElementNormal* lNormlElement= lMesh->CreateElementNormal();
lNormlElement->SetMappingMode(FbxGeometryElement::eByControlPoint);
lNormlElement->SetReferenceMode(FbxGeometryElement::eDirect);
for (int n=0; n<8; n++)
lNormlElement->GetDirectArray().Add(FbxVector4(lNormals[n][0], lNormals[n][1], lNormals[n][2]));
FbxNode* lNode = FbxNode::Create(pScene,pName);
pScene->GetRootNode()->AddChild(lNode);
lNode->SetNodeAttribute(lMesh);
return lNode;
}
FbxNode* CreatePyramid(FbxScene* pScene, const char* pName)
{
int i, j;
FbxMesh* lMesh = FbxMesh::Create(pScene,"");
FbxVector4 lControlPoint0(-50, 0, 50);
FbxVector4 lControlPoint1(50, 0, 50);
FbxVector4 lControlPoint2(50, 0, -50);
FbxVector4 lControlPoint3(-50, 0, -50);
FbxVector4 lControlPoint4(0, 100, 0);
FbxVector4 lNormalP0(0, 1, 0);
FbxVector4 lNormalP1(0, 0.447, 0.894);
FbxVector4 lNormalP2(0.894, 0.447, 0);
FbxVector4 lNormalP3(0, 0.447, -0.894);
FbxVector4 lNormalP4(-0.894, 0.447, 0);
lMesh->InitControlPoints(16);
FbxVector4* lControlPoints = lMesh->GetControlPoints();
lControlPoints[0] = lControlPoint0;
lControlPoints[1] = lControlPoint1;
lControlPoints[2] = lControlPoint2;
lControlPoints[3] = lControlPoint3;
lControlPoints[4] = lControlPoint0;
lControlPoints[5] = lControlPoint1;
lControlPoints[6] = lControlPoint4;
lControlPoints[7] = lControlPoint1;
lControlPoints[8] = lControlPoint2;
lControlPoints[9] = lControlPoint4;
lControlPoints[10] = lControlPoint2;
lControlPoints[11] = lControlPoint3;
lControlPoints[12] = lControlPoint4;
lControlPoints[13] = lControlPoint3;
lControlPoints[14] = lControlPoint0;
lControlPoints[15] = lControlPoint4;
FbxGeometryElementNormal* lNormlElement = lMesh->CreateElementNormal();
lNormlElement->SetMappingMode(FbxGeometryElement::eByControlPoint);
lNormlElement->SetReferenceMode(FbxGeometryElement::eDirect);
lNormlElement->GetDirectArray().Add(lNormalP0);
lNormlElement->GetDirectArray().Add(lNormalP0);
lNormlElement->GetDirectArray().Add(lNormalP0);
lNormlElement->GetDirectArray().Add(lNormalP0);
lNormlElement->GetDirectArray().Add(lNormalP1);
lNormlElement->GetDirectArray().Add(lNormalP1);
lNormlElement->GetDirectArray().Add(lNormalP1);
lNormlElement->GetDirectArray().Add(lNormalP2);
lNormlElement->GetDirectArray().Add(lNormalP2);
lNormlElement->GetDirectArray().Add(lNormalP2);
lNormlElement->GetDirectArray().Add(lNormalP3);
lNormlElement->GetDirectArray().Add(lNormalP3);
lNormlElement->GetDirectArray().Add(lNormalP3);
lNormlElement->GetDirectArray().Add(lNormalP4);
lNormlElement->GetDirectArray().Add(lNormalP4);
lNormlElement->GetDirectArray().Add(lNormalP4);
int lPolygonVertices[] = { 0, 3, 2, 1,
4, 5, 6,
7, 8, 9,
10, 11, 12,
13, 14, 15 };
lMesh->BeginPolygon();
for(j = 0; j < 4; j++)
{
lMesh->AddPolygon(lPolygonVertices[j]);
}
lMesh->EndPolygon ();
for(i = 1; i < 5; i++)
{
lMesh->BeginPolygon();
for(j = 0; j < 3; j++)
{
lMesh->AddPolygon(lPolygonVertices[4 + 3*(i - 1) + j]);
}
lMesh->EndPolygon ();
}
FbxNode* lNode = FbxNode::Create(pScene,pName);
lNode->SetNodeAttribute(lMesh);
pScene->GetRootNode()->AddChild(lNode);
FbxVector4 lTranslation(-150, 0, 0, 0);
lNode->LclTranslation.Set(lTranslation);
return lNode;
}
void CreateUserProperties(FbxNode *pNode) {
FbxProperty p1 = FbxProperty::Create(pNode, FbxBoolDT, "MyBooleanProperty", "My Bool");
FbxProperty p2 = FbxProperty::Create(pNode, FbxFloatDT, "MyRealProperty", "My floating point number");
FbxProperty p3 = FbxProperty::Create(pNode, FbxColor3DT, "MyColorProperty", "My Color");
FbxProperty p4 = FbxProperty::Create(pNode, FbxIntDT, "MyInteger", "");
FbxProperty p5 = FbxProperty::Create(pNode, FbxDouble4DT, "MyVector", "");
FbxProperty p6 = FbxProperty::Create(pNode, FbxStringListDT, "MyList", "");
p1.ModifyFlag(FbxPropertyAttr::eUserDefined, true);
p2.ModifyFlag(FbxPropertyAttr::eUserDefined, true);
p3.ModifyFlag(FbxPropertyAttr::eUserDefined, true);
p4.ModifyFlag(FbxPropertyAttr::eUserDefined, true);
p5.ModifyFlag(FbxPropertyAttr::eUserDefined, true);
p6.ModifyFlag(FbxPropertyAttr::eUserDefined, true);
p3.ModifyFlag(FbxPropertyAttr::eAnimatable, true);
p5.ModifyFlag(FbxPropertyAttr::eAnimatable, true);
p6.ModifyFlag(FbxPropertyAttr::eAnimatable, true);
FbxColor lRed(1.0, 0.0, 0.0);
p1.Set(false);
p2.Set(3.33);
p3.Set(lRed);
p4.Set(11);
p5.Set(FbxDouble3(-1.1, 2.2, -3.3));
p6.Set(2);
p4.SetLimits(-5.0, 9.0);
p5.SetLimits(0.0, 2.1);
p6.AddEnumValue("one");
p6.AddEnumValue("two");
p6.AddEnumValue("three");
p6.AddEnumValue("Four");
p6.InsertEnumValue(0, "zero");
}
void AnimateList(FbxScene* pScene, FbxProperty* pList)
{
FbxAnimStack* lAnimStack = FbxAnimStack::Create(pScene, ANIM_STACK_ANIMATE_LIST);
FbxAnimLayer* lAnimLayer = FbxAnimLayer::Create(pScene, "Base Layer");
lAnimStack->AddMember(lAnimLayer);
FbxAnimCurveNode* lFbxFCurveNode = pList->GetCurveNode(lAnimLayer, true);
if (lFbxFCurveNode)
{
FbxTime lKeyTime;
FbxAnimCurve* lFCurve = lFbxFCurveNode->GetCurve(0U);
if (lFCurve == NULL)
lFCurve = lFbxFCurveNode->CreateCurve(lFbxFCurveNode->GetName());
lFCurve->KeyModifyBegin();
lFCurve->ResizeKeyBuffer(5);
lKeyTime.SetSecondDouble(0.0);
FbxAnimCurveKey lKey1(lKeyTime, 0.0);
lKey1.SetInterpolation(FbxAnimCurveDef::eInterpolationConstant);
lKey1.SetConstantMode(FbxAnimCurveDef::eConstantStandard);
lFCurve->KeySet(0, lKey1);
lKeyTime.SetSecondDouble(1.0);
FbxAnimCurveKey lKey2(lKeyTime, 1.0);
lKey2.SetInterpolation(FbxAnimCurveDef::eInterpolationConstant);
lKey2.SetConstantMode(FbxAnimCurveDef::eConstantStandard);
lFCurve->KeySet(1, lKey2);
lKeyTime.SetSecondDouble(2.0);
lFCurve->KeySet(2, lKeyTime, 2.0, FbxAnimCurveDef::eInterpolationConstant, (FbxAnimCurveDef::ETangentMode)FbxAnimCurveDef::eConstantStandard);
lKeyTime.SetSecondDouble(3.0);
lFCurve->KeySet(3, lKeyTime, 3.0, FbxAnimCurveDef::eInterpolationConstant, (FbxAnimCurveDef::ETangentMode)FbxAnimCurveDef::eConstantStandard);
lKeyTime.SetSecondDouble(4.0);
lFCurve->KeySet(4, lKeyTime, 0.0, FbxAnimCurveDef::eInterpolationConstant, (FbxAnimCurveDef::ETangentMode)FbxAnimCurveDef::eConstantStandard);
lFCurve->KeyModifyEnd();
}
}
FbxConstraintPosition* CreatePositionConstraint(FbxScene* pScene, FbxNode* pSourceNode, FbxNode* pConstrainedNode)
{
FbxConstraintPosition *lPositionConstraint = FbxConstraintPosition::Create(pScene,"Position");
lPositionConstraint->SetConstrainedObject(pConstrainedNode);
lPositionConstraint->AddConstraintSource(pSourceNode, 100.0);
lPositionConstraint->AffectX = true;
lPositionConstraint->AffectY = true;
lPositionConstraint->AffectZ = true;
FbxVector4 lPositionSource;
FbxVector4 lPositionConstrainedObj;
lPositionSource = pSourceNode->LclTranslation.Get();
lPositionConstrainedObj = pConstrainedNode->LclTranslation.Get();
FbxVector4 lOffset = lPositionConstrainedObj - lPositionSource;
lPositionConstraint->Translation = FbxDouble3(lOffset);
FbxProperty lActive = lPositionConstraint->FindProperty("Active", false);
lActive.Set(true);
return lPositionConstraint;
}
void AnimateCube(FbxScene* pScene, FbxNode* pNode)
{
FbxAnimStack* lAnimStack = FbxAnimStack::Create(pScene, ANIM_STACK_ANIMATE_CUBE);
FbxAnimLayer* lAnimLayer = FbxAnimLayer::Create(pScene, "Base Layer");
lAnimStack->AddMember(lAnimLayer);
AnimateNode(pNode, lAnimLayer);
}
void AnimatePyramid(FbxScene* pScene, FbxNode* pNode)
{
FbxAnimStack* lAnimStack = FbxAnimStack::Create(pScene, ANIM_STACK_ANIMATE_PYRAMID);
FbxAnimLayer* lAnimLayer = FbxAnimLayer::Create(pScene, "Base Layer");
lAnimStack->AddMember(lAnimLayer);
AnimateNode(pNode, lAnimLayer);
}
void AnimateNode(FbxNode* pNode, FbxAnimLayer* pAnimLayer)
{
FbxAnimCurve* lCurveX = NULL;
FbxAnimCurve* lCurveY = NULL;
FbxAnimCurve* lCurveZ = NULL;
FbxTime lTime;
int lKeyIndex = 0;
pNode->LclTranslation.GetCurveNode(pAnimLayer, true);
lCurveX = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
lCurveY = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
lCurveZ = pNode->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
if (lCurveX)
{
lCurveX->KeyModifyBegin();
lTime.SetSecondDouble(0.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(1.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, 100.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(2.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(3.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, -100.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(4.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationCubic);
lCurveX->KeyModifyEnd();
}
if (lCurveY)
{
lCurveY->KeyModifyBegin();
lTime.SetSecondDouble(2.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(3.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, 100.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(4.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(5.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, -100.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(6.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationCubic);
lCurveY->KeyModifyEnd();
}
if (lCurveZ)
{
lCurveZ->KeyModifyBegin();
lTime.SetSecondDouble(5.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(6.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, 100.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(7.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(8.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, -100.0, FbxAnimCurveDef::eInterpolationCubic);
lTime.SetSecondDouble(9.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationCubic);
lCurveZ->KeyModifyEnd();
}
}