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.
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);
};




