This is an archived tutorial from the kirupa.com legacy collection. It covers software that may no longer be available, but it is kept online because the ideas still hold up.
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 ]
this.createEmptyMovieClip("theScene", 1);
theScene._x = 150;
theScene._y = 150;
focalLength = 300;
make3DPoint = function(x,y,z){
var point = new Object();
point.x = x;
point.y = y;
point.z = z;
return point;
};
make2DPoint = function(x,y, depth, scaleFactor){
var point = new Object();
point.x = x;
point.y = y;
point.depth = depth;
point.scaleFactor = scaleFactor;
return point;
};
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
Transform3DPointsTo2DPoints = function(points, axisRotations){
var TransformedPointsArray = [];
var sx = Math.sin(axisRotations.x);
var cx = Math.cos(axisRotations.x);
var sy = Math.sin(axisRotations.y);
var cy = Math.cos(axisRotations.y);
var sz = Math.sin(axisRotations.z);
var cz = Math.cos(axisRotations.z);
var x,y,z, xy,xz, yx,yz, zx,zy, scaleFactor;
var i = points.length;
while (i--){
x = points[i].x;
y = points[i].y;
z = points[i].z;
// rotation around x
xy = cx*y - sx*z;
xz = sx*y + cx*z;
// rotation around y
yz = cy*xz - sy*x;
yx = sy*xz + cy*x;
// rotation around z
zx = cz*yx - sz*xy;
zy = sz*yx + cz*xy;
scaleFactor = focalLength/(focalLength + yz);
x = zx*scaleFactor;
y = zy*scaleFactor;
z = yz;
TransformedPointsArray[i] = make2DPoint(x, y, -z, scaleFactor);
}
return TransformedPointsArray;
};
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.
pointsArray = [
make3DPoint(-50,-50,-50),
make3DPoint(50,-50,-50),
make3DPoint(50,-50,50),
make3DPoint(-50,-50,50),
make3DPoint(-50,50,-50),
make3DPoint(50,50,-50),
make3DPoint(50,50,50),
make3DPoint(-50,50,50)
];
for (i=0; i < pointsArray.length; i++){
attachedObj = theScene.attachMovie("redballoon", "redballoon"+i, i);
}
cubeAxisRotations = make3DPoint(0,0,0);
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.
rotateCube = function(){
cubeAxisRotations.y -= this._xmouse/3000;
cubeAxisRotations.x += this._ymouse/3000;
var screenPoints = Transform3DPointsTo2DPoints(pointsArray, cubeAxisRotations);
for (i=0; i < pointsArray.length; i++){
currBalloon = this["balloon"+i];
currBalloon._x = screenPoints[i].x;
currBalloon._y = screenPoints[i].y;
currBalloon._xscale = currBalloon._yscale = 100 * screenPoints[i].scaleRatio;
currBalloon.swapDepths(screenPoints[i].depth);
}
};
theScene.onEnterFrame = rotateCube;
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 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 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.
That wraps up this tutorial. A huge thank you to all of you who buy kirupa's books, became a paid subscriber, watch the videos, and/or interact on the forums. Your support is what keeps writing like this online! 😇
This tutorial was written by senocular, also known as Trevor McCauley. He has been one of this community's most generous teachers since the early Flash days, and he is still around: find him on senocular.com and on the forums.
:: Copyright KIRUPA 2026 //--