Home  >  Development  >  features

Papervision3D: Part 1- Foundation and 3D Object Basics

| | Comments (63)
AddThis Social Bookmark Button
 

Papervision3D
Papervision3D is an open-source, MIT licensed 3D engine written in ActionScript 3.0 for Flash. This article will teach you how to set up your first Papervision3D application with the most recent revision as of this writing, Papervision3D 2.0 Alpha, otherwise known as “Great White.” The great barrier for beginners is usually “installing” Papervision3D as they are unfamiliar with subversion, classpaths, and documents classes. The first three sections address these issues with off-site tutorials as that process is not within the scope of this article. So if you’re familiar with the subversion process and setting up an ActionScript 3.0 project, check out Papervision3D at the following link then skip to the “Foundation of Papervision3D” section:

If you don’t know what to do with that link, then continue on reading the links in the first three sections.

Download
First, you need to download Papervision3D using subversion. Follow the instructions at either of these sites:

Classpath
Set up a classpath that points to the Great White “src” directory:

Document Class
Create a document class to hold the required ActionScript:

 
Foundation of Papervision3D
I’ll keep the code as simple as I can for those of you new to ActionScript 3.0, but I will assume you have a basic understanding of importing classes, declaring/instantiating variables, and writing/calling methods. If not, O’Reilly’s “Essential ActionScript 3.0” is a great place to start. When I instantiate objects in code snippets, I’ll assume you understand you need to import the relevant classes.

Every Papervision3D application requires four classes: Viewport3D, Scene3D, Camera3D (or alternatives), and BasicRenderEngine (or alternative). Glance at the following typical set up of a Papervision3D project before I dive into a full explanation:

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

   public class Main extends Sprite{
        private var viewport:Viewport3D;
        private var scene:Scene3D;
        private var camera:Camera3D;
        private var renderer:BasicRenderEngine;

        public function Main(){
               initPapervision3D();
        }

        private function initPapervision3D():void{
               viewport = new Viewport3D();
               addChild(viewport);

               scene = new Scene3D();
               camera = new Camera3D();
               renderer = new BasicRenderEngine();

               renderer.renderScene(scene, camera, viewport);
        }
   }
}

Viewport3D
Think of a Viewport3D as a window to the world of Papervision3D. Windows allow you to see outside, but they serve no other function. You can position a window on the wall or change its width and height, but that’s really about it. The same is true with Viewport3D. You can change the “x”, “y”, “width”, and “height” of the Viewport3D, but its only true functionality is to let you look at the 3d scene inside of it. To use a viewport, create it then add it to the stage.

private var viewport:Viewport3D = new Viewport3D();
addChild(viewport);

For reference, the default parameters of Viewport3D, which you can adjust to your liking, are as follows. I’ll cover interactive, autoClipping, and autoCulling in a future article:

Viewport3D(viewportWidth:Number = 640, viewportHeight:Number = 480, 
autoScaleToStage:Boolean = false, interactive:Boolean = false,
autoClipping:Boolean = true, autoCulling:Boolean = true)

Scene3D
To continue with the window metaphor, a Scene3D would hold everything you could see looking through the window: the ground, the sky, and everything in-between. Yet the Scene3D is still just empty 3D space. You have to add the ground, the sky, the trees, etc., by adding 3d objects to your Scene3D. A scene3D is created as follows:

private var scene:Scene3D = new Scene3D();

Camera3D
A window and an outside world are pretty worthless if there’s no one there to witness their beauty. Luckily for you, the developers of Papervision3D created cameras to capture all the action. A Camera3D allows you to set the x, y, and z coordinates from where you want to capture the action. Imagine a first-person shooter or flight simulator. You move your character around and the surrounding area adjusts to your current position. The same idea applies to Camera3D movement: you move the camera and the entire Scene3D adjusts to its current position.

Papervision3D provides three cameras with varying functionalities:

  • • Camera3D- requires a target to “look at” and will always “look at” that target regardless of position
  • • FreeCamera3D- moves freely through 3D space in every angle and direction. Includes methods such as yaw(), pitch(), and roll() to adjust the camera’s viewing angle as well as moveForward(), moveBackward(); moveLeft(), moveRight(), moveUp(), and moveDown() to adjust the camera’s position based on its viewing angle. For example, if you position the camera looking straight at someone’s face then call moveBackward(), you will move farther and farther back from that person’s face while still looking straight their face. On the other hand, if you position the camera above the person, pitch() the camera to look straight down at their hair, and then call the same moveBackward() method, you will lift the camera higher into the sky while continuing to look at the person’s hair.
  • • FrustumCamera3D- moves like FreeCamera3D, but only renders the objects within a field of view, far distance, and near distance that you determine.

BasicRenderEngine
In the world of Papervision3D, you’re God. That means you get to decide when the world exists. Without the BasicRenderEngine class rendering your world, it just won’t exist. So you can start and stop the engine as you please. The BasicRenderEngine renders a Scene3D from the Camera3D position through the Viewport3D that you choose:

private var renderer:BasicRenderEngine = new BasicRenderEngine();
//Usually within an Event.ENTER_FRAME handler so the scene
renders in each frame renderer.renderScene( scene, camera,
viewport );

Even if you have multiple scenes, viewports, or cameras, you still only need one BasicRenderEngine to handle all of the rendering:

//A snippet of multiple scenes, cameras, and viewport handled by one 
renderer renderer.renderScene( scene, camera, viewport );
renderer.renderScene( scene2, camera2, viewport2 );

3D Objects
3D Coordinates
Before diving into creating objects, let’s take a look at how objects are positioned in 3D space as opposed to traditional Flash projects.

In Flash, you position an object on the stage based on x:0 and y:0 being in the upper-left corner. Increasing x moves an object to the right and increasing y moves an object down. Conversely, in Papervison3D x:0, y:0, and z:0 are in the center (not the upper-left) of the Scene3D. Since the Camera3D defaults to x:0, y:0, z:-1000 and points at the origin (x:0, y:0, z:0), increasing x moves the object right, increasing y moves the object up, and increasing z moves the object toward the horizon.

xyz_map.jpg

Also, remember the amount of movement you will see is based on how close the camera is to the 3d object. The closer the camera the more objects will appear to move. You cannot rely on pixels like you can in a traditional two dimensional Flash project. Consider the following examples based on the default camera position:

  • • x = 10; //means 10 units right of Scene3D’s center

  • • x = -10; //means 10 units left of Scene3D’s center

  • • y = -10; //means 10 units below Scene3D’s center

  • • z = -10; //means 10 units closer to the camera from Scene3D’s center (remember Camera3D defaults to z:-1000 so moving from 0 to -10 brings the object closer to -1000.)

If you’re the type of person who must understand how 3D coordinates are possible within in a 2D Flash Player, put on your math hat and read up on quarterions:

http://en.wikipedia.org/wiki/Quarterion
http://www.adobe.com/devnet/flash/articles/3d_classes_03.html
http://www.isner.com/tutorials/quatSpells/quaternion_spells_14.htm

Even if you don’t understand the math involved in those articles, you probably understand that 3D objects are made up groups of 3D coordinates. These 3D coordinates (also known as vertices) form triangles. The triangles form a polygon mesh or, in layman’s terms, a 3D object.

On a side note, Papervision3D uses the Painter’s Algorithm to sort the visibility of those triangles. The Painter’s Algorithm evaluates the sorting quickly (ideal for Flash Player), but can fail if triangles overlap. You typically resolve this issue by creating more segments in your 3D object to give less chance that the triangles overlap.

Plane

Plane.JPG

I consider Planes to be the most useful 3D objects for most Papervision3D projects, especially if the project is interactive. Oddly enough, a Plane does not technically qualify as a 3D object as it has no depth. A Plane is simply two triangles stuck together to form a rectangle. Remember, the Scene3D holds all of your 3D objects. So to use a plane, create it then add it to the Scene3D.

var plane:Plane = new Plane();
scene.addChild(plane);

A Plane defaults to a WireFrameMaterial (discussed in a later article) with a width of 500 and height of 500. So using the above code will result in a wireframe Plane centered at x:0, y:0, and z:0 with a width and height of 500 facing the camera (assuming the camera is in its default position discussed earlier). When you pass a material with an image inside it, the Plane will default to the width and height of the bitmap of that image. The parameters available for a Plane are as follows:

