Building your First Application with Papervision3D: Part 2

Exclusive offer: get 50% off this eBook here
Papervision3D Essentials

Papervision3D Essentials — Save 50%

Create interactive Papervision 3D applications with stunning effects and powerful animations

$26.99    $13.50
by Jeff Winder Paul Tondeur | September 2009 | Open Source

In the previous part of the article by Jeff Winder & Paul Tondeur, we introduced the concepts of classes and object-oriented programming and saw how to work with the document class/main application file. In this part, we will learn what a 3D scene in Papervision3D is made up of. Once this is clear, we can write our first basic application!

This article covers:

  • Basics of a 3D composition in Papervision3D
  • Building your first application

Basics of a 3D scene in Papervision3D

Before we're ready to program some code for Papervision3D, we need to know a little bit more about 3D in Papervision3D. The following section is meant to give you a better understanding of the code that you will write. Each of these concepts relates directly to classes that are used by Papervision3D. All the object types that will be described are active elements in a 3D scene. Let's have a visualized look at all these objects:

Papervision3D Essentials

Scene

The scene is the entire composition of 3D objects in a 3D space. Think of it as your stage in Flash with three axes—x, y, and z. Each object that you want to be visible should be added to the scene. If you don't add objects to the scene, they will not appear on your screen.

Camera

You can think of this as a real camera, which is somewhere in 3D space recording activity inside the scene. The camera defines the point of view from which you are viewing the scene. Because a camera in 3D is not a visible object, it is not part of our scene and you don't need to add it. Like a real camera you can, for example, zoom and focus.

Cameras in 3D space can usually do more than real cameras. For example, in 3D you can, exclude objects to be rendered, when they are too close or too far away from the camera. The camera is able to ignore objects that are not in a certain, defined range. This is done for performance reasons. Objects that are too far away, or even behind the camera, don't need to be recorded, saving a lot of calculation for objects that are in a position where the camera simply can't see them.

Viewport

A viewport is a container sprite on your stage, and shows the output of what the camera sees. In the illustrative object overview, this has been compared with the lens of the camera. The lens is our window onto the 3D scene. We can make this window small and see just a small part of the scene, or make it big and see a lot. This works exactly as a real window in a wall—making it bigger will not affect how the world outside looks, but will have an effect on how much we can see from this world.

The following illustration contains the visualization of a relatively big viewport on the left, along with a relatively small and wide viewport on the right. The thick dark outlines represent the viewports. In the right image, you can clearly see how the window to the 3D world works and how changing its size will not stretch the view of the 3D object in the scene. It only affects how much we see of it.

Papervision3D Essentials

3D Objects

A shape in 3D space is called a 3D object, or DisplayObject3D in Papervision3D. You can think of 3D objects as more advanced display objects just like sprites and movie clips. The difference is that a DisplayObject3D has a third axis, so we can place it anywhere in 3D space and rotate over each of the three axes.

Material

A material is the texture that is printed on an object. When an object doesn't have a material applied, it will be invisible. There are a variety of materials available for you to use. For example, a very simple material is a color; a more advanced example of a material could be a live streaming video.

Render engine

A render engine is like a rolling camera. As long as you trigger the render engine, it will output information of the scene recorded by the camera to the viewport. When you stop triggering the render engine, your viewport will not show any new image from the scene and shows the last rendered image. Rendering is actually the most intensive task for your computer, as it needs to recalculate each object that is placed inside your scene and output this to the viewport.

Left-handed Cartesian coordinate system

Flash, as well as Papervision3D, make use of the Cartesian coordinate system. In Flash, a regular visual object can be positioned on the stage by entering an x and y value. The object will be positioned according to these values and relative to the upper left corner of the stage. A higher x value moves the object to the right, whereas a higher y value moves it downward.

The coordinate system in Papervision3D works essentially the same, except for the following two differences:

  • Flash uses Cartesian coordinates on two axes, whereas Papervision3D makes use of them on three axes
  • The y-axis in Flash is inversed compared to the y-axis in Papervision3D

In Papervision3D, we want to position objects not only on the x and y axes, but also on an extra axis, in order to position objects in depth. This third axis is called the z-axis.

In Flash, objects are positioned relative to the upper left corner, which is the 0, 0 coordinate. This is called the center point, or the origin. Predictably, the position of the origin in 3D space is located at 0, 0, 0. The three axes and the origin point are illustrated by the following image:

Papervision3D Essentials

The plus and minus signs illustrate whether the coordinate values are increasing or decreasing in the direction away from the origin. Notice that the y-axis is inverted compared to 2D coordinates in Flash. When you want to position an object lower on your screen in Flash, you need to give it a higher y position. This is how 2D coordinates on a computer screen work. The above figure shows the y-axis as according to the coordinate system as it is used by Papervision3D.

Creating a basic class for Papervision3D

In the previous sections you've learned what a basic scene is made of, and how you can create your own classes. Now that we have gone through all this theory, it's now time that we get our hands dirty by writing some code.

Start your favorite authoring tool. The first application we'll build is a 3D scene containing a sphere that is rotating over its y-axis. A sphere is basically a "3D ball" and is built into Papervision3D as one of the default primitives.

The basic document class

First, have a look at the document class that defines the basic structure for the rotating sphere application.

package {
import flash.display.Sprite;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;

public class FirstApplication extends Sprite
{
private var scene:Scene3D;
private var viewport:Viewport3D;
private var camera:Camera3D;
private var renderEngine:BasicRenderEngine;
private var sphere:Sphere;

public function FirstApplication()
{
scene = new Scene3D();
camera = new Camera3D();
sphere = new Sphere();
scene.addChild(sphere);
viewport = new Viewport3D();
addChild(viewport);
renderEngine = new BasicRenderEngine();
renderEngine.renderScene(scene,camera,viewport);
}
}
}

Let's have a look at this in detail. While we do that, you can create a new project in Flash, Flex Builder, or Flash Builder with a document class called FirstApplication. If you're using Flex Builder or Flash Builder, don't forget to configure the path to the Papervision3D source.

We know that we need to have a scene, a camera, a viewport, a 3D object with a material, and a render engine, in order to create a rendered output on the screen. Remember that the document class needs to extend Sprite. To make all these available inside the class, we need to import them first.

import flash.display.Sprite;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;

Now that the imports are set, we define the properties of the class.

private var scene:Scene3D;
private var viewport:Viewport3D;
private var camera:Camera3D;
private var renderEngine:BasicRenderEngine;
private var sphere:Sphere;

We only define the properties and their class types here, without assigning any value. We'll do that inside the constructor. Let's first create the constructor.

public function FirstApplication()
{
}

We start by creating a scene inside the constructor. A scene is needed as the holder for our 3D objects. It's very easy to create one.

scene = new Scene3D();

All you have to do is create an instance of the Scene3D class, which doesn't take any parameters.

Next, we add a Camera3D, which is just as easy as the creation of a new Scene.

camera = new Camera3D();

A camera can take parameters when you create a new instance; however, the default values will do for now.

The scene and camera are useless as long as there are no 3D objects in the scene to film. For this example a sphere will be used, which is one of the built-in 3D objects.

sphere = new Sphere();

A camera, as well as a sphere, takes parameters when you instantiate it. However, when you do not pass any parameters, a default sphere will be created.

Now that we have created our sphere, we need to add it to the scene, otherwise it will not be seen by the camera. This works in exactly the same way as adding regular display objects to the display list in Flash, by using the addChild() method.

scene.addChild(sphere);

That looks familiar, right?

Now that we have a scene, a camera, and a sphere, we need to set up the window to the 3D scene, so we can see what is going on in there. We need to define our viewport and add it to the stage to make it visible.

viewport = new Viewport3D();
addChild(viewport);

