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

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 หลัก

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 ทั้งหมดได้ที่เอกสารอ้างอิง

ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างการใช้ 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)