Ultrashock Tutorials > Flash4 > 3 Dimensions of Flash4  
 
By: David Colquhoun, DavidColquhoun.com

Source File
PDF file

 
3 Dimensions of Flash4
 

But my screen is flat!

Introduction

Lets face it, Flash just isn't built to do 3D animation. It's a 2D vector animation program. There are no built-in 3D tools, no z-depth. So how do you do anything 3 dimensional in Flash? It's simple - you fake it.

There are two general approaches; using a sequence of still images, and dynamically moving movieclips to create shapes that appear to have depth. I'm going to talk briefly about a few different ways to create 3D sequences and, in much more detail, will explain how to move movieclips using some simple high school maths.



A sequence of still pictures

Trace bitmap

Draw your images use a 3D modeling/animation package like 3D Studio or Lightwave, then render a sequence of still bitmap images. Use the trace bitmap feature in Flash to turn each bitmap into line work. For the best results render the bitmaps large so Flash has more information to work with. Also turn the anti-aliasing off so Flash will draw a single line for separate shapes, rather than drawing lots of grey stripes. After you've traced them, shrink them down to their original size. If your 3D software has a cell shader, using that will help stylise the animation.

Vector rendering

Use a 3D package to draw/animate what you want and use vector rendering software to directly create a sequence of still vector images. Two pieces of software perfect for this are:


     Swift 3D

  • by Electric Rain
  • http://www.swift3d.com
  • pc only
  • us$139
  • gradient shading
  • allows you to draw/animate simple 3D models
  • imports EPS, AI, 3DS

    Vecta 3D


Because they are both quite inexpensive, I'd say buy both and see which has the best look/feel for your project.

Adobe Dimensions

If your images are quite simple - for example, a spinning logo or an extruded piece of text; you can use Adobe Dimensions to extrude/revolve a piece of linework and then export a sequence of Illustrator files. It also draws primitive objects like sphere, cube, cylinder or cone. The best thing about Dimensions is that you may already have it, as it's been around for a long time, and most print companies have brought it at some time or another. So check your software cupboard.


