Actionscript:
-
var verts:Vector.<Number> = new Vector.<Number>();
-
var pVerts:Vector.<Number> = new Vector.<Number>();
-
var uvts:Vector.<Number> = new Vector.<Number>();
-
-
var hs:Number = 2.3;
-
var step:Number = 0.04;
-
-
var tVerts:Vector.<Number> = new Vector.<Number>();
-
var rVerts:Vector.<Number> = new Vector.<Number>();
-
var matrix:Matrix3D = new Matrix3D();
-
matrix.identity();
-
matrix.appendRotation(45,Vector3D.Y_AXIS);
-
matrix.appendRotation(45,Vector3D.X_AXIS);
-
var inc:int = 0;
-
var i:Number, j:Number, k:Number;
-
i = hs;
-
while( i> -hs){
-
j = hs;
-
while(j> -hs){
-
k = hs;
-
while(k> -hs){
-
tVerts[inc] = -i;
-
inc++
-
tVerts[inc] = -j;
-
inc++
-
tVerts[inc] = -k;
-
inc++
-
k -= step;
-
}
-
j -= step;
-
}
-
i -= step;
-
}
-
-
matrix.transformVectors(tVerts, rVerts);
-
-
var vinc:int = 0;
-
inc = 0
-
var R:Number = 1.5;
-
var r:Number = .5;
-
for (i= -hs; i<hs; i+=step){
-
for (j = -hs; j<hs; j+=step){
-
for (k = -hs; k<hs; k+=step){
-
var vx:Number = rVerts[inc] ;
-
inc++
-
var vy:Number = rVerts[inc] ;
-
inc++
-
var vz:Number= rVerts[inc] ;
-
inc++
-
var s:Number = Math.pow(vx * vx + vy * vy + vz * vz + R*R - r * r, 2) - 4 * (R * R)*(vx * vx + vy * vy);
-
if (s <0 && s> -.5){
-
verts[vinc] = (i * 50);
-
vinc++
-
verts[vinc] = (j * 50);
-
vinc++
-
verts[vinc] = (k * 50);
-
vinc++
-
inc += int((hs - k) / step) * 3;
-
k = hs;
-
}
-
}
-
}
-
}
-
-
var canvas:BitmapData = new BitmapData(400,400,false, 0x000000);
-
addChild(new Bitmap(canvas));
-
render();
-
function render():void{
-
matrix.identity();
-
matrix.appendTranslation(200, 200, 0);
-
Utils3D.projectVectors(matrix, verts, pVerts, uvts);
-
canvas.lock();
-
canvas.fillRect(canvas.rect, 0x000000);
-
var inc:int = 2;
-
var c:int = 0;
-
var r:Rectangle = new Rectangle();
-
r.width = r.height = 2;
-
for (var i:int = 0; i<pVerts.length; i+=2){
-
r.x = pVerts[i];
-
r.y = pVerts[i + 1];
-
c = Math.max(0,100 - verts[inc]);
-
canvas.fillRect(r, c <<16 | c <<8 | c);
-
inc += 3;
-
}
-
canvas.unlock();
-
}
This snippet uses some of the techniques from the last few posts to create a distance render - this renders the implicit equation for a torus.
Actionscript:
-
var tVerts:Vector.<Number> = new Vector.<Number>();
-
var inc:int = 0;
-
var t:Number, i:Number, j:Number, k:Number;
-
-
// fast way
-
t = getTimer();
-
for (i= -2; i<2; i+=.03){
-
for (j = -2; j<2; j+=.03){
-
for (k = -2; k<2; k+=.03){
-
tVerts[inc] = i;
-
inc++;
-
tVerts[inc] = j;
-
inc++;
-
tVerts[inc]= k;
-
inc++;
-
}
-
}
-
}
-
trace(getTimer() - t);
-
-
tVerts = new Vector.<Number>();
-
-
// slow way
-
t = getTimer();
-
for (i= -2; i<2; i+=.03){
-
for (j = -2; j<2; j+=.03){
-
for (k = -2; k<2; k+=.03){
-
-
tVerts.push(i, j, k);
-
// tVerts.push(j);
-
// tVerts.push(k);
-
}
-
}
-
}
-
trace(getTimer() - t);
Today I needed to populate a Vector in the above manner... populating the vector using push() was quite slow in this case because (among other reasons) push() is a method call. I was curious how much faster populating the Vector without push would be... so I wrote this snippet - in this case it was significantly faster - took less than a third of the time. You can run this snippet to see what kind of results you get.
It's important to note that this nested for loop could be optimized further but I wanted to focus on the push() optimization alone.
Warning
The most HORRIBLE thing about testing the speed of ActionScript code is that you CANNOT rely on the debug player to test optimizations. Always use the release version of the flash player. The debug player will give unusual (usually slower) results...
Actionscript:
-
var matrix:Matrix3D = new Matrix3D();
-
var verts:Vector.<Number> = new Vector.<Number>();
-
var pVerts:Vector.<Number> = new Vector.<Number>();
-
var uvts:Vector.<Number> = new Vector.<Number>();
-
var sqrt2:Number = Math.sqrt(2)
-
var pi:Number = Math.PI;
-
var pi23:Number= 2 * Math.PI / 3;
-
var step:Number= pi / 50;
-
for (var u:Number = -pi; u<pi; u+=step) {
-
for (var v:Number = -pi; v<pi; v+=step) {
-
// from here http://local.wasp.uwa.edu.au/~pbourke/geometry/hexatorus/
-
var px = Math.sin(u) / Math.abs(sqrt2+ Math.cos(v))
-
var py = Math.sin(u+pi23) / Math.abs(sqrt2 +Math.cos(v + pi23))
-
var pz = Math.cos(u-pi23) / Math.abs(sqrt2 +Math.cos(v - pi23))
-
verts.push(px * 50);
-
verts.push(py * 50);
-
verts.push(pz * 50);
-
}
-
}
-
var brush:BitmapData=new BitmapData(3,2,true,0x41FFFFFF);
-
var canvas:BitmapData=new BitmapData(400,400,false,0x000000);
-
addChild(new Bitmap(canvas));
-
var dx:Number=0;
-
var dy:Number=0;
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
dx += (mouseX - dx)/4;
-
dy += (mouseY - dy)/4;
-
matrix.identity();
-
matrix.appendRotation(dy,Vector3D.X_AXIS);
-
matrix.appendRotation(dx,Vector3D.Y_AXIS);
-
matrix.appendTranslation(200, 200, 0);
-
Utils3D.projectVectors(matrix, verts, pVerts, uvts);
-
canvas.lock();
-
canvas.fillRect(canvas.rect, 0x000000);
-
var p = new Point();
-
for (var i:int = 0; i<pVerts.length; i+=2) {
-
p.x = pVerts[i];
-
p.y = pVerts[i+1];
-
canvas.copyPixels(brush, brush.rect, p, null, null, true);
-
}
-
canvas.unlock();
-
}
More 3D shapes inspired by (taken from) Paul Bourke's website. I figured I should probably add a parametric 3D surface to this set of posts - so I chose to plot the Triaxial Hexatorus. It's important to note that U and V go from -PI to PI.
I googled Triaxial Hexatorus and stumbled upon a great papervision demo that creates meshes using parametric equations - it also morphs between shapes.
I also noticed that I don't need to populate the uvts or pVerts Vectors with zeros - seems to work fine without doing that.
Actionscript:
-
var matrix:Matrix3D = new Matrix3D();
-
var verts:Vector.<Number> = new Vector.<Number>();
-
var pVerts:Vector.<Number> = new Vector.<Number>();
-
var uvts:Vector.<Number> = new Vector.<Number>();
-
for (var i:Number = -10; i<10; i+=.04) {
-
for (var j:Number = -5; j<8; j+=.04) {
-
for (var k:Number = -10; k<10; k+=.04) {
-
var s:Number = i * i * j + j * k * k;
-
if (s <10 && s> 9.95) {
-
verts.push(i * 20);
-
verts.push(j * 20);
-
verts.push(k * 20);
-
pVerts.push(0),pVerts.push(0);
-
uvts.push(0),uvts.push(0),uvts.push(0);
-
}
-
}
-
}
-
}
-
var brush:BitmapData=new BitmapData(3,2,true,0x41FFFFFF);
-
var canvas:BitmapData=new BitmapData(400,400,false,0x000000);
-
addChild(new Bitmap(canvas));
-
var dx:Number=0;
-
var dy:Number=0;
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
dx += (mouseX - dx)/4;
-
dy += (mouseY - dy)/4;
-
matrix.identity();
-
matrix.appendRotation(dy,Vector3D.X_AXIS);
-
matrix.appendRotation(dx,Vector3D.Y_AXIS);
-
matrix.appendTranslation(200, 200, 0);
-
Utils3D.projectVectors(matrix, verts, pVerts, uvts);
-
canvas.lock();
-
canvas.fillRect(canvas.rect, 0x000000);
-
var p = new Point();
-
for (var i:int = 0; i<pVerts.length; i+=2) {
-
p.x = pVerts[i];
-
p.y = pVerts[i+1];
-
canvas.copyPixels(brush, brush.rect, p, null, null, true);
-
}
-
canvas.unlock();
-
}
Yet another variation on the post from the last two days. This one plots something resembling a wormhole - I was randomly tweaking the equation for a sphere and stumbled upon this...