Setting up Away3d with Flex 3

by Alejandro Santander 23

In this tutorial I will show you how to set up a simple away3d scene, taking advantage of FlexBuilder’s enhanced programming interface. I will also take advantage of the tutorial to introduce Flex to Flash developers who have never used it.

The result is THIS and you can download the source HERE.

Requirements:

Flex 3

Try/Buy

Pre Requisites:

– Intermediate programming skills.

– Some knowledge and understanding of the Actionscript 3 language.

– Basic principles of OOP (Object Oriented Programming).

Step 0

NOTE: you may skip this if you’re already familiar with Flex, and know what away3d is.

This tutorial deals with 2 technologies. Away3d and Flex. Before we start, let me say a few words about them:

Away3d is an open source 3d engine designed to boost flash based applications with powerful 3d capabilities. There are a few other3d engines out there, such as Papervision3d, Sandy3d, Alternativa3d and more, each with its pros and cons. I personally useAway3d, because I think its the most apt engine at this time.

Flex is something most developers that come from the Flash arena fear pretty badly. What is it?? Well, the thing is that Flex can be used in complement with Flash for Actionscript projects very easily, providing them with powerful programming tools.Let me list a few:

– When you create a new variable and introduce the “:” character, Flex lists all available object types, and if you press enter after you found the appropriate type, flex automatically creates the import statements for you. This is extremely handy, since you don’t need to remember what package an object belongs to, nor consult the API reference to write the appropriate import statement.

– Flex detects errors while you code! That is, you don’t need to compile your project to see if you made mistakes. This is simple magical.

– By pressing F1 over an object type, Flex takes you to the help section for that type, and if you press F3, it takes you right to the definition of that object. This dramatically accelerates the learning process of any given API.

Well, enough, lets get started. I just wanted to emphasize on the great help that Flex provides when dealing with AS3 development. Personally, once I got over the scary, “what the hell is flex” phase, I cant imagine working without it now.

Step 1

Download the FlexBuilder 3 fully functional 60 day trial from adobe and install it. You just need to create an Adobe account and download the trial from this link.

Then download the latest Away3d API.

Step 2

Create a folder somewhere in your hard drive that will work as your workspace for initial Away3d experimentation. This folder will be able to hold many flex projects.

Open flex, select file -> switch workspace, and point flex to the folder you just created.

Now, right click on the Flex Navigator panel, and select new “Actionscript Project”.

Figure 1

Once the dialog shows up, enter Away3dProject as the project name and click finish.

If you go back to your HD file browser and see the folder you created initially, you can notice that flex created an inner folder for this project. The Flex Navigator pretty much works like a regular file browser, listing the projects you have on that workspace and the files that conform them.

Step 3

Go to your away3d download in your file browser and copy the folder in it named away3d. Come back to the flex navigator, right click on the Away3dProjectfolder icon and paste.

Figure 2

That’s it! Flex is ready to work with the Away3d engine.

Step 4

Its time to code. Right click the Away3dProject folder icon in the Flex Navigator again, and choose new “Actionscript class”, name itAway3dScene and click finish. This should automatically open the file in the coding area, to the right of the Flex Navigator.

The class should extend Sprite, since this class will contain all away3d stuff and be treated as any other graphic object. Start by placing this code in it:

package
{
     import flash.display.Sprite;

     public class Away3dScene extends Sprite
     {
           public function Away3dScene()
           {
                graphics.beginFill(0xFF0000);
                graphics.drawRect(0, 0, 100,  100);
                graphics.endFill();
           }
     }
}

Step 5

Double click the other .as file in the navigator named Away3dProject.as. Notice that this one has a little green triangle attached to its icon. This simply states that when you compile the application, this is the base class, what’s known in Flash as the Document class.

Place this code in it:

package
{
     import flash.display.Sprite;
     import flash.display.StageScaleMode;
     import flash.display.StageAlign;

     public class Away3dProject extends Sprite
     {
           public function Away3dProject()
           {
                stage.scaleMode =  StageScaleMode.NO_SCALE;
                stage.align =  StageAlign.TOP_LEFT;

                var scene:Sprite = new  Away3dScene();
                addChild(scene);
           }
     }
}

Lines 11 to 12 simply set a couple of stage properties that allow us to be in control of how the stage is scaled and positioned in the browser, and lines 4 to 5 provide the appropriate import statements for this.

Lines 14 to 15, create an instance of the Away3dScene (which is a Sprite!) and add it to the stage.

Step 6

Above the Flex Navigator is a little green button with a white play icon in it. This is what you press to compile the application.Go ahead and compile it. Flex will open your default web browser and run the demo in it.

