Physics in Papervision


Hi Everyone!

Today I've been experimenting with Verlet physics, and using Papervision to render the results. Here's what I've come up with:

It's a little bit buggy, but pretty good for a quick papervision project!

I had to modify the DisplayObject3D class a bit, It's a tiny modification which just allows you to store an acceleration and "previous position" in any object. I added the variables because it was the easiest and quickest way to store this information.. And my physics formula needs them.

If you want to play with it, you'll have to download my modified DisplayObject3D class by clicking here

Just replace your current file (located in Greatwhite/src/org/papervision3d/objects) with my one. It won't affect the performance or anything on projects which also use this class (I've only added two or three lines).

Here is the code (Uses the base class and modified DisplayObject3D):

Actionscript:
  1. package  {
  2.     
  3.     import flash.display.StageQuality;
  4.     import org.papervision3d.core.geom.renderables.Vertex3D;
  5.     import org.papervision3d.lights.PointLight3D;
  6.     import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
  7.     import org.papervision3d.materials.shadematerials.PhongMaterial;
  8.     import org.papervision3d.objects.DisplayObject3D;
  9.     import org.papervision3d.objects.primitives.Plane;
  10.     import org.papervision3d.objects.primitives.Sphere;
  11.  
  12.     public class Main extends PaperBase {
  13.       
  14.        public var light:PointLight3D = new PointLight3D(true);
  15.        public var physBox:DisplayObject3D = new DisplayObject3D(); //We'll keep all of the physical objects in here..
  16.        public var sidemat:FlatShadeMaterial = new FlatShadeMaterial(light, 0xBBBBBB, 0x000000);
  17.        public var floor:Plane = new Plane(sidemat, 1100, 1100, 10, 10);
  18.       
  19.        public function Main() {
  20.          stage.quality = StageQuality.LOW; //Set the stage quality to low (for speed)
  21.          init();
  22.        }
  23.       
  24.        override protected function init3d():void {
  25.          //Position the floor
  26.          floor.y = -100;
  27.          floor.pitch(90);
  28.          default_scene.addChild(floor);
  29.          
  30.          //Position the camera
  31.          default_camera.y = 300;
  32.          default_camera.z = 1500;
  33.          default_camera.lookAt(floor);
  34.          
  35.          //Position the light
  36.          light.x = 0;
  37.          light.y = 300;
  38.          light.z = 500;
  39.          
  40.          //Create 10 Spheres, and put them in our Physics Box (Anything you add to physbox will be simulated, only spheres look right)
  41.          for (var x:Number = 0; x <10; x++) {
  42.               var sph:Sphere = new Sphere(new PhongMaterial(light, 0xBBBBBB, Math.round(Math.random() * 10000), 20), 100, 10, 8);
  43.               sph.x = (Math.random() * 40) - 20; // Position it slightly randomly
  44.               sph.z = (Math.random() * 40) - 20;
  45.               sph.y = (300 * x); // Put it 300 px above the previous one
  46.               sph.PreviousPosition = new Vertex3D(sph.x, sph.y, sph.z); // This stops the verlet from going crazy
  47.               physBox.addChild(sph); // Add it to the physbox
  48.          }
  49.          default_scene.addChild(physBox); // Add the physbox to the scene
  50.        }
  51.       
  52.        override protected function processFrame():void {
  53.       
  54.          default_camera.moveLeft(20); //This will rotate our camera around the scene,
  55.          default_camera.lookAt(floor);//whilst keeping it looking at the middle.
  56.          
  57.          for (var item:String in physBox.children) { // This loop is run for every sphere in our physBox.
  58.               var citem:DisplayObject3D = physBox.getChildByName(item); // Get the sphere.
  59.               var lastposTmp:Vertex3D = getPos(citem); // Temporarily store it's position.
  60.               // This line of code is known as "Verlet". Wikipedia it for more info.
  61.               setPos(citem, vertexAdd(getPos(citem), vertexAdd(vertexSubtract(lastposTmp, citem.PreviousPosition), citem.Acceleration)));
  62.               citem.PreviousPosition = lastposTmp; // Update the previous position..
  63.               citem.Acceleration = new Vertex3D(0, -8.3, 0); // Apply Gravity
  64.               constrain(citem); // This code checks if the sphere has collided with the environment.
  65.              
  66.               for (var item2:String in physBox.children) { //Check to see if it's hit any other spheres.
  67.                   if (item != item2) {
  68.                      var pitem:DisplayObject3D = physBox.getChildByName(item2);
  69.                      dohittest(pitem, citem); // Check
  70.                   }
  71.               }
  72.          }
  73.        }
  74.       
  75.        private function dohittest(o1:DisplayObject3D, o2:DisplayObject3D):void {
  76.          if (o1.hitTestObject(o2)) { // IF the two objects have collided, then
  77.               var xmag:Number = (o1.x - o2.x)/2.1; // Get the distance
  78.               var ymag:Number = (o1.y - o2.y)/2.1;
  79.               var zmag:Number = (o1.z - o2.z)/2.1;
  80.               // Move the objects away from eachother
  81.               setPos(o1, vertexAdd(new Vertex3D(xmag, ymag, zmag), getPos(o1)));
  82.               setPos(o2, vertexSubtract(getPos(o2),new Vertex3D(xmag, ymag, zmag)));
  83.          }
  84.        }
  85.       
  86.        private function constrain(obj:DisplayObject3D):void {
  87.          if (obj.x <500 &amp;&amp; obj.x> -500 &amp;&amp; obj.z <500 &amp;&amp; obj.z> -500){ // If the object is over the floor
  88.               if (obj.y <0) { // If it's hit the floor
  89.                   // Move it out of the floor.
  90.                   if((obj.y - obj.PreviousPosition.y) <-10){
  91.                      obj.y = (obj.PreviousPosition.y * 1.2);
  92.                      if (obj.y <0) {
  93.                        obj.y = 0;
  94.                      }
  95.                   }else {
  96.                      obj.y = 0;
  97.                   }
  98.               }
  99.          }
  100.          // If the object is way off the screen, put it back at the top.
  101.          if (obj.y <-10000) {
  102.               obj.y = 300 + (Math.random() * 5000);
  103.               obj.x = (Math.random() * 20) - 40;
  104.               obj.z = (Math.random() * 20) - 40;
  105.               obj.PreviousPosition = new Vertex3D(obj.x, obj.y, obj.z);
  106.          }
  107.        }
  108.       
  109.        // --- These functions are used to do general addition and stuff ---
  110.       
  111.        private function vertexSubtract(v1:Vertex3D, v2:Vertex3D):Vertex3D {
  112.          return new Vertex3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  113.        }
  114.       
  115.        private function vertexAdd(v1:Vertex3D, v2:Vertex3D):Vertex3D {
  116.          return new Vertex3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  117.        }
  118.       
  119.        private function getPos(object:DisplayObject3D):Vertex3D {
  120.          return new Vertex3D(object.x, object.y, object.z);
  121.        }
  122.       
  123.        private function setPos(object:DisplayObject3D, point:Vertex3D):void {
  124.          object.x = point.x;
  125.          object.y = point.y;
  126.          object.z = point.z;
  127.        }
  128.        // --- ---
  129.     }  
  130. }

