Away3D Programming Tutorials - Getting Started
Learn how to get started with the Away3D Flash 3D engine with this detailed, step by step tutorial. Demo and source code included.
VIEW THE DEMO
DOWNLOAD THE CODE
Away3D is a powerful Flash 3D engine which started life as a spin off from the Papervision Flash 3D engine. Since then it has taken on a life of its own, and is currently one of the few 3D engines available for Flash that can make use of the new features of Flash Player 10.
In this tutorial I will be showing you how to get a basic Away3D program up and running. This will be the first in a series of tutorials, and as such we will lay down a lot of foundation here that we can build on. This means that while the outcome will be quite simple, we will be creating a few classes as a result.
The program itself will be conceptually split into two areas: the "engine" and the "application". The reason for this is that there will be a great deal of code that is used to create, run and cleanup the Away3D "engine", and for the most part this code will be common amongst the tutorials. On the other hand the "application" will change significantly between tutorials. By keeping the code that makes up these two areas separate we can define a reusable base that will be used with all the coming tutorials, and it will also help isolate the code that achieves the result of the tutorial from the boilerplate code that runs the Away3D engine.
The first class we need to create is the EngineManager. As the name suggests this class will deal with creating, running and destroying the Away3D engine.
If you click the link above you can see that there is actually quite a bit of code. The reason for this is that we are creating the EngineManager as a Flash Component (see the Adobe documentation here). By extending the UIComponent class and overriding a number of key functions we can create a class that can be dropped onto a Flash or Flex application by someone with no knowledge of the underlying code.
One of the functions of the EngineManager will be to allow any class extending the BaseObject class (more on that later) to update itself before a frame is rendered to the screen. For this we need to maintain a collection of BaseObjects, which is where the baseObjects, newBaseObjects and removedBaseObjects properties come in. The baseObjects property holds all the currently active BaseObjects, while newBaseObjects and removedBaseObjects contain BaseObjects that were just added or removed from the system.
The reason why we don't just add and remove objects from baseObjects directly is that it is almost always a bad idea to modify a collection while you are lopping over it. Take a look at line 158. See how we loop over the baseObjects collection and call enterFrame on each BaseObject. If we added and removed an instance of a BaseObject class from baseObjects directly, and the BaseObject we called enterFrame on was to create a new BaseObject or remove itself from the system during this call we would find ourselves with an inconsistent collection. You might find the for each loop ends up skipping a record, or visits a record twice. In fact a lot of programming languages expressly forbid this sort of collection modification during a loop by throwing an execption, and even in those languages that don't its best avoided.
Once you understand the reason for maintaining separate collections for newly added and removed BaseObjects you can explain a lot of the code in the EngineManager class. The addBaseObject and removeBaseObject functions add a BaseObject to the newBaseObjects and removedBaseObjects collections respectively, while the insertNewBaseObjects and removeDeletedBaseObjects functions are called (from the onEnterFrame function) to synchronise the main baseObjects collection with the added and removed BaseObjects.
EngineManager contains 6 functions that are used in the lifecycle of a Flash/Flex component. Four of these are detailed in the adobe documentation, and I'll run through them here.
The measure function is used to define the minimum and default size of the control. This is pretty straight forward as all we need to do is assign 4 values to the underlying UIComponent measuredMinWidth, measuredMinHeight, measuredHeight and measuredWidth properties.
The updateDisplayList function is called to size and position the children of the control. In this case our only child element is the Away3D engine, specifically the View3D object. All we do here is resize the view property to reflect the changes in the size of the EngineManager control.
The commitProperties function is called to allow the control to apply any property changes that have been made. The idea behind this is that properties can and will be changed in any order, but may have to be applied or processed in a specific order. Even though EngineManager doesn't expose any properties that can be changed, the code here is set to re-initialise the ApplicationManager (more on that class later), which in effect restarts the application.
The createChildren function is called when the control is expected to create any of its children. As mentioned before the only child of the EngineManager control is the Away3D engine, however we don't create the engine just yet. The Away3D engine makes numerous references to the stage property, which is null until the ADDED_TO_STAGE event has been triggered. So we attach the createChildrenEx function to this event, and create the Away3D engine then. Likewise we use the REMOVED_FROM_STAGE to call shutdown, which will clean up the Away3D engine.
The updateDisplayList, commitProperties, createChildren and measure functions all have functionality define by the UIComponent class. There are two more functions, shutdown and createChildrenEx, that also play an important role.
As noted above the createChildrenEx function is where the Away3D engine it actually started up. For this simple example we only need two Away3D classes: Camera3D and View3D. The Camera3D class, which we assign to the cam property, is the camera through which we look into the Away3D world. The View3D class, which we assign to the view property, takes care of rendering the 3D world onto your 2D monitor. The actual code for initialising the Away3D engine isn't more than a few lines. We create a new instance of the Camera3D class, and then a new instance of the View3D class. We then define which sort of renderer we want (the basic one in this case), and add the View3D as a child element of the EngineManager control.
In addition to initialising the Away3D engine, the createChildrenEx function also takes create of creating a new ResourceManager and ApplicationManager, and attaching the onEnterFrame function to the ENTER_FRAME event.
The shutdown function is used to clean up the Away3D engine. "Cleaning up" essentially means running through the createChildrenEx in reverse removing children where the have been added, and setting to null properties that had been initialised.
Finally in the onEnterFrame function we manage our render loop. It's here that we determine how much time has passed sine the last frame was rendered, synchronise the baseObjects collection, call enterFrame on all of our BaseObjects, and then finally render the frame to the screen with view.render().
The sole purpose of the BaseObject class is to allow an extending class to update itself when enterFrame is called. The startupBaseObject and shutdown functions are called to add the BaseObject to the EngineManagers collection and remove it. Then we have the enterFrame function, which is empty. The enterFrame function is expected to be overridden by extending classes.
The MeshObject class extends BaseObject and adds the ability for an object to have a 3D mesh representation on the screen. It includes a function called startupColladaModelObject which takes a Collada XML document, loads it as a mesh, textures it and adds the result to the Away3D scene.
The RotatingModel class is an example of how you would use the MeshObject (and therefore the BaseObject) class. RotatingModel extends MeshObject, and then overrides the enterFrame function to rotate the model around by a small amount every frame. As you can see there is very little effort involved to have the RotatingModel load a model, add it to the scene, and then perform updates every frame: the majority of the work has been taken care of thanks to the MeshObject and BaseObject classes.
The ResourceManager is used as an area to hold any resources used by the application. One of the problems you will face as a developer is the Flash security sand box, where local resources can't be loaded from a SWF located on a web server, and web resources can't be loaded from a local SWF (not without some mucking around anyway). The ResourceManager makes use of resource embedding through the Embed tag, which essentially takes a file on your development PC and embeds the data into the final SWF file. This makes it easy to distribute the resulting Flash SWF file because all the data is included in one file, and it overcomes any security issues when loading resources.
As you can see we embed two files. The fighter1.dae file is the Collada mesh that will be displayed on the screen, and the sf-02.jpg file will be used to texture the mesh.
The loadResources function is used to load the resources. The ConvertToXML function takes the embedded fighter1.dae file, which is embedded as a ByteArray, and converts it back into an XML object.
The ApplicationManager class defines the code that makes use of all the other classes we have created to actually produce the desired outcome. In this case the desired outcome is quite simple: we just want to create an instance of the RotatingMesh class. Because of the work we put into the previous classes the only thing ApplicationManager has to do is create a new instance of the RotatingMesh, initialise it with a call to startupRotatingMesh, and reposition it slightly on the screen.
Finally we have the GettingStarted.mxml file. As you can see we add the EngineManager like it was just another control like a button or a textbox. Because we have implemented the nessessary functions to make EngineManager a Flex component this is all the code that is required.
We have covered a lot of code here for such a simple program, but creating this initial framework does save a lot of time later on, so it is worth the extra initial effort.
Find more Flash tutorials here.

