Extensión XR_ANDROID_hand_mesh de OpenXR

Cadena de nombre

XR_ANDROID_hand_mesh

Tipo de extensión

Extensión de la instancia

Número de extensión registrado

704

Revisión

1

Dependencias de extensiones y versiones

OpenXR 1.0

Fecha de última modificación

2024-09-10

Estado de la IP

No hay reclamos de IP conocidos.

Colaboradores

Nihav Jain, Google

Cairn Overturf, Google

Spencer Quin, Google

Levana Chen, Google

Descripción general

Esta extensión habilita el seguimiento de manos representado como una malla de mano dinámica.

El objetivo de esta extensión es proporcionar búferes de vértices y de índices para la malla de una representación personalizada de las manos del usuario. Se puede usar para la oclusión y la visualización.

Esta extensión no debe usarse para otros fines de seguimiento de la mano.

Los datos del seguimiento de la mano pueden ser información personal sensible y están estrechamente vinculados con la privacidad y la integridad personal. Se recomienda que las aplicaciones que almacenan o transfieren datos de seguimiento de manos siempre soliciten al usuario una aceptación activa y específica para hacerlo.

Cómo inspeccionar la capacidad del sistema

Una aplicación puede inspeccionar si el sistema es capaz de realizar mallas de seguimiento de manos encadenando una estructura XrSystemHandMeshTrackingPropertiesANDROID a XrSystemProperties cuando se llama a xrGetSystemProperties.

typedef struct XrSystemHandMeshTrackingPropertiesANDROID {
  XrStructureType    type;
  void*              next;
  XrBool32           supportsHandMeshTracking;
  XrBool32           supportsTextureUV;
  XrBool32           supportsVertexNormal;
} XrSystemHandMeshTrackingPropertiesANDROID;

Descripciones de los miembros

  • type es el XrStructureType de esta estructura.
  • next es NULL o un puntero a la siguiente estructura en una cadena de estructuras. No se definen tales estructuras en OpenXR principal ni en esta extensión.
  • supportsHandMeshTracking es un XrBool32, que indica si el XrSystemId seleccionado admite el seguimiento de malla de mano.
  • supportsTextureUV es un XrBool32, que indica si el XrSystemId seleccionado admite UV de textura para los vértices de la malla.
  • supportsVertexNormal es un XrBool32, que indica si el XrSystemId seleccionado admite normales de vértices para los vértices de la malla.

La aplicación debe evitar usar las capacidades de malla de mano cuando supportsHandMeshTracking sea XR_FALSE, ya que esto significa que el sistema no admite el seguimiento de malla de mano. En este caso, xrCreateHandMeshTrackerANDROID mostrará XR_ERROR_FEATURE_UNSUPPORTED.

Si supportsHandMeshTracking muestra XR_TRUE, el sistema admite el seguimiento de malla de manos. Una aplicación debe usar XrHandMeshANDROID::indexCount y XrHandMeshANDROID::vertexCount para acceder a los búferes de malla de mano y reutilizarlos en su bucle de renderización cuando llame a xrGetHandMeshANDROID en cada fotograma.

Si supportsTextureUV muestra XR_FALSE, el sistema no admite UV de textura para los vértices de la malla y, por lo tanto, una aplicación recibiría XrHandMeshANDROID::textureUVs NULL cuando llame a xrGetHandMeshANDROID.

Si supportsVertexNormal muestra XR_FALSE, el sistema no admite normales de vértices para los vértices de la malla y, por lo tanto, una aplicación recibiría XrHandMeshANDROID::normals NULL cuando llame a xrGetHandMeshANDROID.

Uso válido (implícito)

Crea un identificador de malla manual

XR_DEFINE_HANDLE(XrHandMeshTrackerANDROID)

El controlador XrHandMeshTrackerANDROID representa un rastreador de malla de mano para el seguimiento de malla de mano y la administración de los recursos relacionados.

Este identificador se puede usar para acceder a los búferes de malla de mano con otras funciones de esta extensión.

Una aplicación puede crear un controlador XrHandMeshTrackerANDROID con la función xrCreateHandMeshTrackerANDROID.

XrResult xrCreateHandMeshTrackerANDROID(
    XrSession                                   session,
    const XrHandMeshTrackerCreateInfoANDROID*   createInfo,
    XrHandMeshTrackerANDROID*                   handMeshTracker);

Descripciones de los parámetros

Si el sistema no admite el seguimiento de malla de mano, xrCreateHandMeshTrackerANDROID mostrará XR_ERROR_FEATURE_UNSUPPORTED.

El control XrHandMeshTrackerANDROID es propietario de todos los recursos para el seguimiento de malla de la mano. Después de terminar con las experiencias de seguimiento de malla de mano, la aplicación debe destruir el control con la función xrDestroyHandMeshTrackerANDROID.

Uso válido (implícito)

Códigos de retorno

Correcto

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Error

  • XR_ERROR_FEATURE_UNSUPPORTED
  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_LIMIT_REACHED

La estructura XrHandMeshTrackerCreateInfoANDROID describe la información para crear un controlador XrHandMeshTrackerANDROID.

typedef struct XrHandMeshTrackerCreateInfoANDROID {
    XrStructureType    type;
    const void*        next;
} XrHandMeshTrackerCreateInfoANDROID;

Descripciones de los miembros

  • type es el XrStructureType de esta estructura.
  • next es NULL o un puntero a la siguiente estructura en una cadena de estructuras. No se definen tales estructuras en OpenXR principal ni en esta extensión.

Uso válido (implícito)

La función xrDestroyHandMeshTrackerANDROID libera el handMeshTracker y los recursos subyacentes cuando finaliza con las experiencias de seguimiento de malla de mano.

XrResult xrDestroyHandMeshTrackerANDROID(
    XrHandMeshTrackerANDROID handMeshTracker);

Descripciones de los parámetros

Uso válido (implícito)

Seguridad de subprocesos

  • El acceso a handMeshTracker y a cualquier controlador secundario debe sincronizarse de forma externa.

Códigos de retorno

Correcto

  • XR_SUCCESS

Error

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID

Cómo ubicar mallas de mano

La aplicación puede usar la función xrGetHandMeshANDROID para recuperar la malla de la mano en una marca de tiempo determinada. La posición y la normalidad de los vértices de la malla de la mano se representan en el espacio especificado por XrHandMeshGetInfoANDROID::baseSpace cuando se llama a xrGetHandMeshANDROID.

XrResult xrGetHandMeshANDROID(
    XrHandMeshTrackerANDROID                    handMeshTracker,
    const XrHandMeshGetInfoANDROID*             getInfo,
    XrHandTrackingMeshesANDROID*                handMeshes);

Descripciones de los parámetros

La aplicación puede usar la función xrGetHandMeshANDROID para acceder a los búferes de malla de mano que genera el entorno de ejecución.

La aplicación debe llamar a xrBeginFrame al menos una vez durante la sesión antes de la primera llamada a xrGetHandMeshANDROID.

Una aplicación debe usar XrHandMeshANDROID::indexCount y XrHandMeshANDROID::vertexCount para acceder a los búferes de malla de mano y reutilizarlos en su bucle de renderización cuando llame a xrGetHandMeshANDROID en cada fotograma.

Uso válido (implícito)

Códigos de retorno

Correcto

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Error

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_SIZE_INSUFFICIENT
  • XR_ERROR_TIME_INVALID

Un XrHandMeshGetInfoANDROID describe la información necesaria para obtener datos de malla de mano.

typedef struct XrHandMeshGetInfoANDROID {
    XrStructureType    type;
    const void*        next;
    XrSpace            baseSpace;
    XrTime             time;
} XrHandMeshGetInfoANDROID;

Descripciones de los miembros

  • type es el XrStructureType de esta estructura.
  • next es NULL o un puntero a la siguiente estructura en una cadena de estructuras. No se definen tales estructuras en OpenXR principal ni en esta extensión.
  • baseSpace es un XrSpace que define el espacio de referencia en el que se debe ubicar la transformación de los vértices en time.
  • time es el XrTime que describe el momento en el que la aplicación desea consultar la malla de la mano.

Uso válido (implícito)

La estructura XrHandTrackingMeshesANDROID contiene datos de malla para ambas manos.

