Hi, I'm coding my skeletal animation system for my engine and I'm not really sure what and how I'm supposed to do what I need to do... I have a vague idea, but I can't really put it into the code in a way that I like. I'm having trouble with both the concept and technical parts of it.
I have this structure:
class KeyFrame
{
public:
unsigned int keyFrame;
Vector3 keyValues;
};
class Bone
{
public:
//Other stuff to deal with hierarchy
vector<KeyFrame*> keyTranslates;
vector<KeyFrame*> keyRotates;
};
class Track
{
public:
wstring trackName;
bool trackLoop;
unsigned int frameStart;
unsigned int frameEnd;
};
class Skeleton
{
public:
vector<Track*> tracks;
vector<Bone*> bones;
//skeleton data here
float boneTranslations[MAX_BONES * 3]; //vec3 trans
float boneRotations[MAX_BONES * 4]; //quat rots
};
I'm already loading the data I want, so I have something like "Bone01: keyFrame 5 > TranslateX 0.5, keyFrame 10 > TranslateX -0.5" etc
Each model has a pointer to a skeleton, who has a collection of bones, and I define tracks:
class Model
{
public:
Skeleton* skeleton;
Track* currentTrack; //current playing track
};
//Game Start
Model* myModel = Resources.Load("myModelName");
myModel->skeleton = Resources.Load("mySkeletonName");
//Skeleton::AddTrack(wstring trackName, uint frameStart, uint frameEnd, bool trackLoop);
myModel->skeleton->AddTrack(L"WALK", 5, 10, true);
//Setting this model's current track as WALK
myModel->SetTrack(L"WALK");
So, first I think I need to change the "current track" to support multiple tracks to compose animations (such as WALK + ATTACK) right?
Then the problem I'm having most is figuring my "Update Skeleton" function:
void Model::Draw(Camera* camera, float& interpolation)
{
Shader* shader = material->GetShader();
skeleton->UpdateSkeleton(currentFrame); //this
meshSkin->Activate(shader);
mesh->Render(shader);
meshSkin->Deactivate(shader);
}
void Skeleton::Update(uint currentFrame)
{
for(uint i = 0; i < bones.size(); i++)
{
//checking ALL translates for that bone
for(uint j = 0; j < bones[i]->keyTranslates.size(); j++)
{
//what should I do here?
//check if this keyFrame value is higher or equal than currentFrame, then loop again
//to search for the previousKeyFrame (if it has one), then interpolate between the two,
//then interpolate again to find the middle (currentFrame)?
//And where/how does deltaTime fits into this? Maybe having a previousFrame as well?
//Actually, scratch this, this seems bad to do at every render call,
//I'd like to avoid doing this if I can and "remember" the animation motion I'm currently at
//for that model so I can skip this operation.
//...or a clever way to handle this
}
//Now check for rotations as well...
for(uint j = 0; j < bones[i]->keyRotates.size(); j++)
{}
}
}
I'm trying to save these operations by remembering the motion I was, but then I'd need to save in the model, for each bone, the previous keyFrame and the next keyFrame for all of them. And I would only need to figure the next motion when I reach the "nextKeyFrame". But this means basically having a copy of the skeleton's bones in the model... not sure if I should go this way.
I've been thinking since yesterday but I can't figure how should I proceed from here... any help?