DX11 FBX Animtion System

Started by
0 comments, last by Doug Rogers 11 years, 8 months ago
I am currently writing an fbx importer/Animtion system for my portfolio class in school. I have got all my rendering done but am now struggling with getting my animtion system to work correctly, I am currently loading in one frame of animtion data and animating in software to test before moving it into my shaders. Here is the code I hope someone can point out my errors as I have asked multiple teachers and, since none of them are familiar with FBX, seem to think the animtion code is relativly correct but still cannot get it working when helping me.

[source lang="cpp"]void FBXModel::InitializeSdkObjects(FbxManager*& pManager, FbxScene*& pScene)
{
//The first thing to do is to create the FBX Manager which is the object allocator for almost all the classes in the SDK
pManager = FbxManager::Create();
if( !pManager )
{
exit(1);
}
//Create an IOSettings object. This object holds all import/export settings.
FbxIOSettings* ios = FbxIOSettings::Create(pManager, IOSROOT);
pManager->SetIOSettings(ios);

//Load plugins from the executable directory (optional)
FbxString lPath = FbxGetApplicationDirectory();
pManager->LoadPluginsDirectory(lPath.Buffer());

//Create an FBX scene. This object holds most objects imported/exported from/to files.
pScene = FbxScene::Create(pManager, "My Scene");
if( !pScene )
{
exit(1);
}
}

bool FBXModel::LoadScene(const char* pFilename)
{
// Create an importer.
FbxImporter* lImporter = FbxImporter::Create(mSdkManager,"");

// Initialize the importer by providing a filename.
const bool lImportStatus = lImporter->Initialize(pFilename, -1, mSdkManager->GetIOSettings());

if( !lImportStatus )
{
return false;
}

//Check to make sure the file is a fbx file
if (!lImporter->IsFBX())
{
return false;
}

// Import the scene.
if(!lImporter->Import(mpScene))
{
return false;
}

//Destroy the importer
lImporter->Destroy();

return true;
}

void FBXModel::AddMesh()
{
FbxNode* lRootNode = mpScene->GetRootNode();
for( int i = 0; i < lRootNode->GetChildCount(); i++)
{
AddMesh(lRootNode->GetChild(i));
}

for(int i = 0; i < mMeshArray.Size(); ++i)
{
FbxMesh* pMesh = mMeshArray;

FbxGeometryConverter converter( mSdkManager );
pMesh = converter.TriangulateMesh( pMesh );


//========================================================================================================================
// TODO: MOVE INTO SHADER
//========================================================================================================================
//Load In Vertex Data
LoadPosNormTex(pMesh, i);

//Load Bone Data
LoadBones(pMesh);

//Place the Bones Recursively using the bone tree
PlaceBones();

//Multiply Verts By bond Pose Inverse
TestMoveVertInverse();

//load Animation Data
LoadAnimationData(0);

//Place Bones in new locations
PlaceBones();

//Move Bones Back into
TestMoveVert();
}
}

void FBXModel::AddMesh(FbxNode* pNode)
{
FbxNodeAttribute::EType nodeType = pNode->GetNodeAttribute()->GetAttributeType();
if(nodeType == FbxNodeAttribute::eMesh)
{
mMeshArray.Add( (FbxMesh*) pNode->GetNodeAttribute() );
}

for(int i = 0; i < pNode->GetChildCount(); i++)
{
AddMesh(pNode->GetChild(i));
}
}

