Muse Get mp3 Ozzy Osbourne Large MP store Artist list Alexandra Burke Dave Matthews Band Nightwish Eva Cassidy Amy Winehouse Jefferson Airplane Coil Mylene Farmer Jason Williams MP3 list

Papervision Explode Image / Rebuild

In early 2008 I wrote a blog article on how to explode an image and rebuild it again. Recently this effect has been used in some amazing ways. Site's like Audi have taken this concept much further with the rows of these tiny boxes swimming in formation.

Today I decided to re-create that simple effect using the latest papervision code and provide a much needed update.

Creating this effect is actually fairly simple. You take an image, use some code to break it into smaller bitmaps which then are used as the materials for your planes. Then you just place the planes in a grid to re-create your image.

Here is a sample of the code that get's our image blocks to be used for our materials:

Actionscript:
  1. //Creates a 30 x 18 bitmapData block
  2. var bitmap_data:BitmapData  = new BitmapData(cellWidth, cellHeight, true, 0x00FFFF);
  3.                
  4. //Create a new Matrix - A matrix is a rectangular array / table
  5. //of numbers with any number of rows / columns.
  6. var matrix:Matrix         = new Matrix();
  7.  
  8. //Get's our desired x / y location information where we will
  9. //pull a block of our image
  10. matrix.translate( -cellWidth * cellX, -cellHeight * cellY);
  11.  
  12. //Write the data to our bitmap data object with our source and
  13. //matrix / block info
  14. bitmap_data.draw(imageMC, matrix);

Once you've created your grid you just need to store the locations of all your x,y,z,rotation etc so that when you break apart the image you can easily piece it back together.

Actionscript:
  1. planeVO.origX         = pl.x;
  2. planeVO.origY            = pl.y;
  3. planeVO.origZ         = pl.z;
  4. planeVO.origRotationY      = pl.rotationY;
  5. planeVO.origRotationX      = pl.rotationX;
  6. planeVO.origRotationZ      = pl.rotationZ;
  7. planeVO.planeRef          = pl;

PlaneVO is nothing more than a simple value object. A value object gives us a nice strongly typed object to store the variables we want to access later.

PlaneVO.as

Actionscript:
  1. package
  2. {
  3.     import org.papervision3d.objects.primitives.Plane;
  4.     /**
  5.      * ...
  6.      * @author Charlie Schulze, Woven Interactive, LLC
  7.      */
  8.     public class PlaneVO
  9.     {
  10.         public var origX:Number;
  11.         public var origY:Number
  12.         public var origZ:Number
  13.         public var origRotationY:Number
  14.         public var origRotationX:Number
  15.         public var origRotationZ:Number
  16.         public var planeRef:Plane;
  17.     }
  18.    
  19. }

Now on to the full code. I have left comments throughout to explain what is happening. Try changing some of the math or swapping the image with your own. Once you mess with it for a little while you'll find it's easy to create some amazing effects.

Actionscript:
  1. package
  2. {
  3.     import br.com.stimuli.loading.BulkLoader;
  4.     import br.com.stimuli.loading.BulkProgressEvent;
  5.     import com.foomonger.utils.Later;
  6.     import flash.display.Bitmap;
  7.     import flash.display.BitmapData;
  8.     import flash.display.DisplayObject;
  9.     import flash.display.MovieClip;
  10.     import flash.geom.Matrix;
  11.     import gs.easing.Quint;
  12.     import gs.TweenMax;
  13.     import org.papervision3d.materials.MovieMaterial;
  14.     import org.papervision3d.objects.DisplayObject3D;
  15.     import org.papervision3d.objects.primitives.Plane;
  16.     import org.papervision3d.view.BasicView;
  17.    
  18.     /**
  19.      * ...
  20.      * @author Charlie Schulze, charlie[at]woveninteractive[dot]com
  21.      */
  22.    
  23.     public class Main extends BasicView
  24.     {
  25.         protected var bulkInstance:BulkLoader;
  26.         protected var imageMC:MovieClip;
  27.         protected var imageString:String
  28.         protected var planeVOs:Array = [];
  29.         protected var planesContainer:DisplayObject3D;
  30.        
  31.         public function Main():void
  32.         {
  33.             super();
  34.            
  35.             //Set the image we want to load
  36.             imageString  = "images/king.gif";
  37.            
  38.             //Load our image
  39.             loadImage();
  40.         }
  41.         protected function loadImage():void
  42.         {
  43.             //BulkLoader is complete overkill for this but thought it would be a
  44.             //nice extra for everyone to see in action. Extremely useful set of classes.
  45.            
  46.             //Create our unique bulkInstance / available anywhere in our app by
  47.             //that name "bulkImageLoader"
  48.             bulkInstance = new BulkLoader("bulkImageLoader");
  49.            
  50.             //Add our image
  51.             bulkInstance.add(imageString);
  52.            
  53.             //Add our listeners
  54.             bulkInstance.addEventListener(BulkProgressEvent.COMPLETE, onImageLoaded);
  55.            
  56.             //Start Loading
  57.             bulkInstance.start();
  58.         }
  59.         protected function onImageLoaded(evt:BulkProgressEvent):void
  60.         {
  61.             init();
  62.         }
  63.         protected function init():void
  64.         {
  65.             createChildren();
  66.             explode();
  67.             startRendering();
  68.         }
  69.        
  70.         protected function createChildren():void
  71.         {
  72.             //Create the clip we will be getting our bitmap data from
  73.             imageMC = new MovieClip();
  74.            
  75.             //add our bitmap
  76.             imageMC.addChild(bulkInstance.getBitmap(imageString));
  77.  
  78.             //Optional - Create a container to hold our planes
  79.             planesContainer = new DisplayObject3D();
  80.            
  81.             //Array to store our value objects
  82.             planeVOs = [];
  83.            
  84.             for (var i:int = 0; i <65; i++)
  85.             {
  86.                 /**
  87.                  * Here is how we get our loop / colunm / cellWidth / cellHeight numbers
  88.                  *
  89.                  * 5 columns * 13 rows = 65 (number of loops)
  90.                  * 5 columns divided by the width (150) of our image = 30 pixels
  91.                  * 13 rows  divided by the height (234) of our image = 18 pixels
  92.                  */
  93.  
  94.                 var columns:uint          = 5;
  95.                 var cellWidth:int       = 30;
  96.                 var cellHeight:int    = 18;
  97.                 var cellX:int         = (i % columns)
  98.                 var cellY:int         = Math.floor(i / columns);
  99.  
  100.                 //Creates a 30 x 18 bitmapData block
  101.                 var bitmap_data:BitmapData  = new BitmapData(cellWidth, cellHeight, true, 0x00FFFF);
  102.                
  103.                 //Create a new Matrix - A matrix is a rectangular array / table
  104.                 //of numbers with any number of rows / columns.
  105.                 var matrix:Matrix         = new Matrix();
  106.                
  107.                 //Get's our desired x / y location information where we will
  108.                 //pull a block of our image
  109.                 matrix.translate( -cellWidth * cellX, -cellHeight * cellY);
  110.                
  111.                 //Write the data to our bitmap data object with our source and
  112.                 //matrix / block info
  113.                 bitmap_data.draw(imageMC, matrix);
  114.                
  115.                 //Create a bitmap with our bitmapData and add it to a movieclip
  116.                 var bitmap:Bitmap       = new Bitmap(bitmap_data);
  117.                 var myMovie:MovieClip     = new MovieClip();
  118.                
  119.                 myMovie.addChild(bitmap);
  120.                
  121.                 //Use the movieclip with our bitmap inside as our movieMaterial
  122.                 //needs to be cast as a DisplayObject to work
  123.                 var movieMat:MovieMaterial  = new MovieMaterial(myMovie as DisplayObject, true);
  124.                 movieMat.smooth             = true;
  125.                
  126.                 //Create a plane with our moviemat the size of our cellWidth/Height
  127.                 var pl:Plane             = new Plane(movieMat, cellWidth, cellHeight, 0, 0);
  128.                
  129.                 //Create a value object to store our origianl infomation
  130.                 //for when we animate we can then rebuild easily
  131.                 var planeVO:PlaneVO         = new PlaneVO();
  132.  
  133.                 //We want to place the planes to re-create our original image
  134.                 pl.x                        = ((cellX * cellWidth) + cellWidth) -(imageMC.width / 2);
  135.                 pl.y                   = -((cellY * cellHeight) + cellHeight) +(imageMC.height / 2);
  136.                
  137.                 //Set the original properties of our value object
  138.                 planeVO.origX         = pl.x;
  139.                 planeVO.origY            = pl.y;
  140.                 planeVO.origZ         = pl.z;
  141.                 planeVO.origRotationY      = pl.rotationY;
  142.                 planeVO.origRotationX      = pl.rotationX;
  143.                 planeVO.origRotationZ      = pl.rotationZ;
  144.                 planeVO.planeRef          = pl;
  145.                
  146.                 //Add our planeVO to our array
  147.                 planeVOs.push(planeVO)
  148.                
  149.                 //Add planes to our container
  150.                 planesContainer.addChild(pl);            
  151.             }
  152.            
  153.             //Add our container to our scene
  154.             scene.addChild(planesContainer);
  155.            
  156.             camera.zoom = 100;
  157.            
  158.             //rotate our container for an skewed effect
  159.             planesContainer.rotationY = 30;
  160.             planesContainer.rotationX = 30;
  161.         }
  162.        
  163.         protected function explode():void
  164.         {
  165.             //Create a for loop of our plane objects set random numbers to explode our image
  166.            
  167.             for (var i:int = 0; i <planeVOs.length; i++)
  168.             {
  169.                 var planeVO:PlaneVO     = planeVOs[i];
  170.                 var plane:Plane         = planeVO.planeRef;
  171.                
  172.                 var ranNumber:Number = Math.round(Math.random() * 200 - 200);
  173.                 var delayAmount:Number = i * .05;
  174.                 var shortDelayAmount:Number = delayAmount * .6;
  175.                
  176.                 var randomX:Number = (Math.random() * 4000) - 6000;
  177.                 var randomY:Number = (Math.random() * 8000) - 1000;
  178.                 var randomZ:Number = (Math.random() * 1000) + 5000;
  179.  
  180.                 TweenMax.to(plane, 2, { x:planeVO.origX + randomX, delay:shortDelayAmount,
  181.                                         z:randomZ, y:150 + planeVO.origY + randomY,
  182.                                         rotationY:180,ease:Quint.easeInOut} );
  183.             }
  184.            
  185.             //In 3 seconds rebuild
  186.             Later.call(this, rebuild, 3000, true);
  187.         }
  188.        
  189.         protected function rebuild():void
  190.         {
  191.             //Rebuild our image with the locations we stored in our VO
  192.            
  193.             for (var i:int = 0; i <planeVOs.length; i++)
  194.             {
  195.                 var planeVO:PlaneVO     = planeVOs[i];
  196.                 var plane:Plane         = planeVO.planeRef;
  197.                 var delayAmount:Number  = i * .005;
  198.                 TweenMax.to(plane, 1.8, { x:planeVO.origX, delay:delayAmount,
  199.                                         z:planeVO.origZ, y:planeVO.origY,
  200.                                         rotationY:planeVO.origRotationY,ease:Quint.easeInOut} );
  201.             }
  202.            
  203.             //In 5 seconds explode the image again
  204.             Later.call(this, explode, 5000, true);
  205.         }
  206.     }
  207. }

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

