public Matrix4f setPerspectiveOffCenter(float fovy, float offAngleX, float offAngleY,
                                            float aspect, float zNear, float zFar, boolean zZeroToOne) {
        MemUtil.INSTANCE.zero(this);
        float h = (float) Math.tan(fovy * 0.5f);
        float xScale = 1.0f / (h * aspect), yScale = 1.0f / h;
        this._m00(xScale);
        this._m11(yScale);
        float offX = (float) Math.tan(offAngleX), offY = (float) Math.tan(offAngleY);
        this._m20(offX * xScale);
        this._m21(offY * yScale);
        boolean farInf = zFar > 0 && Float.isInfinite(zFar);
        boolean nearInf = zNear > 0 && Float.isInfinite(zNear);
        if (farInf) {
            // See: "Infinite Projection Matrix" (http://www.terathon.com/gdc07_lengyel.pdf)
            float e = 1E-6f;
            this._m22(e - 1.0f);
            this._m32((e - (zZeroToOne ? 1.0f : 2.0f)) * zNear);
        } else if (nearInf) {
            float e = 1E-6f;
            this._m22((zZeroToOne ? 0.0f : 1.0f) - e);
            this._m32(((zZeroToOne ? 1.0f : 2.0f) - e) * zFar);
        } else {
            this._m22((zZeroToOne ? zFar : zFar + zNear) / (zNear - zFar));
            this._m32((zZeroToOne ? zFar : zFar + zFar) * zNear / (zNear - zFar));
        }
        this._m23(-1.0f);
        _properties(offAngleX == 0.0f && offAngleY == 0.0f ? PROPERTY_PERSPECTIVE : 0);
        return this;
    }
public Matrix4f setPerspectiveOffCenter ( float fovy , float offAngleX , float offAngleY , float aspect , float zNear , float zFar , boolean zZeroToOne ) { MemUtil . INSTANCE . zero ( this ) ; float h = ( float ) Math . tan ( fovy * 0.5f ) ; float xScale = 1.0f / ( h * aspect ) , yScale = 1.0f / h ; this . _m00 ( xScale ) ; this . _m11 ( yScale ) ; float offX = ( float ) Math . tan ( offAngleX ) , offY = ( float ) Math . tan ( offAngleY ) ; this . _m20 ( offX * xScale ) ; this . _m21 ( offY * yScale ) ; boolean farInf = zFar > 0 && Float . isInfinite ( zFar ) ; boolean nearInf = zNear > 0 && Float . isInfinite ( zNear ) ; if ( farInf ) { float e = 1E-6f ; this . _m22 ( e - 1.0f ) ; this . _m32 ( ( e - ( zZeroToOne ? 1.0f : 2.0f ) ) * zNear ) ; } else if ( nearInf ) { float e = 1E-6f ; this . _m22 ( ( zZeroToOne ? 0.0f : 1.0f ) - e ) ; this . _m32 ( ( ( zZeroToOne ? 1.0f : 2.0f ) - e ) * zFar ) ; } else { this . _m22 ( ( zZeroToOne ? zFar : zFar + zNear ) / ( zNear - zFar ) ) ; this . _m32 ( ( zZeroToOne ? zFar : zFar + zFar ) * zNear / ( zNear - zFar ) ) ; } this . _m23 ( - 1.0f ) ; _properties ( offAngleX == 0.0f && offAngleY == 0.0f ? PROPERTY_PERSPECTIVE : 0 ) ; return this ; }
Set this matrix to be an asymmetric off-center perspective projection frustum transformation for a right-handed
coordinate system using the given NDC z range.
<p>
The given angles <code>offAngleX</code> and <code>offAngleY</code> are the horizontal and vertical angles between
the line of sight and the line given by the center of the near and far frustum planes. So, when <code>offAngleY</code>
is just <code>fovy/2</code> then the projection frustum is rotated towards +Y and the bottom frustum plane
is parallel to the XZ-plane.
<p>
In order to apply the perspective projection transformation to an existing transformation,
use {@link #perspectiveOffCenter(float, float, float, float, float, float) perspectiveOffCenter()}.

@see #perspectiveOffCenter(float, float, float, float, float, float)

@param fovy
the vertical field of view in radians (must be greater than zero and less than {@link Math#PI PI})
@param offAngleX
the horizontal angle between the line of sight and the line crossing the center of the near and far frustum planes
@param offAngleY
the vertical angle between the line of sight and the line crossing the center of the near and far frustum planes
@param aspect
the aspect ratio (i.e. width / height; must be greater than zero)
@param zNear
near clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the near clipping plane will be at positive infinity.
In that case, <code>zFar</code> may not also be {@link Float#POSITIVE_INFINITY}.
@param zFar
far clipping plane distance. If the special value {@link Float#POSITIVE_INFINITY} is used, the far clipping plane will be at positive infinity.
In that case, <code>zNear</code> may not also be {@link Float#POSITIVE_INFINITY}.
@param zZeroToOne
whether to use Vulkan's and Direct3D's NDC z range of <code>[0..+1]</code> when <code>true</code>
or whether to use OpenGL's NDC z range of <code>[-1..+1]</code> when <code>false</code>
@return this