While creating a new viewport, you can pass optional parameters to it, but the default parameters are again fine for now.

We are now just one step away from publishing our application. First we need to get our camera rolling. This is done by defining the render engine, which will render the current view of the camera to the viewport.

renderEngine = new BasicRenderEngine();
renderEngine.renderScene(scene,camera,viewport);

Now that the render engine is defined and an instruction to render the scene is added, we are ready to publish this project. This should result in the following image of triangles that together form something like a circle:

Papervision3D Essentials

Case sensitivity
Pay attention to upper cases and lower cases in the examples. Not following these conventions might result in an error. A good example of this is the definition and instantiation of a sphere as we did in our FirstApplication.
var sphere:Sphere = new Sphere();
Here we see that we have defined a class property called sphere (lowercase) of a Sphere (uppercase) type, containing an instance of Sphere (uppercase). Giving a variable/property the same name as the defined object type will often cause problems.

The result of these few lines of code may not look very impressive yet, but in fact this is the beginning of something that will soon become exciting and could never be accomplished this easy by regular Flash use. When you have managed to compile this application that shows the triangles, you've made it through the hardest part of this example. Let's continue building your first application and see how we can add the illusion of 3D to our object, which still looks very 2D.

Papervision3D Essentials Create interactive Papervision 3D applications with stunning effects and powerful animations
Published: September 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Finalizing your first application

The 2D look is caused by the fact that there's no perspective noticeable. Also, the scene is quite static. When we rotate the sphere over one of its axes, we will get a better 3D illusion. Because perspective changes, it adds the illusion of looking at a 3D sphere. But before we can implement rotation, we need to add a few extra lines of code. At this stage, we have executed only a single render, right after we've defined the render engine. However, this is not enough in a real 3D scene. Remember we talked about the need to have a rolling camera? Calling renderScene once will only render the output image once, similar as a camera that takes one picture. This isn't exactly rolling; we need to do this constantly. The most common way to do this is by adding an ENTER_FRAME event listener and by rendering the scene each time an ENTER_FRAME is dispatched.

We need to import the Event class, so we can listen for ENTER_FRAME events. This can be achieved by setting the following import at the top of your class:

import flash.events.Event;

Now that Event is available, we can add a listener. Place it right after the renderScene call, as shown in bold in the next snippet:

renderEngine.renderScene(scene, camera, viewport);
addEventListener(Event.ENTER_FRAME, render);

On each ENTER_FRAME event, a method called render will be triggered. This method needs to be implemented, together with a renderScene call inside of this method. Add the following code after the constructor method:

 private function render(e:Event):void
{
renderEngine.renderScene(scene, camera, viewport);
}

Each time the playhead enters a new frame, the scene will get rendered again. At this moment, that's just a waste of capacity. Why would you render the scene if nothing has been changed? So, let's start rotating the sphere around its y-axis. This can be achieved by constantly increasing the current rotation of the y-axis, right before the scene renders inside our render method.

private function render(e:Event):void
{
sphere.localRotationY +=1;
renderEngine.renderScene(scene, camera, viewport);
}

Every frame the current rotation of the object increases by one degree. Publishing will lead to an animation as shown in the following sequence of screenshots:

Papervision3D Essentials

This immediately gives you the illusion of having a 3D object rotating! If you are working in Flash CS3, Flex Builder, or Flash Builder, the animation reveals an issue regarding the smoothness of the movement. This is because we haven't changed Flash's or Flex's default frame rate. This results in Flash CS3 playing at its default of 12 frames per second (fps), and Flex Builder and Flash Builder at 24 fps. By default, Flash CS4 does a better job, as it has a default fps of 30. Although the default frame rate of both Flex Builder and Flash Builder is 24, and Flash CS4's frame rate is 30, it can be a lot more. The higher you set this value, the smoother and faster everything will animate. Of course, getting smoother animations is not without extra costs. Higher frame rates consume more CPU power, maybe even more than is available on the user's computer. In that case the Flash player will try its utmost to draw as many new frames as it can, resulting in stalling animations. With our sphere this is far from an issue, but it can become one when render a more complex 3D scene.

