the animation language
intro
al reference
scheme
animation tools
plugins
tutorials
     tutorial #1
     tutorial #2
references
download
index

Tutorial #1: Getting Started

Using the Tutorials
Loading AL Files
Setting Up a Scene
Making Shapes
Specifying a Camera
Rendering
Altering the Appearance of Shapes with Gops
Color
Transformations
Separators
Shading
Light Sources and Surface Shaders
More Shaders!
Shadows
Animation Using Time




Using the Tutorials

For the most part, these tutorials only require the ox interpreter and a RenderMan renderer as the default rendering package in AL (such as "bmrt" or "prman"). However, you'll be able to experiment more easily if you're also using ogre along with ox to view the examples interactively.

Setup

I usually start up ox in an xterm window (the ">" is the UNIX prompt):

> ox
Welcome to OX, version 5.1 [9/29/99]
[Xt/Motif][BMRT][OGRE][Chant]
ox --> 
and then run ogre from the ox interpreter:
ox --> (ogre)

If you want to make sure everything is working, type the following (bold font) in ox and press return.

ox --> (world (sphere))

Your screen should look something like the following:




Loading AL Files

Simple examples can be tried by typing directly into the interpreter, but you'll want to save non-trivial examples from these web pages to your own personal directory and then load them into ox. AL files are loaded using the Scheme load command. For example, the following loads a file called "ex1.1" (in the directory where ox was started) into ox:

ox --> (load "ex1.1")

There is a very handy Emacs mode which allows a keystroke (Ctrl-c Ctrl-l) to load the file being editied in the current Emacs buffer. See ${ALHOME}/contrib/al/emacs-lisp/README for more information on the al-mode for Emacs. Refer to the ox software description for additional information about loading files.




Setting Up A Scene

The world special form is used to specify the AL code which generates a 3D scene whether it's a single, static geometric shape or an entire animation with elaborate sets and characters. We call the code that generates the scene the world model. The world special form is roughly equivalent to the C programming language main() function -- it's where --> -- execution of the world model starts. And like C's main(), it doesn't make sense to have more than one world special form in a single AL program.

(world
   the code which creates the scene, i.e. the world model
   )

Only geometry specified within the world model can be rendered!

Generating an image in AL usually requires the following steps:

  1. specify a world model which contains geometry and at least one camera; and
  2. render the scene from the viewpoint of a camera we specified in the world model.




Making Shapes

