package
{
import com.adobe.utils.*;
import flash.display.*;
import flash.display3D.*;
import flash.events.*;
import flash.geom.*;
import flash.text.*;
import flash.ui.*;
import mx.utils.*;
public class Main extends Sprite
{
private const viewWidth:int = 800;
private const viewHeight:int = 600;
private var context3D:Context3D;
private var vertexBuffer:VertexBuffer3D;
private var indexBuffer:IndexBuffer3D;
private var model:Matrix3D = new Matrix3D;
private var model2:Matrix3D = new Matrix3D;
private var view:Matrix3D = new Matrix3D;
private var projection:PerspectiveMatrix3D = new PerspectiveMatrix3D;
private var keyDown:Array = new Array;
private var tf:TextField = new TextField;
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 stage3D:Stage3D = stage.stage3Ds[0];
stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
stage3D.requestContext3D();
stage.addEventListener(KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent):void{
keyDown[e.keyCode] = true;
});
stage.addEventListener(KeyboardEvent.KEY_UP, function(e:KeyboardEvent):void{
keyDown[e.keyCode] = false;
});
stage.addEventListener(Event.DEACTIVATE, function(e:Event):void{
keyDown = new Array;
});
tf.defaultTextFormat = new TextFormat(null, 20, 0xffffff);
tf.autoSize = TextFieldAutoSize.LEFT;
addChild(tf);
}
private function onContext3DCreate(e:Event):void
{
context3D = Stage3D(e.target).context3D;
context3D.configureBackBuffer(viewWidth, viewHeight, 2);
context3D.setCulling(Context3DTriangleFace.BACK);
// vertex
const vertices:Vector.<Number> = Vector.<Number>([
// x, y, z, r, g, b,
//0, 0, 0, 1, 0, 0,
//0, 1, 0, 0, 1, 0,
//1, 0, 0, 0, 0, 1,
0, 1, 0, 1, 0, 0,
1, 0, 0, 0, 1, 0,
0, 0, 1, 0, 1, 0,
-1, 0, 0, 0, 1, 0,
0, 0, -1, 0, 1, 0,
0, -1, 0, 0, 0, 1,
]);
const perVertex:int = 6;
const numVertices:int = vertices.length / perVertex;
vertexBuffer = context3D.createVertexBuffer(numVertices, perVertex);
vertexBuffer.uploadFromVector(vertices, 0, numVertices);
// index
const indices:Vector.<uint> = Vector.<uint>([
//0, 1, 2,
0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1,
1, 5, 2, 2, 5, 3, 3, 5, 4, 4, 5, 1,
]);
indexBuffer = context3D.createIndexBuffer(indices.length);
indexBuffer.uploadFromVector(indices, 0, indices.length);
// program
var vertexProgram:AGALMiniAssembler = new AGALMiniAssembler;
vertexProgram.assemble(Context3DProgramType.VERTEX,
"m44 op va0 vc0\n" +
"mov v0 va1"
);
var fragmentProgram:AGALMiniAssembler = new AGALMiniAssembler;
fragmentProgram.assemble(Context3DProgramType.FRAGMENT,
"mov oc v0"
);
var program:Program3D = context3D.createProgram();
program.upload(vertexProgram.agalcode, fragmentProgram.agalcode);
context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
context3D.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
context3D.setProgram(program);
model2.appendScale(1, 0.5, 1);
model2.appendTranslation( -2, 0, 0);
view.appendTranslation(0, 0, -2);
projection.perspectiveFieldOfViewRH(45, viewWidth / viewHeight, 1, 500);
stage.addEventListener(Event.ENTER_FRAME, render);
}
private function render(e:Event):void
{
if (IsKeyDown(Keyboard.DOWN)) view.appendTranslation(0, 0, -0.1);
if (IsKeyDown(Keyboard.UP)) view.appendTranslation(0, 0, 0.1);
if (IsKeyDown(Keyboard.W)) model.appendRotation(-2, Vector3D.X_AXIS);
if (IsKeyDown(Keyboard.S)) model.appendRotation(2, Vector3D.X_AXIS);
if (IsKeyDown(Keyboard.A)) model.appendRotation(-2, Vector3D.Y_AXIS);
if (IsKeyDown(Keyboard.D)) model.appendRotation(2, Vector3D.Y_AXIS);
if (IsKeyDown(Keyboard.E)) model.appendRotation(-2, Vector3D.Z_AXIS);
if (IsKeyDown(Keyboard.Q)) model.appendRotation(2, Vector3D.Z_AXIS);
var v:Vector.<Vector3D> = model.decompose();
tf.text = StringUtil.substitute("driverInfo: {0}\nmodel: x={1} y={2} z={3}\nview: z={4}",
context3D.driverInfo,
degrees(v[1].x), degrees(v[1].y), degrees(v[1].z),
view.position.z.toFixed(1));
//
context3D.clear(.3, .3, .3);
var matrix:Matrix3D = new Matrix3D;
matrix.identity();
matrix.append(model);
matrix.append(view);
matrix.append(projection);
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
context3D.drawTriangles(indexBuffer);
matrix.identity();
matrix.append(model2);
matrix.append(view);
matrix.append(projection);
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
context3D.drawTriangles(indexBuffer);
context3D.present();
}
private function IsKeyDown(keyCode:uint):Boolean
{
return (keyDown[keyCode]) ? true : false;
}
private function degrees(x:Number):int
{
return x * 180 / Math.PI;
}
}
}