Inverse Kinematics Tutorial
February 17, 2004
by Christoffer Enedahl
Prolog
This is my first tutorial. I hope it will be worth your time. This tutorial will only show you the basics of a 2 limbs solution for inverse kinematics (IK). It will not handle angle restrictions, dampening, or any other such features. It will not describe vector math, but you will find a trigonometry library in the source. Basically it will give you the math and source code for calculating the angles of a triangle.
Demo can be viewed here (opens in a new window)
Basics
As you can see in Figure 1, the whole thing is about finding out the angles of a triangle with sides of known lengths. The structure of the bones and IK objects can be found in the source, that is not what I will describe here. Almost all angles in the code are radians but I'll describe them in degrees for better understanding.
Figure 1
Get Your Hands Dirty
Here is the function that returns the radian angle x of the far side of a triangle with known lengths. The triangle does not need to be a right triangle. The first argument, c, is the length of the side opposite the corner you want to calculate. You can ignore the order of a and b, they're interchangeable.
-- The code is cut from trigmath v0.6 parentscript.
on GetFarAngle (me,c,a,b)
--
-- |\
-- |x\
-- a | \ b
-- |___\
-- c
--
-- x = a*a + b*b - c*c
-- x = x / float(2*a*b)
-- x = me.InvCos(x)
--
-- return x
if a*b = 0 then return 0
return me.InvCos((a*a+b*b-c*c)/float(2*a*b))
end
on InvCos me, X
y = Sqrt(-X * X + 1)
if y = 0 then return 0--y --NAN
return atan(-X / y) + 2 * pAtan1
end
Let's calculate the angles of our triangle from figure 1
put gTrig.GetFarAngle ( 185, 225 ,104 )
-- 0.9502
put gTrig.RadToDegree (0.9502)
-- 54.4424
put gTrig.GetFarAngle ( 225, 104 ,185 )
-- 1.7164
put gTrig.RadToDegree (1.7164)
-- 98.3425
OK, so we got a 55° angle for the first bone and 98° angle for the second. If we try to assign those values to the bone, it will behave strangely. We need to offset the angle from the goal angle. The goal angle is the angle between the goal and the first bone's starting position. The goal here is pTarget.
a = pTarget.GetLoc ()
b = pBoneChain[1].GetLoc ()
vGoalVector = a-b
vGoalAngle = gTrig.VectorToAngle (vGoalVector)
vGoalLength = gTrig.Magnitude2d (vGoalVector)
There is one thing to keep in mind with the trigonometry code. A 0° angle is to the right and 90° angle is down. But for our Director sprite, 0° is up. So we will have to compensate for that by -90°. This compensation really belongs in the drawing routine, but now it ain't. In this case the goal angle is about 35° angle (starting from the right 0° angle)
--First bone
-- vGoalAngle - vCorner1Angle + 90
put +35 - 55 + 90
-- 70
That seems to be correct according to figure 1 with 0° angle up. The next bone is simple, use the angle from the first bone and add the second corner angle
--Second bone
-- vBone[1].GetTheta() + vCorner1Angle
put 70 + 76
--146
So far, so good. In the source, this part will be slightly messed up by the fact that I have the bone gfx upside down. I know it's kinda stupid. So do better than me.
Now, if you've coded your way here, you'll have a working leg. You should now notice that the leg is bent in one direction only. This is easily fixed, I use a pDirection property in the IK object. It can be -1 or 1, use it to flip the corner angle before calculating the final bone angle. You will need to flipH the sprite as well.
--First bone
-- vGoalAngle - vCorner1Angle*pDirection + 90
put +35 - (55*-1 ) + 90
-- 180
--Second bone
-- vBone[1].GetTheta() + vCorner2Angle
put 180 + (76*-1)
--104
Early Out
First of all, you should check that the leg can reach the target. If not, point the leg towards the target as in figure 2. There is one case when this code breaks. Try moving the target so close to the leg's starting point that it can't reach it, the leg flips. I haven't tried to fix this yet.
Figure 2
That's all folks! That covers the basics, so start coding your own spider or some other beast and show me the results. For more on this subject, see Christophe Leske's Undocumented Lingo site.
Archive files of this Director 8.5-compatible movie are available in ZIP and SIT formats.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.