The drawTriangles Method

The drawTriangles method takes parameters that are Vectors. The AS3 Vector class is new to FP10, so before we talk about drawTriangles, let us say a few words about the Vector class.

The Vector Class.  In short, a Vector is a typed array; that is, it is an array whose all elements are of the same declared datatype. The syntax for creating vectors is a bit different than for arrays. For example, the code:

var myVector:Vector.<Number> = new Vector.<Number>();

creates and initializes a variable 'myVector' which is a Vector whose all elements are of the datatype Number. The length of myVector is not specified; thus, the empty parenthesis in the Vector constructor. To populate 'myVector', we can use any of the following:

myVector.push(1,2.5,7);

myVector=Vector([1,2.5,7]);

myVector[0]=1; myVector[1]=2.5; myVector[2]=7;

The drawTriangles Method.  We will use portions of the code behind our applet to explain how the drawTriangles method can be applied to transform bitmap images. First, we need a BitmapData object. In our example, we embedded the image of the leadlight using the Flex's 'Embed' tag. If we had Flash authoring tool to compile content for FP10, we would store the image in the Library. One way or another, we get the BitmapData of our image and store it in a variable 'bdWindow':

var bdWindow:BitmapData=ourImage.bitmapData;

drawTriangles is a method of the Graphics class. Hence, it can be evoked by a DisplayObject via its 'graphics' property. In our example, we use a Sprite called 'spContainer'. In our applet, the drawTriangles method draws the distorted image in spContainer based on the current positions of its corners. The code that does it is contained within the function 'renderView' defined in the script. The code within the function looks as follows:

spContainer.graphics.clear();

spContainer.graphics.beginBitmapFill(bdWindow);

spContainer.graphics.drawTriangles(vertices,indices,uvtData);

spContainer.graphics.endFill();

As we see, drawTriangles is evoked within a bitmap fill. (For vector drawings, it could be within 'beginFill'...'endFill'.) The drawTriangles method requires at least one and practically at least three parameters. Customarily, they are called 'vertices', 'indices', and 'uvtData'. (The last, optional parameter 'culling' is useful in 3D applications and we will discuss it in an upcoming tutorial on drawTriangles in 3D applications.) All three parameters are instances of the Vector class:

drawTriangles(Vector.<Number>,Vector.<int>,Vector.<Number>)

The first parameter, vertices, contains x and y coordinates of all the vertices for all the triangles to be drawn and filled with portions of our bitmap. The coordinates are listed consecutively but are interpreted as pairs, each pair representing a point, that is, an actual vertex.

The second parameter, indices, contains integers. Again, the integers are listed consecutively but they are read in triples: each triple corresponds to three vertices of a triangle to be drawn. Each integer corresponds to a vertex, that is, to a pair in the vertices Vector.

The third parameter, uvtData, contains numbers. The numbers are listed consecutively but they are read in pairs. Each pair in uvtData corresponds to a pair in the vertices Vector and represents the position of a given vertex within our BitmapData. The positon of a vertex is measured as the horizontal and the vertical distance of the vertex from the point (0,0). Each distance is expressed as a fraction of the total width and height of the BitmapData, so it is always between 0 and 1. (Depending on the length of the uvtData Vector, its elements may be read in triples. Each triple then contains the position of a vertex, u, v, and its disortion for projection factor, t. In the applet presented here, the lenghts of uvtData and vertices are equal, so we do not have the t parameter. The t parameter is useful in 3D applications.)

Given this rather complicated relationship between elements of the three vectors, vertices, indices, and uvtData, manipulating them and using the drawTriangles method is a bit challenging. Let us try to illuminate the concept with an example involving triangulation into two triangles only.

Triangulation of the original image.  Let us create the vertices, indices and uvtData Vectors for only two triangles and no distortion of our BitmapData. The vertices are simply the four vertices of the image. Let us denote them as V0, V1, V2, V3 and think of them as Points so we can talk about their x and y coordinates. The coordinates are measured in pixels relative to the container in which drawing takes place. (In our script, the vertices are denoted curV0, curV1, curV2, curV3, and the container is spContainer.) Here are the corresponding vertices, indices, and uvtData Vectors. For the sake of clarity, in each of the Vectors we separated pairs and triples by adding spaces. Of course, spaces don't matter in the script.

Suppose that with vertices, indices, and uvtData defined as above, we call:

spContainer.graphics.clear();

spContainer.graphics.beginBitmapFill(bdWindow);

spContainer.graphics.drawTriangles(vertices,indices,uvtData);

spContainer.graphics.endFill();

Two triangles, marked T1 and T2 will be drawn, with vertices defined by indices, vertices coordinates defined in vertices, and the portions of the image to be mapped onto each triangle defined in uvtData. Since V0, V1, V2, V3 are original vertices, we will see the original image with no distortion.

If we move the V0, V1, V2, V3 by dragging them, the vertices Vector will change, but the indices Vector and the uvtData vector will not change. Of course: the way we define triangles in terms of vertices has not changed, and we want the same triangles within the original image, T1, T2, to be mapped onto the distorted triangles newT1, newT2.

To produce the distorted image, we call again:

spContainer.graphics.clear();

spContainer.graphics.beginBitmapFill(bdWindow);

spContainer.graphics.drawTriangles(vertices,indices,uvtData);

spContainer.graphics.endFill();

On the illustration above it seems that we are redefining the uvtData and indices Vectors with each distortion. Since they do not change, we are not redefining them in the script. They remain constant throughout the life of the model.

If you play with the applet and change the number of triangles, you will notice that the triangulation into two triangles does not produce smooth results. We triangulate into 20 triangles when the applet is initialized. With many triangles the vertices, indices, and uvtData Vectors become rather long even though we try not to keep to the minimum duplication of vertices that appear in several triangles.

Regardless how many triangles we have in our triangulation, the uvtData and the indices Vectors remain constant. It is the coordinates of all the vertices corresponding to new positions of the dragged corners that have to be recalculated with each corner being dragged. As we will see in an upcoming FP10 3D experiment, the same is true in 3D texture mapping: uvtData and indices stay constant, but the vertices Vector has to be recalculated after each rotation and projection.

Download

The zip file linked above contains all the 'as' and 'jpg' files related to the applet.

The image that we used comes from Wikipedia. It depicts a typical domestic leadlight in 1920s.

Back to Advanced and Experimental              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.