Plane( material:MaterialObject3D=null, width:Number=0,
height:Number=0, segmentsW:Number=0, segmentsH:Number=0,
initObject:Object=null )

Material, width, and height are pretty self-explanatory. SegmentsW and segmentsH set the number of segments in the width and height of the Plane respectively. Multiple segments help to avoid the distortion of an image when the Plane starts rotating as well as the depth sorting of the triangles as mentioned earlier. The screenshot below demonstrates a Plane with four segmentsW and three segmentsH.

Plane_4SegmentsW3SegmentsH.JPG

Be wary when creating many Planes as each additional width or height segment you create tacks on two more triangles (essentially forming another rectangle inside the Plane to give the plane more detail). The number of triangles Flash Player can handle varies depending on your application, but generally try and keep the triangle count below 2000.

The last optional parameter, initObject, can store the initial x, y, z, rotationX, rotationY, rotationZ, scaleX, scaleY, scaleZ, and “extra” parameters. Alternatively, you can directly set the listed properties after instantiating your Plane. A quick example will explain nicely:

var m:WireframeMaterial = new WireframeMaterial();
//width and height
var w:Number = 800;
var h:Number = 800;
//segmentsW and segmentsH
var sW:Number = 1;
var sH:Number = 1;
var initObject:Object = new Object();
initObject.x = 100;
initObject.rotationY = 30;
initObject.scaleZ = 20;
//Option #1 using initObject
var plane:Plane = new Plane(m, w, h, sW, sH, initObject);

scene.addChild(plane);

//Option #2 setting properties directly
var plane:Plane = new Plane(m, w, h, sW, sH, initObject);

plane.x = 100;
plane.rotationY = 30;
plane.scaleZ = 20;

scene.addChild(plane);

One final note about Planes: if you spin a Plane, you’ll notice the plane will disappear once you look at the other side. If you want to have a texture on both sides of the Plane, you will need to enable the “doubleSided” property of your material you pass into your Plane.

material.doubleSided = true;

Sphere
You create a Sphere very similarly to the way you create a Plane:

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

Sphere.JPG

A Sphere’s default parameters closely resemble a Plane’s parameters as well. The Sphere just takes a radius parameter instead of width and height. If you think back to high school, you will probably recall the radius being the distance from the center of the circle to the outer edge. As opposed to the simplicity of width and height of a Plane, the Sphere now uses the radius to calculate the distance between the center and the edges to create groups of three vertices that make groups of triangles that make the Sphere. Pretty neat, huh? The default parameters are as follows:

Sphere( material:MaterialObject3D=null, radius:Number=100, 
segmentsW:int=8, segmentsH:int=6,
initObject:Object=null )

For brevity’s sake, a Cone and a Cylinder can be created similarly with the following default parameters:

Cone( material:MaterialObject3D=null, radius:Number=100, 
height:Number=100, segmentsW:int=8, segmentsH:int=6,
initObject:Object=null )

Cone.JPG

Cylinder( material:MaterialObject3D=null, radius:Number=100,
height:Number=100, segmentsW:int=8, segmentsH:int=6,
topRadius:Number=-1,
initObject:Object=null )

Cylinder.JPG

Cube
What do you get when you take six Planes and organize them into the shape of a box? A Cube!

Cube.JPG

By now you should be getting the hang of creating 3D objects, but the Cube throws in a curve ball by requiring a MaterialsList (discussed in a later article). You will probably get the gist of how to use a MaterialsList by reading how to create a Cube:

var frontMaterial:WireframeMaterial = new WireframeMaterial();
var backMaterial:WireframeMaterial = new WireframeMaterial();
var leftMaterial:WireframeMaterial = new WireframeMaterial();
var rightMaterial:WireframeMaterial = new WireframeMaterial();
var topMaterial:WireframeMaterial = new WireframeMaterial();
var bottomMaterial:WireframeMaterial = new WireframeMaterial();

var materialsList:MaterialsList = new MaterialsList();

