Maya MEL Introduction – part 2

Maya MEL Introduction - part 2 MEL stands for Maya Embedded Language, it is a scripting language used in Maya, it is similar to Perl.

Last time we described you how to import a script into Maya script editor, we discussed how to set-up the environment, viewports and other very important issues about scripting. This part of MEL Intro describes you more about the cubes and their movements using the variable matrix for the animation.

 

Cubes

This part focuses on creating chessboard-like object, made from one hundred cubes.
We create two materials, a cube, duplicate it 99 times, distribute all cubes and change its material.

Material Setup:
renderCreateBarCB -asShader “surfaceShader” lambert;
This creates a lambert material. This is not a typical command- this actually is a procedure- external file called “renderCreateBarCB.mll”. This file consists of more individual MEL commands, it can be run by Maya and can be edited in any standard text editor. Deciding whether it is a simple command or a MEL procedure helps you command  “whatIs” followed by the name of command or procedure you are looking for.
(example whatIs renderCreateBarCB;)

rename matBlack;
Renames currently selected object. As the lambert2 was just created it is currently selected and now renamed. This also can be used without firstly selecting the object: rename oldName newName;
Giving your objects proper names is a good habit.
setAttr “matBlack.color” 0.15 0.15 0.15;
Makes material color dark. It does exactly that would moving the color slider to the left in Attribute Editor do, if material tab is selected.

renderCreateBarCB -asShader “surfaceShader” lambert;
rename matWhite;
setAttr “matWhite.color” 0.975 0.975 0.975;
The same as above, only now with the white (light) material. Those materials will later be assigned to cubes, creating a 3d checkered board object.

The Cube:
polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 -sz 1;
This creates a poly cube. The flags here (-w -h -d) specify the “width”, the “height” and the “depth” of cube. The other flags (-sx -sy -sz) specify subdivision along each of the axis. This simply means: create cube, with the size of the edge 1 unit.
rename “SQUARE_00”;
Renames the first cube. The two digits at the end of cubes’ name correspond with its future location (they represents position as in X and Z coordinates).  We will later use the name of the cube, to select and move cubes to a proper position within the checkered board.
rename “SQUARE_0Shape0” “SQUARE_Shape00”;
This is only a “fix”, to have the Shape node named the same way as the object, both digits are at the end of the name.

currentTime 1;
Sets current time to frame 1. This works kind of like a refresh for the scene, before we use the next dialog, to pause the script and observe the scene.
confirmDialog -title “Continue” -message “Press OK to continue.” -button “OK” ;
Now this is something you only appreciate when writing a script. This opens a simple dialog, with a single button, title (of the window) and a message (above the button). It is a confirmation dialog, meaning, that the script will not continue, until the button is pressed by user. In this script it is only for you to take a look at what is going on in the scene, when the script is running.

Click OK

Click OK

The First Loop- Creating 100 Cubes:
int $i;
This is a very important line, this is a declaration of our first variable. This says, that we will be using a variable called $i – the “$” sign must always precede name of the variable. So every time you see “$“, it is a variable.
The int stands for integer (whole numbers), and that is the type of our variable $i. This variable will serve us for the purpose of for-loop.

for ( $i=1 ; $i<=99 ; $i+=1) {
   duplicate -rr -renameChildren -ic;
   if (objExists("SQUARE_09")) {
       rename "SQUARE_09" "SQUARE_9";
       rename "SQUARE_Shape09" "SQUARE_Shape9";
   }
}

This all is a loop command. It starts with for () { and ends with } (braces).
After for there are (closed in parentheses) the conditions for the loop. The first number is a starting number of the first loop, the second is the last number for this loop. The third number in the parenthesis means the step, or the increment, by which, we are counting. We are adding (or subtracting if the step would be negative number) to the starting number.
In this case, it is from 1 to 99, increasing after each walk through by one.
In other words, the commands between the braces will be executed 99 times. And because the last thing selected is still our first cube (now called SQUARE_00) it will duplicate this cube 99 times.
The trick here is, that Maya automatically renames the new cube, by adding or rising the number at the end of the name.
The if command sets a condition, under which the commands in braces are executed. Here the condition is, that in the scene exists (objExists) object called SQUARE_09.
Here it is again only a “fix”, it is executed only once- only once is the condition met. Because for Maya next name after SQUARE_09 is not SQUARE_10 but SQUARE_010, we temporarily rename the cube SQUARE_09.

rename “SQUARE_9” “SQUARE_09”;
rename “SQUARE_0Shape9” “SQUARE_Shape09”;
This renames back the previously renamed cube and its shape.

currentTime 1;
confirmDialog -title “Continue” -message “Press OK to continue.” -button “OK” ;

And again, the pause with dialog window. You see no difference from the previous pause- that is because all the 100 cubes are overlapping in one spot. The next task is to distribute these cubes, to form a board consisting of 10 times 10 cubes.

Moving the Cubes:
int $x; int $z;
Another declaration, this time it is X and Z- the coordinates for the position of cubes. Also serving as a variable for two loops and the number in those two variables will create a name of the cube that will be moved.
string $objectName;
Declaration of variable of another type- it is string, the variable will contain text, in our case, it will be a name of the cube, that we will be moving.

for ( $x=0 ; $x<=9 ; $x++ ) {
    for ( $z=0 ; $z<=9 ; $z++ ) {
        $objectName="SQUARE_"+$x+$z;
        select $objectName;
        move $x 0 $z ;
    }
}

Two for-loops, one loop inside another loop. The first one (x – the “outer” loop) will be executed 10 times (0, 1 , … , 9). The second (z – “inner”) will be also executed 10 times, but ten times in each x loop. So that makes altogether 100 runs of the three lines in braces.
On the first line of the loop, we indicate, what the name of currently moved cube is. We take value of variable $x and the value of variable $z (in first run of the loops they are both zeroes) and add these two numbers (+$x+$z ) to the text  “SQUARE_” creating the name of actual cube (in first run SQUARE_00). This is assigned to a string variable named $objectName.
Consecutively this object is selected.
And finally moved to its proper position.

currentTime 1;
confirmDialog -title “Continue” -message “Press OK to continue.” -button “OK” ;
The pause dialog.

Even or Odd? Black or White?
float $evenOrOdd;
Defines variable of a float type- this can again contain a numerical value, this time also numbers with decimal point.

for ( $x=0 ; $x<=9 ; $x++ ) {
    for ( $z=0 ; $z<=9 ; $z++ ) {
        $objectName="SQUARE_"+$x+$z;
        select $objectName;
        $evenOrOdd=(float ($x)+ float ($z))/2;
        if ($evenOrOdd==int($evenOrOdd)) {
            hyperShade -assign matWhite;
        }
        else {
            hyperShade -assign matBlack;
        }
    }
}

Again two loops, one in the other, “outer” is x, the “inner” loop is z. Again we will go and address all 100 cubes.
We start by creating the name. The name corresponds also with the location of the cube.
We select the cube SQUARE_XZ (for example SQUARE_00).
To $evenOrOdd we assign a value, that will be either a whole number, or a decimal number. It is then compared with the integer value of the same variable. If the float value and the integer values are equal (==), then the objects position is “even” and the material assigned to this cube is matWhite. Otherwise (else) the currently selected cube is going to be black. So 2 neighboring cubes do not have the same color.
Example for this:
$x=4  $z=1 $evenOrOdd = (4+1)/2=2.5   int($evenOrOdd) =2
This means it is not equal, is odd, and will be black.
$x=4  $z=2 $evenOrOdd = (4+2)/2=3   int($evenOrOdd) =3
This means it is equal, it is even, and will be white.

currentTime 1;
confirmDialog -title “Continue” -message “Press OK to continue.” -button “OK” ;
The pause again.

Chessboard 10 times 10

Chessboard 10 times 10

Animation of Multiple objects

In the next part, we will define matrix variable, we use values from the matrix to manipulate multiple objects. Later we will use mathematical equations to animate these multiple objects.

The Matrix:

matrix $chessBoardM [10][10] = <<0,0,0,0,0,0,0,0,0,0;
1,1,1,1,1,1,1,1,1,1;
2,2,2,2,2,2,2,2,2,2;
3,3,3,3,3,3,3,3,3,3;
4,4,4,4,4,4,4,4,4,4;
5,5,5,5,5,5,5,5,5,5;
6,6,6,6,6,6,6,6,6,6;
7,7,7,7,7,7,7,7,7,7;
8,8,8,8,8,8,8,8,8,8;
9,9,9,9,9,9,9,9,9,9>>;

