/* 透明な球体の頂点に、あたかも丸いシールが貼り付いているかのように見える 3D 表現 * コンテナを回転させるバージョン * (http://wonderfl.kayac.com/code/717c0d8afd7ef96747925381e6d82feffd10b4ff との比較) */ package { /** * @author YOSHIDA, Akio */ import flash.display.Sprite; import flash.events.Event; import flash.geom.Vector3D; import flash.geom.Matrix3D; import net.hires.debug.Stats; [SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")] public class MainContainerRotate extends Sprite { // 3D オブジェクトのコンテナ private var rootNode:Sprite; // 頂点 private var vctrVertics:Vector.<Vertex>; // 回転に関わる変数 private var aX:Number = 0; private var aY:Number = 0; // 中心から頂点までの距離 private const DIST:uint = 200; // コンテナのZ座標 private const DEPTH:uint = 250; public function MainContainerRotate() { createContainer(); // 3D コンテナ生成 createVertics(); // 頂点生成 this.addChild(new Stats()); // イベントハンドラ stage.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler); } // イベントハンドラ private function onEnterFrameHandler(e:Event):void { var cx:Number = stage.stageWidth / 2; var cy:Number = stage.stageHeight / 2; aX += (mouseX - cx) * 0.005; aY -= (mouseY - cy) * 0.005; rootNode.rotationX = aY; rootNode.rotationY = aX; perspective(this); zsort(); } // 投影 private function perspective(container:flash.display.DisplayObjectContainer):void { for each (var element:Vertex in vctrVertics) { element.render(container, DEPTH); } } // Zソート private function zsort():void { vctrVertics.sort( function(x:Vertex, y:Vertex):Number { return x.projz - y.projz; } ); var len:uint = vctrVertics.length; var i:int = len; while(i--) { rootNode.setChildIndex(vctrVertics[i], len-1); } } // 3D コンテナ生成 private function createContainer():void{ rootNode = new Sprite(); rootNode.x = stage.stageWidth / 2; rootNode.y = stage.stageHeight / 2; rootNode.z = DEPTH; addChild(rootNode); } // 頂点生成 private function createVertics():void { var baseNum:uint = 4; var vNum:uint = baseNum * 2; var hNum:uint = baseNum * 2; // theta:シータ(θ)は緯度、phi:ファイ(φ)は経度 var theta:Number = Math.PI / vNum; var phi:Number = Math.PI * 2 / hNum; vctrVertics = new Vector.<Vertex>(); var i:uint = 0; for (var v:int = 0; v < vNum-1 ; v++) { for (var h:int = 0; h < hNum ; h++) { var px:Number = DIST * Math.sin(theta * (v + 1)) * Math.cos(phi * h); var py:Number = DIST * Math.cos(theta * (v + 1)); var pz:Number = DIST * Math.sin(theta * (v + 1)) * Math.sin(phi * h); var vertex:Vertex = new Vertex(px, py, pz); vertex.rotationX = (v + 1) * 180 / vNum - 90; vertex.rotationY = -h * 360 / hNum + 90; rootNode.addChild(vertex); vctrVertics.push(vertex); } } } } } /* * 頂点クラス */ import flash.display.DisplayObjectContainer; import flash.display.Shape; import flash.geom.Vector3D; import flash.geom.Matrix3D; import flash.geom.PerspectiveProjection; import flash.geom.ColorTransform; class Vertex extends Shape { private var home:Vector3D = new Vector3D(); // 座標ホームポジション private var _projz:Number; // 投影Z座標 public function Vertex(x:Number, y:Number, z:Number) { this.x = home.x = x; this.y = home.y = y; this.z = home.z = _projz = z; // 描画 graphics.beginFill(0xffffff); graphics.drawCircle(0, 0, 20); graphics.endFill(); } public function render(container:DisplayObjectContainer, depth:uint):void { var mat:Matrix3D = transform.getRelativeMatrix3D(container); _projz = mat.position.z - depth; // 円に裏と表があるように見せるために色を変える処理 var ct:ColorTransform = new ColorTransform(); (_projz <= 0) ? ct.color = 0xffcc00 : ct.color = 0xcc0000; transform.colorTransform = ct; } public function get projz():Number { return _projz; } } sphere(頂点のコンテナを回転させるバージョン)