3 Responses to “Papervision Explode Image / Rebuild”


  • awesome effect, thanks for the update

  • package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.SpreadMethod;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.net.URLRequest;
    import flash.events.MouseEvent;
    import com.greensock.TweenLite;
    import flash.utils.ByteArray;
    /**
    * …
    * @author dreamnight
    */
    public class Main extends Sprite {
    private var str:String;//外部照片的链接地址
    private var bmp:Bitmap;//保存加载进来的的图片
    private var cellWidth:Number;
    private var cellHeight:Number;
    private var smallImages:Array;
    private var storePosition:Array;
    private var container:Sprite;

    private var row:int;
    private var column:int;
    //判断是否发生click事件
    private var isClick:Boolean;

    public function Main():void {
    if (stage) {
    init();
    } else {
    addEventListener(Event.ADDED_TO_STAGE, addToStage);
    }
    }

    private function addToStage(e:Event = null):void {
    removeEventListener(Event.ADDED_TO_STAGE, addToStage);
    init();
    // entry point
    }

    private function init():void {
    str=”MY.jpg”;
    container = new Sprite();
    addChild(container);
    //让container处在中间
    loadImage(str);

    }
    private function loadImage(str:String=”"):void {
    var loader:Loader = new Loader();
    var urlRequest:URLRequest=new URLRequest(str);
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete);
    loader.load(urlRequest);

    }

    private function onComplete(e:Event):void {
    bmp=Bitmap(e.target.content);
    splite();//拆分相片
    }

    private function splite(rowWidth:int=30,columnHeight:int=18):void {
    cellWidth=rowWidth;
    cellHeight=columnHeight;
    var cellBitmapData:BitmapData=new BitmapData(cellWidth,cellHeight);
    smallImages=[];
    storePosition=[];
    var matrix:Matrix = new Matrix();
    //爆破的个数 : row*column
    row=Math.floor(bmp.width/cellWidth);//横向的个数
    column=Math.floor(bmp.height/cellHeight);//列个数

    for (var i:int = 0; i!=row; ++i) {

    for (var j:int = 0; j != column; ++j) {

    var tx:Number=- cellWidth*i;
    var ty:Number=- cellHeight*j;
    matrix.translate(tx ,ty );
    cellBitmapData.draw(bmp,matrix);
    var bitmap:Bitmap=new Bitmap(cellBitmapData);
    //对该照片进行复原
    bitmap.x=- tx;
    bitmap.y=- ty;
    smallImages.push(bitmap);
    //保存初始位置:
    var oj:Object= new Object();
    oj.x=- tx;
    oj.y=- ty;
    storePosition.push(oj);
    //将其添加到容器中
    container.addChild(bitmap);

    }
    }

    //对数组ujinxing复制,以此来保存其初始X,y坐标
    /*
    var copy:ByteArray = new ByteArray();
    copy.writeObject(smallImages);
    copy.position = 0;
    storePosition = copy.readObject()*/

    //增加交换性
    interactive();// 增加交互性

    }

    private function interactive():void {
    isClick=false;
    container.addEventListener(MouseEvent.CLICK, onClick);

    }
    private function onClick(e:MouseEvent):void {
    if (isClick==true) {
    isClick=false;
    trace(“yes”);
    //进行还原

    for (var j:int = 0; j != row * column; ++j) {
    //还原
    TweenLite.to(smallImages[j],3,{x:storePosition[j].x,y:storePosition[j].y,z:0});
    }

    } else {
    isClick=true;
    trace(“ok”);

    for (var i:int = 0; i != row * column; ++i) {
    //
    TweenLite.to(smallImages[i],5,{x:Math.random()*stage.stageWidth,y:Math.random()*stage.stageHeight,z:Math.random()>0.5?Math.random()*1000:-Math.random()*1000});
    }

    }

    }

    }

    }

    why I can’t see the image?? it shows no pixel

  • Any chance you can give me a hint on where to start with this, i’m creating a Flickr 3D coverflow type gallery and when you click the arrow to move on to the next picture I want the current one to explode like this but I want a different image to rebuild! I’m not sure where to start

Leave a Reply


Follow WovenCharlie on Twitter

Flash and the City banner
2010 Flash And The City Speaker

RSS Feed