I was amazed by the design of the plant species in the movie "Avatar" one of my favorite which is "Helicoradian". These plants are simple, yet attractive and fascinating. In this page it has been tried to explain about the methods I used to create these plants in Maya using MEL scripting.
| First Things First! References: | ||
![]() ![]() |
As usual, the first step is gathering references. I found some good images from the movie.
I needed to study the properties of the plants and behavior of their curves very carefully.
|
|
| Hell! It's all 'bout Math! | ||
![]() |
The process starts with a simple curve created on the center with 6 points. The size of the curve
in all directions is important; we will use it later to change the base height, base radius and curvature.
This curve is resampled to get a nice and even curve. Then we need to find out the amount of rotation
increment for each curve around its Y axis. We have to keep in mind that the curvature can be clockwise or
counterclockwise. The math is very simple here: |
|
| Some Results: (click on images to enlarge) | ||||
![]()
|
![]()
|
![]()
|
![]()
|
![]()
|
| ...And the Code: |
/*
Helicoradian
Version 3.1
by Ali Seiffouri
1-16-2010
(code in MEL)
*/
{ // local scope
// parameters-----------------------------------------------------
int $numberOfCurves = 200; // min 2 curves
float $baseRadius = 5; // not zero or negative
float $finalRadius = 0.1; // min 0
float $turns = 4; // min 0
float $biasVertical = -100; // min -100 ~ max 100 (better results)
float $biasRadial = 80; // min -100 ~ max 100 (better results)
float $baseHeight = 3; // not zero or negative
float $height = 10 ; // greater than $baseHeight
float $zigzag = 0.01 ; // can be negative
float $jagged = 0 ; // can be negative
float $noise = 1; // can be negative
float $noiseScale = 5; // not zero
int $noiseSeed = 12346; // any integer
float $curvature = .7 ; // min -1 ~ max 1 (better results)
int $clockWise = 0; // boolean 0 or 1
// initialization-------------------------------------------------
string $curves[];
int $count = 0;
float $amountFloat = $numberOfCurves;
// main $i loop---------------------------------------------------
for($i = 0; $i < $numberOfCurves ; $i++)
{
// creating curve and initial curvature
$myCurve = `curve -d 3
-p 0 0 0 -p 0 0.75 0
-p 1 2 0 -p 2.7 2.7 -0.35
-p 4 3 -1.35 -p 4.25 3 -2.9`;
rebuildCurve -rt 0 -s 10 $myCurve;
select -r $myCurve;
scale ($baseRadius / 4.25) ($baseHeight / 3) $curvature;
// creating an array from the curves
$curves[$count] = $myCurve;
$count++;
// difinging vertical and radial bias
float $biasVerticalRemap;
float $biasRadialRemap;
if ($biasVertical <= 0)
{
$biasVerticalRemap = pow ( (($i+1) / $amountFloat) , (abs($biasVertical / 100)) );
}
else
{
$biasVerticalRemap = 1 / pow ( (($i+1) / $amountFloat) , (abs($biasVertical / 100)) );
}
if ($biasRadial <= 0)
{
$biasRadialRemap = pow ( (($i+1) / $amountFloat) , (abs($biasRadial)) );
}
else
{
$biasRadialRemap = 1 / pow ( (($i+1) / $amountFloat) , (abs($biasRadial / 100)) );
}
// defining jaggedness of the edges
float $upDown = pow (-1 , $i) * $zigzag * (1 - (1 / $amountFloat * $i));
float $jaggedHorizontal = pow (-1 , $i) * ($jagged / 10) * (1 -(1 / $amountFloat * $i));
// defining the amount of scaling for each curve
float $scaleIncrementH = ($height - $baseHeight) / ($baseHeight * $amountFloat);
float $scaleIncrementR = ($baseRadius - $finalRadius) / ($baseRadius * $amountFloat);
float $scaleHeight = 1 + ($scaleIncrementH * $i * $biasVerticalRemap) + $upDown;
float $scaleRadius = 1 - ($scaleIncrementR * $i * $biasRadialRemap) - $jaggedHorizontal;
// scaling the curves
scale -r $scaleRadius $scaleHeight $scaleRadius;
// rotating each curve
float $myRot = (pow (-1 , $clockWise)) * (360 * $turns * $i / $amountFloat);
rotate 0 $myRot 0 ;
// adding zigzag
move 0 $upDown 0 ;
// adding noise
float $noiseX = $noise / 100 * (noise ($i/$noiseScale + $noiseSeed + 100)-0.5)
* (1 -(1 / $amountFloat * $i));
float $noiseY = $noise / 100 * (noise ($i/$noiseScale + $noiseSeed + 200)-0.5)
* (1 -(1 / $amountFloat * $i));
float $noiseZ = $noise / 100 * (noise ($i/$noiseScale + $noiseSeed + 300)-0.5)
* (1 -(1 / $amountFloat * $i));
scale -r (1+$noiseX) (1+$noiseY) (1+$noiseZ);
} // end $i loop
// creating a loft surface from the curves------------------------
$myLoft = `loft -n "plant_0" -ch true -rn true -ar true $curves` ;
// cleaning up the scene------------------------------------------
$curveGroup = `group $curves` ;
select -r $curveGroup;
delete ;
} // end local scope
|
Scripting is talking to software directly while working with the interface is similar to communicating with it with sign language!
Writing codes gives the abiliy to create things that if not impossible, is really difficult and time consuming to create. Also creating
lots of random objects is one of the most demanded tasks in visual effects which if done manually, it is almost impossible.
Usually in serious production environments, clients ask for a lot of changes very often and they need it fast. Therefore working
procedurally (which mainly requires writing codes) saves a lot of time and budget.
I personally enjoy coding a lot as it can translate the language of nature, "Mathematics" to machine codes.












