Browsing the archives for the 3D category.

Actionscript 3 (as3) - Real-time voxel landscape

3D, BitmapData, Math, actionscript 3, fun, perlinNoise

What can be the natural evolution of an isometric engine? Of course a voxel engine…

It was really a lot of time I had this in mind and already did some experiment, but never finalized them.
What I’ll show you now is some first implementation. Source code is already optimized but I need to finish class public methods so I’ll not post source for now.

Let me say that these screenshot really suck, but you got to see them moving (they runs very fast).

This first sample is a bitmap based map. The class wants two bitmap, one for the height map and one for the color. Of course you can use the same twice (but obviously it looks good only with grayscale images). With my brand new Intel Quad core QX9550 I easilly reach the fps limitator of 51 (ok, ok… on the screenshot is written 29 but believe me! :-D ). I am new to multi core cpu and I am really surprised to see that now the browser vs IDE situation totally changed. Now I can do 51 fps in the browser (Opera 9.23) and 30 in the IDE… mmm strange behaviour, maybe I just need some sleep.

The file is very big cause of the low compressed 2000×2000 jpeg files. No preloader (don’t even try to ask for it) so be patient please (631 Kb) ;-)




Actionscript voxel landscape (Image map)

(move mouse to fly around.Map is bitmap based so has boundaries)

This second one is to make you write some comment like: “hey man how can you be so stupid… trying to code a fast voxel engine lots of optimization etc. and then you came up with a perlin noise based sample which simply drain half of the power”… Yeah! but is cool to have infinite landscape and test my new CPU :-D




Actionscript voxel landscape (perlinNoise)

Same but with two octaves… very blobby feeling.




Actionscript voxel landscape (weird 2 octaves perlinNoise)

Expect more about this and more new things. I am preparing a lot of funny stuff.

As usual if you like this let me now via comments and if you want to keep an eye on updates subscribe to my feed

12 Comments

Actionscript 3 - Fun with 3D Particles

3D, Math, Particles, actionscript 3, morphing

Hi there, some time since I last posted a technical post so here we are.

Brief

I was experimenting with some simple 3d formulas and this is the result…
1200 particles morphing in 3D space.
Added an interactive camera to start having fun.

Usage

Simply move your mouse up/down to move camera forward/backward and left/right for strafing.
Perss SPACE bar to cycle particle conformation between four different shapes.

For better experience move forward and backward while particles are morphing…
Following the morph from behind while moving very fast feel very gratifing for me :)

Performances

On my old CPU it performs @31fps and neither takes the cpu at 100%
No z-sorting here, just fun. I am not trying to build a real 3d engine… and no class for now, just some procedural code, but I am sure my cool readers will not have problems wrapping it inside a class definition if needed ;)

Caurina Tweener needed.

3dparticles.gif
Experience the demo

And here come the code! Simply past it in the first frame actions of a new fla.

import caurina.transitions.Tweener;
import com.oaxoa.components.FrameRater;
import flash.events.KeyboardEvent;
 
var particles:Array=[];
var particlesXY:Array=[];
var flen:Number=100;
var lines:Sprite=new Sprite();
var renderLines:Boolean=false;
var shapeN:int=-1;
 
var camera:Object={px:0, py:0, pz:0};
 
function drawBg():void {
	var bg:Sprite=new Sprite();
	bg.graphics.beginFill(0x333333);
	bg.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
	bg.graphics.endFill();
	addChild(bg);
	var tf:TextFormat=new TextFormat();
	tf.color= 0x999999;
	tf.font="_sans";
	tf.size=11;
	tf.align="right";
	var t:TextField=new TextField();
	t.width=300;
	t.defaultTextFormat=tf;
	t.text="Press SPACEBAR to change particles shape";
	t.x=stage.stageWidth-t.width-10;
	t.selectable=false;
	bg.addChild(t);
}
 
function addParticle(x:Number, y:Number, z:Number):void {
	var p:MovieClip=new MovieClip();
	p.graphics.beginFill(0xcccccc);
	p.graphics.drawCircle(0, 0, 5);
	p.graphics.endFill();
	p.px=x;
	p.py=y;
	p.pz=z;
	particles.push(p);
}
 
function cycleShape():void {
	if (shapeN<3) {
		shapeN++;
	} else {
		shapeN=0;
	}
	var i:uint;
	var p:MovieClip;
	var px:Number;
	var py:Number;
	var pz:Number;
	var arad:Number;
	if (shapeN==0) {
		var a:Number=0;
		for (i=0; i<particles.length; i++) {
			a+=9;
			a%=360;
			p=particles[i];
			arad=a/180*Math.PI;
			px=Math.cos(arad)*100;
			py=Math.sin(arad)*100;
			pz=Math.floor(i/40)*60;
			Tweener.addTween(p, {time:2, transition:"EaseInOutCubic", px:px, py:py, pz:pz, delay:i/300});
		}
	} else if (shapeN==1) {
		for (i=0; i<particles.length; i++) {
			p=particles[i];
			arad=i/180*Math.PI;
			arad*=2;
			px=Math.sin(arad)*100;
			py=Math.cos(arad)*100;
			pz=i;
			Tweener.addTween(p, {time:2, transition:"EaseInOutElastic", px:px, py:py, pz:pz, delay:i/300});
		}
	} else if (shapeN==2) {
		for (i=0; i<particles.length; i++) {
			p=particles[i];
			px=Math.random()*700-350;
			py=Math.random()*700-350;
			pz=Math.random()*1700;
			Tweener.addTween(p, {time:2, transition:"EaseInOutCubic", px:px, py:py, pz:pz, delay:i/200});
		}
	} else if (shapeN==3) {
		var row:uint=0;
		var col:uint=0;
		for (i=0; i<particles.length; i++) {
			col=(i%50);
			row=Math.floor(i/50);
			p=particles[i];
			px=0
			py=-450+row*40;
			pz=col*40;
			Tweener.addTween(p, {time:2, transition:"EaseInOutBounce", px:px, py:py, pz:pz, delay:i/200});
		}
	}
}
 
 
function render():void {
 
	var c:uint=0;
	for each (var p:MovieClip in particles) {
		var dx:Number=p.px-camera.px;
		var dy:Number=p.py-camera.py;
		var dz:Number=p.pz-camera.pz;
		var scale:Number=flen/(flen+(dz));
		if (scale<0) {
			scale=0;
		}
		p.x=stage.stageWidth/2+dx*scale;
		p.y=stage.stageHeight/2+dy*scale;
		p.scaleX=p.scaleY=scale;
		particlesXY[c]={x:p.x, y:p.y, scale:scale};
		c++;
	}
	// activate lines render, false by default, not really a wireframe
	if (renderLines) {
		lines.graphics.clear();
		lines.graphics.lineStyle(2, 0xCCCCCC);
		for(var i:uint=0; i<particlesXY.length; i++) {;
			var t:Object=particlesXY[i];
			if (i<particlesXY.length-1 && t.scale>0) {
				var t2:Object=particlesXY[i+1];
 
				lines.graphics.moveTo(t.x, t.y);
				lines.graphics.lineTo(t2.x, t2.y);
			}
		}
	}
}
 
stage.addEventListener(KeyboardEvent.KEY_UP, onkey);
function onkey(event:KeyboardEvent):void {
	if(event.keyCode==32) {
		cycleShape();
		render();
	}
}
addEventListener(Event.ENTER_FRAME, onframe);
 
function onframe(event:Event):void {
	var offx:Number=stage.stageWidth/2-mouseX;
 
	camera.px-=offx/5;
	if (camera.px>150) {
		camera.px=150;
	}
	if (camera.px<-150) {
		camera.px=-150;
	}
	var offy:Number=stage.stageHeight/2-mouseY;
	if(offy>70) offy=70;
	if(offy<-70) offy=-70;
 
	camera.pz+=offy/5;
	if (camera.pz>1700) {
		camera.pz=1700;
	}
	if (camera.pz<0) {
		camera.pz=0;
	}
	render();
}
 
function addSprites():void {
	for each (var p:MovieClip in particles) {
		addChildAt(p, 1);
	}
}
 
function init():void {
	for(var i:uint=0; i<1200; i++) {
		var px:Number=0;
		var py:Number=0;
		var pz:Number=0;
		addParticle(px, py ,pz);
	}
}
 
// main methods call
drawBg();
addChild(lines);
init();
addSprites();
cycleShape();
render();
var fr:FrameRater=new FrameRater(0xffffff);
addChild(fr);

Have fun and leave a comment if you like.

7 Comments