Actionscript:
-
[SWF(width=600,height=500,frameRate=30)]
-
var canvas:BitmapData=new BitmapData(600,500,false,0x000000);
-
addChild(new Bitmap(canvas));
-
var size:Number=canvas.width*canvas.height;
-
var w:Number=canvas.width;
-
var wd:Number=1/w;
-
var pix:Vector.<uint> = new Vector.<uint>();
-
var sin:Number;
-
var cos:Number;
-
var dx:Number=110;
-
var dy:Number=52;
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
dx+=0.001;
-
canvas.lock();
-
for (var i:int = 0; i<size; i++) {
-
var xp:Number=i%w;
-
var yp:Number=int(i*wd);
-
var xx:Number=xp*0.05+dx;
-
var yy:Number=yp*0.05+dy;
-
var t:Number= (xx * yy) % 3.14159265;
-
//compute sine
-
// technique from http://lab.polygonal.de/2007/07/18/fast-and-accurate-sinecosine-approximation/
-
// by Michael Baczynski
-
if (t<0) {
-
sin=1.27323954*t+.405284735*t*t;
-
} else {
-
sin=1.27323954*t-0.405284735*t*t;
-
}
-
//compute cosine: sin(t + PI/2) = cos(t)
-
t+=1.57079632;
-
if (t>3.14159265) {
-
t-=6.28318531;
-
}
-
if (t<0) {
-
cos=1.27323954*t+0.405284735*t*t;
-
} else {
-
cos=1.27323954*t-0.405284735*t*t;
-
}
-
var c:Number=sin+cos*cos*cos;
-
// fast math abs
-
c=c<0? -c:c;
-
c=c*140;
-
// math max 255
-
c=c>255?255:c;
-
pix[i]=c<<16|c<<8|c;
-
}
-
canvas.setVector(canvas.rect, pix);
-
canvas.unlock();
-
}
The above snippet will animate a gradient that looks like this:
Recently saw some great links making use of Global Illumination/Ambient Occlusion... these ones are from wonderfl posted by keim at Si :
This first example is based on something called AO bench.
one
two
three
and there is something called MiniLight which has been ported to Flex.
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 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.