|開発環境|Apache [[Flex]] SDK 4.12.1| ||FlashDevelop 4.6.2.5| |実行環境|Microsoft Windows 8.1 (64bit)| |プロジェクトの種類|ActionScript 3/AS3 Project| |プロジェクト名|CircleCam| #table_zebra(project, #fff, #eee) http://www.maroon.dti.ne.jp/lance/flash/circlecam.html 参考 -[[床井研究室 - 第6回 視点の移動>http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20090902]] Main.as #highlight(actionscript){{ 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 keyDown:Array = new Array; private var tf:TextField = new TextField; private var camDist:Number = 3; private var camLat:int = 30; private var camLong:int = 120; 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 = (e.target as Stage3D).context3D; context3D.configureBackBuffer(viewWidth, viewHeight, 2); //context3D.setCulling(Context3DTriangleFace.BACK); // vertexBuffer 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 perVertex:int = 6; const numVertices:int = vertices.length / perVertex; vertexBuffer = context3D.createVertexBuffer(numVertices, perVertex); vertexBuffer.uploadFromVector(vertices, 0, numVertices); // indexBuffer const indices:Vector.<uint> = Vector.<uint>([ 0, 1, 2, ]); indexBuffer = context3D.createIndexBuffer(indices.length); indexBuffer.uploadFromVector(indices, 0, indices.length); // program var vertexProgram:AGALMiniAssembler = new AGALMiniAssembler; vertexProgram.assemble(Context3DProgramType.VERTEX, "m44 vt0 va0 vc0\n" + // vt0 = mul(position, world) "m44 vt0 vt0 vc4\n" + // vt0 = mul(vt0, view) "m44 op vt0 vc8\n" + // output position = mul(vt0, projection) "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); var projection:PerspectiveMatrix3D = new PerspectiveMatrix3D; projection.perspectiveFieldOfViewRH(ToRadians(45), viewWidth / viewHeight, 0.1, 100); context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 8, projection, true); stage.addEventListener(Event.ENTER_FRAME, render); } private function render(e:Event):void { if (IsKeyDown(Keyboard.UP)) camLat = Math.min(camLat + 2, 90); if (IsKeyDown(Keyboard.DOWN)) camLat = Math.max(camLat - 2, -90); if (IsKeyDown(Keyboard.LEFT)) camLong = (camLong + 2) % 360; if (IsKeyDown(Keyboard.RIGHT)) camLong = (camLong + 358) % 360; if (IsKeyDown(Keyboard.PAGE_UP)) camDist = Math.max(camDist - 0.1, 0.1); if (IsKeyDown(Keyboard.PAGE_DOWN)) camDist += 0.1; var rad:Number = ToRadians(camLat); var y:Number = Math.sin(rad) * camDist; var r:Number = Math.cos(rad) * camDist; rad = ToRadians(camLong); var x:Number = Math.cos(rad) * r; var z:Number = Math.sin(rad) * r; tf.text = StringUtil.substitute( "driverInfo: {0}\nlat:{1} long:{2} dist:{3}\nx:{4} y:{5} z:{6}", context3D.driverInfo, camLat, camLong, camDist.toFixed(1), x.toFixed(1), y.toFixed(1), z.toFixed(1)); var view:Matrix3D = lookAt(new Vector3D(x, y, z), new Vector3D, Vector3D.Y_AXIS); context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 4, view, true); // context3D.clear(.3, .3, .3); var world:Matrix3D = new Matrix3D; world.identity(); context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, world, true); context3D.drawTriangles(indexBuffer); world.identity(); world.appendTranslation(0, 0, -1); context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, world, true); context3D.drawTriangles(indexBuffer); context3D.present(); } private function IsKeyDown(keyCode:uint):Boolean { return (keyDown[keyCode]) ? true : false; } private function ToRadians(degrees:Number):Number { return degrees * Math.PI / 180; } private function lookAt(eye:Vector3D, at:Vector3D, up:Vector3D):Matrix3D { var m:Vector.<Number> = new Vector.<Number>(16); 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; 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; 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; } } } }}