In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: flash on 2010-6-1

PaperVison3D サンプル
* ・BasicViewを使わずに自前で実装
* ・クリックしてアクティブ後、以下のようにしてカメラ操作
*   回転 - ドラッグ
*   平行移動 - [Space]キーを押しながらドラッグ
*   拡大 - マウスホイール
Get Adobe Flash player
by negimochi 03 Jun 2010
/**
 * Copyright negimochi ( http://wonderfl.net/user/negimochi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/9ZKm
 */

/**
 * 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 {
			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.FlatShadeMaterial;
import org.papervision3d.materials.shadematerials.GouraudMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.objects.primitives.Plane;
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;
import caurina.transitions.Tweener;
import caurina.transitions.properties.CurveModifiers;

internal class BasicViewOrg extends Sprite {
	private static const INIT_CAMERA_X:int = 80;
	private static const INIT_CAMERA_Y:int = 80;
	private static const INIT_CAMERA_Z:int = -80;
	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;
	
	private static const RIBBON_WIDTH:int = 10;
	private static const RIBBON_LENGTH:int = 300;
	private static const EASING:Number = 0.05;
	
	private static const X_MAX_RANGE:Number = 100;
	private static const X_MIN_RANGE:Number = -100;
	private static const Y_MAX_RANGE:Number = 100;
	private static const Y_MIN_RANGE:Number = -100;
	private static const Z_MAX_RANGE:Number = 100;
	private static const Z_MIN_RANGE:Number = -100;
	
	// 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 satellites:Array;
	private var ribbons:Array;
	
	private var container:DisplayObject3D;
	
	public function BasicViewOrg(viewportWidth:Number = 640, viewportHeight:Number = 320, initFlagAxis:Boolean = true) {
		CurveModifiers.init();
		
		_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;
		
		satellites = new Array();
		ribbons = new Array();
		container = new DisplayObject3D();
		scene.addChild(container);
		
		//シーンのオブジェクトを生成
		createSceneObject();
	}
	
	/**
	 * レンダリング開始
	 */
	public function startRendering():void
	{
		addEventListener(Event.ENTER_FRAME, enterFrameHander);
	}
	
	//// private /////////////////////////////////////////////////////////////////////////////////////
	private function enterFrameHander(evt:Event):void
	{
		var i:int = 0;
		for ( i = 0; i < ribbons.length; i++ ) {
			ribbons[i].x += (satellites[i].x - ribbons[i].x) * EASING;
			ribbons[i].y += (satellites[i].y - ribbons[i].y) * EASING;
			ribbons[i].z += (satellites[i].z - ribbons[i].z) * EASING;
			ribbons[i].draw();
		}
		
		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);
		
		// リボン作成
		var ribbonMaterial:FlatShadeMaterial = new FlatShadeMaterial(light, 0xEF2A82, 0x44031F);
		ribbonMaterial.oneSide = false;
		var ribbon:Ribbon3D = new Ribbon3D(ribbonMaterial, RIBBON_WIDTH, RIBBON_LENGTH);
		container.addChild(ribbon);
		ribbon.x = randomNumber(X_MIN_RANGE, X_MAX_RANGE);
		ribbon.y = randomNumber(Y_MIN_RANGE, Y_MAX_RANGE);
		ribbon.z = randomNumber(Z_MIN_RANGE, Z_MAX_RANGE);
		ribbons.push(ribbon);
		
		// サテライト
		var satellite:DisplayObject3D = new DisplayObject3D();
		satellites.push(satellite);
		var yellow:ColorMaterial = new ColorMaterial(0xffff00, 0.0);
		yellow.oneSide = false;
		var yellowPlane:Plane = new Plane(yellow, 20, 20, 1, 1);
		satellite.addChild(yellowPlane);
		container.addChild(satellite);
		tweenObject(satellite);
		
		// 軸の描画(デバッグ専用)
		if (_flagAxis) {
			createAxis();
		}
	}
	
	private function randomNumber(min:Number, max:Number ):Number
	{
		return Math.random() * (max - min) + min;
	}
	
	private function tweenObject(object:*):void 
	{
		Tweener.addTween(object, {
			x:	randomNumber(X_MIN_RANGE, X_MAX_RANGE),
			y:	randomNumber(Y_MIN_RANGE, Y_MAX_RANGE),
			z:	randomNumber(Z_MIN_RANGE, Z_MAX_RANGE),
			_bezier:[ {
				x:	randomNumber(X_MIN_RANGE, X_MAX_RANGE),
				y:	randomNumber(Y_MIN_RANGE, Y_MAX_RANGE),
				z:	randomNumber(Z_MIN_RANGE, Z_MAX_RANGE)
			}],
			time:				4,
			onComplete:			tweenObject,
			onCompleteParams:	[object],
			transition:			"linear"
			}
		);
	}
			
	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;
	}
	
}

