Matrix assignment was a way to play around with MEL loops, and create some interesting geometry with it. I used simple for loops and nested them in each other. Creating the geometry was the easy part. Hard part was to group them and expressions on the groups to animate. 1500 cubes were created, and those each 10 consecutive cubes were placed in a group. Two nested for loops did the job. Top for loop also had the following in it:

  • move pivot to scene origin
  • random speed multiplier generation
  • adding animation expression to the group

I tried to keep a simple look, so the whole scene is in grayscale. creating and assigning shaders to the groups proved to be not so easy as well. the center groups were assigned a lambert that had an incandescence of 20, and the exterior environment sphere an incandescence of .2. since i used final gathering, these overly lit objects became very soft light sources. almost like huge area lights with ray traced shadows, but this renders much much faster. another thing i had to do add to the script was to turn of the default scene light.

Here is the code that added the animation expressions

for($g = 1; $g <= 1500; $g = $g + 10)   {
    for($i = 0; $i < 10; $i++)  {
        $cubeNum = $g + $i;
        $cubeName = "pCube" + $g;
        $cubeNames[$i] = "pCube" + $cubeNum;
        }
    $groupName = "group" + $groupNum;
    group -n $groupName $cubeNames; 
    move -absolute 0 0 0 $groupName.scalePivot $groupName.rotatePivot;
    $randomSpeed = rand(5,10);
    expression -s ($groupName+".rotateY = time * " + $randomSpeed) -o $groupName -ae 1 -uc all;
    $groupNum++;
    clear($cubeNames);
    } 

And here is the code that created the center group shader and assigned it to the object

shadingNode -asShader lambert -name centerSh;
sets -renderable true -noSurfaceShader true -empty -name centerShSG;
connectAttr -f centerSh.outColor centerShSG.surfaceShader;
setAttr "centerSh.color" -type double3 1 1 1 ;
setAttr "centerSh.ambientColor" -type double3 1 1 1 ;
setAttr "centerSh.incandescence" -type double3 20 20 20 ;
select -r center ;
sets -e -forceElement centerShSG;

UPDATE

I've changed the whole code to use global procedures instead. Currently using global procedures for this specific example is completely useless since each procedure is called only once, except for the shader procedure (its called twice).

So now, the animation expressions are added by this procedure

global proc groupCrt(int $totalNumCubes, int $numCubesInGroup, int $minSpeed, int $maxSpeed) {
    int $groupNum = 1;
    string $groupName = "";
    //string $cubeNames[$numCubesInGroup];
    string $cubeNames[10];
    string $cubeName = "";
    float $randomSpeed = 0;
    for($g=1; $g<=$totalNumCubes; $g=$g+$numCubesInGroup) {
        for($i=0; $i<$numCubesInGroup; $i++) {
            $cubeNum = $g + $i;
            $cubeName = "pCube" + $g;
            $cubeNames[$i] = "pCube" + $cubeNum;
            }
        $groupName = "group" + $groupNum;
        group -n $groupName $cubeNames;
        move -absolute 0 0 0 $groupName.scalePivot $groupName.rotatePivot;
        $randomSpeed = rand($minSpeed,$maxSpeed);
        expression -s ($groupName + ".rotateY = time * " + $randomSpeed) -o $groupName -ae 1 -uc all;
        $groupNum++;
        clear($cubeNames);
    }}

And the shaders are created and assigned by this procedure

global proc shaderCrt(string $objName, string $shaderName, vector $colorVector, vector $ambientVector, vector $incanVector) {
    $shaderNameSG = $shaderName + "SG";
    shadingNode -asShader lambert -name $shaderName;
    sets -renderable true -noSurfaceShader true -empty -name $shaderNameSG;
    connectAttr -f ($shaderName+".outColor") ($shaderNameSG+".surfaceShader");
    setAttr ($shaderName+".color") -type double3 ($colorVector.x) ($colorVector.y) ($colorVector.z);
    setAttr ($shaderName+".ambientColor") -type double3 ($ambientVector.x) ($ambientVector.y) ($ambientVector.z);
    setAttr ($shaderName+".incandescence") -type double3 ($incanVector.x) ($incanVector.y) ($incanVector.z);
    select -r $objName;
    sets -e -forceElement $shaderNameSG;
    }

As a result, the main code is reduced down to a couple of lines

There are a lot of advantages of using procedures instead of hard-coding them in the main code.

One of them is that procedures can store lengthy code that will be repeated within the code. That part of the code is only written once, and then called with a single command anytime later. This saves valuable time for the coders as well as making the code more readable.

Another one is that 99.9% of programming languages start interpreting a script from top to bottom, while reading everything in the main code block. Storing repetitive tasks in procedures in this case makes the interpreter interpret the task only once, saving memory and cpu cycles. Also if a specific procedure is not needed for a specific situation, then its not read by the interpreter whatsoever, again saving valuable resources.

Previous Post Next Post