// 頂点を setPixel によって描いた sphere // 以下の URL の sphere とは、レンダリングでビミョーに違っています。 // wonderfl.kayac.com/code/717c0d8afd7ef96747925381e6d82feffd10b4ff package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.geom.Vector3D; import flash.geom.Matrix3D; import flash.geom.PerspectiveProjection; [SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")] public class Main extends Sprite { // プロジェクション private var fov:PerspectiveProjection; // 3D オブジェクトのコンテナ private var canvas:BitmapData; // 頂点格納 Vector private var vctrVertics:Vector.<Vertex>; // 回転に関わる変数 private var aX:Number = 0; private var aY:Number = 0; // 定数 private const SW:uint = 465; // stage.stageWidth private const SH:uint = 465; // stage.stageHeight private const DIST:uint = 150; // 中心から頂点までの距離 private const XOFF:Number = SW / 2; // stageWidth / 2 private const YOFF:Number = SH / 2; // stageheight / 2 public function Main() { Wonderfl.capture_delay(10); createCanvas(); // キャンバス生成 createProjection(); // プロジェクション生成 createVertics(); // 頂点生成 // イベントハンドラ stage.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler); } // onEnterFrame private function onEnterFrameHandler(e:Event):void { // 回転角度を増加 aX += (mouseX - XOFF) * 0.005; aY -= (mouseY - YOFF) * 0.005; // 変換行列生成 var mat:Matrix3D = new Matrix3D(); // 回転を変換行列に合成 mat.appendRotation(aX, Vector3D.Y_AXIS); mat.appendRotation(aY, Vector3D.X_AXIS); mat.appendRotation(aY, Vector3D.Z_AXIS); perspective(mat, fov); // 投影 render(); // レンダリング } // 投影 private function perspective(mat:Matrix3D, fov:PerspectiveProjection):void { for each (var element:Vertex in vctrVertics) { element.perspective(mat, fov); } } // レンダリング private function render():void { canvas.lock(); canvas.fillRect(canvas.rect, 0x000000); for each (var element:Vertex in vctrVertics) { canvas.setPixel(element.x+XOFF, element.y+YOFF, 0xffffff); } canvas.unlock(); } // キャンバス生成 private function createCanvas():void{ canvas = new BitmapData(SW, SH, false, 0x000000); addChild(new Bitmap(canvas)); } // プロジェクション生成 private function createProjection():void { fov = new PerspectiveProjection(); fov.fieldOfView = 60; // 視野角の設定 } // 頂点生成 private function createVertics():void { var baseNum:uint = 20; 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) * Math.cos(phi * h); var pz:Number = DIST * Math.sin(theta * v) * Math.sin(phi * h); var py:Number = DIST * Math.cos(theta * v); var vertex:Vertex = new Vertex(px, py, pz); vctrVertics.push(vertex); } } } } } /* * 頂点クラス */ import flash.geom.Vector3D; import flash.geom.Matrix3D; import flash.geom.PerspectiveProjection; class Vertex { private var home:Vector3D = new Vector3D(); // 座標ホームポジション private var proj:Vector3D = new Vector3D(); // 投影座標 public function Vertex(x:Number, y:Number, z:Number) { home.x = x; home.y = y; home.z = z; } /** * 投影処理(透視投影) */ public function perspective(mat:Matrix3D, fov:PerspectiveProjection):void { proj = mat.transformVector(home); proj.w = fov.focalLength / (fov.focalLength + proj.z); proj.project(); } // getter public function get x():Number { return proj.x; } public function get y():Number { return proj.y; } public function get z():Number { return proj.z; } public function get w():Number { return proj.w; } } sphere by setPixel