# 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.

creates a container for our objects, centers it in the middle of the stage and calls **InitScene()**

, a routine that creates the objects. **make3Dobj(…)**

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

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.**make3Dobj()**

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

**function, which multiplies the matrices and returns the result. If you read the section on matrix math, these equations should look familiar.**

`MatrixMatrixMultiply()`

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

does this by looping through the objects and redrawing each object based on the newly rotated coordinates. The rotation is handled by the **RenderScene()**

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.**MatrixVectorMultiply()**

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

Z-sorting of the objects is handled by the

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.**swapDepths()**

#### 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