package { /* Warping a bitmap using away3D BezierPatch */ import away3d.containers.View3D; import away3d.core.base.Vertex; import away3d.materials.BitmapMaterial; import away3d.primitives.BezierPatch; import away3d.primitives.data.PatchData; import gs.TweenLite; import gs.easing.Quad; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.SecurityErrorEvent; import flash.net.URLRequest; import flash.system.LoaderContext; [SWF(backgroundColor="#1a1a1a", frameRate="31", width="470", height="470")] public class Stretch3D extends Sprite { private var _patchVerts : Array; private var _patchMesh : BezierPatch; private var _view : View3D; private var _patchData : PatchData; private var _texture : BitmapData; private var _material : BitmapMaterial; private var _nodes : Array; private var _uvs : Array; private var _patchInfo : Array; private var _segments : int = 10; public static const IMG_URL:String ="http://fatlinesofcode.philipandrews.org/wp-content/uploads/fox.jpg" public function Stretch3D() { var l:Loader = new Loader() l.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageReady) l.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoadError); l.addEventListener(IOErrorEvent.IO_ERROR, onLoadError); l.load(new URLRequest(Stretch3D.IMG_URL), new LoaderContext(true)) } private function onLoadError(event : SecurityErrorEvent) : void { trace(event) } private function onImageReady(event : Event) : void { try{ _texture = event.target.loader.contentLoaderInfo.content.bitmapData as BitmapData _material = new BitmapMaterial(_texture); createScene(); }catch(e:Error){ trace("error loading external bitmap", e) } } private function createScene() : void { _view = new View3D() _view.x = stage.stageWidth / 2; _view.y = stage.stageHeight / 2; addChild(_view) createPatch(); addEventListener(Event.ENTER_FRAME, onEnterFrame) addEventListener(Event.ENTER_FRAME, onRenderStart) } public function createPatch() : void { _nodes = new Array(); _nodes["patch"] = new Array( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); _patchVerts = getVertexs(); _uvs = new Array(); _uvs["patch"] = new Array(); _uvs["patch"][BezierPatch.N] = new Array( [1, 1, 0, 0] ) var orientation:int = BezierPatch.N _patchInfo = new Array({ key:"patch", orientation:orientation, segmentsW:_segments, segmentsH:_segments }); _patchData = new PatchData(_nodes, _patchVerts, _uvs, _patchInfo, 1); _patchMesh = new BezierPatch(_patchData, { name:"PatchMesh" , material:_material, bothsides:true, ownCanvas:true} ); _view.scene.addChild(_patchMesh); } private function getVertexs() : Array { return [ new Vertex( 150, -150, 0), new Vertex( 50, -150, 0), new Vertex( -50, -150, 0), new Vertex( -150, -150, 0), new Vertex( 150, -50, 0), new Vertex( 50, -50, 0), new Vertex( -50, -50, 0), new Vertex( -150, -50, 0), new Vertex( 150, 50, 0), new Vertex( 50, 50, 0), new Vertex( -50, 50, 0), //10 new Vertex( -150, 50, 0), new Vertex( 150, 150, 0), new Vertex( 50, 150, 0), new Vertex( -50, 150, 0), new Vertex( -150, 150, 0) ] } private function onRenderStart(event : Event) : void { removeEventListener(Event.ENTER_FRAME, onRenderStart) warpVerts(); } private function onEnterFrame(event : Event) : void { _patchMesh.refreshPatch(); _patchMesh.rotationX += 1 _patchMesh.rotationY -= 1 _view.render(); } private function warpVerts() : void { var target:Number = _patchVerts[9].z <= 0 ? 1000: -1000 TweenLite.to(_patchVerts[5], 1, {z:target, ease: Quad.easeInOut, onComplete:warpVerts}); TweenLite.to(_patchVerts[6], 1, {z:target, ease: Quad.easeInOut, onComplete:warpVerts}); TweenLite.to(_patchVerts[9], 1, {z:target, ease: Quad.easeInOut, onComplete:warpVerts}); TweenLite.to(_patchVerts[10], 1, {z:target, ease: Quad.easeInOut, onComplete:warpVerts}); } } } BezierPatch away3D