Search code examples
actionscript-3matrixrotationscalestage3d

Rotation without distortion using Matrix3D


How to assign a value to Matrix3D rotation about the axis Z. (li "rotation")?

The position and size are calculated correctly, but after the addition of rotation, the image is stretched.

I tried two method to rotation:

_positionMatrix.identity();
var v3:Vector.<Vector3D> = new Vector.<Vector3D>(3);
v3 = _positionMatrix.decompose();
v3[0].incrementBy(new Vector3D( x, y, 0 ));// x, y, z
v3[1].incrementBy(new Vector3D(0,0,-rotation*Math.PI/180)); // rotationX, rotationY, rotationZ
v3[2].incrementBy(new Vector3D(width,height,0)); // scaleX, scaleY, scaleZ
_positionMatrix.recompose(v3);

And:

_positionMatrix.identity();
_positionMatrix.appendScale(width,height,1);
_positionMatrix.appendTranslation(x,y,0);
_positionMatrix.appendRotation(-rotation,Vector3D.Z_AXIS );

But the effect is identical:

enter image description here

I find that "PerspectiveProjection" class can help, but cant to understand how to use it with rotation about the axis Z.


Solution

  • Thanks, its true, my perspective Projection matrix was "bad". This code works perfectly:

        private var _vertexData:Vector.<Number> = new <Number>[
            0,0,0, 0, 0, 0, 1,// x, y, z, r, g, b,a
            1, 0, 0, 0, 0, 0, 1,
            1, 1, 0, 0, 0, 0, 1,
            0, 1, 0,0, 0, 0,1
        ];
    
    
    
        var perspectiveProjectionMatrix:Matrix3D = new Matrix3D();
        var scaleX:Number = 2.0 / _stage.stageWidth;  // 2.0 / 500
        var scaleY:Number = -2.0 / _stage.stageHeight; // -2.0 / 375
        perspectiveProjectionMatrix.copyRawDataFrom(
                new <Number>[
                    scaleX, 0.0, 0.0, 0.0,
                    0.0, scaleY, 0.0, 0.0,
                    0.0, 0.0, -1.0, 0.0,
                    -1.0, 1.0, 0.0, 1.0
                ]
        );
        var modelViewMatrix:Matrix3D = trs(stage.stageWidth/2,stage.stageHeight/2, _rotation*Math.PI/180, _width*_globalScaleX, _height*_globalScaleY );
        var resultMatrix:Matrix3D = new Matrix3D();
        resultMatrix.prepend(perspectiveProjectionMatrix);
        resultMatrix.prepend(modelViewMatrix);
        _context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0,resultMatrix , true);
    

    Where "trs" is:

    public function trs( tx:Number, ty:Number, rotation:Number, xScale:Number, yScale:Number ):Matrix3D {
    
    var data:Vector.<Number> = new <Number>[1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1];
    
    var sin:Number = Math.sin( rotation );
    var cos:Number = Math.cos( rotation );
    data[0] =  cos * xScale;
    data[1] =  sin * xScale;
    data[4] = -sin * yScale;
    data[5] =  cos * yScale;
    data[12] = tx;
    data[13] = ty;
    
    
    var matrix:Matrix3D = new Matrix3D();
    matrix.copyRawDataFrom(data);
    return matrix;
    
    }