I'm using Assimp to do skeletal animation in my OpenGL application.
I used Blender to export this one-boned model to a COLLADA file: 
The model has only one bone, called arm bone, that controls the arm mesh. All the other meshes are static.
I made several structures and classes that help me play animations. All the nodes are added to an std::vector of Node objects. each Node contains aiNode data and a toRoot matrix. The bone hierarchy is encapsulated in a Skeleton class, and the animation matrix (T * R) are updated for each bone in a class called Animation.
My Model::Draw() function is this:
void Model::draw() { //iterate through all animation sets. if the animation is running, update the bones it affects. for(size_t i = 0; i < _animations.size(); i++) if(_animations[i].running()) _animations[i].updateAnimationMatrices(&_skeleton); //calculate Bone::finalMatrix for each bone _skeleton.calculateFinalMatrices(_skeleton.rootBone()); //iterate through the nodes and draw their meshes. for(size_t i = 0; i < _nodes.size(); i++) { _shaderProgram.setUniform("ModelMatrix", _nodes[i].toRoot()); _nodes[i].draw(); } } To get the "animationMatrix" for each bone (the TR matrix) I call Animation::updateAnimationMatrices(). Here's what it looks like:
void Animation::updateAnimationMatrices(Skeleton *_skeleton) { double time = ((double)_timer.elapsed() / 1000.0); while(time >= _animation->mDuration) time -= _animation->mDuration; //iterate through aiNodeAnim (called channels) and update their corresponding Bone. for(unsigned int iChannel = 0; iChannel < _animation->mNumChannels; iChannel++) { aiNodeAnim *channel = _animation->mChannels[iChannel]; Bone *bone = _skeleton->getBoneByName(channel->mNodeName.C_Str(), _skeleton->rootBone()); //rotation glm::mat4 R = ... //calculate rotation matrix based on time //translation glm::mat4 T = ... //calculate translation matrix based on time //set animation matrix for the bone bone->animationMatrix = T * R; bone->needsUpdate = true; } } Now in order to calculate the "finalMatrix" for each bone (based on animationMatrix, offsetMatrix etc..), and upload it to the vertex shader, I call Skeleton::calculateFinalMatrices().
void Skeleton::calculateFinalMatrices(Bone *root) { if(root) { Node *node = _getNodeByName(root->name->C_Str()); if(node == nullptr) { std::cout << "could not find corresponding node for bone: " << root->name->C_Str() << "\n"; return; } if(root->needsUpdate) //update only the bones that need to be updated (their animationMatrix has been changed) { root->finalMatrix = root->animationMatrix * root->offsetMatrix; //upload the bone matrix to the shader. the array is defined as "uniform mat4 Bones[64];" { std::string str = "Bones["; char buf[4] = {0}; _itoa_s(root->index, buf, 10); str += buf; str += "]"; _shaderProgram->setUniform(str.c_str(), root->finalMatrix); } root->needsUpdate = false; } for(unsigned int i = 0; i < root->numChildren; i++) calculateFinalMatrices(root->children[i]); } } Here's my bone structure, if it helps.
My glsl vertex shader is pretty standard. Here it is.
And finally, here's the result I get: (ignore the model's static legs. that must be some bug in the Blender exporter). 
And here's the result I should get: (using a 3d party software) 
It looks like there's something wrong with the bone's matrix calculation, although I don't know what. Any ideas or tips?
Thanks!