Membuat dan berinteraksi dengan scene

Halaman ini berisi tips umum untuk membuat Scene dan berinteraksi dengannya.

Merender scene tanpa AR

Class SceneView memungkinkan Anda merender tampilan 3D tanpa memerlukan penggunaan kamera perangkat atau sesi AR. Hal ini berguna untuk melihat pratinjau objek 3D di aplikasi Anda tanpa AR, atau memberikan fungsi alternatif pada perangkat yang tidak mendukung AR.

Secara default, SceneView tidak menampilkan gambar dari kamera AR dan menggunakan latar belakang hitam. Untuk mengubah warna latar belakang, Anda dapat memanggil view.setBackgroundColor() atau menentukan warna latar belakang dalam tata letak seperti yang ditunjukkan di bawah:

<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"/>

Node Camera scene ditempatkan di asal (posisi 0,0,0) dan menghadap ke depan (arah 0,0,-1). Karena posisi dan rotasi kamera tidak terikat dengan pelacakan gerakan AR, Anda dapat mengubah posisi atau menganimasikannya seperti node lain.

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

Interaksi

Menangani sentuh pengguna

Saat pengguna menyentuh layar, Sceneform menyebarkan peristiwa sentuh ke pengendali dan pemroses peristiwa yang dilampirkan ke node dan tampilan. Perilaku ini mirip dengan cara peristiwa sentuh disebarkan ke tampilan dan grup tampilan di Android. Berikut urutan penerapannya:

  1. Peristiwa ini dikirim ke pemroses yang ditambahkan di scene.addOnPeekTouchListener().

    Hal ini mirip dengan viewGroup.intercept(), kecuali bahwa adegan pada pemroses sentuh sekilas tidak dapat menggunakan peristiwa tersebut.

  2. Peristiwa diteruskan ke node pertama yang berpotongan dengan sinar.

    • Node dapat menggunakan peristiwa dengan menentukan set metode onTouchEvent() yang menampilkan true.
    • Jika metode onTouchEvent() menampilkan false, atau tidak ada pemroses yang ditentukan, peristiwa akan disebarkan ke induk node. Proses ini berlanjut hingga peristiwa dipakai, atau tampilan tercapai.
  3. Terakhir, jika tidak ada pemroses yang menggunakan peristiwa, peristiwa akan diteruskan ke scene.onTouchListener().

Mendeteksi gestur

ArFragment telah dilengkapi dukungan untuk gestur ketuk (pilihan), tarik (pindah), cubit (skala), dan putar (putar).

Misalnya, lihat HelloSceneformActivity.java dalam aplikasi contoh HelloSceneform.

Membuat node kustom

Serupa dengan membuat tampilan Android kustom, Anda dapat membuat node kustom dengan membuat subclass Node. Berikut adalah beberapa situasi saat Anda mungkin ingin membuat node kustom:

  • Anda ingin mengakses peristiwa dalam siklus proses node, seperti onUpdate(), onActivate, dan onDeactivate().
  • Anda ingin membuat node yang terdiri dari sekelompok node.
  • Anda menduplikasi banyak kode, dan dapat memfaktorkannya ke subclass.

Untuk contoh, lihat Planet.java di aplikasi contoh Tata Surya.

Menganimasikan node

Ada dua cara untuk menganimasikan node:

Menganimasikan dengan ObjectAnimator

Berikut adalah contoh yang menganimasikan intensitas sorotan:

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();

Untuk informasi selengkapnya, lihat Menganimasikan dengan ObjectAnimator.

Menganimasikan di onUpdate

Ganti onUpdate() node untuk menganimasikan frame-nya ke frame. Contoh berikut, dari Planet.java pada aplikasi contoh Tata Surya, menyesuaikan kartu info setiap frame untuk menghadap ke pengguna, bahkan saat planet berputar.

@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);
}

Tambahkan lampu

Lights dapat dilampirkan ke node mana pun dalam tampilan. Secara default, setiap scene Sceneform menyertakan node Sun, yang memiliki lampu arah yang dipasang.

Anda dapat mengubah matahari atau menambahkan lampu Anda sendiri ke sebuah adegan. Contoh berikut menambahkan sorotan:

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

Lalu, panggil setLight() untuk melampirkannya ke node.

Menyesuaikan visualisasi bidang

Secara default, scene memiliki PlaneRenderer yang menandai Planes saat terdeteksi oleh ARCore. Tampilannya terlihat seperti ini:

Anda dapat mengubah material dan tekstur default yang digunakan untuk merender bidang yang terdeteksi. Berikut cara mengubah tekstur:

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));
        });

Bayangan

Bayangan membuat hasil render terlihat didasarkan pada dunia dan memberikan kesan kedalaman dan ruang kepada pengguna.

Dalam Sceneform, ada objek yang dapat mentransmisikan bayangan dan objek yang dapat menerima bayangan.

  • Lights dan Renderables dapat memunculkan bayangan

    Secara default, transmisi bayangan diaktifkan di matahari, tetapi tidak untuk lampu. Panggil setShadowCastingEnabled() untuk mengaktifkannya.

  • Renderables dan PlaneRenderer dapat menerima bayangan.

    Secara default, penerimaan bayangan diaktifkan. Panggil setShadowReceiver() untuk menonaktifkannya.

Jika dapat dirender dan melakukan transmisi bayangan, bayangan dapat muncul sendiri.