Compartilhar via


Interoperabilidade nativa da Realidade Misturada no Unity

Cada aplicativo de Realidade Misturada obtém um HolographicSpace antes de começar a receber dados da câmera e renderizar quadros. No Unity, o mecanismo cuida dessas etapas para você, manipulando objetos holográficos e atualizando internamente como parte de seu loop de renderização.

No entanto, em cenários avançados, talvez seja necessário obter acesso aos objetos nativos subjacentes, como o HolographicCamera e o HolographicFrame atual.

WindowsMixedRealityUtilities

Namespace: Microsoft.MixedReality.Toolkit.WindowsMixedReality
Tipo: WindowsMixedRealityUtilities

O MRTK fornece tipos já empacotados no WSA herdado e no SDK do XR por meio da classe WindowsMixedRealityUtilities .

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

Desempacotando ponteiros nativos

Depois de obter o IntPtr from de um dos métodos acima (não necessário para o MRTK), use os snippets de código a seguir para empacotá-los em objetos gerenciados.

Se você estiver usando Microsoft.Windows.MixedReality.DotNetWinRT, poderá construir um objeto gerenciado a partir de um ponteiro nativo usando o FromNativePtr() método:

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

Caso contrário, use Marshal.GetObjectForIUnknown() e converta para o tipo desejado:

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

Conversão entre sistemas de coordenadas

O Unity usa um sistema de coordenadas para canhotos, enquanto as APIs do Windows Perception usam sistemas de coordenadas para destros. Para converter entre essas duas convenções, você pode usar os seguintes 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);
    }
}

Usando dados nativos do HolographicFrame

Observação

Alterar o estado dos objetos nativos recebidos por meio de HolographicFrameNativeData pode causar comportamento imprevisível e artefatos de renderização, especialmente se o Unity também raciocinar sobre esse mesmo estado. Por exemplo, você não deve chamar HolographicFrame.UpdateCurrentPrediction, caso contrário, a previsão de pose que o Unity renderiza com esse quadro estará fora de sincronia com a pose que o Windows está esperando, o que reduzirá a estabilidade do holograma.

Se você precisar de acesso a interfaces nativas para fins de renderização ou depuração, use dados de HolographicFrameNativeData em seus plug-ins nativos ou código C#.

Aqui está um exemplo de como você pode usar HolographicFrameNativeData para obter a previsão do quadro atual para o tempo de fóton usando as extensões do SDK do 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;
}

Confira também