Animating a model

Started by
-1 comments, last by Beosar 9 years, 6 months ago
Hi,

I have some problems animating a model. I don't even know what I am doing, I just tried whatever I thought could help and copied some code, but nothing fixed this problem and the FBX documentation sucks and I don't know what to try next to get this work. The problem is that this model should look like a human (it does when setting all of the bone matrices to identity or a fixed rotation or translation or whatever, but I want the human to move), but it looks like... whatever...

2.png

I don't know which part of the code causes this problem, but I think that it has something to do with the matrices set in the AnimatedModel::Animate() function.

animatedmodel.cpp:
void AnimatedModel::Animate(){
	if (FrameCount == Animations[0].KeyFrameCount){
		FrameCount = 0;
	}
	XMMATRIX rotateMatrixX, rotateMatrixY, rotateMatrixZ, translationMatrix, finalMatrix, scaleMatrix;
	int i;
	for (i = 0; i < BoneCount; i++){
		scaleMatrix = XMMatrixScaling(Animations[0].KeyFrameArray[i][FrameCount].Scale.x, Animations[0].KeyFrameArray[i][FrameCount].Scale.y, Animations[0].KeyFrameArray[i][FrameCount].Scale.z);

		rotateMatrixX = XMMatrixRotationX(Animations[0].KeyFrameArray[i][FrameCount].Rotate.x / 180.0f*M_PI);
		rotateMatrixY = XMMatrixRotationY(Animations[0].KeyFrameArray[i][FrameCount].Rotate.y / 180.0f*M_PI);
		rotateMatrixZ = XMMatrixRotationZ(Animations[0].KeyFrameArray[i][FrameCount].Rotate.z / 180.0f*M_PI);


		translationMatrix = XMMatrixTranslation(Animations[0].KeyFrameArray[i][FrameCount].Translate.x, Animations[0].KeyFrameArray[i][FrameCount].Translate.y, Animations[0].KeyFrameArray[i][FrameCount].Translate.z);

		finalMatrix = XMMatrixMultiply(scaleMatrix, rotateMatrixX);
		finalMatrix = XMMatrixMultiply(finalMatrix, rotateMatrixY);
		finalMatrix = XMMatrixMultiply(finalMatrix, rotateMatrixZ);
		finalMatrix = XMMatrixMultiply(finalMatrix, translationMatrix);
		finalMatrix = XMMatrixMultiply(BoneArray[i].GlobalBindposeInverse, finalMatrix);
		finalMatrix = XMMatrixTranspose(finalMatrix);

		XMStoreFloat4x4(&(BoneMatrixArray[0].Bonematrix[i]), finalMatrix);
		
		
		
	}


	FrameCount++;
}

fbxloader.h:
#ifndef _FBXLOADER_H_
#define _FBXLOADER_H_

#include <windows.h>
#include <fbxsdk.h>
#include "d3dclass.h"


#pragma comment(lib,"libfbxsdk-md.lib")

#define INDEX_ARRAY_SIZE 12582912 // max 4194304 (2^22) triangles
#define VERTEX_ARRAY_SIZE INDEX_ARRAY_SIZE //vertex count is always <= index count

class FbxLoader{
public:
	struct VertexType{
		XMFLOAT3 Position;
		XMFLOAT3 Normal;
		XMFLOAT2 Texture;
		float Weights[4];
		unsigned int BoneIDs[4];
	};

	struct KeyFrameType{
		int FrameNumber;
		XMFLOAT3 Rotate, Scale, Translate;
		XMFLOAT4X4 GlobalTransform;
	};

	struct AnimationType{
		char* Name;
		KeyFrameType* KeyFrameArray;
		int KeyFrameArrayCount;
	};


