#include "SDK_Utility.h"
FbxManager* gSdkManager = NULL;
FbxScene* gScene = NULL;
FbxFileTexture* gTexture = NULL;
FbxSurfacePhong* gMaterial = NULL;
int gCubeNumber = 1;
int gCubeRotationAxis = 1;
double gCubeXPos = 0.0;
double gCubeYPos = 20.0;
double gCubeZPos = 0.0;
FbxAnimLayer* gAnimLayer = NULL;
FbxString* gAppPath = NULL;
#ifdef IOS_REF
#undef IOS_REF
#define IOS_REF (*(pSdkManager->GetIOSettings()))
#endif
bool InitializeSdkObjects(FbxManager*& pManager, FbxScene*& pScene)
{
pManager = FbxManager::Create();
if( !pManager )
{
FBXSDK_printf("Error: Unable to create FBX Manager!\n");
exit(1);
}
else FBXSDK_printf("Autodesk FBX SDK version %s\n", pManager->GetVersion());
FbxIOSettings* ios = FbxIOSettings::Create(pManager, IOSROOT);
pManager->SetIOSettings(ios);
pScene = FbxScene::Create(pManager, "My Scene");
if( !pScene )
{
FBXSDK_printf("Error: Unable to create FBX scene!\n");
exit(1);
}
return true;
}
void DestroySdkObjects(FbxManager* pManager, bool pExitStatus)
{
if( pManager ) pManager->Destroy();
if( pExitStatus ) FBXSDK_printf("Program Success!\n");
}
bool CreateScene()
{
if(InitializeSdkObjects(gSdkManager, gScene) == false)
{
return false;
}
FbxAnimStack* lAnimStack = FbxAnimStack::Create(gScene, "Animation stack camera animation");
gAnimLayer = FbxAnimLayer::Create(gScene, "Base Layer");
lAnimStack->AddMember(gAnimLayer);
FbxNode* lMarker = CreateMarker(gScene, "Marker");
FbxNode* lCamera = CreateCamera(gScene, "Camera");
CreateTexture(gScene);
CreateMaterial(gScene);
SetCameraPointOfInterest(lCamera, lMarker);
SetMarkerDefaultPosition(lMarker);
SetCameraDefaultPosition(lCamera);
AnimateCamera(lCamera, gAnimLayer);
FbxNode* lRootNode = gScene->GetRootNode();
lRootNode->AddChild(lMarker);
lRootNode->AddChild(lCamera);
gScene->GetGlobalSettings().SetDefaultCamera((char *)lCamera->GetName());
return true;
}
void CreateCube(bool pWithTexture, bool pAnimate)
{
FbxString lCubeName = "Cube number ";
lCubeName += FbxString(gCubeNumber);
CreateCubeDetailed( lCubeName.Buffer(),
gCubeXPos,
gCubeYPos,
gCubeZPos,
gCubeRotationAxis,
pWithTexture,
pAnimate
);
gCubeNumber++;
if(gCubeXPos >= 0.0)
{
gCubeXPos += 50.0;
gCubeXPos *= -1.0;
gCubeRotationAxis++;
}
else
{
gCubeXPos *= -1.0;
}
gCubeYPos += 30.0;
if(gCubeRotationAxis > 2) gCubeRotationAxis = 0;
}
void RemoveCubes()
{
if(gSdkManager == NULL) return;
int nc = gScene->GetNodeCount();
if(nc <= 3) return;
for(int i=nc-1; i >= 3; i--)
{
FbxNode *node = gScene->GetNode(i);
gScene->RemoveNode(node);
FbxAnimCurveNode* lCurveNode = node->LclRotation.GetCurveNode(gAnimLayer);
if(lCurveNode != NULL)
{
lCurveNode->Destroy(true);
}
node->Destroy(true);
}
SetInitialCubeData();
}
void CreateCubeDetailed( char* pCubeName,
double pX,
double pY,
double pZ,
int pRotateAxe,
bool pWithTexture,
bool pAnimate
)
{
FbxNode* lCube = CreateCubeMesh(gScene, pCubeName);
lCube->LclTranslation.Set(FbxVector4(pX, pY, pZ));
if(pAnimate)
{
AnimateCube(lCube, gAnimLayer, pRotateAxe);
}
if(pWithTexture)
{
AddMaterials(lCube->GetMesh());
}
gScene->GetRootNode()->AddChild(lCube);
}
bool Export(
const char* pFilename,
int pFileFormat
)
{
return SaveScene(gSdkManager, gScene, pFilename, pFileFormat, true);
}
bool SaveScene(FbxManager* pSdkManager, FbxDocument* pScene, const char* pFilename, int pFileFormat, bool pEmbedMedia)
{
if(pSdkManager == NULL) return false;
if(pScene == NULL) return false;
if(pFilename == NULL) return false;
bool lStatus = true;
FbxExporter* lExporter = FbxExporter::Create(pSdkManager, "");
if( pFileFormat < 0 || pFileFormat >= pSdkManager->GetIOPluginRegistry()->GetWriterFormatCount() )
{
pFileFormat = pSdkManager->GetIOPluginRegistry()->GetNativeWriterFormat();
if (!pEmbedMedia)
{
int lFormatIndex, lFormatCount = pSdkManager->GetIOPluginRegistry()->GetWriterFormatCount();
for (lFormatIndex=0; lFormatIndex<lFormatCount; lFormatIndex++)
{
if (pSdkManager->GetIOPluginRegistry()->WriterIsFBX(lFormatIndex))
{
FbxString lDesc =pSdkManager->GetIOPluginRegistry()->GetWriterFormatDescription(lFormatIndex);
char *lASCII = "ascii";
if (lDesc.Find(lASCII)>=0)
{
pFileFormat = lFormatIndex;
break;
}
}
}
}
}
if(lExporter->Initialize(pFilename, pFileFormat, pSdkManager->GetIOSettings() ) == false)
{
return false;
}
IOS_REF.SetBoolProp(EXP_FBX_MATERIAL, true);
IOS_REF.SetBoolProp(EXP_FBX_TEXTURE, true);
IOS_REF.SetBoolProp(EXP_FBX_EMBEDDED, pEmbedMedia);
IOS_REF.SetBoolProp(EXP_FBX_SHAPE, true);
IOS_REF.SetBoolProp(EXP_FBX_GOBO, true);
IOS_REF.SetBoolProp(EXP_FBX_ANIMATION, true);
IOS_REF.SetBoolProp(EXP_FBX_GLOBAL_SETTINGS, true);
lStatus = lExporter->Export(pScene);
lExporter->Destroy();
return lStatus;
}
const char *GetWriterSFNFilters()
{
int nbWriters = gSdkManager->GetIOPluginRegistry()->GetWriterFormatCount();
FbxString s;
int i=0;
for(i=0; i < nbWriters; i++)
{
s += gSdkManager->GetIOPluginRegistry()->
GetWriterFormatDescription(i);
s += "|*.";
s += gSdkManager->GetIOPluginRegistry()->
GetWriterFormatExtension(i);
s += "|";
}
int nbChar = int(strlen(s.Buffer())) + 1;
char *filter = new char[ nbChar ];
memset(filter, 0, nbChar);
FBXSDK_strcpy(filter, nbChar, s.Buffer());
for(i=0; i < int(strlen(s.Buffer())); i++)
{
if(filter[i] == '|')
{
filter[i] = 0;
}
}
return filter;
}
const char *GetFileFormatExt(
const int pWriteFileFormat
)
{
char *buf = new char[10];
memset(buf, 0, 10);
buf[0] = '.';
const char * ext = gSdkManager->GetIOPluginRegistry()->
GetWriterFormatExtension(pWriteFileFormat);
FBXSDK_strcat(buf, 10, ext);
return buf;
}
const FbxNode* GetRootNode()
{
return gScene->GetRootNode();
}
const char * GetRootNodeName()
{
return GetRootNode()->GetName();
}
FbxString GetNodeNameAndAttributeTypeName(const FbxNode* pNode)
{
FbxString s = pNode->GetName();
FbxNodeAttribute::EType lAttributeType;
if(pNode->GetNodeAttribute() == NULL)
{
s += " (No node attribute type)";
}
else
{
lAttributeType = (pNode->GetNodeAttribute()->GetAttributeType());
switch (lAttributeType)
{
case FbxNodeAttribute::eMarker: s += " (Marker)"; break;
case FbxNodeAttribute::eSkeleton: s += " (Skeleton)"; break;
case FbxNodeAttribute::eMesh: s += " (Mesh)"; break;
case FbxNodeAttribute::eCamera: s += " (Camera)"; break;
case FbxNodeAttribute::eLight: s += " (Light)"; break;
case FbxNodeAttribute::eBoundary: s += " (Boundary)"; break;
case FbxNodeAttribute::eOpticalMarker: s += " (Optical marker)"; break;
case FbxNodeAttribute::eOpticalReference: s += " (Optical reference)"; break;
case FbxNodeAttribute::eCameraSwitcher: s += " (Camera switcher)"; break;
case FbxNodeAttribute::eNull: s += " (Null)"; break;
case FbxNodeAttribute::ePatch: s += " (Patch)"; break;
case FbxNodeAttribute::eNurbs: s += " (NURB)"; break;
case FbxNodeAttribute::eNurbsSurface: s += " (Nurbs surface)"; break;
case FbxNodeAttribute::eNurbsCurve: s += " (NURBS curve)"; break;
case FbxNodeAttribute::eTrimNurbsSurface: s += " (Trim nurbs surface)"; break;
case FbxNodeAttribute::eUnknown: s += " (Unidentified)"; break;
}
}
return s;
}
FbxString GetDefaultTranslationInfo(
const FbxNode* pNode
)
{
FbxVector4 v4;
v4 = ((FbxNode*)pNode)->LclTranslation.Get();
return FbxString("Translation (X,Y,Z): ") + FbxString(v4[0]) + ", " + FbxString(v4[1]) + ", " + FbxString(v4[2]);
}
FbxString GetNodeInfo( const FbxNode* pNode )
{
FbxString s;
int lMaterialCount = pNode->GetMaterialCount();
FbxSurfacePhong* lMaterial = NULL;
bool lTextureExist = false;
if( lMaterialCount > 0)
{
for( int i = 0; i < lMaterialCount; ++i)
{
lMaterial = (FbxSurfacePhong*)pNode->GetMaterial( i);
if( lMaterial->Diffuse.GetSrcObjectCount<FbxFileTexture>() > 0)
{
lTextureExist = true;
break;
}
}
}
if( lTextureExist) s+= "[Texture: Yes] ";
else s+= "[Texture: No] ";
bool anim = false;
FbxAnimCurveNode* lCurveNode = NULL;
lCurveNode =((FbxNode* )pNode)->LclRotation.GetCurveNode(gAnimLayer);
if(lCurveNode != NULL) anim = true;
lCurveNode = ((FbxNode* )pNode)->LclTranslation.GetCurveNode(gAnimLayer);
if(lCurveNode != NULL) anim = true;
if(anim == true)
{
s+= "[Animation: Yes] ";
}
else
{
s+= "[Animation: No] ";
}
return s;
}
FbxNode* CreateMarker(FbxScene* pScene, char* pName)
{
FbxMarker* lMarker = FbxMarker::Create(pScene,pName);
FbxNode* lNode = FbxNode::Create(pScene,pName);
lNode->SetNodeAttribute(lMarker);
return lNode;
}
FbxNode* CreateCamera(FbxScene* pScene, char* pName)
{
FbxCamera* lCamera = FbxCamera::Create(pScene,pName);
lCamera->SetFormat(FbxCamera::eNTSC);
FbxNode* lNode = FbxNode::Create(pScene,pName);
lNode->SetNodeAttribute(lCamera);
return lNode;
}
void SetCameraPointOfInterest(FbxNode* pCamera, FbxNode* pPointOfInterest)
{
pCamera->SetTarget(pPointOfInterest);
}
void SetMarkerDefaultPosition(FbxNode* pMarker)
{
pMarker->LclTranslation.Set(FbxVector4(0.0, 40.0, 0.0));
pMarker->LclRotation.Set(FbxVector4(0.0, 0.0, 0.0));
pMarker->LclScaling.Set(FbxVector4(1.0, 1.0, 1.0));
}
void SetCameraDefaultPosition(FbxNode* pCamera)
{
FbxVector4 lCameraLocation(0.0, 200.0, -100.0);
pCamera->LclTranslation.Set(lCameraLocation);
}
void AnimateCamera(FbxNode* pCamera, FbxAnimLayer* pAnimLayer)
{
FbxAnimCurve* lCurve = NULL;
FbxTime lTime;
int lKeyIndex = 0;
pCamera->LclTranslation.GetCurveNode(pAnimLayer, true);
lCurve = pCamera->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
if (lCurve)
{
lCurve->KeyModifyBegin();
lTime.SetSecondDouble(0.0);
lKeyIndex = lCurve->KeyAdd(lTime);
lCurve->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationLinear);
lTime.SetSecondDouble(20.0);
lKeyIndex = lCurve->KeyAdd(lTime);
lCurve->KeySet(lKeyIndex, lTime, 500.0, FbxAnimCurveDef::eInterpolationLinear);
lCurve->KeyModifyEnd();
}
lCurve = pCamera->LclTranslation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
if (lCurve)
{
lCurve->KeyModifyBegin();
lTime.SetSecondDouble(0.0);
lKeyIndex = lCurve->KeyAdd(lTime);
lCurve->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationLinear);
lTime.SetSecondDouble(20.0);
lKeyIndex = lCurve->KeyAdd(lTime);
lCurve->KeySet(lKeyIndex, lTime, 800.0, FbxAnimCurveDef::eInterpolationLinear);
lCurve->KeyModifyEnd();
}
}
void AnimateCube(FbxNode* pCube, FbxAnimLayer* pAnimLayer, int pRotAxe)
{
FbxAnimCurve* lCurve = NULL;
FbxTime lTime;
int lKeyIndex = 0;
pCube->LclRotation.GetCurveNode(pAnimLayer, true);
if(pRotAxe == 0) lCurve = pCube->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
else if(pRotAxe == 1) lCurve = pCube->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
else if(pRotAxe == 2) lCurve = pCube->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
if (lCurve)
{
lCurve->KeyModifyBegin();
lTime.SetSecondDouble(0.0);
lKeyIndex = lCurve->KeyAdd(lTime);
lCurve->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationLinear);
lTime.SetSecondDouble(20.0);
lKeyIndex = lCurve->KeyAdd(lTime);
lCurve->KeySet(lKeyIndex, lTime, -3500, FbxAnimCurveDef::eInterpolationLinear);
lCurve->KeyModifyEnd();
}
}
FbxNode* CreateCubeMesh(FbxScene* pScene, char* pName)
{
int i, j;
FbxMesh* lMesh = FbxMesh::Create(pScene,pName);
FbxVector4 lControlPoint0(-50, 0, 50);
FbxVector4 lControlPoint1(50, 0, 50);
FbxVector4 lControlPoint2(50, 100, 50);
FbxVector4 lControlPoint3(-50, 100, 50);
FbxVector4 lControlPoint4(-50, 0, -50);
FbxVector4 lControlPoint5(50, 0, -50);
FbxVector4 lControlPoint6(50, 100, -50);
FbxVector4 lControlPoint7(-50, 100, -50);
FbxVector4 lNormalXPos(1, 0, 0);
FbxVector4 lNormalXNeg(-1, 0, 0);
FbxVector4 lNormalYPos(0, 1, 0);
FbxVector4 lNormalYNeg(0, -1, 0);
FbxVector4 lNormalZPos(0, 0, 1);
FbxVector4 lNormalZNeg(0, 0, -1);
lMesh->InitControlPoints(24);
FbxVector4* lControlPoints = lMesh->GetControlPoints();
lControlPoints[0] = lControlPoint0;
lControlPoints[1] = lControlPoint1;
lControlPoints[2] = lControlPoint2;
lControlPoints[3] = lControlPoint3;
lControlPoints[4] = lControlPoint1;
lControlPoints[5] = lControlPoint5;
lControlPoints[6] = lControlPoint6;
lControlPoints[7] = lControlPoint2;
lControlPoints[8] = lControlPoint5;
lControlPoints[9] = lControlPoint4;
lControlPoints[10] = lControlPoint7;
lControlPoints[11] = lControlPoint6;
lControlPoints[12] = lControlPoint4;
lControlPoints[13] = lControlPoint0;
lControlPoints[14] = lControlPoint3;
lControlPoints[15] = lControlPoint7;
lControlPoints[16] = lControlPoint3;
lControlPoints[17] = lControlPoint2;
lControlPoints[18] = lControlPoint6;
lControlPoints[19] = lControlPoint7;
lControlPoints[20] = lControlPoint1;
lControlPoints[21] = lControlPoint0;
lControlPoints[22] = lControlPoint4;
lControlPoints[23] = lControlPoint5;
FbxGeometryElementNormal* lGeometryElementNormal= lMesh->CreateElementNormal();
lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect);
lGeometryElementNormal->GetDirectArray().Add(lNormalZPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalZPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalZPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalZPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalXPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalXPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalXPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalXPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalZNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalZNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalZNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalZNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalXNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalXNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalXNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalXNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalYPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalYPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalYPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalYPos);
lGeometryElementNormal->GetDirectArray().Add(lNormalYNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalYNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalYNeg);
lGeometryElementNormal->GetDirectArray().Add(lNormalYNeg);
int lPolygonVertices[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
FbxGeometryElementUV* lUVDiffuseElement = lMesh->CreateElementUV( "DiffuseUV");
FBX_ASSERT( lUVDiffuseElement != NULL);
lUVDiffuseElement->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
lUVDiffuseElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
FbxVector2 lVectors0(0, 0);
FbxVector2 lVectors1(1, 0);
FbxVector2 lVectors2(1, 1);
FbxVector2 lVectors3(0, 1);
lUVDiffuseElement->GetDirectArray().Add(lVectors0);
lUVDiffuseElement->GetDirectArray().Add(lVectors1);
lUVDiffuseElement->GetDirectArray().Add(lVectors2);
lUVDiffuseElement->GetDirectArray().Add(lVectors3);
lUVDiffuseElement->GetIndexArray().SetCount(24);
for(i = 0; i < 6; i++)
{
lMesh->BeginPolygon(-1, -1, -1, false);
for(j = 0; j < 4; j++)
{
lMesh->AddPolygon(lPolygonVertices[i*4 + j]);
lUVDiffuseElement->GetIndexArray().SetAt(i*4+j, j);
}
lMesh->EndPolygon ();
}
FbxNode* lNode = FbxNode::Create(pScene,pName);
lNode->SetNodeAttribute(lMesh);
lNode->SetShadingMode(FbxNode::eTextureShading);
lNode->LclScaling.Set(FbxVector4(0.3, 0.3, 0.3));
return lNode;
}
void CreateTexture(FbxScene* pScene)
{
gTexture = FbxFileTexture::Create(pScene,"Diffuse Texture");
FbxString lTexPath = gAppPath ? *gAppPath + "\\Crate.jpg" : "";
gTexture->SetFileName(lTexPath.Buffer());
gTexture->SetTextureUse(FbxTexture::eStandard);
gTexture->SetMappingType(FbxTexture::eUV);
gTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
gTexture->SetSwapUV(false);
gTexture->SetTranslation(0.0, 0.0);
gTexture->SetScale(1.0, 1.0);
gTexture->SetRotation(0.0, 0.0);
}
void CreateMaterial(FbxScene* pScene)
{
FbxString lMaterialName = "material";
FbxString lShadingName = "Phong";
FbxDouble3 lBlack(0.0, 0.0, 0.0);
FbxDouble3 lRed(1.0, 0.0, 0.0);
FbxDouble3 lDiffuseColor(0.75, 0.75, 0.0);
gMaterial = FbxSurfacePhong::Create(pScene, lMaterialName.Buffer());
gMaterial->Emissive .Set(lBlack);
gMaterial->Ambient .Set(lRed);
gMaterial->Diffuse .Set(lDiffuseColor);
gMaterial->TransparencyFactor .Set(40.5);
gMaterial->ShadingModel .Set(lShadingName);
gMaterial->Shininess .Set(0.5);
if (gTexture)
gMaterial->Diffuse.ConnectSrcObject(gTexture);
}
void AddMaterials(FbxMesh* pMesh)
{
FbxGeometryElementMaterial* lMaterialElement = pMesh->CreateElementMaterial();
lMaterialElement->SetMappingMode(FbxGeometryElement::eByPolygon);
lMaterialElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
FbxNode* lNode = pMesh->GetNode();
if(lNode == NULL)
return;
lNode->AddMaterial(gMaterial);
lMaterialElement->GetIndexArray().SetCount(6);
for(int i=0; i<6; ++i)
lMaterialElement->GetIndexArray().SetAt(i,0);
}
void SetInitialCubeData()
{
gCubeNumber = 1;
gCubeRotationAxis = 1;
gCubeXPos = 0.0;
gCubeYPos = 20.0;
gCubeZPos = 0.0;
}