|開発環境|Apache [[Flex]] SDK 4.12.1| ||FlashDevelop 4.6.2.5| |実行環境|Microsoft Windows 8.1 (64bit)| |プロジェクトの種類|ActionScript 3/AS3 Project| |プロジェクト名|Camera3D| #table_zebra(project, #fff, #eee) http://www.maroon.dti.ne.jp/lance/flash/camera3d.html 参考 -[[Working with 3D cameras | Adobe Developer Connection>http://www.adobe.com/devnet/flashplayer/articles/3d-cameras.html]] Main.as #highlight(actionscript){{ 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; } } } }}