This website uses cookies to improve user experience. By using our website you consent to all cookies in accordance with our Cookie Policy. X

3D engine for beginners I [basic]

If anyone ever wanted to create their own 3D engine in Flash (and not only) not sure of what to expect, surely they met them self with a lot of mathematics and advanced programming routines during the search for information. It might be a little disheartening, but the truth is you don't need all that fancy stuff to create something basic, like for example: an application that displays a 3D cube.
That is why this post will be dedicated to people who are completely new to the topic of creating a 3D engine (which can display that 3D cube).

All of it will fit into one class - for best effect it should be the document's class. In case you are wondering the "Document Class" can be created on properties tab.

(Enter the class name and press the pencil icon).
After creating the new class we should prepare all the variables that we will need in our little engine. Lets start with the camera position:

var cx:Number = 0;
var cy:Number = 0;
var cz:Number = 0;
Nothing fancy here - camera position will determinate what we see on the screen. I think it is best if I take this moment to explain what effects will the movement have (since we don't have to stick to mathematics' rules and switch stuff like up and down around):
cx is the left(-) or the right(+) movement.
cy is the up(-) or down(+) movement.
cz is the backward/"away from the screen"(-) or forward/"to the screen"(+) movement.
OK, now we need a point where the perspective will focus too:
var vx:Number = stage.stageWidth/2;
var vy:Number = stage.stageHeight/2;
The vanishing point is usually in the middle of the screen and the easiest way to get is to divide the screen in half. Of course nothing stops us from defining a different point (but this will required some modifications to the transformation equation I will talk about later). By the way, the 0,0 point is located on the upper left corner of the screen and everything to the right or down from it consists of positive numbers only.
The last set of variables defines the 3D cube:
var bx:Array = [-50, 50, 50, -50, -50, 50, 50, -50];
var by:Array = [-50, -50, 50, 50, -50, -50, 50, 50];
var bz:Array = [200, 200, 200, 200, 300, 300, 300, 300];
Those three arrays hold points that describe our three-dimensional box. For example if we take bx[0],by[0],by[0] we get the upper left corner of the front facing wall.
Now that we have all the needed parameters we can proceed to create our 3D rendering function. To achieve the smoothest animation it's best to connect it with the ENTER_FRAME event - that is why we will write the following line within the constructor:
Don't forget to import! As you can see I named my function "render" and for now it looks like this:
private function render(e:Event):void {
Just a standard function definition. We will need the graphics.clear(); line because the process of rendering always looks the same - when entering a new animation frame we remove the old graphics and insert new ones (inserting will be explain in a moment). Anyway, it is time to move on onto the most important part of the application, which is the transformation from 3D into the 2D (because currently no monitor screen can handle anything else than 2D image):
var bx2:Array = new Array(bx.length);
var by2:Array = new Array(by.length);
var i:Number = 0;
while (i<bx.length) {
	bx2[i] = vx+(((cx-bx[i])/(cz-bz[i]))*vx);
	by2[i] = vy+(((cy-by[i])/(cz-bz[i]))*vy);
So first things first:
var bx2:Array = new Array(bx.length);
var by2:Array = new Array(by.length);
Those arrays will hold all 2D points after the transformation.
Then, in the loop, we have:
bx2[i] = vx+(((cx-bx[i])/(cz-bz[i]))*vx);
by2[i] = vy+(((cy-by[i])/(cz-bz[i]))*vy);
Which is the code responsible for that transformation. Quite frankly you don't need to understand it to use it efficiently, so feel free to skip the following explanation and perhaps return to it later:
cx-bx[i] - we are subtracting a point's coordinate from the camera's position to retrieve the translation vector. It's a standard method when dealing with transformations, because we don't care where the point is, but rather how far it is from the camera - relative information like that is easier to carry between spaces.
cz-bz[i] - here we calculate the distance from the camera. We need this value to create the illusion of perspective.
(cx-bx[i])/(cz-bz[i]) - and here we create that illusion of perspective, so objects will seem to be getting smaller when moving further away.
*vx - after we are done with the perspective it is time to include the viewing angle. Only not in the scope we would expect it to be as bigger number stretch the image (make the angle smaller). Clearly it has nothing to do with the vanishing point's vx that we defined but it just so happens that the best value here is also the half of the screen.
vx+ - and finally our vanishing point.

Now that we have all our points in 2D, it is time to display them:

graphics.lineStyle(1, 0xffffff, 100);
//front face:
graphics.moveTo(bx2[0], by2[0]);
graphics.lineTo(bx2[1], by2[1]);
graphics.lineTo(bx2[2], by2[2]);
graphics.lineTo(bx2[3], by2[3]);
graphics.lineTo(bx2[0], by2[0]);
//back face:
graphics.moveTo(bx2[4], by2[4]);
graphics.lineTo(bx2[5], by2[5]);
graphics.lineTo(bx2[6], by2[6]);
graphics.lineTo(bx2[7], by2[7]);
graphics.lineTo(bx2[4], by2[4]);
//connecting lines:
graphics.moveTo(bx2[0], by2[0]);
graphics.lineTo(bx2[4], by2[4]);
graphics.moveTo(bx2[1], by2[1]);
graphics.lineTo(bx2[5], by2[5]);
graphics.moveTo(bx2[2], by2[2]);
graphics.lineTo(bx2[6], by2[6]);
graphics.moveTo(bx2[3], by2[3]);
graphics.lineTo(bx2[7], by2[7]);
The graphics.lineStyle(1, 0xffffff, 100); part describes the style of the drawing line. First value is the width (in pixels), second is the color, and the last one is transparency.
Next we have the drawing itself, starting from the front face:

Then we add the back face:

And connect them at the end:

(Of course in the application this will be done instantly).
If everything went smoothing an image of 3D cube should be visible on the screen (just like in the last picture).
In the next step we should implement some kind of camera movement but this will be explained later posts.

Whole source code is available here:

Confirm the image code:confirm image