Another type of variables used in Maya is matrix. This is also another possible declaration- we assign value in the moment of declaration.
Matrix type is defined by a name and its size. In this case it is a set of numbers size 10 times 10.
In order to assign values to it, we are using two pairs of angle brackets, one at the beginning and one at the end of the matrix definition. The numbers in row are separated by a comma (,) and each individual row is separated by a semicolon (;).

Matrix 1- stairs

Matrix 1- stairs

Field of Heights:
float $y;
This variable will be used in the next loop statement as a representation of height for our cubes. The loop will show, how to assign values from our previously defined matrix and how to change the height of each individual cube.

for ( $x=0 ; $x<=9 ; $x++ ) {
    for ( $z=0 ; $z<=9 ; $z++ ) {
        $objectName="SQUARE_"+$x+$z;
       
        $objectName=$objectName+".f[1]";
        select -r $objectName;
       
        $y= $chessBoardM [$x] [$z];
        move -y $y ;
    }
}

Again- two loops, one in the other. First for $x from 0 to 9. Second for $z (0 to 9).
Notice, that in a definition of matrix there is [10] times [10] values. But when assigning or obtaining a value to or from the matrix, the counting of row or column starts from 0 !
In the loop, we create the name of the object, we are modifying – so the first will be SQUARE_00, next we add to this name “.f[1]” and this means, that we are addressing a face. This is what the f stands for and it will be the face with number 1. Every component of an object in Maya has its own number and can be modified like this. Another possibility is to select and change vertices that would be .vtx [2:5], this means vertices 2,3,4 and 5. Or edges.e[1:2] and .e[6:7].
After selecting the desired face (face number 1), we assign to variable $y a value from our matrix (named $chessBoardM), from the position [$x] [$z] in the matrix. After that we finally move this selected face to a location obtained from matrix in the vertical direction -y (y-axis).

currentTime 1;
confirmDialog -title “Continue” -message “Press OK to continue.” -button “OK” ;
Confirmation dialog.

Another Matrix:

matrix $chessBoardM [10][10] =  <<0,0,0,0,0,0,0,0,0,0;
0,0,0,0,0,0,0,0,0,1;
0,0,0,0,0,0,0,0,1,2;
0,0,0,0,0,0,0,1,2,3;
0,0,0,0,0,0,1,2,3,4;
0,0,0,0,0,1,2,3,4,5;
0,0,0,0,1,2,3,4,5,6;
0,0,0,1,2,3,4,5,6,7;
0,0,1,2,3,4,5,6,7,8;
0,1,2,3,4,5,6,7,8,9>>;
for ( $x=0 ; $x<=9 ; $x++ ) {
    for ( $z=0 ; $z<=9 ; $z++ ) {
        $objectName="SQUARE_"+$x+$z;
        $objectName=$objectName+".f[1]";
        select -r $objectName;
        $y= $chessBoardM [$x] [$z];
        move -y $y ;
    }
}

currentTime 1;
confirmDialog -title “Continue” -message “Press OK to continue.” -button “OK” ;
Just once more another matrix, another pause.

Matrix 2 - pyramid

Matrix 2 – pyramid

The Time Range:
playbackOptions -min 0 -max  199 -aet 200;
This will set range for our future animation. It works just like clicking in the Range Slider and typing the numbers in. Flags -min and -max mark the start and the end of the visible and playable range of animation (playback). Flag -aet is for the end of an animation. In the time 200 we will be setting our keyframes but we don’t want to see it in the final animation, that is why -max and -aet differ.

autoKeyframe -state false;
This turns off auto keyframe option (the little red or gray key on the Range slider)- otherwise we would end up with many unwanted and unnecessary keyframes.

Playback range

Playback range

Variable Definitions for Animation:
float $dist;
float $distMax=4.527693;
float $height;
float $multiplier;
int $time;

Defines variables for our next computations. These computations may seem complex to you or not very clear at the first look. But it is really not necessary to understand all the equations. So only the basic information will be provided here.
Variable $dist is a distance from the center of the chessboard to each individual center of the cube. $distMax=4.527693 is a constant, the maximum distance. Variable $height is the height of currently selected cube. $multiplier is just a multiplier, taking care of proper scale of the wave.

