Main.as
package
{
import flash.display.Sprite;
import flash.events.Event;
/**
* ルートクラス、子スプライトを登録するのみ
* @author sc
*/
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var objFlashVars:Object = this.loaderInfo.parameters;
var strPerspectiveUV:String = objFlashVars["PerspectiveUV"];
if (strPerspectiveUV == null) { strPerspectiveUV = "yes"; }
new TestSprite(this, 0, 0, stage.stageWidth, stage.stageHeight, strPerspectiveUV.toLowerCase() != "no");
}
}
}
TestSprite.as
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.GradientType;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Vector3D;
/**
* graphics.drawTriangles の描画テスト
* @author sc
*/
public class TestSprite extends Sprite
{
private var w:Number;
private var h:Number;
private var bm:BitmapData;
private var vecSource:Vector.<Vector3D>;// 頂点座標XYZ
private var vecDest:Vector.<Number>;// 座標算出後の格納バッファXY
private var ivec:Vector.<int>;// 2枚の三角形が参照する頂点番号
private var uvt:Vector.<Number>;// UV座標、及び座標算出後の格納バッファZ
private var rotateX:Number = 0;// 横回転角度(垂直軸、単位は度)
private var floatY:Number = 0;// 縦浮遊用
private var bPerspectiveUV:Boolean;// テクスチャの透視補正を行う
/// コンストラクタ、生成した自分を即座に親クラスに貼り付ける
public function TestSprite(parent:Sprite, x:Number, y:Number, width:Number, height:Number, bPerspectiveUV:Boolean)
{
super();
this.x = x;
this.y = y;
this.w = width;
this.h = height;
this.bPerspectiveUV = bPerspectiveUV;
parent.addChild(this);
// 画像読み込み
[Embed(source = 'uv_color.png')]
var res:Class;
bm = Bitmap(new res).bitmapData;
// 正方形の板を構築
vecSource = new Vector.<Vector3D>();
vecSource.push(new Vector3D( -200, -100, -200));
vecSource.push(new Vector3D( +200, -100, -200));
vecSource.push(new Vector3D( +200, -100, +200));
vecSource.push(new Vector3D( -200, -100, +200));
vecDest = new Vector.<Number>(8);
ivec = new Vector.<int>();
ivec.push(0); ivec.push(1); ivec.push(2);
ivec.push(2); ivec.push(3); ivec.push(0);
var sizeUV:int;
sizeUV = bPerspectiveUV ? 3:2;
uvt = new Vector.<Number>(sizeUV * 3);
uvt[ 0] = 0; uvt[ 1] = 0;
uvt[sizeUV ] = 1; uvt[sizeUV +1] = 0;
uvt[sizeUV*2] = 1; uvt[sizeUV*2+1] = 1;
uvt[sizeUV*3] = 0; uvt[sizeUV*3+1] = 1;
// 毎フレーム処理登録
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
/// 毎フレーム処理
public function onEnterFrame(event:Event):void
{
var n:int;
var x:Number;// 座標算出中間値
var y:Number;
var z:Number;
var cx:Number;// スクリーンの中央座標
var cy:Number;
var rxs:Number;// 横回転用行列の一部
var rxc:Number;
var fyc:Number;// 縦浮遊用
var matrix2:Matrix = new Matrix();
var distance:Number = 400;// 視点から正方形の中心までの距離300
// スクリーンをクリア
graphics.clear();
// 背景のグラデーションを描く
matrix2.createGradientBox(w, h, Math.PI/2, 0, 0);
graphics.beginGradientFill(GradientType.LINEAR, [0x80c0ff, 0xffffff], [1, 1], [0, 255], matrix2);
graphics.moveTo(0, 0);
graphics.lineTo(w, 0);
graphics.lineTo(w, h);
graphics.lineTo(0, h);
graphics.endFill();
// 全体演算
rxs = Math.sin(rotateX * Math.PI / 180);
rxc = Math.cos(rotateX * Math.PI / 180);
fyc = Math.cos(floatY * Math.PI / 180) + 0.5;
cx = w * 0.5;
cy = h * 0.5;
// 頂点単位演算
for (n = 0; n < vecSource.length; n++)
{
// 縦軸で回転、ついでに[X右,Y上,Z前]の座標系を[X右,Y下,Z奥]に変換
x = vecSource[n].x * rxc - vecSource[n].z * rxs;
y = -vecSource[n].y * fyc;
z = -vecSource[n].z * rxc - vecSource[n].x * rxs + distance;
if (bPerspectiveUV)
{
uvt[n * 3 + 2] = 1 / z;// z値の演算結果はUV透視補正にしか使用しないためUVと一緒に扱われる
}
// 最終スクリーン座標算出
z = distance / z;
vecDest[n*2 ] = cx + x * z;
vecDest[n*2+1] = cy + y * z;
}
graphics.beginBitmapFill(bm, null, true, true);
graphics.drawTriangles(vecDest, ivec, uvt);
graphics.endFill();
rotateX++;
floatY += 0.35;
}
}
}
uv_color.png