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

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

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