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.
|1||Transformation representation for each bone within an animation should support both rotation and translation||1|
|2||All 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 issue||2|
|3||The system must allow for the input assets to be stored in a memory efficient way to allow fast loading/streaming||2|
|17||Storage of animations, skeleton and mesh should be possible to separate files||2|
Animation Playback & Blending
|4||Ability to play back animations loaded from file or defined within memory||1|
|5||There should be allowed to specify a number of channels within each animation whereby it just affects certain bones, not the entire skeleton||1|
|6||The 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 bones||1|
|7||Multiple animations after each other should (if wanted) possibly have a cross-blend whereby one is blended out and the other in||1|
|8||When 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 itself||2|
|9||Upon animation transition the system should automatically be able to select from a database of transition animations and add that into the blend queue||2|
|10||Apart from pregenerated animations there should be support for using an IK solver for a specific set of bones with a specific target||2|
Mesh & Skinning
|11||Each vertex within the mesh must allow for at least four bone indices and blending weights||1|
|12||The mesh should allow for multiple subparts of the mesh to be specified||2|
|13||Each vertex could allow for more than four, but some other multiple of four, bone indices and blend weights||3|
|14||For each subpart of a mesh a number of morph targets (vertex targets) and associated blending||3|
Additional data in animations
|15||Associated with each animation should be a track of markers such as blend in/out points, application specific markers etc||2|
|16||An animation can apart from just skeletal poses define morph targets and morph target weights||3|
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
- 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 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 Base 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 Comments
Name Skeleton SCF IF iSkeleton Base 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 Comments Bone ID in Skeleton and SkeletonFactory are always same.
Name FactoryBone SCF IF Base Description Representation of a single bone within a skeleton factory Key methods Key data uint parent csQuaternion rotation csVector offset Comments Not externally exposed
Name Bone SCF IF Base Description Representation of a single bone within a skeleton. Key methods Key data uint parent (@@NEEDED? avoid indirection via factory..) csQuaternion rotationBindRel csVector offsetBindRel Comments Not externally exposed
Name SkeletalState SCF IF Base Description Holds an optimized representation of a skeleton during the animation mixing and blending stage Key methods Key data csDualQuaternion* state uint32* bitmapModified Comments Cached copies of this is allocated from a pool when needed. Always allocated & deallocated (including state array) in animation plugin.
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 Base Description Representation of a full mesh Key methods Key data csArray<Submesh> submeshList csVectorN* vertices, textureCoordinates, normals Comments
Name Submesh SCF IF iAnimatedSubmesh Base Description Representation of a submesh mesh Key methods Key data size_t* indexList Comments
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.
Name SCF IF iAnimationNode Base 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 Comments
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 Comments 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 Base 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 Comments At most one channel per bone
Name AnimationChannel SCF IF Base Description A single channel of keyframes (for one bone) Key methods Key data uint boneId float* time csDualQuaternion* keyframes Comments Not externally exposed