Controladores, punteros y foco: MRTK2

Los controladores, los punteros y el foco son conceptos de nivel superior que se basan en la base establecida por el sistema de entrada principal. Juntos, proporcionan una gran parte del mecanismo para interactuar con objetos de la escena.

Controladores

Los controladores son representaciones de un controlador físico (6 grados de libertad, mano articulada, etc.). Los administradores de dispositivos crean y son responsables de comunicarse con el sistema subyacente correspondiente y traducir esos datos en eventos y datos en forma de MRTK.

Por ejemplo, en la plataforma Windows Mixed Reality, WindowsMixedRealityArticulatedHand es un controlador responsable de interactuar con las API de seguimiento de manos subyacentes Windows para obtener información sobre las articulaciones, la posición y otras propiedades de la mano. Es responsable de convertir estos datos en eventos MRTK pertinentes (por ejemplo, llamando a RaisePoseInputChanged o RaiseHandJointsUpdated) y actualizando su propio estado interno para que las consultas TryGetJointPose de devuelvan datos correctos.

Por lo general, el ciclo de vida de un controlador implicará lo siguiente:

  1. Un controlador se crea mediante un administrador de dispositivos tras la detección de un nuevo origen (por ejemplo, el administrador de dispositivos detecta e inicia el seguimiento de una mano).

  2. En el bucle Update() del controlador, llama a su sistema de API subyacente.

  3. En el mismo bucle de actualización, genera cambios de evento de entrada llamando directamente al propio sistema de entrada principal (por ejemplo, generando HandMeshUpdated o HandJointsUpdated).

Punteros y foco

Los punteros se usan para interactuar con objetos de juego. En esta sección se describe cómo se crean los punteros, cómo se actualizan y cómo determinan los objetos que están en el foco. También tratará los diferentes tipos de punteros que existen y los escenarios en los que están activos.

Categorías de puntero

Los punteros generalmente se dividen en una de las siguientes categorías:

  • Punteros lejanos

    Estos tipos de punteros se usan para interactuar con objetos que están lejos del usuario (lejos se define simplemente como "no cerca"). Estos tipos de punteros suelen convertir líneas que pueden ir lejos del mundo y permitir que el usuario interactúe y manipule objetos que no están inmediatamente junto a ellos.

  • Punteros cercanos

    Estos tipos de punteros se usan para interactuar con objetos que están lo suficientemente cerca del usuario para agarrar, tocar y manipular. Por lo general, estos tipos de punteros interactúan con objetos buscando objetos en las proximidades cercanas (ya sea haciendo raycasting a pequeñas distancias, haciendo la conversión esférica buscando objetos en las proximidades o enumerando listas de objetos que se consideran agarrables o táctiles).

  • Punteros de teletransporte

    Estos tipos de punteros se conectan al sistema de teletransportación para controlar el movimiento del usuario a la ubicación de destino del puntero.

Mediación de punteros

Dado que un único controlador puede tener varios punteros (por ejemplo, la mano articulada puede tener punteros de interacción cercanos y lejanos), existe un componente responsable de mediar qué puntero debe estar activo.

Por ejemplo, a medida que la mano del usuario se aproxima a un botón presionable, ShellHandRayPointer debe dejar de mostrarse y debe PokePointer estar activa.

Esto se controla mediante , DefaultPointerMediatorque es responsable de determinar qué punteros están activos, en función del estado de todos los punteros. Una de las principales cosas que esto hace es deshabilitar punteros lejanos cuando un puntero cercano está cerca de un objeto (consulte DefaultPointerMediator).

Es posible proporcionar una implementación alternativa del mediador de puntero cambiando la PointerMediator propiedad en el perfil de puntero.

Cómo deshabilitar punteros

Dado que el mediador del puntero ejecuta cada fotograma, termina controlando el estado activo o inactivo de todos los punteros. Por lo tanto, si establece la propiedad IsInteractionEnabled de un puntero en el código, el mediador de puntero sobrescribirá cada fotograma. En su lugar, puede especificar para PointerBehavior controlar si los punteros deben estar activados o desactivados usted mismo. Tenga en cuenta que esto solo funcionará si usa el valor predeterminado FocusProvider y DefaultPointerMediator en MRTK.

Ejemplo: Deshabilitar rayos de mano en MRTK

El código siguiente desactivará los rayos de mano en MRTK:

// Turn off all hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);

// Turn off hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);

El código siguiente devolverá los rayos de mano a su comportamiento predeterminado en MRTK:

PointerUtils.SetHandRayPointerBehavior(PointerBehavior.Default);

El código siguiente forzará que los rayos de mano estén encendidos, independientemente de si están cerca de un agarrable:

// Turn off all hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOn);

Consulte PointerUtils y TurnPointersOnOff para obtener más ejemplos.

FocusProvider

FocusProvider es elhora que es responsable de iterar en la lista de todos los punteros y averiguar cuál es el objeto centrado para cada puntero.

En cada Update() llamada, esto hará lo siguiente:

  1. Actualice todos los punteros, mediante raycasting y la detección de posicionamientos configuradas por el propio puntero (por ejemplo, el puntero de esfera podría especificar sphereOverlap raycastMode, por lo que FocusProvider realizará una colisión basada en esferas).

  2. Actualice el objeto centrado por puntero (es decir, si un objeto obtuvo el foco, también desencadenaría eventos en ese objeto, si un objeto perdiera el foco, desencadenaría la pérdida de foco, etc.).

Configuración y ciclo de vida del puntero

Los punteros se pueden configurar en la sección Punteros del perfil del sistema de entrada.

La duración de un puntero suele ser la siguiente:

  1. Un administrador de dispositivos detectará la presencia de un controlador. A continuación, este administrador de dispositivos creará el conjunto de punteros asociados al controlador a través de una llamada a RequestPointers.

  2. El FocusProvider, en su bucle Update(), iterará en todos los punteros válidos y realizará la lógica de detección de llamadas o raycast asociada. Se usa para determinar el objeto que se centra en cada puntero determinado.

    • Dado que es posible tener varios orígenes de entrada activos al mismo tiempo (por ejemplo, dos manos activas presentes), también es posible tener varios objetos que tengan el foco al mismo tiempo.
  3. El administrador de dispositivos, al detectar que se perdió un origen del controlador, anulará los punteros asociados al controlador perdido.