All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scaffold.libs_as.starling.utils.MatrixUtil.as Maven / Gradle / Ivy

// =================================================================================================
//
//	Starling Framework
//	Copyright 2011-2015 Gamua. All Rights Reserved.
//
//	This program is free software. You can redistribute and/or modify it
//	in accordance with the terms of the accompanying license agreement.
//
// =================================================================================================

package starling.utils
{
    import flash.geom.Matrix;
    import flash.geom.Matrix3D;
    import flash.geom.Point;
    import flash.geom.Vector3D;

    import starling.errors.AbstractClassError;

    /** A utility class containing methods related to the Matrix class. */
    public class MatrixUtil
    {
        // helper objects
        private static var sRawData:Vector. =
            new [1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1];
        private static var sRawData2:Vector. = new Vector.(16, true);
        private static var sPoint3D:Vector3D = new Vector3D();
        private static var sMatrixData:Vector. =
                new [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

        /** @private */
        public function MatrixUtil() { throw new AbstractClassError(); }

        /** Converts a 2D matrix to a 3D matrix. If you pass an out-matrix,
         *  the result will be stored in this matrix instead of creating a new object. */
        public static function convertTo3D(matrix:Matrix, out:Matrix3D=null):Matrix3D
        {
            if (out == null) out = new Matrix3D();

            sRawData[ 0] = matrix.a;
            sRawData[ 1] = matrix.b;
            sRawData[ 4] = matrix.c;
            sRawData[ 5] = matrix.d;
            sRawData[12] = matrix.tx;
            sRawData[13] = matrix.ty;

            out.copyRawDataFrom(sRawData);
            return out;
        }

        /** Converts a 3D matrix to a 2D matrix. Beware that this will work only for a 3D matrix
         *  describing a pure 2D transformation. */
        public static function convertTo2D(matrix3D:Matrix3D, out:Matrix=null):Matrix
        {
            if (out == null) out = new Matrix();

            matrix3D.copyRawDataTo(sRawData2);
            out.a  = sRawData2[ 0];
            out.b  = sRawData2[ 1];
            out.c  = sRawData2[ 4];
            out.d  = sRawData2[ 5];
            out.tx = sRawData2[12];
            out.ty = sRawData2[13];

            return out;
        }

        /** Determines if the matrix is an identity matrix. */
        public static function isIdentity(matrix:Matrix):Boolean
        {
            return matrix.a  == 1.0 && matrix.b  == 0.0 && matrix.c == 0.0 && matrix.d == 1.0 &&
                   matrix.tx == 0.0 && matrix.ty == 0.0;
        }

        /** Determines if the 3D matrix is an identity matrix. */
        public static function isIdentity3D(matrix:Matrix3D):Boolean
        {
            var data:Vector. = sRawData2;
            matrix.copyRawDataTo(data);

            return data[ 0] == 1.0 && data[ 1] == 0.0 && data[ 2] == 0.0 && data[ 3] == 0.0 &&
                   data[ 4] == 0.0 && data[ 5] == 1.0 && data[ 6] == 0.0 && data[ 7] == 0.0 &&
                   data[ 8] == 0.0 && data[ 9] == 0.0 && data[10] == 1.0 && data[11] == 0.0 &&
                   data[12] == 0.0 && data[13] == 0.0 && data[14] == 0.0 && data[15] == 1.0;
        }

        /** Transform a point with the given matrix. */
        public static function transformPoint(matrix:Matrix, point:Point,
                                              out:Point=null):Point
        {
            return transformCoords(matrix, point.x, point.y, out);
        }

        /** Transforms a 3D point with the given matrix. */
        public static function transformPoint3D(matrix:Matrix3D, point:Vector3D,
                                                out:Vector3D=null):Vector3D
        {
            return transformCoords3D(matrix, point.x, point.y, point.z, out);
        }

        /** Uses a matrix to transform 2D coordinates into a different space. If you pass an
         *  out-point, the result will be stored in this point instead of creating
         *  a new object. */
        public static function transformCoords(matrix:Matrix, x:Number, y:Number,
                                               out:Point=null):Point
        {
            if (out == null) out = new Point();

            out.x = matrix.a * x + matrix.c * y + matrix.tx;
            out.y = matrix.d * y + matrix.b * x + matrix.ty;

            return out;
        }

        /** Uses a matrix to transform 3D coordinates into a different space. If you pass a
         *  'resultVector', the result will be stored in this vector3D instead of creating a
         *  new object. */
        public static function transformCoords3D(matrix:Matrix3D, x:Number, y:Number, z:Number,
                                                 out:Vector3D=null):Vector3D
        {
            if (out == null) out = new Vector3D();

            matrix.copyRawDataTo(sRawData2);
            out.x = x * sRawData2[0] + y * sRawData2[4] + z * sRawData2[ 8] + sRawData2[12];
            out.y = x * sRawData2[1] + y * sRawData2[5] + z * sRawData2[ 9] + sRawData2[13];
            out.z = x * sRawData2[2] + y * sRawData2[6] + z * sRawData2[10] + sRawData2[14];
            out.w = x * sRawData2[3] + y * sRawData2[7] + z * sRawData2[11] + sRawData2[15];

            return out;
        }

        /** Appends a skew transformation to a matrix (angles in radians). The skew matrix
         *  has the following form:
         *  
         *  | cos(skewY)  -sin(skewX)  0 |
         *  | sin(skewY)   cos(skewX)  0 |
         *  |     0            0       1 |
         *  
*/ public static function skew(matrix:Matrix, skewX:Number, skewY:Number):void { var sinX:Number = Math.sin(skewX); var cosX:Number = Math.cos(skewX); var sinY:Number = Math.sin(skewY); var cosY:Number = Math.cos(skewY); matrix.setTo(matrix.a * cosY - matrix.b * sinX, matrix.a * sinY + matrix.b * cosX, matrix.c * cosY - matrix.d * sinX, matrix.c * sinY + matrix.d * cosX, matrix.tx * cosY - matrix.ty * sinX, matrix.tx * sinY + matrix.ty * cosX); } /** Prepends a matrix to 'base' by multiplying it with another matrix. */ public static function prependMatrix(base:Matrix, prep:Matrix):void { base.setTo(base.a * prep.a + base.c * prep.b, base.b * prep.a + base.d * prep.b, base.a * prep.c + base.c * prep.d, base.b * prep.c + base.d * prep.d, base.tx + base.a * prep.tx + base.c * prep.ty, base.ty + base.b * prep.tx + base.d * prep.ty); } /** Prepends an incremental translation to a Matrix object. */ public static function prependTranslation(matrix:Matrix, tx:Number, ty:Number):void { matrix.tx += matrix.a * tx + matrix.c * ty; matrix.ty += matrix.b * tx + matrix.d * ty; } /** Prepends an incremental scale change to a Matrix object. */ public static function prependScale(matrix:Matrix, sx:Number, sy:Number):void { matrix.setTo(matrix.a * sx, matrix.b * sx, matrix.c * sy, matrix.d * sy, matrix.tx, matrix.ty); } /** Prepends an incremental rotation to a Matrix object (angle in radians). */ public static function prependRotation(matrix:Matrix, angle:Number):void { var sin:Number = Math.sin(angle); var cos:Number = Math.cos(angle); matrix.setTo(matrix.a * cos + matrix.c * sin, matrix.b * cos + matrix.d * sin, matrix.c * cos - matrix.a * sin, matrix.d * cos - matrix.b * sin, matrix.tx, matrix.ty); } /** Prepends a skew transformation to a Matrix object (angles in radians). The skew matrix * has the following form: *
         *  | cos(skewY)  -sin(skewX)  0 |
         *  | sin(skewY)   cos(skewX)  0 |
         *  |     0            0       1 |
         *  
*/ public static function prependSkew(matrix:Matrix, skewX:Number, skewY:Number):void { var sinX:Number = Math.sin(skewX); var cosX:Number = Math.cos(skewX); var sinY:Number = Math.sin(skewY); var cosY:Number = Math.cos(skewY); matrix.setTo(matrix.a * cosY + matrix.c * sinY, matrix.b * cosY + matrix.d * sinY, matrix.c * cosX - matrix.a * sinX, matrix.d * cosX - matrix.b * sinX, matrix.tx, matrix.ty); } /** Converts a Matrix3D instance to a String, which is useful when debugging. Per default, * the raw data is displayed transposed, so that the columns are displayed vertically. */ public static function toString3D(matrix:Matrix3D, transpose:Boolean=true, precision:int=3):String { if (transpose) matrix.transpose(); matrix.copyRawDataTo(sRawData2); if (transpose) matrix.transpose(); return "[Matrix3D rawData=\n" + formatRawData(sRawData2, 4, 4, precision) + "\n]"; } /** Converts a Matrix instance to a String, which is useful when debugging. */ public static function toString(matrix:Matrix, precision:int=3):String { sRawData2[0] = matrix.a; sRawData2[1] = matrix.c; sRawData2[2] = matrix.tx; sRawData2[3] = matrix.b; sRawData2[4] = matrix.d; sRawData2[5] = matrix.ty; return "[Matrix rawData=\n" + formatRawData(sRawData2, 3, 2, precision) + "\n]"; } private static function formatRawData(data:Vector., numCols:int, numRows:int, precision:int, indent:String=" "):String { var result:String = indent; var numValues:int = numCols * numRows; var highestValue:Number = 0.0; var valueString:String; var value:Number; for (var i:int=0; i highestValue) highestValue = value; } var numChars:int = highestValue.toFixed(precision).length + 1; for (var y:int=0; yThe first 4 parameters define which area of the stage you want to view (the camera * will 'zoom' to exactly this region). The final 3 parameters determine the perspective * in which you're looking at the stage.

* *

The stage is always on the rectangle that is spawned up between x- and y-axis (with * the given size). All objects that are exactly on that rectangle (z equals zero) will be * rendered in their true size, without any distortion.

* *

If you pass only the first 4 parameters, the camera will be set up above the center * of the stage, with a field of view of 1.0 rad.

*/ public static function createPerspectiveProjectionMatrix( x:Number, y:Number, width:Number, height:Number, stageWidth:Number=0, stageHeight:Number=0, cameraPos:Vector3D=null, out:Matrix3D=null):Matrix3D { if (out == null) out = new Matrix3D(); if (stageWidth <= 0) stageWidth = width; if (stageHeight <= 0) stageHeight = height; if (cameraPos == null) { cameraPos = sPoint3D; cameraPos.setTo( stageWidth / 2, stageHeight / 2, // -> center of stage stageWidth / Math.tan(0.5) * 0.5); // -> fieldOfView = 1.0 rad } const focalLength:Number = Math.abs(cameraPos.z); const offsetX:Number = cameraPos.x - stageWidth / 2; const offsetY:Number = cameraPos.y - stageHeight / 2; const far:Number = focalLength * 20; const near:Number = 1; const scaleX:Number = stageWidth / width; const scaleY:Number = stageHeight / height; // set up general perspective sMatrixData[ 0] = 2 * focalLength / stageWidth; // 0,0 sMatrixData[ 5] = -2 * focalLength / stageHeight; // 1,1 [negative to invert y-axis] sMatrixData[10] = far / (far - near); // 2,2 sMatrixData[14] = -far * near / (far - near); // 2,3 sMatrixData[11] = 1; // 3,2 // now zoom in to visible area sMatrixData[0] *= scaleX; sMatrixData[5] *= scaleY; sMatrixData[8] = scaleX - 1 - 2 * scaleX * (x - offsetX) / stageWidth; sMatrixData[9] = -scaleY + 1 + 2 * scaleY * (y - offsetY) / stageHeight; out.copyRawDataFrom(sMatrixData); out.prependTranslation( -stageWidth /2.0 - offsetX, -stageHeight/2.0 - offsetY, focalLength); return out; } /** Creates a orthographic projection matrix suitable for 2D rendering. */ public static function createOrthographicProjectionMatrix( x:Number, y:Number, width:Number, height:Number, out:Matrix=null):Matrix { if (out == null) out = new Matrix(); out.setTo(2.0/width, 0, 0, -2.0/height, -(2*x + width) / width, (2*y + height) / height); return out; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy