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

InteractiveCamera3D test

Mouse controlled PV3D camera class (collada room forked from tkinjo)
*
* CTRL + mouse drag      - rotate
* SHIFT + drag (up/down) - zoom
* ALT + drag             - move (x/y)
*
/**
 * Copyright yonatan ( http://wonderfl.net/user/yonatan )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/uWAM
 */

// forked from tkinjo's Collada

/*
 * Mouse controlled PV3D camera class (collada room forked from tkinjo)
 *
 * CTRL + mouse drag      - rotate
 * SHIFT + drag (up/down) - zoom
 * ALT + drag             - move (x/y)
 *
 */

package  
{
	import flash.display.Sprite;
	import org.papervision3d.core.proto.CameraObject3D;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.parsers.DAE;
	import org.papervision3d.scenes.Scene3D;
	import org.papervision3d.view.AbstractView;
	import org.papervision3d.view.BasicView;
	
	[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#000000")]
	
	/**
	 * Papervision3D で COLLADA オブジェクトを表示する。
	 * 
	 * まあ、ただ単に Blender とのコラボをやってみたかっただけで。
	 * 
	 * モデルデータは 3DCG ソフトの Blender のみです。
	 * テクスチャもレンダーベイキング機能で作成。
	 * 
	 * @author tkinjo
	 */
	public class Main extends BasicView
	{
		
		/**
		 * 
		 */
		public function Main() 
		{
                        stage.quality = "low";
                        _camera = new InteractiveCamera3D( viewport );
			var dae:DAE = new DAE();
			dae.scale = 200;
			dae.load( "http://cross.gentenzero.com/wonderfl/assets/collada/room.dae" );
			scene.addChild( dae );
			startRendering();
		}
	}
}
	
    import flash.events.*;
    import org.papervision3d.cameras.*;
    import org.papervision3d.view.Viewport3D;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.core.math.*;
    import org.papervision3d.core.log.PaperLogger;

    /**
    * InteractiveCamera3D is a mouse controlled camera.
    */ 
    class InteractiveCamera3D extends Camera3D {

        /**
        * Constructor.
        * 
        * @param   viewport        The viewport, used for mouse interaction
        * @param   fov             This value is the vertical Field Of View (FOV) in degrees.
        * @param   near            Distance to the near clipping plane.
        * @param   far             Distance to the far clipping plane.
        * @param   useCulling      Boolean indicating whether to use frustum culling. When true all objects outside the view will be culled.
        * @param   useProjection   Boolean indicating whether to use a projection matrix for perspective.
        */ 
        public function InteractiveCamera3D(
            viewport3D:Viewport3D, // TODO: stage/viewport??
            fov:Number=60,
            near:Number=10,
            far:Number=5000,
            useCulling:Boolean=false,
            useProjection:Boolean=false ) {
            
            super( fov, near, far, useCulling, useProjection );
            this.viewport3D = viewport3D;
            viewport3D.stage.addEventListener( MouseEvent.MOUSE_DOWN, mouseDown );
        }

        protected var targetDistance:Number = 1000;
        protected var viewport3D:Viewport3D;

        public override function set target(object:DisplayObject3D):void
        {
            PaperLogger.error("You tried to set an InteractiveCamera3D's target property. " +
                "Don't do that! (you can use lookAt instead)");
        }

        public override function lookAt( targetObject:DisplayObject3D, upAxis:Number3D=null ):void {
            targetDistance = distanceTo( targetObject );
            super.lookAt( targetObject, upAxis );
        }

        public static const SPIN:uint = 1;
        public static const MOVE:uint = 2;
        public static const ZOOM:uint = 3;
        public static const INACTIVE:uint = 0;

        protected var _state:uint = INACTIVE;
        public function get state():uint {
            return _state;
        }
        
        // these hold values from when interaction was started
        protected var initialTransform:Matrix3D;
        protected var initialMouseX:Number;
        protected var initialMouseY:Number;

        protected var enterFrame:Function;
        
        protected function startInteraction( type:uint, listener:Function ):void {
            if( state != INACTIVE ) {
                stopInteraction();
            }
            if( _transformDirty ) {
                updateTransform();
            }
            initialTransform = Matrix3D.clone( this.transform );
            initialMouseX = viewport3D.stage.mouseX;
            initialMouseY = viewport3D.stage.mouseY;
            _state = type;
            enterFrame = listener;
            viewport3D.stage.addEventListener( Event.ENTER_FRAME, enterFrame );
            viewport3D.stage.addEventListener( MouseEvent.MOUSE_UP, stopInteraction );
        }

        protected function stopInteraction( e:Event = null ):void {
            viewport3D.stage.removeEventListener( Event.ENTER_FRAME, enterFrame );
            viewport3D.stage.removeEventListener( MouseEvent.MOUSE_UP, stopInteraction );
            _state = INACTIVE;
        }

        protected function spinHandler( e:Event ):void {
            // calculate axis - perpendicular to mouse vector, swap x and y
            var p:Number3D = new Number3D( 
                (initialMouseY - viewport3D.stage.mouseY) / viewport3D.stage.height * 3,
                (initialMouseX - viewport3D.stage.mouseX) / viewport3D.stage.width * 3,
                0 );
            
            // calculate angle (radians)
            var rad:Number = -p.modulo * Math.PI;
            
            // rotate axis (compensate for cam rotation)
            Matrix3D.rotateAxis( initialTransform, p );

            // create a target object (from targetDistance)
            var target:DisplayObject3D = new DisplayObject3D;
            target.copyTransform( initialTransform );
            target.moveForward( targetDistance );
            var refPoint:Number3D = new Number3D( target.x, target.y, target.z );
            
            // rotate cam around axis
            copyTransform( 
                Matrix3D.multiply( 
                    Matrix3D.rotationMatrixWithReference( p, rad, refPoint ), 
                    initialTransform ) );
        }

        protected function moveHandler( e:Event ):void {
            var x:Number = initialMouseX - viewport3D.stage.mouseX;
            var y:Number = initialMouseY - viewport3D.stage.mouseY;
            copyTransform( initialTransform );
            moveDown( y );
            moveRight( x );
        }

        // TODO: rewrite this. targetdistance is no good without a real target object
        protected function zoomHandler( e:Event ):void {
            var y:Number = (initialMouseY - viewport3D.stage.mouseY) / viewport3D.stage.height;
            var dist:Number = 0;
            dist = targetDistance * y * 10;

            if( targetDistance - dist > focus ) {
                copyTransform( initialTransform );
                moveForward( dist );
            }
        }

        public function interactiveSpin():void {
            startInteraction( SPIN, spinHandler );
        }

        public function interactiveMove():void {
            startInteraction( MOVE, moveHandler );
        }

        public function interactiveZoom():void {
            startInteraction( ZOOM, zoomHandler );
        }

        protected function mouseDown( e:MouseEvent ):void {
            if( e.ctrlKey ) {
                interactiveSpin();
            } else if ( e.altKey ) {
                interactiveMove();
            } else if ( e.shiftKey ) {
                interactiveZoom();
            }
        }
    }