※現在、「wonderfl build flash online」求人コンテンツ制作に関してのアンケートを実施中です!みなさまのお力添えを頂いて、続々とアンケート結果が集まっていますが、まだまだ募集しております。ご協力のほど、どうぞよろしくお願いいたします!
wonderfl運営事務局
→アンケートページ(※ログインしてからお答えいただけるようになっています。)
Your Code is very useful. Thank You
at 2010/01/04 17:11:57
by
jidolstar
[Study] Sphere using Graphics.drawTriangles forked from: [Study] Sphere using Graphics.drawTriangles
- // forked from alumican_net's [Study] Sphere using Graphics.drawTriangles
- /**
- * FlashPlayer10から追加になったdrawTrianglesで球面マッピング
- * 重複頂点はできるだけマージ
- * あとクォータニオンで回転とか
- *
- * ブログでちょっとだけ解説
- * http://blog.alumican.net/2009/12/20_014813
- *
- * @author alumican.net
- * @see texture http://visibleearth.nasa.gov/
- */
- package
- {
- import com.bit101.components.HUISlider;
- import com.bit101.components.Label;
- import com.bit101.components.RadioButton;
- import flash.display.Bitmap;
- import flash.display.BitmapData;
- import flash.display.Loader;
- import flash.display.Sprite;
- import flash.display.StageAlign;
- import flash.display.StageScaleMode;
- import flash.events.Event;
- import flash.net.URLRequest;
- import flash.system.LoaderContext;
- import net.hires.debug.Stats;
- /**
- * FP10Sphere
- *
- * @author alumican
- */
- public class FP10Sphere extends Sprite
- {
- //----------------------------------------
- //CLASS CONSTANTS
- //----------------------------------------
- //VARIABLES
- /**
- * スフィア
- */
- private var _sphere:Sphere;
- /**
- * 回転速度
- */
- private var _vx:Number;
- private var _vy:Number;
- //----------------------------------------
- //STAGE INSTANCES
- //----------------------------------------
- //METHODS
- /**
- * コンストラクタ
- */
- public function FP10Sphere():void
- {
- stage.align = StageAlign.TOP_LEFT;
- stage.scaleMode = StageScaleMode.NO_SCALE;
- stage.frameRate = 60;
- addChild(new Stats());
- _createSphere();
- }
- /**
- * 初期化
- */
- private function _createSphere():void
- {
- var texture:BitmapData;
- var loader:Loader = new Loader();
- loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void
- {
- var texture:BitmapData = Bitmap(loader.contentLoaderInfo.content).bitmapData;
- _vx = 0;
- _vy = 0;
- //UI色々
- var vertexCountLabel:Label = new Label(stage, 100, 86, "");
- var surfaceCountLabel:Label = new Label(stage, 180, 86, "");
- function updateCount():void
- {
- vertexCountLabel.text = "vertex : " + String(_sphere.vertexCount);
- surfaceCountLabel.text = "surface : " + String(_sphere.surfaceCount);
- }
- new Label(stage, 300, 10, "PROJECTOR");
- new RadioButton(stage, 300, 30, "Utils3D.projectVectors" , true , function(e:Event):void { _sphere.useProjectVectors = true; } );
- new RadioButton(stage, 300, 50, "Matrix3D.transformVectors", false, function(e:Event):void { _sphere.useProjectVectors = false; } );
- new Label(stage, 100, 10, "SHAPE");
- var segWSlider:HUISlider = new HUISlider(stage, 100, 26, "Segment W", function(e:Event):void { _sphere.segmentW = Math.round(e.target.value); updateCount(); } );
- var segHSlider:HUISlider = new HUISlider(stage, 100, 46, "Segment H", function(e:Event):void { _sphere.segmentH = Math.round(e.target.value); updateCount(); } );
- var radiusSlider:HUISlider = new HUISlider(stage, 100, 66, "Radius" , function(e:Event):void { _sphere.radius = Math.round(e.target.value); } );
- radiusSlider.minimum = 10;
- radiusSlider.maximum = 200;
- radiusSlider.labelPrecision = 0;
- radiusSlider.value = 150;
- segWSlider.minimum = segHSlider.minimum = 2;
- segWSlider.maximum = segHSlider.maximum = 64;
- segWSlider.labelPrecision = segHSlider.labelPrecision = 0;
- segWSlider.value = 16;
- segHSlider.value = 8;
- //スフィアを生成する
- _sphere = addChild(new Sphere(texture, radiusSlider.value, segWSlider.value, segHSlider.value)) as Sphere;
- _sphere.x = stage.stageWidth * 0.5;
- _sphere.y = stage.stageHeight * 0.5 + 50;
- updateCount();
- addEventListener(Event.ENTER_FRAME, _update);
- });
- loader.load(new URLRequest("http://lab.alumican.net/wonderfl/fp10sphere/texture.png"), new LoaderContext(true));
- }
- /**
- * 毎フレーム実行
- * @param e
- */
- private function _update(e:Event):void
- {
- //回転
- _sphere.rotateByQuaternion(
- _vx += (-(mouseY / stage.stageHeight - 0.5) * 10 - _vx) * 0.3,
- _vy += ( (mouseX / stage.stageWidth - 0.5) * 10 - _vy) * 0.3,
- 0
- );
- //レンダリング
- _sphere.render();
- }
- }
- }
- import flash.display.BitmapData;
- import flash.display.Graphics;
- import flash.display.Sprite;
- import flash.display.TriangleCulling;
- import flash.geom.Matrix3D;
- import flash.geom.Utils3D;
- import flash.geom.Vector3D;
- /*****************************************//**
- * 頂点座標情報
- *
- * @author alumican.net
- */
- internal class Vertex3D
- {
- //----------------------------------------
- //CLASS CONSTANTS
- //----------------------------------------
- //VARIABLES
- /**
- * 3D座標
- */
- public var x:Number;
- public var y:Number;
- public var z:Number;
- /**
- * UV座標
- */
- public var u:Number;
- public var v:Number;
- /**
- * 頂点インデックス
- */
- public var index:int;
- //----------------------------------------
- //STAGE INSTANCES
- //----------------------------------------
- //METHODS
- /**
- * コンストラクタ
- */
- public function Vertex3D():void
- {
- index = -1;
- }
- }
- /*****************************************//**
- * 3Dオブジェクトの基底クラス
- *
- * @author alumican.net
- */
- internal class Object3D extends Sprite
- {
- //----------------------------------------
- //CLASS CONSTANTS
- static public const PI:Number = Math.PI;
- static public const PI2:Number = PI * 2;
- static public const TO_RADIAN:Number = PI / 180;
- static public const TO_DEGREE:Number = 180 / PI;
- //----------------------------------------
- //VARIABLES
- /**
- * レンダリング先
- */
- public var _viewport:Sprite;
- /**
- * テクスチャ画像
- */
- public var _texture:BitmapData;
- /**
- * 3D変形マトリックス
- */
- private var _transform3D:Matrix3D;
- /**
- * 3D頂点情報
- */
- private var _vertices3D:Vector.<Number>;
- private var _indices:Vector.<int>;
- private var _uvData:Vector.<Number>;
- /**
- * 頂点/サーフィス数
- */
- public function get vertexCount():uint { return _vertices3D.length / 3; }
- public function get surfaceCount():uint { return _indices.length / 3; }
- /**
- * プロジェクト後の座標
- */
- private var _transformedVertices3D:Vector.<Number>;
- private var _transformedVertices2D:Vector.<Number>;
- /**
- * projectVectors用
- */
- private var _uvtData:Vector.<Number>;
- /**
- * クォータニオン
- */
- private var _qx:Number;
- private var _qy:Number;
- private var _qz:Number;
- private var _qw:Number;
- /**
- * レンダリング方法の指定
- * true : projectVectors
- * false : transformVectors
- */
- public var useProjectVectors:Boolean;
- //----------------------------------------
- //STAGE INSTANCES
- //----------------------------------------
- //METHODS
- /**
- * コンストラクタ
- */
- public function Object3D(texture:BitmapData = null):void
- {
- _viewport = addChild( new Sprite() ) as Sprite;
- _texture = texture;
- useProjectVectors = true;
- _transform3D = new Matrix3D();
- _transform3D.identity();
- _qx = _qy = _qz = 0;
- _qw = 1;
- create();
- }
- /**
- * オブジェクトを生成する
- */
- public function create():void
- {
- _vertices3D = new Vector.<Number>();
- _indices = new Vector.<int>();
- _uvData = new Vector.<Number>();
- _createVetices(_vertices3D, _indices, _uvData);
- _transformedVertices2D = new Vector.<Number>(_uvData.length, true);
- _transformedVertices3D = new Vector.<Number>(_vertices3D.length, true);
- _uvtData = new Vector.<Number>(_vertices3D.length, true);
- var n:uint = _uvData.length;
- var i:uint = 0;
- var j:uint = 0;
- while (i < n)
- {
- _uvtData[j++] = _uvData[i++];
- _uvtData[j++] = _uvData[i++];
- _uvtData[j++] = null;
- }
- }
- /**
- * 3D頂点座標、頂点インデックス、UVデータを生成する(オーバーライド用)
- * @param vertices3D
- * @param indices
- * @param uvData
- */
- protected function _createVetices(vertices3D:Vector.<Number>, indices:Vector.<int>, uvData:Vector.<Number>):void
- {
- }
- /**
- * オブジェクトをレンダリングする
- */
- public function render():void
- {
- if (!_texture) return;
- if (useProjectVectors)
- {
- //projectVectorsを使う
- Utils3D.projectVectors(_transform3D, _vertices3D, _transformedVertices2D, _uvtData);
- }
- else
- {
- //transformVectorsを使う
- _transform3D.transformVectors(_vertices3D, _transformedVertices3D);
- var n:uint = _uvData.length,
- j:uint = 0;
- for (var i:uint = 0; i < n; i += 2)
- {
- _transformedVertices2D[i ] = _transformedVertices3D[j ];
- _transformedVertices2D[i + 1] = _transformedVertices3D[j + 1];
- j += 3;
- }
- }
- var g:Graphics = _viewport.graphics;
- g.clear();
- g.beginBitmapFill(_texture, null, false, false);
- g.drawTriangles(_transformedVertices2D, _indices, _uvData, TriangleCulling.NEGATIVE);
- }
- /**
- * クォータニオンを用いた回転を付与する
- * @param rotateX
- * @param rotateY
- * @param rotateZ
- * @param useDegree
- */
- public function rotateByQuaternion(rotateX:Number, rotateY:Number, rotateZ:Number, useDegree:Boolean = true):void
- {
- if (useDegree)
- {
- rotateX *= TO_RADIAN;
- rotateY *= TO_RADIAN;
- rotateZ *= TO_RADIAN;
- }
- //----------------------------------------
- //回転クォータニオンの生成
- var fSinPitch:Number = Math.sin(rotateY * 0.5),
- fCosPitch:Number = Math.cos(rotateY * 0.5),
- fSinYaw:Number = Math.sin(rotateZ * 0.5),
- fCosYaw:Number = Math.cos(rotateZ * 0.5),
- fSinRoll:Number = Math.sin(rotateX * 0.5),
- fCosRoll:Number = Math.cos(rotateX * 0.5),
- fCosPitchCosYaw:Number = fCosPitch * fCosYaw,
- fSinPitchSinYaw:Number = fSinPitch * fSinYaw,
- rx:Number = fSinRoll * fCosPitchCosYaw - fCosRoll * fSinPitchSinYaw,
- ry:Number = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw,
- rz:Number = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw,
- rw:Number = fCosRoll * fCosPitchCosYaw + fSinRoll * fSinPitchSinYaw,
- //----------------------------------------
- //元のクォータニオンに回転を合成
- qx:Number = _qw * rx + _qx * rw + _qy * rz - _qz * ry,
- qy:Number = _qw * ry - _qx * rz + _qy * rw + _qz * rx,
- qz:Number = _qw * rz + _qx * ry - _qy * rx + _qz * rw,
- qw:Number = _qw * rw - _qx * rx - _qy * ry - _qz * rz,
- //----------------------------------------
- //正規化
- norm:Number = Math.sqrt(qx * qx + qy * qy + qz * qz + qw * qw),
- inv:Number,
- //----------------------------------------
- //行列へ変換
- xx:Number,
- xy:Number,
- xz:Number,
- xw:Number,
- yy:Number,
- yz:Number,
- yw:Number,
- zz:Number,
- zw:Number,
- m:Vector.<Number> = _transform3D.rawData;
- //----------------------------------------
- //正規化
- if(((norm < 0) ? -norm : norm) < 0.000001)
- {
- qx = qy = qz = 0.0;
- qw = 1.0;
- }
- else
- {
- inv = 1 / norm;
- qx *= inv;
- qy *= inv;
- qz *= inv;
- qw *= inv;
- }
- //----------------------------------------
- //行列へ変換
- xx = qx * qx;
- xy = qx * qy;
- xz = qx * qz;
- xw = qx * qw;
- yy = qy * qy;
- yz = qy * qz;
- yw = qy * qw;
- zz = qz * qz;
- zw = qz * qw;
- m[0] = 1 - 2 * (yy + zz);
- m[1] = 2 * (xy - zw);
- m[2] = 2 * (xz + yw);
- m[4] = 2 * (xy + zw);
- m[5] = 1 - 2 * (xx + zz);
- m[6] = 2 * (yz - xw);
- m[8] = 2 * (xz - yw);
- m[9] = 2 * (yz + xw);
- m[10] = 1 - 2 * (xx + yy);
- _transform3D.rawData = m;
- //----------------------------------------
- //クォータニオンの保存
- _qx = qx;
- _qy = qy;
- _qz = qz;
- _qw = qw;
- }
- }
- /*****************************************//**
- * スフィア
- *
- * @author alumican.net
- */
- class Sphere extends Object3D
- {
- //----------------------------------------
- //CLASS CONSTANTS
- //----------------------------------------
- //VARIABLES
- /**
- * 半径
- */
- public function get radius():Number { return _radius; }
- public function set radius(value:Number):void { _radius = value; create(); }
- private var _radius:Number;
- /**
- * 水平方向の分割数
- */
- public function get segmentW():uint { return _segmentW; }
- public function set segmentW(value:uint):void { _segmentW = value; create(); }
- private var _segmentW:uint;
- /**
- * 垂直方向の分割数
- */
- public function get segmentH():uint { return _segmentH; }
- public function set segmentH(value:uint):void { _segmentH = value; create(); }
- private var _segmentH:uint;
- //----------------------------------------
- //METHODS
- /**
- * コンストラクタ
- */
- public function Sphere(texture:BitmapData = null, radius:Number = 100, segmentW:uint = 8, segmentH:uint = 6):void
- {
- _radius = radius;
- _segmentW = segmentW;
- _segmentH = segmentH;
- super(texture);
- }
- /**
- * 頂点情報を生成する
- */
- override protected function _createVetices(vertices3D:Vector.<Number>, indices:Vector.<int>, uvData:Vector.<Number>):void
- {
- var i:uint,
- j:uint,
- n:uint,
- p:Vertex3D,
- index:uint,
- x:Number,
- y:Number,
- u:Number,
- v:Number,
- angleU:Number,
- angleV:Number,
- points:Vector.<Vertex3D> = new Vector.<Vertex3D>(),
- poly:Vector.<Vertex3D> = new Vector.<Vertex3D>(4),
- poleN:Vertex3D,
- poleS:Vertex3D,
- segW:uint = _segmentW + 1,
- segH:uint = _segmentH + 1;
- //頂点の生成
- for (i = 0; i < segH; ++i)
- {
- for (j = 0; j < segW; ++j)
- {
- p = new Vertex3D();
- //このあたりの頂点をマージしたい
- //if (i == 0 ) { if (j == 0) poleN = p; else p = poleN; } // テクスチャ上端に対応する頂点
- //if (i == segH - 1) { if (j == 0) poleS = p; else p = poleS; } // テクスチャ下端に対応する頂点
- //if (j == segW - 1) { p = _points[_points.length - segW + 1]; } // テクスチャ右端に対応する頂点
- u = j / (segW - 1);
- v = i / (segH - 1);
- angleU = u * PI2;
- angleV = v * PI;
- y = -_radius * Math.cos(angleV);
- x = _radius * Math.sin(angleU) * Math.sin(angleV);
- z = -_radius * Math.cos(angleU) * Math.sin(angleV);
- p.x = x;
- p.y = y;
- p.z = z;
- p.u = u;
- p.v = v;
- points.push(p);
- }
- }
- //ポリゴンの生成
- n = points.length;
- index = 0;
- for (i = 0; i < n; ++i)
- {
- if (i + segW + 1 >= n) break;
- if ((i + 1) % segW == 0) continue;
- poly[0] = points[i];
- poly[1] = points[i + 1];
- poly[2] = points[i + segW];
- poly[3] = points[i + segW + 1];
- for (j = 0; j < 4; ++j)
- {
- //新規頂点を追加
- if ((p = poly[j]).index == -1)
- {
- p.index = index++;
- //3D座標
- vertices3D.push(p.x, p.y, p.z);
- //UV座標
- uvData.push(p.u, p.v);
- }
- }
- //頂点インデックスに追加(時計回り)
- indices.push(
- poly[0].index, poly[1].index, poly[2].index,
- poly[1].index, poly[3].index, poly[2].index
- );
- }
- }
- }
notice:



