Real Orbiting 3D Particles (Taking Out the Trash)

Intro

As opposed to using billboarding, this program illustrates real 3D orbiting particles. The particles shown below are recycled after a randomly generated lifetime and the size of each particle is proportional to its mass. Each time a particle is generated it is given a new randomly generated lifetime, position (within an emitter window) and velocity. And the Euler gravitational equations are immediately applied as each particle enters onto the stage. Click on the image below to see a demonstration.

Orbiting 3D Particles

Orbiting 3D Particles

Demo: http://www.professionalpapervision.com/demos/web/real3dparticles/

Download: http://code.google.com/p/flex3cookbook2/downloads/list

Discussion

When handling particle creation and annihilation you’ve got to remove extinguished particles or they will weigh down your computer memory and slow your CPU performance. When working with the Flash player the best way to do this is through recycling. That way you don’t have to worry about extinguishing particles.

But if you don’t or can’t recycle, you should know the following about how the Flash player handles its trash.

Handling Your Particle Trash (You better know this)

Once a particle is extinguished it will hang around in your computer’s memory and need to be removed. The removal process is often referred to as trash collection. And this occurs when the Flash player removes unused objects. There are three things that you must do in order for an object to be eligible for trash collection.

· It must be removed from all arrays

· It must be removed from the stage and all display objects

· It can’t have reference to it such as event listeners and any event listeners that are attaché to it must be removed.

Unfortunately once you do all these things it doesn’t mean your trash is going to be collected. You have only made it available for trash collection. In typical Papervision applications you do not have control over trash collection.

The way trash collection works is that as memory usage get to a certain point Flash performs a mark and sweep operation. The Flash player scans your application looking for elements eligible for trash collection and then sweeps them away. So performing the three tasks above doesn’t mean that the item will be immediately removed from your computer’s memory. Trash collection is sporadic with no guarantees as to when it is going to happen. But it will eventually happen so make sure you keep your unused particles ready to go out with the rest of the garbage. Below are a few code snippets to help your out.

1. Use the shift command to remove a particle from the particles array

myParticle = particles.shift();

2. Use the removeChild command to remove a particle from the stage

stageContainer.removeChild(myParticle);

3. Use null to make sure that all references are removed from your particle

myParticle = null;

Use the commands above to make your unused particles available for trash collection. If you don’t want to worry about collecting your unused particles reinitialize as shown in the earlier code example. But Papervsion is like a big particle system and you’ll eventually need to use the code above. Especially when throttling your 3D objects with a timer. More on that later.

The creation of particles systems are treated in detail in the book, but please download the code and play around with it. Also, to see the code click the more button below;

Note: For this to work I had to put some physics into the DisplayObject3D class. I have packaged that with the download.

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; layout=”absolute” creationComplete=”init()” backgroundGradientAlphas=”[1.0, 1.0]” backgroundGradientColors=”[#C9D2DE, #112C51]“>
<mx:Script>
<![CDATA[

//Flash imports
import flash.display.Sprite;
import flash.events.Event;
import flash.display.StageQuality;
import flash.display.StageScaleMode;

import org.papervision3d.cameras.Camera3D;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;

import flash.display.StageQuality;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.lights.PointLight3D;

import org.papervision3d.materials.*;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.view.stats.*;

private var numParticles:uint = 8;
private var myLifeLived:Number=400;
private var particleArray:Array = new Array();
private var myColor:ColorTransform = new ColorTransform();
private var colorWireframeMaterial: ColorWireframeMaterial;

//Define your class

//Define your properties
private var viewport:Viewport3D;
private var camera:Camera3D;
private var scene:Scene3D;
private var renderer:BasicRenderEngine;
private var myNumber:Number=0;

//Additions for gravity
private var minMass:Number=2;
private var maxMass:Number=20;

private var gravitationalConstant:Number=1;

private function init():void{
//Define your sphere variable.

//Intiate Papervision
initPV3D();

//Create Renderer
createRenderer();

}
//Define your methods

//Initialize Papervision
private function initPV3D():void
{

// Create the viewport
viewport = new Viewport3D(0, 0, true, false);
pv3Canvas.rawChildren.addChild(viewport);

// Create the camera
camera = new Camera3D();

// Create the scene
scene = new Scene3D();

// Create the renderer
renderer = new BasicRenderEngine();

//Position the camera

camera.y = 300;

camera.z = 1500;

//WireframeMaterial, doubleSided draws the color on both sides of the geometry normals
colorWireframeMaterial = new ColorWireframeMaterial(0x00ff00,.6,0x0000ff,1,.1,true, true);
colorWireframeMaterial.doubleSided = true;
colorWireframeMaterial.interactive = true;

}

//Loop Renderer
private function createRenderer():void{
addEventListener(Event.ENTER_FRAME, myLoop);
}

private function myLoop(event:Event):void
{ renderer.renderScene(scene, camera, viewport);

if(particleArray.length < numParticles){

var radiusVar:Number=Math.random()*(maxMass-minMass)+minMass;

var myPart:Sphere = new Sphere(colorWireframeMaterial, 3*radiusVar, 8, 6);

scene.addChild(myPart);
particleArray.push(myPart);

myPart.x = (Math.random() * 240) - 120; // Position it slightly randomly
myPart.z = (Math.random() * 240) - 120;
myPart.y = (Math.random() * 240) - 120;

myPart.velocityX = Math.random() * 10 - 5;
myPart.velocityY = Math.random() * 10 - 5;
myPart.velocityZ = Math.random() * 10 - 5;

myPart.accelerationX = Math.random() * 10 - 5;
myPart.accelerationY = Math.random() * 10 - 5;
myPart.accelerationZ = Math.random() * 10 - 5;

myPart.scaleX=myPart.scaleY=myPart.scaleZ=1;
myPart.gravity=0;
myPart.friction=1;

myPart.particleLife= Math.random()*myLifeLived;

//Initiate Mass
myPart.mass=radiusVar;

}
for(var i:uint = 0; i < particleArray.length; i++)
{
var myParticle:Sphere = particleArray[i];
myNumber++;
if(myNumber > particleArray.length*4){

for(var j:int=i+1;j<numParticles;j++){
var ddx:Number =(particleArray[j].x-particleArray[i].x);
var ddy:Number =(particleArray[j].y-particleArray[i].y);
var ddz:Number =(particleArray[j].z-particleArray[i].z);
var d:Number =(Math.pow(ddx,2)+Math.pow(ddy,2)+Math.pow(ddz,2));
var mainF:Number=(gravitationalConstant*particleArray[j].mass*particleArray[i].mass)/d;
var xc:Number = mainF*ddx;
var yc:Number = mainF*ddy;
var zc:Number = mainF*ddz;
particleArray[i].accelerationX+=xc;
particleArray[i].accelerationY+=yc;
particleArray[i].accelerationZ+=zc;
particleArray[j].accelerationX+=-xc;
particleArray[j].accelerationY+=-yc;
particleArray[j].accelerationZ+=-zc;

}
particleArray[i].accelerationX=particleArray[i].accelerationX/particleArray[i].mass;
particleArray[i].accelerationY=particleArray[i].accelerationY/particleArray[i].mass;
particleArray[i].accelerationZ=particleArray[i].accelerationZ/particleArray[i].mass;

particleArray[i].updateAll();

if(myParticle.particleLife > 400)
{
myParticle.velocityX = Math.random() * 10 – 5;
myParticle.velocityY = Math.random() * 10 – 5;
myParticle.velocityZ = Math.random() * 10 – 5;
myParticle.accelerationX = Math.random() * 10 – 5;
myParticle.accelerationY = Math.random() * 10 – 5;
myParticle.accelerationZ = Math.random() * 10 – 5;
myParticle.x = (Math.random() * 240) – 120; // Position it slightly randomly
myParticle.z = (Math.random() * 240) – 120;
myParticle.y = (Math.random() * 240) – 120; // Put it 300 px above the previous one
myParticle.scaleX=myParticle.scaleY=myParticle.scaleZ=1;
myParticle.alpha=1;
myParticle.friction=1;
myParticle.particleLife=Math.random()*myLifeLived;
myParticle.gravity=0;

}}
}

/* for(var k:int=0;k<=numParticles;k++){

particleArray[k].updateAll();
} */

}

]]>
</mx:Script>
<mx:Canvas x=”0″ y=”0″ width=”694″ height=”460″ id=”pv3Canvas” borderColor=”#FFFFFF”>
</mx:Canvas>
</mx:Application>

About these ads

2 Responses to Real Orbiting 3D Particles (Taking Out the Trash)

  1. [...] I had any doubt as to where the physics should go, working with light totally solidified it for me. Physics goes into the DisplayObject3D class! And [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: