Mixed Reality interoperabilidade nativa no Unity

Cada Mixed Reality aplicação obtém um HolographicSpace antes de começar a receber dados da câmara e a compor frames. No Unity, o motor trata desses passos por si, ao processar objetos holográficos e atualizar internamente como parte do ciclo de composição.

No entanto, em cenários avançados, poderá ter de obter acesso aos objetos nativos subjacentes, como o HolographicCamera e o HolographicFrame atual.

WindowsMixedRealityUtilities

Espaço de Nomes:Microsoft.MixedReality.Toolkit.WindowsMixedReality
Type:WindowsMixedRealityUtilities

O MRTK fornece tipos já organizados no SDK WSA e XR legados através da classe WindowsMixedRealityUtilities .

public static HolographicFrame CurrentHolographicFrame { get; }
public static SpatialCoordinateSystem SpatialCoordinateSystem { get; }
public static SpatialInteractionManager SpatialInteractionManager { get; }

Desmarcagem de ponteiros nativos

Depois de obter o IntPtr de um dos métodos acima (não necessários para MRTK), utilize os seguintes fragmentos de código para os organizar para objetos geridos.

Se estiver a utilizar Microsoft.Windows.MixedReality.DotNetWinRT, pode construir um objeto gerido a partir de um ponteiro nativo com o FromNativePtr() método :

var worldOrigin = Microsoft.Windows.Perception.Spatial.SpatialCoordinateSystem.FromNativePtr(spatialCoordinateSystemPtr);

Caso contrário, utilize Marshal.GetObjectForIUnknown() e cast para o tipo que pretende:

#if ENABLE_WINMD_SUPPORT
var worldOrigin = Marshal.GetObjectForIUnknown(spatialCoordinateSystemPtr) as Windows.Perception.Spatial.SpatialCoordinateSystem;
#endif

Converter entre sistemas de coordenadas

O Unity utiliza um sistema de coordenadas canhoto, enquanto as APIs de Perceção do Windows utilizam sistemas de coordenadas destros. Para converter entre estas duas convenções, pode utilizar os seguintes programa auxiliares:

namespace NumericsConversion
{
    public static class NumericsConversionExtensions
    {
        public static UnityEngine.Vector3 ToUnity(this System.Numerics.Vector3 v) => new UnityEngine.Vector3(v.X, v.Y, -v.Z);
        public static UnityEngine.Quaternion ToUnity(this System.Numerics.Quaternion q) => new UnityEngine.Quaternion(q.X, q.Y, -q.Z, -q.W);
        public static UnityEngine.Matrix4x4 ToUnity(this System.Numerics.Matrix4x4 m) => new UnityEngine.Matrix4x4(
            new Vector4( m.M11,  m.M12, -m.M13,  m.M14),
            new Vector4( m.M21,  m.M22, -m.M23,  m.M24),
            new Vector4(-m.M31, -m.M32,  m.M33, -m.M34),
            new Vector4( m.M41,  m.M42, -m.M43,  m.M44));

        public static System.Numerics.Vector3 ToSystem(this UnityEngine.Vector3 v) => new System.Numerics.Vector3(v.x, v.y, -v.z);
        public static System.Numerics.Quaternion ToSystem(this UnityEngine.Quaternion q) => new System.Numerics.Quaternion(q.x, q.y, -q.z, -q.w);
        public static System.Numerics.Matrix4x4 ToSystem(this UnityEngine.Matrix4x4 m) => new System.Numerics.Matrix4x4(
            m.m00,  m.m10, -m.m20,  m.m30,
            m.m01,  m.m11, -m.m21,  m.m31,
           -m.m02, -m.m12,  m.m22, -m.m32,
            m.m03,  m.m13, -m.m23,  m.m33);
    }
}

Utilizar dados nativos do HolographicFrame

Nota

Alterar o estado dos objetos nativos recebidos através de HolographicFrameNativeData pode causar comportamentos imprevisíveis e composição de artefactos, especialmente se o Unity também tiver motivos para esse mesmo estado. Por exemplo, não deve chamar HolographicFrame.UpdateCurrentPrediction ou a predição de pose que o Unity compõe com essa moldura ficará dessincronizada com a pose esperada pelo Windows, o que reduzirá a estabilidade do holograma.

Se precisar de acesso a interfaces nativas para fins de composição ou depuração, utilize dados do HolographicFrameNativeData nos plug-ins nativos ou código C#.

Eis um exemplo de como pode utilizar HolographicFrameNativeData para obter a predição do fotograma atual para o tempo de fotões com as extensões do SDK XR.

using System;
using System.Runtime.InteropServices;

public static bool GetCurrentFrameDateTime(out DateTime frameDateTime)
{
#if ENABLE_WINMD_SUPPORT
    IntPtr holographicFramePtr = UnityEngine.XR.WindowsMR.WindowsMREnvironment.CurrentHolographicRenderFrame;

    if (holographicFramePtr != IntPtr.Zero)
    {
        var holographicFrame = Marshal.GetObjectForIUnknown(holographicFramePtr) as Windows.Graphics.Holographic.HolographicFrame;
        frameDateTime = holographicFrame.CurrentPrediction.Timestamp.TargetTime.DateTime;
        return true;
    }
#endif

    frameDateTime = DateTime.MinValue;
    return false;
}

Consulte também