손 추적 - 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;
}
}