Nightwish Capone Mumford and Sons Get mp3 Cobra Starship Edge Of Sanity Bon Iver Dave Matthews Band Paramore Michael Buble Benabar She and Him MP3 search Michael Jackson

Tag Archive for 'InteractiveScene3DEvent'

Adding XML to the Papervision Coverflow

Papervision Coverflow XML feed

As a simple addition to yesterday's coverflow post, I wanted to show the same example but with loading images via XML. For simplicity sake the XML is loaded and parsed all in the main file.

The structure for our XML is very simple:

XML:
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <data>
  3.     <image><![CDATA[images/image1.jpg]]></image>
  4.     <image><![CDATA[images/image2.jpg]]></image>
  5.     <image><![CDATA[images/image3.jpg]]></image>
  6.     <image><![CDATA[images/image5.jpg]]></image>
  7.     <image><![CDATA[images/image4.jpg]]></image>
  8.     <image><![CDATA[images/image6.jpg]]></image>
  9.     <image><![CDATA[images/image7.jpg]]></image>
  10. </data>

We simply load our XML file with BulkLoader

Actionscript:
  1. protected function loadXML():void
  2. {
  3.     bulkInstance = new BulkLoader("bulkInstance");     
  4.     bulkInstance.add(xmlPath);
  5.     bulkInstance.addEventListener(BulkProgressEvent.COMPLETE, onXMLReady);
  6.     bulkInstance.start();
  7. }

Parse the results, now adding the images to the BulkLoader:

Actionscript:
  1. protected function onXMLReady(evt:BulkProgressEvent):void
  2. {
  3.     bulkInstance.removeEventListener(BulkProgressEvent.COMPLETE, onXMLReady);
  4.     bulkInstance.addEventListener(BulkProgressEvent.COMPLETE, onImagesReady);
  5.    
  6.     var xml:XML = bulkInstance.getXML(xmlPath);
  7.     var xmlList:XMLList = xml.image;
  8.    
  9.     for (var i:int = 0; i <xmlList.length(); i++)
  10.     {
  11.         var imagePath:String = String(xmlList[i])
  12.         bulkInstance.add(imagePath);
  13.        
  14.         //Add path to array for later access
  15.         images.push(imagePath);
  16.     }
  17.    
  18.     //Set our number of items based on how many images we load
  19.     numItems = images.length;
  20. }

When our images are ready we can continue the process of setting up our coverflow. But now using the images we just loaded for our materials.

Actionscript:
  1. var mat:BitmapMaterial  = new BitmapMaterial(bulkInstance.getBitmapData(images[i]));

It's that simple. Be sure to let us know if you find this useful and are able to use it in a project.

Here is the full code:

Actionscript:
  1. package
  2. {
  3.     import br.com.stimuli.loading.BulkLoader;
  4.     import br.com.stimuli.loading.BulkProgressEvent;
  5.     import flash.display.Sprite;
  6.     import flash.events.MouseEvent;
  7.     import flash.filters.GlowFilter;
  8.     import gs.easing.Quint;
  9.     import gs.TweenLite;
  10.     import org.papervision3d.events.InteractiveScene3DEvent;
  11.     import org.papervision3d.materials.BitmapMaterial;
  12.     import org.papervision3d.objects.DisplayObject3D;
  13.     import org.papervision3d.objects.primitives.Plane;
  14.     import org.papervision3d.view.BasicView;
  15.    
  16.     /**
  17.      * ...
  18.      * @author Charlie Schulze, charlie[at]woveninteractive[dot]com
  19.      * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
  20.      */
  21.    
  22.     public class Main extends BasicView
  23.     {
  24.         protected var planes:Array = [];
  25.         protected var images:Array = [];
  26.         protected var numItems:Number;
  27.         protected var currentItem:Number = 3;
  28.         protected var angle:Number = 25;       
  29.         protected var rightBtn:Sprite;
  30.         protected var leftBtn:Sprite;
  31.         protected var xmlPath:String = "xml/imageXML.xml";
  32.         protected var bulkInstance:BulkLoader;
  33.        
  34.         public function Main():void
  35.         {
  36.             //Make sure that your scene is set to interactive
  37.             super(640, 480, true, true);
  38.             loadXML();
  39.         }
  40.        
  41.         //First load our XML
  42.         protected function loadXML():void
  43.         {
  44.             bulkInstance = new BulkLoader("bulkInstance");     
  45.             bulkInstance.add(xmlPath);
  46.             bulkInstance.addEventListener(BulkProgressEvent.COMPLETE, onXMLReady);
  47.             bulkInstance.start();
  48.         }
  49.        
  50.         //When our xml is ready parse and load our images
  51.         protected function onXMLReady(evt:BulkProgressEvent):void
  52.         {
  53.             bulkInstance.removeEventListener(BulkProgressEvent.COMPLETE, onXMLReady);
  54.             bulkInstance.addEventListener(BulkProgressEvent.COMPLETE, onImagesReady);
  55.            
  56.             var xml:XML = bulkInstance.getXML(xmlPath);
  57.             var xmlList:XMLList = xml.image;
  58.            
  59.             for (var i:int = 0; i <xmlList.length(); i++)
  60.             {
  61.                 var imagePath:String = String(xmlList[i])
  62.                 bulkInstance.add(imagePath);
  63.                
  64.                 //Add path to array for later access
  65.                 images.push(imagePath);
  66.             }
  67.            
  68.             //Set our number of items based on how many images we load
  69.             numItems = images.length;
  70.         }
  71.        
  72.         //Images are finished loading we can now create our papervision coverflow
  73.         protected function onImagesReady(evt:BulkProgressEvent):void
  74.         {
  75.             init();
  76.         }
  77.        
  78.         protected function init():void
  79.         {
  80.             createChildren();
  81.             createNavigation();
  82.             animate();
  83.             startRendering();
  84.         }
  85.         protected function createChildren():void
  86.         {
  87.             for (var i:int = 0; i <numItems; i++)
  88.             {
  89.                 //Grab our bitmapData from the bulkLoader using our array of image paths as our key
  90.                 var mat:BitmapMaterial  = new BitmapMaterial(bulkInstance.getBitmapData(images[i]));
  91.                 mat.interactive         = true;
  92.                 mat.smooth     = true;
  93.                 var plane:Plane         = new Plane(mat, 280, 351, 4, 4);
  94.                
  95.                 planes.push(plane);
  96.                
  97.                 //Click straight to any plane
  98.                 plane.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, onPlaneClick);
  99.                
  100.                 //Set an id to target current item
  101.                 plane.id = i;
  102.                
  103.                 //Add plane to the scene
  104.                 scene.addChild(plane);
  105.             }
  106.            
  107.             camera.zoom = 50;
  108.         }
  109.        
  110.         protected function onPlaneClick(evt:InteractiveScene3DEvent):void
  111.         {
  112.             currentItem = evt.target.id;
  113.             animate();
  114.         }
  115.        
  116.         //Animate the coverflow left / right based off of currentItems
  117.         protected function animate():void
  118.         {
  119.             for (var i:int = 0; i <planes.length; i++)
  120.             {
  121.                 var plane:Plane = planes[i];
  122.                
  123.                 //Each if statement will adjust these numbers as needed
  124.                 var planeX:Number = 0;
  125.                 var planeZ:Number = -50;
  126.                 var planeRotationY:Number = 0
  127.  
  128.                 //Place  & Animate Center Item
  129.                 if (i == currentItem)
  130.                 {
  131.                     planeZ     = -300
  132.                    
  133.                     TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
  134.                 }
  135.                
  136.                 //Place & Animate Right Items
  137.                 if(i> currentItem) 
  138.                 {
  139.                     planeX     = (i - currentItem + 1) * 120;
  140.                     planeRotationY   = angle + 10 * (i - currentItem);
  141.                    
  142.                     TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
  143.                 }
  144.                
  145.                 //Place & Animate Left Items
  146.                 if (i <currentItem)
  147.                 {
  148.                     planeX     = (currentItem - i + 1) * -120;
  149.                     planeRotationY   = -angle - 10 * (currentItem - i);
  150.                    
  151.                     TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
  152.                 }
  153.             }
  154.         }
  155.        
  156.         /*
  157.          * Everything below this point is just for creating the buttons and
  158.          * setting button events for controlling the coverflow.
  159.          */
  160.  
  161.         protected function createNavigation():void
  162.         {
  163.             //Create / Add Buttons
  164.             rightBtn = createButton();
  165.             leftBtn = createButton();
  166.                
  167.             addChild(leftBtn);
  168.             addChild(rightBtn);
  169.            
  170.             //Add button listeners
  171.             rightBtn.buttonMode = true;
  172.             leftBtn.buttonMode = true;
  173.             rightBtn.addEventListener(MouseEvent.CLICK, buttonClick);
  174.             leftBtn.addEventListener(MouseEvent.CLICK, buttonClick);
  175.                        
  176.             //Place buttons on stage
  177.             rightBtn.x    = stage.stageWidth - 20;
  178.             leftBtn.x       = 20;
  179.             rightBtn.y    =  stage.stageHeight / 2;
  180.             leftBtn.y       =  (stage.stageHeight / 2) + 20;
  181.             leftBtn.rotation    = 180;
  182.         }
  183.        
  184.         //Button actions
  185.         protected function buttonClick(evt:MouseEvent):void
  186.         {
  187.             switch (evt.target)
  188.             {
  189.                 case rightBtn:
  190.                 currentItem ++
  191.                 break;
  192.                
  193.                 case leftBtn:
  194.                 currentItem --;
  195.                 break;
  196.             }
  197.            
  198.             //Don't allow any number lower than 0 or past max so there
  199.             //is always a center item
  200.            
  201.             if (currentItem <0)
  202.             {
  203.                 currentItem = 0;
  204.             }
  205.             if (currentItem> (planes.length - 1))
  206.             {
  207.                 currentItem = planes.length - 1;
  208.             }
  209.            
  210.             //Call animation
  211.             animate();
  212.         }
  213.        
  214.         //Creates a simple arrow shape / returns the sprite
  215.         protected function createButton():Sprite
  216.         {
  217.             var btn:Sprite = new Sprite();
  218.            
  219.             btn.graphics.beginFill(0x333333);
  220.             btn.graphics.moveTo(0, 0);
  221.             btn.graphics.lineTo(0, 20);
  222.             btn.graphics.lineTo(10, 10);
  223.             btn.graphics.lineTo(0, 0);
  224.             btn.graphics.endFill();
  225.             btn.filters = [new GlowFilter(0xFFFFFF,1,10,10,3)]
  226.             return btn;
  227.         }
  228.     }
  229. }

