Создание приложений с помощью пространственных контейнеров

Поддерживаемые XR-устройства
Это руководство поможет вам создавать продукты для таких XR-устройств.
XR-шлемы
Проводные XR-очки

Пространственные контейнеры добавляют в OpenXR объемные окна. Пространственный контейнер – это определяемая расширениями XR_EXT_spatial_container и XR_EXT_spatial_container_self_rendering в OpenXR 1.1 управляемая системой трехмерная область в пространстве пользователя, в которой приложение отрисовывает 3D-контент с помощью стандартных слоев композиции OpenXR.

Обычно сеанс OpenXR запрашивает эксклюзивный доступ ко всей зоне обзора пользователя. Пространственные контейнеры позволяют приложению отображать 3D-контент OpenXR в ограниченном трехмерном поле в среде пользователя или в любой момент переходить в неограниченный полноэкранный режим с эффектом присутствия.

О пространственных контейнерах

Пространственный контейнер – это ограниченная или неограниченная трехмерная область, которая управляется системой Android XR и отрисовывается приложением OpenXR.

  • Ограниченный режим. Приложение предлагает размеры 3D-объекта (ширину, высоту и глубину в метрах), а система выделяет для него трехмерную ограничительную рамку в окружении пользователя. Приложение отрисовывает стереоскопический 3D-контент внутри объема, а система обрезает его по границам 3D-области.
  • Режим погружения. Пространственный контейнер расширяется до бесконечных границ, предоставляя приложению всю зону обзора пользователя, как в традиционном полноэкранном режиме OpenXR.
Три пространственных контейнера, запущенных одновременно в режиме полного пространства: оранжевый контейнер с 3D-рельефом, привязанный к полу, синяя 3D-модель утки с прикрепленным 2D-интерфейсом и зеленый контейнер с 2D-интерфейсом.
Рисунок 1. Несколько пространственных контейнеров в режиме полного пространства: 3D-объект ландшафта, привязанный к полу (слева), 3D-объект утки в паре с 2D-интерфейсом (в центре) и контейнер 2D-интерфейса (справа).

Как пользователи взаимодействуют с пространственными контейнерами

Система Android XR управляет элементами управления окном пространственного контейнера и его размещением в физическом пространстве, обеспечивая согласованную модель взаимодействия между приложениями:

  • Перемещение и изменение положения. Пользователи могут перемещать пространственный контейнер в 3D-пространстве, используя системный маркер и жесты руками (например, сведение пальцев) или контроллеры движения.
  • Сворачивание и закрытие. Элементы управления системными окнами позволяют пользователям сворачивать или закрывать отдельные пространственные контейнеры. Когда пользователь закрывает контейнер, система уведомляет об этом приложение, чтобы оно могло освободить ресурсы.
  • Привязка к полу с помощью распознавания сцены. Когда приложение запрашивает разрешение android.permission.SCENE_UNDERSTANDING_COARSE, система автоматически включает привязку к поверхности, чтобы пользователи могли размещать и закреплять пространственный контейнер на физическом полу без дополнительной настройки приложения, как показано на рисунке 1.
  • Прямое взаимодействие с 3D-контентом. Когда контейнер находится в фокусе и интерактивен, пользователи могут напрямую взаимодействовать с 3D-контентом внутри него, используя отслеживание рук, взгляд или контроллеры 6DoF.
Пользователь взаимодействует с 3D-уткой внутри ограниченного синего пространственного контейнера, используя отслеживание рук.
Рисунок 2. Пользователь взаимодействует с 3D-контентом в ограниченном пространственном контейнере, используя отслеживание рук.
  • Переход между ограниченным и иммерсивным режимами. Пользователь или приложение может переключать контейнер между ограниченным трехмерным окном и неограниченным полноэкранным иммерсивным режимом без перезапуска сеанса OpenXR.
3D-сцена с уткой после перехода из ограниченного пространственного контейнера в неограниченный полноэкранный режим с эффектом присутствия.
Рисунок 3. Пространственный контейнер после перехода из ограниченного режима в режим погружения, заполняющий зону обзора пользователя.
  • Режим следования в движении Поскольку система управляет положением координатного пространства каждого пространственного контейнера (xrCreateSpatialContainerSpaceEXT), пользователи могут включить режим следования в элементах управления системным окном. В результате ограниченный 3D-контейнер будет автоматически следовать за ними и оставаться в зоне обзора, когда они перемещаются. Дополнительная настройка в приложении не требуется.

Как использовать пространственные контейнеры в Android XR

При создании приложения с пространственными контейнерами проектируйте сцену с учетом границ контейнера, изменений состояния и режима смешивания фона.

Как адаптировать 3D-контент к границам контейнера

В ограниченном режиме начало координат (0, 0, 0) пространства пространственного контейнера (xrCreateSpatialContainerSpaceEXT) находится в центре трехмерной ограничивающей рамки. Поскольку система управляет положением контейнера в пространстве пользователя, ваше приложение отображает 3D-контент относительно (0, 0, 0), а система обрабатывает перемещение пользователя и режим следования. Система обрезает любую геометрию, отображаемую за пределами ширины, высоты или глубины поля, чтобы контент оставался в пределах назначенного ему объема.

Приложение должно отслеживать события изменения границ от среды выполнения и масштабировать или перемещать 3D-сцену так, чтобы ключевой контент помещался в текущие размеры контейнера. Когда контейнер переходит в режим погружения, границы становятся бесконечными и вы можете восстановить сцену в полном масштабе 1:1.

Как реагировать на изменения состояния контейнера

Вместо того чтобы управлять видимостью и фокусом только на уровне приложения, каждый пространственный контейнер сообщает о своем состоянии, чтобы приложение могло реагировать соответствующим образом:

  • Видимость. Показывает, виден ли контейнер в данный момент. Приостанавливайте анимацию, аудио и симуляции, когда контейнер скрыт. Приложение также может запрашивать показ или скрытие контейнера.
  • Интерактивность. Указывает, находится ли контейнер в фокусе и получает ли он пользовательский ввод от отслеживания рук, контроллеров или взгляда. Включите или отключите интерактивные выделения и обработку ввода при изменении фокуса.
  • Режим границ. Показывает, в каком режиме находится контейнер: XR_SPATIAL_CONTAINER_BOUNDS_MODE_BOUNDED_EXT (ограничен трехмерным полем) или XR_SPATIAL_CONTAINER_BOUNDS_MODE_IMMERSIVE_EXT (неограниченный полноэкранный режим). Обновляйте масштаб сцены и переключайте визуальные эффекты окружения (например, скайбоксы или сквозной режим) при изменении режима. Приложение также может в любой момент запросить переход между ограниченным режимом и режимом погружения.

Использовать альфа-смешивание в ограниченном режиме

В ограниченном режиме прозрачный фон позволяет пользователю видеть физическое окружение и другие окна вокруг ваших 3D-моделей. Настройте камеру или область просмотра с прозрачным фоном и используйте режим смешивания среды alpha-blend. При переходе в режим погружения вы можете оставить сквозную камеру включенной или переключиться на непрозрачный скайбокс.

Проверьте доступность функций и настройте манифест

Для пространственных контейнеров требуется устройство Android XR, поддерживающее Spatial API уровня 4 или выше. Вместо того чтобы напрямую проверять уровень API Android, запросите среду выполнения OpenXR, чтобы определить, поддерживаются ли пространственные контейнеры. Для этого вызовите xrEnumerateInstanceExtensionProperties, чтобы проверить, доступны ли XR_EXT_spatial_container и XR_EXT_spatial_container_self_rendering, и вызовите xrGetSystemProperties с XrSystemSpatialContainerPropertiesEXT, чтобы проверить supportsBounded и supportsImmersive.

Прежде чем создавать приложение, использующее пространственные контейнеры, настройте режим запуска действий и разрешения для отдельных функций в файле AndroidManifest.xml.