typedef struct XrHandTrackingMeshesANDROID {
    XrStructureType      type;
    void*                next;
    XrHandMeshANDROID    leftHandMesh;
    XrHandMeshANDROID    rightHandMesh;
} XrHandTrackingMeshesANDROID;

Descripciones de los miembros

  • type es el XrStructureType de esta estructura.
  • next es NULL o un puntero a la siguiente estructura en una cadena de estructuras. No se definen tales estructuras en OpenXR principal ni en esta extensión.
  • leftHandMesh es XrHandMeshANDROID para la mano izquierda.
  • rightHandMesh es XrHandMeshANDROID para la mano derecha.

Uso válido (implícito)

Una estructura XrHandMeshANDROID contiene datos y búferes para recibir datos de seguimiento de malla de mano de la función xrGetHandMeshANDROID para una mano.

typedef struct XrHandMeshANDROID {
    XrBool32             isActive;
    XrTime               dynamicLastUpdateTime;
    uint32_t             indexCount;
    uint32_t             vertexCount;
    const uint32_t*      indices;
    const XrVector2f*    textureUVs;
    const XrVector3f*    positions;
    const XrVector3f*    normals;
    XrPosef              baseSpaceFromVertexSpace;
} XrHandMeshANDROID;

Descripciones de los miembros

  • type es el XrStructureType de esta estructura.
  • next es NULL o un puntero a la siguiente estructura en una cadena de estructuras. No se definen tales estructuras en OpenXR principal ni en esta extensión.
  • isActive es un XrBool32 que indica si el rastreador de malla de mano actual está activo y si los datos de malla son válidos.
  • dynamicLastUpdateTime es el XrTime que especifica la hora en la que se actualizaron por última vez los búferes dinámicos.
  • indexCount es un uint32_t que funciona como la cantidad de indices de la malla de la mano.
  • vertexCount es un uint32_t que funciona como la cantidad de positions de la malla de la mano. También se puede usar para textureUVs o normals cuando el sistema los admite.
  • indices es un array de uint32_t que representa los índices de malla para los triángulos en el orden de la bobina en sentido contrario a las manecillas del reloj. La cantidad de valores a los que se hace referencia es indexCount.
  • textureUVs es NULL o un array de XrVector2f que representa las coordenadas de textura del vértice. La cantidad de valores a los que se apunta es vertexCount.
  • positions es un array de XrVector3f que representa las posiciones de los vértices en baseSpaceFromVertexSpace. La cantidad de valores a los que se apunta es vertexCount.
  • normals es un NULL o un array de XrVector3f que representa las normales de los vértices en baseSpaceFromVertexSpace. La cantidad de valores a los que se apunta es vertexCount.
  • baseSpaceFromVertexSpace es el vértice XrSpace ubicado en XrHandMeshGetInfoANDROID::baseSpace cuando se llama a xrGetHandMeshANDROID. Las aplicaciones pueden usar esto para transformar el espacio de coordenadas de los vértices y las normales de la malla durante la renderización.

La malla de la mano se representa en listas de triángulos y los vértices de cada triángulo están en orden antihorario cuando se mira desde fuera de la mano.

Cuando el valor de isActive que se muestra es XR_FALSE, significa que no se realiza un seguimiento activo de la mano. Por ejemplo, la mano está fuera del rango del sensor, se quita el enfoque de entrada de la aplicación o la aplicación no tiene los permisos para acceder a los datos de seguimiento de la mano.

Cuando el valor de isActive que se muestra es XR_TRUE, la malla de seguimiento de manos representada en indices y positions, incluidas textureUVs y normals, si el sistema las admite, se actualizan a los datos más recientes de XrHandMeshGetInfoANDROID::time que se le proporcionan a la función xrGetHandMeshANDROID.

El entorno de ejecución es propietario de la memoria a la que apuntan los búferes de malla de mano que se muestran en XrHandMeshANDROID y la comparte con la aplicación. Se puede acceder de forma segura a la memoria desde cualquier subproceso hasta la próxima llamada a xrBeginFrame mientras el control XrHandMeshTrackerANDROID sea válido.

  • Los valores a los que apuntan indices y textureUVs no son dinámicos.
  • El puntero y los valores a los que apuntan positions y normals son dinámicos, por lo que pueden cambiar entre llamadas a xrBeginFrame. La aplicación puede usar dynamicLastUpdateTime para verificar si los valores cambiaron desde el último fotograma y evitar el procesamiento de datos innecesario cuando no hay cambios.

