開発環境 Apache Flex SDK 4.12.1
FlashDevelop 4.6.2.5
実行環境 Microsoft Windows 8.1 (64bit)
プロジェクトの種類 ActionScript 3/AS3 Project
プロジェクト名 Camera3D


参考

Main.as
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;
        }
 
    }
 
}
 
最終更新:2014年07月14日 17:19