#include <fbxsdk.h>
#include "../Common/Common.h"
#define SAMPLE_FILENAME "Instances.fbx"
#define SAMPLE_INSTANCE_COUNT 10
int gNbCubes = -1;
FbxDouble3 gRed(1.0, 0.0, 0.0);
FbxDouble3 gGreen(0.0, 1.0, 0.0);
FbxDouble3 gBlue(0.0, 0.0, 1.0);
FbxDouble3 gGray(0.5, 0.5, 0.5);
FbxDouble3 gWhite(1.0, 1.0, 1.0);
FbxSurfacePhong* gMatWhite;
FbxSurfacePhong* gMatGray;
FbxSurfacePhong* gMatRed;
FbxSurfacePhong* gMatGreen;
FbxSurfacePhong* gMatBlue;
bool CreateScene(FbxManager* pSdkManager, FbxScene* pScene);
FbxNode* CreateCube(FbxScene* pScene, const char* pName);
FbxNode* CreateCubeInstance(FbxScene* pScene, const char* pName, FbxMesh* pFirstCube);
FbxSurfacePhong* CreateMaterial(FbxScene* pScene, FbxDouble3 pColor);
FbxAnimCurve* CreateAnimCurve(FbxScene* pScene);
void AnimateCube(FbxNode* pCube, FbxAnimLayer* pAnimLayer, FbxAnimCurve* pAnimCurve, int pRotAxis);
int main(int argc, char** argv)
{
FbxManager* lSdkManager = NULL;
FbxScene* lScene = NULL;
bool lResult;
InitializeSdkObjects(lSdkManager, lScene);
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];
else if ( gNbCubes < 1 ) gNbCubes = atoi(argv[i]);
}
}
if( !lSampleFileName ) lSampleFileName = SAMPLE_FILENAME;
if( gNbCubes < 1 ) gNbCubes = SAMPLE_INSTANCE_COUNT;
lResult = CreateScene(lSdkManager, lScene);
if(lResult == false)
{
FBXSDK_printf("\n\nAn error occurred while creating the scene...\n");
DestroySdkObjects(lSdkManager, lResult);
return 0;
}
lResult = SaveScene(lSdkManager, lScene, lSampleFileName);
if(lResult == false)
{
FBXSDK_printf("\n\nAn error occurred while saving the scene...\n");
DestroySdkObjects(lSdkManager, lResult);
return 0;
}
DestroySdkObjects(lSdkManager, lResult);
return 0;
}
bool CreateScene(FbxManager* , FbxScene* pScene)
{
double lX = 0.0;
double lY = 20.0;
double lZ = 0.0;
gMatWhite = CreateMaterial(pScene, gWhite);
gMatGray = CreateMaterial(pScene, gGray);
gMatRed = CreateMaterial(pScene, gRed);
gMatGreen = CreateMaterial(pScene, gGreen);
gMatBlue = CreateMaterial(pScene, gBlue);
FbxMesh* lCubeMesh = NULL;
FbxNode* lCubeNode = NULL;
FbxAnimStack* lAnimStack = FbxAnimStack::Create(pScene, "Cube Animation Stack");
FbxAnimLayer* lAnimLayer = FbxAnimLayer::Create(pScene, "Base Layer");
lAnimStack->AddMember(lAnimLayer);
for (int i = 0; i < gNbCubes; i++)
{
FbxString lCubeName = "Cube ";
lCubeName += (i+1);
if (i == 0)
{
lCubeNode = CreateCube(pScene, lCubeName.Buffer());
lCubeMesh = lCubeNode->GetMesh();
}
else
{
lCubeNode = CreateCubeInstance(pScene, lCubeName.Buffer(), lCubeMesh);
}
lCubeNode->LclTranslation.Set(FbxVector4(lX, lY, lZ));
FbxAnimCurve* lAnimCurve = CreateAnimCurve(pScene);
AnimateCube(lCubeNode, lAnimLayer, lAnimCurve, i%3);
if (lX >= 0)
{
lX += 50;
}
else
{
lX -= 50;
}
lX *= -1.0;
lY += 30.0;
}
return true;
}
void AnimateCube(FbxNode* pCube, FbxAnimLayer* pAnimLayer, FbxAnimCurve* pAnimCurve, int pRotAxis)
{
FbxAnimCurveNode *lCurveNode = pCube->LclRotation.GetCurveNode(pAnimLayer, true);
if(pRotAxis == 0)
{
lCurveNode->ConnectToChannel(pAnimCurve, FBXSDK_CURVENODE_COMPONENT_X);
}
else if(pRotAxis == 1)
{
lCurveNode->ConnectToChannel(pAnimCurve, FBXSDK_CURVENODE_COMPONENT_Y);
}
else if(pRotAxis == 2)
{
lCurveNode->ConnectToChannel(pAnimCurve, FBXSDK_CURVENODE_COMPONENT_Z);
}
}
FbxNode* CreateCube(FbxScene* pScene, const 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;
FbxLayer* lLayer = lMesh->GetLayer(0);
if (lLayer == NULL)
{
lMesh->CreateLayer();
lLayer = lMesh->GetLayer(0);
}
FbxLayerElementNormal* lLayerElementNormal= FbxLayerElementNormal::Create(lMesh, "");
lLayerElementNormal->SetMappingMode(FbxLayerElement::eByControlPoint);
lLayerElementNormal->SetReferenceMode(FbxLayerElement::eDirect);
lLayerElementNormal->GetDirectArray().Add(lNormalZPos);
lLayerElementNormal->GetDirectArray().Add(lNormalZPos);
lLayerElementNormal->GetDirectArray().Add(lNormalZPos);
lLayerElementNormal->GetDirectArray().Add(lNormalZPos);
lLayerElementNormal->GetDirectArray().Add(lNormalXPos);
lLayerElementNormal->GetDirectArray().Add(lNormalXPos);
lLayerElementNormal->GetDirectArray().Add(lNormalXPos);
lLayerElementNormal->GetDirectArray().Add(lNormalXPos);
lLayerElementNormal->GetDirectArray().Add(lNormalZNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalZNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalZNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalZNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalXNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalXNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalXNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalXNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalYPos);
lLayerElementNormal->GetDirectArray().Add(lNormalYPos);
lLayerElementNormal->GetDirectArray().Add(lNormalYPos);
lLayerElementNormal->GetDirectArray().Add(lNormalYPos);
lLayerElementNormal->GetDirectArray().Add(lNormalYNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalYNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalYNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalYNeg);
lLayer->SetNormals(lLayerElementNormal);
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 };
FbxLayerElementUV* lUVDiffuseLayer = FbxLayerElementUV::Create(lMesh, "DiffuseUV");
lUVDiffuseLayer->SetMappingMode(FbxLayerElement::eByPolygonVertex);
lUVDiffuseLayer->SetReferenceMode(FbxLayerElement::eIndexToDirect);
lLayer->SetUVs(lUVDiffuseLayer, FbxLayerElement::eTextureDiffuse);
FbxVector2 lVectors0(0, 0);
FbxVector2 lVectors1(1, 0);
FbxVector2 lVectors2(1, 1);
FbxVector2 lVectors3(0, 1);
lUVDiffuseLayer->GetDirectArray().Add(lVectors0);
lUVDiffuseLayer->GetDirectArray().Add(lVectors1);
lUVDiffuseLayer->GetDirectArray().Add(lVectors2);
lUVDiffuseLayer->GetDirectArray().Add(lVectors3);
lUVDiffuseLayer->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]);
lUVDiffuseLayer->GetIndexArray().SetAt(i*4+j, j);
}
lMesh->EndPolygon ();
}
FbxLayerElementMaterial* lMaterialLayer = FbxLayerElementMaterial::Create(lMesh, "MaterialIndices");
lMaterialLayer->SetMappingMode(FbxLayerElement::eByPolygon);
lMaterialLayer->SetReferenceMode(FbxLayerElement::eIndexToDirect);
lLayer->SetMaterials(lMaterialLayer);
for (int i = 0; i < 6; i++)
{
lMaterialLayer->GetIndexArray().Add(i);
}
FbxNode* lNode = FbxNode::Create(pScene,pName);
lNode->SetNodeAttribute(lMesh);
lNode->SetShadingMode(FbxNode::eTextureShading);
lNode->AddMaterial(gMatRed);
lNode->AddMaterial(gMatGreen);
lNode->AddMaterial(gMatBlue);
lNode->AddMaterial(gMatRed);
lNode->AddMaterial(gMatGreen);
lNode->AddMaterial(gMatBlue);
lNode->LclScaling.Set(FbxVector4(0.3, 0.3, 0.3));
pScene->GetRootNode()->AddChild(lNode);
return lNode;
}
FbxNode* CreateCubeInstance(FbxScene* pScene, const char* pName, FbxMesh* pFirstCube)
{
FbxNode* lNode = FbxNode::Create(pScene,pName);
lNode->SetNodeAttribute(pFirstCube);
lNode->SetShadingMode(FbxNode::eTextureShading);
if (pFirstCube->GetNodeCount() % 2 == 0)
{
lNode->AddMaterial(gMatWhite);
lNode->AddMaterial(gMatWhite);
lNode->AddMaterial(gMatWhite);
lNode->AddMaterial(gMatGray);
lNode->AddMaterial(gMatGray);
lNode->AddMaterial(gMatGray);
}
else
{
lNode->AddMaterial(gMatRed);
lNode->AddMaterial(gMatGreen);
lNode->AddMaterial(gMatBlue);
lNode->AddMaterial(gMatRed);
lNode->AddMaterial(gMatGreen);
lNode->AddMaterial(gMatBlue);
}
lNode->LclScaling.Set(FbxVector4(0.3, 0.3, 0.3));
pScene->GetRootNode()->AddChild(lNode);
return lNode;
}
FbxSurfacePhong* CreateMaterial(FbxScene* pScene, FbxDouble3 pColor)
{
FbxSurfacePhong* lMaterial = FbxSurfacePhong::Create(pScene, "Polygon Material");
lMaterial->Diffuse.Set(pColor);
return lMaterial;
}
FbxAnimCurve* CreateAnimCurve(FbxScene* pScene)
{
FbxTime lTime;
int lKeyIndex = 0;
FbxAnimCurve* lAnimCurve = FbxAnimCurve::Create(pScene, "Cube Animation");
lAnimCurve->KeyModifyBegin();
lTime.SetSecondDouble(0.0);
lKeyIndex = lAnimCurve->KeyAdd(lTime);
lAnimCurve->KeySet(lKeyIndex, lTime, 0.0, FbxAnimCurveDef::eInterpolationLinear);
lTime.SetSecondDouble(20.0);
lKeyIndex = lAnimCurve->KeyAdd(lTime);
lAnimCurve->KeySet(lKeyIndex, lTime, -3600, FbxAnimCurveDef::eInterpolationLinear);
lAnimCurve->KeyModifyEnd();
return lAnimCurve;
}