Notes for learning Flex 4. The goal is to use Away3D as the container for Flex 4 components, so that the 3D elements can affect Flex 4 components (e.g., rotating a cube with Flex 4 version of VideoPlayer on each side).


Phase 3


Bringing in an MD2 model.
Not the easiest process to find documentation on, but at least it is fairly simple once you get it. My main reference for this was this website (he’s an excellent designer, by the way). However, the information is from an older version of Away3D, and doesn’t work right out of the box. So I picked out the parts that worked, and re-worked the Actionscript code to plop the MD2 model in place of the rotating box. (The code will follow below.)

Notes about the code:
Note that the MD2 model is embedded. I am dynamically loading the image file, however, since it was easier to just replace the old texture with the new. Also, I have removed the animation, and left only a simple call to the first frame, since Away3D doesn’t seem to be loading fully until frame 1 – I will probably do more research on that in a little bit. I am using the free MD2 model from this website: http://telias.free.fr/models_md2_menu.html. I chose the horse model, and it imports without any issues. I don’t think it has any animation, though, which I will have to fix.

MD2 modeling/animation:
Though models are not impossible to find, MD2 has become fairly scarce. Most of the old sites have died, and none of the new sites are carrying much of interest. There are just plain better 3D game engines, better graphics formats, and different tools.
One great holdover is MilkShape, and this allows most 3D modelers to produce MD2 models. This site has a model loader/editor/saver, which imports a wide variety of formats and outputs an even wider variety. It has a free, time-limited demo, but the final product is only $35 (or 25 Euros), so it’s not a back-breaker. For my purposes, MilkShape’s main benefit is animating and exporting MD2; depending on how well it works, I will think about purchasing.
But don’t forget about Blender. Version 2.49 has a plugin that allows you to export MD2 (2.5 probably will, too, but that may be a year away yet). I have not tested it, and may not ever, since – for now – I am only doing a rudimentary test animation, and I don’t want to bother much with a complicated animation system that I don’t really understand yet. It behooves me to learn it, though, I know. . .
There is also this site, but it may be a bit outdated. Apparently you can set up MD2 animations directly in Away3D, too.

Code:
Here is the revised Actionscript. I renamed it to MD2Import.as (and the revised MXML code follows).

package
{
    import away3d.containers.View3D;
    import away3d.core.base.Mesh;
    import away3d.core.math.Number3D;
    import away3d.lights.AmbientLight3D;
    import away3d.loaders.Md2;
    import away3d.materials.BitmapFileMaterial;

    import flash.events.Event;

    import mx.core.Application;
    import mx.core.UIComponent;

    import org.osmf.metadata.MimeTypes;
    import org.osmf.utils.URL;

    public class MD2Import extends UIComponent
    {
        private var view:View3D;
        private var sceneLight:AmbientLight3D;

        private var testHorse:Mesh;

        [Embed (source="horse.md2", mimeType="application/octet-stream")]
        public static const Model:Class;

        public function MD2Import()
        {
            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(0, 0, -1500);
                this.view.camera.lookAt(new Number3D(0, 0, 0));

            }
            try
            {
                this.getChildIndex(this.view);
            }
            catch (e:Error)
            {
                this.addChild(this.view);
            }

            if(!this.testHorse)
            {
                this.testHorse = Md2.parse(new Model());
                this.testHorse.name = "horseModel";
                testHorse.material = new BitmapFileMaterial("horse.jpg");
                testHorse.scaleX = 0.01;
                testHorse.scaleY = 0.01;
                testHorse.scaleZ = 0.01;
                testHorse.rotationX = 45;
//              testHorse.rotationY = 45;
//              setAnimation("stand");
            }
            try
            {
                if(this.view.scene.getChildByName(this.testHorse.name) == null)
                    this.view.scene.addChild(this.testHorse);
            }
            catch (e:Error)
            {
                this.view.scene.addChild(this.testHorse);
            }

            this.view.render();
        }

        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.testHorse.rotationX += .7;
//              this.testHorse.rotationY += .5;
//              this.testHorse.rotationZ += .4;

                this.view.render();
                this.removeEventListener(Event.ENTER_FRAME, onFrameEnter);
            }
        }
    }
}

Code:
The revised MXML, now named Away3DMD2.mxml:

<?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:Script>
        <![CDATA[
            protected function move3DHnd(event:MouseEvent):void
            {
                var obj:* = event.target.parent;
                var opt:Point = new Point(obj.x + (obj.width * .5), obj.y + (obj.height * .5));

                trace(event.target.parent.name + ": " + opt);

                object3DScene.x = opt.x - (object3DScene.width * .5);
                object3DScene.y = opt.y - (object3DScene.height * .5);
            }
        ]]>
    </mx:Script>

    <mx:Canvas
        width="100%" height="100%"
        backgroundColor="#D1F0FF"
    >
        <mx:Text
            id="textTest1"
            text="This is a sample component underlay."
            x="175" y="175"
            mouseOver="move3DHnd(event)"
            />

        <local:MD2Import
            id="object3DScene"
            width="50%" height="50%"
            x="100" y="100"
        />

        <mx:Text
            id="textTest2"
            text="This is a sample component overlay."
            x="200" y="200"
            mouseOver="move3DHnd(event)"
        />
    </mx:Canvas>
</mx:Application>

Please continue to Away3D in Flex 4 – Phase 4.

– 30 –

Advertisements