The
mech was boned and skinned in the usual fashion.IK
handles were added to its feet to control its leg, and also to its arms.IK
handles were also added to each of its foot appendages to control where
they point to.
Then
I used Maya?s expressions to control the various joints of the mech.I
used one expression for each of the foot?s appendages so that they would
always point downward when it raised its foot, to simulate the force of
gravity.This couldn?t be done with
simple parenting, because I wanted the IK handle of the appendage to be
parented to the movement of the whole foot, but only in terms of its X
and Z coordinates.I wanted the IK
handle?s Y coordinate to always be 0 so the foot appendage would always
be pointing at the floor.But since
all the appendages were grouped as a ?foot? node, all the IK handle?s translation
attributes are always 0, since it is the group that is moved when moving
the leg.Many methods of grouping
and parenting were attempted, but none worked.So
to make each foot appendage point to the ground, I wrote an expression
to assign to the Y coordinate the negative value of the group?s Y coordinate;
this way, they would cancel each other out and the IK handle will always
effectively be at Y = 0.
//controls
right foot appendages
ik_right_toe.translateY
= -rfootc.translateY;
ik_right_ball.translateY
= -rfootc.translateY / 2;
ik_right_heel.translateY
= -rfootc.translateY;
ik_right_wing_left.translateY
= -rfootc.translateY;
ik_right_wing_right.translateY
= -rfootc.translateY;
//controls
left foot appendages
ik_left_toe.translateY
= -lfootc.translateY;
ik_left_ball.translateY
= -lfootc.translateY / 2;
ik_left_heel.translateY
= -lfootc.translateY;
ik_left_wing_left.translateY
= -lfootc.translateY;
ik_left_wing_right.translateY
= -lfootc.translateY;
Next,
I wanted to automate the secondary animation of the mech so that its various
parts would bounce accordingly along its walk cycle.I
added custom attributes for the torso?s up and down bounce and tilt, its
side to side bounce tilt, and its forward and backward shifting.I
also added attributes for its arms bouncing, its legs lifting and forward
and backward movement.I then used
expressions to link all of these to a ?Walk_Cycle? attribute, so that when
I slid this attribute, the mech would walk in place.I
also added custom attributes ?Stride_Length,? which affects how big the
mech?s stride is, and ?Speed? which just affects the apparent bounciness
of the mech (not the distance covered).Stride_Length
was also rigged to control the bounciness of the torso and arms, because
a larger stride should effect more secondary motion.The
Speed control made the mech much bouncier at higher speeds.Also,
since the motions of the legs at a slow walk and a full run are vastly
different (when running, there are times when both feet are in the air,
which is not the case when walking), two different motion curves were created
at each extreme, and interpolated between using the Speed attribute.Expressions
were the mechanism by which I linked the two different animation curves
and the Speed and Stride_Length attribute to the Walk_Cycle attribute,
which was linked to the actual IK handles using the Set Driven Key tool
in Maya.
mech_control.RFStride_h
= ((mech_control.Speed / 10) * mech_control.RightFootStrideRun * (mech_control.StrideLength
/ 40)) +
(((10
- mech_control.Speed) / 10) * mech_control.RightFootStride * (mech_control.StrideLength
/ 40));
//foot
lift due to stride forward
mech_control.LFL_h
= ((mech_control.Speed / 10) * mech_control.LeftFootLiftRun * (.1 + mech_control.StrideLength
/ 80) * (1 + mech_control.Speed / 10)) +
(((10
- mech_control.Speed) / 10) * mech_control.LeftFootLift * (.1 + mech_control.StrideLength
/ 80) * (1 + mech_control.Speed / 10));
mech_control.RFL_h
= ((mech_control.Speed / 10) * mech_control.RightFootLiftRun * (.1 + mech_control.StrideLength
/ 80) * (1 + mech_control.Speed / 10)) +
(((10
- mech_control.Speed) / 10) * mech_control.RightFootLift * (.1 + mech_control.StrideLength
/ 80) * (1 + mech_control.Speed / 10));
//foot
lift due to strafe left/right
$strafe_liftL
= 0;
$strafe_liftR
= 0;
.O[4]
= .I[10];
.O[5]
= .I[11];
mech_control.HRUD_h
= mech_control.HipsRaiseUD * (mech_control.StrideLength / 40) * (mech_control.Speed
/ 5) + mech_control.Speed - 1;
mech_control.HTUD_h
= mech_control.HipsTiltUD * (mech_control.StrideLength / 40) * (mech_control.Speed
/ 10);
mech_control.HLLR_h
= mech_control.HipsLeanLR * (mech_control.StrideLength / 40) * (.25 + mech_control.Speed
/ 40);
mech_control.HSLR_h
= mech_control.HipsSwayLR * (mech_control.StrideLength / 40) * (.75 + mech_control.Speed
/ 40);
mech_control.HSFB_h
= mech_control.HipsSurgeFB * (mech_control.StrideLength / 40) * (.25 +
mech_control.Speed / 20) + mech_control.Speed - 1;
mech_control.ArmBounce_h
= mech_control.ArmBounce * (mech_control.StrideLength / 40) * (mech_control.Speed
/ 10);
mech_control.HLookLR_h
= mech_control.HipsLookLR * (mech_control.StrideLength / 40) * (mech_control.Speed
/ 10);
mech_control.TLLR_h
= mech_control.TorsoLookLR;
For easy testing,
I next rigged the mech?s walk cycle to the frame number.This
was so I could just press the play button and the mech would walk/run in
place.I used an expression to relate
the frame time to the walk cycle.Using
this, the apparent speed of the mech could be easily seen.Not
only was the mech bouncier at higher speeds, it took more steps in the
same amount of time as it would?ve at lower speeds.
The next part was
rigging the mech so that its walk cycle would be automatically generated
based on its position and rotation.This
used trigonometry to figure out how much it was going forward based on
both its heading and its bearing, and then related it to the Walk_Cycle
attribute, which was looped over and over using the modulus of the distance
covered.Using this technique, there
is no footslip while the mech is walking.The
Speed and Stride_Length attributes worked well in this case too.But
the Speed now only controlled how bouncy the mech looked.It
was the distance covered by the keyframing that would control the speed
of the mech, or the number of steps it took in a certain amount of time.I
also had to incorporate reference positions and rotations, because you
just cannot measure the distance traveled from the origin, since the mech
will be rotating and such.
This approach had
a few other shortcomings.The mech?s
automatic motion only looks good when walking in a straight line.There
is no consideration of side-stepping or rotating while walking, so that
if the mech is not keyframed in a straight line, there will be lateral
footslip.I feel that, if given more
time, I could have at least implemented the side-stepping by incorporating
a Side_Step_Cycle attribute, much like the Walk_Cycle attribute.Then
I would interpolate between the two based on the differences between the
angles of its heading and its bearing.Also,
to avoid longitudinal footslip, there were constraints put on the animation
curves of the mech?s feet so that it would be linearly aligned with the
distance traveled.This causes a
slightly less than realistic motion, because I couldn?t adjust the feet?s
curves to have slow in and out tangents, because there were no tangents
for the overall motion of the mech body.
$bearing_dist
= sqrt(pow(mech_control.translateX - mech_control.RefPosX, 2)
+
pow(mech_control.translateZ - mech_control.RefPosZ, 2));
if
($bearing_dist != 0) {
$bearing_dist
*= mySign(mech_control.translateX - mech_control.RefPosX)
*
-mySign(mech_control.translateZ - mech_control.RefPosZ);
if
(mech_control.translateX - mech_control.RefPosX < 0)
$bearing_dist
= -$bearing_dist;
$bearing_angle
= acosd((mech_control.translateX - mech_control.RefPosX) / $bearing_dist);
$heading_angle
= mech_control.rotateY;
$angle_between
= $bearing_angle - $heading_angle;
$heading_dist
= $bearing_dist * cosd($angle_between);
mech_control.one_cycle
= fmod(mech_control.one_cycle + ($heading_dist * 24 / (mech_control.StrideLength
* 2)), 24);
}
mech_control.RefRotY
= mech_control.rotateY;
mech_control.RefPosX
= mech_control.translateX;
mech_control.RefPosZ
= mech_control.translateZ;
Overall, I think the
technical piece was a great success.I
had tried many alternatives to reach a certain goals, and finding the right
method out of many seemed to be the critical lesson learned.