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: forked from: flash on 2010-6-1

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

// forked from negimochi's forked from: flash on 2010-6-1
/**
 * 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; }
    
}