Time Loop:

for ( $time=0 ; $time<=200; $time+=25 ) {
    switch ($time) {
        case 25:
        case 125:
            $multiplier=0;
            break;
        case 75:
        case 175:
            $multiplier=-2;
            break;
        default:
            $multiplier=-1;
            break;
    }

This loop is different from previous loops, because the increment here is not 1, but 25. We are counting by 25, so the keys are set only in times 0, 25, 50, 75, 100, 125, 150, 175, 200.
switch command works as a switch in the script, it says, that when $time is 25 or 125 the $multiplier will be 0, when 75 or 175 it will be -2. And in the rest of the cases (default) it will be -1.
break must end each case.  The cases are (as well as the loop or if) surrounded by the braces.
Notice, that we are still inside of the for-loop- that means, that switch command, and next lines as well, will be executed 9 times, for different values of $time.

Different stages of the wave

Different stages of the wave

Different stages of the wave

Different stages of the wave

Creating 3D Sin Wave:
currentTime $time;
confirmDialog -title “Continue” -message “Press OK to continue.” -button “OK” ;
Pause. This time it is not in the time 0, but in time $time, because we are inside a loop and $time is different in each pass of the loop.

    for ( $x=0 ; $x<=9 ; $x++ ) {
        for ( $z=0 ; $z<=9 ; $z++ ) {
            $objectName="SQUARE_"+$x+$z;
            $objectName=$objectName+".f[1]";
            select -r $objectName;
            $dist=sqrt((float (4.5)- float ($x))*(float (4.5)- float ($x))+
(float (4.5)- float ($z))*(float (4.5)- float ($z)));
            $height=(cos ((($dist)-$distMax)/$distMax*3.141));
            $height= $height+ ($multiplier*$height);   
            $height= $height+5*(1)-4 ;
            $y= $height;
            move  -y $y;
            setKeyframe $objectName;
        }
    }
}

Again, two loops within each other, for row ($x) and column ($z) number.
Top face of each cube is selected.
$dist and $height calculate height of each cube, depending on its position (x, z location) within the “chessboard”.
Afterward we move selected face to calculated height, this changes cubes’ height.
And we finally set the keyframe for this face.

currentTime 0;
confirmDialog -title “Continue” -message “Press OK to continue.” -button “OK” ;
Pause.

Once More for NURBS Plane:
This time we will create the wave using a NURBS plane of the same size as the previous “chessboard” made of cubes.
nurbsPlane -ch on -o on -po 0 -ax 0 1 0 -w 10 -u 10 -v 10 ;
move 4.5 1.5 4.5;
rename NPlane;
We create the plane size 10 times 10 units, move it to the same position as the center of the chessboard. We rename the plane.
After that starts the same loop as the one above. With the exception, that the calculation has a little different equation and, that we select CVs (.cv[“+$x+”][“+$z+”]) instead of faces.
Finally the plane is hidden, you can unhide it yourself, manually, and see its animation.

for ( $time=0 ; $time<=200; $time+=25 ) {
    switch ($time) {
        case 25:
        case 125:
            $multiplier=0;
            break;
        case 75:
        case 175:
            $multiplier=-2;
            break;
        default:
            $multiplier=-1;
            break;
    }

    currentTime $time;
//    confirmDialog -title "Continue" -message "Press OK to continue."
-button "OK" ;
    for ( $x=1 ; $x<=10 ; $x++ ) {
        for ( $z=1 ; $z<=10 ; $z++ ) {
            $objectName="NPlane";
            $objectName=$objectName+".cv["+$x+"]["+$z+"]";
            select -r $objectName;
            $dist=sqrt((float (6)- float ($x))*(float (6)- float ($x))+
(float (6)- float ($z))*(float (6)- float ($z)));
            $height=(cos ((($dist)-$distMax)/$distMax*3.141));
            $height= $height+ ($multiplier*$height);   
            $height= $height+5*(1)-3.5 ;          
            $y= $height;
            move  -y $y;      
            setKeyframe $objectName;
        }
    }
}

currentTime 0;
confirmDialog -title “Continue” -message “Press OK to continue.” -button “OK” ;
select NPlane;
hide;

In the next part of MEL Intro we will describe you more about the random animation of the ball rolling over the cubes, so stay tuned up.