// forked from clockmaker's Ginny Effect 3D /** * Ginny Effect 3D * * Photo by * http://www.flickr.com/photos/88403964@N00/2662752839/ (by clockmaker) */ package { import flash.display.*; import flash.events.*; import flash.geom.*; import flash.net.*; import flash.system.*; import flash.utils.*; import org.libspark.betweenas3.BetweenAS3; import org.libspark.betweenas3.easing.*; import org.libspark.betweenas3.tweens.ITween; import org.papervision3d.core.geom.renderables.Vertex3D; import org.papervision3d.core.utils.Mouse3D; import org.papervision3d.events.InteractiveScene3DEvent; import org.papervision3d.materials.BitmapMaterial; import org.papervision3d.materials.MovieMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Plane; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.render.QuadrantRenderEngine; import org.papervision3d.view.BasicView; import com.bit101.components.*; [SWF(frameRate = 30)] public class Main extends BasicView { private const IMAGE_URL:String = "http://farm4.static.flickr.com/3190/2662752839_249c6642b1.jpg"; private const RADIUS:Number = 200; private const SEGMENTSW:int = 16; private const SEGMENTSH:int = 12; private var loader:Loader; private var isHide:Boolean = false; private var isShift:Boolean = false; private var obj3d:DisplayObject3D; private var floorPlane:Plane; public var defaultVertices:Array; public function Main():void { // init super(0, 0, true, true); stage.quality = StageQuality.MEDIUM; viewport.opaqueBackground = 0x0; Mouse3D.enabled = true; Wonderfl.capture_delay( 3 ); new Label(this, 360, 440, "PLEASE CLICK STAGE") //renderer = new QuadrantRenderEngine(QuadrantRenderEngine.CORRECT_Z_FILTER); //フォーク用に残しておきます。 //var context:LoaderContext = new LoaderContext(true); //loader = new Loader(); //loader.contentLoaderInfo.addEventListener(Event.COMPLETE, compHandler); //loader.load(new URLRequest(IMAGE_URL), context); compHandler(); } private function compHandler(e:Event = null):void { //SaqooshaGradationマテリアルを作成 //コピー元 http://wonderfl.net/code/0b751aa7666374534030347bd27c80001b3fb2c9 var gradSprite:Sprite = new Sprite(); // Gradationクラスを作る。任意の数のカラー値を渡すことができる。 var grad:Gradation = new Gradation(0xFFFFFF, 0xFFF200, 0xFF34D7, 0x9524CC, 0x1178D9); grad.setEasing(Circ.easeInOut); for (var y:int = 0; y < 465; y++) { // getColorでグラデーションを構成する中間色を取り出す。渡す値は0〜1。滑らかにこの値を変化させることでグラデーションを作り出す。 gradSprite.graphics.beginFill(grad.getColor(y / 464)); gradSprite.graphics.drawRect(0, y, 465, 1); gradSprite.graphics.endFill(); } var material:BitmapMaterial = new MovieMaterial(gradSprite); obj3d = new Sphere(material, RADIUS, SEGMENTSW, SEGMENTSH); obj3d.y = RADIUS; scene.addChild(obj3d); //デフォルトの頂点位置を記録 defaultVertices = []; var length:uint = obj3d.geometry.vertices.length; for (var i:int = 0; i < length; i++) { var v:Vertex3D = obj3d.geometry.vertices[i]; defaultVertices[i] = { x:v.x, y:v.y, z:v.z } } // タイルの作り方はrectさんのを参考 var bmd:BitmapData = new BitmapData(2, 2, false); bmd.setPixel(0, 0, 0xDDDDDD); bmd.setPixel(0, 1, 0x333333); bmd.setPixel(1, 0, 0x333333); bmd.setPixel(1, 1, 0xDDDDDD); var floorMat:BitmapMaterial = new BitmapMaterial(bmd, true); floorMat.tiled = true; floorMat.maxU = 10, floorMat.maxV = 10; floorMat.interactive = true; floorPlane = new Plane(floorMat, 1000, 1000, 5, 5); scene.addChild(floorPlane); floorPlane.rotationX = 90; floorPlane.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, clickHandler); addEventListener(Event.ENTER_FRAME, draw); stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler); stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler); startRendering(); } private function clickHandler(e:InteractiveScene3DEvent):void { var mx:Number = viewport.interactiveSceneManager.mouse3D.x; var my:Number = viewport.interactiveSceneManager.mouse3D.y - RADIUS;//SphereをRADIUS分浮かしているため。 var mz:Number = viewport.interactiveSceneManager.mouse3D.z; var tweens:Array = []; var distance:Number; var length:uint = defaultVertices.length; for (var i:int = 0; i < length; i++) { var v:Object = defaultVertices[i];//記憶しておいた初期位置を取得 //初期位置とクリック位置の距離を算出 distance = Math.sqrt((mx - v.x) * (mx - v.x) + (my - v.y) * (my - v.y) + (mz - v.z) * (mz - v.z)); tweens.push( BetweenAS3.delay( BetweenAS3.tween(obj3d.geometry.vertices[i], { x : mx, y : my, z : mz },{ x : v.x, y : v.y, z : v.z }, 0.5, Cubic.easeIn), (distance - RADIUS * 0.5) / RADIUS ) ); } var itw:ITween = BetweenAS3.parallelTweens(tweens); if (isHide) itw = BetweenAS3.reverse(itw); if (isShift) itw = BetweenAS3.scale(itw, 5); itw.play(); isHide = !isHide; } private function draw(e:Event = null):void { // 角度に応じてカメラの位置を設定 camera.x = 1000 * Math.sin(getTimer() / 3000); camera.y = 500 * Math.sin(getTimer() / 2500) + 800; camera.z = 500; } /** * Shiftキーを押してるとスローモーションになる * macの挙動と同じように */ private function keyUpHandler(e:KeyboardEvent):void { if(e.keyCode == 16) isShift = false; } private function keyDownHandler(e:KeyboardEvent):void { if(e.keyCode == 16) isShift = true; } } } import frocessing.color.ColorLerp; import org.libspark.betweenas3.core.easing.IEasing; import org.libspark.betweenas3.easing.Linear; class Gradation { private var _colors:Array; private var _easing:IEasing; public function Gradation(...args) { _colors = args.concat(); _easing = Linear.linear; } public function setEasing(easing:IEasing):void { _easing = easing; } public function getColor(position:Number):uint { position = (position < 0 ? 0 : position > 1 ? 1 : position) * (_colors.length - 1); var idx:int = position; var alpha:Number = _easing.calculate(position - idx, 0, 1, 1); if (alpha == 0) { return _colors[idx]; } else { return ColorLerp.lerp(_colors[idx], _colors[idx + 1], alpha); } } } forked from: Ginny Effect 3D - DisplayObject3D Edition