Actionscript:
-
[SWF(width = 500, height=500, backgroundColor = 0x333333)]
-
x = stage.stageWidth / 2;
-
y = stage.stageHeight / 2;
-
-
-
var polyNum:int = 3000;
-
// standard Vectors for using drawTriangles
-
var verts:Vector.<Number> = new Vector.<Number>();
-
var pVerts:Vector.<Number>;
-
var uvts:Vector.<Number> = new Vector.<Number>();
-
var indices:Vector.<int> = new Vector.<int>();
-
// needed for z-sorting
-
var sortedIndices:Vector.<int>;
-
var faces:Array = [];
-
-
// we'll use this for tranforming points
-
// and as the transormation matrix for our render
-
var m:Matrix3D = new Matrix3D();
-
-
// plot a poly
-
var poly:Vector.<Number>;
-
poly = Vector.<Number>([ 0, 0, 0,
-
10, 0, 0,
-
0,10, 0]);
-
-
// temp vect for any transformed polygons
-
var transPoly:Vector.<Number> = new Vector.<Number>();
-
-
var i:int;
-
var inc:int = 0;
-
for (i = 0; i<polyNum; i++){
-
m.identity();
-
var s:Number = (int(Math.random()*50) == 1) ? 4 + Math.random()*2 : 1 + Math.random() * 2;
-
m.appendScale(s, s, 1);
-
m.appendRotation(Math.random()*360, Vector3D.X_AXIS);
-
m.appendRotation(Math.random()*360, Vector3D.Y_AXIS);
-
m.appendRotation(Math.random()*360, Vector3D.Z_AXIS);
-
m.appendTranslation(200,0,0);
-
-
m.appendRotation(Math.random()*360, Vector3D.X_AXIS);
-
m.appendRotation(Math.random()*360, Vector3D.Y_AXIS);
-
m.appendRotation(Math.random()*360, Vector3D.Z_AXIS);
-
-
m.transformVectors(poly, transPoly);
-
-
verts = verts.concat(transPoly);
-
faces.push(new Vector3D());
-
indices.push(inc++, inc++, inc++);
-
uvts.push(Math.random(), Math.random(), 0, Math.random(), Math.random(), 0, Math.random(), Math.random(), 0);
-
}
-
-
sortedIndices = new Vector.<int>(indices.length, true);
-
-
// create texture
-
var tex:BitmapData = new BitmapData(400,400,false, 0x000000);
-
var grad:Shape = new Shape();
-
var mat:Matrix = new Matrix();
-
mat.createGradientBox(400,400,0,0,0);
-
with (grad.graphics){
-
beginGradientFill(GradientType.LINEAR, [0x000000, 0xAA0000, 0xFFFF00], [1, 1, 1], [20, 200, 255], mat);
-
drawRect(0,0,400,400);
-
}
-
tex.draw(grad);
-
-
// create background
-
mat.createGradientBox(1600,1000,0,-550, -100);
-
with (grad.graphics){
-
beginGradientFill(GradientType.RADIAL, [0x333333, 0xffffff], [1, 1], [0, 255], mat);
-
drawRect(0,0,500,500);
-
}
-
grad.x = -stage.stageWidth/2
-
grad.y = -stage.stageHeight/2;
-
addChild(grad);
-
-
// triangles will be drawn to this
-
var render:Shape = Shape(addChild(new Shape()));
-
-
// fix all vector lengths
-
verts.fixed = true, uvts.fixed = true, indices.fixed = true
-
pVerts = new Vector.<Number>(verts.length/3 * 2, true);
-
-
// we need these if we want perspective
-
var persp:PerspectiveProjection = new PerspectiveProjection();
-
persp.fieldOfView = 45;
-
// projection matrix
-
var proj:Matrix3D = persp.toMatrix3D();
-
-
var dx:Number = 0, dy:Number = 0;
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
dx += (mouseX - dx) / 4;
-
dy += (mouseY - dy) / 4;
-
m.identity();
-
m.appendRotation(dy, Vector3D.X_AXIS);
-
m.appendRotation(dx, Vector3D.Y_AXIS);
-
// push everything back so its not to close
-
m.appendTranslation(0,0,800);
-
// append the projection matrix at the end
-
m.append(proj);
-
-
Utils3D.projectVectors(m, verts, pVerts, uvts);
-
-
var face:Vector3D;
-
inc = 0;
-
for (var i:int = 0; i<indices.length; i+=3){
-
face = faces[inc];
-
face.x = indices[i];
-
// it may look odd, but casting to an int
-
// when doing operations inside array sytnax
-
// adds a big speed boost
-
face.y = indices[int(i + 1)];
-
face.z = indices[int(i + 2)];
-
var i3:int = i * 3;
-
// get the average z position (t value) and store it in the Vector3D w property
-
// depending on your model, you may not need to do an average of all 3 values
-
face.w = (uvts[int(i3 + 2)] + uvts[int(i3 + 5)] + uvts[int(i3 + 8)]) * 0.333333;
-
inc++;
-
}
-
-
// sort on w, so far this beats all other sorting methods for speed,
-
// faster than Vector.sort(), faster than any custom sort method I could find
-
faces.sortOn("w", Array.NUMERIC);
-
-
// re-order indices so that faces are drawn in the correct order (back to front);
-
inc = 0;
-
for each (face in faces){
-
sortedIndices[inc++] = face.x;
-
sortedIndices[inc++] = face.y;
-
sortedIndices[inc++] = face.z;
-
}
-
-
render.graphics.clear();
-
render.graphics.beginBitmapFill(tex, null, false, false);
-
render.graphics.drawTriangles(pVerts, sortedIndices, uvts, TriangleCulling.NONE);
-
}
This is a slightly more advanced version of the z-sorting demo from yesterday. Here 3000 polygons are randomly arranged in a sphere formation...
6 Comments
HOLY COW, you’ve done it again. Impressive looking.
Thanks Terry
it looks great, but the sphere on wonderfl is very small (I had to right-click/zoom 2x or 3x). Is there a scale problem?
ps: I’ve flash player 10.0.r12
Great blog anyway
not sure what would cause the sphere to be small, but if you just copy this code into your timeline or copy the code from wonderfl into flex you can see it full size…
If you see sphere small try upgrading flash player 10. Some versions are buggy with perspectiveProjection and matrix3D.
The results is really nice (like the others we can find on your blog) !
Thanks for sharing !
Just one little thing : I don’t understand why you use Array.sort instead of Vector.sort , this post ( http://webr3.org/experiments/flash-10/fast-z-sort/ ) show us that Vector.sort is pretty much faster than Array.sort