materialsList.addMaterial(frontMaterial, "front");
materialsList.addMaterial(backMaterial, "back");
materialsList.addMaterial(leftMaterial, "left");
materialsList.addMaterial(rightMaterial, "right");
materialsList.addMaterial(topMaterial, "top");
materialsList.addMaterial(bottomMaterial, "bottom");

var cube:Cube = new Cube(materialsList);

scene.addChild(cube);

The Cube faces forward when rendered meaning, with the camera in the default z:-1000 looking at x:0, y:0, z:0 position, you will be looking directly at the back of the Cube. Without any perspective, it will look exactly like a Plane. You can easily set any of the Cube’s rotation properties to see the full effect (the earlier Cube image was rotated slightly to show perspective). Now let’s cover the default parameters of a cube:

Cube( materials:MaterialsList, width:Number=500, depth:Number=500, 
height:Number=500, segmentsS:int=1, segmentsT:int=1, segmentsH:int=1,
insideFaces:int=0, excludeFaces:int=0, initObject:Object=null )

The segments require a little explaining, yet function in the same fashion as Plane’s segments:

  • • segmentS - Number of segments sagitally (plane perpendicular to width). Defaults to 1.
  • • segmentsT - Number of segments transversally (plane perpendicular to depth). Defaults to segmentsS.
  • • segmentsH - Number of segments horizontally (plane perpendicular to height). Defaults to segmentsS.

The insideFaces parameter determines which faces will be rendered on the inside of the Cube. This is useful if you want to have the camera inside of the Cube for the illusion of being trapped in a room. To set the faces you want to include, use the following static public variables of Cube:

  • • Cube.NONE
  • • Cube.FRONT
  • • Cube.BACK
  • • Cube.LEFT
  • • Cube.RIGHT
  • • Cube.TOP
  • • Cube.BOTTOM
  • • Cube.ALL

Simply create an insideFaces integer that describes which faces you want to see on the inside and pass it as a parameter where appropriate. For example, if you want just the top of the inside of the Cube to be rendered, write the following:

var insideFaces:int = Cube.TOP;
var cube:Material = new Cube(m, w, d, h, sS, sT, sH, insideFaces);

For just the left, right, and bottom face:

var insideFaces:int = Cube.LEFT + Cube.RIGHT + Cube.BOTTOM;
var cube:Material = new Cube(m, w, d, h, sS, sT, sH, insideFaces);

For all the faces except the front face:

var insideFaces:int = Cube.ALL - Cube.FRONT;
var cube:Material = new Cube(m, w, d, h, sS, sT, sH, insideFaces);

The next parameter, excludeFaces, works exactly the same way, but excludes the faces you don’t want. Think of it like taking the lid of a shoebox.

Collada
This is where Papervision3D gets really exciting: you create a model in your preferred 3D modeling program (3ds max, Maya, Blender, Swift3D, etc.), export it as a Collada file, and load it using the Papervision3D DAE class. Unfortunately, this topic deserves an article unto itself, but here are a few demos to get you on the right track:

Loading Collada Files into Papervision3D
Testing Kinematics with Papervision3D Collada
DCC Tutorials

Enough Talk, Let’s See Code!
I bet you’re anxious to start tickling the keyboard to see if it laughs out a working Papervision3D project. So let’s make a Cube and spin it using the Cube yaw() and pitch() methods (Don’t fret, I’ll cover the details of yaw, pitch, roll, etc. in future articles):

RotatingCubeExample.JPG

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

    import org.papervision3d.cameras.Camera3D;
    import org.papervision3d.materials.WireframeMaterial;
    import org.papervision3d.materials.utils.MaterialsList;
    import org.papervision3d.objects.primitives.Cube;
    import org.papervision3d.render.BasicRenderEngine;
    import org.papervision3d.scenes.Scene3D;
    import org.papervision3d.view.Viewport3D;

    [SWF ( width = '640', height = '480', backgroundColor = '#ffffff',
frameRate = '31' ) ]
    public class RotatingCubeExample extends Sprite {
       private var viewport:Viewport3D;
       private var scene:Scene3D;
       private var camera:Camera3D;
       private var renderer:BasicRenderEngine;

       private var cube:Cube;

       public function RotatingCubeExample(){
          initPapervision3D();
          createCube();
          beginRender();
       }

       private function initPapervision3D():void{
          viewport = new Viewport3D();
          addChild(viewport);

          scene = new Scene3D();
          camera = new Camera3D();
          renderer = new BasicRenderEngine();
       }

       private function createCube():void{
          var allM:WireframeMaterial = new WireframeMaterial();

          var m:MaterialsList = new MaterialsList();
          m.addMaterial(allM, "all");

          //width, depth, height
          var w:Number = 300;
          var d:Number = 500;
          var h:Number = 700;

          //segments S, T, and H
          var sS:int = 2;
          var sT:int = 3;
          var sH:int = 4;

          cube = new Cube(m, w, d, h, sS, sT, sH);
          scene.addChild(cube);
       }

       private function beginRender():void{
          //calls the render function every frame
          addEventListener(Event.ENTER_FRAME, render);
       }

       private function render(e:Event):void{
          //rotates around the vertical axis
          cube.yaw(2);
          //rotates around the lateral axis
          cube.pitch(1);
          renderer.renderScene(scene, camera, viewport);
       }
    }
}

Common Mistakes: Help! I Don’t See Anything!

  • 1. Did you properly import the Papervision3D classes?

  • 2. Did you “addChild()” your viewport?
    addChild(viewport);

  • 3. Did you “scene.addChild()” your 3D Object?
    scene.addChild(cube);

  • 4. Did you render your scene?
    renderer.renderScene(scene, camera, viewport);

Just Getting Started
I hope you realize that this article barely touched the tip of the Papervision3D iceberg. The next article will cover the materials (sometimes known as textures) so you can make your 3D objects look nice and pretty.

Thanks
I’d like to thank all of the members of the Papervision3D team, everyone who has ever helped anyone on the Papervision3D mailing list, and the community for making such a wonderful open-source product:

  • Core team
  • Carlos Ulloa
  • John Grden
  • Ralph Hauwert
  • Tim Knip
  • Andy Zupko
  • Committer team
  • Mr.doob
  • De'Angelo Richardson
  • Tink
  • Seb-Lee Delisle
  • Contributors
  • Patrick Pietens
  • Ron Valstar

Comments

63 Comments

renkster said:

Great John,

thanks for this great article. its time for all that stuff packed in a book!
Web goes 3D. Thanks PV3D!


long said:

Thank you very much for your tutorial! But where can i get the API documentation of PV2.0(GreatWhite)?Can you give me a URL? http://www.papervision3d.org/docs/as3/is an old version DOC. Thank you! I can't visit the PV3D official blog!

Anonymous said:

Awesome tutorial! Thanks! Can't wait to see more from you!

@long

There is currently only the following temporary documentation until the official documentation is released by the pv3d team:

http://lostboys.epologee.net/papervision/greatwhite.doc/html/

Hope this helps.

Varun Shetty said:

nice article... will visit later for more detailed read n info.

shorty said:

very nice article! a book on this would be great.

Great article John, i would definetly like to see a book on the subject.

Chris said:

thank you, thank you, thank you!! Iv'e been waiting for something like this for ages!

mybeky said:

@John Lindquist
Thanks for the docs!

abym said:

There is also an updated documentation for the Effects branch here :
http://www.flashbookmarks.com/PV3D-Effects-DOC/

abym said:

Great article !
How about writing an entire book about Papervision ?

Antonis said:

Yes a book from O'Reilly it would be great help.

marcel said:

the community needs a book!!

Kurt said:

yeah dude, nice wrok, thx

Frederik said:

Nice article, however the resources and tutorials about pv3D getting better, I still would love to have a book about papervision3D.

marcos said:

Muchas gracias por el articulo.. pero queremos mas! Y una vez que el libro salga en ingles traduzcanlo al español pls!. Otra vez, muchas gracias

A said:

great stuff!!
finally some answers.. hope to see more of that and in that amazing explanatory style!
Book now!

matan poreh said:

truely John, you and the other members of the pv3d team should get a nobel prize, now if only you could pack it all into a good book....

Justin Velazquez said:

Great article, it was very helpful. It would be great to see a book on this!!!

Congrats John, really nice and needed article.
I think a book about this would be more than welcome.

Congrats John, really nice and needed article.
I think a book about this would be more than welcome.

