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: perspective projection bgstaal

Taken from:
http://bgstaal.net/blog/?p=57
Get Adobe Flash player
by jules 14 Jan 2012
    Embed
/**
 * Copyright jules ( http://wonderfl.net/user/jules )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/jzRG
 */

// forked from jules's perspective projection bgstaal
/*Taken from:
http://bgstaal.net/blog/?p=57


*/


package {
    import flash.display.Sprite;
    
        
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Point;
    
        import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.net.*;
    import flash.system.*;
    import flash.utils.*;
    import org.libspark.betweenas3.BetweenAS3;
    import org.libspark.betweenas3.easing.*;
    import org.libspark.betweenas3.tweens.ITween;
    import org.papervision3d.core.geom.renderables.Vertex3D;
    import org.papervision3d.core.utils.Mouse3D;
    import org.papervision3d.events.InteractiveScene3DEvent;
    import org.papervision3d.materials.BitmapMaterial;
    import org.papervision3d.objects.primitives.Plane;
    import org.papervision3d.render.QuadrantRenderEngine;
    import org.papervision3d.view.BasicView;
    import com.bit101.components.*;
    
    [SWF(width="640", height="480", backgroundColor="0xbbFDE2")]
    public class SpinningCube extends Sprite
    {
        private const COLOR:Number = 0x000000;
        private const COLOR2:Number = 0xFF0000;
        private const COLOR3:Number = 0x00FF00;
        
        private var _cubeWidth:Number;
        private var _cubeHeight:Number;
        private var _cubeDepth:Number;
        private var _cubeX:Number;
        private var _cubeY:Number;
        private var _projectionCenter:Point;
        private var _fieldOfView:Number;
        private var _focalLength:Number;
        private var _pivotPoint:Point3d;
        private var _3dPoints:Vector.<Point3d>;
        private var _2dPoints:Vector.<Point2d>;
        
        private var _centrePointX:Number;
        private var  _centrePointY:Number;
        
        private var _rotationX:Number = 0;
        private var _rotationY:Number = 0;
        private var _rotationZ:Number = 0;
        
        private var myLoader:Loader;
        
        private const IMAGE_URL:String = "http://farm4.static.flickr.com/3190/2662752839_249c6642b1.jpg";
        
        
        public function SpinningCube()
        {
            init();
        }
        
        private function init ():void
        {
            setProperties();
            createProjection();
            
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);    
            
            myLoader= new Loader();
            myLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressStatus);
            myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderReady);

            var fileRequest:URLRequest = new URLRequest("http://maptopixel.com/projects/images/1326473779375__yaw_168.0_pitch_47.0_roll_-92.0_small.jpg");
            myLoader.load(fileRequest);
            
            myLoader.alpha = 0.5;

        }
        
        
        public function onProgressStatus(e:ProgressEvent) {   
      // this is where progress will be monitored     
          //trace(e.bytesLoaded, e.bytesTotal); 
        }

        public function onLoaderReady(e:Event) {     
      // the image is now loaded, so let's add it to the display tree! 
              
              addChild(myLoader);
              myLoader.x = 0;
              myLoader.y = 0;
            
        }


        /**
         * Set the inital properties for our perspective projection scene
        */
        private function setProperties ():void
        {
            // set the size properties of the cube
            _cubeWidth = 100;
            _cubeHeight = 100;
            _cubeDepth = 100;
            
            // Set the position of the cube to the center of the stage
            //_cubeX = (stage.stageWidth - _cubeWidth)/2;
            //_cubeY = (stage.stageHeight - _cubeHeight)/2;
            
            
            _cubeX =  stage.stageWidth /2;
            _cubeY =  stage.stageHeight /2;
            
            
            _centrePointX = stage.stageWidth /2;
            _centrePointY = stage.stageHeight/2;
            
           // _cubeX = 0;
            //_cubeY = 0;
            
            
            // Set the projection center (vanishing point) to the center of the stage
            _projectionCenter = new Point(stage.stageWidth/2, stage.stageHeight/2);
            
            

                
                
             //_projectionCenter = new Point(200, 200);
            
            
            // Set the pivot point to be at the 3d center of the cube
            //_pivotPoint = new Point3d(_cubeX + (_cubeWidth/2), _cubeY + (_cubeHeight/2), _cubeDepth/2);
            _pivotPoint = new Point3d(_cubeX, _cubeY, _cubeDepth);
           
            
            // Set the the field of view to a numver between 1 & 179.
            _fieldOfView = 55;
            
            // Calculate the focal length based on the width of the stage and the field of view.
            var a:Number = _fieldOfView/2;
            var b:Number = 90 - a;
            var bRad:Number = b/180*Math.PI;
            var opposite:Number = stage.stageWidth/2;
            
            _focalLength = opposite * Math.tan(bRad);
        }
        
        private function enterFrameHandler (e:Event):void
        {
            createProjection();
        }
        
        
        private function createProjection ():void
        {
            create3dPoints();
            rotate3dPoints();
            projectPoints();
            drawPoints();
            //drawLines();
            drawLines2();
            
            _rotationX =47; //Should take pitch value I think
            _rotationY =12; //Should be taken from the previous points somehoew, or yaw
            _rotationZ = 0;
        }
        
        /**
         * Creates the 3d points based on the properties we set earlier
        */
        private function create3dPoints ():void
        {
            _3dPoints = new Vector.<Point3d>();
            
            /*
            _3dPoints.push(new Point3d(30,10, 180));
            _3dPoints.push(new Point3d(20,10, 28));
            _3dPoints.push(new Point3d(126,10, 20));
            */
            /*
            _3dPoints.push(new Point3d(100,300, 400));
            _3dPoints.push(new Point3d(stage.stageWidth/2, stage.stageHeight/2,300));
            _3dPoints.push(new Point3d(350,300, 400));
            */
 
            // add points to create a rectangle of the supplied width and height
            // at the supplied x and y coordinates and a z value of 0
            
            _3dPoints.push(new Point3d(_centrePointX, _centrePointY , _cubeDepth));//centre of frustr
            
            
            _3dPoints.push(new Point3d(_centrePointX-350, _centrePointY, _cubeDepth));
            _3dPoints.push(new Point3d(_centrePointX+350, _centrePointY, _cubeDepth));
            //_3dPoints.push(new Point3d(_cubeX + _cubeWidth, _cubeY, 0));
            //_3dPoints.push(new Point3d(_cubeX + _cubeWidth, _cubeY + _cubeHeight, 0));
        
            //_3dPoints.push(new Point3d(_cubeX, _cubeY + _cubeHeight, 0));
            
            _3dPoints.push(new Point3d(_centrePointX, _centrePointY , _cubeDepth-250));
            
             _3dPoints.push(new Point3d(_centrePointX, _centrePointY+250 , _cubeDepth));
              _3dPoints.push(new Point3d(_centrePointX, _centrePointY-250, _cubeDepth));
            // then add the same points again with a z value of the supplied depth
           // _3dPoints.push(new Point3d(_cubeX, _cubeY, _cubeDepth));
          //  _3dPoints.push(new Point3d(_cubeX + _cubeWidth, _cubeY, _cubeDepth));
          //  _3dPoints.push(new Point3d(_cubeX + _cubeWidth, _cubeY + _cubeHeight, _cubeDepth));
             
              _3dPoints.push(new Point3d(_centrePointX, _centrePointY , _cubeDepth+250));
             //_3dPoints.push(new Point3d(_centrePointX, _centrePointY , _cubeDepth));
            
        }
        
        /**
         * Loops through the 3d points and rotates each point around the pivot point
         */
        private function rotate3dPoints ():void
        {
            var rotationMatrix:Matrix3d = Matrix3d.createRotationMatrix(_rotationX, _rotationY, _rotationZ);
            
            for (var i:int = 0; i < _3dPoints.length; i++)
            {
                var point3d:Point3d = _3dPoints[i];
                point3d.applyMatrix(rotationMatrix, _pivotPoint);
            }
        }
        
        /**
         * Loops through and projects the 3d points to create a vector of 2d points.
         */
        private function projectPoints ():void
        {
            _2dPoints = new Vector.<Point2d>();
            
            for (var i:int = 0; i < _3dPoints.length; i++)
            {
                var point3d:Point3d = _3dPoints[i];
                
                // calls the project function on each point3d wich reaturns a point2d
                var point2d:Point2d = point3d.project(_focalLength, _projectionCenter);
                _2dPoints.push(point2d)
            }
        }
        
        
        /**
         * Draws a circle on stage as a visual representation of each point
         */
        private function drawPoints ():void
        {
            var radius:Number = 5;
            
            graphics.clear();
            
            for (var i:int = 0; i < _2dPoints.length; i++)
            {
                var point2d:Point2d = _2dPoints[i];
                graphics.beginFill(COLOR);
                graphics.drawCircle(point2d.x, point2d.y, radius*point2d.t);
                graphics.endFill()
            }
            
                            graphics.beginFill(COLOR3);
          
                graphics.drawCircle(_projectionCenter.x,_projectionCenter.y, 2);
                graphics.endFill()
        }
        
        
        /**
         * Draws a the lines that connects the eight corners of the cube
         */
        private function drawLines ():void
        {
            graphics.lineStyle(1, COLOR);
            
            // draw the first rectangle
            graphics.moveTo(_2dPoints[0].x, _2dPoints[0].y);
            graphics.lineTo(_2dPoints[1].x, _2dPoints[1].y);
            
            graphics.lineTo(_2dPoints[2].x, _2dPoints[2].y);
            graphics.lineTo(_2dPoints[3].x, _2dPoints[3].y);
            graphics.lineTo(_2dPoints[0].x, _2dPoints[0].y);
            
            // draw the second rectangle
            graphics.moveTo(_2dPoints[4].x, _2dPoints[4].y);
            graphics.lineTo(_2dPoints[5].x, _2dPoints[5].y);
            graphics.lineTo(_2dPoints[6].x, _2dPoints[6].y);
            graphics.lineTo(_2dPoints[7].x, _2dPoints[7].y);
            graphics.lineTo(_2dPoints[4].x, _2dPoints[4].y);
            
            // draw lines between the corners of the rectangles
            graphics.moveTo(_2dPoints[0].x, _2dPoints[0].y);
            graphics.lineTo(_2dPoints[4].x, _2dPoints[4].y);
            
            graphics.moveTo(_2dPoints[1].x, _2dPoints[1].y);
            graphics.lineTo(_2dPoints[5].x, _2dPoints[5].y);
            
            graphics.moveTo(_2dPoints[2].x, _2dPoints[2].y);
            graphics.lineTo(_2dPoints[6].x, _2dPoints[6].y);
            
            graphics.moveTo(_2dPoints[3].x, _2dPoints[3].y);
            graphics.lineTo(_2dPoints[7].x, _2dPoints[7].y);
            
        }
        
        
       private function drawLines2 ():void
        {
            graphics.lineStyle(1, COLOR);
            
            // draw the first rectangle
            graphics.moveTo(_2dPoints[0].x, _2dPoints[0].y);
            
            graphics.lineTo(_2dPoints[1].x, _2dPoints[1].y);
            
            graphics.lineStyle(1, COLOR2);
            graphics.moveTo(_2dPoints[0].x, _2dPoints[0].y);
            graphics.lineTo(_2dPoints[2].x, _2dPoints[2].y);
            
            graphics.lineStyle(1, COLOR3);
            graphics.moveTo(_2dPoints[0].x, _2dPoints[0].y);
            graphics.lineTo(_2dPoints[3].x, _2dPoints[3].y);
            
            graphics.moveTo(_2dPoints[0].x, _2dPoints[0].y);
            graphics.lineTo(_2dPoints[4].x, _2dPoints[4].y);
            
             graphics.lineStyle(1, COLOR2);
            graphics.moveTo(_2dPoints[0].x, _2dPoints[0].y);
            graphics.lineTo(_2dPoints[5].x, _2dPoints[5].y);
            
           graphics.lineStyle(1, COLOR3);
            graphics.moveTo(_2dPoints[0].x, _2dPoints[0].y);
            graphics.lineTo(_2dPoints[6].x, _2dPoints[6].y);
            /*
            // draw the second rectangle
            graphics.moveTo(_2dPoints[4].x, _2dPoints[4].y);
            graphics.lineTo(_2dPoints[5].x, _2dPoints[5].y);
            graphics.lineTo(_2dPoints[6].x, _2dPoints[6].y);
            graphics.lineTo(_2dPoints[7].x, _2dPoints[7].y);
            graphics.lineTo(_2dPoints[4].x, _2dPoints[4].y);
            
            // draw lines between the corners of the rectangles
            graphics.moveTo(_2dPoints[0].x, _2dPoints[0].y);
            graphics.lineTo(_2dPoints[4].x, _2dPoints[4].y);
            
            graphics.moveTo(_2dPoints[1].x, _2dPoints[1].y);
            graphics.lineTo(_2dPoints[5].x, _2dPoints[5].y);
            
            graphics.moveTo(_2dPoints[2].x, _2dPoints[2].y);
            graphics.lineTo(_2dPoints[6].x, _2dPoints[6].y);
            
            graphics.moveTo(_2dPoints[3].x, _2dPoints[3].y);
            graphics.lineTo(_2dPoints[7].x, _2dPoints[7].y);
            */
        }
        
    }
    

}




    import flash.geom.Point;
    
    /**
     * <b>Point3d ©2009, bgstaal.net</b>
     * <hr/>
     * The Point3d holds the properties to represent a single point i 3d space (x,y,z) 
     * and the methods to apply transformation matrices and return a 2d representation
     * of the 3d point.
     * @author        Bjørn Gunnar Staal
     * @version        1.0
     */
    class Point3d
    {
        /**
         * The x coordinate
         */
        public var x:Number;
        
        /**
         * The y coordinate
         */
        public var y:Number;
        
        /**
         * The z coordinate
         */
        public var z:Number;
        
        /**
         * Creates a Point3d instance
         * @param    x    The x coordinate
         * @param    y    The y coordinate
         * @param    z    The z coordinate
         */
        public function Point3d(x:Number = 0, y:Number = 0, z:Number = 0)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        
        /**
         * Performs a perspective projection on the instance and returns a 2d represenation of the 3d coordinates
         * @param        focalLength            Distance from camera to the stage
         * @param        projectionCenter    2d coordinate representing the center of the viewing frustrum (vanishing point)
         * @return        A Point2d instance representing a projected version of <code>this<code>
         */
        public function project (focalLength:Number, projectionCenter:Point = null):Point2d
        {
            var t:Number = focalLength / (focalLength+z);
            
            
            if (!projectionCenter)
            {
                projectionCenter = new Point(0, 0);
            }
            
            var xOffset:Number = projectionCenter.x;
            var yOffset:Number = projectionCenter.y;
            
            var x:Number = this.x;
            var y:Number = this.y;
            var z:Number = this.z;
            
            x -= xOffset;
            y -= yOffset;
            
            x = (x*t)+xOffset;
            y = (y*t)+yOffset;
            
            return new Point2d(x, y, t);
        }
        
        /**
         * Applies the supplied transformation matrix to the point around the supplied pivot point
         * @param        m                Matrix3d instance with the transformation values
         * @param        pivotPoint        A Point in 3d witch the transformation should be applied around. The coordinates (0,0,0) is used if no value is supplied.
         */
        public function applyMatrix (m:Matrix3d, pivotPoint:Point3d = null):void
        {
            if (!pivotPoint)
            {
                pivotPoint = new Point3d();
            }
            
            var p:Point3d = m.apply(this, pivotPoint);
            
            this.x = p.x;
            this.y = p.y;
            this.z = p.z;
        }

    }
    
    
    class Point2d
    {
        /**
         * The points x coordinate
         */
        public var x:Number;
        
        /**
         * The points y coordinate
         */
        public var y:Number;
        
        /**
         * The value t represents the points scale
         */
        public var t:Number;
        
        /**
         * Create a Point2d instance
         * @param    x    The x coordinate
         * @param    y    The y coordinate
         * @param    t    The value t represents the points scale
         */
        public function Point2d(x:Number, y:Number, t:Number)
        {
            this.x = x;
            this.y = y;
            this.t = t;
        }
        
        /**
         * Returns the x, y & t values as a string
         * @return    A string representation of the public properties.
         */
        public function toString ():String
        {
            return "x: " + x + ", y: " + y + ", t: " + t;
        }

    }
    
    
    
    class Matrix3d
    {
        /**
         * <p>
         * X  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * </p>
         */
        public var n11:Number;
        
        /**
         * <p>
         * 0  X  0  0  <br/>
         * 0  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * </p>
         */
        public var n12:Number;
        
        /**
         * <p>
         * 0  0  X  0  <br/>
         * 0  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * </p>
         */
        public var n13:Number;
        
        /**
         * <p>
         * 0  0  0  X  <br/>
         * 0  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * </p>
         */
        public var n14:Number;
        
        /**
         * <p>
         * 0  0  0  0  <br/>
         * X  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * </p>
         */
        public var n21:Number;
        
        /**
         * <p>
         * 0  0  0  0  <br/>
         * 0  X  0  0  <br/>
         * 0  0  0  0  <br/>
         * </p>
         */
        public var n22:Number;
        
        /**
         * <p>
         * 0  0  0  0  <br/>
         * 0  0  X  0  <br/>
         * 0  0  0  0  <br/>
         * </p>
         */
        public var n23:Number;
        
        /**
         * <p>
         * 0  0  0  0  <br/>
         * 0  0  0  X  <br/>
         * 0  0  0  0  <br/>
         * </p>
         */
        public var n24:Number;
        
        /**
         * <p>
         * 0  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * X  0  0  0  <br/>
         * </p>
         */
        public var n31:Number;
        
        /**
         * <p>
         * 0  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * 0  X  0  0  <br/>
         * </p>
         */
        public var n32:Number;
        
        /**
         * <p>
         * 0  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * 0  0  X  0  <br/>
         * </p>
         */
        public var n33:Number;
        
        /**
         * <p>
         * 0  0  0  0  <br/>
         * 0  0  0  0  <br/>
         * 0  0  0  X  <br/>
         * </p>
         */
        public var n34:Number;
        
        
        /**
         * Create a new Matrix3d Object.
         * By default a 4x3 identity matrix is created.
         * @param    n11        The value in the first collumn of the first row
         * @param    n12        The value in the second collumn of the first row
         * @param    n13        The value in the third collumn of the first row
         * @param    n14        The value in the fourth collumn of the first row
         * @param    n21        The value in the first collumn of the second row
         * @param    n22        The value in the second collumn of the second row
         * @param    n23        The value in the third collumn of the second row
         * @param    n24        The value in the fourth collumn of the second row
         * @param    n31        The value in the first collumn of the third row
         * @param    n32        The value in the second collumn of the third row
         * @param    n33        The value in the third collumn of the third row
         * @param    n34        The value in the fourth collumn of the third row
         */
        public function Matrix3d(n11:Number = 1, n12:Number = 0, n13:Number = 0, n14:Number = 0,
                                 n21:Number = 0, n22:Number = 1, n23:Number = 0, n24:Number = 0,
                                 n31:Number = 0, n32:Number = 0, n33:Number = 1, n34:Number = 0)
        {
            this.n11 = n11;
            this.n12 = n12;
            this.n13 = n13;
            this.n14 = n14;
            this.n21 = n21;
            this.n22 = n22;
            this.n23 = n23;
            this.n24 = n24;
            this.n31 = n31;
            this.n32 = n32;
            this.n33 = n33;
            this.n34 = n34;
        }
        
        /**
         * Applies the transformation to a Point3d around a pivot point and returns a new point3d
         * @param    p            The point witch the transformation should be applied to.
         * @param    pivotPoint    The point in 3d witch the transformation should be applied around. The coordinates (0,0,0) is used if no value is supplied.
         * @return    A new Point3d representing the supplied Point3d instance with the transformations applied.
         */
        public function apply (p:Point3d, pivotPoint:Point3d = null):Point3d
        {
            if (!pivotPoint)
            {
                pivotPoint = new Point3d();
            }
            
            p.x -= pivotPoint.x;
            p.y -= pivotPoint.y;
            p.z -= pivotPoint.z;
            
            var x:Number = (p.x * n11) + (p.y * n12) + (p.z * n13) + n14 + pivotPoint.x;
            var y:Number = (p.x * n21) + (p.y * n22) + (p.z * n23) + n14 + pivotPoint.y;
            var z:Number = (p.x * n31) + (p.y * n32) + (p.z * n33) + n14 + pivotPoint.z;
            
            return new Point3d(x, y, z);
        }
        
        
        /**
         * Creates a transformation matrix with the supplied rotation around either axis
         * @param    xRotation    The number of degrees of rotation that should be applied around the x axis. (roll)
         * @param    yRotation    The number of degrees of rotation that should be applied around the y axis. (pitch)
         * @param    zRotation    The number of degrees of rotation that should be applied around the z axis. (yaw)
         * @return    A Matrix3d instance with the supplied rotations applied.
         */
        public static function createRotationMatrix (xRotation:Number, yRotation:Number, zRotation:Number):Matrix3d
        {
            var xMatrix:Matrix3d = createXRotationMatrix(xRotation);
            var yMatrix:Matrix3d = createYRotationMatrix(yRotation);
            var zMatrix:Matrix3d = createZRotationMatrix(zRotation);
            
            var m:Matrix3d = multiplySeveral(xMatrix, yMatrix, zMatrix);
            
            return m;
        }
        
        /**
         * Creates a rotation matrix with the supplied rotation around the x axis. (roll)
         * @param    rotation    The number of degrees of rotation that should be applied around the x axis
         * @return    A Matrix3d instance with the supplied x rotation applied.
         */
        public static function createXRotationMatrix (rotation:Number):Matrix3d
        {
            var radians:Number = rotation/180*Math.PI;
            
            var n:Array = [1, 0, 0, 0,
                           0, Math.cos(radians), Math.sin(radians), 0,
                           0, -Math.sin(radians), Math.cos(radians), 0];
            
            return matrix3dFromArray(n);
        }

        /**
         * Creates a rotation matrix with the supplied rotation around the y axis. (pitch)
         * @param    rotation    The number of degrees of rotation that should be applied around the y axis
         * @return    A Matrix3d instance with the supplied y rotation applied.
         */
        public static function createYRotationMatrix (rotation:Number):Matrix3d
        {
            var radians:Number = rotation/180*Math.PI;
            
            var n:Array = [Math.cos(radians), 0, Math.sin(radians), 0,
                           0, 1, 0, 0,
                           -Math.sin(radians), 0, Math.cos(radians), 0];
            
            return matrix3dFromArray(n);
        }
        
        /**
         * Creates a rotation matrix with the supplied rotation around the z axis. (yaw)
         * @param    rotation    The number of degrees of rotation that should be applied around the z axis
         * @return    A Matrix3d instance with the supplied z rotation applied.
         */
        public static function createZRotationMatrix (rotation:Number):Matrix3d
        {
            var radians:Number = rotation/180*Math.PI;
            
            var n:Array = [Math.cos(radians), Math.sin(radians), 0, 0,
                           -Math.sin(radians), Math.cos(radians), 0, 0,
                           0, 0, 1, 0];
                                                         
            return matrix3dFromArray(n);
        }
        
        /**
         * Creates a Matrix3d filled with the values from the supplied array
         * @param    n    A Array instance with 12 entries representing the numbers in the matrix starting with the top left collumn and ending with the bottom right.
         * @return    A Matrix3d instance filled with the supplied values
         */
        public static function matrix3dFromArray (n:Array):Matrix3d
        {
            if (n.length == 12)
            {
                var m:Matrix3d = new Matrix3d(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11]);
                return m;
            }
            else
            {
                return null;
            }
        }
        
        /**
         * Multiplies two Matrix3d instances and returns the result
         * @param    a    The first matrix
         * @param    b    The seconds matrix
         * @return    A Matrix3d instance representing the result of the multiplication
         */
        public static function multiply (a:Matrix3d, b:Matrix3d):Matrix3d
        {
            var c:Matrix3d = new Matrix3d();
            
            c.n11 = a.n11 * b.n11 + a.n12 * b.n21 + a.n13 * b.n31;
            c.n12 = a.n11 * b.n12 + a.n12 * b.n22 + a.n13 * b.n32;
            c.n13 = a.n11 * b.n13 + a.n12 * b.n23 + a.n13 * b.n33;
            c.n14 = a.n11 * b.n14 + a.n12 * b.n24 + a.n13 * b.n34 + a.n14;
    
            c.n21 = a.n21 * b.n11 + a.n22 * b.n21 + a.n23 * b.n31;
            c.n22 = a.n21 * b.n12 + a.n22 * b.n22 + a.n23 * b.n32;
            c.n23 = a.n21 * b.n13 + a.n22 * b.n23 + a.n23 * b.n33;
            c.n24 = a.n21 * b.n14 + a.n22 * b.n24 + a.n23 * b.n34 + a.n24;
    
            c.n31 = a.n31 * b.n11 + a.n32 * b.n21 + a.n33 * b.n31;
            c.n32 = a.n31 * b.n12 + a.n32 * b.n22 + a.n33 * b.n32;
            c.n33 = a.n31 * b.n13 + a.n32 * b.n23 + a.n33 * b.n33;
            c.n34 = a.n31 * b.n14 + a.n32 * b.n24 + a.n33 * b.n34 + a.n34;
            
            return c;
        }
        
        /**
         * Multiplies several Matrix3d instances and returns the result
         * @param    matrices    The Matrix3d instances that should be multiplied.
         * @return    A Matrix3d instance representing the result of the multiplication
         */
        public static function multiplySeveral (...matrices):Matrix3d
        {
            var newMatrix:Matrix3d = matrices[0];
            
            for (var i:int = 1; i < matrices.length; i++)
            {
                var m:Matrix3d = matrices[i];
                newMatrix = multiply(newMatrix, m);
            }
            
            return newMatrix;
        }
        
    }