#include "DrawScene.h"
#include "SceneCache.h"
#include "GetPosition.h"
void DrawNode(FbxNode* pNode,
FbxTime& lTime,
FbxAnimLayer * pAnimLayer,
FbxAMatrix& pParentGlobalPosition,
FbxAMatrix& pGlobalPosition,
FbxPose* pPose,
ShadingMode pShadingMode);
void DrawMarker(FbxAMatrix& pGlobalPosition);
void DrawSkeleton(FbxNode* pNode,
FbxAMatrix& pParentGlobalPosition,
FbxAMatrix& pGlobalPosition);
void DrawMesh(FbxNode* pNode, FbxTime& pTime, FbxAnimLayer* pAnimLayer,
FbxAMatrix& pGlobalPosition, FbxPose* pPose, ShadingMode pShadingMode);
void ComputeShapeDeformation(FbxMesh* pMesh,
FbxTime& pTime,
FbxAnimLayer * pAnimLayer,
FbxVector4* pVertexArray);
void ComputeClusterDeformation(FbxAMatrix& pGlobalPosition,
FbxMesh* pMesh,
FbxCluster* pCluster,
FbxAMatrix& pVertexTransformMatrix,
FbxTime pTime,
FbxPose* pPose);
void ComputeLinearDeformation(FbxAMatrix& pGlobalPosition,
FbxMesh* pMesh,
FbxTime& pTime,
FbxVector4* pVertexArray,
FbxPose* pPose);
void ComputeDualQuaternionDeformation(FbxAMatrix& pGlobalPosition,
FbxMesh* pMesh,
FbxTime& pTime,
FbxVector4* pVertexArray,
FbxPose* pPose);
void ComputeSkinDeformation(FbxAMatrix& pGlobalPosition,
FbxMesh* pMesh,
FbxTime& pTime,
FbxVector4* pVertexArray,
FbxPose* pPose);
void ReadVertexCacheData(FbxMesh* pMesh,
FbxTime& pTime,
FbxVector4* pVertexArray);
void DrawCamera(FbxNode* pNode,
FbxTime& pTime,
FbxAnimLayer* pAnimLayer,
FbxAMatrix& pGlobalPosition);
void DrawLight(const FbxNode* pNode, const FbxTime& pTime, const FbxAMatrix& pGlobalPosition);
void DrawNull(FbxAMatrix& pGlobalPosition);
void MatrixScale(FbxAMatrix& pMatrix, double pValue);
void MatrixAddToDiagonal(FbxAMatrix& pMatrix, double pValue);
void MatrixAdd(FbxAMatrix& pDstMatrix, FbxAMatrix& pSrcMatrix);
void InitializeLights(const FbxScene* pScene, const FbxTime & pTime, FbxPose* pPose)
{
LightCache::IntializeEnvironment(pScene->GetGlobalSettings().GetAmbientColor());
const int lLightCount = pScene->GetSrcObjectCount<FbxLight>();
for (int lLightIndex = 0; lLightIndex < lLightCount; ++lLightIndex)
{
FbxLight * lLight = pScene->GetSrcObject<FbxLight>(lLightIndex);
FbxNode * lNode = lLight->GetNode();
if (lNode)
{
FbxAMatrix lGlobalPosition = GetGlobalPosition(lNode, pTime, pPose);
FbxAMatrix lGeometryOffset = GetGeometry(lNode);
FbxAMatrix lGlobalOffPosition = lGlobalPosition * lGeometryOffset;
DrawLight(lNode, pTime, lGlobalOffPosition);
}
}
}
void DrawNodeRecursive(FbxNode* pNode, FbxTime& pTime, FbxAnimLayer* pAnimLayer,
FbxAMatrix& pParentGlobalPosition, FbxPose* pPose,
ShadingMode pShadingMode)
{
FbxAMatrix lGlobalPosition = GetGlobalPosition(pNode, pTime, pPose, &pParentGlobalPosition);
if (pNode->GetNodeAttribute())
{
FbxAMatrix lGeometryOffset = GetGeometry(pNode);
FbxAMatrix lGlobalOffPosition = lGlobalPosition * lGeometryOffset;
DrawNode(pNode, pTime, pAnimLayer, pParentGlobalPosition, lGlobalOffPosition, pPose, pShadingMode);
}
const int lChildCount = pNode->GetChildCount();
for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex)
{
DrawNodeRecursive(pNode->GetChild(lChildIndex), pTime, pAnimLayer, lGlobalPosition, pPose, pShadingMode);
}
}
void DrawNode(FbxNode* pNode,
FbxTime& pTime,
FbxAnimLayer* pAnimLayer,
FbxAMatrix& pParentGlobalPosition,
FbxAMatrix& pGlobalPosition,
FbxPose* pPose, ShadingMode pShadingMode)
{
FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute();
if (lNodeAttribute)
{
if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMarker)
{
DrawMarker(pGlobalPosition);
}
else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton)
{
DrawSkeleton(pNode, pParentGlobalPosition, pGlobalPosition);
}
else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh)
{
DrawMesh(pNode, pTime, pAnimLayer, pGlobalPosition, pPose, pShadingMode);
}
else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eCamera)
{
DrawCamera(pNode, pTime, pAnimLayer, pGlobalPosition);
}
else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eNull)
{
DrawNull(pGlobalPosition);
}
}
else
{
DrawNull(pGlobalPosition);
}
}
void DrawMarker(FbxAMatrix& pGlobalPosition)
{
GlDrawMarker(pGlobalPosition);
}
void DrawSkeleton(FbxNode* pNode, FbxAMatrix& pParentGlobalPosition, FbxAMatrix& pGlobalPosition)
{
FbxSkeleton* lSkeleton = (FbxSkeleton*) pNode->GetNodeAttribute();
if (lSkeleton->GetSkeletonType() == FbxSkeleton::eLimbNode &&
pNode->GetParent() &&
pNode->GetParent()->GetNodeAttribute() &&
pNode->GetParent()->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eSkeleton)
{
GlDrawLimbNode(pParentGlobalPosition, pGlobalPosition);
}
}
void DrawMesh(FbxNode* pNode, FbxTime& pTime, FbxAnimLayer* pAnimLayer,
FbxAMatrix& pGlobalPosition, FbxPose* pPose, ShadingMode pShadingMode)
{
FbxMesh* lMesh = pNode->GetMesh();
const int lVertexCount = lMesh->GetControlPointsCount();
if (lVertexCount == 0)
{
return;
}
const VBOMesh * lMeshCache = static_cast<const VBOMesh *>(lMesh->GetUserDataPtr());
const bool lHasVertexCache = lMesh->GetDeformerCount(FbxDeformer::eVertexCache) &&
(static_cast<FbxVertexCacheDeformer*>(lMesh->GetDeformer(0, FbxDeformer::eVertexCache)))->IsActive();
const bool lHasShape = lMesh->GetShapeCount() > 0;
const bool lHasSkin = lMesh->GetDeformerCount(FbxDeformer::eSkin) > 0;
const bool lHasDeformation = lHasVertexCache || lHasShape || lHasSkin;
FbxVector4* lVertexArray = NULL;
if (!lMeshCache || lHasDeformation)
{
lVertexArray = new FbxVector4[lVertexCount];
memcpy(lVertexArray, lMesh->GetControlPoints(), lVertexCount * sizeof(FbxVector4));
}
if (lHasDeformation)
{
if (lHasVertexCache)
{
ReadVertexCacheData(lMesh, pTime, lVertexArray);
}
else
{
if (lHasShape)
{
ComputeShapeDeformation(lMesh, pTime, pAnimLayer, lVertexArray);
}
const int lSkinCount = lMesh->GetDeformerCount(FbxDeformer::eSkin);
int lClusterCount = 0;
for (int lSkinIndex = 0; lSkinIndex < lSkinCount; ++lSkinIndex)
{
lClusterCount += ((FbxSkin *)(lMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin)))->GetClusterCount();
}
if (lClusterCount)
{
ComputeSkinDeformation(pGlobalPosition, lMesh, pTime, lVertexArray, pPose);
}
}
if (lMeshCache)
lMeshCache->UpdateVertexPosition(lMesh, lVertexArray);
}
glPushMatrix();
glMultMatrixd((const double*)pGlobalPosition);
if (lMeshCache)
{
lMeshCache->BeginDraw(pShadingMode);
const int lSubMeshCount = lMeshCache->GetSubMeshCount();
for (int lIndex = 0; lIndex < lSubMeshCount; ++lIndex)
{
if (pShadingMode == SHADING_MODE_SHADED)
{
const FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lIndex);
if (lMaterial)
{
const MaterialCache * lMaterialCache = static_cast<const MaterialCache *>(lMaterial->GetUserDataPtr());
if (lMaterialCache)
{
lMaterialCache->SetCurrentMaterial();
}
}
else
{
MaterialCache::SetDefaultMaterial();
}
}
lMeshCache->Draw(lIndex, pShadingMode);
}
lMeshCache->EndDraw();
}
else
{
glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
const int lPolygonCount = lMesh->GetPolygonCount();
for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; lPolygonIndex++)
{
const int lVerticeCount = lMesh->GetPolygonSize(lPolygonIndex);
glBegin(GL_LINE_LOOP);
for (int lVerticeIndex = 0; lVerticeIndex < lVerticeCount; lVerticeIndex++)
{
glVertex3dv((GLdouble *)lVertexArray[lMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex)]);
}
glEnd();
}
}
glPopMatrix();
delete [] lVertexArray;
}
void ComputeShapeDeformation(FbxMesh* pMesh, FbxTime& pTime, FbxAnimLayer * pAnimLayer, FbxVector4* pVertexArray)
{
int lVertexCount = pMesh->GetControlPointsCount();
FbxVector4* lSrcVertexArray = pVertexArray;
FbxVector4* lDstVertexArray = new FbxVector4[lVertexCount];
memcpy(lDstVertexArray, pVertexArray, lVertexCount * sizeof(FbxVector4));
int lBlendShapeDeformerCount = pMesh->GetDeformerCount(FbxDeformer::eBlendShape);
for(int lBlendShapeIndex = 0; lBlendShapeIndex<lBlendShapeDeformerCount; ++lBlendShapeIndex)
{
FbxBlendShape* lBlendShape = (FbxBlendShape*)pMesh->GetDeformer(lBlendShapeIndex, FbxDeformer::eBlendShape);
int lBlendShapeChannelCount = lBlendShape->GetBlendShapeChannelCount();
for(int lChannelIndex = 0; lChannelIndex<lBlendShapeChannelCount; ++lChannelIndex)
{
FbxBlendShapeChannel* lChannel = lBlendShape->GetBlendShapeChannel(lChannelIndex);
if(lChannel)
{
FbxAnimCurve* lFCurve = pMesh->GetShapeChannel(lBlendShapeIndex, lChannelIndex, pAnimLayer);
if (!lFCurve) continue;
double lWeight = lFCurve->Evaluate(pTime);
int lShapeCount = lChannel->GetTargetShapeCount();
double* lFullWeights = lChannel->GetTargetShapeFullWeights();
int lStartIndex = -1;
int lEndIndex = -1;
for(int lShapeIndex = 0; lShapeIndex<lShapeCount; ++lShapeIndex)
{
if(lWeight > 0 && lWeight <= lFullWeights[0])
{
lEndIndex = 0;
break;
}
if(lWeight > lFullWeights[lShapeIndex] && lWeight < lFullWeights[lShapeIndex+1])
{
lStartIndex = lShapeIndex;
lEndIndex = lShapeIndex + 1;
break;
}
}
FbxShape* lStartShape = NULL;
FbxShape* lEndShape = NULL;
if(lStartIndex > -1)
{
lStartShape = lChannel->GetTargetShape(lStartIndex);
}
if(lEndIndex > -1)
{
lEndShape = lChannel->GetTargetShape(lEndIndex);
}
if(lStartIndex == -1 && lEndShape)
{
double lEndWeight = lFullWeights[0];
lWeight = (lWeight/lEndWeight) * 100;
memcpy(lDstVertexArray, lSrcVertexArray, lVertexCount * sizeof(FbxVector4));
for (int j = 0; j < lVertexCount; j++)
{
FbxVector4 lInfluence = (lEndShape->GetControlPoints()[j] - lSrcVertexArray[j]) * lWeight * 0.01;
lDstVertexArray[j] += lInfluence;
}
}
else if(lStartShape && lEndShape)
{
double lStartWeight = lFullWeights[lStartIndex];
double lEndWeight = lFullWeights[lEndIndex];
lWeight = ((lWeight-lStartWeight)/(lEndWeight-lStartWeight)) * 100;
memcpy(lDstVertexArray, lStartShape->GetControlPoints(), lVertexCount * sizeof(FbxVector4));
for (int j = 0; j < lVertexCount; j++)
{
FbxVector4 lInfluence = (lEndShape->GetControlPoints()[j] - lStartShape->GetControlPoints()[j]) * lWeight * 0.01;
lDstVertexArray[j] += lInfluence;
}
}
}
}
}
memcpy(pVertexArray, lDstVertexArray, lVertexCount * sizeof(FbxVector4));
delete [] lDstVertexArray;
}
void ComputeClusterDeformation(FbxAMatrix& pGlobalPosition,
FbxMesh* pMesh,
FbxCluster* pCluster,
FbxAMatrix& pVertexTransformMatrix,
FbxTime pTime,
FbxPose* pPose)
{
FbxCluster::ELinkMode lClusterMode = pCluster->GetLinkMode();
FbxAMatrix lReferenceGlobalInitPosition;
FbxAMatrix lReferenceGlobalCurrentPosition;
FbxAMatrix lAssociateGlobalInitPosition;
FbxAMatrix lAssociateGlobalCurrentPosition;
FbxAMatrix lClusterGlobalInitPosition;
FbxAMatrix lClusterGlobalCurrentPosition;
FbxAMatrix lReferenceGeometry;
FbxAMatrix lAssociateGeometry;
FbxAMatrix lClusterGeometry;
FbxAMatrix lClusterRelativeInitPosition;
FbxAMatrix lClusterRelativeCurrentPositionInverse;
if (lClusterMode == FbxCluster::eAdditive && pCluster->GetAssociateModel())
{
pCluster->GetTransformAssociateModelMatrix(lAssociateGlobalInitPosition);
lAssociateGeometry = GetGeometry(pCluster->GetAssociateModel());
lAssociateGlobalInitPosition *= lAssociateGeometry;
lAssociateGlobalCurrentPosition = GetGlobalPosition(pCluster->GetAssociateModel(), pTime, pPose);
pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
lReferenceGeometry = GetGeometry(pMesh->GetNode());
lReferenceGlobalInitPosition *= lReferenceGeometry;
lReferenceGlobalCurrentPosition = pGlobalPosition;
pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
lClusterGeometry = GetGeometry(pCluster->GetLink());
lClusterGlobalInitPosition *= lClusterGeometry;
lClusterGlobalCurrentPosition = GetGlobalPosition(pCluster->GetLink(), pTime, pPose);
pVertexTransformMatrix = lReferenceGlobalInitPosition.Inverse() * lAssociateGlobalInitPosition * lAssociateGlobalCurrentPosition.Inverse() *
lClusterGlobalCurrentPosition * lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;
}
else
{
pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
lReferenceGlobalCurrentPosition = pGlobalPosition;
lReferenceGeometry = GetGeometry(pMesh->GetNode());
lReferenceGlobalInitPosition *= lReferenceGeometry;
pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
lClusterGlobalCurrentPosition = GetGlobalPosition(pCluster->GetLink(), pTime, pPose);
lClusterRelativeInitPosition = lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;
lClusterRelativeCurrentPositionInverse = lReferenceGlobalCurrentPosition.Inverse() * lClusterGlobalCurrentPosition;
pVertexTransformMatrix = lClusterRelativeCurrentPositionInverse * lClusterRelativeInitPosition;
}
}
void ComputeLinearDeformation(FbxAMatrix& pGlobalPosition,
FbxMesh* pMesh,
FbxTime& pTime,
FbxVector4* pVertexArray,
FbxPose* pPose)
{
FbxCluster::ELinkMode lClusterMode = ((FbxSkin*)pMesh->GetDeformer(0, FbxDeformer::eSkin))->GetCluster(0)->GetLinkMode();
int lVertexCount = pMesh->GetControlPointsCount();
FbxAMatrix* lClusterDeformation = new FbxAMatrix[lVertexCount];
memset(lClusterDeformation, 0, lVertexCount * sizeof(FbxAMatrix));
double* lClusterWeight = new double[lVertexCount];
memset(lClusterWeight, 0, lVertexCount * sizeof(double));
if (lClusterMode == FbxCluster::eAdditive)
{
for (int i = 0; i < lVertexCount; ++i)
{
lClusterDeformation[i].SetIdentity();
}
}
int lSkinCount = pMesh->GetDeformerCount(FbxDeformer::eSkin);
for ( int lSkinIndex=0; lSkinIndex<lSkinCount; ++lSkinIndex)
{
FbxSkin * lSkinDeformer = (FbxSkin *)pMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin);
int lClusterCount = lSkinDeformer->GetClusterCount();
for ( int lClusterIndex=0; lClusterIndex<lClusterCount; ++lClusterIndex)
{
FbxCluster* lCluster = lSkinDeformer->GetCluster(lClusterIndex);
if (!lCluster->GetLink())
continue;
FbxAMatrix lVertexTransformMatrix;
ComputeClusterDeformation(pGlobalPosition, pMesh, lCluster, lVertexTransformMatrix, pTime, pPose);
int lVertexIndexCount = lCluster->GetControlPointIndicesCount();
for (int k = 0; k < lVertexIndexCount; ++k)
{
int lIndex = lCluster->GetControlPointIndices()[k];
if (lIndex >= lVertexCount)
continue;
double lWeight = lCluster->GetControlPointWeights()[k];
if (lWeight == 0.0)
{
continue;
}
FbxAMatrix lInfluence = lVertexTransformMatrix;
MatrixScale(lInfluence, lWeight);
if (lClusterMode == FbxCluster::eAdditive)
{
MatrixAddToDiagonal(lInfluence, 1.0 - lWeight);
lClusterDeformation[lIndex] = lInfluence * lClusterDeformation[lIndex];
lClusterWeight[lIndex] = 1.0;
}
else
{
MatrixAdd(lClusterDeformation[lIndex], lInfluence);
lClusterWeight[lIndex] += lWeight;
}
}
}
}
for (int i = 0; i < lVertexCount; i++)
{
FbxVector4 lSrcVertex = pVertexArray[i];
FbxVector4& lDstVertex = pVertexArray[i];
double lWeight = lClusterWeight[i];
if (lWeight != 0.0)
{
lDstVertex = lClusterDeformation[i].MultT(lSrcVertex);
if (lClusterMode == FbxCluster::eNormalize)
{
lDstVertex /= lWeight;
}
else if (lClusterMode == FbxCluster::eTotalOne)
{
lSrcVertex *= (1.0 - lWeight);
lDstVertex += lSrcVertex;
}
}
}
delete [] lClusterDeformation;
delete [] lClusterWeight;
}
void ComputeDualQuaternionDeformation(FbxAMatrix& pGlobalPosition,
FbxMesh* pMesh,
FbxTime& pTime,
FbxVector4* pVertexArray,
FbxPose* pPose)
{
FbxCluster::ELinkMode lClusterMode = ((FbxSkin*)pMesh->GetDeformer(0, FbxDeformer::eSkin))->GetCluster(0)->GetLinkMode();
int lVertexCount = pMesh->GetControlPointsCount();
int lSkinCount = pMesh->GetDeformerCount(FbxDeformer::eSkin);
FbxDualQuaternion* lDQClusterDeformation = new FbxDualQuaternion[lVertexCount];
memset(lDQClusterDeformation, 0, lVertexCount * sizeof(FbxDualQuaternion));
double* lClusterWeight = new double[lVertexCount];
memset(lClusterWeight, 0, lVertexCount * sizeof(double));
for ( int lSkinIndex=0; lSkinIndex<lSkinCount; ++lSkinIndex)
{
FbxSkin * lSkinDeformer = (FbxSkin *)pMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin);
int lClusterCount = lSkinDeformer->GetClusterCount();
for ( int lClusterIndex=0; lClusterIndex<lClusterCount; ++lClusterIndex)
{
FbxCluster* lCluster = lSkinDeformer->GetCluster(lClusterIndex);
if (!lCluster->GetLink())
continue;
FbxAMatrix lVertexTransformMatrix;
ComputeClusterDeformation(pGlobalPosition, pMesh, lCluster, lVertexTransformMatrix, pTime, pPose);
FbxQuaternion lQ = lVertexTransformMatrix.GetQ();
FbxVector4 lT = lVertexTransformMatrix.GetT();
FbxDualQuaternion lDualQuaternion(lQ, lT);
int lVertexIndexCount = lCluster->GetControlPointIndicesCount();
for (int k = 0; k < lVertexIndexCount; ++k)
{
int lIndex = lCluster->GetControlPointIndices()[k];
if (lIndex >= lVertexCount)
continue;
double lWeight = lCluster->GetControlPointWeights()[k];
if (lWeight == 0.0)
continue;
FbxDualQuaternion lInfluence = lDualQuaternion * lWeight;
if (lClusterMode == FbxCluster::eAdditive)
{
lDQClusterDeformation[lIndex] = lInfluence;
lClusterWeight[lIndex] = 1.0;
}
else
{
if(lClusterIndex == 0)
{
lDQClusterDeformation[lIndex] = lInfluence;
}
else
{
double lSign = lDQClusterDeformation[lIndex].GetFirstQuaternion().DotProduct(lDualQuaternion.GetFirstQuaternion());
if( lSign >= 0.0 )
{
lDQClusterDeformation[lIndex] += lInfluence;
}
else
{
lDQClusterDeformation[lIndex] -= lInfluence;
}
}
lClusterWeight[lIndex] += lWeight;
}
}
}
}
for (int i = 0; i < lVertexCount; i++)
{
FbxVector4 lSrcVertex = pVertexArray[i];
FbxVector4& lDstVertex = pVertexArray[i];
double lWeightSum = lClusterWeight[i];
if (lWeightSum != 0.0)
{
lDQClusterDeformation[i].Normalize();
lDstVertex = lDQClusterDeformation[i].Deform(lDstVertex);
if (lClusterMode == FbxCluster::eNormalize)
{
lDstVertex /= lWeightSum;
}
else if (lClusterMode == FbxCluster::eTotalOne)
{
lSrcVertex *= (1.0 - lWeightSum);
lDstVertex += lSrcVertex;
}
}
}
delete [] lDQClusterDeformation;
delete [] lClusterWeight;
}
void ComputeSkinDeformation(FbxAMatrix& pGlobalPosition,
FbxMesh* pMesh,
FbxTime& pTime,
FbxVector4* pVertexArray,
FbxPose* pPose)
{
FbxSkin * lSkinDeformer = (FbxSkin *)pMesh->GetDeformer(0, FbxDeformer::eSkin);
FbxSkin::EType lSkinningType = lSkinDeformer->GetSkinningType();
if(lSkinningType == FbxSkin::eLinear || lSkinningType == FbxSkin::eRigid)
{
ComputeLinearDeformation(pGlobalPosition, pMesh, pTime, pVertexArray, pPose);
}
else if(lSkinningType == FbxSkin::eDualQuaternion)
{
ComputeDualQuaternionDeformation(pGlobalPosition, pMesh, pTime, pVertexArray, pPose);
}
else if(lSkinningType == FbxSkin::eBlend)
{
int lVertexCount = pMesh->GetControlPointsCount();
FbxVector4* lVertexArrayLinear = new FbxVector4[lVertexCount];
memcpy(lVertexArrayLinear, pMesh->GetControlPoints(), lVertexCount * sizeof(FbxVector4));
FbxVector4* lVertexArrayDQ = new FbxVector4[lVertexCount];
memcpy(lVertexArrayDQ, pMesh->GetControlPoints(), lVertexCount * sizeof(FbxVector4));
ComputeLinearDeformation(pGlobalPosition, pMesh, pTime, lVertexArrayLinear, pPose);
ComputeDualQuaternionDeformation(pGlobalPosition, pMesh, pTime, lVertexArrayDQ, pPose);
int lBlendWeightsCount = lSkinDeformer->GetControlPointIndicesCount();
for(int lBWIndex = 0; lBWIndex<lBlendWeightsCount; ++lBWIndex)
{
double lBlendWeight = lSkinDeformer->GetControlPointBlendWeights()[lBWIndex];
pVertexArray[lBWIndex] = lVertexArrayDQ[lBWIndex] * lBlendWeight + lVertexArrayLinear[lBWIndex] * (1 - lBlendWeight);
}
}
}
void ReadVertexCacheData(FbxMesh* pMesh,
FbxTime& pTime,
FbxVector4* pVertexArray)
{
FbxVertexCacheDeformer* lDeformer = static_cast<FbxVertexCacheDeformer*>(pMesh->GetDeformer(0, FbxDeformer::eVertexCache));
FbxCache* lCache = lDeformer->GetCache();
int lChannelIndex = -1;
unsigned int lVertexCount = (unsigned int)pMesh->GetControlPointsCount();
bool lReadSucceed = false;
double* lReadBuf = new double[3*lVertexCount];
if (lCache->GetCacheFileFormat() == FbxCache::eMayaCache)
{
if ((lChannelIndex = lCache->GetChannelIndex(lDeformer->GetCacheChannel())) > -1)
{
lReadSucceed = lCache->Read(lChannelIndex, pTime, lReadBuf, lVertexCount);
}
}
else
{
lReadSucceed = lCache->Read((unsigned int)pTime.GetFrameCount(), lReadBuf, lVertexCount);
}
if (lReadSucceed)
{
unsigned int lReadBufIndex = 0;
while (lReadBufIndex < 3*lVertexCount)
{
pVertexArray[lReadBufIndex/3].mData[0] = lReadBuf[lReadBufIndex]; lReadBufIndex++;
pVertexArray[lReadBufIndex/3].mData[1] = lReadBuf[lReadBufIndex]; lReadBufIndex++;
pVertexArray[lReadBufIndex/3].mData[2] = lReadBuf[lReadBufIndex]; lReadBufIndex++;
}
}
delete [] lReadBuf;
}
void DrawCamera(FbxNode* pNode,
FbxTime& pTime,
FbxAnimLayer* pAnimLayer,
FbxAMatrix& pGlobalPosition)
{
FbxAMatrix lCameraGlobalPosition;
FbxVector4 lCameraPosition, lCameraDefaultDirection, lCameraInterestPosition;
lCameraPosition = pGlobalPosition.GetT();
FbxVector4 lXPositiveAxis(1.0, 0.0, 0.0);
lCameraDefaultDirection = lCameraPosition + lXPositiveAxis;
lCameraGlobalPosition = pGlobalPosition;
if (pNode->GetTarget())
{
lCameraInterestPosition = GetGlobalPosition(pNode->GetTarget(), pTime).GetT();
FbxVector4 lCameraDirection;
FbxVector4::AxisAlignmentInEulerAngle(lCameraPosition,
lCameraDefaultDirection,
lCameraInterestPosition,
lCameraDirection);
lCameraGlobalPosition.SetR(lCameraDirection);
}
FbxCamera* cam = pNode->GetCamera();
double lRoll = 0;
if (cam)
{
lRoll = cam->Roll.Get();
FbxAnimCurve* fc = cam->Roll.GetCurve(pAnimLayer);
if (fc) fc->Evaluate(pTime);
}
GlDrawCamera(lCameraGlobalPosition, lRoll);
}
void DrawLight(const FbxNode* pNode, const FbxTime& pTime, const FbxAMatrix& pGlobalPosition)
{
const FbxLight* lLight = pNode->GetLight();
if (!lLight)
return;
FbxAMatrix lLightRotation;
const FbxVector4 lYNegativeAxis(-90.0, 0.0, 0.0);
lLightRotation.SetR(lYNegativeAxis);
const FbxAMatrix lLightGlobalPosition = pGlobalPosition * lLightRotation;
glPushMatrix();
glMultMatrixd((const double*)lLightGlobalPosition);
const LightCache * lLightCache = static_cast<const LightCache *>(lLight->GetUserDataPtr());
if (lLightCache)
{
lLightCache->SetLight(pTime);
}
glPopMatrix();
}
void DrawNull(FbxAMatrix& pGlobalPosition)
{
GlDrawCrossHair(pGlobalPosition);
}
void MatrixScale(FbxAMatrix& pMatrix, double pValue)
{
int i,j;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
pMatrix[i][j] *= pValue;
}
}
}
void MatrixAddToDiagonal(FbxAMatrix& pMatrix, double pValue)
{
pMatrix[0][0] += pValue;
pMatrix[1][1] += pValue;
pMatrix[2][2] += pValue;
pMatrix[3][3] += pValue;
}
void MatrixAdd(FbxAMatrix& pDstMatrix, FbxAMatrix& pSrcMatrix)
{
int i,j;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
pDstMatrix[i][j] += pSrcMatrix[i][j];
}
}
}