#include <fbxsdk.h>
#include <fstream>
#include "../Common/Common.h"
#define SAMPLE_FILENAME "ProceduralTexture.fbx"
#define TEXTURE_FILENAME "a_texture.jpg"
#define FILENAME_PROP "Filename"
bool CreateSceneAndSaveFile(int argc, char** argv);
bool ReadFileAndDumpProceduralTextureBlobOnDisk(int argc, char** argv);
bool DumpProceduralTextureBlobOnDisk(KFbxScene* pScene);
bool CreateScene(KFbxScene* pScene);
KFbxNode* CreatePlane(KFbxScene* pScene, char* pName);
KFbxSurfacePhong* CreatePhongMaterial(KFbxScene* pScene, char* pName);
KFbxProceduralTexture* CreateProceduralTexture(KFbxScene* pScene, char* pName);
void MapPhong(KFbxSurfacePhong* pPhong, KFbxNode* pNode);
void MapProceduralTexure(KFbxProceduralTexture* pProcTex, KFbxNode* pNode);
int main(int argc, char** argv)
{
bool lResult;
lResult = CreateSceneAndSaveFile(argc, argv);
if(lResult == false)
{
return 1;
}
lResult = ReadFileAndDumpProceduralTextureBlobOnDisk(argc, argv);
if(lResult == false)
{
return 1;
}
return 0;
}
bool CreateSceneAndSaveFile(int argc, char** argv)
{
KFbxSdkManager* lSdkManager = NULL;
KFbxScene* lScene = NULL;
bool lResult;
InitializeSdkObjects(lSdkManager, lScene);
lResult = CreateScene(lScene);
if(lResult == false)
{
printf("\n\nAn error occurred while creating the scene...\n");
DestroySdkObjects(lSdkManager);
return false;
}
printf("Saving the file...\n");
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 false;
}
DestroySdkObjects(lSdkManager);
return true;
}
bool ReadFileAndDumpProceduralTextureBlobOnDisk(int argc, char** argv)
{
KFbxSdkManager* lSdkManager = NULL;
KFbxScene* lScene = NULL;
bool lResult;
InitializeSdkObjects(lSdkManager, lScene);
printf("Reading the FBX file...\n");
if(argc > 1)
{
lResult = LoadScene(lSdkManager, lScene, argv[1]);
}
else
{
lResult = LoadScene(lSdkManager, lScene, SAMPLE_FILENAME);
}
if(lResult == false)
{
printf("\n\nAn error occurred while loading the scene...\n");
DestroySdkObjects(lSdkManager);
return false;
}
lResult = DumpProceduralTextureBlobOnDisk(lScene);
if(lResult == false)
{
printf("\n\nAn error occurred while dumping procedural texture blobs on disk...\n");
DestroySdkObjects(lSdkManager);
return false;
}
DestroySdkObjects(lSdkManager);
return true;
}
bool DumpProceduralTextureBlobOnDisk(KFbxScene* pScene)
{
printf("Writing the blob on disk...\n");
int lNbProcTex = KFbxGetSrcCount<KFbxProceduralTexture>(pScene);
if (!lNbProcTex)
{
return true;
}
bool lWroteBlob = false;
KString lDirPath = KFbxGetCurrentDirectory() + "/Blobs/";
for(int lIndex = 0; lIndex < lNbProcTex; lIndex++)
{
KFbxProceduralTexture* lProcTex = KFbxGetSrc<KFbxProceduralTexture>(pScene, lIndex);
if(!lProcTex)
{
continue;
}
KFbxProperty lFilenameProp = lProcTex->GetRootProperty().Find(FILENAME_PROP);
if (!lFilenameProp.IsValid())
{
continue;
}
void* lBlobBegin = NULL;
size_t lBlobSize = 0;
KFbxBlob lBinaryBlob = lProcTex->GetBlob();
lBlobSize = lBinaryBlob.Size();
lBlobBegin = const_cast<void*>(lBinaryBlob.Access());
KString lFilename;
KFbxGet(lFilenameProp, lFilename);
KString lFilePath = lDirPath + KFbxExtractFileName(lFilename, false) + lIndex + "." + KFbxExtractFileExtension(lFilename);
bool lIsWritable = KFbxEnsureDirectoryExistance(lFilePath);
if (lIsWritable)
{
std::ofstream lDataStreamOut(lFilePath.Buffer(), std::ofstream::binary);
lDataStreamOut.write((const char *)lBlobBegin, lBlobSize);
lDataStreamOut.close();
lWroteBlob = true;
printf("Blob is written on disk! File: %s\n", lFilePath.Buffer());
}
}
return lWroteBlob;
}
bool CreateScene(KFbxScene* pScene)
{
printf("Creating the scene...\n");
KFbxNode* lPlane = CreatePlane(pScene, "Plane");
KFbxSurfacePhong* lPhong = CreatePhongMaterial(pScene, "Phong");
MapPhong(lPhong, lPlane);
KFbxProceduralTexture* lProcTex = CreateProceduralTexture(pScene, "ProcTex");
MapProceduralTexure(lProcTex, lPlane);
KFbxNode* lRootNode = pScene->GetRootNode();
lRootNode->AddChild(lPlane);
return true;
}
KFbxNode* CreatePlane(KFbxScene* pScene, char* pName)
{
KFbxMesh* lMesh = KFbxMesh::Create(pScene,pName);
KFbxVector4 lControlPoint0(-50, 0, 50);
KFbxVector4 lControlPoint1(50, 0, 50);
KFbxVector4 lControlPoint2(50, 100, 50);
KFbxVector4 lControlPoint3(-50, 100, 50);
KFbxVector4 lNormal(0, 0, 1);
lMesh->InitControlPoints(4);
KFbxVector4* lControlPoints = lMesh->GetControlPoints();
lControlPoints[0] = lControlPoint0;
lControlPoints[1] = lControlPoint1;
lControlPoints[2] = lControlPoint2;
lControlPoints[3] = lControlPoint3;
KFbxGeometryElementNormal* lGeometryElementNormal = lMesh->CreateElementNormal();;
lGeometryElementNormal->SetMappingMode(KFbxGeometryElement::eBY_CONTROL_POINT);
lGeometryElementNormal->SetReferenceMode(KFbxGeometryElement::eDIRECT);
lGeometryElementNormal->GetDirectArray().Add(lNormal);
lGeometryElementNormal->GetDirectArray().Add(lNormal);
lGeometryElementNormal->GetDirectArray().Add(lNormal);
lGeometryElementNormal->GetDirectArray().Add(lNormal);
int lPolygonVertices[] = { 0, 1, 2, 3 };
KFbxGeometryElementUV* lUVDiffuseElement = lMesh->CreateElementUV( "DiffuseUV");
K_ASSERT( lUVDiffuseElement != NULL);
lUVDiffuseElement->SetMappingMode(KFbxGeometryElement::eBY_POLYGON_VERTEX);
lUVDiffuseElement->SetReferenceMode(KFbxGeometryElement::eINDEX_TO_DIRECT);
KFbxVector2 lVectors0(0, 0);
KFbxVector2 lVectors1(1, 0);
KFbxVector2 lVectors2(1, 1);
KFbxVector2 lVectors3(0, 1);
lUVDiffuseElement->GetDirectArray().Add(lVectors0);
lUVDiffuseElement->GetDirectArray().Add(lVectors1);
lUVDiffuseElement->GetDirectArray().Add(lVectors2);
lUVDiffuseElement->GetDirectArray().Add(lVectors3);
lUVDiffuseElement->GetIndexArray().SetCount(4);
lMesh->BeginPolygon(-1, -1, false);
for (int j = 0; j < 4; j++)
{
lMesh->AddPolygon(lPolygonVertices[j]);
lUVDiffuseElement->GetIndexArray().SetAt(j, j);
}
lMesh->EndPolygon();
KFbxNode* lNode = KFbxNode::Create(pScene,pName);
lNode->SetNodeAttribute(lMesh);
return lNode;
}
KFbxProceduralTexture* CreateProceduralTexture(KFbxScene* pScene, char* pName)
{
KFbxProceduralTexture* lProceduralTexture = KFbxProceduralTexture::Create(pScene, pName);
KString lFilename = TEXTURE_FILENAME;
bool lIsReadable = KFbxFileExist(lFilename);
if (lIsReadable)
{
KFbxBlob lBinaryBlob;
std::ifstream lDataStreamIn(lFilename, std::ifstream::binary);
char* lBlobBegin = (char *)FbxSdkMalloc(4096);
char* lBlobEnd = lBlobBegin;
long long lBlobSize = 0;
long long lBlobPointerSize = 4096;
std::streamsize lNbRead = 0;
while(!lDataStreamIn.eof())
{
lBlobEnd = lBlobBegin + lBlobSize;
lDataStreamIn.read(lBlobEnd, 4096);
lNbRead = lDataStreamIn.gcount();
lBlobPointerSize += 4096;
lBlobBegin = (char *)FbxSdkRealloc(lBlobBegin, size_t(lBlobPointerSize));
lBlobSize += lNbRead;
}
lDataStreamIn.close();
lBinaryBlob.Assign(lBlobBegin, (int)lBlobSize);
FbxSdkFree(lBlobBegin);
lProceduralTexture->SetBlob(lBinaryBlob);
}
KFbxProperty lFilenameProp = KFbxProperty::Create( lProceduralTexture->GetRootProperty(), DTString, FILENAME_PROP);
if (lFilenameProp.IsValid())
{
KFbxSet<fbxString>(lFilenameProp, TEXTURE_FILENAME);
}
return lProceduralTexture;
}
KFbxSurfacePhong* CreatePhongMaterial(KFbxScene* pScene, char* pName)
{
KFbxSurfacePhong* lPhong = KFbxSurfacePhong::Create(pScene, pName);
return lPhong;
}
void MapProceduralTexure(KFbxProceduralTexture* pProceduralTexture, KFbxNode* pNode)
{
pNode->SetShadingMode(KFbxNode::eTEXTURE_SHADING);
KFbxSurfacePhong* lMaterial = pNode->GetSrcObject<KFbxSurfacePhong>(0);
if (lMaterial)
{
lMaterial->Diffuse.ConnectSrcObject(pProceduralTexture);
}
}
void MapPhong(KFbxSurfacePhong* pPhong, KFbxNode* pNode)
{
KFbxMesh* lMesh = pNode->GetMesh();
KFbxGeometryElementMaterial* lGeometryElementMaterial = lMesh->CreateElementMaterial();
lGeometryElementMaterial->SetMappingMode(KFbxGeometryElement::eALL_SAME);
lGeometryElementMaterial->SetReferenceMode(KFbxGeometryElement::eDIRECT);
pNode->AddMaterial(pPhong);
}