Jetpack XR SDK ช่วยให้คุณใช้ Jetpack SceneCore เพื่อสร้าง ควบคุม และจัดการ
Entity อินสแตนซ์ เช่น โมเดล 3 มิติ, วิดีโอสเตอริโอสโคปิก และ
PanelEntity โดยใช้ Jetpack SceneCore
Jetpack SceneCore ใช้รูปแบบสถาปัตยกรรมทั่วไป 2 แบบเพื่อรองรับการพัฒนา 3 มิติ ได้แก่ กราฟฉากและระบบแยกส่วน (ECS)
ใช้กราฟฉากเพื่อสร้างและควบคุมเอนทิตี
หากต้องการสร้างและควบคุมออบเจ็กต์ในพื้นที่ 3 มิติ คุณสามารถใช้ Jetpack SceneCore's Session API เพื่อเข้าถึงกราฟฉาก กราฟฉากจะสอดคล้องกับโลกแห่งความเป็นจริงของผู้ใช้ และช่วยให้คุณจัดระเบียบเอนทิตี 3 มิติ เช่น แผงและโมเดล 3 มิติ เป็นโครงสร้างแบบลำดับชั้น รวมถึงเก็บสถานะของเอนทิตีเหล่านั้น
เมื่อเข้าถึงกราฟฉากแล้ว คุณจะใช้ API ใน Jetpack
Compose for XR เพื่อสร้าง UI เชิงพื้นที่ (เช่น SpatialPanel และ
Orbiter อินสแตนซ์) ภายในกราฟฉากได้ สำหรับเนื้อหา 3 มิติ เช่น โมเดล 3 มิติ คุณสามารถเข้าถึง Session ได้โดยตรง ดูข้อมูลเพิ่มเติมได้ที่หัวข้อเกี่ยวกับ
ActivitySpace ในหน้านี้
ระบบคอมโพเนนต์เอนทิตี
ระบบเอนทิตีคอมโพเนนต์เป็นไปตามหลักการของการประกอบมากกว่าการรับช่วง คุณสามารถขยายลักษณะการทำงานของเอนทิตีได้โดยแนบคอมโพเนนต์ที่กำหนดลักษณะการทำงาน ซึ่งช่วยให้คุณใช้ลักษณะการทำงานเดียวกันกับเอนทิตีประเภทต่างๆ ได้ ดูข้อมูลเพิ่มเติมได้ที่หัวข้อเพิ่มลักษณะการทำงานทั่วไปให้กับเอนทิตีในหน้านี้
เกี่ยวกับ ActivitySpace
`Session` แต่ละรายการจะมี `ActivitySpace` ที่สร้างขึ้นโดยอัตโนมัติพร้อมกับ `Session`SessionSessionActivitySpace ActivitySpace คือ Entity ระดับบนสุดในกราฟฉาก
ActivitySpace แสดงถึงพื้นที่ 3 มิติที่มีระบบพิกัดแบบมือขวา (แกน x ชี้ไปทางขวา แกน y ชี้ขึ้น และแกน z ชี้ไปข้างหลังเทียบกับจุดกำเนิด) และมีหน่วยเป็นเมตรเพื่อให้ตรงกับโลกแห่งความเป็นจริง จุดกำเนิดของ ActivitySpace ค่อนข้างเป็นไปตามอำเภอใจ (เนื่องจากผู้ใช้สามารถรีเซ็ตตำแหน่งของ ActivitySpace ภายในโลกแห่งความเป็นจริงได้) ดังนั้นจึงขอแนะนำให้วางตำแหน่งเนื้อหาเทียบกับเนื้อหาอื่นๆ แทนที่จะเทียบกับจุดกำเนิด
ทำงานกับเอนทิตี
เอนทิตีเป็นส่วนสำคัญของ SceneCore เกือบทุกสิ่งที่ผู้ใช้เห็นและโต้ตอบด้วยคือเอนทิตีที่แสดงถึงแผง โมเดล 3 มิติ และอื่นๆ
เนื่องจาก ActivitySpace เป็นโหนดระดับบนสุดของกราฟฉาก โดยค่าเริ่มต้น ระบบจะวางเอนทิตีใหม่ทั้งหมดลงใน ActivitySpace โดยตรง คุณสามารถย้ายตำแหน่งเอนทิตีไปตามกราฟฉากได้โดยตั้งค่า parent หรือใช้
addChild()
เอนทิตีมีลักษณะการทำงานเริ่มต้นบางอย่างสำหรับสิ่งที่ใช้ร่วมกันในเอนทิตีทั้งหมด เช่น การเปลี่ยนตำแหน่ง การหมุน หรือการมองเห็น คลาสย่อย Entity
ที่เฉพาะเจาะจง เช่น GltfModelEntity มีลักษณะการทำงานเพิ่มเติมที่
รองรับคลาสย่อย
จัดการเอนทิตี
เมื่อคุณทำการเปลี่ยนแปลงพร็อพเพอร์ตี้ 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 ให้ใช้ 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 โดยค่าเริ่มต้น) จะทำให้เอนทิตี
ปรับขนาดโดยอัตโนมัติเมื่อเคลื่อนที่ออกจากผู้ใช้
ในลักษณะเดียวกับที่ระบบปรับขนาดแผงใน พื้นที่ส่วนตัว
เนื่องจากระบบแยกส่วนของเอนทิตีมีลักษณะการทำงานแบบ "ส่งต่อ" ขนาดของระดับบนจึงจะส่งผลต่อระดับล่างทั้งหมด
นอกจากนี้ คุณยังระบุได้ด้วยว่าเอนทิตีสามารถยึดกับประเภทพื้นผิว เช่น พื้นผิวแนวนอนหรือแนวตั้ง หรือพื้นผิวเชิงความหมายที่เฉพาะเจาะจง เช่น โต๊ะ ผนัง หรือเพดานได้หรือไม่ หากต้องการระบุตัวเลือกการยึด ให้ระบุชุด 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.END) { // update the Entity to reflect the new size surfaceEntity.shape = SurfaceEntity.Shape.Quad(FloatSize2d(event.newSize.width, event.newSize.height)) } } resizableComponent.minimumEntitySize = FloatSize3d(177f, 100f, 1f) resizableComponent.isFixedAspectRatioEnabled = true // Maintain a fixed aspect ratio when resizing surfaceEntity.addComponent(resizableComponent)
ใช้ InteractableComponent เพื่อบันทึกเหตุการณ์ข้อมูลจากผู้ใช้
InteractableComponent ช่วยให้คุณบันทึกเหตุการณ์อินพุตจากผู้ใช้ได้
เช่น เมื่อผู้ใช้มีส่วนร่วมหรือวางเมาส์เหนือ Entity เมื่อสร้าง InteractableComponent ให้ระบุ Listener ที่รับเหตุการณ์อินพุต
เมื่อผู้ใช้ดำเนินการอินพุต Listener จะถูกเรียกใช้พร้อมข้อมูลอินพุตที่ระบุไว้ในพารามิเตอร์ 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.RIGHT) { entity.setScale(1.5f) } else if (it.pointerType == InputEvent.Pointer.LEFT) { entity.setScale(0.5f) } } } entity.addComponent(interactableComponent)
สร้างโมเดล 3 มิติที่กำหนดเองในรันไทม์
Custom Mesh API ช่วยให้คุณสร้างรูปร่าง 3 มิติแบบเป็นโปรแกรมในโค้ดได้โดยตรง แทนที่จะโหลดเนื้อหาแบบคงที่ เช่น ไฟล์ glTF การสร้างรูปทรงเรขาคณิตที่กำหนดเองแบบทันทีช่วยให้คุณแสดงข้อมูลตามขั้นตอน รูปร่างที่กำหนดเองแบบไดนามิก และสภาพแวดล้อม 3 มิติที่ดูเหมือนไม่มีที่สิ้นสุด เช่น ภูมิประเทศที่สร้างขึ้นอย่างต่อเนื่องเมื่อผู้ใช้สำรวจ นอกจากนี้ การสร้าง Mesh ในรันไทม์ยังช่วยลดขนาดไบนารีด้วยการไม่จำเป็นต้องแพ็กเกจเนื้อหา 3 มิติรายการเดียวในรูปแบบต่างๆ มากมาย