6.
Completing the Brief
After much deliberation
and the implementation of many different methods, ranging from particles to
instancing geometry and actually using geometry, as well as having the choice
of writing it in a script or using expressions to dynamically change the attributes,
I had finally arrived at a possible solution.
First
of all I had to fulfil the brief, which was:
- I needed to have a collection of characters
moving past the camera, in a uniform and troop like manner.
- They had to be animated convincingly.
Mud Direction
These were my two
challenges. To begin with I had to get the geometry to follow some sort of point
or orient towards a destination.
My first version
of mudmanTroop_v1 was just a simple script. Because of the nature of the troop
they would be walking in unison and have an almost army like feel to them. Thus
I used a simple expression at the beginning which just made the objects translate
in the x direction uniformly, so the geometry just moved forward over time.
This was not really direction specific but it brought me closer to my goal.
Next I implemented
the solution I had for the animation with using a simple expression on the blendhapes
envelope value. My script was beginning to take shape. When I pressed the magical
return button I got a reaction, not an error. This was a move in the right direction
for me!
However I didn’t
think it had quite the functionality that I needed plus if I gave the script
to anyone else they’d have quite a bit of a problem just executing it.
I needed to build
in some more complexity.
Just a generic transform
in the x direction was no good. I realised I would certainly have to change
that. So how could I constrain the objects but not have them all have the same position? Scouring the Mel command reference
I came across the PointConstraint command,
which as the name says constrains any object selected to the first object selected.
For this to work
I would have to use a simple for loop to loop through the selected objects-(Mud
Men troop)- and assign the PointConstraintt
to the objects. I found when using the Mel command PointConstraint
that it set the default values of the geometry to 0 0
0, which meant that all the objects, no matter how
dynamically -or un-dynamically, as the
case might be- I had placed the objects it just reset them to the default position.
So just iterating through the objects and then assigning the PointConstraint command was no good. I would have to come
up with a method of my own which would not reset my values.
I found that if
I just grouped all the objects then assigned them to the locator with the PointConstraint command that they then were autonomous but
still followed the locator. This meant that I could now keyframe
the locator wherever I wanted the troop to go. I still didn’t like how constricting
the PointConstraint command was so I decided to ditch
it for simpler expressions, which I had far more control over.
All I did to achieve
this was to put an extra procedure in the script which first grouped the objects
and then constrained the group to a locators x y and z values. This left me
with a couple of additional problems.
Looking Mud
I could now make
them go in any direction but the of course didn’t orient themselves towards
their goal, they just faced forward in the x direction. This meant that they
slid as soon as I started moving the locator in two different directions x and
z. So how was I to solve this? Once again I turned towards the Mel commands
reference, which pointed me towards the aimConstraint
command. This would again basically do the hard work for me.
This
command however worked in reverse to the PointConstraintt.
Simply applying it to the group would result in the aimConstraint
falling down. I would have to iterate through the elements in the selected array
of objects and apply the aimConstraint individually
to each object.
Now
I actually had a lot of problems with these different methods. Iterate does
not iterate. There were loads of problems with passing the values of the data
types. It took a bit of fiddling but it worked in the end. Of course once the
aimConstriant was set in place it was joined to the locator,
which meant the troop all looked at the locator but when the locator moved so
did the troop. This meant their focus of attention never left the centre of
the troop. As the troop moved so did the aimConstraint,
and for me this was absolutely useless. I would have to find another way to
do it.
I
figured that I could constrain the actual rotate values of each object with
the rotate values of each object. This worked to an extent on the x and z values,
but if I constrained the y value they each rotated upwards autonomously to each
other which as you can imagine would not work right within the group
.
The
best way to do it was to constrain the entire group’s rotate y value to the
rotate value of the locator, giving complete control. Now I had objects that
moved in the direction of a locator and oriented themselves towards that locator
too. Part of the way there!
Easy
Mud

Next
I wanted make it more user friendly, seeing as it was actually being written
for my brother to implement in his project. Given the fact that he had a limited
knowledge of Maya
I couldn’t exactly give him just the script and say “There you go, Chris, all
you need to do is blah blah .” So for functionality I would have to learn to
use GUI in Maya.
I
never realised before how hard it was to actually capture a value that had been
imputed. Unless I’m really stupid or looking at things upside down, it seemed
so hard to just capture a value, and then use it in the script. Basically all
I wanted to allow my user to do was to be able to choose the amount of geometry
that they wanted and then to be able to simply click the button and everything
would work. Instant script for an army of Mud Men!
I
set an expression that manipulated the envelope attribute of a blendshape
for ease of compatibility. This meant that I needed the objects to all have
the blendshape attribute. The only way to do this
was to instance the object but make it world space and don’t parent it. Then
all I’d need to get was a variable that would stand as the amount by which to
iterate the instance command.
This
brought it’s own problems! Once again I had to learn everything I could
about GUI’s because I had a limited knowledge of GUI’s. This was a completely
new experience and perhaps that’s why I struggled with it quite a bit. However
on a positive note I can’t help but comment that it brought a lot of fun to
the whole exercise. I found I could call the window MuddyWindow, have an input that asks ‘how much mud?’
or have a button with ‘let’s get muddy!’ on it!
Finished Mud
All
that was left was to put it together so that the script executed all the commands
with just one button press.
I decided to use
functions as blocks to make up the program. It also allowed for better error
checking because I could usually find the root of the problem with little trouble.
This made fixing bugs a little easier.
My
script executes at the button press of the GUI. It then calls mixUpMud
proc which creates the Mud Men, or you could throw mud x and throw mud z, which
allows for a more uniform troop. Then there is a separate button for the TROOPFALL_IN
which starts the main loop which calls the smaller functions Mud MenLook and Mud MenMove that constrain
the objects to the locator.
Random Mud Creation

Uniform Mud Creation

Breakdown
- MixUpMud works by taking a value and then looping
through and duplicating the selected object, then it takes two variable $i and $k which are assigned random values between two given
integers and assigns those random values to the x and z values of the newly
instanced object. This creates a random number of Mud Men over a given threshold.
- ThrowMudX Simply loops through a given value
and instances the selected objects that number of times and translates them
in the x axis.
- ThrowMudZ Simply loops through a given value
and instances the selected objects that number of times and translates them
in the z axis.
- TROOPFALL_IN Being the main loop of the script,
it has calls to all the other procedures and creates the locator. It runs
the blendshape expression and takes the string of
the selected objects and assigns them to an array.
- Mud MenLook This is the procedure that constrains
the value of each object to the rotate values of the locator. It takes an
array of the objects $mud and loops through them using expressions to constrain
the rotate values x and y to the rotate values of the locator.
- Mud MenMove This is the procedure that selects
all objects then groups them. It constrains the translated x y and z values
of the group to the translated x y and z values of locator.Also it constrains the rotate z value of the
group to the rotate z value of the locator.
The
end result is a nice behavioural system that is easy to implement.