Skip to content

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

@niguiecandy

Description

@niguiecandy

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions