AS3: Papervision3D FreeCamera Movement

View Example
Get Papervision3D [Tutorial]
Get TweenMax
Download Source

One of the things that I was curious about when using Papervision3D was how the camera moves around and tracks other objects. Originally I set up a Camera3D object and moved it around to look at other objects but that wasn't playing well with the way I was tweening the camera around to look at certain objects. I switched over to the FreeCamera3D and this was the result.

Basically, I'm making 10 cubes on the stage and randomly positioning them along the x, y, and z axis. I then take a camera and zoom in to each cube sequentially so that the camera is facing it straight on by tweening the camera to the same position as the current cube minus 200 on the z axis so that we can look at the cube straight on (rather than being inside of it). Here is the code:

Actionscript:
  1. /**
  2. * @author Matt Przybylski [http://www.reintroducing.com]
  3. * @version 1.0
  4. */
  5.  
  6. package com.reintroducing
  7. {
  8.     import flash.display.Sprite;
  9.     import flash.events.Event;
  10.    
  11.     import org.papervision3d.cameras.FreeCamera3D;
  12.     import org.papervision3d.core.math.Number3D;
  13.     import org.papervision3d.core.proto.SceneObject3D;
  14.     import org.papervision3d.materials.ColorMaterial;
  15.     import org.papervision3d.materials.utils.MaterialsList;
  16.     import org.papervision3d.objects.primitives.Cube;
  17.     import org.papervision3d.render.BasicRenderEngine;
  18.     import org.papervision3d.scenes.Scene3D;
  19.     import org.papervision3d.view.Viewport3D;
  20.    
  21.     import gs.TweenMax
  22.  
  23.     public class CameraMovement extends Sprite
  24.     {
  25. //- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
  26.  
  27.         private var _viewport:Viewport3D;
  28.         private var _scene:Scene3D;
  29.         private var _camera:FreeCamera3D;
  30.         private var _renderer:BasicRenderEngine;
  31.         private var _cubePoints:Array;
  32.         private var _currentCube:Cube;
  33.        
  34.         private var _startPosition:int = 0;
  35.        
  36. //- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
  37.        
  38.        
  39.        
  40. //- CONSTRUCTOR -------------------------------------------------------------------------------------------
  41.    
  42.         public function CameraMovement():void
  43.         {
  44.             this.init();
  45.         }
  46.        
  47. //- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
  48.        
  49.         /**
  50.          *
  51.          */
  52.         private function init():void
  53.         {
  54.             this.initPapervision();
  55.             this.initObjects();
  56.             this.initListeners();
  57.         }
  58.        
  59.         /**
  60.          *
  61.          */
  62.         private function initPapervision():void
  63.         {
  64.             this._viewport = new Viewport3D(stage.stageWidth, stage.stageHeight, true, true);
  65.             this._scene = new Scene3D();
  66.             this._camera = new FreeCamera3D(11);
  67.             this._renderer = new BasicRenderEngine();
  68.            
  69.             this.addChild(this._viewport);
  70.         }
  71.        
  72.         /**
  73.          *
  74.          */
  75.         private function initObjects():void
  76.         {
  77.             this._cubePoints = new Array();
  78.            
  79.             var cube:Cube;
  80.             var pt:Number3D;
  81.             var x:Number;
  82.             var y:Number;
  83.             var z:Number;
  84.            
  85.             for (var i:int = 0; i <10; i++)
  86.             {
  87.                 x = CameraMovement.getRandomBetween(-400, 400);
  88.                 y = CameraMovement.getRandomBetween(-200, 200);
  89.                 z = CameraMovement.getRandomBetween(-200, 1000);
  90.                
  91.                 pt = new Number3D(x, y, z);
  92.                
  93.                 this._cubePoints.push(pt);
  94.                
  95.                 cube = this.makeColoredCube(i, x, y, z);
  96.             }
  97.            
  98.             this.moveCamera();
  99.         }
  100.        
  101.         /**
  102.          *
  103.          */
  104.         private function initListeners():void
  105.         {
  106.             this.addEventListener(Event.ENTER_FRAME, render);
  107.         }
  108.        
  109.         /**
  110.          *
  111.          */
  112.         private static function getRandomBetween($low:Number, $high:Number):Number
  113.         {
  114.             return Math.floor(Math.random() * ($high - $low + 1)) + $low;
  115.         }
  116.        
  117.         /**
  118.          *
  119.          */
  120.         private function makeColoredCube($id:int, $x:Number, $y:Number, $z:Number):Cube
  121.         {
  122.             var colors:Array = new Array();
  123.            
  124.             for (var i:int = 0; i <6; i++)
  125.             {
  126.                 colors.push(new ColorMaterial(Math.random() * 0xFFFFFF));
  127.             }
  128.            
  129.             var matList:MaterialsList = new MaterialsList({front: colors[0], back: colors[1], left: colors[2], right: colors[3], top: colors[4], bottom: colors[5]});
  130.             var cube:Cube = new Cube(matList, 25, 25, 25);
  131.             cube.x = $x;
  132.             cube.y = $y;
  133.             cube.z = $z;
  134.             cube.name = String("cube" + $id);
  135.            
  136.             this._scene.addChild(cube);
  137.            
  138.             return cube;
  139.         }
  140.        
  141.         /**
  142.          *
  143.          */
  144.         private function moveCamera():void
  145.         {
  146.             this._currentCube = Cube(this._scene.getChildByName("cube" + this._startPosition));
  147.             //TODO: highlight the current cube somehow
  148.            
  149.             var points:Number3D = new Number3D(this._cubePoints[this._startPosition].x, this._cubePoints[this._startPosition].y, (this._cubePoints[this._startPosition].z - 200));
  150.            
  151.             TweenMax.to(this._camera, 1, {x: points.x, y: points.y, z: points.z});
  152.             TweenMax.delayedCall(3, moveCamera, [], this);
  153.            
  154.             this._startPosition++;
  155.             this._startPosition %= 10;
  156.         }
  157.  
  158. //- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
  159.    
  160.        
  161.    
  162. //- EVENT HANDLERS ----------------------------------------------------------------------------------------
  163.    
  164.         /**
  165.          *
  166.          */
  167.         private function render($evt:Event):void
  168.         {
  169.             this._renderer.renderScene(this._scene, this._camera, this._viewport);
  170.         }
  171.    
  172. //- GETTERS & SETTERS -------------------------------------------------------------------------------------
  173.    
  174.        
  175.    
  176. //- HELPERS -----------------------------------------------------------------------------------------------
  177.    
  178.         override public function toString():String
  179.         {
  180.             return "com.reintroducing.CameraMovement";
  181.         }
  182.    
  183. //- END CLASS ---------------------------------------------------------------------------------------------
  184.     }
  185. }

As you can see by the TODO on line 147 I was meaning to add a bit more to this but just got sidetracked by client work and wanted to release this.

If you found this post useful, please consider leaving a comment, subscribing to the feed, or making a small donation.

9 Comments

thats pretty cool, I have something a little like yours here

That's pretty sweet, Dominic. I like the computeSpectrum addition to it! I've added your blog to my RSS reader, look forward to future posts.

thx alot, i'm trying to add you to my blogroll, whenever i work out how jemingway works...

[...] 19, 2008 in AS 3, Flash, TutorialesTags: cámara, pv3d Muy padre tutorial con código y ligas a los recursos necesarios para manejar una cámara en nuestro espacio [...]

Thanks so much for your tut! It really helps noobs like me! Keeo up the great work and I can't wait to see the next one.

Since the original time of this post PaperVision has updated a couple files and TweenMax has changed a little bit too. (I just updated both today.)

I had to make the following changes to get the above example to work.

1) Change all references of FreeCamera3D to Camera3D. The latest PaperVision (GreatWhite branch) has merged the Camera files and added a CameraType.as.

2) I changed line #153 from - TweenMax.delayedCall(3, moveCamera, [], this); - to - TweenMax.delayedCall(3, moveCamera);

And pow, it works perfect!

Thanks again!

Hey Trygve,
Thanks for the update! Yeah the source is probably a bit outdated by now. As for the TweenMax change, i'm not sure that you'd have to edit that because all that is is a passing of blank parameters and the scope of the method to run. But as long as it works for you thats good to know.

Hi Matt,

I was surprised to see your quick response. Most people post and then never return to the thread again!

I was receiving a TweenMax error stating that "no more than 3 parameters were expected". Since your third parm was an empty array I removed it too, but I agree that parameter was fine to leave.

To find the fix, I checked the TweenMax documention:
TweenMax.delayedCall(delay:Number, onComplete:Function, onCompleteParams:Array);

I've subscribed to your feed and look forward to seeing more of your work. Thanks.

Trygve,
You're absolutely right, I totally forgot we are talking about AS3 here and not AS2 where you need to define the scope of the function. My apologies 😛

@Trygve : thanks, i made those two edits as well and it worked perfectly.. you have any other tips on extending this?

Leave a comment

(required)

(required)