Post to Twitter Post to Delicious Delicious Post to Digg Digg This Post Post to Facebook Facebook Post to StumbleUpon Stumble This Post

A Simple Papervision Coverflow

There are several great AS3 / Papervision Coverflows out there but today I set out to create one in it's simplest form. There are no bells and whistles, just a stripped down coverflow with it's core functionality. It's up to you to add an XML feed, Flickr feed, or setup your images in an array and load them the way you want to. This is only meant to be a clean jumping off point.

In the download I have included 2 versions. One with left / right buttons and one without. Both versions you can select the items in the coverflow to navigate.

The heart of this coverflow app is a lot like some of the others. We need to calculate the x and rotation of the center item, left items, and right items are, then animate accordingly. This is the same way that John Dyer animates his coverflow.

Actionscript:
  1. for (var i:int = 0; i <planes.length; i++)
  2. {
  3.     var plane:Plane = planes[i];
  4.    
  5.     //Each if statement will adjust these numbers as needed
  6.     var planeX:Number = 0;
  7.     var planeZ:Number = 20;
  8.     var planeRotationY:Number = 0
  9.  
  10.     //Place  & Animate Center Item
  11.     if (i == currentItem)
  12.     {
  13.         planeZ     = -300
  14.        
  15.         TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
  16.     }
  17.    
  18.     //Place & Animate Right Items
  19.     if(i> currentItem) 
  20.     {
  21.         planeX     = (i - currentItem + 1) * 120;
  22.         planeRotationY   = angle + 10 * (i - currentItem);
  23.        
  24.         TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
  25.     }
  26.    
  27.     //Place & Animate Left Items
  28.     if (i <currentItem)
  29.     {
  30.         planeX     = (currentItem - i + 1) * -120;
  31.         planeRotationY   = -angle - 10 * (currentItem - i);
  32.        
  33.         TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
  34.     }
  35. }

For this simple version of coverflow you have two ways of navigating to items.

Selecting a plane to jump right to that item

Actionscript:
  1. plane.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, onPlaneClick);
  2.  
  3. protected function onPlaneClick(evt:InteractiveScene3DEvent):void
  4. {
  5.     currentItem = evt.target.id;
  6.     animate();
  7. }

Or using left / right buttons to navigate one item at a time:

Actionscript:
  1. rightBtn.addEventListener(MouseEvent.CLICK, buttonClick);
  2. leftBtn.addEventListener(MouseEvent.CLICK, buttonClick);
  3.  
  4. protected function buttonClick(evt:MouseEvent):void
  5. {
  6.     switch (evt.target)
  7.     {
  8.         case rightBtn:
  9.         currentItem ++
  10.         break;
  11.        
  12.         case leftBtn:
  13.         currentItem --;
  14.         break;
  15.     }
  16.    
  17.     //Don't allow any number lower than 0 or past max so there
  18.     //is always a center item
  19.    
  20.     if (currentItem <0)
  21.     {
  22.         currentItem = 0;
  23.     }
  24.     if (currentItem> (planes.length - 1))
  25.     {
  26.         currentItem = planes.length - 1;
  27.     }
  28.    
  29.     //Call animation
  30.     animate();
  31. }

On to the full source code. This version includes the left / right buttons.

