General Category > Ongoing Anim8or Development

ASL Functions

(1/2) > >>

As of build 1070 Anim8or supports user functions in ASL. The format is like normal functions:

<type> name ( <type> ident, <type> ident, ...)

There is a new type void for functions that don't return a value and a new statement:
return <expr>;
As usual, return statements can only appear in functions and don't have the <expr> for void functions.

OK now the restrictions:

1. No forward declarations. Function headers must be followed by the definition in the form of a compound statement "{...}".

2. No recursion. Anim8or doesn't check for self-recursion yet (a last minute bug  :().  If you try it be prepared for chaos. I plan on allowing recursion but it's quite a bit of work to do efficiently so it may take a while.

3. Functions must be declared before they are called.

4. There is no "main" function yet. Any statements that aren't in a function are gathered into the "main" function, no matter where they appear.  Kind of whacky, I know, but this allows you to more easily add functions to existing scripts. I'll fix this shortly by supporting a "main" structure.

5. No array parameters. All parameters and function results are the predefined types: int, string, float, point2, point3, quaternion, float4x4, shape, meshdata, spline, material, attribute, texture, object, figure, sequence, scene, and tridata.

6. All parameters are passed by value. Remember: types that represent objects within Anim8or (shape, meshdata, material, etc.) are actually handles so any changes to the parameter within a function affect the same object as outside the function. In the future I hope to add support for an out modifier to return values through parameters as well as via the function result.

7. Function format parameter and local declarations are in a separate scope from global variables.  Declarations within compound statements {} are still in the enclosing scope however. I hope to fix this soon as well but it could potentially break existing scripts. Let me know if you think this would be a big problem.

8. Not really function related, but you can use C++-style "//" comment delimiters now.

I'll post a couple of examples when I get a chance but hopefully this gives you something to start with!

Excellent! I will be sure to test this thoroughly :)

So far so good! I like the "//" comment delimiters ;)

Regarding #5 of the restrictions, do you intend to add arrays?

Regarding #7, I take it you meant that variables declared within an enclosing brackets (such as an if(){} statement), aside from within functions, are still accessible to the entire script. I've tested this and yeah it's a bit against the standard. I don't think it'll be too great of an issue for pre-existing scripts if this is fixed, since a lot of us never even declare variables within compound statements anyway. Personally, I didn't even know I could do so until recently, and most of the scripts by others that I've seen keep the variables outside. Whatever problems with backward compatibility it causes, I think it's worth having local scope, in my opinion.

I've written a few functions based from my AOBake script, and they work exactly as I expected them to. I've had no issues as of yet asides from the restrictions. I do have a few comments about ASL in general, if you don't mind my posting them here:

A "break" statement for compound statements would be...spectacular.
Apparently, changing the starting variable in the for statement, from within, does not affect the looping. I've tried it as a fix for not having a "break" statement, such as in the code below:

--- Code: ---#command("object");

file $c;
int $i;

$"$console", "w");

for $i = 0 to 10 do
$c.print("%d\n", $i);

if($i == 5)
$i = 10;


--- End code ---

The above code does not break the loop when $i reaches 5.

Some happy functions:

--- Code: ---/**
 * @author Randall Bezant (aka Raxx)
 * @attribution "Fast, Minimum Storage Ray/Triangle Intersection" by Tomas Moller and Ben Trumbore:
 * @param <point3> $v0, $v1, $v2 - The three points of the colliding triangle in clockwise direction
 * @param <point3> $rSource - Ray source point
 * @param <point3> $rDir - Ray Direction
 * @return point2 - If collision, returns the length along the ray direction (known as t),
 * and collided indicator of 1 for a value of (1, t). Otherwise returns (0, 0). If t is negative,
 * that means it collided in the opposite direction of the specified ray direction, behind the
 * ray source.
 * Single-sided ray/triangle intersection method. To get the point of intersection on the triangle,
 * use this formula:
 * pI = p + t*d
 * pI: Point of intersection (point3)
 * p: Ray source (point3)
 * t: length along ray (float)
 * d: Ray direction (point3)
point2 $rayTriangleIntersect (point3 $V0, point3 $V1, point3 $V2, point3 $rSource, point3 $rDir)
// Determinant
point3 $pvec, $tvec, $qvec, $edge1, $edge2;
float $determinant, $triangleV, $triangleU;

$edge1 = $V1 - $V0;
$edge2 = $V2 - $V0;

$pvec = cross($rDir, $edge2);
$determinant = dot($edge1, $pvec);

if ($determinant < 0.000001)
return (0,0);

$tvec = $rSource - $V0;
$triangleU = dot($tvec, $pvec);

if($triangleU < 0.0 || $triangleU > $determinant)
return (0,0);

$qvec = cross($tvec, $edge1);
$triangleV = dot($rDir, $qvec);

if ($triangleV < 0.0 || $triangleU + $triangleV > $determinant)
return (0,0);

return (1, dot($edge2, $qvec) / $determinant);


--- End code ---

--- Code: ---/**
 * @author Randall Bezant (aka Raxx)
 * @param <int> $sPointIndex - The point index on the sphere
 * @param <float> $sRadius - Radius of the sphere
 * @return point3 - X,Y,Z of the point
 * Generates the coordinate for an indicated point on a sphere
point3 $uniformSpherePoint(int $sPointIndex, float $sRadius)
float $sY, $sR, $sPhi, $inc, $off;

$inc = PI*(3-sqrt(5));
$off = 2.0/$numSpherePoints;
$sY = $sPointIndex * $off - 1 + ($off/2);
$sR = sqrt(1 - $sY*$sY);
$sPhi = $sPointIndex * $inc;

return (cos($sPhi)*$sR, $sY + 0.05, sin($sPhi)*$sR)*$sRadius;

--- End code ---

--- Code: ---/**
 * @author Randall Bezant (aka Raxx)
 * @param <vector> $vector
 * @return <Float4x4>
 * Convert a directional vector to a transform matrix
float4x4 $vectorToTransform(point3 $vector){

float $dot;
quaternion $quat;

$dot = dot((0,1,0), $vector);

if ($dot <= -1){
$quat = (0, 1, 0, 0);
} else if ($dot >= 1){
$quat = (0, 0, 0, 1);
} else {
$vector = cross((0, 1, 0), $vector);
$quat.x = $vector.x;
$quat.y = $vector.y;
$quat.z = $vector.z;
$quat.w = 1 + $dot;
$quat = normalize($quat);

return toFloat4x4($quat);

--- End code ---

5. Yes I do plan on adding array parameters. There are a number of weird "features" (a.k.a. bugs) in the existing ASL implementation involving arrays that need to be fixed before I can add them. These "features" are thinks like you can assign an array to a scalar, and visa versa, ans Anim8or doesn't catch it.  The result is not defined. Valid programs work correctly but invalid ones are not caught.

7. Yes, I mean supporting true C/C++ like scopes. I think it's worth doing and agree that any backwards compatibility issues should be minimal. I just wanted to point this out before I do the work in case anybody had any objections.

break is a good idea.  I'll add it to the list of things to do.

The for semantics is something that I wasn't aware of (or had forgotten :)) I think your example should work as you intended so I'll fix that too.

Nice function examples :)

Found an easy fix for the for loop bug, raxx.  Thanks for reporting it!

#098-005 - ASL for loops: assignment to control variable is overwritten by loop step code.
Status: Fixed for build 1071


[0] Message Index

[#] Next page

Go to full version