so small, however, that it goes beyond the range of how MEL calcu-

lates decimals and gets rounded off to 0:

print vec[1]

2.44829443007e-011

or

0.0000000000244829443007

7.2.17 Returning to the tree() Procedure

The first argument ($vec) is the point of the rotation. The second

(

$x_axis and $z_axis) is the axis of rotation. The third (deg_to_

rad($angle[])

) is the angle of rotation that will occur. The rot

command requires radian values, which is why the deg_to_rad

command must be used.

// STEP 3: Translate the vector up the y-axis by branch

// length units

vector $x_axis = <<1,0,0>>;

vector $y_axis = <<0,1,0>>;

vector $z_axis = <<0,0,1>>;

$vec = $vec + <<0, $branchLen, 0>>;

// STEP 4: Rotate the vector by the branch angle

// to find the end of a branch

// STEP 5: Draw a line between the base ($base) of the branch

// and the (relative) end of the branch.

// To do this, we will need to compute the angles needed to

// rotate a vector to align to the y-axis in such a way

// that it aims along a particular vector

// - in this case, the growth direction ($growthDir).

// The aimY procedure was written for this purpose

float $angle[2] = aimY($growthDir);

$vec = rot($vec, $x_axis, deg_to_rad($angle[0]));

$vec = rot($vec, $z_axis, deg_to_rad($angle[1]));

$vec = <<($vec.x), ($vec.y), ($vec.z)>>;

// Locate the end of the branch relative to the

Chapter 7

422

// base of the branch.

vector $end1 = $base + $vec;

Draw the first curve using the calculated values as arguments for

the

-point flags:

// STEP 6: Draw a curve that represents the first branch

curve -degree 1

-point ($base.x) ($base.y) ($base.z)

-point ($end1.x) ($end1.y) ($end1.z);

Continue to create the reflected branch and perform recursions to

generate the rest of the limbs:

// STEP 7: Recurse to the next branch

tree($depth - 1, $end1, $vec, $branchAngle, $branchLen * 0.6);

// Finding the second branch:

// STEP 1: Define the second branch as if it were a

// reflection of the first branch, first about the $growthDir

// vector

// The reflect procedure was written for this purpose.

$vec = reflect(-$vec, $growthDir);

$vec = <<($vec.x), ($vec.y), ($vec.z)>>;

// STEP 2: Locate the end of the branch relative to the

// base of the branch.

vector $end2 = $base + $vec;

// STEP 3: Draw the curve segment that represents

// the second branch.

curve -degree 1

-point ($base.x) ($base.y) ($base.z)

-point ($end2.x) ($end2.y) ($end2.z);

// STEP 4: Recurse to the next branch

tree($depth - 1, $end2, $vec, $branchAngle, $branchLen * 0.6);

}

To test out the script, enter the block of code that follows. When this

many arguments need to be passed it can be easier to store the val-

ues in variables and pass the variables for the arguments.

Recursion

423

Chapter 7

Keep in mind the usages of the arguments:

n

$depth: This is the depth of the recursion and essentially how

complex the tree will be. More recursions mean more branches.

n

$base: This is the position where the tree will start. For exam-

ple, <<0,0,0>> would be the center of the world.

n

$growthDir: This is the direction in which the branches will

grow, which is the argument of the aimY() procedure.

n

$branchAngle: This value controls the spread of the branching,

similar to the cone angle of a spotlight.

n

$branchLen: This value controls the overall length of the

recurring branches.

vector $begin = <<0,0,0>>;

vector $dir = <<0,1,0>>;

float $spread = 15;

float $len = 2;

tree(7, $begin, $dir, $ spread, $len);

This is when you pop a cigar in your mouth, walk to the nearest

beach, squat down, and say: “I love the smell of recursion in the

morning. Smells like… victory.”

Chapter 7

424

Figure 7-43

Get *Professional MEL Solutions for Production* now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.