Отслеживание рук — MRTK2

Профиль отслеживания рук

Профиль отслеживания рук находится в профиле системы ввода. Он содержит параметры для настройки представления руки.

Профиль отслеживания рук

Совместные заготовки

Совместные заготовки визуализируются с помощью простых заготовок. Суставы ладони и указательного пальца имеют особое значение и имеют собственную заготовку, в то время как все остальные суставы имеют одну и ту же заготовку.

По умолчанию заготовки для суставов рук являются простыми геометрическими примитивами. При необходимости их можно заменить. Если заготовка не указана, вместо этого создаются пустые Объекты GameObject.

Предупреждение

Избегайте использования сложных скриптов или дорогостоящей отрисовки в совместных заготовках, так как совместные объекты преобразуются на каждом кадре и могут иметь значительные затраты на производительность!

Представление соединения руки по умолчанию Совместные метки
Шарнирные суставы рук Входные соединения рук

Ручная заготовка сетки

Сетка рук используется, если устройство отслеживания рук предоставляет полностью определенные данные сетки. Сетка, отрисовываемая в заготовке, заменяется данными с устройства, поэтому достаточно фиктивной сетки, такой как куб. Материал заготовки используется для ручной сетки.

Входная сетка рук

Отображение сетки рук может оказать заметное влияние на производительность. По этой причине его можно полностью отключить, сняв флажок Включить визуализацию сетки рук .

Параметры визуализации руки

Визуализации сетки рук и суставов рук можно отключить или включить с помощью параметра Режимы визуализации сетки рук и Режимы визуализации суставов рук соответственно. Эти параметры зависят от режима приложения. Это означает, что можно включить некоторые функции во время работы в редакторе (например, для просмотра соединений с имитацией в редакторе), при этом при развертывании на устройстве (в сборках проигрывателя) одни и те же функции отключены.

Обратите внимание, что обычно рекомендуется включить визуализацию суставов рук в редакторе (чтобы симуляция в редакторе показывала, где находятся суставы рук), а также отключить визуализацию суставов рук и визуализацию сетки рук в проигрывателе (так как они влечет за собой снижение производительности).

Написание сценариев

Положение и поворот можно запросить из системы ввода для каждого отдельного соединения рук в 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 сохраняет постоянный набор Объектов GameObject для отслеживания суставов.

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 Native

В настоящее время существует известная проблема с основными сборками, использующими серверную часть .NET. В .NET Native IInspectable указатели нельзя маршалировать из машинного кода в управляемый с помощью Marshal.GetObjectForIUnknown. MRTK использует его для получения SpatialCoordinateSystem для получения данных о руках и глазах с платформы.

Мы предоставили источник DLL в качестве решения этой проблемы в собственном репозитории Смешанная реальность Toolkit. Следуйте инструкциям в файле сведений и скопируйте полученные двоичные файлы в папку Plugins в ресурсах Unity. После этого сценарий WindowsMixedRealityUtilities, предоставленный в MRTK, решит обходной путь.

Если вы хотите создать собственную библиотеку 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;
    }
}