إنشاء مشهد والتفاعل معه

تحتوي هذه الصفحة على نصائح شائعة لإنشاء Scene والتفاعل معها.

عرض مشهد بدون الواقع المعزّز

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

بشكل تلقائي، لا يعرض SceneView الصورة من كاميرا الواقع المعزّز ويستخدم خلفية سوداء. لتغيير لون الخلفية، يمكنك طلب view.setBackgroundColor() أو تحديد لون خلفية في التنسيق على النحو الموضّح أدناه:

<com.google.ar.sceneform.SceneView
    android:id="@+id/scene_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/deep_teal"/>

يتم وضع عقدة Camera للمنظر في نقطة الانطلاق (الموضع 0,0,0) باتجاه الأمام (الاتجاه 0,0,-1). نظرًا لعدم ارتباط موضع الكاميرا ودورانها بتتبُّع الحركة في الواقع المعزّز، يمكنك تغيير موضعها أو تحريكها مثل أي عُقدة أخرى.

Camera camera = sceneView.getScene().getCamera();
camera.setLocalRotation(Quaternion.axisAngle(Vector3.right(), -30.0f));

التفاعلات

التعامل مع لمسة المستخدم

عندما يلمس المستخدم الشاشة، ينشر Sceneform حدث اللمس على معالجات الحدث والمستمعين المرفقين بالعُقد والمشهد. يشبه هذا السلوك كيفية نشر أحداث اللمس في طرق العرض ومجموعات البيانات في نظام التشغيل Android. في ما يلي ترتيب انتشار:

  1. يتم إرسال الحدث إلى أي مستمع تمت إضافته في scene.addOnPeekTouchListener().

    يتشابه هذا مع viewGroup.intercept()، باستثناء أن المشاهد الذي لا يتوفّر لديه مشاهِد يمكن أن يشاهد الحدث.

  2. يتم تمرير الحدث إلى العقدة الأولى التي تتقاطع معها الشعاع.

    • يمكن أن تحلّ العُقدة الحدث من خلال تحديد مجموعة طرق onTouchEvent() التي تعرض true.
    • إذا عرضت الطريقة onTouchEvent() القيمة false، أو لم يتم تحديد أي مستمع، يتم نشر الحدث إلى العقدة الرئيسية. وتستمر هذه العملية حتى يتم استهلاك الحدث أو يتم الوصول إلى المشهد.
  3. أخيرًا، إذا لم يشاهد أي مستمع الحدث، يتم تمريره إلى scene.onTouchListener().

رصد الإيماءات

تم تضمين دعم ArFragment للنقر (الاختيار) والسحب (النقل) والتكبير (التصغير) والتوسّط (التدوير) واللف (التدوير).

على سبيل المثال، يمكنك الاطّلاع على HelloSceneformActivity.java في نموذج تطبيق HelloSceneform.

إنشاء عُقد مخصّصة

كما هو الحال مع إنشاء طرق عرض Android المخصصة، يمكنك إنشاء عُقد مخصصة من خلال الفئة الفرعية Node. في ما يلي بعض الحالات التي قد تحتاج فيها إلى إنشاء عقدة مخصّصة:

  • تريد الوصول إلى الأحداث في مراحل نشاط العقدة، مثل onUpdate() وonActivate وonDeactivate().
  • تريد إنشاء عقدة تتألف من مجموعة من العُقد.
  • أنت تنسخ الكثير من الرمز، ويمكنك تحليله إلى فئة فرعية.

للحصول على مثال، يمكنك الاطّلاع على Planet.java في تطبيق نموذج النظام الشمسي.

تحريك العُقد

ثمة طريقتان لتحريك العُقد:

الصور المتحركة باستخدام ObjectAnimator

في ما يلي مثال يوضّح درجة شدة الضوء:

final int durationInMilliseconds = 1000;
final float minimumIntensity = 1000.0f;
final float maximumIntensity = 3000.0f;
ValueAnimator intensityAnimator =
    ObjectAnimator.ofFloat(
        spotlightNode.getLight(), "intensity", minimumIntensity, maximumIntensity);
intensityAnimator.setDuration(durationInMilliseconds);
intensityAnimator.setRepeatCount(ValueAnimator.INFINITE);
intensityAnimator.setRepeatMode(ValueAnimator.REVERSE);
intensityAnimator.start();

لمزيد من المعلومات، يُرجى الاطّلاع على الصور المتحركة باستخدام ObjectAnimator.

المؤثرات الحركية في onUpdate

يمكنك إلغاء onUpdate() العقدة لتحريك إطارها إلى الإطار. في المثال التالي، من Planet.java في نموذج نموذج النظام الشمسي، يعدِّل بطاقة المعلومات في كل إطار لمواجهة المستخدم، حتى أثناء تدوير الكوكب.

@Override
public void onUpdate(FrameTime frameTime) {
  Vector3 cameraPosition = getScene().getCamera().getWorldPosition();
  Vector3 cardPosition = infoCard.getWorldPosition();
  Vector3 direction = Vector3.subtract(cameraPosition, cardPosition);
  Quaternion lookRotation = Quaternion.lookRotation(direction, Vector3.up());
  infoCard.setWorldRotation(lookRotation);
}

إضافة أضواء

يمكن إرفاق Lights بأي عقدة في المشهد. يحتوي كل مشهد Sceneform تلقائيًا على عُقدة Sun مرتبطة بضوء اتجاهي.

يمكنك تعديل ضوء الشمس أو إضافة مصابيحك الخاصة إلى مشهد. في ما يلي مثال بارز:

Light spotLightYellow =
    Light.builder(this, Light.Type.FOCUSED_SPOTLIGHT)
        .setColor(new Color(android.graphics.Color.YELLOW))
        .setShadowCastingEnabled(true)
        .build();

ثم اطلب setLight() لإرفاقه بعقدة.

تخصيص التمثيل البصري للطائرة

يحتوي المشهد تلقائيًا على رمز PlaneRenderer يُميّز Planes عندما يرصدها ARCore. يبدو كما يلي:

يمكنك تعديل المادة والزخارف التلقائية المستخدَمة لعرض الطائرات التي تم اكتشافها. في ما يلي كيفية تغيير النسيج:

Texture.Sampler sampler =
        Texture.Sampler.builder()
                .setMinFilter(Texture.Sampler.MinFilter.LINEAR)
                .setWrapMode(Texture.Sampler.WrapMode.REPEAT)
                .build();

// R.drawable.custom_texture is a .png file in src/main/res/drawable
Texture.builder()
        .setSource(this, R.drawable.custom_texture)
        .setSampler(sampler)
        .build()
        .thenAccept(texture -> {
          arSceneView.getPlaneRenderer()
                  .getMaterial().thenAccept(material ->
                  material.setTexture(PlaneRenderer.MATERIAL_TEXTURE, texture));
        });

الظلال

تساعد التظليل على إظهار العناصر القابلة للعرض في جميع أنحاء العالم وتمنح المستخدمين شعورًا بالعمق والفضاء.

في Ceneform، هناك كائنات يمكنها بث الظلال والكائنات التي يمكن أن تظلل الظلال.

  • بإمكان Lights وRenderables بث ظلال.

    يتم تلقائيًا تفعيل ميزة "التظليل" على الشمس، ولكن ليس للإضاءة. انقر على رمز الاتصال setShadowCastingEnabled() لتفعيله.

  • يمكن لـ Renderables وPlaneRenderer تلقي ظلال.

    يتم تفعيل استلام الظل تلقائيًا. يُرجى الاتصال بالرقم setShadowReceiver() لإيقافها.

وإذا كان البث القابل للعرض يلتقط ظلالاً ويتلقّاه، يمكنه إرسال تظليل على نفسه.