สร้าง ควบคุม และจัดการเอนทิตี

Jetpack XR SDK ช่วยให้คุณใช้ Jetpack SceneCore เพื่อสร้าง ควบคุม และจัดการอินสแตนซ์ Entity เช่น โมเดล 3 มิติ วิดีโอสเตอริโอสโคปิก และ PanelEntity โดยใช้ Jetpack SceneCore

Jetpack SceneCore ใช้รูปแบบสถาปัตยกรรมทั่วไป 2 รูปแบบเพื่อรองรับการพัฒนา 3 มิติ ได้แก่ Scene Graph และระบบเอนทิตี-คอมโพเนนต์ (ECS)

ใช้กราฟฉากเพื่อสร้างและควบคุมเอนทิตี

หากต้องการสร้างและควบคุมออบเจ็กต์ในพื้นที่ 3 มิติ คุณสามารถใช้ API Session ของ 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 โดยตรง คุณย้ายตำแหน่ง เอนทิตีตามกราฟฉากได้โดยการตั้งค่า parent หรือใช้ addChild()

เอนทิตีมีลักษณะการทำงานเริ่มต้นบางอย่างสำหรับสิ่งที่เป็นสากลสำหรับเอนทิตีทั้งหมด เช่น การเปลี่ยนตำแหน่ง การหมุน หรือระดับการมองเห็น Entity คลาสย่อยที่เฉพาะเจาะจง เช่น GltfModelEntity มีลักษณะการทำงานเพิ่มเติมที่ รองรับคลาสย่อย

แก้ไขเอนทิตี

เมื่อคุณเปลี่ยนแปลงพร็อพเพอร์ตี้ 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 ให้ใช้ 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 เพื่อให้ผู้ใช้ย้ายเอนทิตีได้

MovableComponent อนุญาตให้ผู้ใช้ย้าย Entity ได้

ระบบจะส่งเหตุการณ์การเคลื่อนไหวไปยังคอมโพเนนต์เมื่อมีการโต้ตอบกับองค์ประกอบตกแต่ง ลักษณะการทำงานเริ่มต้นของระบบที่สร้างด้วย MovableComponent.createSystemMovable() จะย้าย Entity เมื่อมีการลาก การตกแต่ง

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

พารามิเตอร์ scaleInZ ที่ไม่บังคับ (ตั้งค่าเป็น true โดยค่าเริ่มต้น) จะทําให้เอนทิตี ปรับขนาดโดยอัตโนมัติเมื่อย้ายออกจากผู้ใช้ ในลักษณะเดียวกับที่ระบบปรับขนาดแผงในพื้นที่บ้าน เนื่องจากลักษณะ "เรียงซ้อน" ของระบบคอมโพเนนต์เอนทิตี สเกลของออบเจ็กต์หลัก จะมีผลกับออบเจ็กต์ย่อยทั้งหมด

นอกจากนี้ คุณยังระบุได้ด้วยว่าเอนทิตีสามารถยึดกับประเภทพื้นผิว เช่น พื้นผิวแนวนอนหรือแนวตั้ง หรือพื้นผิวเชิงความหมายที่เฉพาะเจาะจง เช่น โต๊ะ ผนัง หรือเพดาน ได้หรือไม่ หากต้องการระบุตัวเลือก Anchor ให้ระบุชุด 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.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 เมื่อสร้าง InteractableComponent ให้ระบุ Listener ที่รับเหตุการณ์อินพุต เมื่อผู้ใช้ดำเนินการป้อนข้อมูล ระบบจะเรียก Listener พร้อมกับ ข้อมูลอินพุตที่ระบุในพารามิเตอร์ 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.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)