Geometric primitives (gprims) are special AL functions for making shapes. The quadrics (spheres, cones, cylinders, disks, hyperboloids, paraboloids, and torii) are gprims which are both flexible and easy to use. The following AL command is a complete AL program. It creates a world model containing a single torus ("doughnut") shape. (In order to see anything at this point, you'll need to be running ogre.)

ox --> (world (torus))

The torus function, like all the quadric functions and many other gprims, has no required arguments but does allow optional parameters to be specified in a paramlist.

The "thetamax" parameter allows the "sweep" angle (in degrees) of the torus to be specified. The default "thetamax" is 360 degrees. To create a "half-torus," we specify an angle of 180 degrees for the "thetamax" parameter.

ox --> (world (torus 'thetamax 180))
default
(thetamax = 360)
thetamax = 180

To make the torus thinner, the "minorrad" parameter can be adjusted (the default for "minorrad" is 0.5). As many parameters as needed can be set in the paramlist. Remember also that the order of parameters does not matter.

ox --> (world (torus 'thetamax 270 'minorrad 0.25))
thetamax = 270, minorrad = 0.25



Specifying a Camera

The camera gop is used to specify a viewpoint from which the world model will be rendered. AL programs may contain an arbitrary number of cameras.

(camera name type paramlist)

All cameras have a name (so that they can be referenced during rendering) and type. The "perspective" camera is the most commonly used type and it has a number of optional parameters including

  • "from" - the position of the camera
  • "to" - the point in space that the camera is "looking at"
  • "fov" - the field of view specified in degrees

The default camera used by RenderMan render packages is called "main" so it's convenient, particularly if you only need one camera, to define a camera called "main." Below is a world model containing an example camera definition and a torus. You can copy this program into a text editor or just save this file into your own directory. Then it can be loaded into ox.

(world
  (camera "main" "perspective" 'from '#<1 1 3> 'to '#<0 0 0> 'fov 45)
  (torus)
  )
Note: ogre is capable of viewing the scene from any of the cameras defined in the world model. Just select the camera you want from the "Current Camera" sub-menu using the right mouse button.



Rendering

Once a world model containing geometry and a camera has been defined, we can render an image of it using the render command. The AL commands below load example 2.1 and render it.

ox --> (load "ex2.1.al")
ox --> (render)

If you're rendering with BMRT, your shaded image may appear black. In order to see surfaces, light source and surface shaders will have to be specified -- shaders are introduced later in this tutorial -- or you can render image in "wireframe."

A "wireframe" version of the image can be rendered by setting the "style" parameter to "vector" (as in vector line drawing).

ox --> (render 'style "vector")

By default, the image will be rendered to the screen at a default resolution. The size of the output image (shaded or wireframe) can be adjusted using the "format" parameter. The value for the "format" parameter has several forms. The most commonly used one (shown in the example below) is a list containing the horizontal and vertical resolution, in this case, 320 by 240.

ox --> (render 'style "vector" 'format '(320 240))

To render the image to a file, use the "display-name" parameter to set the filename and set the "display-type" parameter to "file."

ox --> (render 'display-name "myimage" 'display-type "file")




Altering the Appearance of Shapes with Gops

Geometric primitives (gprims), like the torus, create simple geometric shapes. Geometric operations (gops) affect the way gprims are drawn in terms of position, orientation, scaling, color, and shading.




Color

For example, the color gop changes the surface color of gprims (the default surface color of gprims is white).

(color red green blue)

Colors in AL are specified using 3 reals (red, green, and blue) each in the range of 0 to 1. Try typing the following AL program into the ox interpreter:

ox --> (world (color 1 0 0) (torus))

If you're running ogre, you should see a red torus.




Transformations

Among the most useful gops are the transformation gops. They allow gprims to be scaled, translated, and rotated.

(uscale s)
(scale x y z)
(translate x y z)
(rotate angle axis)

Let's try rotating the torus 90 degrees about the Y-axis. The program below does just that (you can type this directly into the AL interpreter or into a file which you can then load into AL). The code which has changed since the previous program is in bold.

(world
  (color 1 0 0)
  (rotate 90 y-axis)
  (torus)
  )

y-axis is a global variable defined to the vec3 #<0 1 0>. There are corresponding variables for the other axes called x-axis and z-axis.

Now, let's add a cone which is scaled along the Z-axis to make it longer (the cone, by definition, points along the Z-axis).

(world
  (color 1 0 0)
  (rotate 90 y-axis)
  (torus)
  (scale 1 1 2)
  (cone)
  )

Note that the cone is also colored red and rotated! That's because a gop applies not only to the immediately following gprim, but to all following gprims! But what if we don't want that? The effect of gops can be limited using another gop, called the separator.

There is one other very important property of transformation gops. For a particular gprim, the transformation gops which are closest (in the program) to the gprim are applied first. So, in the example program above, the cone is

  1. scaled along Z; and then
  2. rotated about Y.
One way to think about this is that there is a list of tranformations which is built up by transformation gops. When a gprim is drawn, each transformation in the list is applied in order to the gprim. But, when a transformation gop is executed, that individual transformation specified by that gop is placed at the beginning of the list, and not at the end as you might expect. Using the example above again, the transformation list would look like
    (rotate 90 y-axis)
when the torus is drawn and
    (scale 1 1 2), (rotate 90 y-axis)
when the cone is drawn. And for the cone, that's why the scale is applied before the rotation.




Separators

Conceptually, the separator gop localizes the effect of gops to a particular block of code.

(separator body)

Any gops appearing in body will not apply to any gprims or anything else (like shaders) outside of body. Let's use a separator so that the color gop and rotate gop (in the program above) apply only to the torus. Note that now the torus is rotated and colored red, but the cone is not.

(world
  (separator
    (color 1 0 0)
    (rotate 90 y-axis)
    (torus)
    )
  (scale 1 1 2)
  (cone)
  )




Shading

The section will introduce the use of light source and surface shaders in AL and also touch on shadow generation. But first, let's introduce two new gprims: polygonal boxes and bilinear patches.




Some New Gprims

The box gprim creates a six-sided, polygonal cube which extends from -1 to 1 in each dimension.

(box paramlist)

A slightly more complex gprim is the surface patch which is used to define free-form surfaces. Patches come in two flavors: "bilinear" and "bicubic." In this tutorial, we'll use "bilinear" patches only. Bilinear patches are defined by 4 vertices (control points). Bilinear patches are similar to quadrilateral polygons, except that bilinear patches don't have to be flat and the control points are specified in row order rather that in a clockwise or counter-clockwise order. Note that the control point vertices are specified in the paramlist using the "P" parameter.

(patch type paramlist)

The example code below (available as ex4.1.al) uses the patch, box, and sphere gprims to generate the model shown in the images immediately below. This example will be used repeatedly in this section to illustrate the use of shaders.

example 4.1
wireframeshaded

;; example 4.1

(world
  (camera "main" "perspective" 'from '#<1 1 3> 'to '#<0 0 0> 'fov 45)

  (separator
    (uscale 3)
    (patch "bilinear" 'P '(#<-1 0 1> #<1 0 1> #<-1 0 -1> #<1 0 -1>)))

  (separator
    (translate -.5 .5 .2)
    (rotate -30 y-axis)
    (uscale .5)
    (color .54 .14 .14)
    (box))

  (separator 
    (translate .6 .35 .8)
    (uscale .35)
    (color 1 1 .25)
    (sphere))
  )




Light Source and Surface Shaders

Light source and surface shaders are specified using the light and surface gops.

(light name paramlist)
(surface name paramlist)

name specifies the name of the shader to use (e.g. "spotlight" or "plastic"). Most shaders have several parameters each with a reasonable default value. The parameters can be changed by specifying the parameter name and value in the paramlist. For example,

(surface "plastic" 'Ks 0.7 'specularcolor '#<0 0 1>)
specifies the "plastic" surface shader and changes the value of the "Ks" parameter to 0.7 and changes the "specularcolor" from its to default of white (#<1 1 1>) to blue (#<0 0 1>).

Always remember that shaders are gops -- they affect all subsequent geometry and can be localized using separators. Also, shaders are affected by transformation gops. In other words, most lights and other shaders are rotated, scaled, translated, etc. just like gprims are (altough this behavior is dependent on each individual shader implementation).

In example 4.2, two light source shaders are specified (one "ambientlight" and one "spotlight") and the "plastic" surface shader is applied to all surfaces.

example 4.2




More Shaders!

AL provides several mechanisms for getting information about shaders since the supported shaders and shader types varies from renderer to renderer. The examples in this section assume that the default render package is "prman."

The query-shader-types function returns a list containing each shader type supported by the default render package.

ox --> (query-shader-types)
("displacement" "imager" "light" "surface" "volume")

The query-shader function has two forms used to find out

  • what shaders are available for a particular shader type
    (query-shader shader-type)

  • the parameters and default values for individual shaders
    (query-shader shader-name)
For example, let's find an interesting surface shader for the cube in our working example. If we supply query-shader with a valid shader type, it will print a sorted list of the available shaders corresponding to that type for each directory in your shader path.
ox --> (query-shader "surface")
/usr/local/prman/prman/lib/shaders
    carpet
    cmarble
    ...
    spatter
    stippled
    stone
    texmap
    wood

If we supply query-shader with the name of a shader it will print the shader type and name, a list of all parameters with default values, and the location of the shader.

ox --> (query-shader "spatter")
surface spatter
    Ka            1.0
    Kd            0.5
    Ks            0.699999988079071
    roughness     0.200000002980232
    specksize     0.00999999977648258
    sizes         5.0
    specularcolor "rgb" #<1 1 1>
    basecolor     "rgb" #<0.1 0.1 0.1>
    spattercolor  "rgb" #<1 1 1>

/usr/local/prman/prman/lib/shaders/spatter.slo

Example 4.3 applies the "spatter" shader, with changes to a few shader parameters, to the cube. Note that the spatter shader is applied only to the cube because the surface gop is placed inside the separator with the cube.

example 4.3




Shadows

Example 4.4 is exactly the same as Example 4.3 except that the light-shadows gop is used to make the spotlight cast shadows. By passing #t as the argument to light-shadows (the default is #f -- don't cast shadows), any subsequent light sources will cast shadows.

example 4.4

Both the "prman" and "bmrt" render packages support this facility. However, the "prman" package only supports shadows for the "spotlight," "distantlight," and "pointlight" light source shaders and even though AL does much of the work regarding shadow map generation, there are still numerous controls for shadow map appearance and efficiency. You should consult the PRMan AL extension documentation for more information.




Animation Using Time

This section introduces the simplest form of animation in AL: animation based on the global variable time. The use of hierarchically animated models and animation tracks (avars) will be discussed in a later tutorial.




Time

The global variable time is a Scheme number (an integer or a real) which corresponds to the current "logical" time in the world model. It is sometimes called "global time" because is often associated with the current frame number of an animation. It is not "wall clock" time -- it does not change continuously. It only changes when we set it directly or when we execute another AL function which sets it (like render). If you type the variable name "time" into the ox interpreter, its value will be printed (like any other Scheme expression). The default value for time is 1.
ox --> time
1.0

Unlike other Scheme variables, time has a unique status. It is assumed, by default, that the world model is dependent upon the value of time. Therefore if time changes, the world model is automatically re-evaluated (re-executed).

Try the following experiment. Define a world model which only prints the value of time.

ox --> (world (print time))
1.0

Note that the body of world (the world model) is executed by the world special form itself -- the value "1.0" is printed. Now, change the value of time using set-time!.

ox --> (set-time! 5)
5

The value "5" is printed because the world model was automatically re-evaluated by set-time!. The reason for using set-time! instead of good old set! is that set! will not automatically update the world model.

IMPORTANT! Do not use set-time! inside the body of world (ie. in the world model) because this would cause an infinite loop.



Animated Gprim!

Load the following AL program into ox. It says "draw a sphere and use the current value of time for the thetamax paramter." (Thetamax is the sweep angle and can have a value between 0 and 360 degrees.)
(world 
  (camera "main" "perspective" 'from '#<1 1 3> 'to '#<0 0 0> 'fov 45)
  (sphere 'thetamax time)
  )

If you are running ogre, you should see a thin sliver of an arc instead of the full sphere (because time is small). The frame can be rendered at the current time by just executing render.

ox --> (render)

Now try changing time and rendering again (ogre should update automatically).

ox --> (set-time! 180)
()
ox --> (render)

Instead of calling set-time! and render, we can use the render command's "frame" parameter to set the value of time and render the frame all at once.

ox --> (render 'frame 270)

By passing a list containing the first frame, last frame, and frame increment as the value for the "frame" parameter, a sequence of frames can be rendered. The following command renders frames 1, 55, 109, 163, 217, and 271 in wireframe at a resolution of 160x120 to the screen.

ox --> (render 'frame '(1 271 54) 'format '(160 120) 'style "vector")

To render the frames to a file, set the "display-type" parameter to "file." The default value for "display-name" is "frame~s" which means that the individual frame filenames will be "frame0001," "frame0055," etc. The "~s" is replaced by the current frame number padded, by default, with 4 zeros. If you specify a different "display-name" and forget to include "~s" in the name, all the frames will be written to the same file (probably not what you want). The "~s" can be placed anywhere in the name.

ox --> (render 'frame '(1 271 54) 'display-type "file"
               'format '(160 120) 'style "vector")



AL: The Animation Language is Copyright © 1992-2000, Stephen F. May