Simple, but useful ASL controller script examples

Scaling

The following simple scripts scale an element depending on the current frame (or time) and a constant ‘factor’:

float $factor;
$factor = 3.0;  /* use a suitable value */
$scale = 1 + $factor * time; /* increases uniformly, starting with 1 */

The third line could be replaced by one of the following lines:

$scale = 1 + $factor / (1 + frame); /* decreases non-uniformly towards 1 */
or
$scale = $factor * time * time; /* increases geometrically */
or
$scale = $factor * time * frame; /*increases geometrically (more rapidly than the previous) */
or
$scale = $factor * frame * frame; /*increases geometrically (even more rapidly than the previous) */

The following script uses different scaling, depending on the current frame. It could scale the particles in a rocket trail (usable in Teranim8or particle trails)

/* Simulates the exhaust at a rocket launch */

float $factor, $factor1, $factor2; /* $factor1,2 - scaling factors in the first/second phase */
int $ignition, $liftoff ; /* the frame of ignition and liftoff */

$ignition = 7; 
$liftoff = 20; 
$factor = 25; /* main scaling constant */

/* We’ll set factor1 to have scale equal ‘factor’ at liftoff */
$factor1 = $factor / ($liftoff – $ignition) / ($liftoff – $ignition);

/* We’ll set factor2 to have a smooth transition between the expanding and collapsing  phases */
$factor2 = ($factor1*($liftoff-$ignition)*($liftoff-$ignition) – 1) * $liftoff;

if(frame <= $ignition)
           
$scale = 0; /* no exhaust before ignition */
else
{
           
if(frame < $liftoff) /* increasing phase */
                       
$scale = $factor1 * (frame – $ignition) * (frame – $ignition); /* increases geometrically */
           
else /* after liftoff - decreasing phase */
                       
$scale = 1 + $factor2 / frame; /* decreasing hyperbolically towards 1 */
}


Spinning

An infinite rotator can be done much easily with ASL, than with key frames! The basic relation is that connecting the orientation quaternion with the angle of rotation (alpha) around an arbitrary unit axis a(ax, ay, az):

orientation = (ax*sin(alpha/2), ay*sin(alpha/2), az*sin(alpha/2), cos(alpha/2))

We particularize the above relation for rotations around the canonic axii.
To make a rotation around the X axis, enter the following script:

float $speed;
$speed = 5;
/* Replace 5 by your value for speed */
$orientation = (sin($speed*time), 0, 0, cos($speed*time));

To make a rotation around the Y axis, enter the following script:

float $speed;
$speed = 5;
/* Replace 5 by your value for speed */
$orientation = (0, sin($speed*time), 0, cos($speed*time));

To make a rotation around the Z axis, enter the following script

float $speed;
$speed = 5;
/* Replace 5 by your value for speed */
$orientation = (0, 0, sin($speed*time), cos($speed*time));
To make a rotation around an arbitrary axis given by a unit vector ‘a’



point3 $a;
$a = (sin(27), 0, cos(27)); /* a vector defining an axis */
float $speed;
$speed = 5; /* Replace 5 by your value for speed */
$orientation = ($a.x*sin($speed*time), $a.y*sin($speed*time), $a.z*sin($speed*time), cos($speed*time));

 
Gravity path

 Let’s suppose we have a scene element positioned at ‘Initial_position’. We throw it aiming a point (‘Aimed_position’). Let’s find the path of the element, assuming there is gravity, given by the acceleration constant ‘g’. The code:

/* Set the initial position and the aimed position */
point3 $Initial_position, $Aimed_position;
$Initial_position = (-100, 51.07, -17.6); /* some initial location */
$Aimed_position = (-92.6, 71, -15.1); /* the point aimed */

/* Set the gravity acceleration constant */
float $g;
$g = 0.98; /* the value depends on the scale of the environment */

/* Get the velocity of the throwing. We set it as the difference */
/* between the aimed location and the initial location */
point3 $velocity;
$velocity = $Aimed_position - $Initial_position;

/* The current position of the element is the sum of the initial */
/* location and the current displacement. Let's get the */
/* displacement, using the laws of physics: */
point3 $displacement;

$displacement.x = $velocity.x * time;
$displacement.y = $velocity.y * time - 0.5 * $g * time * time;
$displacement.z = $velocity.z * time;

/* Finally, the current position */
$position = $Initial_position + $displacement;


Rolling ball, or wheel

We can see quite often in animations rolling wheels, or a rolling ball. With ASL we can easily make it look real, without sliding. A correct synchronizing between the orientation and the position of the rolling element is given by the following relation:

displacement =  alpha * radius , where the variables have the following meaning:
alpha – angle of rotation around the rotation axis in a time interval (radians)
displacement – how much the element moved in that time interval
radius – the radius of the wheel, or ball

Let’s consider the simplest example of a rolling element in the 'xz' plane, along x axis. This means the rotation takes place around an axis parallel with 'z' axis.
Now, remember the basic relation between the orientation quaternion and the angle of rotation introduced above, because we’ll use it again. The displacement is given by the difference between the current position of the element and its initial position. With some elementary math, we get the following script:

point3 $current_pos, $init_pos;
$init_pos = (-300, 0, 21.3); /* some initial location in the xz plane*/
$current_pos = ? This line is not a code, only that we don’t know yet what to write here
float $half_angle, $radius;
$radius = 15;
$half_angle = -($current_pos.x - $init_pos.x)/$radius/2; /* negative for clockwise */
$orientation = (0.0, 0.0, sin($half_angle), cos($half_angle));

 The problem with this script is that we cannot get the current position of the object! ASL lets us to find the attributes of other elements, but forbids querying the attributes of the current element that runs the script. This would generate a ‘Circular reference’ error. So, we need a workaround! Let’s add a new element in the scene, no matter what element. When it comes to animation, we’ll hide it anyway, so it won’t show up. In this tutorial we’ll ad a target (“target01”) which is invisible in camera view. The important thing is to copy exactly the motion of our element to the newly added element! That means, if our element is animated by position keys, we’ll add exactly the same keys to “target01”, or in case of an ASL position script, we’ll copy that script to “target01”. Now, “target01” will have exactly the same position as our element, but they are not related and we won’t get circular reference error. We can now find out easily the current position of our element, querying the position of “target01”:

$current_pos = GetAttributePoint3("target01", "position");

We can replace line three of the above script with this line and enjoy the animation!
A few more notes:

- One could wonder why don’t we use a simple rotation script for the orientation which doesn’t involve the position of the element, only the time (or frame) variable. With a suitable rotation speed, we could synchronize the uniform rotation with a uniform translation. That would be true for uniform motion, but our script is more general and copes with whatever irregular translations. Our translation doesn’t need to be uniform!

- The radius of the rolling element is obtained from the object editor when the wheel, or ball is created. If it needs scaling, do it using the edit menu (to know exactly the scaling that was performed), NOT with the uniform scale tool! Then compute the scaled radius which will be used in the script.

- The ball (or wheel) has to be located in the origin of the object editor. Otherwise, instead of spinning, we get our element orbiting.

 

 

www.biederman.net/leslie