/**
* Copyright mutantleg ( http://wonderfl.net/user/mutantleg )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/sAWD
*/
package {
import flash.geom.Vector3D;
import flash.geom.Matrix3D;
import flash.display.Graphics;
import flash.events.Event;
import flash.display.Sprite;
public class FlashTest extends Sprite {
public function FlashTest() {
var a:xVert;
vecVert = new Vector.<xVert>(0, false);
vecBuff = initVert(1024);
//generate some random shape
var i:int;
for (i = 0; i < 8; i++)
{
vecVert.push( new xVert(Math.random()*32-16, Math.random()*32-16, Math.random()*32-16, Math.random()*6+6, (Math.random()*0xFF)<<16) );
}//nexti
for (i = 0; i < 64; i++)
{
vecVert.push( new xVert(Math.random()*128-64, Math.random()*128-64, Math.random()*128-64, Math.random()*4+3, (Math.random()*0xFF)<<8) );
}//nexti
for (i = 0; i < 128; i++)
{
vecVert.push( new xVert(Math.random()*256-128, Math.random()*256-128, Math.random()*256-128, Math.random()*2+1, (Math.random()*0xFF)) );
}//nexti
stage.addEventListener(Event.ENTER_FRAME, onEnter);
}//ctor
public var gameTime:int = 0;
public function onEnter(e:Event):void
{
var it:int;
graphics.clear();
//it = projectVert(vecVert, vecIdent, 0, vecBuff);
tempMat.identity();
tempMat.appendRotation(gameTime, Vector3D.Y_AXIS, null);
tempMat.appendRotation(gameTime, Vector3D.X_AXIS, null);
vecIdent = tempMat.rawData;
it = projectVert(vecVert, vecIdent, 0, vecBuff);
sortVert(vecBuff, it); //sort back to front
renderVert(graphics, vecBuff, it, 225,225);
gameTime += 1;
}//onenter
public var tempMat:Matrix3D = new Matrix3D();
public var vecBuff:Vector.<xVert>;
public var vecVert:Vector.<xVert> = new Vector.<xVert>(0, false);
public static var vecIdent:Vector.<Number> = Vector.<Number>([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1]);
//create a vert buffer
public function initVert(num:int):Vector.<xVert>
{
var ret:Vector.<xVert>; var i:int;
ret = new Vector.<xVert>(num, false);
for (i = 0; i < num; i++) { ret[i] = new xVert(); }
return ret;
}//initvert
//g -- graphics to render to
//vec -- buffer of verts
//num -- number of verts to render (less or equal to vec.length)
//ax ay -- center of screen
public function renderVert(g:Graphics, vec:Vector.<xVert>, num:int, ax:Number=320,ay:Number=240):void
{
var a:xVert; var i:int;
num = vec.length;
g.lineStyle(2, 0);
for (i = 0; i < num; i++)
{
a = vec[i];
g.beginFill(a.col, 1);
g.drawCircle(a.sx + ax, a.sy + ay, a.sr);
g.endFill();
}//nexti
}//rendervert
//vec -- verts to project
//mat -- projection matrix (combined with view matrix)
//st -- iterator for tv
//tv buffer of projected verts
public function projectVert(vec:Vector.<xVert>, mat:Vector.<Number>, st:int, tv:Vector.<xVert> ):int
{
var a:xVert; var b:xVert;
var i:int;
var num:int; var tnum:int;
var w:Number;
var sz:Number;
num = vec.length;
tnum = tv.length;
for (i = 0; i < num; i++)
{
a = vec[i];
w = a.cx * mat[3] + a.cy * mat[7] + a.cz * mat[11] + mat[15];
if (w <= 0) { continue; }
//trace("w ",w,w*16384);
// trace("z ", a.cz, a.cz+8192);
b = tv[st];
b.sx = a.cx * mat[0] + a.cy * mat[4] + a.cz * mat[8] + mat[12];
b.sy = a.cx * mat[1] + a.cy * mat[5] + a.cz * mat[9] + mat[13];
b.sx /= w; b.sy /= w;
sz = a.cx * mat[2] + a.cy * mat[6] + a.cz * mat[10] + mat[14];
//there is still some cheating as its only ortho rendering
b.sr = a.rad; //todo -- calculate projected radius (for ortho it doesnt matter)
b.col = a.col;
b.sortCode = 65536 - ( sz + 8192); //cheating -- sort by z coordinate (no camera pos yet)
st += 1; if (st >= tnum) { return st; }
}//nexti
return st;
}//project
public function sortVert(vec:Vector.<xVert>, num:int):void
{
radixSortVert(vec, num);
}//sortvert
public var tempVec:Vector.<xVert> = new Vector.<xVert>(8192, false);
public var tempBuck:Vector.<int> = new Vector.<int>(256, false);
public function radixSortVert(vec:Vector.<xVert>, num:int):void
{
var a:xVert; var temp:Vector.<xVert>; var buck:Vector.<int>;
var i:int; var k:uint; var shift:int; var g:int;
if (vec.length < num) { num = vec.length; }
temp = tempVec; if (temp.length < num) { return; }
buck = tempBuck; shift = 0;
while (shift < 32) {
for (k = 0; k < 256; k++) { buck[k] = 0; } //reset bucket
for (i = 0; i < num; i++) { g = (vec[i].sortCode >> shift) &0xFF; buck[g]++; }
for (i = 1; i < 256; i++) { buck[i] += buck[i - 1]; }
for (i = num - 1; i >= 0; i--) { g = (vec[i].sortCode >> shift) &0xFF; temp[--buck[g] ] = vec[i]; }
for (i = 0; i < num; i++) { vec[i] = temp[i]; }
shift += 8;
}//wend
}//radixsort
}//classend
}
internal class xVert
{
public function xVert(ax:Number = 0, ay:Number = 0, az:Number = 0, ar:Number = 4, c:uint = 0)
{
cx = ax; cy = ay; cz = az; rad = ar; col = c;
}//ctor
public var cx:Number = 0;
public var cy:Number = 0;
public var cz:Number = 0;
public var rad:Number = 8;
public var col:uint = 0;
public var sx:Number = 0;
public var sy:Number = 0;
public var sr:Number = 0;
public var sortCode:int = 0;
}//xvert