void FBXModel::LoadPosNormTex(FbxMesh* pMesh, int i)
{
FbxVector4* pMeshVertices = new FbxVector4[pMesh->GetControlPointsCount()];
memcpy(pMeshVertices, pMesh->GetControlPoints(), pMesh->GetControlPointsCount()*sizeof(FbxVector4));

// Create the vertex array.
mVertexCount = pMesh->GetControlPointsCount();
vertices = new VertexType[mVertexCount];

FbxLayerElementUV* texCoords = pMesh->GetLayer(i)->GetUVs();

for( int i = 0; i < mVertexCount; ++i )
{
VertexType v;
//Vertex
v.mPosition = D3DXVECTOR3(
(float)pMeshVertices[ i ].mData[0],
(float)pMeshVertices[ i ].mData[1],
(float)pMeshVertices[ i ].mData[2]
);

//Normal
v.mNormal = D3DXVECTOR3
(
(float)pMesh->GetElementNormal(0)->GetDirectArray().GetAt(i).mData[0],
(float)pMesh->GetElementNormal(0)->GetDirectArray().GetAt(i).mData[1],
(float)pMesh->GetElementNormal(0)->GetDirectArray().GetAt(i).mData[2]
);


//Texture
if(texCoords)
{
v.mTexture = D3DXVECTOR2
(
(float)texCoords->GetDirectArray().GetAt(i).mData[0],
(float)texCoords->GetDirectArray().GetAt(i).mData[1]
);
}
else
{
v.mTexture = D3DXVECTOR2(0.7f, 0.7f);
}

vertices = v;
}
delete [] pMeshVertices;


// Create the index array.
mIndexCount = pMesh->GetPolygonVertexCount();
indices = new unsigned short[mIndexCount];
for(int i = 0; i < pMesh->GetPolygonVertexCount(); ++i )
{
indices = pMesh->GetPolygonVertices();
}
}

void FBXModel::LoadBones(FbxGeometry* pGeometry)
{
int lSkinCount = pGeometry->GetDeformerCount(FbxDeformer::eSkin);

for(int i = 0; i!=lSkinCount; ++i)
{
int lClusterCount = ((FbxSkin *) pGeometry->GetDeformer(i, FbxDeformer::eSkin))->GetClusterCount();

mBoneCount = lClusterCount;
mBones = new Bone[lClusterCount];
for (int j = 0; j != lClusterCount; ++j)
{
FbxCluster* lCluster = ((FbxSkin *) pGeometry->GetDeformer(i, FbxDeformer::eSkin))->GetCluster(j);

FbxNode* link = lCluster->GetLink();
const char* linkname = link->GetName();
mBones[j].mChildCount = link->GetChildCount();
mBones[j].mChildren = new Bone*[mBones[j].mChildCount];

if(lCluster->GetLink() != NULL)
{
mBones[j].mName = (char*)lCluster->GetLink()->GetName();
}

FbxAMatrix lMatrix;
lMatrix = lCluster->GetTransformLinkMatrix(lMatrix);

//Transform Matrix
D3DXMATRIX D3DTranslate;
D3DXMATRIX D3DRotate;
D3DXMATRIX D3DScale;

D3DXMatrixIdentity(&D3DTranslate);
D3DXMatrixIdentity(&D3DRotate);
D3DXMatrixIdentity(&D3DScale);

float rx = lMatrix.GetR().mData[0];
float ry = lMatrix.GetR().mData[1];
float rz = lMatrix.GetR().mData[2];
float sx = lMatrix.GetS().mData[0];
float sy = lMatrix.GetS().mData[1];
float sz = lMatrix.GetS().mData[2];

D3DXMatrixTranslation(&D3DTranslate, (float)lMatrix.GetT().mData[0], (float)lMatrix.GetT().mData[1], (float)lMatrix.GetT().mData[2]);
D3DXMatrixRotationYawPitchRoll(&D3DRotate, DEG2RAD((float)lMatrix.GetR().mData[0]), DEG2RAD((float)lMatrix.GetR().mData[1]), DEG2RAD((float)lMatrix.GetR().mData[2]));
D3DXMatrixScaling(&D3DScale, (float)lMatrix.GetS().mData[0], (float)lMatrix.GetS().mData[1], (float)lMatrix.GetS().mData[2]);

mBones[j].mTransformPositionMatrix = D3DRotate * D3DTranslate * D3DScale;
mBones[j].mBindPoseMatrix = D3DRotate * D3DTranslate * D3DScale;
D3DXMatrixInverse(&mBones[j].mBindPoseInverse, NULL, &mBones[j].mTransformPositionMatrix);

}

//Create the bone tree and set bone weights
for (int j = 0; j != lClusterCount; ++j)
{
FbxCluster* lCluster = ((FbxSkin *) pGeometry->GetDeformer(i, FbxDeformer::eSkin))->GetCluster(j);

FbxNode* link = lCluster->GetLink();

for(int k = 0; k < mBones[j].mChildCount; ++k)
{
FbxNode* childNode = link->GetChild(k);
int ChildId = GetBoneIdByName( childNode->GetName() );
mBones[j].mChildren[k] = &mBones[ChildId];
mBones[j].mChildren[k]->mParent = &mBones[j];
}


int indicesCount = lCluster->GetControlPointIndicesCount();
if(indicesCount)
{
int* Boneindcies = lCluster->GetControlPointIndices();
double* BoneWeights = lCluster->GetControlPointWeights();
int indicesCount = lCluster->GetControlPointIndicesCount();

for(int l = 0; l < indicesCount; ++l)
{
for(int m = 0; m < 4; ++m)
{
if(vertices[Boneindcies[l]].mBoneIds[m] == 0)
{
vertices[Boneindcies[l]].mBoneIds[m] = j;
vertices[Boneindcies[l]].mBoneWeights[m] = BoneWeights[l];
break;
}
}
}
}

}
}

//Copy in loaded data from verts into findPoseVerts to create bind pose position
verticesBindPose = new VertexType[mVertexCount];
memcpy(verticesBindPose, vertices, sizeof(VertexType) * mVertexCount);
}

