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

أجهزة XR المشمولة
تساعدك هذه الإرشادات في إنشاء تجارب لهذه الأنواع من أجهزة XR.
سماعات الرأس بنظام الواقع الممتد
نظارات سلكية بنظام الواقع الممتد

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

تستخدم Jetpack SceneCore نمطَين شائعَين للتصميم المعماري من أجل توفير الدعم لتطوير التطبيقات الثلاثية الأبعاد، وهما: مخطط المشهد ونظام الكيانات والمكونات (ECS).

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

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

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

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

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

لمحة عن ActivitySpace

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

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

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

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

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

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

تعديل الكيانات

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

يمثّل Pose الموقع الجغرافي والتدوير الخاصَّين بالكيان ضمن المساحة الثلاثية الأبعاد. الموقع الجغرافي هو 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: يسمح للمستخدم بتغيير حجم العناصر باستخدام أنماط واجهة مستخدم متسقة
  • 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، حدِّد أداة معالجة تتلقّى أحداث الإدخال. عندما ينفّذ المستخدم أي إجراء إدخال، سيتم استدعاء أداة معالجة الأحداث مع معلومات الإدخال المقدَّمة في المَعلمة 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.RIGHT) {
            entity.setScale(1.5f)
        } else if (it.pointerType == InputEvent.Pointer.LEFT) {
            entity.setScale(0.5f)
        }
    }
}
entity.addComponent(interactableComponent)

إنشاء تصاميم ثلاثية الأبعاد مخصّصة في وقت التشغيل

تتيح لك واجهة برمجة التطبيقات Custom Mesh API إنشاء أشكال ثلاثية الأبعاد آليًا مباشرةً في الرمز البرمجي، بدلاً من تحميل مواد عرض ثابتة مثل ملفات glTF. من خلال إنشاء أشكال هندسية مخصّصة أثناء التنفيذ، يمكنك عرض بيانات إجرائية وأشكال مخصّصة ديناميكية وبيئات ثلاثية الأبعاد تبدو لانهائية، مثل التضاريس التي يتم إنشاؤها باستمرار أثناء استكشاف المستخدمين لها. بالإضافة إلى ذلك، يساهم إنشاء الشبكات في وقت التشغيل في تقليل أحجام الملفات الثنائية من خلال إلغاء الحاجة إلى تجميع عدد لا يحصى من الاختلافات في مادة عرض ثلاثية الأبعاد واحدة.