Add simple NTO viewer
[dormin.git] / reeng / skeletons.txt
blob50cf8d692dacb376a26486e1c75c6327c2a0c46e
1 What defines a skeleton in SOTC
2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 Bones of the skeleton are defined by:
5 32 bit index
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?))
9 9 floats
11 Floats:
12  [0]    0.0
13  [1..3] Translation vector
14  [4]    1.0
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.
22 Peculiarities
23 ~~~~~~~~~~~~~
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?
51       b   =  q[0]
52       c   =  q[1]
53       d   =  q[2]
54       p1  =  p[0]
55       p2  =  p[1]
56       p3  =  p[2]
57       t2  =  a*b
58       t3  =  a*c
59       t4  =  a*d
60       t5  = -b*b
61       t6  =  b*c
62       t7  =  b*d
63       t8  = -c*c
64       t9  =  c*d
65       t10 = -d*d
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
70       return (r0, r1, r2)