[test]stage3d, AGAL(2)
Stage3Dテスト
@author okoi
/**
* Copyright okoi ( http://wonderfl.net/user/okoi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/bVJX
*/
/**
* Stage3Dテスト
*/
package
{
import com.adobe.utils.AGALMiniAssembler;
import com.adobe.utils.PerspectiveMatrix3D;
import flash.display.Sprite;
import flash.display.Stage3D;
import flash.display3D.IndexBuffer3D;
import flash.display3D.VertexBuffer3D;
import flash.events.Event;
import flash.display3D.Context3D;
import flash.display3D.Context3DRenderMode;
import flash.display3D.Context3DVertexBufferFormat;
import flash.display3D.Context3DProgramType;
import flash.display3D.Context3DTriangleFace;
import flash.display3D.Program3D;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.PerspectiveProjection;
import flash.utils.ByteArray;
import flash.geom.Vector3D;
[SWF(width = "465", height = "465", frameRate="60")]
/**
* @author okoi
*/
public class Main extends Sprite
{
private static const WIDTH:int = 465;
private static const HEIGHT:int = 465;
private static const DEPTH:int = 465;
private var _stage3D:Stage3D;
private var _context3D:Context3D;
private var _renderProgram:Program3D; // レンダリングプログラム
private var _rotation:Number = 0;
private var _camera:Camera;
private var _matViewPort:PerspectiveMatrix3D;
private var _tetrahedral:Tetrahedral;
private var _count:uint = 0;
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
_stage3D = stage.stage3Ds[0];
_stage3D.addEventListener( Event.CONTEXT3D_CREATE, Context3DCreateHandler );
_stage3D.requestContext3D( Context3DRenderMode.AUTO );
}
private function Context3DCreateHandler( e:Event ) : void
{
_context3D = _stage3D.context3D;
_context3D.enableErrorChecking = true;
_context3D.configureBackBuffer( WIDTH, HEIGHT, 0, true );
_context3D.setCulling(Context3DTriangleFace.BACK);
InitViewPort();
InitCamera();
_renderProgram = _context3D.createProgram();
InitShader();
_tetrahedral = new Tetrahedral( _context3D );
addEventListener( Event.ENTER_FRAME, EnterFrameHandler );
}
private function InitShader() : void
{
var agalAssembler:AGALMiniAssembler = new AGALMiniAssembler();
var code:String = "";
var vShader:ByteArray;
var fShader:ByteArray;
code = "m44 op, va0, vc0\n";
code += "mov v0, va1\n";
vShader = agalAssembler.assemble( Context3DProgramType.VERTEX, code );
code = "mov oc, v0\n";
fShader = agalAssembler.assemble( Context3DProgramType.FRAGMENT, code );
_renderProgram.upload( vShader, fShader );
_context3D.setProgram(_renderProgram);
}
private function InitCamera() : void {
_camera = new Camera();
_camera.InitProjection( 45 * Math.PI / 180, WIDTH / HEIGHT, 0.1, 3000 );
_camera.InitView( new Vector3D(0, 0, -15), new Vector3D(0, 0, 0), new Vector3D(0, 1, 0) );
}
/**
* スクリーン変換行列の作成
*/
private function InitViewPort() : void {
// 通常 WIDTH / 2 とやるような所を 2 / WIDTH にしている
_matViewPort = new PerspectiveMatrix3D();
// _matViewPort.appendScale( WIDTH / 2, HEIGHT / 2, 1 );
// _matViewPort.appendTranslation( -WIDTH / 2, -HEIGHT / 2, 0 );
// _matViewPort.orthoLH( WIDTH, HEIGHT, 0.1, 3000 );
}
private function EnterFrameHandler( e:Event ) : void
{
var vBuf:VertexBuffer3D;
var cBuf:VertexBuffer3D;
var iBuf:IndexBuffer3D;
var mat:Matrix3D = new Matrix3D();
// カメラ回転処理
// var cx:Number = Math.cos( ((_count/10) % 360) * Math.PI / 180 ) * 2;
// var cz:Number = Math.sin( ((_count/10) % 360) * Math.PI / 180 ) * 2;
_camera.InitView( new Vector3D(0, 0, -2), new Vector3D(0, 0, 0), new Vector3D(0, 1, 0) );
_context3D.clear();
_tetrahedral.Rotation( (_count % 360), new Vector3D( 0, 1, 0.5 ), true );
_context3D.setVertexBufferAt( 0, _tetrahedral.vBuf, 0, Context3DVertexBufferFormat.FLOAT_3 ); // va0
_context3D.setVertexBufferAt( 1, _tetrahedral.cBuf, 0, Context3DVertexBufferFormat.FLOAT_3 ); // va1
mat.append( _tetrahedral.matrix ); // ワールド座標変換
mat.append( _camera.view ); // ビュー変換変換
mat.append( _camera.projection ); // プロジェクション座標変換
//mat.append( _matViewPort ); // スクリーン座標変換
_context3D.setProgramConstantsFromMatrix( Context3DProgramType.VERTEX, 0, mat, true ); // vc0
_context3D.drawTriangles( _tetrahedral.iBuf );
_context3D.present();
_count++;
}
}
}
import com.adobe.utils.PerspectiveMatrix3D
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
import flash.display3D.VertexBuffer3D;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Context3D;
/**
* カメラクラス
*/
class Camera {
private var _view:PerspectiveMatrix3D;
private var _projection:PerspectiveMatrix3D;
public function Camera() {
_view = new PerspectiveMatrix3D();
_projection = new PerspectiveMatrix3D();
}
/**
* 射影変換行列の設定を行う
* @param fov
* @param aspect
* @param zn
* @param zf
*/
public function InitProjection( fov:Number, aspect:Number, zn:Number, zf:Number ) : void {
_projection.perspectiveFieldOfViewLH( fov, aspect, zn, zf );
}
/**
* ビュー行列の設定を行う
* PerspectiveMatrix3DのlookAtLH,RHはバグがあるっぽいので自力計算
* @param from
* @param at
* @param up
*/
public function InitView( from:Vector3D, at:Vector3D, up:Vector3D ) : void {
var vz:Vector3D = at.subtract( from );
vz.normalize();
var vx:Vector3D = up.crossProduct( vz );
vx.normalize();
var vy:Vector3D = vz.crossProduct( vx );
vy.normalize();
var vtx:Number = vx.dotProduct( from ) * -1;
var vty:Number = vy.dotProduct( from ) * -1;
var vtz:Number = vz.dotProduct( from ) * -1;
_view.identity();
_view.rawData = Vector.<Number>([
vx.x, vy.x, vz.x, 0,
vx.y, vy.y, vz.y, 0,
vx.z, vy.z, vz.z, 0,
vtx, vty, vtz, 1,
]);
}
public function get mat():Matrix3D {
var mat:Matrix3D = new Matrix3D();
mat.identity();
mat.append( _view );
mat.append( _projection );
return mat;
}
public function get view() : Matrix3D { return _view; }
public function get projection() : Matrix3D { return _projection; }
}
class Tetrahedral {
private var _vBuf:VertexBuffer3D;
private var _cBuf:VertexBuffer3D;
private var _iBuf:IndexBuffer3D;
private var _matRotation:Matrix3D;
public function Tetrahedral( context3D:Context3D ) {
var radius:Number = 1;
var pi0:Number = 0;
var pi30:Number = 30 * Math.PI / 180;
var pi120:Number = (2 / 3) * Math.PI;
var pi150:Number = 150 * Math.PI / 180;
var pi240:Number = pi120 * 2;
var pi270:Number = 270 * Math.PI / 180;
var pathLength:Number = radius * Math.sqrt(3);
var height:Number = pathLength * Math.sqrt( 2 / 3 );
trace( height );
_vBuf = context3D.createVertexBuffer( 4, 3 );
_vBuf.uploadFromVector( Vector.<Number>([
Math.cos( pi30 ) * radius, -height/2, Math.sin( pi30 ) * radius,
Math.cos( pi150 ) * radius, -height/2, Math.sin( pi150 ) * radius,
Math.cos( pi270 ) * radius, -height/2, Math.sin( pi270 ) * radius,
0, height/2, 0,
]),
0,
4
);
_cBuf = context3D.createVertexBuffer( 4, 3 );
_cBuf.uploadFromVector( Vector.<Number>([
1, 0, -0,
0, 1, 0,
0, 0, 1,
1, 1, 1,
]),
0,
4
);
_iBuf = context3D.createIndexBuffer( 3 * 4 );
_iBuf.uploadFromVector( Vector.<uint>([
0, 3, 1,
1, 3, 2,
2, 3, 0,
0, 1, 2,
/*
1, 2, 3,
0, 2, 3,
*/
]),
0,
3 * 4
);
_matRotation = new Matrix3D();
_matRotation.identity();
}
public function get vBuf() : VertexBuffer3D {
return _vBuf;
}
public function get cBuf() : VertexBuffer3D {
return _cBuf;
}
public function get iBuf() : IndexBuffer3D {
return _iBuf;
}
public function get matrix() : Matrix3D {
var mat:Matrix3D = new Matrix3D();
mat.append( _matRotation );
return mat;
}
public function Rotation( degree:Number, axis:Vector3D, reset:Boolean = false ) : void {
if( reset ) _matRotation.identity();
_matRotation.appendRotation( degree, axis );
}
}