How skeletons are stored in Outcast (this is generalization)
=============================================================
Each joint is defined like this:
integer index (always starting with 1, leaving 0 for whole object root)
string name 
vector position
matrix rotation


Example (all human like characters have this sort of skeleton)
==============================================================
(position, rotation) omitted
1, BIPED
2, LF_HIP
3, LF_KNEE
4, LF_ANKLE
5, LF_TOES
2, RT_HIP
3, RT_KNEE
4, RT_ANKLE
5, RT_TOES
2, BACK
3, NECK
4, HEAD
5, LF_EYEBROW
5, RT_EYEBROW
4, JAW
3, LF_SHOULDER
4, LF_ELBOW
5, LF_WRIST
6, LF_FINGERS
6, LF_THUMB
3, RT_SHOULDER
4, RT_ELBOW
5, RT_WRIST
6, RT_FINGERS
6, RT_THUMB
The whole object root is implicit and its index is 0.

It looks like this taking hierarchy into account
implicit root                   0
 BIPED                          1
  LF_HIP                        2
   LF_KNEE                      3
    LF_ANKLE                    4
     LF_TOES                    5
  RT_HIP                        2
   RT_KNEE                      3
    RT_ANKLE                    4
     RT_TOES                    5
  BACK                          2
   NECK                         3
    HEAD                        4
     LF_EYEBROW                 5
     RT_EYEBROW                 5
    JAW                         4
   LF_SHOULDER                  3
    LF_ELBOW                    4
     LF_WRIST                   5
      LF_FINGERS                6
      LF_THUMB                  6
   RT_SHOULDER                  3
    RT_ELBOW                    4
     RT_WRIST                   5
      RT_FINGERS                6
      RT_THUMB                  6


Traversal and reconstruction
============================
Matrices are 4x4 homogenous

matrix rotations[max(index)]            # temporary storage, stack in reality
vector positions[len(skeleton)]         # joint positions after reconstruction
rotations[0] = identity_matrix

i = 0
for joint in skeleton:
    parent_index = joint.index - 1
    parent_rotation = rotations[parent_index]

    ## rotation is around joint, not origin
    rotation = translation(-joint.position) * joint.rotation * translation(joint.position)
    rotations[joint.index] = parent_rotation * rotation # rotations are accumulated

    ## store the coordinates of joint in array
    positions[i] = joint.position * parent_rotation
    i = i + 1

Animations
==========
Each frame(?) is defined as array of following structures:
integer index
short OX 
short OY
short OZ

OX,OY,OZ rotation angles (fixed point)

Most indices start with 0, some with 2, one with 1.


Examples
=========
First skeleton idinces, then anim's

x_tentacle       [16] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14]
tentacle_grab    [ 8] [0, 1, 2, 3, 4, 5, 6, 6]
tentacle_spit    [16] [0, 1, 2, 3, 4, 5, 6, 7, 8,  9, 10, 11, 12, 13, 14, 13]
tentacle_stop1   [18] [0, 1, 2, 3, 4, 5, 6, 7, 8,  9, 10, 11, 12, 13, 14, 15, 13, 14]

x_shark          [ 7] [1, 2, 3, 4, 5, 2, 2]
shark_attack     [ 7]    [1, 2, 3, 4, 5, 2, 2] this is the only anim with first index = 1
shark_swim       [ 5] [0, 1, 2, 3, 4]

x_aquarex        [30] [1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 4, 5, 6, 7, 4, 5, 6, 7, 3, 4, 5, 6, 3, 4, 5, 6, 3, 4, 5, 6]
gorgor_slow_walk [30] [0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 3, 4, 5, 6, 3, 4, 5, 6, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5]

Tentacle (wireframe, skeleton)

Tentacle in wireframeTentacle's skeleton

Shark (wireframe, skeleton)

Shark in wireframeShark's skeleton

Aquarex(aka Gorgor) (wireframe, skeleton)

Aquarex in wireframeAquarex's skeleton

Additional information


Mail me

Valid HTML 4.0!