8. Keyboard Interaction (To move the camera)


In this tutorial I'm going to cover keyboard interaction.

(use W,A,S and D)

The very first thing we need to do before we start is to go right back and edit the base class. We're going to make it accept more than one camera, then we can dynamically select the camera, scene and viewport to use.

Open up PaperBase.as (Double click on it in the project tree, under PaperBase). Insert the following lines just below the line "public var default_camera:Camera3D;":

Actionscript:
  1. public var current_scene:Scene3D;
  2. public var current_camera:CameraObject3D;
  3. public var current_viewport:Viewport3D;

These three variables will store the camera, scene and viewport to use in the render. We need to make the default camera, scene and viewport be stored in these variables when we initiate our project, so in the initPapervision function, right at the end, add the following lines:

Actionscript:
  1. current_camera = default_camera;
  2. current_scene = default_scene;
  3. current_viewport = viewport;

The final little edit that we need to make is to render from the current objects.

Change the line "renderer.renderScene(default_scene, default_camera, viewport);" to:

Actionscript:
  1. renderer.renderScene(current_scene, current_camera, current_viewport);

Done. You can download the NEW version of the base class by clicking here!

Now that we've got the base class edited, we can start editing Main.as.

Copy and paste this code into Main.as, make sure you have the papervision library, and the PaperBase class imported in your project's classpaths.

Actionscript:
  1. package {
  2.  
  3.     import PaperBase;
  4.     import flash.events.KeyboardEvent;
  5.     import org.papervision3d.cameras.FreeCamera3D;
  6.     import org.papervision3d.objects.primitives.Plane;
  7.     import org.papervision3d.materials.BitmapFileMaterial;
  8.     
  9.     public class Main extends PaperBase {
  10.       
  11.        public var wdown:Boolean = false;
  12.        public var adown:Boolean = false;
  13.        public var sdown:Boolean = false;
  14.        public var ddown:Boolean = false;
  15.        public var camera:FreeCamera3D;
  16.       
  17.        public function Main() {
  18.          init();
  19.        }
  20.       
  21.        override protected function init3d():void {
  22.          // Initiate 3d
  23.        }
  24.        override protected function processFrame():void {
  25.          // Process Frame Here
  26.        }
  27.     }
  28. }

I've put in all the imports that you'll need for the project. Let's set up the event listeners which will listen for when we press or release a key. Change the code in the Main() function so it looks like this:

Actionscript:
  1. public function Main() {
  2.     init();
  3.     stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
  4.     stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
  5. }

This sets up the two event listeners. Now the functions "onKeyDown" then "onKeyUp" will be triggered when you press a key down, then release it.

If you look at the code, you'll notice that I've declared four boolean values, Wdown, Adown, Sdown and Ddown.

Actionscript:
  1. public var Wdown:Boolean = false;
  2. public var Adown:Boolean = false;
  3. public var Sdown:Boolean = false;
  4. public var Ddown:Boolean = false;

I like to use the W A S and D keys for movement, so each of these boolean values will hold whether W,A,S or D is down.

We'll now set up our onKey functions, which will set the above variables to the correct value. Add this code to your project:

Actionscript:
  1. public function onKeyDown( event:KeyboardEvent ):void {
  2.     // The keycodes for the W,A,S & D keys are:
  3.     // W: 87
  4.     // A: 65
  5.     // S: 83
  6.     // D: 68
  7.     // -------
  8.     switch(event.keyCode) {
  9.        case 87:
  10.          wdown = true;
  11.        break;
  12.        case 65:
  13.          adown = true;
  14.        break;
  15.        case 83:
  16.          sdown = true;
  17.        break;
  18.        case 68:
  19.          ddown = true;
  20.        break;
  21.     }
  22. }
  23.  
  24. public function onKeyUp( event:KeyboardEvent ):void {
  25.        switch(event.keyCode) {
  26.        case 87:
  27.          wdown = false;
  28.        break;
  29.        case 65:
  30.          adown = false;
  31.        break;
  32.        case 83:
  33.          sdown = false;
  34.        break;
  35.        case 68:
  36.          ddown = false;
  37.        break;
  38.     }
  39. }

Pretty simple stuff - Just sets the needed variable to true.

Now we've set that all up, we need to set up our scene. Add the following function to your code:

Actionscript:
  1. override protected function init3d():void {
  2.     camera = new FreeCamera3D(1, 500);
  3.     camera.moveUp(400);
  4.     current_camera = camera;
  5.     for (var x:Number = 0; x <4; x++) {
  6.        for (var y:Number = 0; y <4; y++) {
  7.          var p:Plane = new Plane(new BitmapFileMaterial("http://papervision2.com/wp-content/downloads/concretetex.jpg"), 1000, 1000, 8, 8);
  8.          p.pitch(90);
  9.          p.x = (x * 1000)-2000;
  10.          p.z = (y * 1000)-2000;
  11.          default_scene.addChild(p);
  12.        }
  13.     }
  14. }

Notice that we initiate our "camera" variable here. We then set the current_camera to the camera that we just made. After the line "current_camera = camera", the baseclass will render the scene looking through "camera" instead of "default_camera". The rest of the code in this function just adds a big flat area to the scene which will be our "floor"

Now we can use the boolean variables to move our camera in the processframe function. Add this code to your project:

Actionscript:
  1. override protected function processFrame():void {
  2.     if (wdown) {
  3.        camera.moveForward(60);
  4.     }
  5.     if (sdown) {
  6.        camera.moveBackward(60);
  7.     }
  8.     if (adown) {
  9.        camera.yaw( -8);
  10.     }
  11.     if (ddown) {
  12.        camera.yaw( 8);
  13.     }
  14. }

This just moves the camera forward or back, or rotates it left/right, depending on which key has been pressed.

Your project is now ready to be run. Here is my final code:

Actionscript:
  1. package {
  2.  
  3.     import PaperBase;
  4.     import flash.events.KeyboardEvent;
  5.     import org.papervision3d.cameras.FreeCamera3D;
  6.     import org.papervision3d.objects.primitives.Plane;
  7.     import org.papervision3d.materials.BitmapFileMaterial;
  8.     
  9.     public class Main extends PaperBase {
  10.       
  11.        public var wdown:Boolean = false;
  12.        public var adown:Boolean = false;
  13.        public var sdown:Boolean = false;
  14.        public var ddown:Boolean = false;
  15.        public var camera:FreeCamera3D;
  16.       
  17.        public function Main() {
  18.          init();
  19.          stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
  20.          stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
  21.        }
  22.       
  23.        public function onKeyDown( event:KeyboardEvent ):void {
  24.          // The keycodes for the W,A,S &amp; D keys are:
  25.          // W: 87
  26.          // A: 65
  27.          // S: 83
  28.          // D: 68
  29.          // -------
  30.          switch(event.keyCode) {
  31.               case 87:
  32.                   wdown = true;
  33.               break;
  34.               case 65:
  35.                   adown = true;
  36.               break;
  37.               case 83:
  38.                   sdown = true;
  39.               break;
  40.               case 68:
  41.                   ddown = true;
  42.               break;
  43.          }
  44.        }
  45.       
  46.        public function onKeyUp( event:KeyboardEvent ):void {
  47.               switch(event.keyCode) {
  48.               case 87:
  49.                   wdown = false;
  50.               break;
  51.               case 65:
  52.                   adown = false;
  53.               break;
  54.               case 83:
  55.                   sdown = false;
  56.               break;
  57.               case 68:
  58.                   ddown = false;
  59.               break;
  60.          }
  61.        }
  62.       
  63.        override protected function init3d():void {
  64.          camera = new FreeCamera3D(1, 500);
  65.          camera.moveUp(400);
  66.          current_camera = camera;
  67.          for (var x:Number = 0; x <4; x++) {
  68.               for (var y:Number = 0; y <4; y++) {
  69.                   var p:Plane = new Plane(new BitmapFileMaterial("http://papervision2.com/wp-content/downloads/concretetex.jpg"), 1000, 1000, 8, 8);
  70.                   p.pitch(90);
  71.                   p.x = (x * 1000)-2000;
  72.                   p.z = (y * 1000)-2000;
  73.                   default_scene.addChild(p);
  74.               }
  75.          }
  76.        }
  77.        override protected function processFrame():void {
  78.          if (wdown) {
  79.               camera.moveForward(60);
  80.          }
  81.          if (sdown) {
  82.               camera.moveBackward(60);
  83.          }
  84.          if (adown) {
  85.               camera.yaw( -8);
  86.          }
  87.          if (ddown) {
  88.               camera.yaw( 8);
  89.          }
  90.        }
  91.     }
  92. }



7. Basic Mouse Interaction


In this tutorial, I'll simply show you how to do some basic movement in the scene by using the mouse.

This is the result:

Ugly, but simple. It's so simple that I'm just going to post the source code.. If you've been following my last tutorials, and you read the comments around the three lines of code in "ProcessFrame" then you should understand it.

Actionscript:
  1. package {
  2.     
  3.     import PaperBase;
  4.     import org.papervision3d.objects.DisplayObject3D;
  5.     import org.papervision3d.objects.parsers.Collada;
  6.     
  7.     public class Main extends PaperBase {
  8.       
  9.        public var cow:DisplayObject3D;
  10.        public var distance:Number = 1000; //Distance the camera should be from the model
  11.       
  12.        public function Main() {
  13.          init();
  14.        }
  15.       
  16.        override protected function init3d():void {
  17.          cow = new Collada("http://papervision2.com/wp-content/downloads/dae/cow.dae");
  18.          cow.moveDown(100);
  19.          cow.scale = 3;
  20.          default_scene.addChild(cow);
  21.        }
  22.        override protected function processFrame():void {
  23.          // The next line is a bit of a mouthful, but it's quite simple really.
  24.          // It just gets the Y position of your mouse, and sets the camera.y to a
  25.          // value between -800 and 800, depending on the Y position of your mouse
  26.          // (If mouseY = 0 then camera.y = 800. If mouseY = stage.height, camera.y = -800)
  27.          default_camera.y = -(((mouseY - (stage.height / 2)) / stage.height) * 1600);
  28.          
  29.          // We don't want the camera to move further away from the model, so we do this:
  30.          default_camera.moveForward(default_camera.distanceTo(cow) - distance);
  31.          
  32.          // We now want to rotate the object depending on
  33.          // the Xmouse position. This is really simple.
  34.          cow.rotationY = -((mouseX / stage.width) * 360) //Rotation
  35.          
  36.          // NOTE: This will only work if you only have one object in your scene.
  37.          // I'll write a more advanced movement tutorial soon :)
  38.        }
  39.     }
  40. }



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;