anggie said:

I want the book! ;-)

Perxeo said:

Congrats John. We need this complet book just now. It´s about time would came a book like that.

Pedro Santos said:

Please, please, please publish the book!!! :)

Really, the info I find on this issue is so confused and complicated for a designer with average actionscript skills...

You got a buyer here if you publish the book.

Kevin Vertucio said:

Great!

When is the book coming out?!

We really need a book for PV3D. I already know of quite a few people who are interested!

Alek said:

Yes! A book of Pv3D will be so helpfull.

very nice as usual! i cant wait to see something more indepth! keep it up!

Frazko said:

book!! book!! book!!

vlady said:

BOOOOOOOOOOOOOOK!!! :)

Stoyan said:

Book! Book! Book!

Alex Ionescu said:

Please design the book with some exercises at the end of each chapter, so that it is easier to use as a textbook in game development classes.

November said:

Great article for me, thank you very much!

Jiri said:

Great article, is there any perspectives on a book coming out?

stelios said:

A book would be very useful

Anogar said:

Excellent base article. I've been checking out the tutorials on your site, I'd really love to see this info in a book.

colubroid said:

BOOK

Bryan Roman said:

A book would be friggin excellentl. In the meantime, maybe some more parts? Very informative!

april said:

A book would be great

Joel Hart said:

I think this article is really useful! I would love to have a book on papervision written once the GW version is out of alpha and beta

Peter said:

It would be cool if there was a Papervision 3D book on the market!

Marc Pelland said:

I have been hoping for a PV3D book for a while now, it would to see something. I think it would really push the technology forward.

Driveby said:

Where can we suggest new books to O'Reilly?

BOOK!BOOK!BOOK!BOOK!

Scott Bull said:

Fantastic. I'm not the most advanced actionscripter and yet your straight forward and detailed writing makes it easy for even me to understand.

Thanks so much! Can't wait for more, I'll be watching.

Jon said:

Great beginning article, can't wait to read more!

A book would be awesome!! Can't wait to see what happens with this.

Michael said:

WRITE A BOOK! I WILL BUY IT!!

Ralf said:

this is great stuff. Actually - OREILLY: why don't you do a series of high-qualified online articles available for small cost? Writing a book about this stuff seems to be ok, but in terms of speed, up-to-dateness and delivery to a huge online community who likes to cut-and-paste the code-bits it might just be an alternative...

rey said:

we need a book....with the source to the shark thing in it.

Stewey said:

Great article. Please do more and put me down for a pre-order of any future book!

João Cunha said:

Are you thinking to publish a book? if so give some nice examples not just for developers but also for designers using papervision. thanks for the wonderfull tutorials

boom said:

we need urgently a book of papervision3d

Stephen said:

So when's the book due?

Scott said:

I'd buy a book on this.

Matt said:

Ditto to all of the above comments on a book for pv3d - WE NEED A BOOK...

Zu said:

Excellent intro to GreatWhite, thanks John!

It was daunting to get started till I stumbled upon this. Hope you can add some more soon! :)

chris said:

Please print a book for of this. Thanks

GTC said:

Please can we have a Papervision Book, O'Reilly! Go crazy and make it Flex-oriented too.

bertziarra said:

awesome work!

it´s time to compile all the info in a from-zero-to-hero book!!

thanks John and hope to give thanks soon to OReilly for an excellent book :)

ricardo said:

When is book out?!?

Niels said:

Why wait an other day!
Move on O'reilly publish the book we are waiting for...

claudia said:

I want the book now! : )
Cheers form Uruguay

Ben W said:

i was just at FITC in toronto and asked Ralph Hauwert about a book... he didn't say much except for maybe. come on book!

Ron Velzeboer said:

Thanks for your article. Hopefully O'Reilly will publish a book on Papervision3D in combination with FLEX (/Flash). Can you have it ready tomorrow??? ;-P

Thanks!

Leave a comment


Type the characters you see in the picture above.

Tag Cloud

Related Books

Development Series

Get an overview of the tools and technologies that work together to allow developers to build Rich Internet Applications (RIAs) quickly and easily.

Anatomy of an Enterprise Flex RIA

Archives