For now, all we have to do is change the default FPS. There's no such thing as a best frame rate value. For all examples in this article, we'll use a value of 40. In Flash IDE you simply set a property of your FLA, but in Flex you can change this only by programming a line of code. This approach works for Flash as well. You can do this by setting the frameRate property of your stage:

stage.frameRate = 40;

Usually this value is set as one of the first instructions inside the constructor of a document class, but you can change it wherever and whenever you want in your application. To see a smoother animation, add the above line as the first command inside your constructor.

We have just finished our first application! Publish it and you'll see the same sphere rotating on its y-axis, but now it runs much smoother.

Let's recap and have a look at the updated class with the changes in bold:

package {
import flash.display.Sprite;
import flash.events.Event;

import org.papervision3d.cameras.Camera3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;

public class FirstApplication extends Sprite
{
private var scene:Scene3D;
private var viewport:Viewport3D;
private var camera:Camera3D;
private var renderEngine:BasicRenderEngine;
private var sphere:Sphere;

public function FirstApplication()
{
stage.frameRate = 40;
scene = new Scene3D();
camera = new Camera3D();

sphere= new Sphere();
scene.addChild(sphere);

viewport = new Viewport3D();
this.addChild(viewport);

renderEngine = new BasicRenderEngine();
renderEngine.renderScene(scene,camera,viewport);
this.addEventListener(Event.ENTER_FRAME,render);
}
private function render(e:Event):void
{
sphere.localRotationY +=1;
renderEngine.renderScene(scene,camera,viewport);
}
}
}

Smart programmers use less code

The FirstApplication example is a nice and minimal Papervision3D class. Each time we want to make a new Papervision3D application we could copy this class and add the specific logic for the new application to it. But isn't there a smarter way to do this? Each Papervision3D project contains minimal definitions of—a camera, a scene, a renderer, and a viewport. Defining these properties and importing the classes each time you start with a Papervision3D project sounds like a lot of work. Smart programmers ask themselves how they can do this in a more efficient way. Fortunately, Papervision3D includes a class called BasicView that contains the basic setup we need. As the BasicView class is, in the end, an extended Sprite, we can instantiate it and add it to the stage or extend our document class with it. In this article we'll use the last option.

So how does that work? Let's have a look at the improved version, with the same sphere rotating on its y-axis.

package {
import flash.events.Event;

import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.view.BasicView;

public class BasicViewExample extends BasicView
{
private var sphere:Sphere;
public function BasicViewExample()
{
stage.frameRate = 40;

sphere = new Sphere();
scene.addChild(sphere);

startRendering();
}
override protected function onRenderTick(e:Event=null):void
{
sphere.localRotationX +=1;
super.onRenderTick();
}
}
}

Inside the constructor, we need to set only project specific values such as the frame rate and a sphere object. The sphere is added to the scene, without instantiating a Scene3D object. This was already done automatically inside the BasicView class. We then tell the BasicView class that it can start rendering by calling the startRendering() method which is part of the BasicView class. Once this method is called, it will add an ENTER_FRAME eventListener, re-rendering the scene each time the event is dispatched. This is already enough to see our sphere rendered on screen, but we need to increase the rotation-y value of the sphere which we do on each ENTER_FRAME. In most examples we will do something at each ENTER_FRAME. The easiest way to do this is to override the onRenderTick() method, which is part of the BasicView class, and will be called every frame. By overriding this method we can write our own code to be executed each time onRenderTick() gets called. As we want the original onRenderTick() to be executed as well, we'll call this method on the super class by calling super.onRenderTick();.

Due to some minor differences between the settings in the BasicView class and the settings we have used in FirstApplication, the size of the sphere will not be the same. Whereas the viewport in our example was predefined, BasicView automatically scales it to the size of the stage.

