3D in Flash (Plus source code)

Friday, May 02, 2008   —   Vienna 0 Comments

I came across an old peice of Flash work I did about 2 years ago amongst some of my old files on the computer. I did this when I was developing a Flash website as part of the Dark Gloriole video game project. I eventually abandoned the website idea this because building the game demanded too much time.

But what I have left is a neat little peice of a 3D engine implemented in Flash — complete with backface-culling an all! Some time in the future, when I have time I'll revisit this whole 3D thing, it was a lot of nerdy fun.

Loading...

I've posted the source code for the 3D engine here for anyone who's interested. You can cut-n-paste it into Flash and it will work swell!

var dCount = 1;
var fl = 300;
var toRad = Math.PI/180;
var origin = {x:0, y:0};
// degree of rotation on x, y, and z axis
var rotate = {x:0, y:0, z:0};
var camera = {x:0, y:0, z:0};


var spin = {x:0, y:0, z:0};

// object coordinates in 3D world space
var plots = [pt3D(0, -50, -5), pt3D(50, -25, -5), pt3D(50, 25, -5), pt3D(0, 50, -5), pt3D(-50, 25, -5), pt3D(-50, -25, -5), pt3D(0, -50, -5), pt3D(0, -50, 5), pt3D(50, -25, 5), pt3D(50, 25, 5), pt3D(0, 50, 5), pt3D(-50, 25, 5), pt3D(-50, -25, 5), pt3D(0, -50, 5)];


toPaint = new Array();

// put points in 3D world space
function pt3D(x, y, z) {
    point = new Object();
    point.x = x;
    point.y = y;
    point.z = z;

    return point;
}


isVisibleBetween = function (a, b, c) { if (((b.y-a.y)/(b.x-a.x)-(c.y-a.y)/(c.x-a.x)<0) ^ (a.x<=b.x == a.x>c.x)) {return true;} else {return false;}};

// draw point into 2D for camera space
function draw2D(x, y, z) {
    // paint the 3d object onto the screen space
    this.createEmptyMovieClip("obj", 100+dCount);
    with (this.obj) {
        // face 1
        lineStyle(1, 0x112240, 5);
        if (isVisibleBetween(toPaint[0], toPaint[1], toPaint[2])) {
            beginFill(0x445570, 100);
            moveTo(toPaint[0].x, toPaint[0].y);
            for (var i = 0; i<5; i++) {
                lineTo(toPaint[i+1].x, toPaint[i+1].y);
            }
            endFill();
            // face 1 shine
            beginFill(0xD6DFE2, ((((toPaint[1].x-toPaint[5].x)/100)*100)/1.5)+((((toPaint[0].y-toPaint[3].y)/100)*100)/1.5));
            moveTo(toPaint[0].x, toPaint[0].y);
            for (var i = 0; i<5; i++) {
                lineTo(toPaint[i+1].x, toPaint[i+1].y);
            }
            endFill();
        }

        // face 2
        if (isVisibleBetween(toPaint[9], toPaint[8], toPaint[7])) {
            beginFill(0x445570, 100);
            moveTo(toPaint[7].x, toPaint[7].y);
            for (var i = 7; i<12; i++) {
                lineTo(toPaint[i+1].x, toPaint[i+1].y);
            }
            endFill();
            // face 1 shine
            beginFill(0xD6DFE2, ((((toPaint[8].x-toPaint[12].x)/100)*100)/1.5)-((((toPaint[7].y-toPaint[10].y)/100)*100)/1.5));
            moveTo(toPaint[7].x, toPaint[7].y);
            for (var i = 7; i<12; i++) {
                lineTo(toPaint[i+1].x, toPaint[i+1].y);
            }
            endFill();
        }
 
        // sides
        for (var i = 0; i<6; i++) {
            if (isVisibleBetween(toPaint[i+8], toPaint[i+1], toPaint[i+0])) {
                beginFill(0x445570, 100);
                moveTo(toPaint[i].x, toPaint[i].y);
                lineTo(toPaint[i+1].x, toPaint[i+1].y);
                lineTo(toPaint[i+8].x, toPaint[i+8].y);
                lineTo(toPaint[i+7].x, toPaint[i+7].y);
                lineTo(toPaint[i+0].x, toPaint[i+0].y);
                endFill();
                // side 1 shine
                beginFill(0xD6DFE2, ((((toPaint[i].x-toPaint[i+7].x)/1.5)*100)/10)-((((toPaint[i].y-toPaint[i+2].y)/100)*100)/1.5));
                moveTo(toPaint[i].x, toPaint[i].y);
                lineTo(toPaint[i+1].x, toPaint[i+1].y);
                lineTo(toPaint[i+8].x, toPaint[i+8].y);
                lineTo(toPaint[i+7].x, toPaint[i+7].y);
                lineTo(toPaint[i+0].x, toPaint[i+0].y);
                endFill();
            }
        }
    }
}


var yx, zx, xy, zy, xz, yz;
var x, y, z;
function rotation(array, rotate) {
    for (i=0; i < array.length; i++) {

        x = array[i].x+camera.x;
        y = array[i].y+camera.y;
        z = array[i].z;

        yx = y*Math.cos(rotate.x)-z*Math.sin(rotate.x);
        zx = z*Math.cos(rotate.x)+y*Math.sin(rotate.x);

        xy = x*Math.cos(rotate.y)+zx*Math.sin(rotate.y);
        zy = zx*Math.cos(rotate.y)-x*Math.sin(rotate.y);

        xz = xy*Math.cos(rotate.z)-yx*Math.sin(rotate.z);
        yz = yx*Math.cos(rotate.z)+xy*Math.sin(rotate.z);
        scale = fl/(fl+zy+camera.z);

        x = xz*scale;
        y = yz*scale;
        z = zy;

        // create an array of points to paint
        this.toPaint[i] = {x:origin.x+x, y:origin.y+y};

        this.draw2D(x, y, z);
    }
}



this.onEnterFrame = function() {
    this.rotate.x += (origin.y-_ymouse)/25*toRad;
    this.rotate.y += -(origin.x-_xmouse)/25*toRad;
    // this.rotate.z += Math.atan2(_ymouse, _xmouse)/25;
    thiswheel._rotation += (_xmouse-origin.x)/50;
    this.wheel._alpha = 50;

    // run the world
    rotation(this.plots, this.rotate);
};

Add a comment

The fields that are highlighted contain errors
Name:
Email:     (Not shown)
Website:
Comment:
  Notify me when my comment has been cleared.
  Notify me of followup comments.