Uso válido (implícito)

  • La extensión XR_ANDROID_hand_mesh debe estar habilitada antes de usar XrHandMeshANDROID.
  • indices debe ser un puntero a un valor uint32_t válido.
  • textureUVs debe ser un puntero a una estructura XrVector2f válida.
  • positions debe ser un puntero a una estructura XrVector3f válida.
  • normals debe ser un puntero a una estructura XrVector3f válida.

Ejemplo de código para el seguimiento de malla de mano

En el siguiente código de ejemplo, se muestra cómo acceder a los búferes de malla de mano para la renderización.

XrInstance instance;  // Created at app startup
XrSystemId systemId;  // Received from xrGetSystem() at app startup
XrSession session;    // Created at app startup.
XrSpace appPlaySpace; // Created at app startup.

// The function pointers are previously initialized using xrGetInstanceProcAddr.
PFN_xrCreateHandMeshTrackerANDROID xrCreateHandMeshTrackerANDROID; // previously initialized
PFN_xrDestroyHandMeshTrackerANDROID xrDestroyHandMeshTrackerANDROID; // previously initialized
PFN_xrGetHandMeshANDROID xrGetHandMeshANDROID; // previously initialized

// Inspect system capability
XrSystemHandMeshTrackingPropertiesANDROID handMeshTrackingProps = {
  .type = XR_TYPE_SYSTEM_HAND_MESH_TRACKING_PROPERTIES_ANDROID,
};
XrSystemProperties sysProps = {
  .type = XR_TYPE_SYSTEM_PROPERTIES,
  .next = &handMeshTrackingProps
};
CHK_XR(xrGetSystemProperties(instance, systemId, &sysProps));
if (!handMeshTrackingProps.supportsHandMeshTracking) {
  // hand mesh tracking is not supported.
  return;
}

XrHandMeshTrackerCreateInfoANDROID trackerCreateInfo = {
  .type = XR_TYPE_HAND_MESH_TRACKER_CREATE_INFO_ANDROID
};
XrHandMeshTrackerANDROID handMeshTracker = XR_NULL_HANDLE;
CHK_XR(xrCreateHandMeshTrackerANDROID(
    session, &trackerCreateInfo, &handMeshTracker));
// app update loop
while (true) {
    // ...
    // For every frame in frame loop
    // ...

    XrFrameState frameState;  // previously returned from xrWaitFrame
    const XrTime time = frameState.predictedDisplayTime;

    // ...
    XrHandMeshGetInfoANDROID getInfo = {
        .type = XR_TYPE_HAND_MESH_GET_INFO_ANDROID,
        .baseSpace = appPlaySpace,
        .time = time,
    };
    XrHandTrackingMeshesANDROID handMeshes = {
        .type = XR_TYPE_HAND_TRACKING_MESHES_ANDROID
    };
    CHK_XR(xrGetHandMeshANDROID(handMeshTracker, &getInfo, &handMeshes));

    if (handMeshes.leftHandMesh.isActive) {
        // access vertex/index buffers for rendering.
    }

    // ...
    // Finish frame loop
    // ...
}

CHECK_XR(xrDestroyHandMeshTracker(handMeshTracker));

Nuevos tipos de objetos

Nuevas constantes de enum

La enumeración XrObjectType se extiende con lo siguiente:

  • XR_OBJECT_TYPE_HAND_MESH_TRACKER_ANDROID

La enumeración XrStructureType se extiende con lo siguiente:

  • XR_TYPE_SYSTEM_HAND_MESH_TRACKING_PROPERTIES_ANDROID
  • XR_TYPE_HAND_MESH_TRACKER_CREATE_INFO_ANDROID
  • XR_TYPE_HAND_MESH_GET_INFO_ANDROID
  • XR_TYPE_HAND_TRACKING_MESHES_ANDROID

Enumeraciones nuevas

Nuevas estructuras

Funciones nuevas

Problemas

Historial de versiones

  • Revisión 1, 10/9/2024 (Levana Chen)
    • Descripción inicial de la extensión