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

作りかけ。


Main.as
package 
{
    import com.adobe.utils.*;
    import flash.display.Sprite;
    import flash.display3D.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.text.*;
    import flash.ui.Keyboard;
    import mx.utils.StringUtil;
 
    public class Main extends Sprite 
    {
        private var context3D:Context3D;
        private var vertexBuffer:VertexBuffer3D;
        private var indexBuffer:IndexBuffer3D;
 
        private var projectionTransform:PerspectiveMatrix3D;
        private var cameraPos:Vector3D = new Vector3D(0, 200, 0);
        private var cameraFront:Vector3D = new Vector3D(0, 0, 1);
        private var cameraUp:Vector3D = new Vector3D(0, 1, 0);
        private var viewTransform:Matrix3D;
 
        private var velocity:Vector3D = new Vector3D(1, 0, 0);
        private var roll:Number = 0;
        private var pitch:Number = 0;
        private var yaw:Number = 0;
        private var throttle:Number = 0;
 
        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
 
            stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
            stage.stage3Ds[0].requestContext3D();
 
            addEventListener(Event.ENTER_FRAME, onRender);
 
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
 
            tf.defaultTextFormat = new TextFormat(null, 20, 0xffffff);
            tf.autoSize = TextFieldAutoSize.LEFT;
            addChild(tf);
        }
 
        private function onContext3DCreate(e:Event):void 
        {
            context3D = stage.stage3Ds[0].context3D;
            context3D.configureBackBuffer(800, 600, 2);
            context3D.setCulling(Context3DTriangleFace.BACK);
 
            const vertices:Vector.<Number> = Vector.<Number>([
            //  x, y, z, r, g, b,
                0, 0, 0, 0, 0, 0,
                0, 0, 1, 0, 0.5, 0.5,
                1, 0, 1, 0, 1, 1,
                1, 0, 0, 0, 0.5, 0.5,
            ]);
            const indices:Vector.<uint> = Vector.<uint>([
                0, 1, 2, 2, 3, 0,
            ]);
 
            var vertexData:Vector.<Number> = new Vector.<Number>;
            var indexData:Vector.<uint> = new Vector.<uint>;
            var numVertices:int = 0;
            for (var z:int = -10; z < 10; z++) 
            {
                var green:Number = (0 <= z) ? 1 : 0;
                var blue:Number = (0 <= z) ? 0 : 1;
                for (var x:int = -10; x < 10; x++) 
                {
                    for (var i:int = 0; i < 4; i++) 
                    {
                        var base:int = i * 6;
                        vertexData.push((vertices[base + 0] + x) * 100);
                        vertexData.push(vertices[base + 1]);
                        vertexData.push((vertices[base + 2] + z) * 100);
                        vertexData.push(vertices[base + 3]);
                        vertexData.push(vertices[base + 4] * green);
                        vertexData.push(vertices[base + 5] * blue);
                    }
                    for (i = 0; i < indices.length; i++) 
                    {
                        indexData.push(numVertices + indices[i]);
                    }
                    numVertices += 4;
                }
            }
 
            // vertexBuffer
            vertexBuffer = context3D.createVertexBuffer(numVertices, 6);
            vertexBuffer.uploadFromVector(vertexData, 0, numVertices);
 
            // indexBuffer
            indexBuffer = context3D.createIndexBuffer(indexData.length);
            indexBuffer.uploadFromVector(indexData, 0, indexData.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);
 
            //
            viewTransform = new Matrix3D;
 
            projectionTransform = new PerspectiveMatrix3D;
            projectionTransform.perspectiveFieldOfViewLH(45 * Math.PI / 180, 800 / 600, 1, 5000);
 
            //
            context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
            context3D.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
            context3D.setProgram(program);
        }
 
        private function onRender(e:Event):void 
        {
            if (!context3D) return;
 
            context3D.clear(0.39, 0.58, 0.93);
            updateViewMatrix();
 
            var m:Matrix3D = new Matrix3D;
            m.append(viewTransform);
            m.append(projectionTransform);
 
            context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
            context3D.drawTriangles(indexBuffer);
            context3D.present();
        }
 
        private function updateViewMatrix():void 
        {
            // update
            var m:Matrix3D = new Matrix3D;
 
            var cameraCross:Vector3D;
            cameraCross = cameraFront.crossProduct(cameraUp);
 
            m.identity();
            m.prependRotation(yaw, cameraUp);
            cameraFront = m.transformVector(cameraFront);
            cameraCross = m.transformVector(cameraCross);
 
            m.identity();
            m.prependRotation(pitch, cameraCross);
            cameraFront = m.transformVector(cameraFront);
            cameraUp = m.transformVector(cameraUp);
 
            m.identity();
            m.prependRotation(roll, cameraFront);
            cameraCross = m.transformVector(cameraCross);
            cameraUp = m.transformVector(cameraUp);
 
            var forward:Vector3D = new Vector3D;
            forward.copyFrom(cameraFront);
            forward.scaleBy(2);
            if (0 < throttle)
            {
                cameraPos = cameraPos.add(forward);
            }
            if (throttle < 0)
            {
                cameraPos = cameraPos.subtract(forward);
            }
 
            // transform
            var cameraTransform:Matrix3D = new Matrix3D;
            cameraTransform = lookAt(cameraPos, cameraPos.subtract(cameraFront), cameraUp);
 
            viewTransform.copyFrom(cameraTransform);
            //viewTransform.invert();
 
            tf.text = StringUtil.substitute("Pos:{0} {1} {2}\nFront:{3} {4} {5}",
                cameraPos.x.toFixed(0), cameraPos.y.toFixed(0), cameraPos.z.toFixed(0),
                cameraFront.x.toFixed(2), cameraFront.y.toFixed(2), cameraFront.z.toFixed(2));
        }
 
        private function onKeyDown(e:KeyboardEvent):void 
        {
            switch (e.keyCode) 
            {
                case Keyboard.LEFT: // aileron
                    roll = 1;
                    break;
                case Keyboard.RIGHT:
                    roll = -1;
                    break;
                case Keyboard.UP: // elevator
                    pitch = -1;
                    break;
                case Keyboard.DOWN:
                    pitch = 1;
                    break;
                case Keyboard.Z: // rudder
                    yaw = -1;
                    break;
                case Keyboard.X:
                    yaw = 1;
                    break;
                case Keyboard.Q: // throttle
                    throttle = 1;
                    break;
                case Keyboard.A:
                    throttle = -1;
                    break;
            }
        }
 
        private function onKeyUp(e:KeyboardEvent):void 
        {
            switch (e.keyCode) 
            {
                case Keyboard.LEFT:
                case Keyboard.RIGHT:
                    roll = 0;
                    break;
                case Keyboard.UP:
                case Keyboard.DOWN:
                    pitch = 0;
                    break;
                case Keyboard.Z:
                case Keyboard.X:
                    yaw = 0;
                    break;
                case Keyboard.Q:
                case Keyboard.A:
                    throttle = 0;
                    break;
            }
        }
 
        private function lookAt(eye:Vector3D, at:Vector3D, up:Vector3D):Matrix3D
        {
            var m:Vector.<Number> = new Vector.<Number>(16);
 
            // z軸 = eye - at
            at.x = eye.x - at.x;
            at.y = eye.y - at.y;
            at.z = eye.z - at.z;
            m[2] = at.x / at.length;
            m[6] = at.y / at.length;
            m[10] = at.z / at.length;
 
            // x軸 = up × z軸
            at.x = up.y * m[10] - up.z * m[6];
            at.y = up.z * m[2] - up.x * m[10];
            at.z = up.x * m[6] - up.y * m[2];
            m[0] = at.x / at.length;
            m[4] = at.y / at.length;
            m[8] = at.z / at.length;
 
            // y軸 = z軸 × x軸
            m[1] = m[6] * m[8] - m[10] * m[4];
            m[5] = m[10] * m[0] - m[2] * m[8];
            m[9] = m[2] * m[4] - m[6] * m[0];
 
            // 平行移動
            m[12] = -(eye.x * m[0] + eye.y * m[4] + eye.z * m[8]);
            m[13] = -(eye.x * m[1] + eye.y * m[5] + eye.z * m[9]);
            m[14] = -(eye.x * m[2] + eye.y * m[6] + eye.z * m[10]);
 
            m[3] = m[7] = m[11] = 0;
            m[15] = 1;
 
            var matrix:Matrix3D = new Matrix3D;
            matrix.rawData = m;
            return matrix;
        }
 
        private function degrees(x:Number):int
        {
            return x * 180 / Math.PI;
        }
    }
 
}
 
最終更新:2014年07月21日 14:07