|

A procedural dragonfly
rig
| In this lesson we will be
creating a procedural setup that will allow us to ease the animation
of this dragonfly. This tutorial will explore procedural walk-cycles
and conditional animation cycles. The model used in this rig is a
hybrid from several free models from 3D Cafe but you can download this
model here |
 |
A Procedural Walk Cycle
The first thing we would like to achieve with our model is that when
its body moves forward in the Z direction, we would like to have each of
its feet walking much the same way that an insect does.
Start Simple
Open the scene DragonFly_Simple.mb and note that a simple joint
hierarchy has been set up for the Left Middle leg, with a SC IK handle and
all finished off with a curve controller for the foot.
|
To develop our walk cycle we first need to
understand what a walk cycle consists of. Standard keyframed walk
cycles consist of;
1) Contact pose 2) Down extreme 3)
Passing pose 4) Up extreme 5) Another contact.
To recreate this procedurally we need to
first consider the behaviour of the translate X, Y & Z of the
foot controllers.
|
 |
The foot's translation in X, Y & Z remains constant from the point
of contact up until the moment when the opposing foot contacts the ground.
This means that for half of the cycle there is;
1) TranslateY = 0; 2) Translate X & Translate Z are unchanging.
(ie the foot stays put)
For the other half of the cycle when the opposing foot is planted, the
foot will be raising and advancing forward. That is to say;
1) TranslateY: will be increasing then decreasing (like a
projectile) 2) Translate X & Translate Z will be increasing
constantly to simplify things (essentially this means the foot
moves)
Step 1: Translate Y
Start by creating an expression for translateY for one of the feet to
make it raise up and down like a projectile (a sine curve does a good job
of that).
|
The problem we are faced with is that normally
a sine wave is driven by an angular value. We can see from the graph
that Y=0 when X=0, 180 & 360 degrees.
So if we would like each footstep to be 1 unit
long, each unit step in Z would have to correspond to 180 degrees,
ie;
180 degrees = 1 unit in Z |
 |
Which gives the expression;
LM_Foot_CON.translateY =
sind(180*Thorax.translateZ);
|
The problem with this approach is that the foot
continues through the floor for the second half of the cycle. To
prevent this we can use a MEL Maximum command.
LM_Foot_CON.translateY =
max(0,sind(180*Thorax.translateZ)); Now for the other foot. We want this foot to
reflect the actions of the first foot. We can do this by inverting
the function already applied to the left foot. |
 |
RM_Foot_CON.translateY =
max(0,-sind(180*Thorax.translateZ));
Translate Z
|
As you can see now, the feet lift off the
ground at the correct times in the cycle. The only problem is that
the feet slide backwards and forwards. Currently the feet move with
the Thorax so their TranslateZ equals that of the thorax. Instead we
would prefer the situation illustrated in the figure to the right.
As the feet are parented to the thorax we are dealing with a case of
relativity. So to determine the correct expression for the feet we
just need to understand that;
Desired global movement of feet = movement
of thorax + feet movement relative to the thorax |
 |
|
So the required adjustment will be that of the
desired footsteps minus the movement of the thorax.
This curve looks just like a sawtooth curve and
can be recreated using a modulus function. The modulus function
(written as % in MEL) is shown below. The example shows X with
modulus 2.

by shifting this modulus function in Y by half
its amplitude and in Z by 1 unit, then taking its absolute value, we
can obtain an expression that equates to the required adjustment
curve |
 |
LM_Foot_CON.translateZ =
abs((abs((Thorax.translateZ-1))%2)-1);
To get the correct expression for the other foot we just simply invert
the expression.
RM_Foot_CON.translateZ =
1-abs((abs((Thorax.translateZ-1))%2)-1);
Now that we have this working for two legs the next task is to get it
working for six...
Open up the original dragonfly file and copy the following expressions
onto the feet.
LF_CON.translateY =
max(0,sind(180*Thorax.translateZ)); LM_CON.translateY =
max(0,sind(180*Thorax.translateZ)); LB_CON.translateY =
max(0,sind(180*Thorax.translateZ)); RF_CON.translateY =
max(0,-sind(180*Thorax.translateZ)); RM_CON.translateY =
max(0,-sind(180*Thorax.translateZ)); RB_CON.translateY =
max(0,-sind(180*Thorax.translateZ));
and
LF_CON.translateZ =
abs((abs((Thorax.translateZ-1))%2)-1); LM_CON.translateZ =
abs((abs((Thorax.translateZ-1))%2)-1); LB_CON.translateZ =
abs((abs((Thorax.translateZ-1))%2)-1); RF_CON.translateZ =
1-abs((abs((Thorax.translateZ-1))%2)-1); RM_CON.translateZ =
1-abs((abs((Thorax.translateZ-1))%2)-1); RB_CON.translateZ =
1-abs((abs((Thorax.translateZ-1))%2)-1);
which essentially replicates what we discoverd above for all of the
feet.
The insect now walks, all feet touch the ground in the correct manner.
All we need to do now is add some character that will make it look more
like an insect's walk. For starters the insect's walk needs to have each
foot touching the ground at different times.
The easiest way from here is just to offset the front feet forward by half a unit in Z and backwards half a unit for the back feet;
LF_CON.translateY = max(0,sind(180*(Thorax.translateZ+0.5))); LM_CON.translateY =
max(0,sind(180*Thorax.translateZ)); LB_CON.translateY =
max(0,sind(180*(Thorax.translateZ-0.5))); RF_CON.translateY =
max(0,-sind(180*(Thorax.translateZ+0.5))); RM_CON.translateY =
max(0,-sind(180*Thorax.translateZ)); RB_CON.translateY =
max(0,-sind(180*(Thorax.translateZ-0.5))); LF_CON.translateZ =
abs((abs((Thorax.translateZ-0.5))%2)-1);
....... one half minus one LM_CON.translateZ =
abs((abs((Thorax.translateZ-1))%2)-1); LB_CON.translateZ =
abs((abs((Thorax.translateZ-1.5))%2)-1); RF_CON.translateZ =
1-abs((abs((Thorax.translateZ-0.5))%2)-1); RM_CON.translateZ =
1-abs((abs((Thorax.translateZ-1))%2)-1); RB_CON.translateZ =
1-abs((abs((Thorax.translateZ-1.5))%2)-1);
And there we have it... our walking insect. This probably won't be
perfect, but those who want to spend the time working out exactly the
right amount of delay... good luck to you!
Making it fly
Now we can write an expression for the wings
L_Wing_Shoulder.rotateZ =
45*sind(1000*Thorax.translateZ); R_Wing_Shoulder.rotateZ =
45*sind(1000*Thorax.translateZ);
Fly or Walk?
The last part we would like to achieve is to have a conditional switch
that stops the dragonfly walking when it gets higher than say 1 unit off
the ground.
To create a conditional expression we can use either the
if...then...else notation or alternatively we can use the (condition)? <if true> : <if
false> notation, which is much more compact. For example we can
change the above expression for the fly to;
L_Wing_Shoulder.rotateZ = (Thorax.translateY>1)?45*sind(1000*Thorax.translateZ):0; R_Wing_Shoulder.rotateZ = (Thorax.translateY>1)?45*sind(1000*Thorax.translateZ):0;
Similarly we can do the same for the walk.
LF_CON.translateY =
(Thorax.translateY>1)?0:(max(0,sind(180*(Thorax.translateZ+0.5)))); LM_CON.translateY
=
(Thorax.translateY>1)?0:(max(0,sind(180*Thorax.translateZ))); LB_CON.translateY
=
(Thorax.translateY>1)?0:(max(0,sind(180*(Thorax.translateZ-0.5)))); RF_CON.translateY
=
(Thorax.translateY>1)?0:(max(0,-sind(180*(Thorax.translateZ+0.5)))); RM_CON.translateY
=
(Thorax.translateY>1)?0:(max(0,-sind(180*Thorax.translateZ))); RB_CON.translateY
=
(Thorax.translateY>1)?0:(max(0,-sind(180*(Thorax.translateZ-0.5))));
LF_CON.translateZ =
(Thorax.translateY>1)?(-5):(abs((abs((Thorax.translateZ-0.5))%2)-1)); LM_CON.translateZ
=
(Thorax.translateY>1)?(-3):(abs((abs((Thorax.translateZ-1))%2)-1)); LB_CON.translateZ
=
(Thorax.translateY>1)?0:(abs((abs((Thorax.translateZ-1.5))%2)-1)); RF_CON.translateZ
=
(Thorax.translateY>1)?(-5):(1-abs((abs((Thorax.translateZ-0.5))%2)-1)); RM_CON.translateZ
=
(Thorax.translateY>1)?(-3):(1-abs((abs((Thorax.translateZ-1))%2)-1)); RB_CON.translateZ
=
(Thorax.translateY>1)?0:(1-abs((abs((Thorax.translateZ-1.5))%2)-1));
And in all its messy glory that is about it.
|