Erain 3D
-->

Author: Max Pellizzaro
Date: October 27th 2007
version: 3.0

Using the Camera

Objective of the tutorial

In this tutorial, we will study the use of the object Camera3D object. In the previous tutorial, we have just used the camera as a view point of the entire scene, but we actually never used it, neither had we gone through its properties or methods.

A Camera3D is just more than a static object – we can move it around, rotate, roll, tilt, and much more.

Knowing that you can move the Camera is very important because sometimes you will face a simple dilemma: should I move my object around or should I move my camera around?

Well, this is my personal advice: if you need to move only one object around, leaving the others in their original positions, move the single object. But if you want to move all the objects around, consider moving only the camera, and nothing else. You will soon discover that it will be easier and more efficient.

For example, if you implement a 3D maze, you can just draw the walls of the maze, and move the camera around to explore the maze.
But let's stop talking and dig into our example. I have decided to move away from the cube and start using other primitives: Line3D and a Torus.

How to

Set up

Remember these few little changes:
The Document class must be changed to Example003.as The name of the class written inside the .as file and the name of the constructor now is: Example003

example003.rar

The AS Code

Use the code below for reference. Do not worry if it is not commented – it is being discussed below.

package {
   import flash.display.Sprite; 
   import flash.events.*;
   import flash.ui.*;
   import sandy.core.Scene3D;
   import sandy.core.data.*;
   import sandy.core.scenegraph.*;
   import sandy.materials.*;
   import sandy.materials.attributes.*;
   import sandy.primitive.*;
 
   public class Example003 extends Sprite {
      private var scene:Scene3D;
      private var camera:Camera3D;
 
      public function Example003() { 
         camera = new Camera3D( 300, 300 );
         //camera.x = 100;
         //camera.y = 100;
         camera.z = -400;
         //camera.lookAt(0,0,0);
 
         var root:Group = createScene();
 
         scene = new Scene3D( "scene", this, camera, root );
 
         addEventListener( Event.ENTER_FRAME, enterFrameHandler );
         stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
 
      }
 
      private function createScene():Group {
         var g:Group = new Group();
 
         var myXLine:Line3D = new Line3D( "x-coord", new Vector(-50, 0, 0), new Vector( 50, 0, 0 ));
         var myYLine:Line3D = new Line3D( "y-coord", new Vector(0, -50, 0), new Vector( 0, 50, 0 ));
         var myZLine:Line3D = new Line3D( "z-coord", new Vector(0, 0, -50), new Vector( 0, 0, 50 ));
 
         var torus:Torus = new Torus( "theTorus", 120, 20);
 
         var materialAttr:MaterialAttributes = new MaterialAttributes( 
                        new LineAttributes( 0.5, 0x2111BB, 0.4 ),
                        new LightAttributes( true, 0.1)
                  );
 
         var material:Material = new ColorMaterial( 0xFFCC33, 1, materialAttr );
         material.lightingEnable = true;
         var app:Appearance = new Appearance( material );
 
         torus.appearance = app;
 
         torus.rotateX = 30;
         torus.rotateY = 30;
 
         g.addChild(myXLine);
         g.addChild(myYLine);
         g.addChild(myZLine);
         g.addChild(torus);
 
         return g;
      }
 
      private function enterFrameHandler( event : Event ) : void {
         scene.render();
      }
 
      private function keyPressed(event:KeyboardEvent):void {
         switch(event.keyCode) {
            case Keyboard.UP:
               camera.tilt +=2;
               break;
            case Keyboard.DOWN:
               camera.tilt -=2;
               break;
            case Keyboard.RIGHT:
               camera.pan -=2;
               break;
            case Keyboard.LEFT:
               camera.pan +=2;
               break;
            case Keyboard.CONTROL:
               camera.roll +=2;
               break;	
            case Keyboard.PAGE_DOWN:
               camera.z -=5;
               break;
            case Keyboard.PAGE_UP:
               camera.z +=5;
               break;	
         }
      }
   }
}

Examining the code

Now, let’s see what we have changed from the previous tutorial.

Importing the packages

First, we have added some extra import statements in order to use some new classes (If you are not familiar with importing classes and packages, see the Adobe documentation or a third-party book on ActionScript 3.0)

   import flash.display.Sprite; 
   import flash.events.*;
   import flash.ui.*;
   import sandy.core.Scene3D;
   import sandy.core.data.*;
   import sandy.core.scenegraph.*;
   import sandy.materials.*;
   import sandy.materials.attributes.*;
   import sandy.primitive.*;

Relocating the Camera

camera = new Camera3D( 300, 300 );
//camera.x = 100;
//camera.y = 100;
camera.z = -400;
//camera.lookAt(0,0,0);

In the first Flash swf example below, I'm not using these settings (I have commented them out). You can uncomment them to see their effect. You just need to know that you can move the camera anywhere in the space using its three properties: x, y, z, and you can tell the camera where in the scene to point, using camera.lookAt().

Placing an axis as reference

var myXLine:Line3D = new Line3D( "x-coord", new Vector(-50, 0, 0), new Vector( 50, 0, 0 ));
var myYLine:Line3D = new Line3D( "y-coord", new Vector(0, -50, 0), new Vector( 0, 50, 0 ));
var myZLine:Line3D = new Line3D( "z-coord", new Vector(0, 0, -50), new Vector( 0, 0, 50 ));

It is simple to draw the lines–just specify the starting and ending points, which you can define using the Vector class. To make the code simpler to read, I am not attaching any appearance to them, so they will be rendered as solid black lines.

Placing a Torus

var torus:Torus = new Torus( "theTorus", 120, 20);

Some of you might remember this object from geometry. The constructor takes three parameters: the name, the radius of the ring, and the radius of the cross-section of the ring (how thick the tube will be).

Adding the objects to the Group

g.addChild(myXLine);
g.addChild(myYLine);
g.addChild(myZLine);
g.addChild( torus);

Constructing the EventListener

addEventListener( Event.ENTER_FRAME, enterFrameHandler );
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);

The first listener is responsible of the rendering of the entire scene, while the other is responsible to catch user input events: in this case Keyboard Event. (I’ve implemented the KEY_DOWN event, but feel free to implement any event you feel more comfortable. On the web, you can find classes that allows to hide this implementation and gives you static method to catch the key pressed, but I want to give you here the basic concepts that will allow you to understand what is going on, and let you dig in more sophisticated code).

Let’s investigate what does the keyPressed method:

   switch(event.keyCode) {
      case Keyboard.UP:
         camera.tilt +=2;
         break;
      case Keyboard.DOWN:
         camera.tilt -=2;
         break;
      case Keyboard.RIGHT:
         camera.pan -=2;
         break;
      case Keyboard.LEFT:
         camera.pan +=2;
         break;
      case Keyboard.CONTROL:
         camera.roll +=2;
         break;	
      case Keyboard.PAGE_DOWN:
         camera.z -=5;
         break;
      case Keyboard.PAGE_UP:
         camera.z +=5;
         break;	
   }

The keyPressed method takes different actions depending on which key was pressed (the Page Up and Page Down keys won't be recognized during authoring but will be detected properly at runtime). And what it does it just use some properties of the class Camera3D. It’s easy to understand what we are doing, so we just need to see the result live.

The output

We now have something to play with. Remember, for the Flash examples below to receive keyboard focus, you must click the mouse inside the scene. (The thin red border around each Flash example was created in the Flash authoring tool for cosmetic reasons and has nothing to do with the tutorial or Sandy.)

Once a Flash example has keyboard focus, you can use the up, down, right, or left arrow keys to move (translate) the camera in each direction. Use the PageUp and PageDown keys to zoom the camera in and out (translate it in the z direction). Use the control key to rotate the camera.

You are moving the Camera, not the object; the object is stationary, as you can see by the fact that its position is constant relative to the coordinate system.

I think you have got an idea of how the Camera3D works, and now you can play with it.