Как включить режим полного пространства в AndroidManifest.xml

Для пространственных контейнеров требуется режим управляемого полного пространства, даже для автономных приложений OpenXR. Традиционные полноэкранные приложения OpenXR объявляют XR_ACTIVITY_START_MODE_FULL_SPACE_UNMANAGED, чтобы получить эксклюзивный контроль над экраном без управления системными окнами. Приложение, использующее пространственные контейнеры, полагается на системный компоновщик Android XR для управления ограниченными 3D-объемами, элементами управления окнами и пространственным размещением в режиме полного пространства. В этом случае необходимо задать для android.window.PROPERTY_XR_ACTIVITY_START_MODE значение 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>

Объявление и запрос разрешений для определенных функций

Для создания и отрисовки базового пространственного контейнера не требуются опасные динамические разрешения. Однако для некоторых функций необходимо объявить и запросить соответствующие разрешения Android XR:

  • Чтобы закрепить пространственный контейнер на физическом полу с помощью распознавания сцены, объявите и запросите опасное разрешение android.permission.SCENE_UNDERSTANDING_COARSE во время выполнения.
  • Чтобы отслеживать положение головы пользователя в OpenXR, объявите и запросите android.permission.HEAD_TRACKING.
<uses-permission android:name="android.permission.HEAD_TRACKING" />
<uses-permission android:name="android.permission.SCENE_UNDERSTANDING_COARSE" />

Подробнее о том, как объявлять и запрашивать опасные разрешения XR во время выполнения, рассказывается в статье Разрешения для XR.

Как включить пространственные контейнеры в проекте

Вы можете создавать пространственные контейнеры с помощью Unity, Godot или непосредственно с помощью OpenXR на C++. Выберите вкладку, чтобы увидеть предварительные требования, настройку редактора и пример кода для предпочитаемой вами среды:

Unity

Требования

Настройте проект

  1. Выберите Edit (Редактировать) > Project Settings (Настройки проекта) > XR Plug-in Management (Управление плагинами XR) > OpenXR.
  2. Нажмите Настройки рядом с пунктом Android XR (Extensions): Session Management (Android XR (расширения): управление сеансами) и снимите флажок Immersive XR (XR с эффектом присутствия).
  3. В списке OpenXR Feature Groups (Группы функций OpenXR) включите Spatial Container (Пространственный контейнер).

Используйте XRSpatialContainerFeature в C#, чтобы запрашивать границы, реагировать на события контейнера и переключаться между ограниченным режимом и режимом погружения.

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);
}

Полные инструкции по настройке проекта, конфигурации манифеста и обработке разрешений приведены в статье Как использовать пространственные контейнеры в Unity.

Godot

Требования

Настройте проект

  1. Перейдите в раздел Project (Проект) > Project Settings (Настройки проекта), включите Advanced Settings (Расширенные настройки) и выберите General (Общие) > XR > OpenXR > Extensions (Расширения).
  2. В подразделе Spatial Container (Пространственный контейнер) выберите Enabled (Включено) и настройте Bounds Mode (Режим границ) и Bounds (Границы).
  3. Выберите Project (Проект) > Export (Экспорт). > Android и в разделе Android XR Features (Функции Android XR) выберите Use Experimental Features (Использовать экспериментальные функции).

Используйте синглтон OpenXRSpatialContainerExtension в GDScript, чтобы реагировать на изменения границ и режима контейнера:

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
    )

Полные настройки проекта, разрешения на экспорт и примеры GDScript можно найти в статье Как использовать пространственные контейнеры в Godot.

OpenXR

Требования

При создании XrInstance включите XR_EXT_spatial_container и XR_EXT_spatial_container_self_rendering, а затем создайте и отрисуйте пространственный контейнер:

// 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);

Дополнительная информация


OpenXR™ и логотип OpenXR являются товарными знаками, принадлежащими The Khronos Group Inc. и зарегистрированными в Великобритании, Европейском союзе, Китае и Японии.