3D Engine / ActionScript 2 / 2005

Found this old thing laying around. Originally started in Flash 4, it's evolved a bit over the years. The last thing I did was add that shading from the light source. This is the result of a lot of googling, porting various C code equations, and trial and error.



The light is affected by mouse position and you can spin the cube by dragging.

3D Engine / ActionScript 1 (Flash 4) / 2000

This is a 3D engine I made back in 2000 in Flash 4. It was of the first example of a 3D engine I created in Flash 4, which I eventually ported to Flash 5. I still believe this is one of the first 3D engines built in Flash. At the time, Flash didn’t support real math calculations. So, operations like Sin and Cosin had to be estimated or stored in a lookup table (ack!). I had to take all these ridiculous equations from c/c++ code and port them to the then primitive ActionScript. Below, I display the heart of the nasty Flash 4 code.

Ancient Flash 4 Code
x_speed = Number(x_speed) + Number(rotate_x);
y_speed = Number(y_speed) + Number(rotate_y);
z_speed = Number(z_speed) + Number(rotate_z);

if (x_speed > 360){ x_speed=number(x_speed)-360;}
if (y_speed > 360){ y_speed=number(y_speed)-360;}
if (z_speed > 360){ z_speed=number(z_speed)-360;}

tellTarget("trig"){
    gotoandStop(/:x_speed);
}
tsx = (trig.point._x +10.1)/100;
tcx = (trig.point._y +10.1)/100;

tellTarget("trig"){
    gotoandStop(/:y_speed);
}
tsy = (trig.point._x +10.1)/100;
tcy = (trig.point._y +10.1)/100;

tellTarget("trig"){
    gotoandStop(/:z_speed);
}
tsz = (trig.point._x +10.1)/100;
tcz = (trig.point._y +10.1)/100;

for (i=1; i<=Number(point_count); i++) {
    tellTarget("point" add i){
        /:bx = x;
        /:by = y;
        /:bz = z;
    }
    
    rx = tcy * bx + tsy * bz;
    rz = -tsy * bx + tcy * bz;
    ry = tcx * by - tsx * rz;
    
    rz = tsx * by + tcx * rz;
    rrx = tcz * rx - tsz * ry;
    rry = tsz * rx + tcz * ry;
    
    rx = rrx * perspective;
    ry = rry * perspective;
    rz = rz + perspective;
    
    tellTarget("point" add i){
    	z_alpha = /:rz 
    }
    
    if (rz == 0) {
        rz = 1;
    }
    
    dx =  rx/rz + CX;
    dy = -ry/rz + CY;
    
    setProperty ("point" add i, _x, dx);
    setProperty ("point" add i, _y, dy);
    
    pos1 = "point" add i;
}


3D Engine / ActionScript 1 (Flash 5) / 2001

Below is an example of the engine in Flash 5. This was done sometime in early 2001. The engine is more stable with the Flash 5 code and supports vertex dragging (although inaccurate). Rolling over the smaller boxes will morph the 3d object into another shape.

Bloated Flash 5 Code
r2d = 0.0174531625854772222222222222222222 ; 

if (dragging ne "true"){
if (random_mode eq "true"){
	x_speed = Number(x_speed) + Number(rotate_x);
	y_speed = Number(y_speed) + Number(rotate_y);
	z_speed = Number(z_speed) + Number(rotate_z);
}

for (var i=1; i<=point_count; i++) {
		if (Key.isDown(32)){
			set("point" add i add ":name","point" add i);
		} else {
				set("point" add i add ":name","");
		}

		tsx = math.sin(Number(x_speed) * Number(r2d));
		tsy = math.sin(Number(y_speed) * Number(r2d));
		tsz = math.sin(Number(z_speed) * Number(r2d));
	
		tcx = math.cos(Number(x_speed) * Number(r2d));
		tcy = math.cos(Number(y_speed) * Number(r2d));
		tcz = math.cos(Number(z_speed) * Number(r2d));	

if (random_mode eq "true"){
	if (cont_rand eq "true"){
		for (var ii=1; ii<=Number(line_count); ii++) {
			if (getProperty("line" add ii, _alpha) > 20){
				setProperty ("line" add ii,_alpha,getProperty("line" add ii, _alpha) - 1);	
			}
		}
		da_speed = random_speed;
	} else {
		for (var ii=1; ii<=Number(line_count); ii++) {
			if (getProperty("line" add ii, _alpha) < 100){
				setProperty ("line" add ii,_alpha,getProperty("line" add ii, _alpha) + 1);
			}
		}
		da_speed = regroup_speed;
	}
	x[i] = x[i] - ((x[i] - x_goto[i])/da_speed);
	y[i] = y[i] - ((y[i] - y_goto[i])/da_speed);
	z[i] = z[i] - ((z[i] - z_goto[i])/da_speed);
	if (Math.abs(x[i] - x_goto[i]) < 2 && Math.abs(y[i] - y_goto[i]) < 2 && Math.abs(z[i] - z_goto[i]) < 2){
		if (cont_rand eq "true"){
			rand = sizecube*2;
			x_goto[i] = random(rand) - random(rand);
			y_goto[i] = random(rand) - random(rand);
			z_goto[i] = random(rand) - random(rand);
			if (x_goto[i] > sizecube){ x_goto[i] = sizecube;}
			if (y_goto[i] > sizecube){ y_goto[i] = sizecube;}
			if (z_goto[i] > sizecube){ z_goto[i] = sizecube;}
			if (x_goto[i] < -sizecube){ x_goto[i] = -sizecube;}
			if (y_goto[i] < -sizecube){ y_goto[i] = -sizecube;}
			if (z_goto[i] < -sizecube){ z_goto[i] = -sizecube;}
		} else { 
			x[i] = x_goto[i];
			y[i] = y_goto[i];
			z[i] = z_goto[i];
			
			random_wait++;

			if (random_wait eq point_count){
				
				random_wait = 0;
				random_mode  = "false";
			}
		}
	}
} else {
	for (var ii=1; ii<=Number(line_count); ii++) {
			if (getProperty("line" add ii, _alpha) < 100){
				setProperty ("line" add ii,_alpha,getProperty("line" add ii, _alpha) + 1);
			}
		}
}
	bx = x[i];
	by = y[i];
	bz = z[i];

	rx = tcy * bx + tsy * bz;
	rz = -tsy * bx + tcy * bz;
	ry = tcx * by - tsx * rz;
	
	rz = tsx * by + tcx * rz;
	rrx = tcz * rx - tsz * ry;
	rry = tsz * rx + tcz * ry;
	
	
	if (random_mode ne "true"){
		x[i] = rrx;
		y[i] = rry;
		z[i] = rz;
		x_goto[i] = rrx;
		y_goto[i] = rry;
		z_goto[i] = rz;
	}
	rx = rx * perspective;
	ry = ry * perspective;
	rz = rz + perspective;
	
	
	if (rz == 0) {
		rz = 1;
	}
	
	dx =  rx/rz + CX;
	dy = -ry/rz + CY;

	setProperty ("point" add i, _x, dx);
	setProperty ("point" add i, _y, dy);
}
}	
        


The engine was neither efficient or scalable mostly due to Flash's restrictions but I can say it was a large accomplishment at the time. Unfortunately, I never had anytime to play with it in further versions of Flash.




Gary Fong Puffer vs Lightscoop Reddit's Favorite 200 Books Flash Plugin Switcher Matt Shaw API