借助 Jetpack XR SDK,您可以使用 Jetpack SceneCore 创建、控制和管理 Entity
实例,例如 3D 模型、立体视频和 PanelEntity
。
Jetpack SceneCore 采用两种常见的架构模式来支持 3D 开发:场景图和实体-组件系统 (ECS)。
使用场景图创建和控制实体
如需在 3D 空间中创建和控制对象,您可以使用 Jetpack SceneCore 的 Session API 来访问场景图。场景图与用户的真实世界保持一致,可让您将面板和 3D 模型等 3D 实体整理成层次结构,并保持这些实体的状态。
获得场景图的访问权限后,您可以使用 Jetpack Compose for XR 中的 API 在场景图中创建空间界面(例如 SpatialPanel
和 Orbiter
实例)。对于 3D 模型等 3D 内容,您可以直接访问会话。如需了解详情,请参阅本页面上的ActivitySpace 简介。
实体组件系统
实体组件系统遵循组合优于继承的原则。您可以通过附加定义行为的组件来扩展实体的行为,从而将相同的行为应用于不同类型的实体。如需了解详情,请参阅本页面上的向实体添加通用行为。
ActivitySpace 简介
每个 Session
都有一个与 Session
一起自动创建的 ActivitySpace
。ActivitySpace
是场景图中的顶级 Entity
。
ActivitySpace 表示一个三维空间,采用右手坐标系(x 轴指向右侧,y 轴指向上方,z 轴指向后方,相对于原点),单位为米,与现实世界相符。ActivitySpace
的原点在某种程度上是任意的(因为用户可以在现实世界中重置 ActivitySpace
的位置),因此建议相对于彼此定位内容,而不是相对于原点定位内容。
处理实体
实体是 SceneCore 的核心。用户看到和互动的大部分内容都是表示面板、3D 模型等的实体。
由于 ActivitySpace
是场景图的顶级节点,因此默认情况下,所有新实体都会直接放置到 ActivitySpace
中。您可以通过设置实体的 parent
或使用 addChild()
沿场景图重新定位实体。
实体针对所有实体通用的事物(例如更改位置、旋转或可见性)具有一些默认行为。特定的 Entity
子类(例如 GltfModelEntity
)具有支持该子类的其他行为。
操纵实体
如果您更改属于基本 Entity
类的 Entity
属性,相应更改会向下级联到其所有子级。例如,调整父 Entity
的 Pose
会导致其所有子项都进行相同的调整。更改子级 Entity
不会影响其父级。
Pose
表示实体在 3D 空间中的位置和旋转。位置是一个 Vector3
,包含 x、y、z 数值位置。旋转由 Quaternion
表示。Entity
的位置始终相对于其父实体。换句话说,位置为 (0, 0, 0) 的 Entity
将放置在其父实体的原点处。
// 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
)可使实体在远离用户时自动调整其缩放比例,这与系统在主空间中缩放面板的方式类似。由于实体组件系统的“级联”特性,父级的缩放比例会影响其所有子级。
您还可以指定实体是否可以锚定到水平或垂直表面等表面类型,或锚定到桌面、墙壁或天花板等特定语义表面。如需指定锚点选项,请在创建 MovableComponent
时指定一组 AnchorPlacement
。在此示例中,可移动并锚定到任何地面或桌面水平表面的实体:
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
。
下面是一个在 SurfaceEntity
上使用固定宽高比的 ResizableComponent
的示例:
val resizableComponent = ResizableComponent.create(session) { event -> if (event.resizeState == ResizeEvent.ResizeState.RESIZE_STATE_END) { // update the Entity to reflect the new size surfaceEntity.canvasShape = SurfaceEntity.CanvasShape.Quad(event.newSize.width, event.newSize.height) } } resizableComponent.minimumEntitySize = FloatSize3d(177f, 100f, 1f) resizableComponent.fixedAspectRatio = 16f / 9f // Specify a 16:9 aspect ratio surfaceEntity.addComponent(resizableComponent)
使用 InteractableComponent
捕获用户输入事件
借助 InteractableComponent
,您可以捕获用户的输入事件,例如用户与 Entity
互动或将鼠标悬停在 Entity
上时。创建 InteractableComponent
时,请指定接收输入事件的监听器。当用户执行任何输入操作时,系统会使用 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.SOURCE_HANDS && it.action == InputEvent.Action.ACTION_UP) { // increase size with right hand and decrease with left if (it.pointerType == InputEvent.Pointer.POINTER_TYPE_RIGHT) { entity.setScale(1.5f) } else if (it.pointerType == InputEvent.Pointer.POINTER_TYPE_LEFT) { entity.setScale(0.5f) } } } entity.addComponent(interactableComponent)