	struct BoneType{
		BoneType** Children;
		int ChildCount, ID;
		unsigned long long UniqueID;
		char* Name;
		AnimationType* AnimationArray;
		FbxAMatrix GlobalBindposeInverse;
	};

	
	struct ReturnType{
		VertexType** VertexArray; //array of pointers to vertex arrays
		int VertexArrayCount; // count of vertex and index arrays
		unsigned int* VertexCountArray; // array of vertex counts of vertex arrays
		unsigned int** IndexArray; //array of pointers to arrays of indices
		unsigned int* IndexCountArray; //array of index counts
		BoneType* RootBone;
		FbxNode** MeshArray;
		int AnimationCount, BoneCount;
	};

	struct WeightType{
		float Weights[4];
		unsigned int BoneID[4];
		int CurrID;
	};

	static void Initialize();

	static bool LoadModel(char* FileName, ReturnType* Result);
	static void EndLoading();

private:

	static void BeginLoading();
	static void ProcessNode(FbxNode* Node, ReturnType* Result);
	static void ProcessMesh(FbxNode* Node, ReturnType* Result);

	static void FindFirstSkeletonNode(FbxNode* Node, ReturnType* Result);
	static void ProcessSkeleton(FbxNode* Node, ReturnType* Result, BoneType** Bone);

	static void CopyToNewString(char** Dest, const char* Src);

	static FbxAMatrix GetGeometryTransformation(FbxNode* Node);

	static void ProcessBonesAndAnimations(FbxNode* Node, FbxScene* Scene, ReturnType* Result);

	static BoneType* FindBoneByID(unsigned long long ID, ReturnType* Result);
	static WeightType* GetWeightArray(FbxNode* Node, ReturnType* Result);

	static void SetWeight(WeightType* WeightPtr, float Weight, int BoneID);

	//static void LoadAnimations(FbxScene* Scene, ReturnType* Result);

	static FbxManager* SdkManager;
	static unsigned int* IndexArray;
	static VertexType* vertices;
	static int BoneCount;
	static WeightType** WeightArray;
};

#endif

fbxloader.cpp:
#include "fbxloader.h"
#include "macros.h"

#include <queue>

FbxManager* FbxLoader::SdkManager;
unsigned int* FbxLoader::IndexArray;
FbxLoader::VertexType* FbxLoader::vertices;
FbxLoader::WeightType** FbxLoader::WeightArray;

void FbxLoader::Initialize(){
	SdkManager = 0;
	IndexArray = 0;
	vertices = 0;
	WeightArray = 0;
}

void FbxLoader::BeginLoading(){
	if (!SdkManager){
		SdkManager = FbxManager::Create();
		FbxIOSettings *ios = FbxIOSettings::Create(SdkManager, IOSROOT);
		SdkManager->SetIOSettings(ios);
	}
	if (!IndexArray){
		IndexArray = new unsigned int[INDEX_ARRAY_SIZE];
	}
	if (!vertices){
		vertices = new VertexType[VERTEX_ARRAY_SIZE];
	}
	
}

bool FbxLoader::LoadModel(char* FileName, ReturnType* Result){
	
	if (Result==0){
		return false;
	}

	BeginLoading();

	Result->VertexArrayCount = 0;

	Result->AnimationCount = 0;

	
	Result->BoneCount = 0;
	

	FbxIOSettings *ios = FbxIOSettings::Create(SdkManager, IOSROOT);
	SdkManager->SetIOSettings(ios);

	FbxImporter* Importer = FbxImporter::Create(SdkManager, "");

	if (!Importer->Initialize(FileName, -1, SdkManager->GetIOSettings())) {
		return false;
	}

	FbxScene* Scene = FbxScene::Create(SdkManager, "myScene");

	Importer->Import(Scene);

	Importer->Destroy();

	FbxNode* Node=Scene->GetRootNode();

	int NodeCount = Scene->GetNodeCount();

	if (NodeCount == 0){
		Scene->Destroy();
		return false;
	}

	Result->IndexCountArray = new unsigned int[NodeCount];
	Result->VertexCountArray = new unsigned int[NodeCount];
	
	Result->MeshArray = new FbxNode*[NodeCount];
	memset(Result->MeshArray, 0, sizeof(FbxNode*)*NodeCount);
	
	Result->IndexArray = new unsigned int*[NodeCount];
	Result->VertexArray = new VertexType*[NodeCount];

	
	WeightArray = new WeightType*[NodeCount];
	memset(WeightArray, 0, sizeof(WeightType*)*NodeCount);

	FindFirstSkeletonNode(Node, Result);

	int MeshCount = 0;

	std::queue<FbxNode*> NodeQueue;

	FbxNode* CurrNode = Node;

	while (CurrNode){

		FbxNodeAttribute* Attribute = CurrNode->GetNodeAttribute();
		if (Attribute){
			if (Attribute->GetAttributeType() == FbxNodeAttribute::EType::eMesh){
				Result->MeshArray[MeshCount] = CurrNode;
				WeightArray[MeshCount] = new WeightType[CurrNode->GetMesh()->GetControlPointsCount()];
				memset(WeightArray[MeshCount], 0, sizeof(WeightType)*CurrNode->GetMesh()->GetControlPointsCount());
				MeshCount++;
			}
		}

		int j, ChildCount = CurrNode->GetChildCount();
		for (j = 0; j < ChildCount; j++){
			NodeQueue.push(CurrNode->GetChild(j));
		}
		if (!NodeQueue.empty()){
			CurrNode = NodeQueue.front();
			NodeQueue.pop();
		}
		else{
			CurrNode = 0;
		}

	}


	

	int i;
	for (i = 0; i < MeshCount; i++){
		ProcessBonesAndAnimations(Result->MeshArray[i], Scene, Result);
	}

	Result->VertexArrayCount = 0;
	ProcessNode(Node, Result);

	

	
	
	for (i = 0; i < NodeCount; i++){
		SAFE_ARRAY_DELETE(WeightArray[i]);
	}

	SAFE_ARRAY_DELETE(WeightArray);

	Scene->Destroy();

	

	return true;
	
}

void FbxLoader::ProcessNode(FbxNode* Node, ReturnType* Result){
	if (!Node){
		return;
	}

	//Processing all child nodes
	int i, ChildCount = Node->GetChildCount();
	for (i = 0; i < ChildCount; i++){
		ProcessNode(Node->GetChild(i), Result);
	}


	FbxNodeAttribute* Attribute = Node->GetNodeAttribute();
	if (!Attribute){
		return;
	}

	FbxNodeAttribute::EType Type = Attribute->GetAttributeType();

	switch (Type){
	case FbxNodeAttribute::EType::eMesh:
		ProcessMesh(Node, Result);
		break;

	default:
		break;
	}

}

void FbxLoader::FindFirstSkeletonNode(FbxNode* Node, ReturnType* Result){
	if (!Node){
		return;
	}

	FbxNodeAttribute* Attribute = Node->GetNodeAttribute();
	if (!Attribute){


		//Processing all child nodes
		int i, ChildCount = Node->GetChildCount();
		for (i = 0; i < ChildCount; i++){
			FindFirstSkeletonNode(Node->GetChild(i), Result);
		}
	}
	else{
		FbxNodeAttribute::EType Type = Attribute->GetAttributeType();

		if (Type == FbxNodeAttribute::EType::eSkeleton){
			ProcessSkeleton(Node, Result,&Result->RootBone);
		}
		else{
			int i, ChildCount = Node->GetChildCount();
			for (i = 0; i < ChildCount; i++){
				FindFirstSkeletonNode(Node->GetChild(i), Result);
			}
		}
	}
}


