Jump to content
  • Advertisement
Sign in to follow this  
Magogan

Animating a model

This topic is 1422 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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 Edited by Magogan

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!