sphere(頂点のコンテナを回転させるバージョン)
透明な球体の頂点に、あたかも丸いシールが貼り付いているかのように見える 3D 表現
* コンテナを回転させるバージョン
* (http://wonderfl.kayac.com/code/717c0d8afd7ef96747925381e6d82feffd10b4ff との比較)
/* 透明な球体の頂点に、あたかも丸いシールが貼り付いているかのように見える 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; }
}