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

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 modelPosition = 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 ให้เรียกใช้ session.createResizableComponent()

หากต้องการเพิ่มลักษณะการทํางานของคอมโพเนนต์ที่เฉพาะเจาะจงลงใน Entity ให้ใช้เมธอด addComponent()

ใช้ MovableComponent เพื่อทำให้เอนทิตีเคลื่อนย้ายได้โดยผู้ใช้

MovableComponent ช่วยให้ผู้ใช้ย้าย Entity ได้ นอกจากนี้ คุณยังระบุได้ว่าเอนทิตีจะยึดกับประเภทพื้นผิวได้หรือไม่ เช่น พื้นผิวแนวนอนหรือแนวตั้ง หรือพื้นผิวเชิงความหมายที่เฉพาะเจาะจง เช่น โต๊ะ ผนัง หรือเพดาน หากต้องการระบุตัวเลือกของหมุด ให้ระบุชุด AnchorPlacement เมื่อสร้าง MovableComponent

ต่อไปนี้คือตัวอย่างของเอนทิตีที่ย้ายและยึดกับพื้นผิวแนวตั้งได้ รวมถึงพื้นผิวแนวนอนของพื้นและเพดานเท่านั้น

val anchorPlacement = AnchorPlacement.createForPlanes(
    planeTypeFilter = setOf(PlaneSemantic.FLOOR, PlaneSemantic.TABLE),
    planeSemanticFilter = setOf(PlaneType.VERTICAL))

val movableComponent = xrSession.createMovableComponent(
    systemMovable = false,
    scaleInZ = false,
    anchorPlacement = setOf(anchorPlacement)
)
entity.addComponent(movableComponent)

ใช้ ResizableComponent เพื่อทำให้ผู้ใช้ปรับขนาดเอนทิตีได้

ResizableComponent ช่วยให้ผู้ใช้ปรับขนาด Entity ได้ ResizableComponent มีสัญญาณการโต้ตอบด้วยภาพซึ่งเชิญชวนให้ผู้ใช้ปรับขนาด Entity เมื่อสร้าง ResizeableComponent คุณสามารถระบุขนาดขั้นต่ำหรือสูงสุด (เป็นเมตร) นอกจากนี้ คุณยังมีตัวเลือกในการระบุสัดส่วนการแสดงผลคงที่เมื่อปรับขนาดเพื่อให้ความกว้างและความสูงปรับขนาดตามสัดส่วนกัน

ต่อไปนี้คือตัวอย่างการใช้ ResizableComponent ที่มีสัดส่วนภาพแบบคงที่

val resizableComponent = xrSession.createResizableComponent()
resizableComponent.minimumSize = Dimensions(177f, 100f, 1f )
resizableComponent.fixedAspectRatio = 16f / 9f //Specify a 16:9 aspect ratio
entity.addComponent(resizableComponent)

ใช้ InteractableComponent เพื่อบันทึกเหตุการณ์การป้อนข้อมูลของผู้ใช้

InteractableComponent ช่วยให้คุณบันทึกเหตุการณ์อินพุตจากผู้ใช้ได้ เช่น เมื่อผู้ใช้มีส่วนร่วมหรือวางเมาส์เหนือ Entity เมื่อสร้าง InteractableComponent คุณต้องระบุ InputEventListener เพื่อรับเหตุการณ์อินพุต เมื่อผู้ใช้ดำเนินการป้อนข้อมูล ระบบจะเรียกใช้เมธอด onInputEvent ด้วยข้อมูลการป้อนข้อมูลที่เฉพาะเจาะจงซึ่งระบุไว้ในพารามิเตอร์ InputEvent

ดูรายการค่าคงที่ InputEvent ทั้งหมดได้ที่เอกสารอ้างอิง

ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างการใช้ InteractableComponent เพื่อเพิ่มขนาดของเอนทิตีด้วยมือขวาและลดขนาดด้วยมือซ้าย

private val executor by lazy { Executors.newSingleThreadExecutor() }
val interactableComponent = xrSession.createInteractableComponent(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)