Papervision3D の FreeCamera3D で視点移動
Papervision3D でテクスチャぐるぐる PlaneWorld サンプル その2 by Flex SDK でうまく視点移動できなかった問題を解決できたっぽい。
Papervision3D には視野を司るカメラオブジェクトというのがあって、3Dオブジェクトの世界を描画するには SceneObject3D#renderCamera(camera:CameraObject3D) を使う。
引数の CameraObject3D がカメラオブジェクト。
APIリファレンスを見ると、
The CameraObject3D class is the base class for all the cameras that can be placed in a scene.
A camera defines the view from which a scene will be rendered. Different camera settings would present a scene from different points of view.
3D cameras simulate still-image, motion picture, or video cameras of the real world. When rendering, the scene is drawn as if you were looking through the camera lens.
とある。CameraObject3D はすべてのカメラオブジェクトの一番基本となるクラスらしい。
で、実際にはそこらのサンプルコードを見た感じでは CameraObject3D のサブクラスである Camera3D と FreeCamera3D がよく使われている。
Papervision3D の API リファレンスには、
The Camera3D class creates a camera that views the area around a target object.
The FreeCamera3D class creates a camera that views the area in the direction the camera is aimed.
とある。
Camera3D は目標対象のオブジェクトを見つめている感じのカメラ。カメラをぐるぐる回しても、視界にはいつも目標のオブジェクトが映っている。映画マトリックスのあの有名なグルグルシーンみたいに。
FreeCamera3D はカメラは見ている方向を映す。目標対象は無い。自由に動かせるイメージ。
参考: [PV3D] Camera3DとFreeCamera3D (C-dashi._blog)
動くサンプル
方向キーとShiftキーを組み合わせて前後左右上昇下降な移動が可能。
画像は XB-LIM さん作の Pledge of BAHAMUT { FF3 ULTIMANIAc DATABASE } - ドラゴンクエストの世界地図 を利用しています。
The map image by XB-LIM (Pledge of BAHAMUT { FF3 ULTIMANIAc DATABASE } - The World maps of Dragon Quest)
ソースコード(MovingCamera.as)
package {
import flash.display.*;
import flash.events.*;
import flash.text.*;
import org.papervision3d.scenes.*;
import org.papervision3d.objects.*;
import org.papervision3d.cameras.*;
import org.papervision3d.materials.*;
[SWF(width="400", height="400", backgroundColor="#000000", frameRate="30")]
public class MovingCamera extends Sprite {
private var container : Sprite;
private var scene : Scene3D;
private var camera : FreeCamera3D;
private var rootNode : DisplayObject3D;
// 画像ファイルのパス
private var imageFilePath:String = "movingcamera.png";
// カメラ移動速度
private var cameraSpeed : Number = 5;
public function MovingCamera():void {
// リサイズに対応(swfをブラウザで直接ひらいているときとか)
stage.addEventListener(Event.RESIZE, onStageResize);
// キーボード操作
stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown);
// 表示用の Sprite オブジェクトを生成
container = new Sprite();
container.x = 400 / 2; // at center : swf width = 400
//container.y = 400 / 2; // at center : swf height = 400
container.y = 500;
addChild(container);
// シーンオブジェクトを作る
scene = new MovieScene3D(container);
// カメラオブジェクトを作る
camera = new FreeCamera3D();
camera.x = 0;
camera.y = 0;
camera.z = 0;
camera.focus = 100;
camera.zoom = 10;
camera.sort = true;
camera.rotationX = 60;
// ルートノードを作る
rootNode = new DisplayObject3D();
scene.addChild(rootNode);
// 平面世界オブジェクトを作る
rootNode.addChild(createWorld());
scene.renderCamera(camera);
}
private function createWorld():DisplayObject3D{
var material:BitmapFileMaterial = new BitmapFileMaterial(imageFilePath);
material.doubleSided = true;
material.lineColor = 0x00FF00;
material.lineAlpha = 1;
var planeSize:int = 400;
var segment:int = 30;
var p:Plane = new Plane(material, planeSize, planeSize, segment, segment);
p.x = 0;
p.y = 0;
p.z = 0;
return p;
}
private function keydown(event:KeyboardEvent):void {
if(event.shiftKey){
switch(event.keyCode) { // 37← 38↑ 39→ 40↓
case 37: // 左移動
camera.x = camera.x - (cameraSpeed * sin(camera.rotationZ + 90));
camera.y = camera.y + (cameraSpeed * cos(camera.rotationZ + 90));
break;
case 38:
camera.z -= cameraSpeed; // 上昇
break;
case 39: // 右移動
camera.x = camera.x - (cameraSpeed * sin(camera.rotationZ + 270));
camera.y = camera.y + (cameraSpeed * cos(camera.rotationZ + 270));
break;
case 40:
camera.z += cameraSpeed; // 下降
break;
}
}else{
switch(event.keyCode) { // 37← 38↑ 39→ 40↓
case 37: // 右回転
camera.rotationZ += 1;
break;
case 38: // 前進
camera.x = camera.x - (cameraSpeed * sin(camera.rotationZ));
camera.y = camera.y + (cameraSpeed * cos(camera.rotationZ));
break;
case 39: // 左回転
camera.rotationZ -= 1;
break;
case 40: // 後退
camera.x = camera.x + (cameraSpeed * sin(camera.rotationZ));
camera.y = camera.y - (cameraSpeed * cos(camera.rotationZ));
break;
}
}
scene.renderCamera(camera);
}
private static function sin(degrees:Number):Number{
return Math.sin(toRadians(degrees));
}
private static function cos(degrees:Number):Number{
return Math.cos(toRadians(degrees));
}
private static function toRadians(degrees:Number):Number{
return degrees * (Math.PI / 180);
}
private function onStageResize(event:Event):void {
container.x = stage.stageWidth / 2;
container.y = stage.stageHeight / 2;
}
}
}
# FreeCamera3D を使わなくても
# 透明で動く目標物を作って、
# それを Camera3D で追いかければ
# けっこう自由に視点移動できるんじゃないだろうか。
# とか思った。
tags: zlashdot Flash Flash Flex Papervision3D
Posted by NI-Lab. (@nilab)