Using the BasicView class can save you a lot of code. When you compare this extended BasicView class to the FirstApplication class, you'll see that you've reduced the amount of lines from 43 to 26. So, this saved you 17 lines of code that you don't have to write over and over again.

Summary

In this article we learned what Papervision3D application is made of and that it at least contains:

  • A scene to hold 3D objects
  • A camera that registrates the scene
  • A viewport as the window to the world
  • A render engine to render information to the viewport
  • A 3D object as a visual object in 3D space
  • A material to assign to the 3D object in order to make it visible

We've learned how to use these objects as the building blocks for a basic application by using a document class in Flash CS3, Flash CS4, Flex Builder, or Flash Builder. As an example, we've made a primitive sphere rotating around its y-axis. An important thing you have learned is how we can program smarter by extending the BasicView class, which already contains the basic setup for a Papervision3D scene.

Papervision3D Essentials Create interactive Papervision 3D applications with stunning effects and powerful animations
Published: September 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Jeff Winder

Jeff Winder is an independent Flash developer living and working in Amsterdam, the Netherlands. He discovered Flash and ActionScript in 2003, mainly creating timeline animation, but was soon gripped by non-timeline coding. He has a special interest in new technologies that are related to Flash, especially open-source projects such as WiiFlash, FLARToolKit, and Papervision3D. Jeff acquired an MSc in Social Psychology at the University of Amsterdam. He is also a passionate musician, playing guitar and drums. Since 2006 Jeff has been self-employed and working for leading agencies. URL: http://www.jeffwinder.nl

Paul Tondeur

Paul Tondeur is as an internet entrepreneur who lives and works in Amsterdam, the Netherlands.

He started as a freelance PHP and Flash developer during his study multimedia technology in 2003. After successfully completing his study he was asked to become the CTO of a Dutch online marketing agency in 2004. At this company he developed a strong interest for 3D and got the chance to get professionally involved as the technical lead for serious Second Life projects. Second Life was too limited to fulfill his needs to create accessible interactive multiplayer 3D on the web and this is when he found out about Papervision3D during the early days. Because of his passion for the Flash platform this was love at first sight.

At the beginning of 2009, Paul decided he had to take more advantage of his technical skills as an internet entrepreneur. Currently he helps other companies as a Unity, Papervision3D, Red5 and mobile streaming consultant. Together with a team of people around him, he is also involved in creating a browser based MMO, incorporating the usage of Red5, Unity, Flash and Papervision3D.

URL: www.paultondeur.com

Books From Packt

Flash with Drupal
Blender 3D Architecture, Buildings, and Scenery

ImageMagick Tricks
ImageMagick Tricks

Joomla! 1.5 SEO
Joomla! 1.5 SEO

Drupal 6 Search Engine Optimization
Drupal 6 Search Engine Optimization

Mastering phpMyAdmin 3.1 for Effective MySQL Management
Mastering phpMyAdmin 3.1 for Effective MySQL Management

Drupal Multimedia
Drupal Multimedia

jQuery UI 1.6: The User Interface Library for jQuery
jQuery UI 1.6: The User Interface Library for jQuery

Ext JS 3.0 Cookbook
Ext JS 3.0 Cookbook

Your rating: None Average: 5 (3 votes)
Problem adding more classes by
Hi, thanks for the short manual :))...but I got a problem I cannot solve: in my Main class extending BasicView I call another class, also extending basic view...I just call: var inst:MyOtherClass= new MyOtherClass(); myDisplayObject3D.addChild (inst) this normally would work just fine...but in Papervision (2.0) and I receive the error: C:********Main.as:46: 1067: Implicit coercion of a value of type com.whatever:MyOtherClass to an unrelated type org.papervision3d.objects:DisplayObject3D. Any suggestion

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
B
Z
u
E
F
S
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software