Showcase and discover digital art at yex

Follow Design Stacks

Subscribe to our free newsletter to get all our latest tutorials and articles delivered directly to your inbox!

3D ActionScript

3D ActionScript

With all of the background information out of the way, it is time to begin building our 3D engine. In the example FLA file included with this tutorial, these scripts are located in Frame 1.

Initializing the environment

We start by initializing the movie with our global variables. It is always good practice to initialize global variables in one place so that you may re-initialize them at a later time. The following function, initMovie() will set our global variables:

function 
InitMovie() {
   TransformMatrix = new Array(new Array(1,0,0),

new Array(0,1,0), new
     Array(0,0,1), new Array(0,0,0));
   f = 300;
   moviewidth = 600;
   movieheight = 400;
   lines = 0;
   curves = 0;
   surfaces = 0;
}

The variable TransformMatrix will be the container for all of our model rotations. The initial value of ((1,0,0), (0,1,0), (0,0,1)) corresponds to no rotation at all. As we rotate our model, this variable will be updated to reflect the current angle of view.

The variable f is the focal length of the ‘camera’ that we use to view the objects in the 3D space. The value will affect the amount of perspective introduced into the rendering. Higher values tend to flatten the 3D space, while low values tend to warp the 3D space.

Creating the 3D objects

Next, we build the 3D objects that will live in the 3D space. InitScene() creates a container for our objects, centers it in the middle of the stage and calls make3Dobj(…), a routine that creates the objects.

function 
InitScene() {
   createEmptyMovieClip("Scene",
1);
   Scene._x = moviewidth/2;
   Scene._y = movieheight/2;
   make3Dobj("line", new Array(new
Array(50,100,0), new Array(50,-100,0)), 1, "0x009900",50);
}

The function make3Dobj() can create lines, curves and fills, depending upon the parameters passed, populating the objects with line weight, color and alpha values used in rendering the object.

function 
make3Dobj(objtype, pointarray, lineweight, linecolour, linealpha,
fillcolour, fillalpha) {
   obj = Scene.createEmptyMovieClip(objtype
+ "_" + this[objtype + "s"], lines+curves+surfaces);
   obj.pointarray = pointarray;
   obj.lineweight = lineweight;
   obj.linecolour = linecolour;
   obj.linealpha = linealpha;
   obj.fillcolour = fillcolour;
   obj.fillalpha = fillalpha;
   this[objtype + "s"] ++;
}

These parameters are described in the following table:

Parameters Description
objtype String. Only the values “line”, “curve”, and “surface” are valid.
pointarray Multi-dimensional Array. See below.
lineweight Number. The thickness of the line measured in pixels.
linecolor String. The hexadecimal color value of the line.
linealpha Number. The percent visibility of the line.
fillcolor String. The hexadecimal color value of the fill.
fillalpha Number. The percent of visibility of the fill.

The pointarray parameter is a multi-dimensional array that defines the x, y and z coordinates of the points and control points needed to draw 3D lines, curves and surfaces. The parameter may be created inside the function call as the code above shows, or may be created as a global variable as shown in the examples that follow.

The pointarray parameter for lines contains two arrays. The first array corresponds to the coordinates for the start point of the line and the second corresponds to the coordinates for the end point. The following ActionScript example creates a line array that can be passed to make3Dobj():

Point1 
= new Array(0,0,0);
Point2 = new Array(100,0,0);
Pointarray = new Array(Point1, Point2);

The pointarray parameter for curves contains three arrays. The first and second arrays correspond to the coordinates of the start and end points of the curve. The third corresponds to the coordinates of the control point. The following ActionScript example creates a curve array that can be passed to make3Dobj():

Point1 
= new Array(0,0,0);
Point2 = new Array(0,100,0);
Point3 = new Array(50, 50, 0);
Pointarray = new Array(Point1, Point2, Point3);

The pointarray parameter for surfaces contains line and curve arrays in any sequence or number. The following ActionScript example creates a surface that can be passed to make3Dobj():

Point1 = new Array(0,0,0);
Point2 = new Array(100,0,0);
Line1 = new Array(Point1, Point2);
Point3 = new Array(0,0,0);
Point4 = new Array(0,100,0);
Point5 = new Array(50, 50, 0);
Curve1 = new Array(Point3, Point4, Point5);
Pointarray = new Array(Line1, Curve1);

Setting the transformation matrix

Next, we’ll need a method for updating our global transformation matrix so that we can rotate our 3D objects. The function SetTransformMatrix() does this by first generating a temporary transformation matrix and then calling the MatrixMatrixMultiply() function, which multiplies the matrices and returns the result. If you read the section on matrix math, these equations should look familiar.

function 
SetTransformMatrix(x, y, z, M) {
   vectorLength = Math.sqrt(x*x+y*y+z*z);
   if (vectorLength>.0001) {
     x /= vectorLength;
     y /= vectorLength;
     z /= vectorLength;
     Theta = vectorLength/500;
     cosT = Math.cos(Theta);
     sinT = Math.sin(Theta);
     tanT = 1-cosT;
     T =[[], [], []];
     T[0][0] = tanT*x*x+cosT;
     T[0][1] = tanT*x*y-sinT*z;
     T[0][2] = tanT*x*z+sinT*y;
     T[1][0] = tanT*x*y+sinT*z;
     T[1][1] = tanT*y*y+cosT;
     T[1][2] = tanT*y*z-sinT*x;
     T[2][0] = tanT*x*z-sinT*y;
     T[2][1] = tanT*y*z+sinT*x;
     T[2][2] = tanT*z*z+cosT;
     TransformMatrix = MatrixMatrixMultiply(T,M);
   }
}

function MatrixMatrixMultiply(A, B) {
   C = new & Array(new Array(), new Array(),
new Array());
   C[0][0] = A[0][0]*B[0][0]+A[0][1]*B[1][0]+A[0][2]*B[2][0];
   C[0][1] = A[0][0]*B[0][1]+A[0][1]*B[1][1]+A[0][2]*B[2][1];
   C[0][2] = A[0][0]*B[0][2]+A[0][1]*B[1][2]+A[0][2]*B[2][2];
   C[1][0] = A[1][0]*B[0][0]+A[1][1]*B[1][0]+A[1][2]*B[2][0];
   C[1][1] = A[1][0]*B[0][1]+A[1][1]*B[1][1]+A[1][2]*B[2][1];
   C[1][2] = A[1][0]*B[0][2]+A[1][1]*B[1][2]+A[1][2]*B[2][2];
   C[2][0] = A[2][0]*B[0][0]+A[2][1]*B[1][0]+A[2][2]*B[2][0];
   C[2][1] = A[2][0]*B[0][1]+A[2][1]*B[1][1]+A[2][2]*B[2][1];
   C[2][2] = A[2][0]*B[0][2]+A[2][1]*B[1][2]+A[2][2]*B[2][2];
   return C;
}

The input parameters x, y and z define the axis about which the global transformation matrix will be rotated and can be any number value. In the case when x is given a value and y and z are both zero, the resulting rotation will be about the X-axis only. The same holds true for the other axes as well.

Rendering the scene

Finally, we will write a function for rendering the 3D objects created above. The function RenderScene() does this by looping through the objects and redrawing each object based on the newly rotated coordinates. The rotation is handled by the MatrixVectorMultiply() function, which performs the necessary matrix multiplication. To create perspective, each x and y coordinate is then multiplied by the global variable f and divided by the z coordinate.

View the ActionScript that renders the 3D objects (in a new browser window).

Z-sorting of the objects is handled by the swapDepths() command. To determine the stacking order of the objects, the center of each object is calculated from the points and subtracted from the camera position. Thus, the further away the object is from the camera, the lower the layer number.

Adding interaction

So that we can see the engine in action, we will add a simple mouse interaction to our movie that rotates the 3D objects. To do this, we will add a simple two-frame loop to our movie by adding a keyframe at frame 3 containing the code below. Of course, more complex interactions can be built into our movie, but you will have to experiment with those on your own.

SetTransformMatrix(-Scene._ymouse,Scene._xmouse,0,TransformMatrix); 
RenderScene(); gotoAndPlay(2);

Now we’re ready to take a look at the finished movie.

Comments