Sealyu

--- 博客已迁移至: http://www.sealyu.com/blog

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  618 随笔 :: 87 文章 :: 225 评论 :: 0 Trackbacks

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".

Away3D Library

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.

References

posted on 2008-11-12 10:05 seal 阅读(601) 评论(0)  编辑  收藏 所属分类: Flex+ActionScript

只有注册用户登录后才能发表评论。


网站导航: