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


Main.as
package 
{
    import com.adobe.utils.*;
    import flash.display.*;
    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 view:Matrix3D;
        private var projection:PerspectiveMatrix3D;
 
        private var keyDown:Array = new Array;
        private var tf:TextField = new TextField;
 
        private var camDist:Number = 3; // 距離
        private var camLat:int = 0; // 緯度
        private var camLon:int = 90; // 経度
 
        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();
 
            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 = (e.target as Stage3D).context3D;
            context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2);
            //context3D.setCulling(Context3DTriangleFace.BACK);
 
            //
            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,
            ]);
            const indices:Vector.<uint> = Vector.<uint>([
                0, 1, 2,
            ]);
            const perVertex:int = 6;
            var numVertices:int = vertices.length / perVertex;
 
            vertexBuffer = context3D.createVertexBuffer(numVertices, perVertex);
            vertexBuffer.uploadFromVector(vertices, 0, numVertices);
 
            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);
 
            //
            projection = new PerspectiveMatrix3D;
            projection.perspectiveFieldOfViewRH(
                radians(45), stage.stageWidth / stage.stageHeight, 0.1, 100);
 
            stage.addEventListener(Event.ENTER_FRAME, render);
        }
 
        private function render(e:Event):void 
        {
            updateView();
 
            context3D.clear(0.39, 0.58, 0.93);
 
            for (var i:int = 0; i < 2; i++) 
            {
                var world:Matrix3D = new Matrix3D;
                world.appendTranslation(0, 0, -i);
 
                var m:Matrix3D = new Matrix3D;
                m.append(world);
                m.append(view);
                m.append(projection);
 
                context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
                context3D.drawTriangles(indexBuffer, 0, -1);
            }
 
            context3D.present();
        }
 
        private function updateView():void 
        {
            if (keyDown[Keyboard.W]) camLat = Math.min(camLat + 2, 90);
            if (keyDown[Keyboard.S]) camLat = Math.max(camLat - 2, -90);
            if (keyDown[Keyboard.A]) camLon = (camLon + 2) % 360;
            if (keyDown[Keyboard.D]) camLon = (camLon + 358) % 360;
            if (keyDown[Keyboard.UP]) camDist = Math.max(camDist - 0.1, 0.1);
            if (keyDown[Keyboard.DOWN]) camDist += 0.1;
 
            var rad:Number = radians(camLat);
            var y:Number = Math.sin(rad) * camDist;
            var r:Number = Math.cos(rad) * camDist;
            rad = radians(camLon);
            var x:Number = Math.cos(rad) * r;
            var z:Number = Math.sin(rad) * r;
 
            tf.text = StringUtil.substitute(
                "driverInfo: {0}\nlat:{1} lon:{2} dist:{3}",
                context3D.driverInfo, camLat, camLon, camDist.toFixed(1));
 
            view = new Matrix3D;
            view.position = new Vector3D(x, y, z);
            view.pointAt(new Vector3D, new Vector3D(0, 0, -1), new Vector3D(0, -1, 0));
            view.invert();
        }
 
        private function radians(x:Number):Number
        {
            return x * Math.PI / 180;
        }
 
    }
 
}
 

lookAt版
+ ...
package 
{
    import com.adobe.utils.*;
    import flash.display.*;
    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 view:Matrix3D;
        private var projection:PerspectiveMatrix3D;
 
        private var keyDown:Array = new Array;
        private var tf:TextField = new TextField;
 
        private var camDist:Number = 3; // 距離
        private var camLat:int = 0; // 緯度
        private var camLon:int = 90; // 経度
 
        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();
 
            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 = (e.target as Stage3D).context3D;
            context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2);
            //context3D.setCulling(Context3DTriangleFace.BACK);
 
            //
            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,
            ]);
            const indices:Vector.<uint> = Vector.<uint>([
                0, 1, 2,
            ]);
            const perVertex:int = 6;
            var numVertices:int = vertices.length / perVertex;
 
            vertexBuffer = context3D.createVertexBuffer(numVertices, perVertex);
            vertexBuffer.uploadFromVector(vertices, 0, numVertices);
 
            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);
 
            //
            projection = new PerspectiveMatrix3D;
            projection.perspectiveFieldOfViewRH(
                radians(45), stage.stageWidth / stage.stageHeight, 0.1, 100);
 
            stage.addEventListener(Event.ENTER_FRAME, render);
        }
 
        private function render(e:Event):void 
        {
            updateView();
 
            context3D.clear(0.39, 0.58, 0.93);
 
            for (var i:int = 0; i < 2; i++) 
            {
                var world:Matrix3D = new Matrix3D;
                world.appendTranslation(0, 0, -i);
 
                var m:Matrix3D = new Matrix3D;
                m.append(world);
                m.append(view);
                m.append(projection);
 
                context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
                context3D.drawTriangles(indexBuffer, 0, -1);
            }
 
            context3D.present();
        }
 
        private function updateView():void 
        {
            if (keyDown[Keyboard.W]) camLat = Math.min(camLat + 2, 90);
            if (keyDown[Keyboard.S]) camLat = Math.max(camLat - 2, -90);
            if (keyDown[Keyboard.A]) camLon = (camLon + 2) % 360;
            if (keyDown[Keyboard.D]) camLon = (camLon + 358) % 360;
            if (keyDown[Keyboard.UP]) camDist = Math.max(camDist - 0.1, 0.1);
            if (keyDown[Keyboard.DOWN]) camDist += 0.1;
 
            var rad:Number = radians(camLat);
            var y:Number = Math.sin(rad) * camDist;
            var r:Number = Math.cos(rad) * camDist;
            rad = radians(camLon);
            var x:Number = Math.cos(rad) * r;
            var z:Number = Math.sin(rad) * r;
 
            tf.text = StringUtil.substitute(
                "driverInfo: {0}\nlat:{1} lon:{2} dist:{3}",
                context3D.driverInfo, camLat, camLon, camDist.toFixed(1));
 
            view = lookAt(new Vector3D(x, y, z), new Vector3D, Vector3D.Y_AXIS);
        }
 
        private function lookAt(
            cameraPosition:Vector3D, cameraTarget:Vector3D, cameraUpVector:Vector3D):Matrix3D
        {
            var zaxis:Vector3D = cameraPosition.subtract(cameraTarget);
            zaxis.normalize();
            var xaxis:Vector3D = cameraUpVector.crossProduct(zaxis);
            xaxis.normalize();
            var yaxis:Vector3D = zaxis.crossProduct(xaxis);
 
            return new Matrix3D(Vector.<Number>([
                xaxis.x, yaxis.x, zaxis.x, 0,
                xaxis.y, yaxis.y, zaxis.y, 0,
                xaxis.z, yaxis.z, zaxis.z, 0,
                -xaxis.dotProduct(cameraPosition), -yaxis.dotProduct(cameraPosition),
                -zaxis.dotProduct(cameraPosition), 1
            ]));
        }
 
        private function radians(x:Number):Number
        {
            return x * Math.PI / 180;
        }
 
    }
 
}
 
最終更新:2014年07月29日 14:17