Once you compiled, you should simply see a red square, at the top left corner of the browser.

Figure 3

Hmm… What? Well, I just wanted to show you how a class that will be holding all the 3d content can be a Sprite itself, and you can treat it as such, 100%.Alright, delete lines 9 through 11 of Away3dScene.as and lets get started with the 3d stuff.

Step 7

Now, lets create an event listener on the constructor that will call the initialization of the scene when the instance of Away3dScene is added to the stage. The initialization will be a method called “init()”, consisting of two sub methods and an event listener registration for enterframe events.

In Away3dScene.as, modify the constructor and add the other methods under it as follows:

public  function Away3dScene()
{
     addEventListener(Event.ADDED_TO_STAGE,  init, false, 0, true);
}

private  function init(evt:Event):void
{
     removeEventListener(Event.ADDED_TO_STAGE,  init);

     init3dScene();
     init3dObjects();
     addEventListener(Event.ENTER_FRAME,  renderScene);
}

private  function init3dScene():void
{

}

private  function init3dObjects():void
{

}

private  function renderScene(evt:Event):void
{

}

Make sure that as you type “evt:Eve…”, press enter when the flex auto complete dialogue box shows “Event”on one of the function declaration parameters of “init()” or “renderScene()”. Doing this will ensure that Flex creates the appropriate import statements automatically.

Figure 4

Now, why wait until the instance is added to the stage to call the “init()” method? Its a simple matter actually: In “init3dScene()” we will set up the core of the 3d environment, and when doing this, we need to know the dimensions of the stage… and we wouldn’t be able to know this if the sprite (or Away3dScene instance) wasn’t yet added to the stage! In “init3dObjects()”, as the name of the method makes it pretty obvious, we will create a bunch of objects and place them inside the 3d environment.

Step 8

The 3d scene will have 3 main elements: a Scene3D object, a Camera3D object, and View3D. These are all very important classes within the Away3d API. Declare instances of these as private variables in Away3dScene.as:

private  var scene:Scene3D;
private  var camera:Camera3D;
private  var view:View3D;

Make sure you rewrite this and not just paste it to make sure that Flex imports the correct classes. Don’t worry, you’ll get used to this ;D

Step 9

Lets build the 3d environment. Place the following code within the “init3dScene()” method:

scene  = new Scene3D();

camera  = new Camera3D();
camera.zoom  = 10;
camera.focus  = 200;
camera.z  = -3000;
camera.lookAt(new  Number3D(0, 0, 0));

view  = new View3D();
view.scene  = scene;
view.camera  = camera;
view.clip  = new RectangleClipping(-stage.stageWidth/2, -stage.stageHeight/2,  stage.stageWidth/2, stage.stageHeight/2);
view.x  = stage.stageWidth/2;
view.y  = stage.stageHeight/2;
addChild(view);

Now, lets go over those lines slowly. First, we created “scene”, an instance of Scene3D. This is actually the container of all the objects of the 3d environment. Those of you who are familiar with 3D, it is the main node of the environment. Then, we create a camera as an instance of Camera3D. This is pretty intuitive; its the object we will move around and that will represent us, the spectator, inside the 3denvironment. Notice the parameters of the camera that are set immediately after its initialization. If you type “camera.”, Flex will automatically bring up the auto complete dialogue box and show you all available methods and parameters that you can use for this object, so, if you want to see if the camera has a “y” property, type “camera.” And see if it shows up… Its pretty handy, and we’ve never looked at the API reference yet.

Finally, we create an instance of View3D. The view will represent the graphical output of the situation of our camera looking at our scene or environment. It is an object that extends sprite, and that represents what we see.The first 2 parameters of the view are the scene and the camera. What we are doing here is just telling it what camera and what scene

It will refer to.

Then, we clip and position the view. The clipping part is telling the view which are its limits in x, y, width and height, and hence setting the center of coordinates. The positioning part just places the view as if it were a normal sprite.

Oh, and of course, the view is added to the display, since it is a graphical element after all.

Note: To avoid confusion, Away3dScene (our class) and View3D both extend Sprite, Scene3D doesn’t! Away3dScene is just a class that we are using to place all the 3d stuff in, it has nothing to do with Scene3D. Sorry about that, I don’t know why but I see I got used to naming things this way.

Step 10

So, the 3d environment is set. Lets put some stuff in it. I’ve decided to make a little nested loop structure, in order to make this tutorial a little fancier, but don’t mind this, what really matters is the creation of the 3d objects:

var i:uint;
var j:uint;
var  k:uint;
var  spacing:Number = 250;
var  quantity:uint = 3;
var  offset:Number = (quantity-1)*spacing/2;
for(i  = 0; i<quantity; i++)
{
     for(j = 0; j<quantity; j++)
     {
           for(k = 0; k<quantity; k++)
           {
                var cube:Cube = new Cube();
                cube.x = i*spacing - offset;
                cube.y = j*spacing - offset;
                cube.z = k*spacing - offset;
                scene.addChild(cube);
           }
     }
}

We are creating the cube instance and then adjusting its parameters the same way as we created the scene and camera before. To see what kind of primitives you can create with Away3d, bookmark the away API reference http://away3d.com/livedocs/, check out the primitives package and have the API handy for future experiments.

Step 11

So, what’s left?

We just need to implement on more thing and were done. Add this line at the end of the “init()” method:

addEventListener(Event.ENTER_FRAME,  renderScene);

…and add this method at the end of the class

private  function renderScene(evt:Event):void
{
     camera.x = 3*(mouseX - stage.stageWidth/2);
     camera.y = 3*(mouseY -  stage.stageHeight/2);
     camera.lookAt(new Number3D(0, 0, 0));

     view.render();
}

We’ve just indicated that after initializing the scene, and then the objects in it, the application should call the “renderScene()” method on enterframe, that is every frame of course.

In “renderScene()”, we will position the camera according to the position of the mouse over the stage, and of course, render the view.

The render() method of a View3D object is what calls all the 3d transformation algorithms of the away3d engine and show us the display output in a view Sprite.

Now compile… and voila!! That’s it.

Final words.

Pretty nice huh? If you like it, there are some obvious steps you can take from here. You can look on the Away3d Blog for lots of info, samples and

Tutorials, or you could sign up to the mailing list to see a vivid community learning and expanding the away3d.Away3d can do pretty advanced stuff, specially when you are ready to play with materials on your objects, or importing 3d models from external programs. Ill be writing more tutorials about this when I can.

Hope its helpful…

Enjoy!

Complete Code

Away3dProject.as

package
{
     import flash.display.Sprite;
     import flash.display.StageScaleMode;
     import flash.display.StageAlign;

     publicclass Away3dProject extends Sprite
     {
           publicfunction Away3dProject()
           {
                stage.scaleMode =  StageScaleMode.NO_SCALE;
                stage.align =  StageAlign.TOP_LEFT;

                var scene:Away3dScene = new Away3dScene();
                addChild(scene);
           }
     }
}

Away3dScene.as

package
{
     import away3d.cameras.Camera3D;
     import away3d.containers.Scene3D;
     import away3d.containers.View3D;
     import away3d.core.math.Number3D;
     import away3d.core.render.RectangleClipping;
     import away3d.primitives.Cube;

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

     publicclass Away3dScene extends Sprite
     {
           privatevar scene:Scene3D;
           privatevar camera:Camera3D;
           privatevar view:View3D;

           publicfunction Away3dScene()
           {
                addEventListener(Event.ADDED_TO_STAGE,  init, false, 0, true);
           }

           privatefunction init(evt:Event):void
           {
                removeEventListener(Event.ADDED_TO_STAGE,  init);

                init3dScene();
                init3dObjects();
                addEventListener(Event.ENTER_FRAME,  renderScene);
           }

           privatefunction init3dScene():void
           {
                scene = new Scene3D();

                camera = new Camera3D();
                camera.zoom = 10;
                camera.focus = 200;
                camera.z = -3000;
                camera.lookAt(new Number3D(0, 0, 0));

                view = new View3D();
                view.scene = scene;
                view.camera =  camera;
                view.clip = new RectangleClipping(-stage.stageWidth/2, -stage.stageHeight/2,  stage.stageWidth/2, stage.stageHeight/2);
                view.x =  stage.stageWidth/2;
                view.y =  stage.stageHeight/2;
                addChild(view);
           }

           privatefunction init3dObjects():void
           {
                var i:uint;
                var j:uint;
                var k:uint;
                var spacing:Number = 250;
                var quantity:uint = 3;
                var offset:Number = (quantity-1)*spacing/2;
                for(i = 0; i<quantity; i++)
                {
                     for(j = 0; j<quantity; j++)
                     {
                           for(k = 0; k<quantity; k++)
                           {
                                var cube:Cube = new Cube();
                                cube.x  = i*spacing - offset;
                                cube.y  = j*spacing - offset;
                                cube.z  = k*spacing - offset;
                                scene.addChild(cube);
                           }
                     }
                }
           }

           privatefunction renderScene(evt:Event):void
           {
                camera.x =  3*(mouseX - stage.stageWidth/2);
                camera.y =  3*(mouseY - stage.stageHeight/2);
                camera.lookAt(new Number3D(0, 0, 0));

                view.render();
           }
     }
}

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>