http://www.amnesty.org/en/campaigns/stop-violence-against-women

Inverse Kinematics - Basics

What is a Bone object ?

Figure 1: A single bone
A bone is the fundamental building block when doing inverse kinematics with the library FXUtil. A bone has a length and a joint around which it can be rotated. The end with the joint is called the head of the bone, the other one is called the tail.

Figure 1 shows a single bone, its head, tail, and length. The bone rotates around its joint.
1 Bone {
2 currentLength: 50
3 currentAngle: 0
4 }

Code Sample 1: Creating a single bone

In the library FXUtil, a bone is resembled by the class Bone. The minimum set of variables usually required to initialize a Bone object are currentAngle to setup the rotation and currentLength for the length of the bone. Code Sample 1 sets up a bone with a length of 50 and a rotation of 0, which means it will point horizontally to the right.

Assembling bones

Figure 2: Two connected bones
Bones can be assembled to define the skeleton of an animated object. Two bones are linked by attaching the tail of one bone b1 with the head of another bone b2. Bone b1 is called the parent of bone b2, bone b2 is called a child of bone b1. Figure 2 shows two connected bones b1 and b2.

The class Bone offers two variables to define the structure. The variable parent stores the parent of a bone, the variable children is a sequence of all child-bones. To connect two bones, only one direction has to be set, the other is set automatically. In other words, to link the bones b1 and b2 from the example above, one can either add b2 to the children of b1:
insert b2 into b1.children;
or set the parent of b2:
b2.parent = b1;
The instance variable currentAngle defines the rotation between a bone and the extension of its parent bone. A value of 0 results in a straight line, a value of 180 results in the child bone overlapping its parent, but pointing in the opposite direction.

Structure of the dummy
Figure 3: Structure of the dummy
Although having parents and children imposes an order on the bones in a skeleton, it usually makes no difference, which bone is the parent and which is the child. There is just one exception, when angles are limited, which will be covered in part 2 of this tutorial.

By repeatedly linking heads and tails of Bone objects, it is possible to create a chain. This simple structure is used in the caterpillar sample. For more complex objects, this is not sufficient. As the variable children suggests, a Bone object can have more than one child bone, which allows to define a tree structure.

The bone at the top of the tree, which does not have a parent, is called the root bone. The root bone is treated a little different then other bones during initialization. The position of a bone is usually defined by the position of its parent and its rotation, which is measured relative to the parent's extension.

But for a root bone the position can be set by initializing currentHead. (Note: Setting currentHead for any other bone has no effect; the value is simply ignored.) The second difference is, that the instance variable currentAngle of a root bone defines its rotation in the overall scene. You can think of it as having a parent bone which points horizontally to the right.

Now we are able to define the structure of our dummy, as shown in Figure 3. The code to generate the skeleton of the dummy can be seen in Code Sample 2.
 1 def head: Bone = Bone {
2 currentAngle: 90
3 currentLength: 30
4 }
5
6 def torso: Bone = Bone {
7 parent: head
8 currentAngle: 0
9 currentLength: 80
10 }
11
12 def upperArm: Bone[] = for (i in [0..1]) {
13 Bone {
14 parent: head
15 currentLength: 60
16 currentAngle: 60 - 90*i
17 }
18 }
19
20 def lowerArm: Bone[] = for (i in [0..1]) {
21 Bone {
22 parent: upperArm[i]
23 currentLength: 60
24 currentAngle: -90
25 }
26 }
27
28 def upperLeg: Bone[] = for (i in [0..1]) {
29 Bone {
30 parent: torso
31 currentLength: 60
32 currentAngle: 30 - 90*i
33 }
34 }
35
36 def lowerLeg: Bone[] = for (i in [0..1]) {
37 Bone {
38 parent: upperLeg[i]
39 currentLength: 75
40 currentAngle: 90
41 }
42 }

Code Sample 2: Creating the structure of the dummy

Attaching visual elements

Figure 4: A bone with attached visual elements
Bones themselves are not visible. They are only defining the structure. The instance variable content, which is a sequence of javafx.scene.Node objects, can be used to attach visible elements to a bone.