void FbxLoader::ProcessMesh(FbxNode* Node, ReturnType* Result){
		int i, j, PolygonSize;
	int index=0;
	if (!Node){
		return;
	}

	FbxMesh* Mesh = Node->GetMesh();
	WeightType* Weights = GetWeightArray(Node, Result);
	if (!Mesh){
		return;
	}
	int ControlPointCount = Mesh->GetControlPointsCount();
	int PolygonCount = Mesh->GetPolygonCount();


	FbxGeometryElementNormal* Normal;
	FbxGeometryElementUV* UV;
	int index0, VertexCounter=0, ControlPointIndex;

	int* VertexUsedArray = new int[ControlPointCount];
	memset(VertexUsedArray, 0, sizeof(int)*ControlPointCount);


	FbxVector4* ControlPoints = Mesh->GetControlPoints();
	
	for (i = 0; i < PolygonCount; i++){ //TBD concave polygons
		PolygonSize = Mesh->GetPolygonSize(i)-1;
		for (j = 1; j < PolygonSize; j++){ //only works for convex polygons and some concave polygons
			if (index == INDEX_ARRAY_SIZE){
				goto IndexLoadingEnded;
			}
			IndexArray[index] = VertexCounter;
			index++;
			IndexArray[index] = VertexCounter + j;
			index++;
			IndexArray[index] = VertexCounter + j + 1;
			index++;
		}
		for (j = 0; j <= PolygonSize; j++){
			ControlPointIndex = Mesh->GetPolygonVertex(i, j);
			vertices[VertexCounter].Position.x = static_cast<float>(ControlPoints[ControlPointIndex].mData[0]);
			vertices[VertexCounter].Position.y = static_cast<float>(ControlPoints[ControlPointIndex].mData[1]);
			vertices[VertexCounter].Position.z = static_cast<float>(ControlPoints[ControlPointIndex].mData[2]);
			
			memcpy(vertices[VertexCounter].Weights, Weights[ControlPointIndex].Weights, sizeof(float) * 4);
			memcpy(vertices[VertexCounter].BoneIDs, Weights[ControlPointIndex].BoneID, sizeof(unsigned int) * 4);

			///////////////////////
			/// LOADING NORMALS ///
			///////////////////////

			Normal = Mesh->GetElementNormal(0);
			if (Normal){

				switch (Normal->GetMappingMode())
				{
				case FbxGeometryElement::eByControlPoint:
					switch (Normal->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					{
						vertices[VertexCounter].Normal.x = static_cast<float>(Normal->GetDirectArray().GetAt(ControlPointIndex).mData[0]);
						vertices[VertexCounter].Normal.y = static_cast<float>(Normal->GetDirectArray().GetAt(ControlPointIndex).mData[1]);
						vertices[VertexCounter].Normal.z = static_cast<float>(Normal->GetDirectArray().GetAt(ControlPointIndex).mData[2]);
					}
						break;

					case FbxGeometryElement::eIndexToDirect:
					{
						index0 = Normal->GetIndexArray().GetAt(ControlPointIndex);
						vertices[VertexCounter].Normal.x = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[0]);
						vertices[VertexCounter].Normal.y = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[1]);
						vertices[VertexCounter].Normal.z = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[2]);
					}
						break;

					default:
						break; //TBD error
					}
					break;

				case FbxGeometryElement::eByPolygonVertex:
					switch (Normal->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					{
						vertices[VertexCounter].Normal.x = static_cast<float>(Normal->GetDirectArray().GetAt(VertexCounter).mData[0]);
						vertices[VertexCounter].Normal.y = static_cast<float>(Normal->GetDirectArray().GetAt(VertexCounter).mData[1]);
						vertices[VertexCounter].Normal.z = static_cast<float>(Normal->GetDirectArray().GetAt(VertexCounter).mData[2]);
					}
						break;

					case FbxGeometryElement::eIndexToDirect:
					{
						index0 = Normal->GetIndexArray().GetAt(VertexCounter);
						vertices[VertexCounter].Normal.x = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[0]);
						vertices[VertexCounter].Normal.y = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[1]);
						vertices[VertexCounter].Normal.z = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[2]);
					}
						break;

					default:
						break; //TBD error
					}
					break;
				}
			}
			else{
				vertices[VertexCounter].Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);

			}

			//////////////////////////////
			/// LOADING TEXTURE COORDS ///
			//////////////////////////////

			UV = Mesh->GetElementUV(0);
			if (UV){

				switch (UV->GetMappingMode())
				{
				case FbxGeometryElement::eByControlPoint:
					switch (UV->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					{
						vertices[VertexCounter].Texture.x = static_cast<float>(UV->GetDirectArray().GetAt(ControlPointIndex).mData[0]);
						vertices[VertexCounter].Texture.y = static_cast<float>(UV->GetDirectArray().GetAt(ControlPointIndex).mData[1]);
					}
						break;

					case FbxGeometryElement::eIndexToDirect:
					{
						index0 = UV->GetIndexArray().GetAt(ControlPointIndex);
						vertices[VertexCounter].Texture.x = static_cast<float>(UV->GetDirectArray().GetAt(index0).mData[0]);
						vertices[VertexCounter].Texture.y = static_cast<float>(UV->GetDirectArray().GetAt(index0).mData[1]);
					}
						break;

					default:
						break; //TBD error
					}
					break;

				case FbxGeometryElement::eByPolygonVertex:
					switch (UV->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					{
						vertices[VertexCounter].Texture.x = static_cast<float>(UV->GetDirectArray().GetAt(VertexCounter).mData[0]);
						vertices[VertexCounter].Texture.y = static_cast<float>(UV->GetDirectArray().GetAt(VertexCounter).mData[1]);
					}
						break;

					case FbxGeometryElement::eIndexToDirect:
					{
						index0 = UV->GetIndexArray().GetAt(VertexCounter);
						vertices[VertexCounter].Texture.x = static_cast<float>(UV->GetDirectArray().GetAt(index0).mData[0]);
						vertices[VertexCounter].Texture.y = static_cast<float>(UV->GetDirectArray().GetAt(index0).mData[1]);
					}
						break;

					default:
						break; //TBD error
					}
					break;
				}
			}
			else{
				vertices[VertexCounter].Texture = XMFLOAT2(0.0f, 0.0f);

			}





			VertexCounter++;
		}
	}

	IndexLoadingEnded:
	
	
	Result->IndexArray[Result->VertexArrayCount] = new unsigned int[index]; //index is now the count of indices
	memcpy(Result->IndexArray[Result->VertexArrayCount], IndexArray, sizeof(unsigned int)*index);
	
	Result->VertexArray[Result->VertexArrayCount] = new VertexType[VertexCounter];
	memcpy(Result->VertexArray[Result->VertexArrayCount], vertices, sizeof(VertexType)*VertexCounter);

	Result->IndexCountArray[Result->VertexArrayCount] = index;
	Result->VertexCountArray[Result->VertexArrayCount] = VertexCounter;

	SAFE_ARRAY_DELETE(VertexUsedArray)

	Result->VertexArrayCount++;

}


