Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

float4x4.PerspectiveOffCenter(): possible logic flaw? #247

Open
niguiecandy opened this issue Mar 13, 2024 · 0 comments
Open

float4x4.PerspectiveOffCenter(): possible logic flaw? #247

niguiecandy opened this issue Mar 13, 2024 · 0 comments

Comments

@niguiecandy
Copy link

niguiecandy commented Mar 13, 2024

The Unity.Mathematics implementation of PerspectiveOffCenter() Link

public static float4x4 PerspectiveOffCenter(float left, float right, float bottom, float top, float near, float far)
{
    float rcpdz = 1.0f / (near - far);
    float rcpWidth = 1.0f / (right - left);
    float rcpHeight = 1.0f / (top - bottom);

    return float4x4(
        2.0f * near * rcpWidth,     0.0f,                       (left + right) * rcpWidth,     0.0f,
        0.0f,                       2.0f * near * rcpHeight,    (bottom + top) * rcpHeight,    0.0f,
        0.0f,                       0.0f,                        **(far + near) * rcpdz**,          **2.0f * near * far * rcpdz**,
        0.0f,                       0.0f,                       -1.0f,                          0.0f
        );
}

differs from the .NET System.Numerics.Matrix4x4 implementation:

public static Matrix4x4 CreatePerspectiveOffCenter(float left, float right, float bottom, float top, float nearPlaneDistance, float farPlaneDistance)
{
    if (nearPlaneDistance <= 0.0f)
        throw new ArgumentOutOfRangeException("nearPlaneDistance");

    if (farPlaneDistance <= 0.0f)
        throw new ArgumentOutOfRangeException("farPlaneDistance");

    if (nearPlaneDistance >= farPlaneDistance)
        throw new ArgumentOutOfRangeException("nearPlaneDistance");

    Matrix4x4 result;

    result.M11 = 2.0f * nearPlaneDistance / (right - left);
    result.M12 = result.M13 = result.M14 = 0.0f;

    result.M22 = 2.0f * nearPlaneDistance / (top - bottom);
    result.M21 = result.M23 = result.M24 = 0.0f;

    result.M31 = (left + right) / (right - left);
    result.M32 = (top + bottom) / (top - bottom);
    // below is different
    **result.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);**
    result.M34 = -1.0f;
    // below is different
    **result.M43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);**
    result.M41 = result.M42 = result.M44 = 0.0f;

    return result;
}

In Unity M33 is:
(far + near) * rcpdz
while System M33 is:
result.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);

In Unity M34 is:
2.0f * near * far * rcpdz
while System M43 is:
result.M43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);

Note that both matrices are transposed to each other; System Matrix can be thought of as rotating the coordinate system itself while Unity Matrix rotates the given vector.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant