-
package {
-
-
import flash.display.StageQuality;
-
import org.papervision3d.core.geom.renderables.Vertex3D;
-
import org.papervision3d.lights.PointLight3D;
-
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
-
import org.papervision3d.materials.shadematerials.PhongMaterial;
-
import org.papervision3d.objects.DisplayObject3D;
-
import org.papervision3d.objects.primitives.Plane;
-
import org.papervision3d.objects.primitives.Sphere;
-
-
public class Main extends PaperBase {
-
-
public var light:PointLight3D = new PointLight3D(true);
-
public var physBox:DisplayObject3D = new DisplayObject3D(); //We'll keep all of the physical objects in here..
-
public var sidemat:FlatShadeMaterial = new FlatShadeMaterial(light, 0xBBBBBB, 0x000000);
-
public var floor:Plane = new Plane(sidemat, 1100, 1100, 10, 10);
-
-
public function Main() {
-
stage.quality = StageQuality.LOW; //Set the stage quality to low (for speed)
-
init();
-
}
-
-
override protected function init3d():void {
-
//Position the floor
-
floor.y = -100;
-
floor.pitch(90);
-
default_scene.addChild(floor);
-
-
//Position the camera
-
default_camera.y = 300;
-
default_camera.z = 1500;
-
default_camera.lookAt(floor);
-
-
//Position the light
-
light.x = 0;
-
light.y = 300;
-
light.z = 500;
-
-
//Create 10 Spheres, and put them in our Physics Box (Anything you add to physbox will be simulated, only spheres look right)
-
for (var x:Number = 0; x <10; x++) {
-
var sph:Sphere = new Sphere(new PhongMaterial(light, 0xBBBBBB, Math.round(Math.random() * 10000), 20), 100, 10, 8);
-
sph.x = (Math.random() * 40) - 20; // Position it slightly randomly
-
sph.z = (Math.random() * 40) - 20;
-
sph.y = (300 * x); // Put it 300 px above the previous one
-
sph.PreviousPosition = new Vertex3D(sph.x, sph.y, sph.z); // This stops the verlet from going crazy
-
physBox.addChild(sph); // Add it to the physbox
-
}
-
default_scene.addChild(physBox); // Add the physbox to the scene
-
}
-
-
override protected function processFrame():void {
-
-
default_camera.moveLeft(20); //This will rotate our camera around the scene,
-
default_camera.lookAt(floor);//whilst keeping it looking at the middle.
-
-
for (var item:String in physBox.children) { // This loop is run for every sphere in our physBox.
-
var citem:DisplayObject3D = physBox.getChildByName(item); // Get the sphere.
-
var lastposTmp:Vertex3D = getPos(citem); // Temporarily store it's position.
-
// This line of code is known as "Verlet". Wikipedia it for more info.
-
setPos(citem, vertexAdd(getPos(citem), vertexAdd(vertexSubtract(lastposTmp, citem.PreviousPosition), citem.Acceleration)));
-
citem.PreviousPosition = lastposTmp; // Update the previous position..
-
citem.Acceleration = new Vertex3D(0, -8.3, 0); // Apply Gravity
-
constrain(citem); // This code checks if the sphere has collided with the environment.
-
-
for (var item2:String in physBox.children) { //Check to see if it's hit any other spheres.
-
if (item != item2) {
-
var pitem:DisplayObject3D = physBox.getChildByName(item2);
-
dohittest(pitem, citem); // Check
-
}
-
}
-
}
-
}
-
-
private function dohittest(o1:DisplayObject3D, o2:DisplayObject3D):void {
-
if (o1.hitTestObject(o2)) { // IF the two objects have collided, then
-
var xmag:Number = (o1.x - o2.x)/2.1; // Get the distance
-
var ymag:Number = (o1.y - o2.y)/2.1;
-
var zmag:Number = (o1.z - o2.z)/2.1;
-
// Move the objects away from eachother
-
setPos(o1, vertexAdd(new Vertex3D(xmag, ymag, zmag), getPos(o1)));
-
setPos(o2, vertexSubtract(getPos(o2),new Vertex3D(xmag, ymag, zmag)));
-
}
-
}
-
-
private function constrain(obj:DisplayObject3D):void {
-
if (obj.x <500 && obj.x> -500 && obj.z <500 && obj.z> -500){ // If the object is over the floor
-
if (obj.y <0) { // If it's hit the floor
-
// Move it out of the floor.
-
if((obj.y - obj.PreviousPosition.y) <-10){
-
obj.y = (obj.PreviousPosition.y * 1.2);
-
if (obj.y <0) {
-
obj.y = 0;
-
}
-
}else {
-
obj.y = 0;
-
}
-
}
-
}
-
// If the object is way off the screen, put it back at the top.
-
if (obj.y <-10000) {
-
obj.y = 300 + (Math.random() * 5000);
-
obj.x = (Math.random() * 20) - 40;
-
obj.z = (Math.random() * 20) - 40;
-
obj.PreviousPosition = new Vertex3D(obj.x, obj.y, obj.z);
-
}
-
}
-
-
// --- These functions are used to do general addition and stuff ---
-
-
private function vertexSubtract(v1:Vertex3D, v2:Vertex3D):Vertex3D {
-
return new Vertex3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
-
}
-
-
private function vertexAdd(v1:Vertex3D, v2:Vertex3D):Vertex3D {
-
return new Vertex3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
-
}
-
-
private function getPos(object:DisplayObject3D):Vertex3D {
-
return new Vertex3D(object.x, object.y, object.z);
-
}
-
-
private function setPos(object:DisplayObject3D, point:Vertex3D):void {
-
object.x = point.x;
-
object.y = point.y;
-
object.z = point.z;
-
}
-
// --- ---
-
}
-
}