Scripting
3D in Flash
by
senocular
Rotation Around A Common
Center
This first example represents
a cube rotating in 3D space but does so by rotating
circle shapes around a common center all with
the same rotation. Their arrangement in respect
to each other make up the 8 corners of a cube
shape. Despite the fact that they are just circles,
the cube shape is fairly distinguishable to anyone
viewing it.
[
balloon forming a rotating cube ]
Steps to Create Animation
- Create
your screen element. There's only one; a circle
(or balloon). This is all that is needed for
this example. No ground or anything else. In
fact, it will be the last movieclip made for
this collection of 3D examples. Everything beyond
this will be made entirely with Actionscript.
This current example revolves entirely around
this one movieclip which will be attached 8
times to define the cube
- Next
is your basic scene setup creating theScene
and centering it in the screen. No camera this
time, but a focalLength is still needed for
that scaling associated with the 3D space. Also,
no objectsInScene array will be defined yet.
This example will take a slightly different
approach in handling the objects in the scene
that will carry over better into the next examples.
- After
that, a new small function will be defined.
This will create an object in Flash with 3 properties
x, y and z, passed into that function. This
new object, as you might have guessed, would
represent a point in 3D space. The reason we
are making a function to make a point like this
is for the sake of ease and compactness. Instead
of writing out the needed code to make an object
with set x, y and z properties, this function
can be easily called and that object can be
created more easily for us.
- Similarly,
a 2D point making function can be made. This
will act to create an object for holding just
an x and a y position. However, considering
how the balloon clips on the screen need to
be scaled and have their depths swapped, some
extra values for that can be added to this point.
You'll see where this is used in the following
step.
- Now
its time to get into what was effectively before,
the display function(s). The idea of the display
function was to provide a unique way of handling
individual shapes in 3D scene each frame. That
concept is going to be dropped here for something
slightly different. There will still be an array
of positions a la objectsInScene, only here,
they will be a collection of points (created
with the makePoint function) rather than movieclips.
All these points, though, are each handled the
same way and simply rotated without any other
behaviors to separate them from the other points.
The reason for this is because all those points
make up the same final 3D object, a square in
this example and would therefore behave the
same. The balloon movieclips are then, after
the 3D calculations on those points, put at
the position of those points as they would exist
in 2D space on the screen.
The 3D calculations on the array of points will,
like before, be done in a loop. This loop, however,
will be contained in a single function call
which will be used to convert or transform
all of the 3D points in the array into 2D points.
This function will handle all trig functions
and looping and produce a new array of 2D points.
Before, the 2D aspect was just set to a MovieClip's
_x and _y, but since the points don't necessarily
have their own _x and _y, we can just make a
new array to be used as the transformed screen
points. The real effectiveness of this function
comes in its handling of the trig functions.
If you think about how the display functions
work, each one of those functions when called
for each movieclip in the scene re-calculated
a Math.sin() and Math.cos() calculation for
each movieclip given their angles and the angle
of the camera. Because all of the points here
behave the same and are all based the same rotation,
you can greatly reduce the need for calling
Math.sin() and Math.cos() speeding up processing.
The truth is, you only need to call Math.sin()
three times and Math.cos() three times, once
for each axis of rotation and just use them
for each point in the loop. Pre-calculating
Math.sin(angle) and Math.cos(angle) before the
loop can add some much needed speed to the 3D
scene. This can be especially important later
on when more complex shapes might be attempted.
So this new function follows the following pattern:
-
function call:
-
pre-calculate
Math.sin and Math.cos for each 3 angles
of rotation
-
loop through
each point in the array containing the
3D points for the scene
-
use the trig
equations with the pre-calculated sine
and cosine values to rotate each point
in 3D space
-
based on the
new x, y and z values determine a 2D x
and y (along with scaleRatio and z for
depth of movieclip)
-
add each of
the calculated values to a new array as
a 2D point
-
when done looping,
return the new 2D array of 3D points transformed
to 2D points
This function represents the the 3D engine
for this movie. It handles all the points and
rotations and transforms those points from 3D
points to 2D points as they would appear on
the screen. Its this function that handles most
all the work and will do so for basically all
of the examples that follow. Notice how temporary
values are used in each of the trig functions
which are then, following the operations, set
to the actual final x, y and z.
- With
that 3D functionality complete you can begin
mapping out the 3D points that make up your
scene, in this case, the cube. This is just
an array of eight 3D points made using the make3DPoint
function. As you can see, the make3DPoint function
makes the coordinates in for each point much
more compact and easier to see and interpret
being together like that. This square is 100x100x100
centered around the 3D point (0,0,0) or the
center of the cube and scene.
- Following
the definition of the points, the balloons can
be attached. One balloons will be attached for
each point in the pointsArray. This can be done
using a loop based on the pointsArray's length,
attaching a balloon for each point in that array.
The naming convention here will be important
as it will be used later on when these clips
are set to the 2D positions of each of those
points after the 3D to 2D transformation - in
fact, this same loop will be used again in doing
that - each name being based the i value in
that iteration of the loop.
- There's
one last item that needs to be created before
getting to the onEnterFrame function. That's
the variables for the rotations used in the
cube. If you noticed in the Transform3DPointsTo2DPoints
function, a passed axisRotations object was
used in the sine and cosine calculations. This
was an object with an x, y and z value for each
rotation for that axis - and object with an
x, y and z - that's just a 3D point object!
The fact that there are rotations equivalent
to the number of axis or values in a 3D point
makes the 3D point created with the make3DPoint
function a prime candidate for containing the
rotations for the cube. So now, just make a
3D point to hold the rotations of the cube as
it spins around in the scene.
- Last
but not least, the function to run the spinning
cube - the onEnterFrame function. This performs
3 actions:
-
determines
rotation values from the mouse
-
calls the Transform3DPointsTo2DPoints
function to create an array of all the
3D points converted into 2D or screen
points
-
and assign
the position of each attached balloon
to each of those new 2D points (adding
in scaling and depth swapping)
Its
number 3 where we see the return of the loop
for the balloons. Once the 2D points have
been created, we'll need to go through and
correctly relate those points to each one
of those attached clips. Since they were created
based on the pointsArray, they can be assigned
the same way. The difference being you are
assigning based on the new array of 2D points
and not the original 3D points in pointsArray.
That, however, doesn't matter since the new
array of points is the same as pointsArray,
just in 2D terms and not 3D. With that assignment,
the 3D cube is fully functional.
Note that the mouse only changes
the x and y values in cubeAxisRotations. The
z axis isn't even changed, though it still seems
as if (and really is) a full range of 3D rotation
is achieved.
|
SUGGESTION:
Avoid Re-looping |
This last
example with the rotating cube with
the balloons loops through the pointsArray
2 times, once to transform the points
and create the array of 2D points and
another to cycle through and assign
each movieclip to its corresponding
screen position. Looping twice like
inefficient and could slow-down your
movie. It would be best to perform all
the actions in one loop. However, that
example was to setup the new Transform3DPointsTo2DPoints
function which will be used in the examples
to follow that don't have the extra
loop since there are no attached movieclips
involved. The only loop will be the
one in Transform3DPointsTo2DPoints. |
|
The 3D Engine
The Transform3DPointsTo2DPoints function
of this past example is the grounds from which
all following examples will be based. It will
be the engine running each of those movies. There
may be some changes here and there, but the general
functionality will remain the same. As an engine,
Transform3DPointsTo2DPoints is actually quite
simple only performing the basics of point transformation
and doesn't even handle other operations such
as the displaying of visuals etc. for you which
other, and probably most, 3D engines would. That
process, however, will be done manually and slightly
different concerning in the remaining examples
so it's not incorporated into the function as
it exists now. You are free to do so on your own,
though. There is no set way of doing things and
other 3D engines for Flash could be completely
different than this one. This is just one way
of getting the job done.
The Drawing API
The drawing functions in Flash was only just touched
upon in the first example. Its about time we started
pushing what they have to offer in terms of getting
a true rendered 3D shape out of all that has been
learned so far in creating a 3D scene in Flash.
No attached movieclips involved here.
|