#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"
KFbxNode* CreateCube(KFbxScene* pScene, char* pName);
KFbxNode* CreatePyramid(KFbxScene* pScene, char* pName);
void CreateUserProperties(KFbxNode *pNode);
void AnimateList(KFbxScene* pScene, KFbxNode* pNode, KFbxProperty* pList);
KFbxConstraintPosition* CreatePositionConstraint(KFbxScene* pScene, KFbxNode* pSourceNode, KFbxNode* pConstrainedNode);
void AnimateCube(KFbxScene* pScene, KFbxNode* pNode);
void AnimatePyramid(KFbxScene* pScene, KFbxNode* pNode);
void AnimateNode(KFbxNode* pNode, KFbxAnimLayer* pAnimLayer);
int main(int argc, char** argv)
{
KFbxSdkManager* lSdkManager = NULL;
KFbxScene* lScene = NULL;
bool lResult;
InitializeSdkObjects(lSdkManager, lScene);
KFbxNode* lCube = CreateCube(lScene, "Cube");
KFbxNode* lPyramid = CreatePyramid(lScene, "Pyramid");
KFbxNode* lRootNode = lScene->GetRootNode();
lRootNode->AddChild(lCube);
lRootNode->AddChild(lPyramid);
CreateUserProperties(lCube);
KFbxProperty p6 = lCube->FindProperty("MyList", false);
AnimateList(lScene, lCube, &p6);
KFbxConstraintPosition* lPositionConstraint = (KFbxConstraintPosition*)CreatePositionConstraint(lScene, lCube, lPyramid);
KFbxConnectDst(lPositionConstraint,lScene);
AnimateCube(lScene, lCube);
AnimatePyramid(lScene, lPyramid);
if(argc > 1)
{
lResult = SaveScene(lSdkManager, lScene, argv[1], lSdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)") );
}
else
{
lResult = SaveScene(lSdkManager, lScene, SAMPLE_FILENAME, lSdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)") );
}
if(lResult == false)
{
printf("\n\nAn error occurred while saving the scene...\n");
DestroySdkObjects(lSdkManager);
return 0;
}
DestroySdkObjects(lSdkManager);
return 0;
}
KFbxNode* CreateCube(KFbxScene* pScene, 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}
};
KFbxMesh* lMesh = KFbxMesh::Create(pScene,"");
lMesh->InitControlPoints(8);
KFbxVector4* vertex = lMesh->GetControlPoints();
memcpy((void*)vertex, (void*)lControlPoints, 8*sizeof(KFbxVector4));
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();
}
KFbxGeometryElementNormal* lNormlElement= lMesh->CreateElementNormal();
lNormlElement->SetMappingMode(KFbxGeometryElement::eBY_CONTROL_POINT);
lNormlElement->SetReferenceMode(KFbxGeometryElement::eDIRECT);
for (int n=0; n<8; n++)
lNormlElement->GetDirectArray().Add(KFbxVector4(lNormals[n][0], lNormals[n][1], lNormals[n][2]));
KFbxNode* lNode = KFbxNode::Create(pScene,pName);
pScene->GetRootNode()->AddChild(lNode);
lNode->SetNodeAttribute(lMesh);
return lNode;
}
KFbxNode* CreatePyramid(KFbxScene* pScene, char* pName)
{
int i, j;
KFbxMesh* lMesh = KFbxMesh::Create(pScene,"");
KFbxVector4 lControlPoint0(-50, 0, 50);
KFbxVector4 lControlPoint1(50, 0, 50);
KFbxVector4 lControlPoint2(50, 0, -50);
KFbxVector4 lControlPoint3(-50, 0, -50);
KFbxVector4 lControlPoint4(0, 100, 0);
KFbxVector4 lNormalP0(0, 1, 0);
KFbxVector4 lNormalP1(0, 0.447, 0.894);
KFbxVector4 lNormalP2(0.894, 0.447, 0);
KFbxVector4 lNormalP3(0, 0.447, -0.894);
KFbxVector4 lNormalP4(-0.894, 0.447, 0);
lMesh->InitControlPoints(16);
KFbxVector4* 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;
KFbxGeometryElementNormal* lNormlElement = lMesh->CreateElementNormal();
lNormlElement->SetMappingMode(KFbxGeometryElement::eBY_CONTROL_POINT);
lNormlElement->SetReferenceMode(KFbxGeometryElement::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 ();
}
KFbxNode* lNode = KFbxNode::Create(pScene,pName);
lNode->SetNodeAttribute(lMesh);
pScene->GetRootNode()->AddChild(lNode);
KFbxVector4 lTranslation(-150, 0, 0, 0);
lNode->LclTranslation.Set(lTranslation);
return lNode;
}
void CreateUserProperties(KFbxNode *pNode) {
KFbxProperty p1 = KFbxProperty::Create(pNode, DTBool, "MyBooleanProperty", "My Bool");
KFbxProperty p2 = KFbxProperty::Create(pNode, DTFloat, "MyRealProperty", "My floating point number");
KFbxProperty p3 = KFbxProperty::Create(pNode, DTColor3, "MyColorProperty", "My Color");
KFbxProperty p4 = KFbxProperty::Create(pNode, DTInteger, "MyInteger", "");
KFbxProperty p5 = KFbxProperty::Create(pNode, DTDouble4, "MyVector", "");
KFbxProperty p6 = KFbxProperty::Create(pNode, DTStringList, "MyList", "");
p1.ModifyFlag(KFbxProperty::eUSER, true);
p2.ModifyFlag(KFbxProperty::eUSER, true);
p3.ModifyFlag(KFbxProperty::eUSER, true);
p4.ModifyFlag(KFbxProperty::eUSER, true);
p5.ModifyFlag(KFbxProperty::eUSER, true);
p6.ModifyFlag(KFbxProperty::eUSER, true);
p3.ModifyFlag(KFbxProperty::eANIMATABLE, true);
p5.ModifyFlag(KFbxProperty::eANIMATABLE, true);
p6.ModifyFlag(KFbxProperty::eANIMATABLE, true);
KFbxColor 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(KFbxScene* pScene, KFbxNode* pNode, KFbxProperty* pList)
{
KFbxAnimStack* lAnimStack = KFbxAnimStack::Create(pScene, ANIM_STACK_ANIMATE_LIST);
KFbxAnimLayer* lAnimLayer = KFbxAnimLayer::Create(pScene, "Base Layer");
lAnimStack->AddMember(lAnimLayer);
KFbxAnimCurveNode* lFbxFCurveNode = pList->GetCurveNode(lAnimLayer, true);
if (lFbxFCurveNode)
{
KTime lKeyTime;
KFbxAnimCurve* lFCurve = lFbxFCurveNode->GetCurve(0U);
if (lFCurve == NULL)
lFCurve = lFbxFCurveNode->CreateCurve(lFbxFCurveNode->GetName());
lFCurve->KeyModifyBegin();
lFCurve->ResizeKeyBuffer(5);
lKeyTime.SetSecondDouble(0.0);
KFbxAnimCurveKey lKey1(lKeyTime, 0.0);
lKey1.SetInterpolation(KFbxAnimCurveDef::eINTERPOLATION_CONSTANT);
lKey1.SetConstantMode(KFbxAnimCurveDef::eCONSTANT_STANDARD);
lFCurve->KeySet(0, lKey1);
lKeyTime.SetSecondDouble(1.0);
KFbxAnimCurveKey lKey2(lKeyTime, 1.0);
lKey2.SetInterpolation(KFbxAnimCurveDef::eINTERPOLATION_CONSTANT);
lKey2.SetConstantMode(KFbxAnimCurveDef::eCONSTANT_STANDARD);
lFCurve->KeySet(1, lKey2);
lKeyTime.SetSecondDouble(2.0);
lFCurve->KeySet(2, lKeyTime, 2.0, KFbxAnimCurveDef::eINTERPOLATION_CONSTANT, (KFbxAnimCurveDef::ETangentMode)KFbxAnimCurveDef::eCONSTANT_STANDARD);
lKeyTime.SetSecondDouble(3.0);
lFCurve->KeySet(3, lKeyTime, 3.0, KFbxAnimCurveDef::eINTERPOLATION_CONSTANT, (KFbxAnimCurveDef::ETangentMode)KFbxAnimCurveDef::eCONSTANT_STANDARD);
lKeyTime.SetSecondDouble(4.0);
lFCurve->KeySet(4, lKeyTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CONSTANT, (KFbxAnimCurveDef::ETangentMode)KFbxAnimCurveDef::eCONSTANT_STANDARD);
lFCurve->KeyModifyEnd();
}
}
KFbxConstraintPosition* CreatePositionConstraint(KFbxScene* pScene, KFbxNode* pSourceNode, KFbxNode* pConstrainedNode)
{
KFbxConstraintPosition *lPositionConstraint = KFbxConstraintPosition::Create(pScene,"Position");
lPositionConstraint->SetConstrainedObject(pConstrainedNode);
lPositionConstraint->AddConstraintSource(pSourceNode, 100.0);
lPositionConstraint->SetAffectX(true);
lPositionConstraint->SetAffectY(true);
lPositionConstraint->SetAffectZ(true);
KFbxVector4 lPositionSource;
KFbxVector4 lPositionConstrainedObj;
lPositionSource = pSourceNode->LclTranslation.Get();
lPositionConstrainedObj = pConstrainedNode->LclTranslation.Get();
KFbxVector4 lOffset = lPositionConstrainedObj - lPositionSource;
lPositionConstraint->SetOffset(lOffset);
KFbxProperty lActive = lPositionConstraint->FindProperty("Active", false);
lActive.Set(true);
return lPositionConstraint;
}
void AnimateCube(KFbxScene* pScene, KFbxNode* pNode)
{
KFbxAnimStack* lAnimStack = KFbxAnimStack::Create(pScene, ANIM_STACK_ANIMATE_CUBE);
KFbxAnimLayer* lAnimLayer = KFbxAnimLayer::Create(pScene, "Base Layer");
lAnimStack->AddMember(lAnimLayer);
AnimateNode(pNode, lAnimLayer);
}
void AnimatePyramid(KFbxScene* pScene, KFbxNode* pNode)
{
KFbxAnimStack* lAnimStack = KFbxAnimStack::Create(pScene, ANIM_STACK_ANIMATE_PYRAMID);
KFbxAnimLayer* lAnimLayer = KFbxAnimLayer::Create(pScene, "Base Layer");
lAnimStack->AddMember(lAnimLayer);
AnimateNode(pNode, lAnimLayer);
}
void AnimateNode(KFbxNode* pNode, KFbxAnimLayer* pAnimLayer)
{
KFbxAnimCurve* lCurveX = NULL;
KFbxAnimCurve* lCurveY = NULL;
KFbxAnimCurve* lCurveZ = NULL;
KTime lTime;
int lKeyIndex = 0;
pNode->LclTranslation.GetCurveNode(pAnimLayer, true);
lCurveX = pNode->LclTranslation.GetCurve<KFbxAnimCurve>(pAnimLayer, KFCURVENODE_T_X, true);
lCurveY = pNode->LclTranslation.GetCurve<KFbxAnimCurve>(pAnimLayer, KFCURVENODE_T_Y, true);
lCurveZ = pNode->LclTranslation.GetCurve<KFbxAnimCurve>(pAnimLayer, KFCURVENODE_T_Z, true);
if (lCurveX)
{
lCurveX->KeyModifyBegin();
lTime.SetSecondDouble(0.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(1.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, 100.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(2.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(3.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, -100.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(4.0);
lKeyIndex = lCurveX->KeyAdd(lTime);
lCurveX->KeySet(lKeyIndex, lTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lCurveX->KeyModifyEnd();
}
if (lCurveY)
{
lCurveY->KeyModifyBegin();
lTime.SetSecondDouble(2.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(3.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, 100.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(4.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(5.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, -100.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(6.0);
lKeyIndex = lCurveY->KeyAdd(lTime);
lCurveY->KeySet(lKeyIndex, lTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lCurveY->KeyModifyEnd();
}
if (lCurveZ)
{
lCurveZ->KeyModifyBegin();
lTime.SetSecondDouble(5.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(6.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, 100.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(7.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(8.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, -100.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lTime.SetSecondDouble(9.0);
lKeyIndex = lCurveZ->KeyAdd(lTime);
lCurveZ->KeySet(lKeyIndex, lTime, 0.0, KFbxAnimCurveDef::eINTERPOLATION_CUBIC);
lCurveZ->KeyModifyEnd();
}
}