package {
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.utils.ByteArray;
    
    import org.libspark.flartoolkit.core.FLARCode;
    import org.libspark.flartoolkit.core.param.FLARParam;
    import org.libspark.flartoolkit.core.raster.rgb.FLARRgbRaster_BitmapData;
    import org.libspark.flartoolkit.core.transmat.FLARTransMatResult;
    import org.libspark.flartoolkit.detector.FLARSingleMarkerDetector;
    import org.libspark.flartoolkit.pv3d.FLARBaseNode;
    import org.libspark.flartoolkit.pv3d.FLARCamera3D;
    import org.papervision3d.objects.parsers.Collada;
    import org.papervision3d.render.BasicRenderEngine;
    import org.papervision3d.scenes.Scene3D;
    import org.papervision3d.view.Viewport3D;

    
    /* SWF Metadata */
    [SWF(width='640', height='480', frameRate='60', backgroundColor='#ffffff')]

    public class AR extends Sprite
    {
        
        /* embed the pattern file generated using 
        http://saqoosha.net/lab/FLARToolKit/MarkerGenerator/MakerGenerator.air */ 
        [Embed(source="pattern.pat", mimeType="application/octet-stream")]
        private var pattern:Class;
        
        /* embed teh camera parameters file generated using 
        http://www.hitl.washington.edu/artoolkit/download/ */
        [Embed(source="camera_para.dat", mimeType="application/octet-stream")]
        private var params:Class;


        
        
        /* used to display the video */
        private var video:Video; 
        
        /* used to capture camera input */
        private var webcam:Camera; 
        
        
        
        
        /* stores the camera parameters */
        private var fparams:FLARParam; 
        
        /* stores the pattern */
        private var mpattern:FLARCode;
        
        
        
        
        /* used to detect if a pattern is present in a bitmap */
        private var detector:FLARSingleMarkerDetector;
        
        /* used to get the transformation of the pattern 
        in the captured bitmap  and to apply that 
        transformation to the 3D object we are adding*/
        private var trans:FLARTransMatResult;
        
        
        
        
        /* used to store and operate on each frame of the video */
        private var bitmapData:BitmapData;
        
        /* wraps the bitmapData above  */
        private var raster:FLARRgbRaster_BitmapData; 
        
        
        
        
        
        /* your 3D scene */
        private var scene:Scene3D;
        
        /* a 3D camera to look at your 3D scene,
        note that in FLARToolkit projects you have 
        to use FLARCamera3D instead of the normal 
        Camera3D */
        private var camera:FLARCamera3D;
        
        /* your 3D viewport */
        private var viewport:Viewport3D;
        
        /* rendering engine to render 3D */
        private var renderEngine:BasicRenderEngine;
        
        
        
        
        
        
        /* container  */
        private var container:FLARBaseNode; 
        
        
        
        
        /**
         * Constructor 
         */        
        public function AR()
        {
            setupCamera();    
            setupFLAR();
            setupBitmap();
            setupPV3d();
            
            addEventListener(Event.ENTER_FRAME, loop);
        }
        
        
        /**
         * Setup a webcam and show the video
         */        
        private function setupCamera():void
        {
            video = new Video(640,480);
            webcam = Camera.getCamera();
            webcam.setMode(640,480,30);
            
            video.attachCamera(webcam);
            
            addChild(video);
        }


         /**
          * Setup teh FLARToolkit 
          */        
         private function setupFLAR():void
         {

            /* load the camera parameters coming from 
            the binary file into a FLARParam object    */
             fparams = new FLARParam();
             fparams.loadARParam(new params() as ByteArray);
             
             /* load the pattern from the embedded pattern file
             into a FLARCode object */
             mpattern = new FLARCode(16,16);
             mpattern.loadARPatt(new pattern());
             
             /* create a marker detctor, this is responsible for 
             detecting if a bitmap has the pattern we are looking for*/
             detector = new FLARSingleMarkerDetector(fparams,mpattern, 80);
             
             /* create a FLARTrasMatResult object, this is used to 
             transform teh 3D out based on teh transformation of the 
             pattern in the captured bitmap */
             trans = new FLARTransMatResult();
         }

        
        
        private function setupBitmap():void
        {
            bitmapData = new BitmapData(640,480);
            bitmapData.draw(video);
            raster = new FLARRgbRaster_BitmapData(bitmapData);
        }
        
        private function setupPV3d():void
        {
            scene = new Scene3D(); // create scene
            camera = new FLARCamera3D(fparams); // create camera
            viewport = new Viewport3D(); // create viewport
            renderEngine = new BasicRenderEngine(); //create render engine
            
            container = new FLARBaseNode(); // create container
                    
            createObjects();
            
            scene.addChild(container); // add container to scene
            addChild(viewport); // add viewport to this sprite  
        }
        
        
        





        /**
         * This method is where objects are added to the container
         * Everything else in this class can be used as a template 
         * just edit this function to add your own custom 3d objects
         */        
        private function createObjects():void
        {
            var cow:Collada = new Collada("cow.dae");
            cow.rotationX += 90;
            cow.scale = 0.5;
            container.addChild(cow);    
        }        






        
        
        private function loop(e:Event):void
        {
            // capture the current frame of th video
            bitmapData.draw(video);

            try
            {
                // see if the detector found the pattern
                if(detector.detectMarkerLite(raster,80) 
                        && detector.getConfidence() > 0.5) 
                {
                    // if pattern was found
                    
                    // ask the detector how transfomed the patten is 
                    detector.getTransformMatrix(trans);
                    
                    // transform the container same as teh pattern 
                    container.setTransformMatrix(trans);
                    
                    // render the 3D scene
                    renderEngine.renderScene(scene,camera,viewport);
                }
                
            }catch(e:Error){}
            
        }
        
    }
}