#include "SceneContext.h"
#include "SceneCache.h"
#include "SetCamera.h"
#include "DrawScene.h"
#include "DrawText.h"
#include "targa.h"
#include "../Common/Common.h"
namespace
{
const char * SAMPLE_FILENAME = "humanoid.fbx";
const int LEFT_BUTTON = 0;
const int MIDDLE_BUTTON = 1;
const int RIGHT_BUTTON = 2;
const int BUTTON_DOWN = 0;
const int BUTTON_UP = 1;
{
if (pNode)
{
{
{
}
}
for (int i = 0; i < lCount; i++)
{
FillCameraArrayRecursive(pNode->
GetChild(i), pCameraArray);
}
}
}
{
FillCameraArrayRecursive(pScene->
GetRootNode(), pCameraArray);
}
{
for (int i=0; i < lPoseCount; ++i)
{
}
}
{
for (int lIndex=0; lIndex<lNodeCount; lIndex++)
{
{
lVertexCacheDeformerCount = lVertexCacheDeformerCount > 0 ? 1 : 0;
for (i=0; i<lVertexCacheDeformerCount; ++i )
{
if( !lDeformer ) continue;
if( !lCache ) continue;
{
{
#if 0
{
FbxString lTheErrorIs = lCache->GetStaus().GetErrorString();
}
#endif
}
{
{
FbxString lTheErrorIs = lStatus.GetErrorString();
}
}
{
FbxString lTheErrorIs = lStatus.GetErrorString();
}
else
{
{
if(lChannel_Start < pCache_Start) pCache_Start = lChannel_Start;
if(lChannel_Stop > pCache_Stop) pCache_Stop = lChannel_Stop;
}
}
}
}
}
}
}
bool LoadTextureFromFile(
const FbxString & pFilePath,
unsigned int & pTextureObject)
{
{
tga_image lTGAImage;
if (tga_read(&lTGAImage, pFilePath.
Buffer()) == TGA_NOERR)
{
if (tga_is_right_to_left(&lTGAImage))
tga_flip_horiz(&lTGAImage);
if (tga_is_top_to_bottom(&lTGAImage))
tga_flip_vert(&lTGAImage);
tga_convert_depth(&lTGAImage, 24);
glGenTextures(1, &pTextureObject);
glBindTexture(GL_TEXTURE_2D, pTextureObject);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D, 0, 3, lTGAImage.width, lTGAImage.height, 0, GL_BGR,
GL_UNSIGNED_BYTE, lTGAImage.image_data);
glBindTexture(GL_TEXTURE_2D, 0);
tga_free_buffers(&lTGAImage);
return true;
}
}
return false;
}
{
for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex)
{
{
if (lMaterialCache->Initialize(lMaterial))
{
}
}
}
if (lNodeAttribute)
{
{
{
if (lMeshCache->Initialize(lMesh))
{
}
}
}
{
{
if (lLightCache->Initialize(lLight, pAnimLayer))
{
}
}
}
}
for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex)
{
LoadCacheRecursive(pNode->
GetChild(lChildIndex), pAnimLayer, pSupportVBO);
}
}
void UnloadCacheRecursive(
FbxNode * pNode)
{
for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex)
{
{
MaterialCache * lMaterialCache =
static_cast<MaterialCache *
>(lMaterial->
GetUserDataPtr());
delete lMaterialCache;
}
}
if (lNodeAttribute)
{
{
{
VBOMesh * lMeshCache =
static_cast<VBOMesh *
>(lMesh->
GetUserDataPtr());
delete lMeshCache;
}
}
{
{
LightCache * lLightCache =
static_cast<LightCache *
>(lLight->
GetUserDataPtr());
delete lLightCache;
}
}
}
for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex)
{
UnloadCacheRecursive(pNode->
GetChild(lChildIndex));
}
}
void LoadCacheRecursive(
FbxScene * pScene,
FbxAnimLayer * pAnimLayer,
const char * pFbxFileName,
bool pSupportVBO)
{
for (int lTextureIndex = 0; lTextureIndex < lTextureCount; ++lTextureIndex)
{
{
{
FBXSDK_printf(
"Only TGA textures are supported now: %s\n", lFileName.
Buffer());
continue;
}
GLuint lTextureObject = 0;
bool lStatus = LoadTextureFromFile(lFileName, lTextureObject);
if (!lStatus)
{
lStatus = LoadTextureFromFile(lResolvedFileName, lTextureObject);
}
if (!lStatus)
{
lStatus = LoadTextureFromFile(lResolvedFileName, lTextureObject);
}
if (!lStatus)
{
FBXSDK_printf(
"Failed to load texture file: %s\n", lFileName.
Buffer());
continue;
}
if (lStatus)
{
GLuint * lTextureName = new GLuint(lTextureObject);
}
}
}
LoadCacheRecursive(pScene->
GetRootNode(), pAnimLayer, pSupportVBO);
}
void UnloadCacheRecursive(
FbxScene * pScene)
{
for (int lTextureIndex = 0; lTextureIndex < lTextureCount; ++lTextureIndex)
{
{
GLuint * lTextureName =
static_cast<GLuint *
>(lFileTexture->
GetUserDataPtr());
glDeleteTextures(1, lTextureName);
delete lTextureName;
}
}
}
}
bool InitializeOpenGL()
{
GLenum lError = glewInit();
if (lError != GLEW_OK)
{
FBXSDK_printf("GLEW Error: %s\n", glewGetErrorString(lError));
return false;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glClearColor(0.0, 0.0, 0.0, 0.0);
if (!GLEW_VERSION_1_5)
{
FBXSDK_printf("The OpenGL version should be at least 1.5 to display shaded scene!\n");
return false;
}
return true;
}
SceneContext::SceneContext(const char * pFileName, int pWindowWidth, int pWindowHeight, bool pSupportVBO)
: mFileName(pFileName), mStatus(UNLOADED),
mPoseIndex(-1), mCameraStatus(CAMERA_NOTHING), mPause(false), mShadingMode(SHADING_MODE_SHADED),
mSupportVBO(pSupportVBO), mCameraZoomMode(ZOOM_FOCAL_LENGTH),
mWindowWidth(pWindowWidth), mWindowHeight(pWindowHeight), mDrawText(new DrawText)
{
mFileName = SAMPLE_FILENAME;
InitializeSdkObjects(mSdkManager, mScene);
if (mSdkManager)
{
int lFileFormat = -1;
if (!mSdkManager->GetIOPluginRegistry()->DetectReaderFileFormat(mFileName, lFileFormat) )
{
lFileFormat = mSdkManager->GetIOPluginRegistry()->FindReaderIDByDescription( "FBX binary (*.fbx)" );;
}
if(mImporter->Initialize(mFileName, lFileFormat) == true)
{
mWindowMessage = "Importing file ";
mWindowMessage += mFileName;
mWindowMessage += "\nPlease wait!";
mStatus = MUST_BE_LOADED;
}
else
{
mWindowMessage = "Unable to open file ";
mWindowMessage += mFileName;
mWindowMessage += "\nError reported: ";
mWindowMessage += mImporter->GetStatus().GetErrorString();
mWindowMessage += "\nEsc to exit";
}
}
else
{
mWindowMessage = "Unable to create the FBX SDK manager";
mWindowMessage += "\nEsc to exit";
}
}
SceneContext::~SceneContext()
{
delete mDrawText;
if (mScene)
{
UnloadCacheRecursive(mScene);
}
DestroySdkObjects(mSdkManager, true);
}
bool SceneContext::LoadFile()
{
bool lResult = false;
if (mStatus == MUST_BE_LOADED)
{
if (mImporter->Import(mScene) == true)
{
mStatus = MUST_BE_REFRESHED;
FbxAxisSystem SceneAxisSystem = mScene->GetGlobalSettings().GetAxisSystem();
if( SceneAxisSystem != OurAxisSystem )
{
}
FbxSystemUnit SceneSystemUnit = mScene->GetGlobalSettings().GetSystemUnit();
{
}
mScene->FillAnimStackNameArray(mAnimStackNameArray);
FillCameraArray(mScene, mCameraArray);
LoadCacheRecursive(mScene, mCurrentAnimLayer, mFileName, mSupportVBO);
PreparePointCacheData(mScene, mCache_Start, mCache_Stop);
FillPoseArray(mScene, mPoseArray);
mWindowMessage = "File ";
mWindowMessage += mFileName;
mWindowMessage += "\nClick on the right mouse button to enter menu.";
mWindowMessage += "\nEsc to exit.";
mFrameTime.SetTime(0, 0, 0, 1, 0, mScene->GetGlobalSettings().GetTimeMode());
FBXSDK_printf("Play/Pause Animation: Space Bar.\n");
FBXSDK_printf("Camera Rotate: Left Mouse Button.\n");
FBXSDK_printf("Camera Pan: Left Mouse Button + Middle Mouse Button.\n");
FBXSDK_printf("Camera Zoom: Middle Mouse Button.\n");
lResult = true;
}
else
{
mStatus = UNLOADED;
mWindowMessage = "Unable to import file ";
mWindowMessage += mFileName;
mWindowMessage += "\nError reported: ";
mWindowMessage += mImporter->GetStatus().GetErrorString();
}
mImporter->Destroy();
}
return lResult;
}
bool SceneContext::SetCurrentAnimStack(int pIndex)
{
const int lAnimStackCount = mAnimStackNameArray.GetCount();
if (!lAnimStackCount || pIndex >= lAnimStackCount)
{
return false;
}
if (lCurrentAnimationStack ==
NULL)
{
return false;
}
mScene->SetCurrentAnimationStack(lCurrentAnimationStack);
FbxTakeInfo* lCurrentTakeInfo = mScene->GetTakeInfo(*(mAnimStackNameArray[pIndex]));
if (lCurrentTakeInfo)
{
}
else
{
mScene->GetGlobalSettings().GetTimelineDefaultTimeSpan(lTimeLineTimeSpan);
mStop = lTimeLineTimeSpan.
GetStop();
}
if(mCache_Start < mStart)
mStart = mCache_Start;
if(mCache_Stop > mStop)
mStop = mCache_Stop;
mCurrentTime = mStart;
mStatus = MUST_BE_REFRESHED;
return true;
}
bool SceneContext::SetCurrentCamera(const char * pCameraName)
{
if (!pCameraName)
{
return false;
}
mStatus = MUST_BE_REFRESHED;
return true;
}
bool SceneContext::SetCurrentPoseIndex(int pPoseIndex)
{
mPoseIndex = pPoseIndex;
mStatus = MUST_BE_REFRESHED;
return true;
}
void SceneContext::OnTimerClick() const
{
if (mStop > mStart && !mPause)
{
mStatus = MUST_BE_REFRESHED;
mCurrentTime += mFrameTime;
if (mCurrentTime > mStop)
{
mCurrentTime = mStart;
}
}
else
{
mStatus = REFRESHED;
}
}
bool SceneContext::OnDisplay()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (mStatus != UNLOADED && mStatus != MUST_BE_LOADED)
{
glPushAttrib(GL_ENABLE_BIT);
glPushAttrib(GL_LIGHTING_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
SetCamera(mScene, mCurrentTime, mCurrentAnimLayer, mCameraArray,
mWindowWidth, mWindowHeight);
if (mPoseIndex != -1)
{
lPose = mScene->GetPose(mPoseIndex);
}
if (mSelectedNode)
{
InitializeLights(mScene, mCurrentTime, lPose);
DrawNodeRecursive(mSelectedNode, mCurrentTime, mCurrentAnimLayer, lDummyGlobalPosition, lPose, mShadingMode);
DisplayGrid(lDummyGlobalPosition);
}
else
{
InitializeLights(mScene, mCurrentTime, lPose);
DrawNodeRecursive(mScene->GetRootNode(), mCurrentTime, mCurrentAnimLayer, lDummyGlobalPosition, lPose, mShadingMode);
DisplayGrid(lDummyGlobalPosition);
}
glPopAttrib();
glPopAttrib();
}
DisplayWindowMessage();
return true;
}
void SceneContext::OnReshape(int pWidth, int pHeight)
{
glViewport(0, 0, (GLsizei)pWidth, (GLsizei)pHeight);
mWindowWidth = pWidth;
mWindowHeight = pHeight;
}
void SceneContext::OnKeyboard(unsigned char pKey)
{
if (pKey == 43 || pKey == 61)
{
FbxCamera* lCamera = GetCurrentCamera(mScene);
if(lCamera)
{
CameraZoom(mScene, 10, mCameraZoomMode);
mStatus = MUST_BE_REFRESHED;
}
}
if (pKey == 45 || pKey == 95)
{
FbxCamera* lCamera = GetCurrentCamera(mScene);
if(lCamera)
{
CameraZoom(mScene, 0 - 10, mCameraZoomMode);
mStatus = MUST_BE_REFRESHED;
}
}
if (pKey == 'N' || pKey == 'n')
{
}
if (pKey == ' ')
{
SetPause(!GetPause());
}
}
void SceneContext::OnMouse(int pButton, int pState, int pX, int pY)
{
FbxCamera* lCamera = GetCurrentCamera(mScene);
if (lCamera)
{
}
mLastX = pX;
mLastY = pY;
switch (pButton)
{
case LEFT_BUTTON:
switch (pState)
{
case BUTTON_DOWN:
if (mCameraStatus == CAMERA_ZOOM)
{
mCameraStatus = CAMERA_PAN;
}
else
{
mCameraStatus = CAMERA_ORBIT;
}
break;
default:
if (mCameraStatus == CAMERA_PAN)
{
mCameraStatus = CAMERA_ZOOM;
}
else
{
mCameraStatus = CAMERA_NOTHING;
}
break;
}
break;
case MIDDLE_BUTTON:
switch (pState)
{
case BUTTON_DOWN:
if (mCameraStatus == CAMERA_ORBIT)
{
mCameraStatus = CAMERA_PAN;
}
else
{
mCameraStatus = CAMERA_ZOOM;
}
break;
default:
if (mCameraStatus == CAMERA_PAN)
{
mCameraStatus = CAMERA_ORBIT;
}
else
{
mCameraStatus = CAMERA_NOTHING;
}
break;
}
break;
}
}
void SceneContext::OnMouseMotion(int pX, int pY)
{
int motion;
switch (mCameraStatus)
{
default:
break;
case CAMERA_ORBIT:
CameraOrbit(mScene, mCamPosition, mRoll, pX-mLastX, mLastY-pY);
mStatus = MUST_BE_REFRESHED;
break;
case CAMERA_ZOOM:
motion = mLastY-pY;
CameraZoom(mScene, motion, mCameraZoomMode);
mLastY = pY;
mStatus = MUST_BE_REFRESHED;
break;
case CAMERA_PAN:
CameraPan(mScene, mCamPosition, mCamCenter, mRoll, pX-mLastX, mLastY-pY);
mStatus = MUST_BE_REFRESHED;
break;
}
}
void SceneContext::SetSelectedNode(
FbxNode * pSelectedNode)
{
mSelectedNode = pSelectedNode;
mStatus = MUST_BE_REFRESHED;
}
void SceneContext::SetShadingMode(ShadingMode pMode)
{
mShadingMode = pMode;
mStatus = MUST_BE_REFRESHED;
}
void SceneContext::DisplayWindowMessage()
{
glColor3f(1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, mWindowWidth, 0, mWindowHeight);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
const float lX = 5;
const float lY = static_cast<float>(mWindowHeight) - 20;
glTranslatef(lX, lY, 0);
mDrawText->SetPointSize(15.f);
mDrawText->Display(mWindowMessage.Buffer());
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
void SceneContext::DisplayGrid(
const FbxAMatrix & pTransform)
{
glPushMatrix();
glMultMatrixd(pTransform);
glColor3f(0.3f, 0.3f, 0.3f);
glLineWidth(1.0);
const int hw = 500;
const int step = 20;
const int bigstep = 100;
int i;
for (i = -hw; i <= hw; i+=step) {
if (i % bigstep == 0) {
glLineWidth(2.0);
} else {
glLineWidth(1.0);
}
glBegin(GL_LINES);
glVertex3i(i,0,-hw);
glVertex3i(i,0,hw);
glEnd();
glBegin(GL_LINES);
glVertex3i(-hw,0,i);
glVertex3i(hw,0,i);
glEnd();
}
const GLfloat zoffset = -2.f;
const GLfloat xoffset = 1.f;
mDrawText->SetPointSize(4.f);
for (i = -hw; i <= hw; i+=bigstep)
{
int lCount;
if (i == 0) {
scoord = "0";
lCount = (int)scoord.
GetLen();
glPushMatrix();
glVertex3f(i+xoffset,0,zoffset);
glRotatef(-90,1,0,0);
mDrawText->Display(scoord.
Buffer());
glPopMatrix();
continue;
}
scoord = "X: ";
scoord += i;
lCount = (int)scoord.
GetLen();
glPushMatrix();
glTranslatef(i+xoffset,0,zoffset);
glRotatef(-90,1,0,0);
mDrawText->Display(scoord.
Buffer());
glPopMatrix();
scoord = "Z: ";
scoord += i;
lCount = (int)scoord.
GetLen();
glPushMatrix();
glTranslatef(xoffset,0,i+zoffset);
glRotatef(-90,1,0,0);
mDrawText->Display(scoord.
Buffer());
glPopMatrix();
}
glPopMatrix();
}
void SceneContext::SetZoomMode( CameraZoomMode pZoomMode)
{
if( pZoomMode == ZOOM_POSITION)
{
mCameraZoomMode = ZOOM_POSITION;
}
else
{
mCameraZoomMode = ZOOM_FOCAL_LENGTH;
}
}