Home

Menu
Home
Articles
Downloads
AoI Extensions Catalog
Portal Blog
Forum
Links
AoI Wiki
AoI Homepage
About Art of Illusion
Popular Downloads
Live Translation
Login Form





Lost Password?
The Cornell Box
Name:

Message:

Polls
What do you think about the Spline Mesh toolbar button? Do you use it?
 
Which area of AoI needs to be made more convenient?
 
Syndicate
FS AoI Portal
Who's Online
Latest Forum Posts
Scripting Tutorial - Part I
User Rating: / 2
PoorBest 
Written by Francois Guillet   
Tuesday, 26 June 2007
This article is the first one of a series that introduces scripting for Art of Illusion. No specific knowledge is required, although obviously some rudiments in Java are welcomed.

Although Art of Illusion offers wealth of possibilities using its GUI interface, there are times when manipulating/adding objects programmatically can achieve results no other method can. Programmatically means that a computer program is run to achieve a given result.

Programs external to Art of Illusion can be written either in a plugin or a script. There is not much difference between the two and we can consider that scripts are small plugins. What is important to remember is that scripts have little limitation in what they can do. Scripts are written in a scripting language called Beanshell (http://www.beanshell.org/) which is essentially the Java language plus some language facilities for scripting. The important result is that you would write essentially the same code wether you write a script, a plugin or even a part of AoI code.

Whew, that's quite a statement! Does that mean that only people that are able to write AoI code can write scripts? No, of course not. All you need are some examples to feed from, cooking recipes and the like. This is precisely what this series of articles are about!

Before we dive into AoI API, we'll spend some time on Java. Java is an object oriented language. What does that mean? Let's suppose you hava a point on a screen refered to as an integer value along X axis (x) and an integer vlaue along Y axis (y). We want to offset this point by 10 pixels along X and 15 pixels along Y. In the early days of programming, you'd use two variables to define the point and simply add the relevant offset to each variable:

int x, y;

...

x=x+10;

y=y+15;

It can't be much simpler, but there is a problem with this design. x and y variables are not tied, in fact no-one except the programmer know they from a point. Later came on languages like C that are able to embed variables in a structure. Here we'll supose the structure Point includes two integer variables named x and y. Our program would go:

Point point;

...

point.x = point.x + 10;

point.y = point.y + 15;

(the dot in point.x means accessing a structure inner variable, or, rather, field). That's better, but still not perfect. Supposing the screen has bounds (and it sure has), what warrants that the point remains within the screen bounds after offset? Would you have to check against these bounds each you offset a point? In fact, it would be probably better if the Point structure provided a safe way of offsetting a point as well..

Here comes object orientated programming. Not only can we embed variables inside a structure (now called class) bu we can also provide bits of code that will work safely on these variables. The bits of code are called methods. In an oriented language, the program would now go:

Point point;

...

point.offset(10, 15);

and the offset method would take care that the point remains within the screen bounds. Here, the definition of a point is the Point class, the variable point itself is called an instance of the class Point and offset is the method that carries out on offset on a point.

Obviously, if we want to program scripts for Art of Illusion, we need to now which class have been writtent and how they do work. To this end, you must download the following documentation: http://www.artofillusion.org/docs/downloads/javadocs.zip. Un pack the archive and look for the index.html file. Open it with your favourite browser. The lower left pane lists all classes defined within Art of Illusion. Select a class, say Vec3. This is the class used to represent 3D vectors. The documentation says you can access x, y and z fields. Fields can be hidden to external access so as to make sure people use methods rather than directly set fields, a dangerous way of living. Here, accessing x, y and z fields is rather harmless so you can access a Vec3 v coordinates through v.x, v.y and v.z.

Do I need to read the whole set of classes before writing a script? Not at all. But there are a few key classes that you'll encounter often and you need to know. Once you get acquainted with these, you'll see learning to use a new class using the documentation is easy.

Enough with academic stuff, let's code! For this time, we'll suppose you need to write a script that mirrors the positions of a curve points. In other words you want to mirror a curve such that points at the right become at the left and vice versa. Mathematically, this means that if x is the value of the X coordinate of a curve vertex, you must assign -x to this coordinate.

We need a tool script to do this. Tool scripts transform existing objects or add objects to a scene, permanently. Object scripts can do the same transformation/addition, but they're executed prior to rendering and they do not permanently affect the scene.

So let's edit a file using a suitable text editor. I'd suggest JEdit but you can do with any editor that features colour syntaxing and line numbering. AoI built-in editor is too weak for any other job than just correct a script on the fly.

How are we going to achieve curve mirroring? First, we must gain access to the curve currently selected. Then we need to transform each of its vertex.

First things first. All we have access to when the script starts is the active editing window. This window is an instance of the class LayoutWindow and is referred to as the variable window. We're not much interested in the editing window, what we want is the scene (the collection of 3D objects if you prefer). Let's browse the LayoutWindow methods... Hmm it looks like getScene() (Get the Scene associated with this window) would do the job. So the first line of our script is:

scene = window.getScene();

Now we have the scene we want to access currently selected objects. Looking at the API doc, it seems getSelection() (Get a list of the indices of all selected objects) is the one to use. Notice it returns a variable of type int[], an array of integer. So our next line goes:

selection = scene.getSelection();

We'll decide that the script runs only if there is one object selected and it's a curve (obviously). So we need to check the number of selected objects and exit the script if it's not equal to one.

if (selection.length != 1){
new MessageDialog(window, "Select at least 1 curve");
return;
}

MessageDialog is a utility class that displays a message, as the name implies. If the program runs past this point then we're sure there is only one object selected.

The next step is making sure the selected object is a curve. To fetch the nth object of a scene, we can use scene.getObject(n). Here the index t the (presumably) curve object is hold in selection[0]. But have look at what this method returns: an instance of ObjectInfo. We're not to a 3d object yet. Nevertheless, we enter the following line into our script :

info = scene.getObject(selection[0]);

And have a look at this ObjectInfo class. Ah, it has an Object3D as field. Cool, Object3Ds are the real 3D objects such as Cylinders, Spheres, Meshes, etc. There is also a CoordinateSystem... ObjectInfo class makes sense when you realize objects have to be laid in the scene at a given point with a given orientation. A cylinder is not always centered at origin of the scene coordinate system with its axis pointing upwards... The ObjectInfo coordinate system thus translates the object internal coordinate system (or local coordinate system) to the scene coordinate system (or global coordinate system). But this has little to do with our goal: retrieving the curve). Let's get to the selected Object3D:

object = info.object;

and let's check if it's a curve. But what's the class for a curve. Let's see... Hey it's a Curve. Too easy! Butt how can we check if it's a Curve? Type in the following lines which don't need much explanation:

if (! (object instanceof Curve) ) {

new MessageDialog(window, "The selected object must be a curve");
return;
}

Now we're sure that object is indeed a curve we can start working on the positions of the curve vertices. We'll use the getVertexPositions() method to access the vertex positions. This method returns an aray of Vec3 which hold a copy of the location of the vertices.

v = object.getVertexPositions();

We then loop over the array to invert the x value of each Vec3 :

for (int i = 0; i < v.length; i++) {

v[i].x = -v[i].x;

}

Since we work on a copy of the locations, we have to set the curve vertices locations to their new values. We'll use the setVertexPositions() method:

object.setVertexPositions(v);

and finally we've got to tell the scene that we've modified an object so it can update the display:

scene.objectModified(object);

Here's a recap of the script so you can copy it for convenience:

scene = window.getScene();
selection = scene.getSelection();
if (selection.length != 1){
new MessageDialog(window, "Select at least 1 curve");
return;
}
info = scene.getObject(selection[0]);
object = info.object;
if (! (object instanceof Curve) ) {
new MessageDialog(window, "The selected object must be a curve ");
return;
}
v = object.getVertexPositions();
for (int i = 0; i < v.length; i++) {
v[i].x = -v[i].x;
}
object.setVertexPositions(v);
scene.objectModified(object);

We're done! Now is the time to test our work. Save the file as MirrorCurve.bsh in the Scripts/Tools folder of AoI distribution. Create a curve, select it and run the script. Congratulations! You've written your first script!




Leave a comment
RSS comments

Only registered users can leave comments.
Please login or register.

Powered by AkoComment Tweaked Special Edition v.1.4

Last Updated ( Tuesday, 26 June 2007 )
 
< Prev