Some of the drawbacks with using a sequence of still pictures are: the increased file size, a limited point of view, and decreased frame-rate (because Flash doesn't like moving lots of curves), but the advantage is that you do get much more detailed pictures.


Moving movieclips using mathematics

By arranging movieclips containing points, lines or triangles on the screen, you can suggest depth and space. For example; railway tracks and trees getting smaller in the distance.

There are many tricks to doing this. The main one that I use is to make objects in the background smaller than objects in the foreground. To do this we need to know how far back each part of the picture is. So we store the location of each point in 3 dimensional space. Then we map each 3D point (x,y,z) onto a 2D surface (x,y), shrinking the 3D x and y values as the z value gets greater. Show where the points are by placing a movieclip on each point, stretching a line between two points or warping a triangle to fit between 3 points. The final part is to rotate the points around the x and y axis, as seeing the object from all directions makes it easier to see its shape.

There are two example FLA files to help you understand this section. Better3DFlash-simple.fla and Better3DFlash-complex.fla. Start with the simple file and when you have the hang of that, check out the extra features built into the complex file. Both are made to be as modular as posible; most parts are contained within the 'object' movieclip. The 'sin' and 'cos' movieclips can be anywhere as long as they are referenced properly from within the 'spinxy' frame action, which I'll explained in more detail later (This is used in the 'object' movieclip).

Example : Cube Spinning in 3 Dimensions



Step 1 : Storage

Each point in 3D space is defined by x, y, z co-ordinates, in the same way that the position of a movieclip in Flash is defined by x, y co-ordinates. A shape like a cube is therefore defined by a set of points something like this:

  X   Y   Z
 50  50 -50
-50  50 -50
-50 -50 -50
 50 -50 -50
 50  50  50
-50  50  50
-50 -50  50
 50 -50  50

This represents a cube 100 pixel wide, and centered on 0,0,0. To store this in Flash you will need to create an array using dynamically named variables. In action script the cube would look like:


Set Variable: "pt1_x" = 50
Set Variable: "pt1_y" = 50
Set Variable: "pt1_z" = -50
Set Variable: "pt2_x" = -50
Set Variable: "pt2_y" = 50
Set Variable: "pt2_z" = -50
Set Variable: "pt3_x" = -50
Set Variable: "pt3_y" = -50
Set Variable: "pt3_z" = -50
Set Variable: "pt4_x" = 50
Set Variable: "pt4_y" = -50
Set Variable: "pt4_z" = -50
Set Variable: "pt5_x" = 50
Set Variable: "pt5_y" = 50
Set Variable: "pt5_z" = 50
Set Variable: "pt6_x" = -50
Set Variable: "pt6_y" = 50
Set Variable: "pt6_z" = 50
Set Variable: "pt7_x" = -50
Set Variable: "pt7_y" = -50
Set Variable: "pt7_z" = 50
Set Variable: "pt8_x" = 50
Set Variable: "pt8_y" = -50
Set Variable: "pt8_z" = 50

Example : Cube with points and co-ordinates labeled

In the example files this array is created inside the 'init' frame. It's parsed from a variable called 'pointset' that looks like:

50, 50, -50R -50, 50, -50R -50, -50, -50R 50, -50, -50R 50, 50, 50R -50, 50, 50R -50, -50, 50R 50, -50, 50R



Writing the co-ordinates for a simple shape like a cube isn't too mind-bending, but you just try drawing a person like this! :) Thankfully you don't have to, because you can draw your model using something like 3D Studio, export it as a VRML format file, open the file in a text editor and look for something like:

Coordinate { point [ 10.0 10.0 10.0, 2 20 2, 30 0 0 ] }

which is a list of x,y,z co-ordinates for the VRML model which you just need to copy into Flash.



Step 2 : Display

To display your 3D object on a flat computer screen you need to map each 3 dimensional point (x,y,z) onto a 2 dimensional surface (x,y). The most common way is to use a single point perspective, where objects in the background are smaller, and closer together than objects in the foreground. As z gets greater (positive) then x and y gets smaller, and as z gets smaller (negative) x and y get greater.

Railway tracks and trees getting smaller in the distance.

The math looks kind of like this:

scalar = z / 600
scalar = 1 / scalar
2Dx = scalar * x
2Dy = scalar * y


where 600 is the strength of the perspective.

Monitor plane and xyz co-ordinates mapping



The set of 2D points is built by the 'build2Dpointset' frame action within the '3Dobjects' timeline. It is called from within the looping frame, every time the 3D point set is moved or changed.

The 2D point set for the 100 pixel cube would look like:

  2Dx 2Dy
pt1 64.65 68.1
pt2 -67.65 66.5
pt3 -68.4 -65.05
pt4 65.4 -66.5
pt5 41.45 39.45
pt6 -38.2 38.85
pt7 -38.45 -40.5
pt8 41.75 -41.05

and in action script:


Set Variable: "pt1_2Dx" = 64.65
Set Variable: "pt1_2Dy" = 68.1
Set Variable: "pt2_2Dx" = -67.65
Set Variable: "pt2_2Dy" = 66.5
Set Variable: "pt3_2Dx" = -68.4
Set Variable: "pt3_2Dy" = -65.05
Set Variable: "pt4_2Dx" = 65.4
Set Variable: "pt4_2Dy" = -66.5
Set Variable: "pt5_2Dx" = 41.45
Set Variable: "pt5_2Dy" = 39.45
Set Variable: "pt6_2Dx" = -38.2
Set Variable: "pt6_2Dy" = 38.85
Set Variable: "pt7_2Dx" = -38.45
Set Variable: "pt7_2Dy" = -40.5
Set Variable: "pt8_2Dx" = 41.75
Set Variable: "pt8_2Dy" = -41.05

Points

If you create several movieclips, and set their x and y properties to match the 2Dx and 2Dy positions of each point, then the movieclips will follow the points of your shape and you'll get something looking like: Cube with points only

Each of those movieclips could contain an animation, a button, or even another set of spinning points.

In the example files the point movieclips are called 'p1', 'p2', 'p3' and so on. In the 'init' frame action these points are duplicated off a movieclip called 'point' which is then hidden. This way you just need to change the variable called 'numberofpoints' rather than copying and renaming movieclips manually.

Inside the point movieclip is a frame called 'moveme', which when called uses the 'me' variable stored within itself, to establish its 2Dx and 2Dy values, and then sets its position.


Set Property ("", X Position) = "../" & me & "_2Dx"
Set Property ("", Y Position) = "../" & me & "_2Dx"
These moveme frame actions are called every time the frame updates from within the looping frame. It's structured this way so that it has the same structure as the lines movieclips. It's easy therefore, to add more features such as setting the alpha or scale properties, or setting the type of point, to this 'moveme' function. You can see an example of this in the complex FLA file and you can also read more about this style of structuring here.


Lines

Displaying lines in 3D is simply a matter of stretching a line between the two 2D co-ordinates which we've already calculated. For each line there are two variables: 'line1_start' and 'line1_end'. They are both strings that describe the start and ending point of that particular line:

Set Variable: "line1_start" = "pt1" 
Set Variable: "line1_end" = "pt3" 
The moveme frame action inside the lines movieclip does the following:

1. Figures out the x and y positions of the start and end points:


Set Variable: "start" = eval("../:"&me&"_start") 
Set Variable: "end" = eval("../:"&me&"_end") 
Set Variable: "x1" = eval("../:"&start&"_2Dx")
Set Variable: "y1" = eval("../:"&start&"_2Dy")
Set Variable: "x2" = eval("../:"&end&"_2Dx")
Set Variable: "y2" = eval("../:"&end&"_2Dy")
2. If the gradient of the line is positive then it's going down the screen \ , if it's negative then it's going up the screen / . Go to the frame with the appropriate line in.


If (((y2 - y1) / (x2 - x1)) > 0)
      Go to and Stop (2)
Else
      Go to and Stop (1)
End If
3. Because the / and \ lines are centered, we can position the lines movieclip half way between the start and end points;


Set Property ("", X Position) = x1 - ((x1 - x2) / 2)
Set Property ("", Y Position) = y1 - ((y1 - y2) / 2)
4. And then scale its width and height to fit the distance between the two points. Because the lines movieclip is 100x100 pixels we just need to know the number of pixels between the start and end points, and then set the x_scale and y_scale to that distance.


Set Variable: "xscale" = x1 - x2
Set Variable: "yscale" = y1 - y2
If (xscale<0)
      SET VARIABLE: "Xscale" = XSCALE * -1
END IF
IF (YSCALE<0)
      SET VARIABLE: "Yscale" = YSCALE * -1
END IF
SET PROPERTY ("", X SCALE) = XSCALE + 1
SET PROPERTY ("", Y SCALE) = YSCALE + 1
In Better3DFlash-complex.fla the alpha value for the line is also calculated, using the z value halfway between the start and end z locations.

Example : Cube with lines only


Triangles

Ok, now it get really too scary for me. I'm not going into detail, as it would take a thesis to explain this thoroughly. If you take a right angle triangle, 100x100 pixels, you can use combinations of scale and rotate to stretch it into a triangle of any shape. If you write some action script to figure how much to scale and rotate the triangles by, you could draw solid shapes built out of triangles.

Example : Triangle scaleing/rotating

And here's someone (Kaluzhny Pavel) who has made triangles work.
http://kaluzhny.nm.ru/3D.html



Step 3 : Move them

The nice thing about building 3D objects this way is you can rotate/scale/squash them anyway you want. Add or subtract to the x, y, z values to move the points/shapes. Multiply or divide to scale the shape.

Rotation however gets a bit confusing. Here's the actionscript:


Set Variable: "/sin:input" = spinx
Call ("/sin:sin")
Set Variable: "sinX" = /sin:output

Set Variable: "/sin:input" = spiny
Call ("/sin:sin")
Set Variable: "sinY" = /sin:output

Set Variable: "/cos:input" = spinx
Call ("/cos:cos")
Set Variable: "cosX" = /cos:output

Set Variable: "/cos:input" = spiny
Call ("/cos:cos")
Set Variable: "cosY" = /cos:output



Set Variable: "i" = 0
Loop While (i <> numberofpoints)
      Set Variable: "i" = i + 1
      Set Variable: "ii" = "p"&i&"_"
      Set Variable: "tmp_zpos" = eval(ii&"z") * cosY - eval(ii&"x") * sinY
      Set Variable: ii&"tx" = eval(ii&"z") * sinY + eval(ii&"x") * cosY
      Set Variable: ii&"tz" = eval(ii&"y") * sinX + tmp_zpos * cosX
      Set Variable: ii&"ty" = eval(ii&"y") * cosX - tmp_zpos * sinX
End Loop


The first part calculates the sine and cosine of 'spinx' and 'spiny', using my homemade sine and cosine functions. You can read more about how these work here.

'spinx' is the angle you want to rotate the points by around the x axis and 'spiny' is the angle you want to rotate the points by around the y axis. This takes place inside the 'spinxy' frame action inside the objects timeline, and is called every time the frame is updated.

Looping through all the points, we create temporary x,y,z coordinates ('pt1_tx', 'pt1_ty', 'pt1_tz') for each point. They are temporary because errors in rounding get compounded over time and cause spinning objects to look like they are collapsing, as the x,y,z values are continuously rounded closer to zero. To solve this we always spin the points from their original locations. "spinx" and 'spiny' are how much the object is currently rotated by. They are measured in degrees and can be any number, negative or positive. 'spinxchange' and 'spinychange' are how much to change 'spinx' and 'spiny' by, each frame. To control the speed of the rotation, change 'spinxchange' and 'spinychange'.

Don't worry too much about the math in the last 4 lines, I don't understand it, and I've never needed to, just copy and paste it. If you do understand it, and can explain it to me, I would appreaciate that very much! :)


Conclusion

I hope that this helps you to understand 3D in Flash, and that the source files save you a bit of time developing the worlds next 3D spinny menu system.



Extension exercises
  • animated/tweened points
  • worlds within worlds
  • 3d shape modeler
  • Faster depth sort
  • curved lines

Download source FLA:

Example files:

Related links:

Related Ultrashock Articles:


 

 
©2000 Ultrashock.com Inc. - All rights reserved