package
{
import com.adobe.utils.*;
import flash.display.*;
import flash.display3D.*;
import flash.display3D.textures.Texture;
import flash.events.*;
import flash.geom.*;
import flash.text.*;
import flash.ui.Keyboard;
import flash.utils.getTimer;
import mx.utils.StringUtil;
public class Main extends Sprite
{
[Embed(source="6001.png")]
private const TextureBitmap:Class;
private var context3D:Context3D;
private var vertexBuffer:VertexBuffer3D;
private var indexBuffer:IndexBuffer3D;
private var program:Program3D;
private var texture:Texture;
private var projectionTransform:PerspectiveMatrix3D;
private var cameraWorldTransform:Matrix3D;
private var viewTransform:Matrix3D;
private var cameraLinearVelocity:Vector3D;
private var cameraRotationVelocity:Number;
private var cameraRotationAcceleration:Number;
private var cameraLinearAccelerationZ:Number;
private var cameraLinearAccelerationX:Number;
private var tf:TextField = new TextField;
private const MAX_FORWARD_VELOCITY:Number = 0.05;
private const MAX_ROTATION_VELOCITY:Number = 1;
private const LINEAR_ACCELERATION:Number = 0.001;
private const ROTATION_ACCELERATION:Number = 0.02;
private const DAMPING:Number = 1.09;
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
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, initMolehill);
stage.stage3Ds[0].requestContext3D();
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
addEventListener(Event.ENTER_FRAME, onRender);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownEventHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpEventHandler);
tf.defaultTextFormat = new TextFormat(null, 20, 0xffffff);
tf.autoSize = TextFieldAutoSize.LEFT;
addChild(tf);
}
private function keyDownEventHandler(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case Keyboard.LEFT:
cameraRotationAcceleration = -ROTATION_ACCELERATION;
break;
case Keyboard.RIGHT:
cameraRotationAcceleration = ROTATION_ACCELERATION;
break;
case Keyboard.W:
cameraLinearAccelerationZ = LINEAR_ACCELERATION;
break;
case Keyboard.S:
cameraLinearAccelerationZ = -LINEAR_ACCELERATION;
break;
case Keyboard.A:
cameraLinearAccelerationX = -LINEAR_ACCELERATION;
break;
case Keyboard.D:
cameraLinearAccelerationX = LINEAR_ACCELERATION;
break;
}
}
private function keyUpEventHandler(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case Keyboard.LEFT:
case Keyboard.RIGHT:
cameraRotationAcceleration = 0;
break;
case Keyboard.W:
case Keyboard.S:
cameraLinearAccelerationZ = 0;
break;
case Keyboard.A:
case Keyboard.D:
cameraLinearAccelerationX = 0;
break;
}
}
private function initMolehill(e:Event):void
{
context3D = stage.stage3Ds[0].context3D;
context3D.configureBackBuffer(800, 600, 2);
var vertices:Vector.<Number> = Vector.<Number>([
// x, y, z, u, v
-0.6, -0.3, 0, 0, 1,
-0.6, 0.3, 0, 0, 0,
0.6, 0.3, 0, 1, 0,
0.6, -0.3, 0, 1, 1,
]);
vertexBuffer = context3D.createVertexBuffer(4, 5);
vertexBuffer.uploadFromVector(vertices, 0, 4);
indexBuffer = context3D.createIndexBuffer(6);
indexBuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 2, 3, 0]), 0, 6);
var bitmap:Bitmap = new TextureBitmap;
texture = context3D.createTexture(
bitmap.bitmapData.width, bitmap.bitmapData.height, Context3DTextureFormat.BGRA, false);
texture.uploadFromBitmapData(bitmap.bitmapData);
var vertexShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler;
vertexShaderAssembler.assemble(Context3DProgramType.VERTEX,
"m44 op va0 vc0\n" +
"mov v0 va1"
);
var fragmentShaderAssembler:AGALMiniAssembler = new AGALMiniAssembler;
fragmentShaderAssembler.assemble(Context3DProgramType.FRAGMENT,
"tex ft1 v0 fs0 <2d,linear,nomip>\n" +
"mov oc ft1"
);
program = context3D.createProgram();
program.upload(vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
cameraWorldTransform = new Matrix3D;
cameraWorldTransform.appendTranslation(0, 0, -2);
//viewTransform = new Matrix3D;
viewTransform = cameraWorldTransform.clone();
viewTransform.invert();
cameraLinearVelocity = new Vector3D;
cameraRotationVelocity = 0;
cameraLinearAccelerationZ = 0;
cameraLinearAccelerationX = 0;
cameraRotationAcceleration = 0;
projectionTransform = new PerspectiveMatrix3D;
var aspect:Number = 4 / 3;
var zNear:Number = 0.1;
var zFar:Number = 1000;
var fov:Number = 45 * Math.PI / 180;
projectionTransform.perspectiveFieldOfViewLH(fov, aspect, zNear, zFar);
context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
context3D.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
context3D.setTextureAt(0, texture);
context3D.setProgram(program);
}
private function onRender(e:Event):void
{
if ( !context3D)
return;
context3D.clear(0.5, 0.5, 0.5, 1);
updateViewMatrix();
var m:Matrix3D = new Matrix3D;
//m.appendRotation(getTimer() / 30, Vector3D.Y_AXIS);
//m.appendRotation(getTimer() / 10, Vector3D.X_AXIS);
m.appendTranslation(0, 0, 2);
m.append(viewTransform);
m.append(projectionTransform);
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
context3D.drawTriangles(indexBuffer);
context3D.present();
tf.text = StringUtil.substitute(
"RotationVelocity:{0}\nLinearVelocityZ:{1}\nLinearVelocityX:{2}",
cameraRotationVelocity.toFixed(2),
cameraLinearVelocity.z.toFixed(3),
cameraLinearVelocity.x.toFixed(3));
}
private function updateViewMatrix():void
{
cameraLinearVelocity.z = calculateUpdatedVelocity(
cameraLinearVelocity.z, cameraLinearAccelerationZ, MAX_FORWARD_VELOCITY);
cameraLinearVelocity.x = calculateUpdatedVelocity(
cameraLinearVelocity.x, cameraLinearAccelerationX, MAX_FORWARD_VELOCITY);
cameraRotationVelocity = calculateUpdatedVelocity(
cameraRotationVelocity, cameraRotationAcceleration, MAX_ROTATION_VELOCITY);
cameraWorldTransform.appendRotation(
cameraRotationVelocity, Vector3D.Y_AXIS, cameraWorldTransform.position);
cameraWorldTransform.position = cameraWorldTransform.transformVector(cameraLinearVelocity);
viewTransform.copyFrom(cameraWorldTransform);
viewTransform.invert();
}
private function calculateUpdatedVelocity(
curVelocity:Number, curAcceleration:Number, maxVelocity:Number):Number
{
var newVelocity:Number;
if (curAcceleration != 0)
{
newVelocity = curVelocity + curAcceleration;
if (newVelocity > maxVelocity)
{
newVelocity = maxVelocity;
}
else if (newVelocity < -maxVelocity)
{
newVelocity = - maxVelocity;
}
}
else
{
newVelocity = curVelocity / DAMPING;
}
return newVelocity;
}
}
}