Here on the blog we are always looking for new technologies to play
around with and I seem to have found one that I am going to be spending
some time playing with, Away3D (a
3D Flash engine). Personally, I have spent a good deal of my time in
the last couple of years looking at 3D, whether it be on the desktop or
web, and it is exciting to finally play around with 3D in Flex. The
goal of this tutorial is simple, to get you acquainted with Away3D and
get a spinning cube rendered on the screen. This is going to be easier
than you think.
|
First we are going to take a look at the small demo running below.
As you can see there isn't much to it. We have a panel and inside that
we have a spinning cube. One item that isn't noticeable is that we use
a UIComponent to hold our 3D scene. I will explain why we do this more later. I created the texture that is being used in Paint.Net
and will not go over how it was built in this tutorial. But for now
just take a second and stare at the nice spinning cube. You can look at
and get the source code for the demo here.
|
Here on the blog we are always looking for new technologies to play
around with and I seem to have found one that I am going to be spending
some time playing with, Away3D (a
3D Flash engine). Personally, I have spent a good deal of my time in
the last couple of years looking at 3D, whether it be on the desktop or
web, and it is exciting to finally play around with 3D in Flex. The
goal of this tutorial is simple, to get you acquainted with Away3D and
get a spinning cube rendered on the screen. This is going to be easier
than you think.
First we are going to take a look at the small demo running below.
As you can see there isn't much to it. We have a panel and inside that
we have a spinning cube. One item that isn't noticeable is that we use
a UIComponent to hold our 3D scene. I will explain why we do this more later. I created the texture that is being used in Paint.Net
and will not go over how it was built in this tutorial. But for now
just take a second and stare at the nice spinning cube. You can look at
and get the source code for the demo here.
To begin, we are going to step out and grab the latest Away3D source
code and compile it into a library we can use. Step one, download the
latest source code from here
- as of this post they are on version 1.9.4. Once you have it
downloaded, extract the source code somewhere you can remember. The
next step is to create a Flex Library Project, I did this in Flex
Builder 3. This can be performed by right clicking in the "Flex
Explorer" area and go to new > Flex Library Project. Go ahead and
give it a name, I used Away3D. Now click "Finish".
You
should now have a project in your explorer for Away3D. Copy the source
code from wherever you extracted it to the project. You should have two
root folders, away3d and nochump. With any
luck your project looks similar to the one on the right. You should get
a compile error though mentioning that you don't have any source code
selected. This is solved easily, open up the properties for the project
(right click the project and go to properties) and once the window
opens go to "Flex Library Build Path". The "Classes" tab should be open
and go ahead and check both root folders then click "OK". Consequently
you should have your bin folder fill up with your library swc.
Following the compilation of our library we can now get started
actually building the demo. Create a new Flex Project and name it.
Afterwords, you need to copy your Away3D library swc to the libs folder
- this ensures that Flex Builder will handle adding to the project
references. In our main application file we are going to add a panel
that has 100% width and height, I also added a title. This code is illustrated below.
Next comes the more difficult part - we need to get our 3D view
setup. We are going to create a custom component that will handle all
the 3D stuff. I actually created a custom Actionscript class named FlexView3D and it extends UIComponent. The reason we extend UIComponent is because the View3D class in Away3D is based on a Sprite and the only Flex component that can add a Sprite as a child is UIComponent. The following code is the base of our class and component.
package
{
import mx.core.UIComponent;
public class FlexView3D extends UIComponent
{
public function FlexView3D()
{
super();
}
}
}
To finish up the main application we add our FlexView3D to our panel. This results in following complete code for the main application.
Getting back to our custom class, we start by adding a private variable for our 3D view which is of type View3D. Now we override the protected function createChildren
this is where we are going to create the view and add it to our
component. You can learn more about creating custom Actionscript
components here. The function lies below.
private var view:View3D;
override protected function createChildren():void
{
super.createChildren();
if(!this.view)
{
this.view = new View3D();
this.view.camera.moveTo(new Number3D(0, 0, -1500));
this.view.camera.lookAt(new Number3D(0, 0, 0));
}
this.addChild(this.view);
}
You can see above we check to make sure the view is not already
created and then create a new one. The next two lines initialize the 3D
camera. It moves the camera to a far away point. This is where the
coordinate system comes in, we use +y as up and +z is into the screen.
We also tell the camera to look at the center of the screen 0, 0, 0.
One item to note is that we have not moved the view yet, really we need
to move the view to the middle because its position is used as 0, 0, 0.
This centering is done in another function. We override the updateDisplayList function and in there we are guaranteed the size of the overall component is set so we center our 3D view.
override protected function updateDisplayList(
unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(this.width / 2 != this.view.x)
this.view.x = this.width / 2;
if(this.height / 2 != this.view.y)
this.view.y = this.height / 2;
}
Getting the cube added is the next item in the agenda. This will not
be hard either, Away3D has taken the hard graphics pieces out of the
equation. We add another private variable for the cube, then add
creation and initialization code for it in the createChildren
function. This again checks to make sure it is not created yet then
creates a cube with a couple of init arguments, one for the name and
one for size. We also add a material to the cube (a material defines
the look), in this case we add a BitmapFileMaterial which
takes a path to an image. It uses that image as the texture for each
side. We then add our cube to the scene in the view. The following is
added to the createChildren function.
if(!this.sotcCube)
{
this.sotcCube = new Cube({name: "cube", size: 250});
this.sotcCube.material =
new BitmapFileMaterial("sotc.jpg");
}
this.view.scene.addChild(this.sotcCube);
There is only one thing left to do, and that is actually spinning
the cube and render the scene. We are going to setup a render loop by
hooking into the ENTER_FRAME event on our component. We do this in the constructor of the class which updates this to the below code.
public function FlexView3D()
{
super();
this.addEventListener(Event.ENTER_FRAME, onFrameEnter);
}
Our event listener onFrameEnter does a couple of things. It checks to see if the view and the view's stage have been created. If both exist then we update the rotationX, rotationY, and rotationZ of the cube which will make it spin. Finally we call render on the view. This completes our component and now we have a spinning 3D cube in Flex. The entire class code is below.
package
{
import away3d.core.material.BitmapFileMaterial;
import away3d.core.math.Number3D;
import away3d.core.scene.View3D;
import away3d.objects.Cube;
import flash.events.Event;
import mx.core.UIComponent;
public class FlexView3D extends UIComponent
{
private var view:View3D;
private var sotcCube:Cube;
public function FlexView3D()
{
super();
this.addEventListener(Event.ENTER_FRAME, onFrameEnter);
}
override protected function createChildren():void
{
super.createChildren();
if(!this.view)
{
this.view = new View3D();
this.view.camera.moveTo(new Number3D(0, 0, -1500));
this.view.camera.lookAt(new Number3D(0, 0, 0));
}
this.addChild(this.view);
if(!this.sotcCube)
{
this.sotcCube = new Cube({name: "cube", size: 250});
this.sotcCube.material =
new BitmapFileMaterial("sotc.jpg");
}
this.view.scene.addChild(this.sotcCube);
}
override protected function updateDisplayList(
unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(this.width / 2 != this.view.x)
this.view.x = this.width / 2;
if(this.height / 2 != this.view.y)
this.view.y = this.height / 2;
}
private function onFrameEnter(event:Event):void
{
if(this.view && this.view.stage)
{
this.sotcCube.rotationX += .7;
this.sotcCube.rotationY += .5;
this.sotcCube.rotationZ += .4;
this.view.render();
}
}
}
}
Well I hope you all feel that we accomplished our goal for this
tutorial. Plan on seeing more posts concerning Away3D in the future
here at Switch on the Code. As always, if you have any questions,
concerns, or just plain quips about the tutorial feel free to drop a
comment.
References
Away3DAway3D DocumentationArno MandersLabs@flexcoders2.0 | Rich Internet Experience
To begin, we are going to step out and grab the latest Away3D source
code and compile it into a library we can use. Step one, download the
latest source code from here
- as of this post they are on version 1.9.4. Once you have it
downloaded, extract the source code somewhere you can remember. The
next step is to create a Flex Library Project, I did this in Flex
Builder 3. This can be performed by right clicking in the "Flex
Explorer" area and go to new > Flex Library Project. Go ahead and
give it a name, I used Away3D
. Now click "Finish".
You
should now have a project in your explorer for Away3D. Copy the source
code from wherever you extracted it to the project. You should have two
root folders, away3d
and nochump
. With any
luck your project looks similar to the one on the right. You should get
a compile error though mentioning that you don't have any source code
selected. This is solved easily, open up the properties for the project
(right click the project and go to properties) and once the window
opens go to "Flex Library Build Path". The "Classes" tab should be open
and go ahead and check both root folders then click "OK". Consequently
you should have your bin
folder fill up with your library swc.
Following the compilation of our library we can now get started
actually building the demo. Create a new Flex Project and name it.
Afterwords, you need to copy your Away3D library swc to the libs folder
- this ensures that Flex Builder will handle adding to the project
references. In our main application file we are going to add a panel
that has 100%
width and height, I also added a title. This code is illustrated below.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="500" height="400">
<mx:Panel width="100%" height="100%" title="Our 3D Canvas"
backgroundColor="#D1F0FF">
</mx:Panel>
</mx:Application>
Next comes the more difficult part - we need to get our 3D view
setup. We are going to create a custom component that will handle all
the 3D stuff. I actually created a custom Actionscript class named FlexView3D
and it extends UIComponent
. The reason we extend UIComponent
is because the View3D
class in Away3D is based on a Sprite
and the only Flex component that can add a Sprite
as a child is UIComponent
. The following code is the base of our class and component.
package
{
import mx.core.UIComponent;
public class FlexView3D extends UIComponent
{
public function FlexView3D()
{
super();
}
}
}
To finish up the main application we add our FlexView3D
to our panel. This results in following complete code for the main application.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:local="*" layout="absolute" width="500" height="400">
<mx:Panel width="100%" height="100%" title="Flex 3D View"
backgroundColor="#D1F0FF">
<local:FlexView3D width="100%" height="100%" />
</mx:Panel>
</mx:Application>
Getting back to our custom class, we start by adding a private variable for our 3D view which is of type View3D
. Now we override the protected function createChildren
this is where we are going to create the view and add it to our
component. You can learn more about creating custom Actionscript
components here. The function lies below.
private var view:View3D;
override protected function createChildren():void
{
super.createChildren();
if(!this.view)
{
this.view = new View3D();
this.view.camera.moveTo(new Number3D(0, 0, -1500));
this.view.camera.lookAt(new Number3D(0, 0, 0));
}
this.addChild(this.view);
}
You can see above we check to make sure the view is not already
created and then create a new one. The next two lines initialize the 3D
camera. It moves the camera to a far away point. This is where the
coordinate system comes in, we use +y as up and +z is into the screen.
We also tell the camera to look at the center of the screen 0, 0, 0.
One item to note is that we have not moved the view yet, really we need
to move the view to the middle because its position is used as 0, 0, 0.
This centering is done in another function. We override the updateDisplayList
function and in there we are guaranteed the size of the overall component is set so we center our 3D view.
override protected function updateDisplayList(
unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(this.width / 2 != this.view.x)
this.view.x = this.width / 2;
if(this.height / 2 != this.view.y)
this.view.y = this.height / 2;
}
Getting the cube added is the next item in the agenda. This will not
be hard either, Away3D has taken the hard graphics pieces out of the
equation. We add another private variable for the cube, then add
creation and initialization code for it in the createChildren
function. This again checks to make sure it is not created yet then
creates a cube with a couple of init arguments, one for the name and
one for size. We also add a material to the cube (a material defines
the look), in this case we add a BitmapFileMaterial
which
takes a path to an image. It uses that image as the texture for each
side. We then add our cube to the scene in the view. The following is
added to the createChildren
function.
if(!this.sotcCube)
{
this.sotcCube = new Cube({name: "cube", size: 250});
this.sotcCube.material =
new BitmapFileMaterial("sotc.jpg");
}
this.view.scene.addChild(this.sotcCube);
There is only one thing left to do, and that is actually spinning
the cube and render the scene. We are going to setup a render loop by
hooking into the ENTER_FRAME
event on our component. We do this in the constructor of the class which updates this to the below code.
public function FlexView3D()
{
super();
this.addEventListener(Event.ENTER_FRAME, onFrameEnter);
}
Our event listener onFrameEnter
does a couple of things. It checks to see if the view and the view's stage have been created. If both exist then we update the rotationX
, rotationY
, and rotationZ
of the cube which will make it spin. Finally we call render
on the view. This completes our component and now we have a spinning 3D cube in Flex. The entire class code is below.
package
{
import away3d.core.material.BitmapFileMaterial;
import away3d.core.math.Number3D;
import away3d.core.scene.View3D;
import away3d.objects.Cube;
import flash.events.Event;
import mx.core.UIComponent;
public class FlexView3D extends UIComponent
{
private var view:View3D;
private var sotcCube:Cube;
public function FlexView3D()
{
super();
this.addEventListener(Event.ENTER_FRAME, onFrameEnter);
}
override protected function createChildren():void
{
super.createChildren();
if(!this.view)
{
this.view = new View3D();
this.view.camera.moveTo(new Number3D(0, 0, -1500));
this.view.camera.lookAt(new Number3D(0, 0, 0));
}
this.addChild(this.view);
if(!this.sotcCube)
{
this.sotcCube = new Cube({name: "cube", size: 250});
this.sotcCube.material =
new BitmapFileMaterial("sotc.jpg");
}
this.view.scene.addChild(this.sotcCube);
}
override protected function updateDisplayList(
unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(this.width / 2 != this.view.x)
this.view.x = this.width / 2;
if(this.height / 2 != this.view.y)
this.view.y = this.height / 2;
}
private function onFrameEnter(event:Event):void
{
if(this.view && this.view.stage)
{
this.sotcCube.rotationX += .7;
this.sotcCube.rotationY += .5;
this.sotcCube.rotationZ += .4;
this.view.render();
}
}
}
}
Well I hope you all feel that we accomplished our goal for this
tutorial. Plan on seeing more posts concerning Away3D in the future
here at Switch on the Code. As always, if you have any questions,
concerns, or just plain quips about the tutorial feel free to drop a
comment.