用于在视口和变换后的矩形之间变换坐标的矩阵

Matrix to transform coordinates between viewport and transformed rectangle

我正在尝试编写一个矩阵,在屏幕上已转换矩形的局部坐标和视口坐标之间进行转换。

如下图所示:

到目前为止,我有以下代码,它适用于平移和缩放,并且似乎在正确的方向上旋转。

但是在应用旋转时似乎存在某种形式的倾斜:

public Matrix4x4 LocalToViewportMatrix
{
    get
    {
        Vector2 translation = viewportPosition;
        float rotation = this.rotation;
        Vector2 scale = viewportSize;
        Vector2 centering = -(new Vector2(0.5f, 0.5f));
        
        Matrix4x4 T = Matrix4x4.Translate(translation.WithZ(0));
        Matrix4x4 R = Matrix4x4.Rotate(Quaternion.Euler(0, 0, rotation));
        Matrix4x4 S = Matrix4x4.Scale(scale.WithZ(1));
        Matrix4x4 t = Matrix4x4.Translate(centering.WithZ(0));

        return T * R * S * t;
    }
}

我很确定这与我的操作顺序有关,但我尝试了很多东西,但无法弄清楚。

我设法通过为视口使用绝对像素坐标而不是相对 [0, 1] 范围来解决我的问题。我不确定如何解释它,但我认为坐标系在两个轴上的长度不同这一事实导致了倾斜。

public Matrix4x4 LocalToScreenMatrix
{
    get
    {
        var ScreenSize = new Vector2(Screen.width, Screen.height);
        var screenPosition = viewportPosition * ScreenSize;
        var screenSize = viewportSize * ScreenSize;

        var translation = screenPosition;
        var rotation = this.rotation;
        var scale = screenSize;
        var centering = -new Vector2(0.5f, 0.5f);

        var T = Matrix4x4.Translate(translation.WithZ(0));
        var R = Matrix4x4.Rotate(Quaternion.Euler(0, 0, rotation));
        var S = Matrix4x4.Scale(scale.WithZ(1));
        var t = Matrix4x4.Translate(centering.WithZ(0));

        return T * R * S * t;
    }
}