Unity의 Mixed Reality 네이티브 interop

모든 Mixed Reality 앱은 카메라 데이터 수신 및 프레임 렌더링을 시작하기 전에 HolographicSpace를 가져옵니다. Unity에서 엔진은 Holographic 개체를 처리하고 내부적으로 렌더링 루프의 일부로 업데이트하여 이러한 단계를 처리합니다.

그러나 고급 시나리오에서는 HolographicCamera 및 현재 HolographicFrame과 같은 기본 네이티브 개체에 액세스해야 할 수 있습니다.

WindowsMixedRealityUtilities

네임스페이스:Microsoft.MixedReality.Toolkit.WindowsMixedReality
형식:WindowsMixedRealityUtilities

MRTK는 WindowsMixedRealityUtilities 클래스를 통해 레거시 WSA 및 XR SDK 모두에서 이미 마샬링된 형식을 제공합니다.

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

네이티브 포인터 구분 해제

위의 메서드 중 하나에서 를 가져온 IntPtr 후(MRTK에 필요하지 않음) 다음 코드 조각을 사용하여 관리되는 개체로 마샬링합니다.

Microsoft.Windows.MixedReality.DotNetWinRT를 사용하는 경우 메서드를 사용하여 네이티브 포인터에서 관리되는 개체를 생성할 FromNativePtr() 수 있습니다.

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

그렇지 않으면 를 사용하고 Marshal.GetObjectForIUnknown() 원하는 형식으로 캐스팅합니다.

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

좌표계 간 변환

Unity는 왼손 좌표계를 사용하고 Windows Perception API는 오른손 좌표계를 사용합니다. 이러한 두 규칙 간에 변환하려면 다음 도우미를 사용할 수 있습니다.

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);
    }
}

HolographicFrame 네이티브 데이터 사용

참고

HolographicFrameNativeData를 통해 수신된 네이티브 개체의 상태를 변경하면 예측할 수 없는 동작과 렌더링 아티팩트가 발생할 수 있습니다. 특히 Unity가 동일한 상태에 대한 이유도 있습니다. 예를 들어 HolographicFrame.UpdateCurrentPrediction을 호출해서는 안 되며, 그렇지 않으면 Unity가 해당 프레임으로 렌더링하는 포즈 예측이 Windows에서 기대하는 포즈와 동기화되지 않아 홀로그램 안정성이 감소합니다.

렌더링 또는 디버깅을 위해 네이티브 인터페이스에 액세스해야 하는 경우 네이티브 플러그 인 또는 C# 코드에서 HolographicFrameNativeData의 데이터를 사용합니다.

다음은 HolographicFrameNativeData를 사용하여 XR SDK 확장을 사용하여 현재 프레임의 광자 시간 예측을 가져오는 방법의 예입니다.

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;
}

참고 항목