Warning: Can't synchronize with the repository (Couldn't open Subversion repository /home/crystal/scm/crystal: SubversionException: ("Expected FS format between '1' and '3'; found format '4'", 160043)). Look in the Trac log for more information.

Comment page


As rewriting the character animation library there is a set of "must have" as well as a list of "want to have". Part of the distinction is based on priorities for the Apricot project.

As an overview the entire page concerns itself with a system for animation of meshes by the concept of skeletal animation, which means that a number of bones defines the movement and then a skin describes a mesh that deforms according to those bones.

The requirements are documented using a table syntax and priority assignment of 1-3, 1 is highest priority. When adding a new requirement, just use next number for it. Do not reuse requirement numbers.

Minimum required features

These are the feature that is definitely needed and will be required to implement very early in the lifetime of the system.


1Transformation representation for each bone within an animation should support both rotation and translation1
2All the runtime data structures should be to a great length be designed and optimized for optimal runtime performance. Ability to use the same format in file or editing as in the runtime part is less of an issue2
3The system must allow for the input assets to be stored in a memory efficient way to allow fast loading/streaming2
17Storage of animations, skeleton and mesh should be possible to separate files2

Animation Playback & Blending

4Ability to play back animations loaded from file or defined within memory1
5There should be allowed to specify a number of channels within each animation whereby it just affects certain bones, not the entire skeleton1
6The system should allow multiple animations playing at once without any form interaction between them for bones that have just a single animation channel applied to it. When multiple animation channels touch a specific bone it should be possible to set the relative strength of the animations as well as one operation overriding all the earlier animations on its affected bones1
7Multiple animations after each other should (if wanted) possibly have a cross-blend whereby one is blended out and the other in1
8When switching from animation A to animation B the switch should possibly be scheduled to be done directly or at a later time indicated within the animation itself2
9Upon animation transition the system should automatically be able to select from a database of transition animations and add that into the blend queue2

Animation generation

10Apart from pregenerated animations there should be support for using an IK solver for a specific set of bones with a specific target2

Mesh & Skinning

11Each vertex within the mesh must allow for at least four bone indices and blending weights1
12The mesh should allow for multiple subparts of the mesh to be specified2
13Each vertex could allow for more than four, but some other multiple of four, bone indices and blend weights3
14For each subpart of a mesh a number of morph targets (vertex targets) and associated blending3

Additional data in animations

15Associated with each animation should be a track of markers such as blend in/out points, application specific markers etc2
16An animation can apart from just skeletal poses define morph targets and morph target weights3

Future extensions


Coordinate spaces

There are a large number of possible and used coordinate representations in skeletons, this section (tries to:) define them.


  • World space - CS world, untransformed
  • Model space - Mesh object local space, transform to world via the iMovable transform. Base space for all skeleton/animation specific spaces

For skeletons:

  • Absolute space - Same as model space
  • Bone space - Coordinate space defined by the parent bone. Root bone have bone space equal to absolute space.
  • Bind space - Coordinate space relative to the bind pose. The bind pose is the skeletal pose when the skeleton is undeformed and defined by the skeletal factory. All skinning is done with bind space matrices.

The mesh and the mesh morph targets are specified in model space.

Skeleton representation

Skeleton is represented as a tree hierarchy of bones. No cycles are allowed. Each bone is is represented by a parent, quaternion for orientation and a vector for offset. Coordinates are relative to the parent bone and the root bone is relative to the model space.

Name         SkeletonFactory
SCF IF       iSkeletonFactory
Description  Representation of the full skeleton of a character as defined.
Key methods  uint CreateBone(uint parent)
             bool RemoveBone(uint index)
             uint GetBoneParent(uint index)
             void SetBoneTransform(uint index, csQuaternion rotation, csVector offset)
             void GetBoneTransform(uint index, csQuaternion& rotation, csVector& offset)
             void GetBoneAbsoluteTransform(uint index, csQuaternion& rotation, csVector& offset)
