Seguimiento de manos: MRTK2
Perfil de seguimiento de manos
El perfil seguimiento de manos se encuentra en el perfil sistema de entrada. Contiene la configuración para personalizar la representación manual.
Objetos prefabricados conjuntos
Los objetos prefabricados conjuntos se visualizan mediante objetos prefabricados simples. Las articulaciones Palm e Index Finger son de importancia especial y tienen su propio objeto prefabricado, mientras que todas las demás articulaciones comparten el mismo objeto prefabricado.
De forma predeterminada, los objetos prefabricados de la articulación de mano son primitivos geométricos simples. Se pueden reemplazar si lo desea. Si no se especifica ningún objeto prefabricado, se crean gameObjects vacíos en su lugar.
Advertencia
Evite el uso de scripts complejos o una representación costosa en objetos prefabricados conjuntos, ya que los objetos conjuntos se transforman en cada fotograma y pueden tener un costo de rendimiento significativo.
Representación de articulación manual predeterminada | Etiquetas conjuntas |
---|---|
Objeto prefabricado de malla de mano
La malla de mano se usa si el dispositivo de seguimiento de manos proporciona datos de malla totalmente definidos. La malla que se puede representar en el objeto prefabricado se reemplaza por datos del dispositivo, por lo que una malla ficticía, como un cubo, es suficiente. El material del objeto prefabricado se utiliza para la malla de mano.
La visualización de malla de mano puede tener un impacto notable en el rendimiento, por este motivo se puede deshabilitar completamente desactivando la opción Habilitar visualización de malla de mano .
Configuración de visualización manual
La malla de mano y las visualizaciones de articulaciones de mano se pueden desactivar o activar a través de la configuración De modos de visualización de malla de mano y Modos de visualización de articulación de mano respectivamente. Esta configuración es específica del modo de aplicación, lo que significa que es posible activar algunas características mientras está en el editor (para ver las articulaciones con la simulación en el editor, por ejemplo) mientras se desactivan las mismas características cuando se implementan en el dispositivo (en compilaciones del reproductor).
Tenga en cuenta que, por lo general, se recomienda que la visualización de las articulaciones de mano esté activada en el editor (para que la simulación en el editor muestre dónde se encuentran las articulaciones de la mano) y para que la visualización de la articulación de la mano y la visualización de malla de mano se desactiven en el reproductor (porque incurren en un impacto en el rendimiento).
Scripting
La posición y la rotación se pueden solicitar desde el sistema de entrada para cada articulación de mano individual como .MixedRealityPose
Como alternativa, el sistema permite el acceso a GameObjects que siguen las articulaciones. Esto puede ser útil si otro GameObject debe realizar un seguimiento continuo de una articulación.
Las articulaciones disponibles se enumeran en la TrackedHandJoint
enumeración.
Nota
¡El objeto conjunto se destruye cuando se pierde el seguimiento de la mano! Asegúrese de que los scripts que usan el objeto conjunto controlan el null
caso correctamente para evitar errores.
Acceso a un controlador de mano determinado
Un controlador de mano específico suele estar disponible, por ejemplo, al controlar eventos de entrada. En este caso, los datos conjuntos se pueden solicitar directamente desde el dispositivo, mediante la IMixedRealityHand
interfaz .
Posición de la articulación de sondeo del controlador
La TryGetJoint
función devuelve false
si la articulación solicitada no está disponible por algún motivo. En ese caso, la posición resultante será MixedRealityPose.ZeroIdentity
.
public void OnSourceDetected(SourceStateEventData eventData)
{
var hand = eventData.Controller as IMixedRealityHand;
if (hand != null)
{
if (hand.TryGetJoint(TrackedHandJoint.IndexTip, out MixedRealityPose jointPose)
{
// ...
}
}
}
Transformación conjunta del visualizador de manos
Los objetos conjuntos se pueden solicitar desde el visualizador del controlador.
public void OnSourceDetected(SourceStateEventData eventData)
{
var handVisualizer = eventData.Controller.Visualizer as IMixedRealityHandVisualizer;
if (handVisualizer != null)
{
if (handVisualizer.TryGetJointTransform(TrackedHandJoint.IndexTip, out Transform jointTransform)
{
// ...
}
}
}
Acceso simplificado a datos conjuntos
Si no se proporciona ningún controlador específico, se proporcionan clases de utilidad para un acceso cómodo a los datos de las articulaciones de mano. Estas funciones solicitan datos conjuntos del primer dispositivo disponible que se está realizando actualmente.
Posición de articulación de sondeo de HandJointUtils
HandJointUtils
es una clase estática que consulta el primer dispositivo de mano activo.
if (HandJointUtils.TryGetJointPose(TrackedHandJoint.IndexTip, Handedness.Right, out MixedRealityPose pose))
{
// ...
}
Transformación conjunta del servicio conjunto a mano
IMixedRealityHandJointService
mantiene un conjunto persistente de GameObjects para realizar un seguimiento de las articulaciones.
var handJointService = CoreServices.GetInputSystemDataProvider<IMixedRealityHandJointService>();
if (handJointService != null)
{
Transform jointTransform = handJointService.RequestJointTransform(TrackedHandJoint.IndexTip, Handedness.Right);
// ...
}
Eventos de seguimiento de manos
El sistema de entrada también proporciona eventos, si no es deseable sondear datos de controladores directamente.
Eventos conjuntos
IMixedRealityHandJointHandler
controla las actualizaciones de las posiciones conjuntas.
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))
{
// ...
}
}
}
}
Eventos de malla
IMixedRealityHandMeshHandler
controla los cambios de la malla de mano articulada.
Tenga en cuenta que las mallas de mano no están habilitadas de forma predeterminada.
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;
}
// ...
}
}
}
Problemas conocidos
.NET Native
Actualmente hay un problema conocido con las compilaciones maestras mediante el back-end de .NET. En .NET Native, IInspectable
los punteros no se pueden serializar de código nativo a administrado mediante Marshal.GetObjectForIUnknown
. MRTK lo usa para obtener el SpatialCoordinateSystem
para recibir datos de mano y ojo de la plataforma.
Hemos proporcionado un origen DLL como solución alternativa para este problema, en el repositorio nativo de Mixed Reality Toolkit. Siga las instrucciones del archivo Léame y copie los archivos binarios resultantes en una carpeta Plugins en los recursos de Unity. Después, el script WindowsMixedRealityUtilities proporcionado en MRTK resolverá la solución alternativa.
Si desea crear su propio archivo DLL o incluir esta solución alternativa en una existente, el núcleo de la solución alternativa es:
extern "C" __declspec(dllexport) void __stdcall MarshalIInspectable(IUnknown* nativePtr, IUnknown** inspectable)
{
*inspectable = nativePtr;
}
Y su uso en el código de Unity de C#:
[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;
}
}