I hope it's commented enough :D

Have fun!

11 Comments

  1. Comment by Joakim on February 22, 2008 12:50 pm

    If you have the time, could you do some demo using WOW. The engine looks very interesting, but the documentation available is very scarce. I need some besic demos to get the hang of it.

    Would be very much appreciated.

  2. Comment by cslamsg on February 25, 2008 3:31 pm

    Hi,

    Coming across the demo is indeed very interesting. Great !

    I am now currently working around quaternion physics. Cheers.

  3. Comment by Luke on February 26, 2008 11:38 am

    Hi Joakim,

    If I get the time I will, I still haven't looked into WOW yet though, and thanks for the comment cslamsg, would be cool to see what you come up with :)!

    -Luke

  4. Comment by Manuel on March 18, 2008 7:42 pm

    Thanks for the great example!
    Found something similar using papervision and the wow physics engine here: http://lab.tojio.com/projects/wowpv3dhelloworld/

  5. Comment by George Profenza on June 12, 2008 11:21 am

    Hi,

    Thanks for the example. I've downloaded your modified version of DisplayObject3D and it doesn't work. Apparently it doesn't have the clone method and related properties. Any reason why these might be left out ?

  6. Comment by George Profenza on June 12, 2008 11:48 am

    Why not just create a DisplayObject3DPhys for example, that extends DisplayObject3D ?

  7. Comment by Amanita on June 17, 2008 10:32 am

    What kind of Papervision3D version do you have???

  8. Comment by Amanita on June 25, 2008 8:23 am

    Sorry, but GreatWhite doesn`t work. Phong shader materials classes is wrong ((

  9. Comment by wizim on June 29, 2008 12:12 pm

    WoW where is your PaperBase Class? give me pleasssssse.

  10. Comment by wizim on June 29, 2008 12:15 pm

    oh i see it.Thx

  11. Comment by Maceo on July 15, 2008 2:58 pm

    It doesn't work... there seems a problem with the override function in the vertex3d class. i think something is wrong with your new "DisplayObject3D"!!! can u check this????

Comments RSS TrackBack Identifier URI

Leave a comment


Papervision 2 is proudly powered by WordPress and themed by Mukka-mu