Jetpack XR SDK позволяет использовать Jetpack SceneCore для создания, контроля и управления экземплярами Entity
, такими как 3D-модели , стереоскопическое видео и PanelEntity
, с помощью Jetpack SceneCore.
Jetpack SceneCore использует два распространенных архитектурных шаблона для поддержки 3D-разработки: граф сцены и система «сущность-компонент» (ECS).
Используйте граф сцены для создания и управления сущностями
Для создания и управления объектами в 3D-пространстве можно использовать API сеанса Jetpack SceneCore, чтобы получить доступ к графу сцены. Граф сцены согласуется с реальным миром пользователя и позволяет организовывать 3D-сущности, такие как панели и 3D-модели, в иерархическую структуру и сохранять состояние этих сущностей.
Получив доступ к графу сцены, вы можете использовать API в Jetpack Compose для XR для создания пространственного пользовательского интерфейса (например, SpatialPanel
и Orbiter
s) в графе сцены. Для 3D-контента, такого как 3D-модели, вы можете получить прямой доступ к сеансу. Чтобы узнать больше, см. раздел About the ActivitySpace на этой странице.
Система компонентов сущности
Система сущность-компонент следует принципу композиции вместо наследования. Вы можете расширить поведение сущностей, прикрепив компоненты, определяющие поведение, что позволяет применять одно и то же поведение к разным типам сущностей. Для получения дополнительной информации ознакомьтесь с разделом Добавление общего поведения к сущностям на этой странице.
О ActivitySpace
Каждая Session
имеет ActivitySpace
, которая автоматически создается с помощью Session
. ActivitySpace
— это Entity
верхнего уровня в графе сцены.
ActivitySpace представляет собой трехмерное пространство с правосторонней системой координат (ось x указывает вправо, ось y указывает вверх, а ось z — назад относительно начала координат) и с метрами в качестве единиц, соответствующих реальному миру. Начало координат для ActivitySpace
несколько произвольно (поскольку пользователи могут сбросить положение ActivitySpace
в реальном мире), поэтому рекомендуется размещать контент относительно друг друга, а не относительно начала координат.
Работа с сущностями
Сущности играют центральную роль в SceneCore. Почти все, что видит и с чем взаимодействует пользователь, — это сущности, представляющие панели, 3D-модели и многое другое.
Поскольку ActivitySpace
является узлом верхнего уровня графа сцены, по умолчанию все новые сущности помещаются непосредственно в ActivitySpace
. Вы можете перемещать сущности по графу сцены, вызывая setParent
или addChild
.
У сущностей есть некоторые поведения по умолчанию для вещей, которые являются универсальными для всех сущностей, таких как изменение положения, поворот или видимость. Конкретные подклассы Entity
, такие как GltfEntity
, имеют дополнительные поведения, которые поддерживают подкласс.
Манипулировать сущностями
Когда вы вносите изменение в свойство 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
, используйте setHidden
.
// Hide the entity entity.setHidden(true)
Чтобы изменить размер Entity
, сохранив ее общую форму, используйте setScale
.
// Double the size of the entity entity.setScale(2f)
Добавить общее поведение к сущностям
Для добавления общего поведения сущностям можно использовать следующие компоненты:
-
MovableComponent
: позволяет пользователю перемещать объекты. -
ResizableComponent
: позволяет пользователю изменять размер объектов с использованием согласованных шаблонов пользовательского интерфейса. -
InteractableComponent
: позволяет захватывать события ввода для пользовательских взаимодействий.
Создание экземпляров компонентов должно осуществляться с помощью соответствующего метода создания в классе Session
. Например, чтобы создать ResizableComponent
, вызовите ResizableComponent.create()
.
Чтобы добавить определенное поведение компонента к Entity
, используйте метод addComponent()
.
Используйте MovableComponent, чтобы сделать сущность перемещаемой пользователем
MovableComponent
позволяет пользователю перемещать Entity
. Вы также можете указать, может ли сущность быть прикреплена к типу поверхности, например, к горизонтальной или вертикальной, или к определенным семантическим поверхностям, например, к столу, стене или потолку. Чтобы указать параметры привязки, укажите набор AnchorPlacement
при создании MovableComponent
.
Вот пример объекта, который можно перемещать и закреплять на любой вертикальной поверхности, а также только на горизонтальных поверхностях пола и потолка.
val anchorPlacement = AnchorPlacement.createForPlanes( planeTypeFilter = setOf(PlaneSemantic.FLOOR, PlaneSemantic.TABLE), planeSemanticFilter = setOf(PlaneType.VERTICAL) ) val movableComponent = MovableComponent.create( session = session, systemMovable = false, scaleInZ = false, anchorPlacement = setOf(anchorPlacement) ) entity.addComponent(movableComponent)
Когда пользователь перемещает сущность, параметр scaleInZ
автоматически корректирует масштаб сущности по мере ее удаления от пользователя аналогично тому, как панели масштабируются системой в домашнем пространстве . Из-за «каскадной» природы системы компонентов сущности масштаб родительского элемента будет влиять на всех его дочерних элементов.
Используйте ResizableComponent, чтобы сделать Entity доступным для изменения размера пользователем
ResizableComponent
позволяет пользователям изменять размер Entity
. ResizableComponent
включает визуальные подсказки взаимодействия, которые приглашают пользователя изменить размер Entity
. При создании ResizeableComponent
можно указать минимальный или максимальный размер (в метрах). Также есть возможность указать фиксированное соотношение сторон при изменении размера, чтобы ширина и высота изменялись пропорционально друг другу.
При использовании ResieableComponent
необходимо указать ResizeListener
для реагирования на определенные события изменения размера, такие как onResizeUpdate
или onResizeEnd
.
Вот пример использования ResizableComponent
с фиксированным соотношением сторон на SurfaceEntity
:
val resizableComponent = ResizableComponent.create(session) resizableComponent.minimumSize = Dimensions(177f, 100f, 1f) resizableComponent.fixedAspectRatio = 16f / 9f // Specify a 16:9 aspect ratio resizableComponent.addResizeListener( executor, object : ResizeListener { override fun onResizeEnd(entity: Entity, finalSize: Dimensions) { // update the size in the component resizableComponent.size = finalSize // update the Entity to reflect the new size (entity as SurfaceEntity).canvasShape = SurfaceEntity.CanvasShape.Quad(finalSize.width, finalSize.height) } }, ) entity.addComponent(resizableComponent)
Используйте InteractableComponent для захвата событий пользовательского ввода
InteractableComponent
позволяет захватывать события ввода от пользователя, например, когда пользователь взаимодействует или наводит курсор на Entity
. При создании InteractableComponent
необходимо указать InputEventListener
для получения событий ввода. Когда пользователь выполняет какое-либо действие ввода, будет вызван метод onInputEvent
с конкретной информацией ввода, предоставленной в параметре InputEvent
.
-
InputEvent.action
указывает тип ввода, например наведение или нажатие на объект. -
InputEvent.source
указывает, откуда поступил ввод, например, от руки или с контроллера . -
InputEvent.pointerType
указывает, поступил ли ввод с правой или левой руки.
Полный список всех констант 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_TYPE_RIGHT) { entity.setScale(1.5f) } else if (it.pointerType == InputEvent.POINTER_TYPE_LEFT) { entity.setScale(0.5f) } } } entity.addComponent(interactableComponent)