int FBXModel::GetBoneIdByName(const char* name)
{
for(int i = 0; i < mBoneCount; ++i)
{
if(name == mBones.mName)
{
return i;
}
}
return -1;
}


void FBXModel::LoadAnimationData(int key)
{
for(int h = 0; h < mBoneCount; ++h)
{
FbxNode* lNode = mpScene->FindNodeByName(mBones[h].mName);
int AnimationStackCount = mpScene->GetSrcObjectCount(FBX_TYPE(FbxAnimStack));
for (int i = 0; i < AnimationStackCount; ++i)
{
FbxAnimStack* lAnimStack = FbxCast<FbxAnimStack>( mpScene->GetSrcObject(FbxAnimStack::ClassId, i) );

int nbAnimLayerCount = lAnimStack->GetMemberCount(FBX_TYPE(FbxAnimLayer));
for (int l = 0; l < nbAnimLayerCount; l++)
{
FbxAnimLayer* lAnimLayer = lAnimStack->GetMember(FBX_TYPE(FbxAnimLayer), l);
const char* AnimLayerName = lAnimLayer->GetName();

FbxAnimCurveNode* lAnimCurve = lNode->LclTranslation.GetCurveNode();

FbxAnimCurve* lAnimCurveTX = lAnimCurve->GetCurve(0);
FbxAnimCurve* lAnimCurveTY = lAnimCurve->GetCurve(1);
FbxAnimCurve* lAnimCurveTZ = lAnimCurve->GetCurve(2);

lAnimCurve = lNode->LclRotation.GetCurveNode();
FbxAnimCurve* lAnimCurveRX = lAnimCurve->GetCurve(0);
FbxAnimCurve* lAnimCurveRY = lAnimCurve->GetCurve(1);
FbxAnimCurve* lAnimCurveRZ = lAnimCurve->GetCurve(2);

lAnimCurve = lNode->LclScaling.GetCurveNode();
FbxAnimCurve* lAnimCurveSX = lAnimCurve->GetCurve(0);
FbxAnimCurve* lAnimCurveSY = lAnimCurve->GetCurve(1);
FbxAnimCurve* lAnimCurveSZ = lAnimCurve->GetCurve(2);

float SX = 1.0f;
float SY = 1.0f;
float SZ = 1.0f;
float TX = 0;
float TY = 0;
float TZ = 0;
float RX = 0;
float RY = 0;
float RZ = 0;


//Load Translations Data
if(lAnimCurveTX && key < lAnimCurveTX->KeyGetCount())
TX = lAnimCurveTX->KeyGet(key).GetValue();

if(lAnimCurveTY && key < lAnimCurveTY->KeyGetCount())
TY = lAnimCurveTY->KeyGet(key).GetValue();

if(lAnimCurveTZ && key < lAnimCurveTZ->KeyGetCount())
TZ = lAnimCurveTZ->KeyGet(key).GetValue();

//Load Rotation Data
if(lAnimCurveRX && key < lAnimCurveRX->KeyGetCount())
RX = lAnimCurveRX->KeyGet(key).GetValue();

if(lAnimCurveRY && key < lAnimCurveRY->KeyGetCount())
RY = lAnimCurveRY->KeyGet(key).GetValue();

if(lAnimCurveRZ && key < lAnimCurveRZ->KeyGetCount())
RZ = lAnimCurveRZ->KeyGet(key).GetValue();

//Load Scale Data
if(lAnimCurveSX && key < lAnimCurveSX->KeyGetCount())
SX = lAnimCurveSX->KeyGet(key).GetValue();
if(lAnimCurveSY && key < lAnimCurveSY->KeyGetCount())
SY = lAnimCurveSY->KeyGet(key).GetValue();
if(lAnimCurveSZ && key < lAnimCurveSZ->KeyGetCount())
SZ = lAnimCurveSZ->KeyGet(key).GetValue();

//Transform Matrix
D3DXMATRIX D3DTranslate;
D3DXMATRIX D3DRotate;
D3DXMATRIX D3DScale;

D3DXMatrixIdentity(&D3DTranslate);
D3DXMatrixIdentity(&D3DRotate);
D3DXMatrixIdentity(&D3DScale);

D3DXMatrixTranslation(&D3DTranslate, TX, TY, TZ);
D3DXMatrixRotationYawPitchRoll(&D3DRotate, DEG2RAD(RX), DEG2RAD(RY), DEG2RAD(RZ));
D3DXMatrixScaling(&D3DScale, SX, SY, SZ);
mBones[h].mTransformPositionMatrix = D3DRotate * D3DTranslate * D3DScale;
}
}
}
}

