

  • 1
    \$\begingroup\$ Could you explain a bit better whether you want help extracting the animation from the Assimp graph or actually implementing animation. Assimp animations are stored as transforms for nodes (which can be anything - including bones) in the Animations array (scene/model level). They are straightforward to extract, but its not 100% clear if that is actually what you are asking :) \$\endgroup\$ – sebf Mar 29 '12 at 14:47
  • \$\begingroup\$ I need help extracting the animation from the file, and I also need to know how to run the animation in the game. \$\endgroup\$ – Brendan Webster Mar 29 '12 at 17:03

I personally think Assimp is a wonderful idea, and has saved me countless hours, but translating their graph to your engine is writing an importer and learning everything required to do so.

I am assume you are referring to Skeletal animation, rather than blendshapes or just individual nodes (though the latter I'll mention anyway).


enter image description here


Importing the Animations

Importing the animation data is the simplest part of the process. The aiScene object will have a member aiAnimations which is a list of aiAnimation objects. Each aiAnimation will have a list of aiNodeAnim* objects, in the mChannels member. Essentially, each channel controls a single node, and contains a list of keyframes, each with a scale, a rotation, and a translation value for this node at a specific point in time. Animation tracks identify nodes to control via their name.


So, say you are animating "Box". You have already imported the node 'Box' with its geometry and you have an item in your world with a transform. To animate the box, get the animation from aiAnimations and iterate over each aiNodeAnim (channel) until you find one with the mNodeName matching "Box". Then, iterate over each of the Position, Scale, and Rotation keyframes in the mPositionKeys, mScalingKeys, and mRotationKeys members, transforming the value (Vectors or Quaternions, and the time offset) into whatever structure your application stores animation data in.

Then just pick a keyframe/interpolate between them as usual and apply the transform specified by the frame to that nodes local transform and see it move!

Extracting skeletal animation is an identical process, since in Assimp bones are just other nodes. The skinning data is slightly trickier. To animate a skinned model you need three things:


  2. The hierarchy of the skeleton


The first thing to do, though, is find the skeleton.

Finding the Skeleton

Assimp makes no distinction between 'bone nodes' and 'nodes', which means your importer will have to engage in some guesswork to pick the right starting node before reading in the whole tree.

The reason we need to find the skeleton is because, as can be seem from the diagram, each bone is parented to each other bone; the transforms extracted from the animation tracks/channels need to be combined with the transforms from other tracks to move the vertices correctly.

The way I do it is this:



Skinning Data

This is the trickiest bit, extracting the bones and weights from each mesh. The member you are looking for this time in mBones and it will be a member of aiMesh. It contains two things of interest:

  1. mOffsetMatrix - this is the skinning transform, or Inverse Bind Pose transform - you want to store this for each bone along with the bones original transform and the name of its parent.


Each aiVertexWeight object contains mVertexId (which identifies the vertex) and mWeight, which is the weighting of the bone. The mVertexId is the index of the vertex in the 'vertex array' that serves the mesh. What that means is that you have to define a 'master list' of bone names, so that you can assign a number to each bone and have it refer consistently to the same bone. Then you need to look up that number for the name of the aiBone object which contains the vertex weight. Now you can update the vertex in your mesh with the bone ids and weights.


enter image description here



If you have a skinned mesh then you should have:

a. A list of bones in a specific order
d. The parent for each bone in (a)

This is the "standard dataset" for skeletal animation, and if you know about skeletal animation then it's all you need! If not, that best be a different question since it's quite a large area ;)



  • 1
    \$\begingroup\$ Well this is a huge answer, and it definitely worth my upvote. \$\endgroup\$ – Valkea Mar 29 '12 at 23:12
  • \$\begingroup\$ This is an excellent write-up of assimp's animation import. Do you mind if I add a link to the assimp docs? \$\endgroup\$ – Alexander Gessler Jun 21 '12 at 1:18
  • 1
    \$\begingroup\$ @AlexanderGessler, Thanks! Not at all, go ahead - I'm glad after writing all that it is of use :) \$\endgroup\$ – sebf Jun 21 '12 at 20:15
  • \$\begingroup\$ you said you get "The bind pose transform for each bone in (a) (same place you got (d), or just take the inverse of the skinning transform)". Isn't the matrix you get in the node the local bind transform (the transform relative to the parent bone in the bind pose) what you actually get? If so, you'd need to multiply the transform with the parent's to-root transform to get the bind pose transform for the bone, wouldn't you? \$\endgroup\$ – Luca Mar 13 '18 at 22:27
  • 1
    \$\begingroup\$ @Luca, if you were computing it yourself from the hierarchy yes, but IIRC Assimp gives you the pre-multiplied inverse bind pose for each node. (By 'skinning transform' I meant world space transform.) \$\endgroup\$ – sebf Mar 14 '18 at 8:45





I hope this could help...

  • \$\begingroup\$ It might be worth noting that the "Open Asset Import Library animation loader" is very slow and precalculates every single animation keyframe (high memory usage) instead of computing it on the fly. By "fixing" it I gained a 15-fold speedup. \$\endgroup\$ – Tara Apr 29 '15 at 14:09

Your Answer

