Jetpack XR SDK 可讓您使用 Jetpack SceneCore 建立、控制及管理 Entity 執行個體,例如 3D 模型、立體影片和 PanelEntity。
Jetpack SceneCore 採用兩種常見的架構模式,支援 3D 開發:場景圖和實體元件系統 (ECS)。
使用場景圖建立及控制實體
如要在 3D 空間中建立及控制物件,可以使用 Jetpack SceneCore 的 Session API 存取場景圖。場景圖會與使用者的現實世界對齊,方便您將面板和 3D 模型等 3D 實體整理成階層式結構,並保留這些實體的狀態。
存取場景圖後,您可以使用 Jetpack Compose for XR 中的 API,在場景圖中建立空間 UI (例如 SpatialPanel 和 Orbiter 執行個體)。如果是 3D 模型等 3D 內容,可以直接存取工作階段。詳情請參閱本頁的「關於 ActivitySpace」一文。
實體元件系統
實體元件系統遵循組合而非繼承的原則。您可以附加定義行為的元件來擴充實體的行為,以便將相同行為套用至不同類型的實體。詳情請參閱本頁的「為實體新增常見行為」。
關於 ActivitySpace
每個 Session 都有一個 ActivitySpace,會隨著 Session 自動建立。ActivitySpace 是場景圖中的頂層 Entity。
ActivitySpace 代表 3 維空間,採用右手座標系統 (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:讓使用者透過一致的 UI 模式調整實體大小InteractableComponent:可擷取自訂互動的輸入事件
您必須透過 Session 類別中的適當建立方法,將元件例項化。舉例來說,如要建立 ResizableComponent,請呼叫 ResizableComponent.create()。
如要將特定元件行為新增至 Entity,請使用 addComponent() 方法。
使用 MovableComponent 將 Entity 設為可供使用者移動
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.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 互動或將游標懸停在 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)