The position and rotation of the attached Node objects is controlled by the underlying bone. The origin of the local coordinate system for all attached nodes is the head position of the bone. If the head position is moved, so are all nodes.

The rotation of a bone is also passed to the nodes. If the bone is not rotated at all and currentAngle has the value 0, it is pointing horizontally to the right.

In Code Sample 3 a bone is defined with two circles and an ellipse attached. In Figure 4 this bone is shown and animated. The attached nodes are moved and rotated according to the position of the bone.
 1 Bone {
2 currentHead: Point2D {x: 30, y: 30}
3 currentLength: 50
4 currentAngle: 0
5 content: [
6 Circle {radius: 20}
7 Ellipse {radiusX: 25, radiusY: 15, centerX: 45}
8 Circle {centerX: 80, radius: 10}
9 ]
10 }

Code Sample 3: Attaching visual elements to a bone

Dummy with all visual components attached
Figure 3: Dummy with all visual components attached
Code Sample 4 shows the required changes define the appearance of our dummy by attaching circles and rectangles. The resulting dummy can be seen in Figure 5. In the picture, I added symbols for the bones to make them visible.

Note that none of the visual components are rotated themselves and all positions are local to the bone. The final positions and rotations in the scene are calculated from the positions and rotations of the bones only.
 1 def head: Bone = Bone {
2 [...]
3 content: Ellipse {radiusX: 20, radiusY: 15}
4 }
5
6 def torso: Bone = Bone {
7 [...]
8 content: Ellipse {radiusX: 50, radiusY: 20, centerX: 40}
9 }
10
11 def upperArm: Bone[] = for (i in [0..1]) {
12 Bone {
13 [...]
14 content: Ellipse {radiusX: 30, radiusY: 12.5, centerX: 22.5}
15 }
16 }
17
18 def lowerArm: Bone[] = for (i in [0..1]) {
19 Bone {
20 [...]
21 content: [
22 Circle {radius: 12.5}
23 Ellipse {radiusX: 20, radiusY: 12.5, centerX: 30}
24 Circle {radius: 12.5, centerX: 60}
25 ]
26 }
27 }
28
29 def upperLeg: Bone[] = for (i in [0..1]) {
30 Bone {
31 [...]
32 content: Ellipse {radiusX: 30, radiusY: 15, centerX: 20}
33 }
34 }
35
36 def lowerLeg: Bone[] = for (i in [0..1]) {
37 Bone {
38 [...]
39 content: [
40 Circle {radius: 15}
41 Ellipse {radiusX: 30, radiusY: 15, centerX: 40}
42 Ellipse {radiusX: 10, radiusY: 22.5, centerX: 75, centerY: -10}
43 ]
44 }
45 }

Code Sample 4: Attaching visual elements to the dummy

Adding everything to the scenegraph

Now there is just one final information missing to be able to render the dummy on the screen: the class Skeleton. The class Skeleton is the bridge between the scenegraph and the bones with the attached Node objects. It extends CustomNode and can therefore be added anywhere in a scenegraph. It can be translated, rotated, scaled and transformed like any other node in the scenegraph.

A Skeleton object and the bones of an animated object are linked by setting the instance variable skeleton of one bone. You will notice that the variable skeleton of all bones in the same structure will be updated to point to the same Skeleton object afterwards, because it is not possible that two bones in the same structure point to different Skeleton objects.

To see the result, download the full script. To compile the script, you need to add the library FXUtil to your classpath. You can download it from FXUtil.com. To add it to the classpath for example in a NetBeans project, open the Project Properties and add the jar-file in the section “Libraries”.

What's next?

The first part of this tutorial showed how to define the static structure – or skeleton – of an animated object and how to attach visible components. The second part will explain how this structure can be animated to create naturally looking animations.

Comments

Inverse Kinematics - Basics
Thank you Michael. I think this library most important and useful then other libraries. Because animation very important piece of RIA.
18 Mar : 10:32

Inverse Kinematics - Basics
Very Straightforward Design/Implementation. I look forward to more tutorials with frossos... WJ
15 Aug : 02:38


You must be logged in to make comments on this site - please log in, or if you are not registered click here to signup
This site is powered by e107, which is released under the terms of the GNU GPL License.