/**
* Copyright negimochi ( http://wonderfl.net/user/negimochi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/e08v
*/
/**
* PaperVison3D サンプル
* ・BasicViewを使わずに自前で実装
* ・クリックしてアクティブ後、以下のようにしてカメラ操作
* 回転 - ドラッグ
* 平行移動 - [Space]キーを押しながらドラッグ
* 拡大 - マウスホイール
*/
package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.geom.Point;
import flash.geom.Vector3D;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.objects.DisplayObject3D;
public class TestFlash extends Sprite
{
private var pvLayer:Sprite;
private static const ZOOM_SPEED:Number = 1.0;
private static const MOVE_SPEED:Number = 0.1;
private static const ROTATE_SPEED:Number = 0.1;
private var pv3d:BasicViewOrg;
private var cameraLookAtTarget:DisplayObject3D;
private var cameraFollowTarget:DisplayObject3D;
private var mousePoint:Point;
private var cameraRotX:Number;
private var cameraRotY:Number;
private var initCameraPos:Vector3D;
private var isSpaceDown:Boolean;
public function TestFlash()
{
// ベースレイヤー
this.tabEnabled = false;
this.graphics.beginFill(0xFFFFFF, 1.0);
this.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
this.graphics.endFill();
pv3d = new BasicViewOrg( stage.stageWidth, stage.stageHeight, true );
pv3d.x = 0;
pv3d.y = 0;
// レイヤーにビューポートを貼り付け
this.addChild( pv3d );
pv3d.startRendering();
mousePoint = new Point(0, 0);
initCameraPos = new Vector3D(
pv3d.camera.x - pv3d.camera.target.x,
pv3d.camera.y - pv3d.camera.target.y,
pv3d.camera.z - pv3d.camera.target.z,
0
);
cameraRotY = Math.atan2( initCameraPos.x, -initCameraPos.z );
cameraRotX = Math.atan2( initCameraPos.x, initCameraPos.y );
this.stage.addEventListener( MouseEvent.MOUSE_DOWN, cameraMouseDownHandler );
this.stage.addEventListener( MouseEvent.MOUSE_UP, cameraMouseUpHandler );
this.stage.addEventListener( MouseEvent.MOUSE_WHEEL, cameraMouseWheelHandler );
this.stage.addEventListener( KeyboardEvent.KEY_DOWN, keyboardDownHandler );
this.stage.addEventListener( KeyboardEvent.KEY_UP, keyboardUpHandler );
isSpaceDown = false;
}
private function keyboardDownHandler(evt:KeyboardEvent):void
{
switch( evt.keyCode )
{
case Keyboard.SPACE : // [Space]
isSpaceDown = true;
break;
default:
}
}
private function keyboardUpHandler(evt:KeyboardEvent):void
{
isSpaceDown = false;
}
private function cameraMouseWheelHandler(evt:MouseEvent):void
{
pv3d.camera.zoom += evt.delta * ZOOM_SPEED;
if ( pv3d.camera.zoom < 1.0 ) pv3d.camera.zoom = 1.0;
}
private function cameraMouseDownHandler(evt:MouseEvent):void
{
mousePoint.x = evt.stageX;
mousePoint.y = evt.stageY;
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, cameraMouseMoveHandler);
}
private function cameraMouseMoveHandler(evt:MouseEvent):void
{
var dx:Number = mousePoint.x - evt.stageX;
var dy:Number = evt.stageY - mousePoint.y;
if (isSpaceDown) {
// カメラ -> カメラ視点のベクトル(スクリーンの法線ベクトルの算出)
var nx:Number = pv3d.camera.target.x - pv3d.camera.x;
var ny:Number = pv3d.camera.target.y - pv3d.camera.y;
var nz:Number = pv3d.camera.target.z - pv3d.camera.z;
var vectorLength:Number = Math.sqrt(nx * nx + ny * ny + nz * nz);
// 単位ベクトル化
nx /= vectorLength;
ny /= vectorLength;
nz /= vectorLength;
// スクリーンのX方向を表すベクトル
var ux:Number = nz;
var uy:Number = 0;
var uz:Number = -nx;
vectorLength = Math.sqrt(ux * ux + uy * uy + uz * uz);
// 単位ベクトル化
ux /= vectorLength;
uy /= vectorLength;
uz /= vectorLength;
// スクリーンのY方向を表すベクトル
var vx:Number = -nx * ny;
var vy:Number = nx * nx + nz * nz;
var vz:Number = -nz * ny;
vectorLength = Math.sqrt(vx * vx + vy * vy + vz * vz);
// 単位ベクトル化
vx /= vectorLength;
vy /= vectorLength;
vz /= vectorLength;
// カメラとカメラ視点の更新
pv3d.camera.x += ux * dx + vx * dy;
pv3d.camera.y += uy * dx + vy * dy;
pv3d.camera.z += uz * dx + vz * dy;
pv3d.camera.target.x += ux * dx + vx * dy;
pv3d.camera.target.y += uy * dx + vy * dy;
pv3d.camera.target.z += uz * dx + vz * dy;
}
else {
// X軸の回転角を算出
cameraRotX = cameraRotX - dy * ROTATE_SPEED;
if(-89 >= cameraRotX) {
cameraRotX = -89;
}
else if(89 <= cameraRotX) {
cameraRotX = 89;
}
// Y軸の回転角を算出
cameraRotY = cameraRotY - dx * ROTATE_SPEED;
// 行列演算
var oldPoint:Matrix3D = new Matrix3D(
[initCameraPos.x, initCameraPos.y, initCameraPos.z, 1,
0, 0, 0, 0,
0, 0, 0, 0]);
var rotateX:Matrix3D = Matrix3D.rotationX( cameraRotX * Math.PI / 180 );
var rotateY:Matrix3D = Matrix3D.rotationY( cameraRotY * Math.PI / 180 );
var newPoint:Matrix3D = Matrix3D.multiply( Matrix3D.multiply(oldPoint, rotateX), rotateY );
pv3d.camera.x = newPoint.n11 + pv3d.camera.target.x;
pv3d.camera.y = newPoint.n12 + pv3d.camera.target.y;
pv3d.camera.z = newPoint.n13 + pv3d.camera.target.z;
}
// マウス位置の更新
mousePoint.x = evt.stageX;
mousePoint.y = evt.stageY;
}
private function cameraMouseUpHandler(evt:MouseEvent):void {
trace("cameraMouseUpHandler");
mousePoint.x = evt.stageX;
mousePoint.x = evt.stageY;
this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, cameraMouseMoveHandler);
}
}
}
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.Event;
import org.papervision3d.materials.shadematerials.GouraudMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.layer.ViewportLayer;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.view.BasicView;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.core.geom.Lines3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.materials.special.LineMaterial;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.objects.primitives.Sphere;
internal class BasicViewOrg extends Sprite {
private static const INIT_CAMERA_X:int = 0;
private static const INIT_CAMERA_Y:int = 100;
private static const INIT_CAMERA_Z:int = -400;
private static const INIT_CAMERA_ZOOM:int = 10;
private static const INIT_CAMERA_FOCUS:int = 20;
private static const INIT_TARGET_X:int = 0;
private static const INIT_TARGET_Y:int = 0;
private static const INIT_TARGET_Z:int = 0;
private static const INIT_LIGHT_X:int = 500;
private static const INIT_LIGHT_Y:int = 500;
private static const INIT_LIGHT_Z:int = -200;
// 3D基本要素
private var scene:Scene3D;
private var _camera:Camera3D;
private var viewport:Viewport3D;
private var renderer:BasicRenderEngine;
// ライト
private var light:PointLight3D;
// 軸
private var axisXMaterial:LineMaterial; // X軸マテリアル
private var axisYMaterial:LineMaterial; // Y軸マテリアル
private var axisZMaterial:LineMaterial; // Z軸マテリアル
private var axisXLine:Lines3D; // X軸コンテナ
private var axisYLine:Lines3D; // Y軸コンテナ
private var axisZLine:Lines3D; // Z軸コンテナ
// ベースライン
private var _flagAxis:Boolean;
private var container:DisplayObject3D;
public function BasicViewOrg(viewportWidth:Number = 640, viewportHeight:Number = 320, initFlagAxis:Boolean = true) {
_flagAxis = initFlagAxis;
// シーン設定
renderer = new BasicRenderEngine();
scene = new Scene3D();
// ビューポートの設定
viewport = new Viewport3D(viewportWidth, viewportHeight, false, true, true, true);
viewport.x = 0;
viewport.y = 0;
viewport.opaqueBackground = 0xcccccc;
this.addChild( viewport );
// カメラ設定
var cameraTarget:DisplayObject3D = new DisplayObject3D();
cameraTarget.x = INIT_TARGET_X;
cameraTarget.y = INIT_TARGET_Y;
cameraTarget.z = INIT_TARGET_Z;
_camera = new Camera3D();
_camera.target = cameraTarget;
_camera.x = INIT_CAMERA_X;
_camera.y = INIT_CAMERA_Y;
_camera.z = INIT_CAMERA_Z;
_camera.zoom = INIT_CAMERA_ZOOM;
_camera.focus = INIT_CAMERA_FOCUS;
//シーンのオブジェクトを生成
createSceneObject();
}
/**
* レンダリング開始
*/
public function startRendering():void
{
addEventListener(Event.ENTER_FRAME, enterFrameHander);
}
//// private /////////////////////////////////////////////////////////////////////////////////////
private function enterFrameHander(evt:Event):void
{
renderer.renderScene(scene, _camera, viewport);
}
private function createSceneObject():void {
// ライトの設定
light = new PointLight3D(false);
light.x = INIT_LIGHT_X;
light.y = INIT_LIGHT_Y;
light.z = INIT_LIGHT_Z;
scene.addChild(light);
// 軸の描画(デバッグ専用)
if (_flagAxis) {
createAxis();
}
}
private function createAxis():void {
axisXMaterial = new LineMaterial(0xFF0000, 0.5); // X軸マテリアル
axisYMaterial = new LineMaterial(0x00FF00, 0.5); // Y軸マテリアル
axisZMaterial = new LineMaterial(0x0000FF, 0.5); // Z軸マテリアル
axisXMaterial.interactive = true;
axisYMaterial.interactive = true;
axisZMaterial.interactive = true;
axisXLine = new Lines3D(axisXMaterial); // コンテナ
axisYLine = new Lines3D(axisYMaterial); // コンテナ
axisZLine = new Lines3D(axisZMaterial); // コンテナ
axisXLine.addNewLine(1, 0, 0, 0,
50, 0, 0);
axisYLine.addNewLine(1, 0, 0, 0,
0, 50, 0);
axisZLine.addNewLine(1, 0, 0, 0,
0, 0, 50);
scene.addChild(axisXLine);
scene.addChild(axisYLine);
scene.addChild(axisZLine);
}
private function deleteAxis():void {
// materialのインタラクティブを切ってからremove
if(axisXMaterial != null) {
axisXMaterial.interactive = false;
axisXMaterial.destroy();
axisXMaterial = null;
}
if(axisYMaterial != null) {
axisYMaterial.interactive = false;
axisYMaterial.destroy();
axisYMaterial = null;
}
if(axisZMaterial != null) {
axisZMaterial.interactive = false;
axisZMaterial.destroy();
axisZMaterial = null;
}
scene.removeChild(axisXLine);
scene.removeChild(axisYLine);
scene.removeChild(axisZLine);
}
//// setter ////////////////////////////////////////////////////////////////
/**
* _flagAxis
* @param setFlag
*/
public function set flagAxis(setFlag:Boolean):void
{
if (_flagAxis && !setFlag) {
_flagAxis = setFlag;
deleteAxis();
}
else if (!_flagAxis && setFlag) {
_flagAxis = setFlag;
createAxis();
}
}
//// getter ////////////////////////////////////////////////////////////////
/**
* _camera
*/
public function get camera():Camera3D
{
return _camera;
}
}