إنشاء الكيانات والتحكّم فيها وإدارتها

تتيح لك حزمة تطوير البرامج (SDK) لتجربة الواقع المعزّز من Jetpack استخدام Jetpack SceneCore لإنشاء نُسخ Entity والتحكّم فيها وإدارتها، مثل النماذج الثلاثية الأبعاد والفيديوهات المجسمة وPanelEntity باستخدام Jetpack SceneCore.

يتّبع Jetpack SceneCore نمطَين معماريَين شائعَين لدعم تطوير المحتوى المجسم: رسم بياني للمشهد ونظام العناصر والمكونات (ECS).

استخدام مخطّط المشهد لإنشاء العناصر والتحكّم فيها

لإنشاء عناصر والتحكّم فيها في الفضاء الثلاثي الأبعاد، عليك استخدام واجهة برمجة التطبيقات Session في Jetpack SceneCore للوصول إلى الرسم البياني للمشهد. يتوافق مخطّط المشهد مع الواقع الذي يعيشه المستخدم، ويتيح لك تنظيم الكيانات الثلاثية الأبعاد، مثل الألواح والنماذج الثلاثية الأبعاد، في بنية هرمية، كما يتيح لك الاحتفاظ بحالة هذه الكيانات.

بعد الحصول على إذن الوصول إلى مخطّط المشهد، يمكنك استخدام واجهات برمجة التطبيقات في Jetpack Compose لإنشاء واجهة مستخدم مكانية (مثل، SpatialPanel وOrbiter) داخل مخطّط المشهد. بالنسبة إلى المحتوى الثلاثي الأبعاد، مثل النماذج الثلاثية الأبعاد، يمكنك الوصول إلى الجلسة مباشرةً. لمزيد من المعلومات، يُرجى الاطّلاع على لمحة عن ActivitySpace في هذه الصفحة.

نظام مكونات الكيان

يتبع نظام العناصر المكوّنة مبدأ التركيب على الاستبدال. يمكنك توسيع نطاق سلوك الكيانات من خلال إرفاق مكونات تحدّد السلوك، ما يتيح لك تطبيق السلوك نفسه على أنواع مختلفة من الكيانات. لمزيد من المعلومات، اطّلِع على إضافة سلوك شائع إلى الكيانات في هذه الصفحة.

لمحة عن ActivitySpace

يحتوي كل Session على ActivitySpace يتم إنشاؤه تلقائيًا باستخدام Session. ActivitySpace هو Entity من المستوى الأعلى في مخطّط المشهد.

يمثّل ActivitySpace مساحة ثلاثية الأبعاد باستخدام نظام إحداثيات يعتمد على اليد اليمنى (يشير محور x إلى اليمين، ويشير محور y إلى أعلى، ويشير محور z إلى الخلف بالنسبة إلى نقطة الأصل) وباستخدام متر للوحدات التي تتطابق مع الواقع. إنّ موضع ActivitySpace عشوائي إلى حدٍ ما (لأنّه يمكن للمستخدمين إعادة ضبط موضع ActivitySpace في العالم الحقيقي)، لذلك ننصح بوضع المحتوى بالنسبة إلى بعضها البعض بدلاً من وضعه بالنسبة إلى الموضع الأصلي.

العمل مع الكيانات

الكيانات هي العنصر الأساسي في SceneCore. إنّ معظم ما يراه المستخدم ويتفاعل معه هو عناصر تمثّل الألواح والنماذج الثلاثية الأبعاد وغير ذلك.

بما أنّ ActivitySpace هي العقدة ذات المستوى الأعلى في الرسم البياني للمشهد، يتم تلقائيًا وضع كل الكيانات الجديدة مباشرةً في ActivitySpace. يمكنك إعادة تحديد مواضع الكيانات على طول الرسم البياني للمشهد من خلال استدعاء setParent أو addChild.

تتضمّن العناصر بعض السلوكيات التلقائية للعناصر العامة التي تنطبق على جميع العناصر، مثل تغيير الموضع أو التدوير أو مستوى الرؤية. تتضمّن Entity الفئات الفرعية المحدّدة، مثل GltfEntity، Entity سلوكيات إضافية تتوافق مع الفئة الفرعية.

التلاعب بالكيانات

عند إجراء تغيير على موقع Entity ينتمي إلى فئة Entity الأساسية، سيتم تطبيق التغيير على جميع المواقع الفرعية التابعة له. على سبيل المثال، يؤدي تعديل Pose لعنصر رئيسي Entity إلى تعديل كل العناصر الفرعية له بالطريقة نفسها. لا يؤثّر إجراء تغيير في وحدة تنظيمية فرعية Entity في الوحدة التنظيمية الرئيسية.

يمثّل الرمز Pose موقع الكيان واتجاه دورانه في الفضاء الثلاثي الأبعاد. الموقع هو 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: السماح للمستخدم بتغيير حجم الكيانات باستخدام أنماط واجهة مستخدِم متّسقة
  • InteractableComponent: يتيح لك تسجيل أحداث الإدخال للتفاعلات المخصّصة.

يجب إنشاء العناصر من خلال طريقة الإنشاء المناسبة في صف Session. على سبيل المثال، لإنشاء ResizableComponent، اتصل بالرقم session.createResizableComponent().

لإضافة سلوك المكوّن المحدّد إلى Entity، استخدِم الطريقة addComponent().

استخدِم MovableComponent لجعل عنصر Entity قابلاً للتحريك من قِبل المستخدم.

يسمح الرمز 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 لجعل عنصر Entity قابلاً للتغيير من قِبل المستخدم.

يتيح الرمز 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)