Jetpack XR SDK ให้คุณใช้ Jetpack SceneCore เพื่อสร้าง ควบคุม และจัดการอินสแตนซ์ Entity
เช่น โมเดล 3 มิติ วิดีโอสเตอริโอสโคป และ PanelEntity
โดยใช้ Jetpack SceneCore
Jetpack SceneCore ใช้รูปแบบสถาปัตยกรรมทั่วไป 2 รูปแบบเพื่อรองรับการพัฒนา 3 มิติ ได้แก่ กราฟฉากและระบบเอนทิตีคอมโพเนนต์ (ECS)
ใช้กราฟฉากเพื่อสร้างและควบคุมเอนทิตี
หากต้องการสร้างและควบคุมวัตถุในพื้นที่ 3 มิติ คุณสามารถใช้ Session API ของ Jetpack SceneCore เพื่อเข้าถึงกราฟฉาก กราฟฉากจะสอดคล้องกับโลกแห่งความเป็นจริงของผู้ใช้ และให้คุณจัดระเบียบเอนทิตี 3 มิติ เช่น แผงและโมเดล 3 มิติ ให้เป็นโครงสร้างตามลําดับชั้น และเก็บสถานะของเอนทิตีเหล่านั้น
เมื่อได้รับสิทธิ์เข้าถึงกราฟฉากแล้ว คุณจะใช้ API ใน Jetpack Compose สำหรับ XR เพื่อสร้าง UI แบบพื้นที่ (เช่น อินสแตนซ์ SpatialPanel
และ Orbiter
) ภายในกราฟฉากได้ สำหรับเนื้อหา 3 มิติ เช่น โมเดล 3 มิติ คุณจะเข้าถึงเซสชันได้โดยตรง ดูข้อมูลเพิ่มเติมได้ที่เกี่ยวกับ ActivitySpace ในหน้านี้
ระบบคอมโพเนนต์เอนทิตี
ระบบเอนทิตีคอมโพเนนต์เป็นไปตามหลักการขององค์ประกอบมากกว่าการรับช่วง คุณสามารถขยายลักษณะการทํางานของเอนทิตีได้โดยแนบคอมโพเนนต์ที่กําหนดลักษณะการทํางาน ซึ่งจะช่วยให้คุณใช้ลักษณะการทํางานเดียวกันกับเอนทิตีประเภทต่างๆ ได้ ดูข้อมูลเพิ่มเติมได้ที่เพิ่มลักษณะการทำงานทั่วไปให้กับเอนทิตีในหน้านี้
เกี่ยวกับ ActivitySpace
Session
แต่ละรายการจะมี ActivitySpace
ที่สร้างขึ้นโดยอัตโนมัติพร้อมกับ Session
ActivitySpace
คือ Entity
ระดับบนสุดในกราฟฉาก
ActivitySpace แสดงถึงพื้นที่ 3 มิติด้วยระบบพิกัดที่ใช้มือขวา (แกน X ชี้ไปทางขวา แกน Y ชี้ขึ้น และแกน Z ชี้ไปด้านหลังโดยสัมพันธ์กับจุดเริ่มต้น) และมีเมตรเป็นหน่วยที่ตรงกับโลกแห่งความเป็นจริง ต้นทางของ ActivitySpace
นั้นค่อนข้างจะเป็นค่าที่กำหนดเอง (เนื่องจากผู้ใช้สามารถรีเซ็ตตำแหน่งของ ActivitySpace
ในโลกแห่งความเป็นจริงได้) เราจึงขอแนะนำให้จัดตำแหน่งเนื้อหาให้สัมพันธ์กันแทนที่จะสัมพันธ์กับต้นทาง
ทำงานกับเอนทิตี
เอนทิตีเป็นหัวใจสําคัญของ SceneCore เกือบทุกอย่างที่ผู้ใช้เห็นและโต้ตอบด้วยคือเอนทิตีที่แสดงแผง โมเดล 3 มิติ และอื่นๆ
เนื่องจาก ActivitySpace
เป็นโหนดระดับบนสุดของกราฟฉาก โดยค่าเริ่มต้น ระบบจะวางเอนทิตีใหม่ทั้งหมดไว้ใน ActivitySpace
โดยตรง คุณสามารถย้ายตำแหน่งของเอนทิตีตามกราฟฉากได้โดยเรียกใช้ setParent()
หรือ addChild()
เอนทิตีมีลักษณะการทำงานเริ่มต้นบางอย่างสำหรับสิ่งที่เป็นสากลสำหรับเอนทิตีทั้งหมด เช่น การเปลี่ยนตำแหน่ง การหมุน หรือการแสดงผล Entity
คลาสย่อยที่เฉพาะเจาะจง เช่น GltfEntity
จะมีลักษณะการทำงานเพิ่มเติมที่รองรับคลาสย่อยนั้น
จัดการเอนทิตี
เมื่อคุณทําการเปลี่ยนแปลงในพร็อพเพอร์ตี้ Entity
ที่เป็นของคลาส Entity
พื้นฐาน การเปลี่ยนแปลงจะส่งผลต่อพร็อพเพอร์ตี้ย่อยทั้งหมด ตัวอย่างเช่น การปรับเปลี่ยน Pose
ของ Entity
หลักจะส่งผลให้รายการย่อยทั้งหมดของ Entity
นั้นได้รับการปรับเปลี่ยนด้วย การเปลี่ยนแปลงใน Entity
ย่อยจะไม่ส่งผลต่อ Entity
หลัก
Pose
แสดงตําแหน่งและการหมุนของเอนทิตี้ภายในพื้นที่ 3 มิติ ตำแหน่งเป็น 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
: อนุญาตให้ผู้ใช้ปรับขนาดเอนทิตีด้วยรูปแบบ UI ที่สอดคล้องกัน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 เพื่อทำให้ผู้ใช้ปรับขนาดเอนทิตีได้
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)