// 以下 Ribbon3Dを転載

//	SOULWIRE LTD
//	© JUSTIN CLARKE WINDLE
//	blog.soulwire.co.uk

//	Ribbon3d v1.00
//	11/08/2008 20:35

import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.geom.TriangleMesh3D;
import org.papervision3d.core.math.NumberUV;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.objects.DisplayObject3D;

internal class Ribbon3D extends DisplayObject3D
{
	
//	————————————————————————————————————————————————————————————
//	MEMBER										CLASS / DATATYPE
//	————————————————————————————————————————————————————————————

	private var length:							Number;
	private var planes:							Array;
	private var v1:								Vertex3D;
	private var v2:								Vertex3D;
	private var v3:								Vertex3D;
	private var v4:								Vertex3D;

//	————————————————————————————————————————————————————————————

	public var tx:								Number;
	public var ty:								Number;
	public var tz:								Number;
	public var width:							Number;
	
//	————————————————————————————————————————————————————————————
//													 CONSTRUCTOR
//	————————————————————————————————————————————————————————————
	
	public function Ribbon3D( materialObj:MaterialObject3D = null, thickness:Number = 20, maxSegments:int = 100 ) 
	{
		super();
		planes = new Array();
		
		tx = ty = tz = 0;
		v1 = new Vertex3D( tx + width, ty, tz );
		v2 = new Vertex3D( tx - width, ty, tz );
		
		material = materialObj;
		length = maxSegments;
		width = thickness;
	}
	
//	————————————————————————————————————————————————————————————
//														 METHODS
//	————————————————————————————————————————————————————————————
	
	private function newPlane():TriangleMesh3D
	{
		var plane:TriangleMesh3D = new TriangleMesh3D( material, [], [] );
		
		plane.geometry.vertices.push( v1, v2, v3, v4 );
		plane.geometry.faces.push( newTriangle( plane, 0 ) );
		plane.geometry.faces.push( newTriangle( plane, 1 ) );
		plane.geometry.ready = true;

		return plane;
	}
	
	private function newTriangle( plane:TriangleMesh3D, type:int ):Triangle3D
	{
		var b:Boolean = Boolean( type );
		
		var vA:Vertex3D = plane.geometry.vertices[ b ? 3 : 0 ];
		var vB:Vertex3D = plane.geometry.vertices[ b ? 1 : 2 ];
		var vC:Vertex3D = plane.geometry.vertices[ b ? 2 : 1 ];
		
		var nA:NumberUV = new NumberUV( int(b), 1 );
		var nB:NumberUV = new NumberUV( int(b), int(!b) );
		var nC:NumberUV = new NumberUV( int(!b), int(b) );
		
		return( new Triangle3D( plane, [ vA, vB, vC ], null, [ nA, nB, nC ] ) );
	}
	
//	————————————————————————————————————————————————————————————

	public function draw():void
	{
		v3 = new Vertex3D( tx + width, ty, tz );
		v4 = new Vertex3D( tx - width, ty, tz );
		
		var plane:TriangleMesh3D;
		
		if ( numChildren >= length )
		{
			plane = planes.shift();
			plane.geometry.vertices = [ v1, v2, v3, v4 ];
			plane.geometry.faces = [ newTriangle( plane, 0 ), newTriangle( plane, 1 ) ];
			planes.push( plane );
		}
		else
		{
			plane = newPlane();
			planes.push( plane );
			addChild( plane );
		}

		v1 = v3;
		v2 = v4;
	}
	
	public function moveTo( xp:Number = 0, yp:Number = 0, zp:Number = 0 ):void
	{
		super.x = xp;
		super.y = yp;
		super.z = zp;
	}
	
//	————————————————————————————————————————————————————————————
//													   GET / SET
//	————————————————————————————————————————————————————————————
	
	override public function get x():Number { return tx; }
	override public function get y():Number { return ty; }
	override public function get z():Number { return tz; }
	
	override public function set x(n:Number):void { tx = n; }
	override public function set y(n:Number):void { ty = n; }
	override public function set z(n:Number):void { tz = n; }
	
}