1 What defines a skeleton in SOTC
2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 Bones of the skeleton are defined by:
6 32 bit parent index (-1 if no parent)
7 32 bit index of child1 (-1 if no child1 (what for?))
8 32 bit index of child2 (-1 if no child2 (what for?))
13 [1..3] Translation vector
15 [5..7] Rotation (unit quaternion)
17 P.S. The above description doesn't mention Opt bones, but
18 they should be irrelevant if we drop IK from consideration,
19 besides animations (stored in .anb files) are defined in
20 terms of main bones only.
25 Skeleton can be visualized (brought to bind pose) like this:
27 quaternions[len (skeleton.bones) + 1]
28 translations[len (skeleton.bones) + 1]
30 quaternions[0] = (0, 0, 0, 1)
31 translations[0] = (0, 0, 0)
33 for bone in skeleton.bones:
34 parentquaternion = quaternions[bone.parent + 1]
35 parenttranslation = translations[bone.parent + 1]
37 p = quaternion_apply_to_point (parentquaternion, bone.translation)
38 p = vector_add (p, parenttranslation)
39 q = quaternion_compose (bone.quaternion, parentquaternion)
41 translations[bone.index + 1] = p
42 quaternions[bone.index + 1] = q
44 Thing is - quaternion_apply_to_point only "works" if we negate last
45 element of quaternion, i.e:
47 # Routine taken straight from the wikipedia article
48 # http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
49 def quaternion_apply_to_point (q, p):
50 a = -q[3] # why this must be negated?
67 r0 = 2*((t8 + t10)*v1 + (t6 - t4)*v2 + (t3 + t7)*v3) + v1
68 r1 = 2*((t4 + t6)*v1 + (t5 + t10)*v2 + (t9 - t2)*v3) + v2
69 r2 = 2*((t7 - t3)*v1 + (t2 + t9)*v2 + (t5 + t8)*v3) + v3