void FBXModel::TestMoveVert()
{
for(int i = 0; i < mVertexCount; ++i)
{
D3DXVECTOR3 pos1;
D3DXVECTOR3 pos2;
D3DXVECTOR3 pos3;
D3DXVECTOR3 pos4;

D3DXVec3TransformCoord(&pos1, &verticesBindPose.mPosition, &mBones[vertices.mBoneIds[0]].mWorldTransformPositionMatrix );
D3DXVec3TransformCoord(&pos2, &verticesBindPose.mPosition, &mBones[vertices.mBoneIds[1]].mWorldTransformPositionMatrix );
D3DXVec3TransformCoord(&pos3, &verticesBindPose.mPosition, &mBones[vertices.mBoneIds[2]].mWorldTransformPositionMatrix );
D3DXVec3TransformCoord(&pos4, &verticesBindPose.mPosition, &mBones[vertices.mBoneIds[3]].mWorldTransformPositionMatrix );

vertices.mPosition = (pos1*vertices.mBoneWeights[0]) +
(pos2*vertices.mBoneWeights[1]) +
(pos3*vertices.mBoneWeights[2]) +
(pos4*vertices.mBoneWeights[3]);
}
}

void FBXModel::TestMoveVertInverse()
{
for(int i = 0; i < mVertexCount; ++i)
{
D3DXVECTOR3 pos1;
D3DXVECTOR3 pos2;
D3DXVECTOR3 pos3;
D3DXVECTOR3 pos4;

D3DXVec3TransformCoord(&pos1, &vertices.mPosition, &mBones[vertices.mBoneIds[0]].mBindPoseInverse);
D3DXVec3TransformCoord(&pos2, &vertices.mPosition, &mBones[vertices.mBoneIds[1]].mBindPoseInverse );
D3DXVec3TransformCoord(&pos3, &vertices.mPosition, &mBones[vertices.mBoneIds[2]].mBindPoseInverse );
D3DXVec3TransformCoord(&pos4, &vertices.mPosition, &mBones[vertices.mBoneIds[3]].mBindPoseInverse );

verticesBindPose.mPosition = (pos1*vertices.mBoneWeights[0]) +
(pos2*vertices.mBoneWeights[1]) +
(pos3*vertices.mBoneWeights[2]) +
(pos4*vertices.mBoneWeights[3]);
}
}

void FBXModel::PlaceBones()
{
mBones[0].mWorldTransformPositionMatrix = mBones[0].mTransformPositionMatrix;
for(int i = 0; i < mBones[0].mChildCount; ++i)
{
PlaceBones(mBones[0].mChildren, mBones[0].mTransformPositionMatrix );
}
}

void FBXModel::PlaceBones( Bone* bone, D3DXMATRIX parent )
{
bone->mWorldTransformPositionMatrix = bone->mTransformPositionMatrix * parent;
for(int j = 0; j < bone->mChildCount; ++j)
{
PlaceBones( bone->mChildren[j], bone->mWorldTransformPositionMatrix);
}
}[/source]
Advertisement
Try posting here:

http://area.autodesk.com/forum/autodesk-fbx/fbx-sdk/

This topic is closed to new replies.

Advertisement