package net.zylum.bB3D { import flash.display.*; import flash.events.*; public class BB3D extends Sprite { private var polys:Array; public function BB3D () { stage.frameRate = 32; polys = new Array(); /* the 'z' */ addPoly(new Vector(-40, -40, 50), new Vector(40, -40, 50), new Vector(-5, 20, 50), new Vector(40, 40, 50), new Vector(-40, 40, 50), new Vector(5, -20, 50)); /* a cube with the front face removed */ addPoly(new Vector(-50, -50, -50), new Vector(-50, 50, -50), new Vector(50, 50, -50), new Vector(50, -50, -50)); //addPoly(new Vector(-50, -50, 50), new Vector(-50, 50, 50), new Vector(50, 50, 50), new Vector(50, -50, 50)); addPoly(new Vector(-50, -50, -50), new Vector(-50, -50, 50), new Vector(-50, 50, 50), new Vector(-50, 50, -50)); addPoly(new Vector(50, -50, -50), new Vector(50, -50, 50), new Vector(50, 50, 50), new Vector(50, 50, -50)); addPoly(new Vector(-50, -50, -50), new Vector(-50, -50, 50), new Vector(50, -50, 50), new Vector(50, -50, -50)); addPoly(new Vector(-50, 50, -50), new Vector(-50, 50, 50), new Vector(50, 50, 50), new Vector(50, 50, -50)); addEventListener(Event.ENTER_FRAME, animate); } private function animate(e:Event) { /* each frame, rotate and draw the object */ rotatePolys(new Vector(1, 1, 1), 0.02); drawPolys(); } /* add a polygon to the object */ public function addPoly(p1:Vector, p2:Vector, p3:Vector, ...pn) { polys.push(new Array(p1, p2, p3)); for each (var p in pn) polys[polys.length-1].push(p); } /* rotate all the polygons */ public function rotatePolys(axis:Vector, angle:Number) { var c:Number = Math.cos(angle); var s:Number = Math.sin(angle); /* make sure the axis of rotation is a unit vector */ axis.normalize(); /* compute the transformation matrix */ var xFormMatrix = new Array ( new Array( c + (1 - c)*axis.i*axis.i, (1 - c)*axis.i*axis.j - s*axis.k, (1 - c)*axis.i*axis.k + s*axis.j), new Array( (1 - c)*axis.i*axis.j + s*axis.k, c + (1 - c)*axis.j*axis.j, (1 - c)*axis.j*axis.k - s*axis.i), new Array( (1 - c)*axis.i*axis.k - s*axis.j, (1 - c)*axis.j*axis.k + s*axis.i, c + (1 - c)*axis.k*axis.k) ); /* rotate the vectors */ for each (var poly in polys) for each (var v in poly) v.rotate(xFormMatrix); } /* draw the polygons */ public function drawPolys() { /* sort them based on depth so that no overlapping issues occure */ polys.sort( function (p1, p2) { var d1:Number = 0; var d2:Number = 0; var p:Vector; for each (p in p1) d1 += p.k; for each (p in p2) d2 += p.k; return d1/p1.length < d2/p2.length ? -1 : 1; } ); graphics.clear(); graphics.lineStyle(); for each (var poly in polys) { /* find the centroid */ var centroid:Vector = new Vector(0, 0, 0); for each (var v in poly) centroid.add(v); centroid.scale(1/poly.length); /* find the vector from the light source to the centroid */ /* the light source in this case is at (0, 0, -1000) */ var light:Vector = new Vector(-centroid.i, -centroid.j, -1000-centroid.k); /* find the normal vector of the current polygon */ var norm:Vector = Vector.cross ( Vector.difference(poly[0], poly[1]), Vector.difference(poly[2], poly[1]) ); norm.normalize(); /* normalize */ light.normalize();/* the vectors */ /* compute the shade based on the angle between the normal vector and light vector */ var c:Number = (Math.abs(Vector.dot(norm, light))/2+1/3)*255; /* a hack to color the 'z' */ /* if the current polygon has 4 sides (ie a side of the cube) then apply the same */ /* shade to all the RGB components, otherwise only to the blue component */ graphics.beginFill(uint(c) | (poly.length==4?(uint(c) << 8) | (uint(c) << 16):0)); graphics.moveTo(poly[0].i + stage.stageWidth/2, poly[0].j + stage.stageHeight/2); for (var i = 1; i < poly.length; i++) graphics.lineTo(poly[i].i + stage.stageWidth/2, poly[i].j + stage.stageHeight/2); graphics.endFill(); } } } }