Key data     csArray<FactoryBone*> bones
Name         Skeleton
SCF IF       iSkeleton
Description  Representation of the full skeleton of a character instance.
Key methods  iSkeletonFactory* GetFactory()
             void SetBoneTransform(uint index, csQuaternion rotation, csVector offset)
             void GetBoneTransform(uint index, csQuaternion& rotation, csVector& offset)
             void GetBoneAbsoluteTransform(uint index, csQuaternion& rotation, csVector& offset)
             void SetBoneTransformBindRel(uint index, csQuaternion rotation, csVector offset)
             void GetBoneTransformBindRel(uint index, csQuaternion& rotation, csVector& offset)
Key data     SkeletonFactory* factory
             csArray<Bone*> bones
Bone ID in Skeleton and SkeletonFactory are always same.
Name         FactoryBone
Description  Representation of a single bone within a skeleton factory
Key methods
Key data     uint parent
             csQuaternion rotation
             csVector offset
Not externally exposed
Name         Bone
Description  Representation of a single bone within a skeleton.
Key methods
Key data     uint parent              (@@NEEDED? avoid indirection via factory..)
             csQuaternion rotationBindRel
             csVector offsetBindRel
Not externally exposed
Name         SkeletalState
Description  Holds an optimized representation of a skeleton during the animation mixing and blending stage
Key methods
Key data     csDualQuaternion* state
             uint32* bitmapModified
Cached copies of this is allocated from a pool when needed. Always allocated & deallocated (including state array) in animation plugin.

Mesh representation

The mesh is represented as a mesh containing the raw data such as vertices and normals together with a set of submeshes that defines triangles making up body parts.

Name         Mesh
SCF IF       iAnimatedMesh
Description  Representation of a full mesh
Key methods
Key data     csArray<Submesh> submeshList
             csVectorN* vertices, textureCoordinates, normals
Name         Submesh
SCF IF       iAnimatedSubmesh
Description  Representation of a submesh mesh
Key methods
Key data     size_t* indexList

Skeletal animations


Skeletal animation is represented on two levels. At the foundation it is made up of a number of individual animations, each consisting of a set of channels, one for every bone affected. Every channel is made up of a list of keyframes with a transform and time. Animations can either be played cyclic or as a "one shot" thing.

The animations are mixed together using a tree of nodes defining mixing/blending operations.

SCF IF       iAnimationNode
Description  Base interface for nodes in the animation tree
Key methods  void BlendState(SkeletalState* state, float baseWeight)
             void TickAnimation(float dt)
             bool IsActive()
Key data     
Name         Animation
SCF IF       iAnimation
Base         iAnimationNode
Description  Animation instance for an animation
Key methods  void PlayOnce(float speed = 1)
             void PlayCyclic(float speed = 1)
             void Stop()
             void Reset()
             void SetPlaybackPosition(float time)
Key data     float speed
             float currentTime
Cyclic playing means repetitive playback until manually stopped.
Playback speed is a scaling factor on time, either positive or negative.
Name         AnimationFactory
SCF IF       iAnimationFactory
Description  Animation factory defining the "base format" for an animation
Key methods  uint AddChannel(uint bone)
             void AddKeyframe(uint channel, float time, csDualQuaternion transform)
             void GetKeyframe(uint channel, uint keyframe, float& time, csDualQuaternion& transform)
             void GetTwoKeyframes(uint channel, float time, csDualQuaternion& transformBefore, csDualQuaternion& transformAfter)
Key data     float duration
             csArray<AnimationChannel> channels
At most one channel per bone
Name         AnimationChannel
Description  A single channel of keyframes (for one bone)
Key methods  
Key data     uint boneId
             float* time
             csDualQuaternion* keyframes
Not externally exposed

Mixing & Blending

Extra data

Morph animations


Mixing & Blending



File format