Создание, контроль и управление сущностями

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

Jetpack XR SDK позволяет использовать Jetpack SceneCore для создания, управления и контроля экземпляров Entity , таких как 3D-модели , стереоскопическое видео и PanelEntity , с помощью Jetpack SceneCore.

Jetpack SceneCore использует два распространенных архитектурных шаблона для поддержки 3D-разработки: граф сцены и систему «сущность-компонент» (ECS).

Используйте граф сцены для создания и управления объектами.

Для создания и управления объектами в трехмерном пространстве можно использовать API сессий Jetpack SceneCore, чтобы получить доступ к графу сцены. Граф сцены соответствует реальному миру пользователя и позволяет организовывать трехмерные объекты, такие как панели и трехмерные модели, в иерархическую структуру и хранить состояние этих объектов.

Получив доступ к графу сцены, вы можете использовать API Jetpack Compose for XR для создания пространственного пользовательского интерфейса (например, экземпляров SpatialPanel и Orbiter ) внутри графа сцены. Для 3D-контента, такого как 3D-модели, вы можете получить прямой доступ к сессии. Для получения дополнительной информации см. раздел «О пространстве активности» на этой странице.

Система компонентов сущности

Система компонентов сущностей следует принципу композиции, а не наследования. Вы можете расширить поведение сущностей, присоединяя компоненты, определяющие поведение, что позволяет применять одно и то же поведение к различным типам сущностей. Для получения дополнительной информации см. раздел «Добавление общего поведения к сущностям» на этой странице.

О пространстве для активного отдыха

Каждая Session имеет ActivitySpace , который автоматически создается вместе с Session . ActivitySpace — это Entity верхнего уровня в графе сцены.

ActivitySpace представляет собой трехмерное пространство с правосторонней системой координат (ось X направлена ​​вправо, ось Y — вверх, а ось Z — назад относительно начала координат) и единицами измерения в метрах, соответствующими реальному миру. Начало координат для ActivitySpace несколько произвольно (поскольку пользователи могут изменять положение ActivitySpace в реальном мире), поэтому рекомендуется размещать контент относительно друг друга, а не относительно начала координат.

Работа с сущностями

Сущности играют центральную роль в SceneCore. Практически всё, что видит пользователь и с чем взаимодействует, представляет собой сущности, отображающие панели, 3D-модели и многое другое.

Поскольку ActivitySpace является узлом верхнего уровня графа сцены, по умолчанию все новые объекты размещаются непосредственно в ActivitySpace . Вы можете перемещать объекты вдоль графа сцены, задавая его parent или используя addChild() .

Сущности имеют некоторые по умолчанию свойства, универсальные для всех сущностей, такие как изменение положения, вращения или видимости. Конкретные подклассы Entity , такие как GltfModelEntity , имеют дополнительные свойства, поддерживающие этот подкласс.

Манипулирование сущностями

При изменении свойства Entity , принадлежащей базовому классу Entity , это изменение распространится на все её дочерние сущности. Например, изменение Pose родительской Entity приведёт к тому, что все её дочерние сущности получат такое же изменение. Изменение дочерней Entity не повлияет на её родительскую сущность.

Pose представляет собой местоположение и вращение объекта в трехмерном пространстве. Местоположение — это Vector3 , состоящий из числовых координат x, y, z. Вращение представлено Quaternion . Положение Entity всегда относительно его родительского объекта. Другими словами, Entity , положение которого равно (0, 0, 0), будет помещен в начало координат своего родительского объекта.

// Place the entity forward 2 meters
val newPosition = Vector3(0f, 0f, -2f)
// Rotate the entity by 180 degrees on the up axis (upside-down)
val newOrientation = Quaternion.fromEulerAngles(0f, 0f, 180f)
// Update the position and rotation on the entity
entity.setPose(Pose(newPosition, newOrientation))

Чтобы отключить Entity , используйте setEnabled() . Это сделает её невидимой и остановит всю обработку, выполняемую с ней.

// Disable the entity.
entity.setEnabled(false)

Чтобы изменить размер Entity , сохранив при этом его общую форму, используйте setScale() .

// Double the size of the entity
entity.setScale(2f)

Добавить общее поведение к сущностям

Для добавления общего поведения к сущностям можно использовать следующие компоненты:

  • MovableComponent : Позволяет пользователю перемещать объекты.
  • ResizableComponent : Позволяет пользователю изменять размер объектов, используя согласованные шаблоны пользовательского интерфейса.
  • InteractableComponent : Позволяет перехватывать события ввода для пользовательских взаимодействий.

Создание экземпляров компонентов должно осуществляться с помощью соответствующего метода создания в классе Session . Например, для создания ResizableComponent вызовите ResizableComponent.create() .

Для добавления определенного поведения компонента к Entity используйте метод addComponent() .

Используйте MovableComponent , чтобы сделать сущность перемещаемой пользователем.

MovableComponent позволяет пользователю перемещать Entity .

События перемещения отправляются компоненту при взаимодействии с декорациями. Стандартное поведение системы, созданное с помощью MovableComponent.createSystemMovable() , перемещает вашу Entity при перетаскивании декораций:

val movableComponent = MovableComponent.createSystemMovable(session)
entity.addComponent(movableComponent)

Необязательный параметр scaleInZ (по умолчанию установлен на true ) заставляет объект автоматически регулировать свой масштаб по мере удаления от пользователя, аналогично тому, как система масштабирует панели в домашнем пространстве . Из-за «каскадной» природы системы компонентов объекта масштаб родительского объекта будет влиять на все его дочерние элементы.

Вы также можете указать, можно ли прикрепить объект к поверхности определенного типа, например, горизонтальной или вертикальной, или к определенным семантическим поверхностям, таким как стол, стена или потолок. Чтобы указать параметры привязки, задайте набор параметров AnchorPlacement при создании MovableComponent . В этом примере объект, который можно перемещать и прикреплять к любой горизонтальной поверхности пола или стола:

val anchorPlacement = AnchorPlacement.createForPlanes(
    anchorablePlaneOrientations = setOf(PlaneOrientation.VERTICAL),
    anchorablePlaneSemanticTypes = setOf(PlaneSemanticType.FLOOR, PlaneSemanticType.TABLE)
)

val movableComponent = MovableComponent.createAnchorable(
    session = session,
    anchorPlacement = setOf(anchorPlacement)
)
entity.addComponent(movableComponent)

Используйте ResizableComponent , чтобы сделать сущность изменяемой пользователем.

Компонент ResizableComponent позволяет пользователям изменять размер Entity . ResizableComponent включает визуальные подсказки, побуждающие пользователя изменять размер Entity . При создании ResizableComponent можно указать минимальный или максимальный размер (в метрах). Также есть возможность указать фиксированное соотношение сторон при изменении размера, чтобы ширина и высота изменялись пропорционально друг другу.

При создании ResizableComponent укажите resizeEventListener , который будет обрабатывать события обновления. Вы можете реагировать на различные события ResizeState , такие как RESIZE_STATE_ONGOING или RESIZE_STATE_END .

Вот пример использования ResizableComponent с фиксированным соотношением сторон на SurfaceEntity :

val resizableComponent = ResizableComponent.create(session) { event ->
    if (event.resizeState == ResizeEvent.ResizeState.END) {
        // update the Entity to reflect the new size
        surfaceEntity.shape = SurfaceEntity.Shape.Quad(FloatSize2d(event.newSize.width, event.newSize.height))
    }
}
resizableComponent.minimumEntitySize = FloatSize3d(177f, 100f, 1f)
resizableComponent.isFixedAspectRatioEnabled = true // Maintain a fixed aspect ratio when resizing

surfaceEntity.addComponent(resizableComponent)

Используйте InteractableComponent для перехвата событий ввода пользователя.

Компонент InteractableComponent позволяет перехватывать события ввода от пользователя, например, когда пользователь взаимодействует с сущностью или наводит на нее Entity . При создании компонента InteractableComponent укажите слушатель, который будет получать эти события ввода. Когда пользователь выполняет какое-либо действие ввода, слушатель будет вызван с информацией о вводе, предоставленной в параметре InputEvent .

Полный список всех констант InputEvent см. в справочной документации .

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

val executor = Executors.newSingleThreadExecutor()
val interactableComponent = InteractableComponent.create(session, executor) {
    // when the user disengages with the entity with their hands
    if (it.source == InputEvent.Source.HANDS && it.action == InputEvent.Action.UP) {
        // increase size with right hand and decrease with left
        if (it.pointerType == InputEvent.Pointer.RIGHT) {
            entity.setScale(1.5f)
        } else if (it.pointerType == InputEvent.Pointer.LEFT) {
            entity.setScale(0.5f)
        }
    }
}
entity.addComponent(interactableComponent)

Создавайте пользовательские 3D-модели во время выполнения.

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