Compila con contenedores espaciales

Dispositivos de realidad extendida correspondientes
Esta guía te ayuda a crear experiencias para estos tipos de dispositivos de realidad extendida.
Visores de realidad extendida
Lentes de realidad extendida con cable

Los contenedores espaciales llevan las ventanas volumétricas a OpenXR. Definido por las extensiones XR_EXT_spatial_container y XR_EXT_spatial_container_self_rendering en OpenXR 1.1, un contenedor espacial es una región volumétrica 3D administrada por el sistema en el espacio del usuario en la que tu app renderiza contenido 3D con capas de composición estándar de OpenXR.

Tradicionalmente, una sesión de OpenXR reclama acceso exclusivo a todo el campo visual del usuario. Los contenedores espaciales permiten que tu app renderice contenido de OpenXR en 3D dentro de un cuadro 3D delimitado en el entorno del usuario o que realice la transición a una experiencia envolvente de pantalla completa sin límites en cualquier momento.

Acerca de los contenedores espaciales

Un contenedor espacial es una región en 3D limitada o ilimitada que administra el sistema de Android XR y renderiza tu app de OpenXR:

  • Modo limitado: Tu app sugiere dimensiones en 3D (ancho, alto y profundidad en metros), y el sistema asigna un cuadro delimitador en 3D en el entorno del usuario. Tu app renderiza contenido 3D estéreo dentro del volumen, y el sistema recorta el contenido renderizado según los límites de la caja 3D.
  • Modo envolvente: El contenedor espacial se expande a límites infinitos, lo que le da a tu app todo el campo visual del usuario, como una sesión de OpenXR tradicional de pantalla completa.
Tres contenedores espaciales que se ejecutan de forma simultánea en el modo de espacio completo: un contenedor de terreno en 3D de color naranja bloqueado en el suelo, un modelo de pato en 3D de color azul con una IU en 2D adjunta y un contenedor de IU en 2D de color verde.
Figura 1: Varios contenedores espaciales en el modo de espacio completo: un volumen de terreno 3D bloqueado en el suelo (izquierda), un volumen de pato 3D vinculado con una IU 2D (centro) y un contenedor de IU 2D (derecha).

Cómo interactúan los usuarios con los contenedores espaciales

El sistema de Android XR administra los controles de la ventana del contenedor espacial y su ubicación en el espacio físico, lo que proporciona un modelo de interacción coherente en todas las apps:

  • Movimiento y reposicionamiento: Los usuarios pueden tomar el controlador del sistema de un contenedor espacial con gestos con la mano (como pellizcar) o controles de movimiento para cambiar su posición en el espacio 3D.
  • Minimizar y cerrar: Los controles de la ventana del sistema permiten que los usuarios minimicen o cierren contenedores espaciales individuales. Cuando un usuario cierra un contenedor, el sistema notifica a tu app para que pueda limpiar los recursos.
  • Bloqueo en el piso con comprensión de la escena: Cuando tu app declara y solicita el permiso android.permission.SCENE_UNDERSTANDING_COARSE, el sistema habilita automáticamente el ajuste a la superficie para que los usuarios puedan colocar y bloquear un contenedor espacial en el piso físico sin configuración adicional de la app, como se muestra en el contenedor de terreno naranja de la Figura 1.
  • Interacción directa en 3D: Cuando un contenedor está enfocado y es interactivo, los usuarios pueden interactuar directamente con el contenido en 3D dentro del volumen con el monitoreo de manos, la mirada o los controles de 6DoF.
Un usuario interactúa con un pato en 3D dentro de un contenedor espacial azul delimitado con el monitoreo de manos.
Figura 2: Un usuario interactúa con contenido en 3D dentro de un contenedor espacial limitado usando el monitoreo de manos.
  • Transición entre los modos limitado y envolvente: El usuario o tu app pueden cambiar un contenedor entre un cuadro 3D limitado y una vista envolvente de pantalla completa sin límites sin reiniciar la sesión de OpenXR.
La escena del pato en 3D después de la transición de un contenedor espacial limitado a una vista envolvente de pantalla completa sin límites.
Figura 3. El contenedor espacial después de la transición del modo limitado al modo envolvente, que llena el campo visual del usuario.
  • Modo de seguimiento en cualquier lugar: Como el sistema controla la pose del espacio de coordenadas de cada contenedor espacial (xrCreateSpatialContainerSpaceEXT), los usuarios pueden habilitar el modo de seguimiento desde los controles de la ventana del sistema para que un contenedor 3D limitado los siga automáticamente y permanezca en su campo visual mientras caminan, sin necesidad de realizar ninguna configuración adicional en tu app.

Cómo usar contenedores espaciales en Android XR

Cuando crees una app con Spatial Containers, diseña tu escena en torno a los límites, los cambios de estado y el modo de combinación de fondo del contenedor.

Adapta tu contenido en 3D a los límites del contenedor

En el modo limitado, el origen (0, 0, 0) del espacio del contenedor espacial (xrCreateSpatialContainerSpaceEXT) se encuentra en el centro del cuadro delimitador 3D. Como el sistema administra la posición del espacio del contenedor en el entorno del usuario, tu app renderiza su contenido en 3D en relación con (0, 0, 0), mientras que el sistema controla el reposicionamiento del usuario y el modo de seguimiento. El sistema recorta cualquier geometría renderizada fuera del ancho, la altura o la profundidad del cuadro para que el contenido permanezca dentro de su volumen asignado.

Tu app debería escuchar los eventos de cambio de límites del entorno de ejecución y escalar o cambiar la posición de tu escena en 3D para que el contenido clave se ajuste a las dimensiones actuales del contenedor. Cuando el contenedor pasa al modo envolvente, los límites se vuelven infinitos y puedes restablecer la escena a su escala mundial completa de 1:1.

Cómo responder a los cambios de estado del contenedor

En lugar de administrar la visibilidad y el enfoque solo a nivel de la aplicación, cada contenedor espacial informa su propio estado para que tu app pueda reaccionar según corresponda:

  • Visibilidad: Indica si el contenedor se muestra o se oculta en ese momento. Pausa las animaciones, el audio o las actualizaciones de simulación mientras el contenedor está oculto. Tu app también puede solicitar que se muestre o se oculte un contenedor.
  • Interactividad: Indica si el contenedor está enfocado y recibe entradas del usuario a través del monitoreo de manos, los controles o la mirada. Habilita o inhabilita los elementos destacados interactivos y el control de entradas cuando cambia el enfoque.
  • Modo de límites: Indica si el contenedor se encuentra actualmente en XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT (recortado a un cuadro 3D) o XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT (pantalla completa sin límites). Actualiza la escala de la escena y activa o desactiva los elementos visuales del entorno (como skyboxes o passthrough) cuando cambie el modo. Tu app también puede solicitar transiciones entre los modos limitado y envolvente en cualquier momento.

Usa la transparencia con combinación alfa en el modo limitado

En el modo limitado, un fondo transparente permite que el entorno físico del usuario y otras ventanas permanezcan visibles alrededor de tus modelos 3D. Configura la cámara o el viewport con un fondo transparente y usa el modo de fusión de entorno de combinación alfa. Cuando cambies al modo envolvente, puedes mantener habilitada la transferencia o cambiar a un entorno de skybox opaco.

Verifica la disponibilidad de las funciones y configura tu manifiesto

Los contenedores espaciales requieren un dispositivo Android XR que admita el nivel de API espacial 4 o una versión posterior. En lugar de verificar el nivel de API de Android directamente, consulta el entorno de ejecución de OpenXR para determinar si se admiten los contenedores espaciales llamando a xrEnumerateInstanceExtensionProperties para verificar que XR_EXT_spatial_container y XR_EXT_spatial_container_self_rendering estén disponibles, y llamando a xrGetSystemProperties con XrSystemSpatialContainerPropertiesEXT para inspeccionar supportsBounded y supportsImmersive.

Antes de compilar una app que use Spatial Containers, configura el modo de inicio de la actividad y los permisos específicos de las funciones en AndroidManifest.xml.

Habilita el modo de espacio completo en AndroidManifest.xml

Los contenedores espaciales requieren el modo de espacio completo administrado, incluso para las apps de OpenXR independientes. Las apps tradicionales de OpenXR de pantalla completa declaran XR_ACTIVITY_START_MODE_FULL_SPACE_UNMANAGED para tomar el control exclusivo de la pantalla sin la administración de ventanas del sistema. Por el contrario, una app que usa contenedores espaciales depende del compositor del sistema de Android XR para administrar los volúmenes delimitados en 3D, los controles de ventanas y la ubicación espacial en el modo de espacio completo, y debe establecer android.window.PROPERTY_XR_ACTIVITY_START_MODE en XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ...>
        <!-- Spatial Containers require Full Space Managed mode -->
        <property
            android:name="android.window.PROPERTY_XR_ACTIVITY_START_MODE"
            android:value="XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED" />

        <activity android:name=".MainActivity" ...>
            <!-- Optional hint declaring which bounds modes the activity uses -->
            <property
                android:name="org.khronos.openxr.PROPERTY_ACTIVITY_HINT_XR_SPATIAL_CONTAINER_USED_BOUNDS_MODES"
                android:value="XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT|XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT" />
        </activity>
    </application>
</manifest>

Declara y solicita permisos específicos de funciones

Crear y renderizar un contenedor espacial básico no requiere permisos de tiempo de ejecución peligrosos. Sin embargo, algunas funciones específicas requieren que declares y solicites los permisos de Android XR correspondientes:

  • Para bloquear y fijar un contenedor espacial al piso físico con la comprensión de la escena, declara y solicita el permiso peligroso android.permission.SCENE_UNDERSTANDING_COARSE durante el tiempo de ejecución.
  • Para hacer un seguimiento de la postura de la cabeza del usuario en OpenXR, declara y solicita android.permission.HEAD_TRACKING.
<uses-permission android:name="android.permission.HEAD_TRACKING" />
<uses-permission android:name="android.permission.SCENE_UNDERSTANDING_COARSE" />

Consulta Información sobre los permisos para la RE para obtener detalles sobre cómo declarar y solicitar permisos peligrosos de RE durante el tiempo de ejecución.

Habilita Spatial Containers en tu proyecto

Puedes compilar con Spatial Containers usando Unity, Godot o directamente con OpenXR en C++. Selecciona una pestaña para ver los requisitos previos, la configuración del editor y el ejemplo de código para tu entorno preferido:

Unity

Requisitos previos

Configura tu proyecto

  1. Navega a Edit > Configuración del proyecto > XR Plug-in Management > OpenXR.
  2. Haz clic en Configuración junto a Android XR (Extensions): Session Management y desmarca Immersive XR.
  3. En la lista OpenXR Feature Groups, habilita Spatial Container.

Usa XRSpatialContainerFeature en C# para consultar los límites, responder a los eventos del contenedor y cambiar entre los modos limitado y envolvente:

void OnEnable()
{
    XRSpatialContainerFeature.OnSpatialContainerBoundsChanged += OnBoundsChanged;
}

private void OnBoundsChanged(Vector3 bounds, bool infiniteBounds)
{
    float minScale = Mathf.Min(bounds.x, bounds.y, bounds.z);
    transform.localScale = infiniteBounds ? Vector3.one : Vector3.one * minScale;
}

public void SetImmersiveMode(bool immersive)
{
    XRSpatialContainerFeature.TryRequestBoundsMode(immersive);
}

Para conocer los pasos completos de configuración del proyecto, la configuración del manifiesto y el manejo de permisos, consulta Cómo usar contenedores espaciales en Unity.

Godot

Requisitos previos

Configura tu proyecto

  1. Navega a Project > Project Settings, habilita Advanced Settings y ve a General > XR > OpenXR > Extensions.
  2. En el apartado Spatial Container, selecciona Enabled y configura Bounds Mode y Bounds.
  3. Navega a Project > Export… > Android y selecciona Use Experimental Features en Android XR Features.

Usa el singleton OpenXRSpatialContainerExtension en GDScript para responder a los cambios de modo y límites del contenedor:

func _ready() -> void:
    if OpenXRSpatialContainerExtension.is_enabled():
        OpenXRSpatialContainerExtension.spatial_container_bounds_changed.connect(
            _on_bounds_changed
        )

func _on_bounds_changed(_rid: RID, bounds: Vector3) -> void:
    scale = Vector3.ONE * min(bounds.x, bounds.y, bounds.z)

func set_immersive_mode() -> void:
    OpenXRSpatialContainerExtension.request_main_spatial_container_bounds_mode(
        OpenXRSpatialContainerState.IMMERSIVE
    )

Para obtener ejemplos completos de configuración del proyecto, permisos de exportación y GDScript, consulta Usa Spatial Containers en Godot.

OpenXR

Requisitos previos

Habilita XR_EXT_spatial_container y XR_EXT_spatial_container_self_rendering cuando crees tu XrInstance, luego crea y renderiza tu contenedor espacial:

// 1. Enable the Spatial Container extensions during xrCreateInstance
const char* enabledExtensions[] = {
    XR_EXT_SPATIAL_CONTAINER_EXTENSION_NAME,
    XR_EXT_SPATIAL_CONTAINER_SELF_RENDERING_EXTENSION_NAME,
};

// 2. Configure and create a self-rendering spatial container
XrSpatialContainerConfigurationSelfRenderingEXT selfRenderingConfig{
    .type = XR_TYPE_SPATIAL_CONTAINER_CONFIGURATION_SELF_RENDERING_EXT,
    .next = nullptr,
    .viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO,
    .suggestedBounds = {1.5f, 1.5f, 1.5f}, // Width, height, depth in meters
};

XrSpatialContainerCreateInfoEXT createInfo{
    .type = XR_TYPE_SPATIAL_CONTAINER_CREATE_INFO_EXT,
    .next = &selfRenderingConfig,
    .spatialContainerConfig =
        reinterpret_cast<const XrSpatialContainerConfigurationBaseHeaderEXT*>(
            &selfRenderingConfig),
};

XrSpatialContainerEXT spatialContainer = XR_NULL_HANDLE;
xrCreateSpatialContainerEXT(session, &createInfo, &spatialContainer);

// 3. Request bounded mode and make the container visible
xrRequestSpatialContainerBoundsModeEXT(
    spatialContainer, XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT);
xrRequestSpatialContainerVisibilityEXT(spatialContainer, XR_TRUE);

Consulta también


OpenXR™ y el logotipo de OpenXR son marcas comerciales de The Khronos Group Inc. y están registradas como marcas comerciales en China, la Unión Europea, Japón y el Reino Unido.