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.
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.
- 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.
- 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) oXR_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_COARSEdurante 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
- Versión de Unity: Unity 6 versión 6000.0.58f2 o posterior
- Configuración del proyecto: Completa todos los pasos de la guía de configuración del proyecto de Unity.
- Paquetes de Unity: Instala la versión 1.5.0 o una posterior del paquete Android XR Extensions para Unity.
Configura tu proyecto
- Navega a Edit > Configuración del proyecto > XR Plug-in Management > OpenXR.
- Haz clic en Configuración junto a Android XR (Extensions): Session Management y desmarca Immersive XR.
- 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
- Versión de Godot: Godot 4.8-dev o posterior.
- Configuración del proyecto: Completa todos los pasos de la guía de configuración del proyecto de Godot Engine.
- Complemento de proveedores de OpenXR de Godot: Instala la versión 5.2 o una posterior del complemento de proveedores de OpenXR de Godot.
Configura tu proyecto
- Navega a Project > Project Settings, habilita Advanced Settings y ve a General > XR > OpenXR > Extensions.
- En el apartado Spatial Container, selecciona Enabled y configura Bounds Mode y Bounds.
- 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
- Versión de OpenXR: Encabezados de OpenXR 1.1 con
XR_EXT_spatial_containeryXR_EXT_spatial_container_self_rendering. - Configuración del manifiesto de la app: Configura el manifiesto de tu app como se describe en Comienza a usar OpenXR para Android XR con
XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED.
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
- Usa contenedores espaciales en Unity
- Usa contenedores espaciales en Godot
- Información sobre los permisos para la RE
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.