void FbxLoader::EndLoading(){

	if (SdkManager){
		SdkManager->Destroy();
	}
	SAFE_ARRAY_DELETE(IndexArray)
	SAFE_ARRAY_DELETE(vertices)
}



void FbxLoader::ProcessSkeleton(FbxNode* Node, ReturnType* Result, BoneType** Bone){
	
	FbxSkeleton* Skeleton=Node->GetSkeleton();
	if (!Skeleton){
		*Bone = 0;
		return;
	}
	const char* Name=Skeleton->GetInitialName();
	*Bone = new BoneType;
	
	(*Bone)->UniqueID = Node->GetUniqueID();
	(*Bone)->AnimationArray = 0;
	CopyToNewString(&((*Bone)->Name), Name);


	
	int i, ChildCount = Node->GetChildCount();
	if (ChildCount != 0){
		(*Bone)->Children = new BoneType*[ChildCount];
		for (i = 0; i < ChildCount; i++){
			ProcessSkeleton(Node->GetChild(i), Result, &((*Bone)->Children[i]));
		}
	}
	else{
		(*Bone)->Children = 0;
	}
	(*Bone)->ChildCount = ChildCount;
	(*Bone)->ID = Result->BoneCount;
	Result->BoneCount++;
}

FbxAMatrix FbxLoader::GetGeometryTransformation(FbxNode* Node)
{
	if (!Node)
	{
		throw std::exception("Null for mesh geometry");
	}

	const FbxVector4 lT = Node->GetGeometricTranslation(FbxNode::eSourcePivot);
	const FbxVector4 lR = Node->GetGeometricRotation(FbxNode::eSourcePivot);
	const FbxVector4 lS = Node->GetGeometricScaling(FbxNode::eSourcePivot);

	return FbxAMatrix(lT, lR, lS);
}


void FbxLoader::ProcessBonesAndAnimations(FbxNode* Node, FbxScene* Scene, ReturnType* Result)
{
	int AnimStackCount = Scene->GetSrcObjectCount<FbxAnimStack>();
	Result->AnimationCount = AnimStackCount;

	FbxMesh* currMesh = Node->GetMesh();
	unsigned int numOfDeformers = currMesh->GetDeformerCount();
	
	FbxAMatrix geometryTransform = FbxLoader::GetGeometryTransformation(Node);

	WeightType* Weights = GetWeightArray(Node, Result);

	
	for (unsigned int deformerIndex = 0; deformerIndex < numOfDeformers; ++deformerIndex)
	{
		
		FbxSkin* currSkin = reinterpret_cast<FbxSkin*>(currMesh->GetDeformer(deformerIndex, FbxDeformer::eSkin));
		if (!currSkin)
		{
			continue;
		}

		unsigned int numOfClusters = currSkin->GetClusterCount();
		for (unsigned int clusterIndex = 0; clusterIndex < numOfClusters; clusterIndex++)
		{
			FbxCluster* currCluster = currSkin->GetCluster(clusterIndex);	
			BoneType* currBone = FindBoneByID(currCluster->GetLink()->GetUniqueID(), Result);
			FbxAMatrix transformMatrix;
			FbxAMatrix transformLinkMatrix;
			FbxAMatrix globalBindposeInverseMatrix;

			currCluster->GetTransformMatrix(transformMatrix);	// The transformation of the mesh at binding time
			currCluster->GetTransformLinkMatrix(transformLinkMatrix);	// The transformation of the cluster(joint) at binding time from joint space to world space
			globalBindposeInverseMatrix = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform;

			
			currBone->GlobalBindposeInverse = globalBindposeInverseMatrix;


			
			unsigned int numOfIndices = currCluster->GetControlPointIndicesCount();
			int* ControlPointIndices = currCluster->GetControlPointIndices();
			for (unsigned int i = 0; i < numOfIndices; ++i)
			{

				SetWeight(&(Weights[ControlPointIndices[i]]), currCluster->GetControlPointWeights()[i], currBone->ID);
			}

			if (!currBone->AnimationArray){
				currBone->AnimationArray = new AnimationType[AnimStackCount];
			}

			for (int i = 0; i < AnimStackCount; i++)
			{


				FbxAnimStack* lAnimStack = Scene->GetSrcObject<FbxAnimStack>(i);


				FbxTakeInfo* takeInfo = Scene->GetTakeInfo(lAnimStack->GetName());
				FbxTime start = takeInfo->mLocalTimeSpan.GetStart();
				FbxTime end = takeInfo->mLocalTimeSpan.GetStop();




				FbxLongLong AnimationLength = end.GetFrameCount(FbxTime::eFrames24) - start.GetFrameCount(FbxTime::eFrames24) + 1;
				currBone->AnimationArray[i].KeyFrameArrayCount = AnimationLength;
				currBone->AnimationArray[i].KeyFrameArray = new KeyFrameType[AnimationLength];
				CopyToNewString(&(currBone->AnimationArray[i].Name), lAnimStack->GetName());

				int k = 0;
				for (FbxLongLong j = start.GetFrameCount(FbxTime::eFrames24); j <= end.GetFrameCount(FbxTime::eFrames24); j++)
				{
					FbxTime currTime;
					currTime.SetFrame(j, FbxTime::eFrames24);

					currBone->AnimationArray[i].KeyFrameArray[k].FrameNumber = k;

					FbxVector4 Rotate, Scale, Translate;
					
					FbxAMatrix currentTransformOffset = Node->EvaluateGlobalTransform(currTime) * GetGeometryTransformation(Node);
					FbxAMatrix GlobalTransform = currentTransformOffset.Inverse() * currCluster->GetLink()->EvaluateGlobalTransform(currTime);
					
					Rotate = GlobalTransform.GetR();
					
					currBone->AnimationArray[i].KeyFrameArray[k].Rotate.x = -Rotate.mData[0];
					currBone->AnimationArray[i].KeyFrameArray[k].Rotate.y = -Rotate.mData[1];
					currBone->AnimationArray[i].KeyFrameArray[k].Rotate.z = Rotate.mData[2];
					
					Scale = GlobalTransform.GetS();
					
					currBone->AnimationArray[i].KeyFrameArray[k].Scale.x = Scale.mData[0];
					currBone->AnimationArray[i].KeyFrameArray[k].Scale.y = Scale.mData[1];
					currBone->AnimationArray[i].KeyFrameArray[k].Scale.z = Scale.mData[2];

					Translate = GlobalTransform.GetT();
					
					currBone->AnimationArray[i].KeyFrameArray[k].Translate.x = Translate.mData[0];
					currBone->AnimationArray[i].KeyFrameArray[k].Translate.y = Translate.mData[1];
					currBone->AnimationArray[i].KeyFrameArray[k].Translate.z = -Translate.mData[2];

					currBone->AnimationArray[i].KeyFrameArray[k].GlobalTransform=XMFLOAT4X4(
						GlobalTransform.mData[0].mData[0], GlobalTransform.mData[1].mData[0], GlobalTransform.mData[2].mData[0], GlobalTransform.mData[3].mData[0],
						GlobalTransform.mData[0].mData[1], GlobalTransform.mData[1].mData[1], GlobalTransform.mData[2].mData[1], GlobalTransform.mData[3].mData[1],
						GlobalTransform.mData[0].mData[2], GlobalTransform.mData[1].mData[2], GlobalTransform.mData[2].mData[2], GlobalTransform.mData[3].mData[2],
						GlobalTransform.mData[0].mData[3], GlobalTransform.mData[1].mData[3], GlobalTransform.mData[2].mData[3], GlobalTransform.mData[3].mData[3]);

					k++;
				}
			}
		}
	}

	
}




void FbxLoader::CopyToNewString(char** Dest, const char* Src){
	if (Src == 0){
		*Dest = 0;
		return;
	}
	*Dest = new char[strlen(Src) + 1];
	memcpy(*Dest, Src, strlen(Src) + 1);
}



FbxLoader::BoneType* FbxLoader::FindBoneByID(unsigned long long ID, ReturnType* Result){
	
	BoneType* tempBone = Result->RootBone;
	std::queue < BoneType* > BoneQueue;

	while (tempBone){

		if (ID==tempBone->UniqueID){
			return tempBone;
		}


		for (int i = 0; i < tempBone->ChildCount; i++)
		{
			BoneQueue.push(tempBone->Children[i]);
		}

		if (BoneQueue.size() > 0)
		{
			tempBone = BoneQueue.front();
			BoneQueue.pop();
		}
		else
		{
			tempBone = NULL;
		}


	}
	return 0;
}


FbxLoader::WeightType* FbxLoader::GetWeightArray(FbxNode* Node, ReturnType* Result){
	//assuming that count of meshes is smaller than count of nodes
	int i=0;
	while (Result->MeshArray[i]){
		if (Result->MeshArray[i] == Node){
			return WeightArray[i];
		}
		i++;
	}
	return 0;
}

void FbxLoader::SetWeight(WeightType* WeightPtr, float Weight, int BoneID){
	if (WeightPtr->CurrID > 3){
		return;
	}
	WeightPtr->Weights[WeightPtr->CurrID] = Weight;
	WeightPtr->BoneID[WeightPtr->CurrID] = BoneID;
}
animatedmodel.vs:
////////////////////////////////////////////////////////////////////////////////
// Filename: model.vs
////////////////////////////////////////////////////////////////////////////////


struct BoneMatrixType{
	matrix BoneMatrix[64];
};


cbuffer MatrixBuffer
{
	matrix worldMatrix;
	matrix viewMatrix;
	matrix projectionMatrix;
};

cbuffer BoneMatrixBuffer{
	BoneMatrixType BoneMatrices[16];
};



struct VertexInputType
{
    float4 position : POSITION;
	float4 normal : NORMAL;
	float2 tex : TEXCOORD;
	float4 boneWeights : BONEWEIGHT;
	uint4 boneIDs : BONEID;
	uint instanceID : SV_InstanceID;
	row_major matrix instanceWorld : WORLD;
	row_major matrix instanceRotate : ROTATE;
	float alpha : ALPHA;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
	float3 normal : NORMAL;
	float4 worldPosition: WORLDPOSITION;
	float2 tex : TEXCOORD0;
	float alpha : ALPHA;
};


////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType AnimatedModelVertexShader(VertexInputType input)
{
    PixelInputType output;
    

	// Change the position vector to be 4 units for proper matrix calculations.
    input.position.w = 1.0f;
	input.normal.w=0.0f;

	float4 positions[4];

	
	positions[0]=mul(input.position,BoneMatrices[input.instanceID%16].BoneMatrix[input.boneIDs.x]);
	positions[1]=mul(input.position,BoneMatrices[input.instanceID%16].BoneMatrix[input.boneIDs.y]);
	positions[2]=mul(input.position,BoneMatrices[input.instanceID%16].BoneMatrix[input.boneIDs.z]);
	positions[3]=mul(input.position,BoneMatrices[input.instanceID%16].BoneMatrix[input.boneIDs.w]);
	

	if(input.boneWeights.x!=0.0f || input.boneWeights.y!=0.0f || input.boneWeights.z!=0.0f || input.boneWeights.w!=0.0f){
		output.position=input.boneWeights.x*positions[0] + input.boneWeights.y*positions[1] + input.boneWeights.z*positions[2] + input.boneWeights.w*positions[3];
	}
	else{
		output.position=input.position;
	}
	// Calculate the position of the vertex against the world, view, and projection matrices.
	
    output.position = mul(output.position, input.instanceWorld);
    output.worldPosition=output.position;
	output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);
    
	output.alpha=input.alpha;

	output.normal=normalize(mul(input.normal,input.instanceRotate).xyz);

	output.tex=input.tex;
    
    return output;
}
How can I fix the size of the clothes and their positions? What is wrong with the animation? (Yes, I know that the animation speed currently depends on the fps, I will change this when the rest of the animation process works.)

I don't even know if the FbxLoader is correct. There may be something wrong but I don't know much about the FBX SDK and the explanations in the documentation of this SDK are... I don't know if I want to call them "explanations", because there is almost nothing explained...

Greetings,
Magogan

PS: Sorry for my bad English biggrin.png

This topic is closed to new replies.

Advertisement