손 추적 - MRTK2

손 추적 프로필

손 추적 프로필입력 시스템 프로필 아래에 있습니다. 여기에는 손 표현을 사용자 지정하기 위한 설정이 포함되어 있습니다.

손 추적 프로필

조인트 프리팹

조인트 프리팹은 간단한 프리팹을 사용하여 시각화됩니다. 손바닥검지 손가락 관절은 특별한 중요성과 자신의 프리팹을 가지고, 다른 모든 관절은 동일한 프리팹을 공유하는 동안.

기본적으로 손 관절 프리팹은 간단한 기하학적 기본 형식입니다. 원하는 경우 바꿀 수 있습니다. 프리팹을 전혀 지정하지 않으면 빈 GameObjects 가 대신 만들어집니다.

경고

조인트 개체는 모든 프레임에서 변환되고 성능 비용이 많이 들 수 있으므로 복잡한 스크립트를 사용하거나 공동 프리팹에서 비용이 많이 드는 렌더링을 사용하지 마세요.

기본 손 관절 표현 공동 레이블
관절 관절 입력 손 관절

손 메시 프리팹

손 메시는 손 추적 디바이스에서 완전히 정의된 메시 데이터를 제공하는 경우에 사용됩니다. 프리팹에서 렌더링 가능한 메시는 디바이스의 데이터로 대체되므로 큐브와 같은 더미 메시로 충분합니다. 프리팹의 재질은 손 메시에 사용됩니다.

입력 손 메시

손 메시 디스플레이는 성능에 큰 영향을 미칠 수 있으므로 손 메시 시각화 사용 옵션을 선택 취소하여 완전히 사용하지 않도록 설정할 수 있습니다.

손 시각화 설정

손 메시 및 손 관절 시각화는 각각 손 메시 시각화 모드 설정 및 손 관절 시각화 모드 를 통해 끄거나 끌 수 있습니다. 이러한 설정은 애플리케이션 모드에 따라 다릅니다. 즉, 편집기에서 일부 기능을 켜고(예: 편집기 내 시뮬레이션과의 조인트 보기) 디바이스에 배포할 때(플레이어 빌드에서) 동일한 기능을 해제할 수 있습니다.

일반적으로 편집기에서 손 관절 시각화를 켜고(편집기 내 시뮬레이션에서 손 관절이 있는 위치를 표시하도록) 플레이어에서 손 관절 시각화와 손 메시 시각화를 모두 해제하는 것이 좋습니다(성능이 저하되기 때문).

스크립팅

각 개별 손 관절에 대한 입력 시스템에서 위치 및 회전을 로 MixedRealityPose요청할 수 있습니다.

또는 시스템에서 관절을 따르는 GameObjects에 액세스할 수 있습니다. 이는 다른 GameObject가 연속적으로 조인트를 추적해야 하는 경우에 유용할 수 있습니다.

사용 가능한 조인트 열거형에 TrackedHandJoint 나열됩니다.

참고

손 추적이 손실되면 관절 개체가 파괴됩니다! 조인트 개체를 사용하는 모든 스크립트가 오류를 방지하기 위해 대/소문자를 null 정상적으로 처리해야 합니다.

지정된 손 컨트롤러에 액세스

입력 이벤트를 처리할 때와 같이 특정 손 컨트롤러를 자주 사용할 수 있습니다. 이 경우 인터페이스를 사용하여 IMixedRealityHand 디바이스에서 직접 공동 데이터를 요청할 수 있습니다.

컨트롤러에서 공동 포즈 폴링

TryGetJoint 어떤 이유로 요청된 조인트 를 사용할 수 없는 경우 함수는 를 반환 false 합니다. 이 경우 결과 포즈는 입니다 MixedRealityPose.ZeroIdentity.

public void OnSourceDetected(SourceStateEventData eventData)
{
  var hand = eventData.Controller as IMixedRealityHand;
  if (hand != null)
  {
    if (hand.TryGetJoint(TrackedHandJoint.IndexTip, out MixedRealityPose jointPose)
    {
      // ...
    }
  }
}

손 시각화 도우미에서 조인트 변환

컨트롤러 시각화 도우미에서 조인트 개체를 요청할 수 있습니다.

public void OnSourceDetected(SourceStateEventData eventData)
{
  var handVisualizer = eventData.Controller.Visualizer as IMixedRealityHandVisualizer;
  if (handVisualizer != null)
  {
    if (handVisualizer.TryGetJointTransform(TrackedHandJoint.IndexTip, out Transform jointTransform)
    {
      // ...
    }
  }
}

간소화된 공동 데이터 액세스

특정 컨트롤러가 제공되지 않으면 손 관절 데이터에 편리하게 액세스할 수 있도록 유틸리티 클래스가 제공됩니다. 이러한 함수는 현재 추적된 사용 가능한 첫 번째 손 디바이스에서 공동 데이터를 요청합니다.

HandJointUtils에서 공동 포즈 폴링

HandJointUtils 는 첫 번째 활성 손 디바이스를 쿼리하는 정적 클래스입니다.

if (HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexTip, Handedness.Right, out MixedRealityPose pose))
{
    // ...
}

손 조인트 서비스에서 조인트 변환

IMixedRealityHandJointService 는 관절 추적을 위해 GameObjects 의 영구 집합을 유지합니다.

var handJointService = CoreServices.GetInputSystemDataProvider<IMixedRealityHandJointService>();
if (handJointService != null)
{
    Transform jointTransform = handJointService.RequestJointTransform(TrackedHandJoint.IndexTip, Handedness.Right);
    // ...
}

손 추적 이벤트

컨트롤러에서 직접 데이터를 폴링하는 것이 바람직하지 않은 경우 입력 시스템도 이벤트를 제공합니다.

공동 이벤트

IMixedRealityHandJointHandler 는 조인트 위치의 업데이트를 처리합니다.

public class MyHandJointEventHandler : IMixedRealityHandJointHandler
{
    public Handedness myHandedness;

    void IMixedRealityHandJointHandler.OnHandJointsUpdated(InputEventData<IDictionary<TrackedHandJoint, MixedRealityPose>> eventData)
    {
        if (eventData.Handedness == myHandedness)
        {
            if (eventData.InputData.TryGetValue(TrackedHandJoint.IndexTip, out MixedRealityPose pose))
            {
                // ...
            }
        }
    }
}

메시 이벤트

IMixedRealityHandMeshHandler 는 관절형 손 메시의 변경 내용을 처리합니다.

손 메시는 기본적으로 사용하도록 설정되지 않습니다.

public class MyHandMeshEventHandler : IMixedRealityHandMeshHandler
{
    public Handedness myHandedness;
    public Mesh myMesh;

    public void OnHandMeshUpdated(InputEventData<HandMeshInfo> eventData)
    {
        if (eventData.Handedness == myHandedness)
        {
            myMesh.vertices = eventData.InputData.vertices;
            myMesh.normals = eventData.InputData.normals;
            myMesh.triangles = eventData.InputData.triangles;

            if (eventData.InputData.uvs != null && eventData.InputData.uvs.Length > 0)
            {
                myMesh.uv = eventData.InputData.uvs;
            }

            // ...
        }
    }
}

알려진 문제

.NET 네이티브

현재 .NET 백 엔드를 사용하는 마스터 빌드에 알려진 문제가 있습니다. .NET 네이티브 IInspectable 포인터는 를 사용하여 Marshal.GetObjectForIUnknown네이티브에서 관리 코드로 마샬링할 수 없습니다. MRTK는 이를 사용하여 플랫폼에서 손 및 눈 데이터를 수신하기 위해 를 가져옵니다 SpatialCoordinateSystem .

네이티브 Mixed Reality Toolkit 리포지토리에서 이 문제에 대한 해결 방법으로 DLL 원본을 제공했습니다. 추가 정보 지침에 따라 결과 이진 파일을 Unity 자산의 플러그 인 폴더에 복사하세요. 그런 다음 MRTK에 제공된 WindowsMixedRealityUtilities 스크립트가 해결 방법을 resolve.

고유한 DLL을 만들거나 기존 DLL에 이 해결 방법을 포함하려는 경우 해결 방법의 핵심은 다음과 같습니다.

extern "C" __declspec(dllexport) void __stdcall MarshalIInspectable(IUnknown* nativePtr, IUnknown** inspectable)
{
    *inspectable = nativePtr;
}

그리고 C# Unity 코드에서 다음을 사용합니다.

[DllImport("DotNetNativeWorkaround.dll", EntryPoint = "MarshalIInspectable")]
private static extern void GetSpatialCoordinateSystem(IntPtr nativePtr, out SpatialCoordinateSystem coordinateSystem);

private static SpatialCoordinateSystem GetSpatialCoordinateSystem(IntPtr nativePtr)
{
    try
    {
        GetSpatialCoordinateSystem(nativePtr, out SpatialCoordinateSystem coordinateSystem);
        return coordinateSystem;
    }
    catch
    {
        UnityEngine.Debug.LogError("Call to the DotNetNativeWorkaround plug-in failed. The plug-in is required for correct behavior when using .NET Native compilation");
        return Marshal.GetObjectForIUnknown(nativePtr) as SpatialCoordinateSystem;
    }
}