#include <fbxsdk.h>
#ifdef KARCH_ENV_WIN
#include <malloc.h>
#endif
#include "../MyOwnWriterReader/MyOwnWriterReader.h"
#include "../Common/Common.h"
#define SAMPLE_FILENAME "ExportScene05.fbx"
bool CreateScene(KFbxScene* pScene);
void SetGlobalDefaultPosition(KFbxNode* pNode, KFbxXMatrix pGlobalPosition);
KFbxXMatrix GetGlobalDefaultPosition(KFbxNode* pNode);
class MyMemoryAllocator : public KFbxMemoryAllocator
{
public:
MyMemoryAllocator()
: KFbxMemoryAllocator(MyMalloc, MyCalloc, MyRealloc, MyFree, MyMsize)
{
}
~MyMemoryAllocator()
{
}
static void* MyMalloc(size_t pSize)
{
return malloc(pSize);
}
static void* MyCalloc(size_t pCount,size_t pSize)
{
return calloc(pCount, pSize);
}
static void* MyRealloc(void* pData, size_t pSize)
{
return realloc(pData, pSize);
}
static void MyFree(void* pData)
{
free(pData);
}
static size_t MyMsize(void* pData)
{
return _msize(pData);
}
};
int main(int argc, char** argv)
{
KFbxSdkManager* lSdkManager = NULL;
MyMemoryAllocator lMyMemoryAllocator;
KFbxScene* lScene = NULL;
bool lResult;
KFbxSdkManager::SetMemoryAllocator(&lMyMemoryAllocator);
InitializeSdkObjects(lSdkManager, lScene);
lResult = CreateScene(lScene);
if(lResult == false)
{
printf("\n\nAn error occurred while creating the scene...\n");
DestroySdkObjects(lSdkManager);
return 1;
}
if(argc > 1)
{
lResult = SaveScene(lSdkManager, lScene, argv[1]);
}
else
{
lResult = SaveScene(lSdkManager, lScene, SAMPLE_FILENAME);
}
if(lResult == false)
{
printf("\n\nAn error occurred while saving the scene...\n");
DestroySdkObjects(lSdkManager);
return 1;
}
printf("Writing to file with custom writer\n");
int lRegisteredCount;
int lPluginId;
lSdkManager->GetIOPluginRegistry()->RegisterWriter(CreateMyOwnWriter, GetMyOwnWriterInfo,
lPluginId, lRegisteredCount, FillOwnWriterIOSettings);
const char* lFileName = "CustomWriter.ABC";
KFbxExporter* lExporter = KFbxExporter::Create(lSdkManager, "");
int lFileFormat = lSdkManager->GetIOPluginRegistry()->FindWriterIDByExtension("ABC");
if(lExporter->Initialize(lFileName, lFileFormat, lSdkManager->GetIOSettings()) == false)
{
printf("Call to KFbxExporter::Initialize() failed.\n");
printf("Error returned: %s\n\n", lExporter->GetLastErrorString());
DestroySdkObjects(lSdkManager);
return 1;
}
lResult = lExporter->Export(lScene);
if(lResult == false)
{
printf("Error in write of our custom writer\n");
DestroySdkObjects(lSdkManager);
return 1;
}
lSdkManager->GetIOPluginRegistry()->RegisterReader(CreateMyOwnReader, GetMyOwnReaderInfo,
lPluginId, lRegisteredCount, FillOwnReaderIOSettings);
KFbxImporter* lImporter = KFbxImporter::Create(lSdkManager,"");
lResult = lImporter->Initialize(lFileName, -1, lSdkManager->GetIOSettings() );
lResult = lImporter->Import(lScene);
if(lResult == false)
{
printf("There was a problem in the read of our custom reader\n");
DestroySdkObjects(lSdkManager);
return 1;
}
DestroySdkObjects(lSdkManager);
return 0;
}
bool CreateScene(KFbxScene* pScene)
{
KFbxVector4 lT, lR, lS;
KFbxXMatrix lGM;
KFbxNode* pNodeA = KFbxNode::Create(pScene,"A");
KFbxNode* pNodeB = KFbxNode::Create(pScene,"B");
KFbxNode* pNodeC = KFbxNode::Create(pScene,"C");
KFbxNode* pNodeD = KFbxNode::Create(pScene,"D");
KFbxSkeleton* lSkeletonA = KFbxSkeleton::Create(pScene,"");
lSkeletonA->SetSkeletonType(KFbxSkeleton::eROOT);
pNodeA->SetNodeAttribute(lSkeletonA);
KFbxSkeleton* lSkeletonB = KFbxSkeleton::Create(pScene,"");
lSkeletonB->SetSkeletonType(KFbxSkeleton::eLIMB_NODE);
pNodeB->SetNodeAttribute(lSkeletonB);
KFbxSkeleton* lSkeletonC = KFbxSkeleton::Create(pScene,"");
lSkeletonC->SetSkeletonType(KFbxSkeleton::eLIMB_NODE);
pNodeC->SetNodeAttribute(lSkeletonC);
KFbxSkeleton* lSkeletonD = KFbxSkeleton::Create(pScene,"");
lSkeletonD->SetSkeletonType(KFbxSkeleton::eLIMB_NODE);
pNodeD->SetNodeAttribute(lSkeletonD);
pNodeA->GetLimits().SetTranslationLimitActive(true);
pNodeA->GetLimits().mTranslationLimits.SetLimitMinActive(true, true, true);
pNodeA->GetLimits().mTranslationLimits.SetLimitMin(KFbxVector4(0.1, 0.2, 0.3));
pNodeA->GetLimits().mTranslationLimits.SetLimitMaxActive(true, true, true);
pNodeA->GetLimits().mTranslationLimits.SetLimitMax(KFbxVector4(5.0, 1.0, 0.0));
pNodeB->SetRotationActive(true);
pNodeB->GetLimits().mRotationLimits.SetLimitMaxActive(true, false, false);
pNodeB->GetLimits().mRotationLimits.SetLimitMax(KFbxVector4(33.3, 0.0, 0.0));
pNodeB->SetPivotState(KFbxNode::eSOURCE_SET, KFbxNode::ePIVOT_STATE_ACTIVE);
pNodeB->SetRotationOrder(KFbxNode::eSOURCE_SET, eSPHERIC_XYZ);
pNodeB->SetUseRotationSpaceForLimitOnly(KFbxNode::eSOURCE_SET, false);
pNodeB->SetQuaternionInterpolation(KFbxNode::eSOURCE_SET, eQUATINTERP_CLASSIC);
pNodeB->SetRotationPivot(KFbxNode::eSOURCE_SET, KFbxVector4(11.1, 22.2, 33.3));
pNodeB->SetPreRotation(KFbxNode::eSOURCE_SET, KFbxVector4(15.0, 30.0, 45.0));
pNodeB->SetPostRotation(KFbxNode::eSOURCE_SET, KFbxVector4(-45.0, -30.0, -15.0));
pScene->GetRootNode()->AddChild(pNodeA);
pNodeA->AddChild(pNodeB);
pNodeB->AddChild(pNodeC);
pNodeC->AddChild(pNodeD);
lT.Set(0.0, 0.0, 0.0); lGM.SetT(lT);
lR.Set(0.0, 0.0, 45.0); lGM.SetR(lR);
SetGlobalDefaultPosition(pNodeA, lGM);
lT.Set(30.0, 20.0, 0.0); lGM.SetT(lT);
lR.Set(0.0, 0.0, 0.0); lGM.SetR(lR);
SetGlobalDefaultPosition(pNodeB, lGM);
lT.Set(55.0, 20.0, 0.0); lGM.SetT(lT);
lR.Set(0.0, 0.0, -40.0); lGM.SetR(lR);
SetGlobalDefaultPosition(pNodeC, lGM);
lT.Set(70.0, 10.0, 0.0); lGM.SetT(lT);
lR.Set(0.0, 0.0, 0.0); lGM.SetR(lR);
SetGlobalDefaultPosition(pNodeD, lGM);
KFbxObjectMetaData* pFamilyMetaData = KFbxObjectMetaData::Create(pScene, "Family");
KFbxProperty::Create(pFamilyMetaData, DTString, "Level", "Level").Set(KString("Family"));
KFbxProperty::Create(pFamilyMetaData, DTString, "Type", "Type").Set(KString("Wall"));
KFbxProperty::Create(pFamilyMetaData, DTFloat, "Width", "Width").Set(10.0f);
KFbxProperty::Create(pFamilyMetaData, DTDouble, "Weight", "Weight").Set(25.0);
KFbxProperty::Create(pFamilyMetaData, DTDouble, "Cost", "Cost").Set(1.25);
KFbxObjectMetaData* pTypeMetaData = KFbxCast<KFbxObjectMetaData>(pFamilyMetaData->Clone(KFbxObject::eREFERENCE_CLONE, pScene));
pTypeMetaData->SetName("Type");
pTypeMetaData->FindProperty("Cost").Set(2500.0);
pTypeMetaData->FindProperty("Level").Set(KString("Type"));
KFbxObjectMetaData* pInstanceMetaData = KFbxCast<KFbxObjectMetaData>(pTypeMetaData->Clone(KFbxObject::eREFERENCE_CLONE, pScene));
pInstanceMetaData->SetName("Instance");
KFbxProperty::Create(pInstanceMetaData, DTString, "Sku", "Sku#").Set(KString("143914-10"));
pInstanceMetaData->FindProperty("Width").Set(1100.50f);
pInstanceMetaData->FindProperty("Type").Set(KString("Super Heavy Duty Wall"));
pInstanceMetaData->FindProperty("Level").Set(KString("Instance"));
pNodeA->ConnectSrcObject(pInstanceMetaData);
pNodeC->ConnectSrcObject(pInstanceMetaData);
pNodeD->ConnectSrcObject(pTypeMetaData);
return true;
}
void SetGlobalDefaultPosition(KFbxNode* pNode, KFbxXMatrix pGlobalPosition)
{
KFbxXMatrix lLocalPosition;
KFbxXMatrix lParentGlobalPosition;
if (pNode->GetParent())
{
lParentGlobalPosition = GetGlobalDefaultPosition(pNode->GetParent());
lLocalPosition = lParentGlobalPosition.Inverse() * pGlobalPosition;
}
else
{
lLocalPosition = pGlobalPosition;
}
pNode->LclTranslation.Set(lLocalPosition.GetT());
pNode->LclRotation.Set(lLocalPosition.GetR());
pNode->LclScaling.Set(lLocalPosition.GetS());
}
KFbxXMatrix GetGlobalDefaultPosition(KFbxNode* pNode)
{
KFbxXMatrix lLocalPosition;
KFbxXMatrix lGlobalPosition;
KFbxXMatrix lParentGlobalPosition;
lLocalPosition.SetT(pNode->LclTranslation.Get());
lLocalPosition.SetR(pNode->LclRotation.Get());
lLocalPosition.SetS(pNode->LclScaling.Get());
if (pNode->GetParent())
{
lParentGlobalPosition = GetGlobalDefaultPosition(pNode->GetParent());
lGlobalPosition = lParentGlobalPosition * lLocalPosition;
}
else
{
lGlobalPosition = lLocalPosition;
}
return lGlobalPosition;
}