Jetpack XR SDK की मदद से, Jetpack SceneCore का इस्तेमाल करके Entity
इंस्टेंस बनाए, कंट्रोल किए, और मैनेज किए जा सकते हैं. जैसे, 3D मॉडल, स्टीरियोस्कोपिक वीडियो, और PanelEntity
.
Jetpack SceneCore, 3D डेवलपमेंट के लिए दो सामान्य आर्किटेक्चरल पैटर्न का इस्तेमाल करता है: सीन ग्राफ़ और इकाई-कॉम्पोनेंट सिस्टम (ईसीएस).
सीन ग्राफ़ का इस्तेमाल करके, इकाइयां बनाएं और उन्हें कंट्रोल करें
3D स्पेस में ऑब्जेक्ट बनाने और उन्हें कंट्रोल करने के लिए, Jetpack SceneCore के Session API का इस्तेमाल करके सीन ग्राफ़ को ऐक्सेस किया जा सकता है. सीन ग्राफ़, उपयोगकर्ता की असली दुनिया के साथ अलाइन होता है. इससे पैनल और 3D मॉडल जैसी 3D इकाइयों को क्रमबद्ध स्ट्रक्चर में व्यवस्थित किया जा सकता है. साथ ही, इन इकाइयों की स्थिति को बनाए रखा जा सकता है.
सीन ग्राफ़ का ऐक्सेस मिलने के बाद, सीन ग्राफ़ में स्पेशल यूज़र इंटरफ़ेस (जैसे, SpatialPanel
और Orbiter
इंस्टेंस) बनाने के लिए, Jetpack Compose for XR में मौजूद एपीआई का इस्तेमाल किया जा सकता है. 3D मॉडल जैसे 3D कॉन्टेंट के लिए, सीधे सेशन को ऐक्सेस किया जा सकता है. ज़्यादा जानने के लिए, इस पेज पर ActivitySpace के बारे में जानकारी देखें.
इकाई कॉम्पोनेंट सिस्टम
इकाई कॉम्पोनेंट सिस्टम, इनहेरिटेंस के बजाय कंपोज़िशन के सिद्धांत का पालन करता है. व्यवहार तय करने वाले कॉम्पोनेंट अटैच करके, इकाइयों के व्यवहार को बढ़ाया जा सकता है. इससे अलग-अलग तरह की इकाइयों पर एक जैसा व्यवहार लागू किया जा सकता है. ज़्यादा जानकारी के लिए, इस पेज पर इकाइयों में सामान्य व्यवहार जोड़ना लेख पढ़ें.
ActivitySpace के बारे में जानकारी
हर Session
में एक ActivitySpace
होता है, जो Session
के साथ अपने-आप जनरेट होता है. ActivitySpace
, सीन ग्राफ़ में टॉप-लेवल Entity
है.
ActivitySpace, तीन डाइमेंशन वाली जगह को दिखाता है. इसमें राइट-हैंडेड कोऑर्डिनेट सिस्टम होता है. इसमें x-ऐक्सिस दाईं ओर, y-ऐक्सिस ऊपर की ओर, और z-ऐक्सिस ऑरिजिन के हिसाब से पीछे की ओर होता है. साथ ही, इसमें यूनिट के तौर पर मीटर का इस्तेमाल किया जाता है, जो असल दुनिया से मेल खाता है. ActivitySpace
की जगह कुछ हद तक मनमुताबिक होती है, क्योंकि उपयोगकर्ता ActivitySpace
की जगह को असल दुनिया में रीसेट कर सकते हैं. इसलिए, हमारा सुझाव है कि कॉन्टेंट को ऑरिजिन के हिसाब से रखने के बजाय, एक-दूसरे के हिसाब से रखें.
इकाइयों के साथ काम करना
SceneCore के लिए इकाइयां बहुत ज़रूरी होती हैं. उपयोगकर्ता को जो भी चीज़ें दिखती हैं और जिनसे वह इंटरैक्ट करता है वे पैनल, 3D मॉडल वगैरह को दिखाने वाली इकाइयां होती हैं.
ActivitySpace
सीन ग्राफ़ का टॉप-लेवल नोड है. इसलिए, डिफ़ॉल्ट रूप से सभी नई इकाइयों को सीधे ActivitySpace
में रखा जाता है. सीन ग्राफ़ में मौजूद इकाइयों की जगह बदलने के लिए, parent
को सेट करें या addChild()
का इस्तेमाल करें.
सभी इकाइयों के लिए, कुछ डिफ़ॉल्ट व्यवहार होते हैं. जैसे, पोज़िशन, रोटेशन या दिखने की स्थिति बदलना. Entity
की कुछ खास सबक्लास, जैसे कि GltfModelEntity
, में कुछ अतिरिक्त व्यवहार होते हैं. ये व्यवहार सबक्लास को सपोर्ट करते हैं.
इकाइयों में बदलाव करना
जब बेस Entity
क्लास से जुड़ी किसी Entity
प्रॉपर्टी में बदलाव किया जाता है, तो यह बदलाव उससे जुड़ी सभी चाइल्ड प्रॉपर्टी में भी लागू हो जाता है. उदाहरण के लिए, पैरंट Entity
के Pose
में बदलाव करने से, उसकी सभी चाइल्ड यूनिट में एक जैसा बदलाव होता है. चाइल्ड Entity
में बदलाव करने से, पैरंट पर कोई असर नहीं पड़ता.
Pose
, 3D स्पेस में मौजूद इकाई की जगह और रोटेशन को दिखाता है. जगह की जानकारी, x, y, z की संख्यात्मक स्थितियों वाली Vector3
होती है. रोटेशन को 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()
का इस्तेमाल करें. इससे Entity
का आकार नहीं बदलेगा.
// Double the size of the entity entity.setScale(2f)
इकाइयों में सामान्य व्यवहार जोड़ना
इन कॉम्पोनेंट का इस्तेमाल करके, इकाइयों में सामान्य व्यवहार जोड़ा जा सकता है:
MovableComponent
: इससे उपयोगकर्ता, इकाइयों को एक जगह से दूसरी जगह ले जा सकता हैResizableComponent
: इसकी मदद से उपयोगकर्ता, एक जैसे यूज़र इंटरफ़ेस (यूआई) पैटर्न का इस्तेमाल करके इकाइयों का साइज़ बदल सकता हैInteractableComponent
: इससे आपको कस्टम इंटरैक्शन के लिए इनपुट इवेंट कैप्चर करने की सुविधा मिलती है
कॉम्पोनेंट को इंस्टैंशिएट करने के लिए, Session
क्लास में सही क्रिएशन मेथड का इस्तेमाल करना ज़रूरी है. उदाहरण के लिए, ResizableComponent
बनाने के लिए, कॉल
ResizableComponent.create()
करें.
किसी Entity
में कॉम्पोनेंट के खास व्यवहार को जोड़ने के लिए, addComponent()
तरीके का इस्तेमाल करें.
MovableComponent
का इस्तेमाल करके, किसी इकाई को उपयोगकर्ता के हिसाब से मूव करने की सुविधा चालू करना
MovableComponent
की मदद से, Entity
को उपयोगकर्ता की ज़रूरत के हिसाब से जगह बदलने की अनुमति मिलती है.
डेकोरेशन के साथ इंटरैक्ट करने पर, कॉम्पोनेंट को मूवमेंट इवेंट भेजे जाते हैं. MovableComponent.createSystemMovable()
की मदद से बनाया गया सिस्टम का डिफ़ॉल्ट बिहेवियर, डेकोरेशन को खींचने पर आपके Entity
को मूव करता है:
val movableComponent = MovableComponent.createSystemMovable(session) entity.addComponent(movableComponent)
वैकल्पिक scaleInZ
पैरामीटर (डिफ़ॉल्ट रूप से, true
पर सेट होता है) की मदद से, उपयोगकर्ता से दूर ले जाने पर इकाई अपने-आप स्केल हो जाती है. यह ठीक उसी तरह काम करता है जिस तरह होम स्पेस में सिस्टम, पैनल को स्केल करता है.
इकाई कॉम्पोनेंट सिस्टम के "कैस्केडिंग" नेचर की वजह से, पैरंट के स्केल का असर उसके सभी चाइल्ड पर पड़ेगा.
यह भी तय किया जा सकता है कि इकाई को किस तरह की सतह पर ऐंकर किया जा सकता है. जैसे, हॉरिज़ॉन्टल या वर्टिकल सतहें या टेबल, दीवार या छत जैसी खास सिमैंटिक सतहें. ऐंकर के विकल्प तय करने के लिए, MovableComponent
बनाते समय AnchorPlacement
का सेट तय करें. इस उदाहरण में, ऐसी इकाई के बारे में बताया गया है जिसे किसी भी फ़्लोर या टेबल की हॉरिज़ॉन्टल सतह पर ले जाया जा सकता है और ऐंकर किया जा सकता है:
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
का इस्तेमाल करके, किसी Entity को उपयोगकर्ता के हिसाब से साइज़ बदलने की सुविधा देना
ResizableComponent
की मदद से, उपयोगकर्ता Entity
का साइज़ बदल सकते हैं. ResizableComponent
में विज़ुअल इंटरैक्शन के ऐसे संकेत शामिल होते हैं जो उपयोगकर्ता को Entity
का साइज़ बदलने का न्योता देते हैं. ResizableComponent
बनाते समय, कम से कम या ज़्यादा से ज़्यादा साइज़ (मीटर में) तय किया जा सकता है. आपके पास साइज़ बदलते समय, आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) तय करने का विकल्प भी होता है. इससे चौड़ाई और लंबाई, एक-दूसरे के हिसाब से बदलती हैं.
ResizableComponent
बनाते समय, ऐसा ResizableComponent
तय करें जो अपडेट इवेंट को हैंडल करता हो.resizeEventListener
आपके पास अलग-अलग ResizeState
इवेंट पर प्रतिक्रिया देने का विकल्प होता है. जैसे, RESIZE_STATE_ONGOING
या RESIZE_STATE_END
.
यहां SurfaceEntity
पर, तय किए गए आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) के साथ ResizableComponent
का इस्तेमाल करने का एक उदाहरण दिया गया है:
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
बनाते समय, ऐसा लिसनर तय करें जो इनपुट इवेंट को स्वीकार करे.
जब उपयोगकर्ता कोई इनपुट कार्रवाई करता है, तो लिसनर को 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.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)