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: Alternativa3D / Zoom to object's face

Alternativa3D 7.5

Camera3D, Matrix3D, pointAt

@author liquid.cow
Get Adobe Flash player
by bradsedito 23 Oct 2012

    Talk

    liquid.cow at 04 Dec 2010 00:41
    hej, i optimized the calculation in the onClick() method and could reduce it to a view lines. maybe you want to adopt this update.

    Tags

    Embed
/**
 * Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/dga7
 */

// forked from liquid.cow's Alternativa3D / Zoom to object's face
package {
    import alternativ7.engine3d.containers.KDContainer;
    import alternativ7.engine3d.core.Camera3D;
    import alternativ7.engine3d.core.Face;
    import alternativ7.engine3d.core.MouseEvent3D;
    import alternativ7.engine3d.core.Object3D;
    import alternativ7.engine3d.core.RayIntersectionData;
    import alternativ7.engine3d.core.View;
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.primitives.Box;

    import gs.*;
    import gs.easing.Sine;

    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
    
    /**
     *
     * Alternativa3D 7.5
     *
     * Camera3D, Matrix3D, pointAt
     *
     * @author liquid.cow
     */
    [SWF(backgroundColor="#FFFFFF", frameRate="100", width="800", height="600")]
    public class Test extends Sprite
    {
        private static const V_CAMERA_INIT  : Vector3D = new Vector3D(0, 3000, -4000);
        private static const CAM_DISTANCE   : Number = 1100;
        private static const RAD2DEG        : Number = 180 / Math.PI;
        private static const DEG2RAD        : Number = Math.PI / 180;
        
        private var _container      : KDContainer;
        private var _camera         : Camera3D;
        private var _vCam           : Vector3D;
        private var _vCamTarget     : Vector3D;
        private var _cameraMatrix   : Matrix3D;
        private var _camRotationY   : Number;
        private var _vMouse3D       : Vector3D;
        private var _clickedFace    : Face;
        
        
        public function Test() : void {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event=null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            
            _camera = new Camera3D();
            _camera.view = new View(stage.stageWidth, stage.stageHeight);
            _camera.view.interactive = true;
            addChild(_camera.view);
            
            _container = new KDContainer();
            _container.resolveByAABB = true;
            _container.resolveByOOBB = true;
            _container.addChild(_camera);
            
            _vCamTarget = new Vector3D();
            _vCam = V_CAMERA_INIT.clone();
            _camRotationY = 0;
            
            var positions:Vector.<Vector3D> = new Vector.<Vector3D>();
            positions.push(new Vector3D(-500, 0, -500), new Vector3D(500, 0, -500), new Vector3D(0, 0, 500));
            
            var rotations:Vector.<Number> = new Vector.<Number>();
            rotations.push(45 * DEG2RAD, -45 * DEG2RAD, 0);
            
            var material:FillMaterial = new FillMaterial(0x333333, 1, 0, 0x0);
            
            for (var i:int = 0; i<3; i++) {
                var box:Box = new Box(500, 300, 300, 1, 1, 1);
               
                box.x = positions[i].x;
                box.y = positions[i].y;
                box.z = positions[i].z;
                box.rotationY = rotations[i];
                box.setMaterialToAllFaces(material);
                box.addEventListener(MouseEvent3D.CLICK, onClick);
                _container.addChild(box);
            }
            
            _camera.render();
            
            stage.addEventListener(Event.RESIZE, onResize);
            stage.addEventListener(MouseEvent.CLICK, onStageClick);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            addEventListener(Event.ENTER_FRAME, render);
            onResize();
        }
        
        private function onClick(e:MouseEvent3D):void
        {
            var vTarget:Vector3D;
            var vCam:Vector3D;
            var camRotationY:Number = 0;
            var tempObject:Object3D = e.target as Object3D;
            var vPos:Vector3D = new Vector3D(tempObject.x, tempObject.y, tempObject.z);
            var data:RayIntersectionData = tempObject.intersectRay(e.localOrigin, e.localDirection);
            _clickedFace = data.face;
            
            // Difference vector of clicked face to object's pos
            var vDiff:Vector3D = new Vector3D();
            var m3d : Matrix3D = tempObject.matrix.clone();
            m3d.appendTranslation(_clickedFace.normal.x * tempObject.boundMaxX, _clickedFace.normal.y * tempObject.boundMaxY, _clickedFace.normal.z * tempObject.boundMaxZ);
            vDiff = m3d.transformVector(vDiff);

            // Direction vector
            var vDirection : Vector3D = vPos.clone();
            vDirection = vDirection.subtract(vDiff.clone());
            vDirection.normalize();
            
            // Check face vector's alignment to y-axis
            var angleDirectionToUpVector:Number = Vector3D.angleBetween(new Vector3D(0,1,0), vDirection) * RAD2DEG;
            camRotationY = (angleDirectionToUpVector == 0 || angleDirectionToUpVector == 180) ? tempObject.rotationY : 0;
            
            // Calculate new camera target pos
            var vO : Vector3D = new Vector3D();
            m3d = new Matrix3D();
            m3d.identity();
            m3d.appendTranslation(-vDirection.x * tempObject.boundMaxX, -vDirection.y * tempObject.boundMaxY, -vDirection.z * tempObject.boundMaxZ);
            m3d.appendRotation(tempObject.rotationY * RAD2DEG, Vector3D.Y_AXIS, vO);
            m3d.appendTranslation(vPos.x, vPos.y, vPos.z);
            vTarget = new Vector3D();
            vTarget = m3d.transformVector(vTarget);
            
            // Calculate new camera pos
            m3d = new Matrix3D();
            m3d.identity();
            m3d.appendTranslation(-vDirection.x * CAM_DISTANCE, -vDirection.y * CAM_DISTANCE, -vDirection.z * CAM_DISTANCE);
            m3d.appendRotation(tempObject.rotationY * RAD2DEG, Vector3D.Y_AXIS, vO);
            m3d.appendTranslation(vTarget.x, vTarget.y, vTarget.z);
            vCam = new Vector3D();
            vCam = m3d.transformVector(vCam);
            vCam.z -= .001; // up-vector hack 

            // Start camera tween
            moveCamera(vTarget, vCam, camRotationY);
        }
        
        private function moveCamera(vTarget : Vector3D, vCam : Vector3D, camRotationY_:Number) : void 
        {
            TweenLite.killTweensOf(_vCamTarget);
            TweenLite.to(_vCamTarget, 1, {x:vTarget.x, y:vTarget.y, z:vTarget.z, ease:Sine.easeInOut});

            TweenLite.killTweensOf(this);
            TweenLite.to(this, 1, {camRotationY:camRotationY_, ease:Sine.easeInOut});

            TweenLite.killTweensOf(_vCam);
            TweenLite.to(_vCam, 1, {x:vCam.x, y:vCam.y, z:vCam.z, ease:Sine.easeInOut});
        }

        private function render( event:Event ) : void 
        {
            _cameraMatrix = new Matrix3D();
            _cameraMatrix.identity();
            _cameraMatrix.appendTranslation(_vCam.x, _vCam.y, _vCam.z);
            _cameraMatrix.appendRotation(_camRotationY * RAD2DEG, Vector3D.Y_AXIS, _vCamTarget);
            _cameraMatrix.pointAt(new Vector3D(_vCamTarget.x, _vCamTarget.y, _vCamTarget.z), Vector3D.Z_AXIS, Vector3D.Y_AXIS);
            
            _camera.matrix = _cameraMatrix;
            _camera.render();
        }
        
        public function onResize(event:Event = null) :void
        {
            _camera.view.width = stage.stageWidth;
            _camera.view.height = stage.stageHeight;
            _camera.fov = 2 * Math.atan2(Math.sqrt(_camera.view.width * _camera.view.width + _camera.view.height * _camera.view.height) / 2, 1100);  
        }
        
        private function onStageClick(event : MouseEvent) : void 
        {
            if (event.target is Stage) {
                
                if (!_clickedFace) 
                {
                    var vTarget:Vector3D = _vMouse3D.clone();
                    var vCam:Vector3D;
                    var camRotationY:Number = 0;
        
                    // Calculate direction vector of clicked pos (x,0,z) in relation to zero point (0,0,0)
                    var vDirection : Vector3D = new Vector3D();
                    vDirection = vDirection.subtract(vTarget.clone());
                    vDirection.normalize();
                    vDirection.scaleBy(4000);
                    
                    vCam = vTarget.clone();
                    vCam = vCam.subtract(vDirection);
                    vCam.y = 4000;
                    
                    moveCamera(vTarget, vCam, camRotationY);
                }
                else 
                {
                    _clickedFace = null;
                    moveCamera(new Vector3D(), V_CAMERA_INIT.clone(), 0);
                }
            }
            
        }
        
        private function onMouseMove(event : MouseEvent) : void {
            if (event.target is Stage) {
                
                var origin:Vector3D = new Vector3D();
                var directionA:Vector3D = new Vector3D();
                var directionB:Vector3D = new Vector3D();
                
                _camera.calculateRay(origin, directionA, _camera.view.width / 2, _camera.view.height / 2);
                _camera.calculateRay(origin, directionB, stage.mouseX, stage.mouseY);
    
                var pos : Vector3D = intersectionPoint(origin, directionB, new Vector3D(0, 0, 0), new Vector3D(0, 1, 0));
                _vMouse3D = new Vector3D(pos.x, pos.y, pos.z);
            }
        }
        
        public static function intersectionPoint(lineStart:Vector3D, lineDirection:Vector3D, planePosition:Vector3D, planeNormal:Vector3D):Vector3D {
            
            var result:Vector3D = new Vector3D();
            var w:Vector3D = lineStart.subtract(planePosition);
            var d:Number = planeNormal.dotProduct(lineDirection);
            var n:Number = -planeNormal.dotProduct(w);
            
            var sI:Number = n / d;
            
            result.x = lineStart.x + (lineDirection.x * sI);
            result.y = lineStart.y + (lineDirection.y * sI);
            result.z = lineStart.z + (lineDirection.z * sI);

            return result;
        }

        public function get camRotationY() : Number {
            return _camRotationY;
        }

        public function set camRotationY(camRotationY : Number) : void {
            _camRotationY = camRotationY;
        }

        public function get vCamTarget() : Vector3D {
            return _vCamTarget;
        }

        public function set vCamTarget(vCamTarget : Vector3D) : void {
            _vCamTarget = vCamTarget;
        }

        public function get vCam() : Vector3D {
            return _vCam;
        }

        public function set vCam(vCam : Vector3D) : void {
            _vCam = vCam;
        }
    }
}