Note
This code assumes you are using Flex Builder 3 and have already targetting the Flash Player 10 platerform. See http://opensource.adobe.com/wiki/display/flexsdk/Targeting+Flash+Player+10 for more deatils.
-
Away3D Programming Tutorial - Effects
| By mcasperson | in Programming
See how you can add the standard Flash filters to any Away3D object to easily create advanced effects. Demo and sou...
-
Away3D Programming Tutorial - Primitives
| By mcasperson | in Programming
See how easy it is to use the build in primitive shapes supplied with Away3D. Demo and source code included....
-
Away3D Programming Tutorial - Environment Material
| By mcasperson | in Programming
See how to use the EnviroBitmapMaterial to create a real time reflective look in Away3D. Demo and source code inclu...
-
Away3D Programming Tutorial - Mouse Interaction
| By mcasperson | in Programming
Learn how to respond to mouse events in Away3D. Demo and source code included....
-
Javascript functions for : trim, right trim, left trim, no Apostrophe, is Empty , is Digit , VarChar To Number , is integer , check Is Zero , Get Que | By xxris | in Programming
Javascript functions for : trim, right trim, left trim, no Apostrophe, is Empty , is Digit , VarChar To Number , i...
-
How to access and use a Window's command line | By MaxwellPayne | in Programming
Learn about the Window's command line in DOS and how to use it....
-
Zen Cart Development – Improved Open Source for Shopping Cart | By dainawill | in Programming
Main task of every online merchant is not only to launch the online store successfully but to keep it on the same l...
-
How to Learn to Program Your Computer | By dsj8760 | in Programming
This article is about learning to program a computer. It is a general article giving tips on how to learn about pro...
-
Jailbroken iPhones get RickRolled | By explorer | in Programming
First iPhone worm, attacks via SSH and does the classic rick roll gag on the user....
-
Away3D Programming Tutorial - Environment Material | By mcasperson | in Programming
See how to use the EnviroBitmapMaterial to create a real time reflective look in Away3D. Demo and source code inclu...
-
Away3D Programming Tutorial - Primitives | By mcasperson | in Programming
See how easy it is to use the build in primitive shapes supplied with Away3D. Demo and source code included....
-
Away3D Programming Tutorial - Mouse Interaction | By mcasperson | in Programming
Learn how to respond to mouse events in Away3D. Demo and source code included....
-
Away3D Programming Tutorial - Effects | By mcasperson | in Programming
See how you can add the standard Flash filters to any Away3D object to easily create advanced effects. Demo and sou...
-
Papervision 3D Programming Tutorial - Creating a Papervision Component | By mcasperson | in Programming
See how Papervision can be packaged into a SWC Flash component, which allows you to drag and drop Papervision into ...








You are absolutely right, the resizing code needs to be fixed up. I'll update the source code when I get a chance. Thanks for the feedback.
You are an absolute GOD for publishing this! This is the first time a getting started tutorial has really helped structure a project. Usually when I learn something new I am so focused on learning the material that I can't also focus on good abstraction and OO technique. Thanks for laying out the beginners stuff in such a great fasion! Just one simple update for you: If you change the width and height of the View3D viewport it skewes the image, as the container is updated it's probably more logical to update a clipping area (at least that was the first thing I ran into). In updateDisplayList() swap out the width/heigh update for: view.clipping = new RectangleClipping({minX:-this.width/2, minY:-this.height/2, maxX:this.width/2, maxY:this.height/2 }); Thanks again for the truly superb tutorial - best I've ever seen! I can't wait to get through the rest of them!