HateDread
Topic Author
Posts: 74
Joined: 06 Feb 2020, 10:27

Any recommendations for custom engine + world-space UI?

02 Jul 2023, 09:35

Hi,

I've seen the world space UI features, which look great. Are there any recommendations, samples, guides, etc, for achieving that with a custom engine integration?

Example I saw in another title that made me want to try in-world UI with Noesis - the names/text here, aligned with ships and somewhat flat against the world plane.
FallingFrontier_TextInWorld.png
Thanks
 
User avatar
jsantos
Site Admin
Posts: 4822
Joined: 20 Jan 2012, 17:18
Contact:

Re: Any recommendations for custom engine + world-space UI?

03 Jul 2023, 14:13

We have this Oculus example, but unfortunately it is a bit outdated.

The most complicated step in world-space UI is syncing the projection matrix used by your custom engine with the one needed by Noesis (IView)
    /// Sets the projection matrix that transforms the coordinates of each primitive to a
    /// non-normalized homogeneous space where (0, 0) is at the lower-left corner and
    /// (width, height) is at the upper-right corner after projection.
    /// The following table compares the clip space used by OpenGL and D3D in comparison.
    /// ========= =========== ============ =========
    /// System    X Range     Y Range      Z Range
    /// ========= =========== ============ =========
    /// OpenGL    [-1...+1]   [-1...+1]    [-1...+1]
    /// Direct3D  [-1...+1]   [-1...+1]    [0...1]
    /// NoesisGUI [0...width] [0...height] [0...1]
    /// ========= =========== ============ =========
    virtual void SetProjectionMatrix(const Matrix4& projection) = 0;
If this helps, this is how we are converting from Unity camera to Noesis
    private static Noesis.Matrix4 NoesisMatrix(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, float w, float h)
    {
        float hw = 0.5f * w;
        float hh = 0.5f * h;

        Matrix4x4 noesisMatrix;

        if (SystemInfo.usesReversedZBuffer)
        {
            noesisMatrix = new Matrix4x4
            (
                new UnityEngine.Vector4(hw,  0,  0,    0),
                new UnityEngine.Vector4(0, -hh,  0,    0),
                new UnityEngine.Vector4(0,   0, -0.5f, 0),
                new UnityEngine.Vector4(hw, hh,  0.5f, 1)
            );
        }
        else
        {
            noesisMatrix = new Matrix4x4
            (
                new UnityEngine.Vector4(hw,  0, 0,    0),
                new UnityEngine.Vector4(0, -hh, 0,    0),
                new UnityEngine.Vector4(0,   0, 0.5f, 0),
                new UnityEngine.Vector4(hw, hh, 0.5f, 1)
            );
        }

        Matrix4x4 _ = noesisMatrix * projectionMatrix * viewMatrix;

        return new Matrix4
        (
            _.m00, _.m10, _.m20, _.m30,
            _.m01, _.m11, _.m21, _.m31,
            _.m02, _.m12, _.m22, _.m32,
            _.m03, _.m13, _.m23, _.m33
        );
    }
 
HateDread
Topic Author
Posts: 74
Joined: 06 Feb 2020, 10:27

Re: Any recommendations for custom engine + world-space UI?

05 Jul 2023, 10:55

Thanks for the info! With that projection matrix, does setting that move all GUI elements into world space or does the Noesis API have a concept of screen vs world space? How about on the XAML side, does it know (or need to know) about this? Just not seeing how screen and world space elements all fit together in Noesis and the xaml.
We have this Oculus example, but unfortunately it is a bit outdated.

The most complicated step in world-space UI is syncing the projection matrix used by your custom engine with the one needed by Noesis (IView)
    /// Sets the projection matrix that transforms the coordinates of each primitive to a
    /// non-normalized homogeneous space where (0, 0) is at the lower-left corner and
    /// (width, height) is at the upper-right corner after projection.
    /// The following table compares the clip space used by OpenGL and D3D in comparison.
    /// ========= =========== ============ =========
    /// System    X Range     Y Range      Z Range
    /// ========= =========== ============ =========
    /// OpenGL    [-1...+1]   [-1...+1]    [-1...+1]
    /// Direct3D  [-1...+1]   [-1...+1]    [0...1]
    /// NoesisGUI [0...width] [0...height] [0...1]
    /// ========= =========== ============ =========
    virtual void SetProjectionMatrix(const Matrix4& projection) = 0;
If this helps, this is how we are converting from Unity camera to Noesis
    private static Noesis.Matrix4 NoesisMatrix(Matrix4x4 viewMatrix, Matrix4x4 projectionMatrix, float w, float h)
    {
        float hw = 0.5f * w;
        float hh = 0.5f * h;

        Matrix4x4 noesisMatrix;

        if (SystemInfo.usesReversedZBuffer)
        {
            noesisMatrix = new Matrix4x4
            (
                new UnityEngine.Vector4(hw,  0,  0,    0),
                new UnityEngine.Vector4(0, -hh,  0,    0),
                new UnityEngine.Vector4(0,   0, -0.5f, 0),
                new UnityEngine.Vector4(hw, hh,  0.5f, 1)
            );
        }
        else
        {
            noesisMatrix = new Matrix4x4
            (
                new UnityEngine.Vector4(hw,  0, 0,    0),
                new UnityEngine.Vector4(0, -hh, 0,    0),
                new UnityEngine.Vector4(0,   0, 0.5f, 0),
                new UnityEngine.Vector4(hw, hh, 0.5f, 1)
            );
        }

        Matrix4x4 _ = noesisMatrix * projectionMatrix * viewMatrix;

        return new Matrix4
        (
            _.m00, _.m10, _.m20, _.m30,
            _.m01, _.m11, _.m21, _.m31,
            _.m02, _.m12, _.m22, _.m32,
            _.m03, _.m13, _.m23, _.m33
        );
    }
 
User avatar
jsantos
Site Admin
Posts: 4822
Joined: 20 Jan 2012, 17:18
Contact:

Re: Any recommendations for custom engine + world-space UI?

06 Jul 2023, 11:45

Thanks for the info! With that projection matrix, does setting that move all GUI elements into world space or does the Noesis API have a concept of screen vs world space? How about on the XAML side, does it know (or need to know) about this? Just not seeing how screen and world space elements all fit together in Noesis and the xaml.
The projection matrix changes the camera position and perspective of the view. So all elements are affected by this, converting effectively the View to world space. There is no concept of screen vs world space in the XAML. For each element, there is a transformation that is used when rendering. This transformation takes into account the local transform of the element plus the transformation of the parent. If there is a projection matrix set (by default it is the identity) it is also appended to the element transformation.

This 3D Transforms tutorial may help.

Who is online

Users browsing this forum: No registered users and 6 guests