Actionscript:
  1. package
  2. {
  3.     import flash.display.DisplayObject;
  4.     import flash.display.Sprite;
  5.     import flash.events.Event;
  6.     import flash.events.MouseEvent;
  7.     import flash.filters.GlowFilter;
  8.     import gs.easing.Quint;
  9.     import gs.TweenLite;
  10.     import org.papervision3d.events.InteractiveScene3DEvent;
  11.     import org.papervision3d.materials.BitmapFileMaterial;
  12.     import org.papervision3d.objects.DisplayObject3D;
  13.     import org.papervision3d.objects.primitives.Plane;
  14.     import org.papervision3d.view.BasicView;
  15.    
  16.     /**
  17.      * ...
  18.      * @author Charlie Schulze, charlie[at]woveninteractive[dot]com
  19.      * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
  20.      */
  21.    
  22.     public class Main extends BasicView
  23.     {
  24.         protected var planes:Array = [];
  25.         protected var numItems:Number = 7;
  26.         protected var currentItem:Number = 3;
  27.         protected var angle:Number = 25;
  28.        
  29.         protected var mat:BitmapFileMaterial;
  30.         protected var rightBtn:Sprite;
  31.         protected var leftBtn:Sprite;
  32.        
  33.         public function Main():void
  34.         {
  35.             //Make sure that your scene is set to interactive
  36.             super(640, 480, true, true);
  37.            
  38.             init();
  39.         }
  40.         protected function init():void
  41.         {
  42.             createChildren();
  43.             createNavigation();
  44.             animate();
  45.             startRendering();
  46.         }
  47.         protected function createChildren():void
  48.         {
  49.             //Create Material
  50.             mat             = new BitmapFileMaterial("images/iPhone-back2.png");
  51.             mat.smooth   = true;
  52.             mat.interactive = true;
  53.             for (var i:int = 0; i <numItems; i++)
  54.             {
  55.                 var plane:Plane = new Plane(mat, 177, 334, 4, 4);
  56.                 planes.push(plane);
  57.                
  58.                 //Click straight to any plane
  59.                 plane.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, onPlaneClick);
  60.                
  61.                 //Set an id to target current item
  62.                 plane.id = i;
  63.                
  64.                 //Add plane to the scene
  65.                 scene.addChild(plane);
  66.             }
  67.            
  68.             camera.zoom = 60;
  69.         }
  70.        
  71.         protected function onPlaneClick(evt:InteractiveScene3DEvent):void
  72.         {
  73.             currentItem = evt.target.id;
  74.             animate();
  75.         }
  76.        
  77.         //Animate the coverflow left / right based off of currentItems
  78.         protected function animate():void
  79.         {
  80.             for (var i:int = 0; i <planes.length; i++)
  81.             {
  82.                 var plane:Plane = planes[i];
  83.                
  84.                 //Each if statement will adjust these numbers as needed
  85.                 var planeX:Number = 0;
  86.                 var planeZ:Number = -50;
  87.                 var planeRotationY:Number = 0
  88.  
  89.                 //Place  & Animate Center Item
  90.                 if (i == currentItem)
  91.                 {
  92.                     planeZ     = -300
  93.                    
  94.                     TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
  95.                 }
  96.                
  97.                 //Place & Animate Right Items
  98.                 if(i> currentItem) 
  99.                 {
  100.                     planeX     = (i - currentItem + 1) * 120;
  101.                     planeRotationY   = angle + 10 * (i - currentItem);
  102.                    
  103.                     TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
  104.                 }
  105.                
  106.                 //Place & Animate Left Items
  107.                 if (i <currentItem)
  108.                 {
  109.                     planeX     = (currentItem - i + 1) * -120;
  110.                     planeRotationY   = -angle - 10 * (currentItem - i);
  111.                    
  112.                     TweenLite.to(plane, 1, { rotationY:planeRotationY,x:planeX,z:planeZ, ease:Quint.easeInOut } );
  113.                 }
  114.             }
  115.         }
  116.        
  117.         /*
  118.          * Everything below this point is just for creating the buttons and
  119.          * setting button events for controlling the coverflow.
  120.          */
  121.  
  122.         protected function createNavigation():void
  123.         {
  124.             //Create / Add Buttons
  125.             rightBtn = createButton();
  126.             leftBtn = createButton();
  127.                
  128.             addChild(leftBtn);
  129.             addChild(rightBtn);
  130.            
  131.             //Add button listeners
  132.             rightBtn.buttonMode = true;
  133.             leftBtn.buttonMode = true;
  134.             rightBtn.addEventListener(MouseEvent.CLICK, buttonClick);
  135.             leftBtn.addEventListener(MouseEvent.CLICK, buttonClick);
  136.                        
  137.             //Place buttons on stage
  138.             rightBtn.x    = stage.stageWidth - 20;
  139.             leftBtn.x       = 20;
  140.             rightBtn.y    =  stage.stageHeight / 2;
  141.             leftBtn.y       =  (stage.stageHeight / 2) + 20;
  142.             leftBtn.rotation    = 180;
  143.         }
  144.        
  145.         //Button actions
  146.         protected function buttonClick(evt:MouseEvent):void
  147.         {
  148.             switch (evt.target)
  149.             {
  150.                 case rightBtn:
  151.                 currentItem ++
  152.                 break;
  153.                
  154.                 case leftBtn:
  155.                 currentItem --;
  156.                 break;
  157.             }
  158.            
  159.             //Don't allow any number lower than 0 or past max so there
  160.             //is always a center item
  161.            
  162.             if (currentItem <0)
  163.             {
  164.                 currentItem = 0;
  165.             }
  166.             if (currentItem> (planes.length - 1))
  167.             {
  168.                 currentItem = planes.length - 1;
  169.             }
  170.            
  171.             //Call animation
  172.             animate();
  173.         }
  174.        
  175.         //Creates a simple arrow shape / returns the sprite
  176.         protected function createButton():Sprite
  177.         {
  178.             var btn:Sprite = new Sprite();
  179.            
  180.             btn.graphics.beginFill(0x333333);
  181.             btn.graphics.moveTo(0, 0);
  182.             btn.graphics.lineTo(0, 20);
  183.             btn.graphics.lineTo(10, 10);
  184.             btn.graphics.lineTo(0, 0);
  185.             btn.graphics.endFill();
  186.             btn.filters = [new GlowFilter(0xFFFFFF,1,10,10,3)]
  187.             return btn;
  188.         }
  189.     }
  190. }

That's it. This should provide a good base for you to build out your own unique coverflow.

Post to Twitter Post to Delicious Delicious Post to Digg Digg This Post Post to Facebook Facebook Post to StumbleUpon Stumble This Post

Advanced Interactivity

advancedinteractivity1

download-source

This is just another example of how to do some advanced interactivity in Papervision 3D. This tutorial is just a slightly updated version of the #10 : Advanced Interactivity tutorial from a while back.

Here is what has been updated:
1) Removed InteractiveScene3DEvent and replaced it with standard MouseEvents
2) Updated to use papervision's BasicView.as class

For a full description of what is going on please refer back to this link: #10 : Advanced Interactivity

Actionscript:
  1. package
  2. {
  3.     import flash.display.Sprite;
  4.     import flash.events.Event;
  5.     import flash.events.MouseEvent;
  6.     import flash.text.TextField;
  7.     import org.papervision3d.materials.ColorMaterial;
  8.     import org.papervision3d.materials.MovieMaterial;
  9.     import org.papervision3d.materials.utils.MaterialsList;
  10.     import org.papervision3d.objects.primitives.Cube;
  11.     import org.papervision3d.view.BasicView;
  12.    
  13.     /**
  14.      * ...
  15.      * @author Charlie Schulze, charlie[at]woveninteractive[dot]com
  16.      */
  17.    
  18.     public class Main extends BasicView
  19.     {
  20.         protected var cube:Cube;
  21.         protected var interactiveMats:Array;
  22.         protected var materialsList:MaterialsList;
  23.         protected var targetrotationX:Number;
  24.         protected var targetrotationY:Number;
  25.         protected var targetrotationZ:Number;
  26.         protected var tweening:Boolean;
  27.        
  28.         public function Main():void
  29.         {
  30.             super();
  31.             init();
  32.         }
  33.         protected function init():void
  34.         {
  35.             createChildren();
  36.             startRendering();
  37.         }
  38.         protected function createChildren():void
  39.         {
  40.             //Set the viewport to interactive
  41.             viewport.interactive = true;
  42.            
  43.             //Create Materials:
  44.             materialsList       = new MaterialsList();
  45.             interactiveMats         = ["front", "back", "left", "right", "bottom", "top"];
  46.             var colorsArray:Array   = [0x76b6f8, 0x4291e1, 0x1f73c8, 0xe77111, 0xe8914c, 0xfad2b2];
  47.            
  48.             for (var i:int = 0; i <interactiveMats.length; i++)
  49.             {
  50.                 //Create a color box so we can use our MouseEvents
  51.                 var colorBox:Sprite = new Sprite();
  52.                 colorBox.graphics.beginFill(colorsArray[i]);
  53.                 colorBox.graphics.drawRect(0, 0, 100, 100);
  54.                 colorBox.graphics.endFill();
  55.                 colorBox.name = interactiveMats[i];
  56.                
  57.                 //Add a textField for reference
  58.                 var textField:TextField = new TextField()
  59.                 colorBox.addChild(textField)
  60.                 textField.text = interactiveMats[i];
  61.                
  62.                 //Add a MouseEvent to the Sprite
  63.                 colorBox.mouseChildren = false;
  64.                 colorBox.addEventListener(MouseEvent.CLICK, onMovieMatClicked);
  65.                
  66.                 //Create the MovieMat
  67.                 var movieMat:MovieMaterial   = new MovieMaterial(colorBox, true, true);
  68.                 movieMat.interactive          = true;
  69.                 movieMat.smooth                 = true;
  70.                 materialsList.addMaterial(movieMat, interactiveMats[i]);
  71.             }
  72.            
  73.             //Create Cube
  74.             cube    = new Cube(materialsList, 100, 100, 100);
  75.            
  76.             //Add cube to the scene
  77.             scene.addChild(cube);
  78.         }
  79.        
  80.         protected function onMovieMatClicked(evt:MouseEvent):void
  81.         {
  82.             if (tweening)
  83.             {
  84.                 // Let it rotate again
  85.                 tweening = false;
  86.             }
  87.             else
  88.             {
  89.                 switch(evt.target.name) {
  90.                     case "front":
  91.                         targetrotationX = 0;
  92.                         targetrotationY = 180;
  93.                         targetrotationZ = 0;
  94.                         tweening = true;
  95.                     break;
  96.                     case "back":
  97.                         targetrotationX = 0;
  98.                         targetrotationY = 0;
  99.                         targetrotationZ = 0;
  100.                         tweening = true;
  101.                     break;
  102.                     case "left":
  103.                         targetrotationX = 0;
  104.                         targetrotationY = -90;
  105.                         targetrotationZ = 0;
  106.                         tweening = true;
  107.                     break;
  108.                     case "right":
  109.                         targetrotationX = 0;
  110.                         targetrotationY = 90;
  111.                         targetrotationZ = 0;
  112.                         tweening = true;
  113.                     break;
  114.                     case "top":
  115.                         targetrotationX = -90;
  116.                         targetrotationY = 0;
  117.                         targetrotationZ = 0;
  118.                         tweening = true;
  119.                     break;
  120.                     case "bottom":
  121.                         targetrotationX = 90;
  122.                         targetrotationY = 0;
  123.                         targetrotationZ = 180;
  124.                         tweening = true;
  125.                     break;
  126.                 }
  127.             }
  128.         }
  129.        
  130.         override protected function onRenderTick(event:Event = null):void
  131.         {
  132.             super.onRenderTick(event);
  133.            
  134.             if (tweening) {
  135.                 // If a face has been clicked
  136.                 if (camera.zoom <230) {
  137.                     // If the camera isn't zoomed enough then zoom in a bit more:
  138.                     camera.zoom += Math.sqrt(230-camera.zoom)/5;
  139.                 }
  140.                 // Test each rotation and rotate it towards the target rotation:
  141.                 // X axis:
  142.                 if (cube.rotationX <targetrotationX)
  143.                 {
  144.                     cube.rotationX += Math.sqrt(targetrotationX-cube.rotationX);
  145.                     cube.rotationX = Math.round(cube.rotationX);
  146.                 }
  147.                 else if (cube.rotationX> targetrotationX)
  148.                 {
  149.                     cube.rotationX -= Math.sqrt(cube.rotationX-targetrotationX);
  150.                     cube.rotationX = Math.round(cube.rotationX);
  151.                 }
  152.                
  153.                 // Y axis:
  154.                 if (cube.rotationY <targetrotationY)
  155.                 {
  156.                     cube.rotationY += Math.sqrt(targetrotationY-cube.rotationY);
  157.                     cube.rotationY = Math.round(cube.rotationY);
  158.                 }
  159.                 else if (cube.rotationY> targetrotationY)
  160.                 {
  161.                     cube.rotationY -= Math.sqrt(cube.rotationY-targetrotationY);
  162.                     cube.rotationY = Math.round(cube.rotationY);
  163.                 }
  164.                
  165.                 // Z axis:
  166.                 if (cube.rotationZ <targetrotationZ)
  167.                 {
  168.                     cube.rotationZ += Math.sqrt(targetrotationZ-cube.rotationZ);
  169.                     cube.rotationZ = Math.round(cube.rotationZ);
  170.                 }
  171.                 else if (cube.rotationZ> targetrotationZ)
  172.                 {
  173.                     cube.rotationZ -= Math.sqrt(cube.rotationZ-targetrotationZ);
  174.                     cube.rotationZ = Math.round(cube.rotationZ);
  175.                 }
  176.             }
  177.             else
  178.             {
  179.                 // If the camera is zoomed in, it shouldn't be now
  180.                 if (camera.zoom> 200)
  181.                 {
  182.                     // So zoom out a bit.
  183.                     camera.zoom -= Math.sqrt(camera.zoom-2)/5;
  184.                 }
  185.                 // Rotate the cube a bit:
  186.                 cube.rotationX += 2;
  187.                 cube.rotationY += 2;
  188.                 // Make sure that we dont "wind up" the rotation
  189.                 if (cube.rotationX>= 360) cube.rotationX = 0;
  190.                 if (cube.rotationY>= 360) cube.rotationY = 0;
  191.             }
  192.         }      
  193.     }
  194. }

download-source

Post to Twitter Post to Delicious Delicious Post to Digg Digg This Post Post to Facebook Facebook Post to StumbleUpon Stumble This Post

Basic Mouse Interaction (v2)

basic-mouse-interaction

download-source

In the previous tutorial we showed you how to load a 3D model into Papervision. Now we are just going to show you how to rotate that model based off of your mouse movements.

The process is very simple. Since our render function is like the engine of our animations that is where we will add the code for the rotation. Later we'll cover animating objects via TweenLite / TweenMax.

Actionscript:
  1. override protected function onRenderTick(event:Event = null):void
  2. {
  3.     super.onRenderTick(event);
  4.     cow.rotationY = stage.mouseX / sceneWidth * 360
  5. }

When you first start moving objects in Papervision you may notice that rotationY and rotationX do not act as you might think they would. In flash you would think of something on a Y axis as going up and down and X as left and right. With Papervision RotationY rotates and object on its Y axis (left /right) and RotationX rotates an object on it's X axis (top / bottom).

Here is the full code:

Actionscript:
  1. package 
  2. {
  3.     import flash.events.Event;
  4.     import org.papervision3d.materials.BitmapFileMaterial;
  5.     import org.papervision3d.materials.utils.MaterialsList;
  6.     import org.papervision3d.objects.DisplayObject3D;
  7.     import org.papervision3d.objects.parsers.Collada;
  8.     import org.papervision3d.view.BasicView;
  9.  
  10.     public class Main extends BasicView
  11.     {
  12.         protected var cow:DisplayObject3D;
  13.         protected var materialList:MaterialsList;
  14.         protected var bitmapFileMaterial:BitmapFileMaterial;
  15.        
  16.         protected var sceneWidth:Number;
  17.         protected var sceneHeight:Number;
  18.        
  19.         public function Main()
  20.         {
  21.             super();
  22.             init();
  23.             createChildren();
  24.             startRendering();
  25.         }
  26.         protected function init():void
  27.         {
  28.             sceneWidth = stage.stageWidth
  29.         }
  30.         public function createChildren():void
  31.         {
  32.             //Setup the materials manually (sometimes the dae handles this without issue)
  33.             materialList       = new MaterialsList();
  34.             bitmapFileMaterial  = new BitmapFileMaterial("daeModel/Cow.png");
  35.             materialList.addMaterial(bitmapFileMaterial,"all");
  36.            
  37.             //Create the new Collada Object with materialList
  38.             cow = new Collada("daeModel/cow.dae",materialList);
  39.  
  40.             ///Set some properties
  41.             cow.moveDown(150);
  42.             cow.scale = 3;
  43.             cow.pitch( -10);
  44.  
  45.             //Add to scene
  46.             scene.addChild(cow);
  47.         }
  48.        
  49.         override protected function onRenderTick(event:Event = null):void
  50.         {
  51.             super.onRenderTick(event);
  52.             cow.rotationY = stage.mouseX / sceneWidth * 360
  53.         }
  54.     }
  55. }

download-source

Post to Twitter Post to Delicious Delicious Post to Digg Digg This Post Post to Facebook Facebook Post to StumbleUpon Stumble This Post

10. Advanced Interactivity

**UPDATE
This tutorial has been updated:
Updates:
1) Removed InteractiveScene3DEvent and replaced it with standard MouseEvents
2) Updated to use papervision's BasicView.as class

view-update

Today we're going to learn how to handle more advanced interactivity. We'll be making something like this:

Click on a face of the cube to zoom into it. Click it again to make the cube spin again.

So, in this tutorial I'm going to show you exactly how to work out which material has been clicked on the cube and act accordingly.

If you haven't read it already, I strongly suggest that you read the Basic Interactivity tutorial first or you'll probably miss something.

Ok, so on to the code.

Firstly we'll want six materials to apply to each face of the cube. Here are mine, although you can create whatever materials you like:

Actionscript:
  1. private var frontMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front.jpg");
  2.         private var backMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/back.jpg");
  3.         private var leftMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/left.jpg");
  4.         private var rightMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/right.jpg");
  5.         private var topMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/top.jpg");
  6.         private var bottomMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/bottom.jpg");

So, in this code I'm just loading six images from my server to use as each face.

Also, add the following declaration beneath the texture declarations to hold our Cube object:

Actionscript:
  1. private var cube:Cube;

Now we need to set up the 3d initiation code. In this code we will firstly set all of our materials as interactive, and then give each of our materials a name. This is VERY important to be able to easily find out which material has been clicked. If we didn't give each material a name then we wouldn't be able to easily work out which face has been clicked.

So, add the following code to your init3d() function:

Actionscript:
  1. override protected function init3d():void {
  2.             // We need to be able to identify each side. We'll do this
  3.             // by asssigning names to each material. During this process
  4.             // we'll also make the materials interactive.
  5.             frontMaterial.interactive = true;
  6.             frontMaterial.name = "front";
  7.             backMaterial.interactive = true;
  8.             backMaterial.name = "back";
  9.             leftMaterial.interactive = true;
  10.             leftMaterial.name = "left";
  11.             rightMaterial.interactive = true;
  12.             rightMaterial.name = "right";
  13.             topMaterial.interactive = true;
  14.             topMaterial.name = "top";
  15.             bottomMaterial.interactive = true;
  16.             bottomMaterial.name = "bottom";
  17.             // ---------------------------------------------
  18.            
  19.             cube = new Cube(new MaterialsList( {
  20.                 front: frontMaterial,
  21.                 back: backMaterial,
  22.                 left: leftMaterial,
  23.                 right: rightMaterial,
  24.                 top: topMaterial,
  25.                 bottom: bottomMaterial
  26.                 } ), 500, 500, 500, 3, 3, 3);
  27.             cube.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onPress);
  28.             default_scene.addChild(cube);
  29.         }

So, In this code, we've set each material as interactive, given each one a sensible name, and initialised our cube with the materials assigned to the correct faces.

We then add an event listener to trigger the "onPress" event when the cube is clicked, then finally we add the cube to the scene.

We've now got a cube with six materials on it listening for a click event.

Now, the code which will let us work out which face has been clicked:

Actionscript:
  1. private function onPress( e:InteractiveScene3DEvent ):void {
  2.     switch(e.face3d.material.name) {
  3.         case "front":
  4.             // This code will be run when the front face is clicked
  5.         break;
  6.         case "back":
  7.             // This code will be run when the back face is clicked
  8.         break;
  9.         case "left":
  10.             // This code will be run when the left face is clicked
  11.         break;
  12.         case "right":
  13.             // This code will be run when the right face is clicked
  14.         break;
  15.         case "top":
  16.             // This code will be run when the top face is clicked
  17.         break;
  18.         case "bottom":
  19.             // This code will be run when the bottom face is clicked
  20.         break;
  21.     }
  22. }

Pretty self explanitary. The "e" variable in this code holds lots of data about the click event, including which material has been clicked, so, because we know which material is on each face, we can tell by the materials name which face has been clicked!

With a little bit of code, you can make a nice spinning cube gallery like the example above:

Here is my final code, have fun!

Actionscript:
  1. package  {
  2.    
  3.     import flash.display.DisplayObject;
  4.     import org.papervision3d.materials.BitmapFileMaterial;
  5.     import org.papervision3d.materials.utils.MaterialsList;
  6.     import org.papervision3d.events.InteractiveScene3DEvent;
  7.     import org.papervision3d.objects.primitives.Cube;
  8.    
  9.     public class Main extends PaperBase {
  10.        
  11.         private var frontMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/front.jpg");
  12.         private var backMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/back.jpg");
  13.         private var leftMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/left.jpg");
  14.         private var rightMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/right.jpg");
  15.         private var topMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/top.jpg");
  16.         private var bottomMaterial:BitmapFileMaterial = new BitmapFileMaterial("http://papervision2.com/wp-content/pvTex/bottom.jpg");
  17.        
  18.         private var targetrotationX:Number = 0;
  19.         private var targetrotationY:Number = 0;
  20.         private var targetrotationZ:Number = 0;
  21.        
  22.         private var tweening:Boolean = false;
  23.        
  24.         private var cube:Cube;
  25.        
  26.         public function Main() {
  27.             init(400, 400);
  28.         }
  29.        
  30.         override protected function init3d():void {
  31.             // We need to be able to identify each side. We'll do this
  32.             // by asssigning names to each material. During this process
  33.             // we'll also make the materials interactive.
  34.             frontMaterial.interactive = true;
  35.             frontMaterial.name = "front";
  36.             backMaterial.interactive = true;
  37.             backMaterial.name = "back";
  38.             leftMaterial.interactive = true;
  39.             leftMaterial.name = "left";
  40.             rightMaterial.interactive = true;
  41.             rightMaterial.name = "right";
  42.             topMaterial.interactive = true;
  43.             topMaterial.name = "top";
  44.             bottomMaterial.interactive = true;
  45.             bottomMaterial.name = "bottom";
  46.             // ---------------------------------------------
  47.            
  48.             cube = new Cube(new MaterialsList( {
  49.                 front: frontMaterial,
  50.                 back: backMaterial,
  51.                 left: leftMaterial,
  52.                 right: rightMaterial,
  53.                 top: topMaterial,
  54.                 bottom: bottomMaterial
  55.                 } ), 500, 500, 500, 3, 3, 3);
  56.             // Listen for the click:
  57.             cube.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, onPress);
  58.             // Add to scene:
  59.             default_scene.addChild(cube);
  60.         }
  61.        
  62.         private function onPress( e:InteractiveScene3DEvent ):void {
  63.             // If the cube has been moved to the front:
  64.             if (tweening) {
  65.                 // Let it rotate again
  66.                 tweening = false;
  67.             }else {
  68.                 // Find which rotation we need to be able to see
  69.                 // the face image:
  70.                 switch(e.face3d.material.name) {
  71.                     case "front":
  72.                         targetrotationX = 0;
  73.                         targetrotationY = 180;
  74.                         targetrotationZ = 0;
  75.                         tweening = true;
  76.                     break;
  77.                     case "back":
  78.                         targetrotationX = 0;
  79.                         targetrotationY = 0;
  80.                         targetrotationZ = 0;
  81.                         tweening = true;
  82.                     break;
  83.                     case "left":
  84.                         targetrotationX = 0;
  85.                         targetrotationY = -90;
  86.                         targetrotationZ = 0;
  87.                         tweening = true;
  88.                     break;
  89.                     case "right":
  90.                         targetrotationX = 0;
  91.                         targetrotationY = 90;
  92.                         targetrotationZ = 0;
  93.                         tweening = true;
  94.                     break;
  95.                     case "top":
  96.                         targetrotationX = 90;
  97.                         targetrotationY = 0;
  98.                         targetrotationZ = 0;
  99.                         tweening = true;
  100.                     break;
  101.                     case "bottom":
  102.                         targetrotationX = -90;
  103.                         targetrotationY = 0;
  104.                         targetrotationZ = 180;
  105.                         tweening = true;
  106.                     break;
  107.                 }
  108.             }
  109.         }
  110.        
  111.         override protected function processFrame():void {
  112.             if (tweening) {
  113.                 // If a face has been clicked
  114.                 if (default_camera.zoom &lt;6.8) {
  115.                     // If the camera isn't zoomed enough then zoom in a bit more:
  116.                     default_camera.zoom += Math.sqrt(6.8-default_camera.zoom)/5;
  117.                 }
  118.                
  119.                 // Test each rotation and rotate it towards the target rotation:
  120.                 // X axis:
  121.                 if (cube.rotationX &lt;targetrotationX) {
  122.                     cube.rotationX += Math.sqrt(targetrotationX-cube.rotationX);
  123.                     cube.rotationX = Math.round(cube.rotationX);
  124.                 }else if (cube.rotationX&gt; targetrotationX) {
  125.                     cube.rotationX -= Math.sqrt(cube.rotationX-targetrotationX);
  126.                     cube.rotationX = Math.round(cube.rotationX);
  127.                 }
  128.                 // Y axis:
  129.                 if (cube.rotationY &lt;targetrotationY) {
  130.                     cube.rotationY += Math.sqrt(targetrotationY-cube.rotationY);
  131.                     cube.rotationY = Math.round(cube.rotationY);
  132.                 }else if (cube.rotationY&gt; targetrotationY) {
  133.                     cube.rotationY -= Math.sqrt(cube.rotationY-targetrotationY);
  134.                     cube.rotationY = Math.round(cube.rotationY);
  135.                 }
  136.                 // Z axis:
  137.                 if (cube.rotationZ &lt;targetrotationZ) {
  138.                     cube.rotationZ += Math.sqrt(targetrotationZ-cube.rotationZ);
  139.                     cube.rotationZ = Math.round(cube.rotationZ);
  140.                 }else if (cube.rotationZ&gt; targetrotationZ) {
  141.                     cube.rotationZ -= Math.sqrt(cube.rotationZ-targetrotationZ);
  142.                     cube.rotationZ = Math.round(cube.rotationZ);
  143.                 }
  144.             }else {
  145.                 // If the camera is zoomed in, it shouldn't be now
  146.                 if (default_camera.zoom&gt; 2) {
  147.                     // So zoom out a bit.
  148.                     default_camera.zoom -= Math.sqrt(default_camera.zoom-2)/5;
  149.                 }
  150.                
  151.                 // Rotate the cube a bit:
  152.                 cube.rotationX += 2;
  153.                 cube.rotationY += 2;
  154.                
  155.                 // Make sure that we dont "wind up" the rotation
  156.                 if (cube.rotationX&gt;= 360) cube.rotationX = 0;
  157.                 if (cube.rotationY&gt;= 360) cube.rotationY = 0;
  158.             }
  159.         }
  160.     }
  161. }

Post to Twitter Post to Delicious Delicious Post to Digg Digg This Post Post to Facebook Facebook Post to StumbleUpon Stumble This Post


Follow WovenCharlie on Twitter

Flash and the City banner
2010 Flash And The City Speaker

RSS Feed