package org.codemonkey.papervision3d { import flash.utils.Dictionary; import org.papervision3d.cameras.Camera3D; import org.papervision3d.core.math.Number3D; import org.papervision3d.materials.special.ParticleMaterial; import org.papervision3d.objects.special.ParticleField; import org.papervision3d.scenes.Scene3D; /** * Spacedust simulator. Creates 8 segments of the dustcloud around the given camera at any point in space. * When the camera moves, new dustpockets are generated and old ones (out of sight) are removed. * * @author Benny Bottema */ public class Spacedust { private static const DEFAULT_PARTICLEMATERIAL:ParticleMaterial = new ParticleMaterial(0xffffff, .5, ParticleMaterial.SHAPE_CIRCLE); private var basic3DSetup:Basic3DSetup; private var camera:Camera3D; private var spacedustCloud:Dictionary; private var fieldsize:Number; private var particleCount:Number; private var dustMaterial:ParticleMaterial = new ParticleMaterial(0xffffff, .5, ParticleMaterial.SHAPE_CIRCLE); public function Spacedust(basic3DSetup:Basic3DSetup, camera:Camera3D = null, fieldsize:Number = 2500, particleCount:Number = 400, dustMaterial:ParticleMaterial = null) { spacedustCloud = new Dictionary(); this.basic3DSetup = basic3DSetup; this.camera = (camera != null) ? camera : basic3DSetup.camera; this.fieldsize = fieldsize; this.particleCount = particleCount; this.dustMaterial = (dustMaterial != null) ? dustMaterial : DEFAULT_PARTICLEMATERIAL; } public function update():void { // calculate segment (dustpocket) size const FIELDSIZE_POCKET:Number = fieldsize / 5; // determine the 8 gridpositions around the ship (eg. 1: front bottom left, 2: behind top right) const pocketPositions:Array = new Array(); pocketPositions.push(calcGridPosition(camera.position, FIELDSIZE_POCKET, false, false, false)); pocketPositions.push(calcGridPosition(camera.position, FIELDSIZE_POCKET, true, false, false)); pocketPositions.push(calcGridPosition(camera.position, FIELDSIZE_POCKET, false, true, false)); pocketPositions.push(calcGridPosition(camera.position, FIELDSIZE_POCKET, false, false, true)); pocketPositions.push(calcGridPosition(camera.position, FIELDSIZE_POCKET, true, true, false)); pocketPositions.push(calcGridPosition(camera.position, FIELDSIZE_POCKET, true, false, true)); pocketPositions.push(calcGridPosition(camera.position, FIELDSIZE_POCKET, false, true, true)); pocketPositions.push(calcGridPosition(camera.position, FIELDSIZE_POCKET, true, true, true)); const newSpacedustCloud:Dictionary = new Dictionary(); // create new dustfields or transfer existing ones (and remove existing ones the scene) const particlesPerPocket:Number = particleCount / pocketPositions.length; for each (var pocketPosition:Number3D in pocketPositions) { const pocketKey:String = pocketPosition.toString(); const reusableDustPocket:ParticleField = spacedustCloud[pocketKey]; // remove so we can delete the particles from the remaining particlefields (which means they are out of sight) delete spacedustCloud[pocketKey]; // add the removed particlefield to the new dustcloud or create one if dustpocket is new for te current gridposition around the ship if (reusableDustPocket != null) { basic3DSetup.scene.removeChild(reusableDustPocket); newSpacedustCloud[pocketKey] = reusableDustPocket; } else { newSpacedustCloud[pocketKey] = new ParticleField(dustMaterial, particlesPerPocket, 2, fieldsize, fieldsize, fieldsize); newSpacedustCloud[pocketKey].x = pocketPosition.x; newSpacedustCloud[pocketKey].y = pocketPosition.y; newSpacedustCloud[pocketKey].z = pocketPosition.z; } } // manually remove all the remaining obsolete particles from the old cloud (they are out of sight) for each (var oldDustPocket:ParticleField in spacedustCloud) { oldDustPocket.removeAllParticles(); } // now add the old dustpockets which are still within sight, plus the new dustpockets to the scene for each (var newDustPocket:ParticleField in newSpacedustCloud) { basic3DSetup.scene.addChild(newDustPocket); } // replace the old cloud with the new cloud spacedustCloud = newSpacedustCloud; } /** * Calculates a gridpoint around the ship. */ private function calcGridPosition(position:Number3D, gridSize:Number, xMin:Boolean, yMin:Boolean, zMin:Boolean):Number3D { const gridPosition:Number3D = new Number3D(); gridPosition.x = (position.x - (position.x % gridSize)) + ((xMin) ? 0 : gridSize); gridPosition.y = (position.y - (position.y % gridSize)) + ((yMin) ? 0 : gridSize); gridPosition.z = (position.z - (position.z % gridSize)) + ((zMin) ? 0 : gridSize); return gridPosition; } } }