Panduan memulai untuk Google Cardboard untuk Android NDK

Panduan ini menunjukkan cara menggunakan Cardboard SDK Android untuk menciptakan pengalaman Virtual Reality (VR) Anda sendiri.

Anda dapat menggunakan Cardboard SDK untuk mengubah ponsel cerdas menjadi platform VR. Smartphone dapat menampilkan adegan 3D dengan rendering stereoskopik, melacak dan bereaksi terhadap gerakan kepala, dan berinteraksi dengan aplikasi dengan mendeteksi ketika pengguna menekan tombol penampil.

Untuk memulai, Anda akan menggunakan HelloCardboard, game demo yang menunjukkan inti yang lebih canggih dari Cardboard SDK. Dalam {i>game<i}, pengguna berkeliling dunia virtual untuk menemukan dan mengumpulkan objek. Laporan ini menunjukkan cara:

  • Menyiapkan lingkungan pengembangan
  • Mendownload dan membangun aplikasi demo
  • Pindai kode QR penampil Cardboard untuk menyimpan parameternya
  • Lacak gerakan kepala pengguna
  • Merender gambar stereoskopik dengan menyetel matriks proyeksi tampilan yang benar untuk setiap mata

HelloCardboard menggunakan Android NDK. Setiap metode native:

  • Ditetapkan secara unik ke metode class HelloCardboardApp, atau
  • Membuat atau menghapus instance class tersebut

Menyiapkan lingkungan pengembangan

Persyaratan hardware:

  • Perangkat Android yang menjalankan Android 8.0 "Oreo" (API level 26) atau yang lebih tinggi
  • Penampil karton

Persyaratan software:

  • Android Studio versi 2022.1.1 "Electric Eel" atau yang lebih tinggi
  • Android SDK 13.0 "Tiramisu" (API level 33) atau yang lebih tinggi
  • Framework Android NDK versi terbaru

    Untuk meninjau atau mengupdate SDK yang terinstal, buka Preferensi > Tampilan dan Perilaku

    Setelan Sistem > Android SDK di Android Studio.

Mendownload dan membangun aplikasi demo

Cardboard SDK dibuat menggunakan Vulkan yang telah dikompilasi sebelumnya file header untuk setiap shader. Langkah-langkah untuk membuat file header dari awal dapat ditemukan di sini.

  1. Jalankan perintah berikut untuk meng-clone Cardboard SDK dan demo HelloCardboard aplikasi dari GitHub:

    git clone https://github.com/googlevr/cardboard.git
  2. Di Android Studio, pilih Open an existing Android Studio Project, lalu pilih direktori tempat Cardboard SDK dan aplikasi demo HelloCardboard di-clone.

    Kode Anda akan muncul di jendela Project di Android Studio.

  3. Untuk merakit Cardboard SDK, klik dua kali opsi susun dalam Folder cardboard/:sdk/Tasks/build di tab Gradle (View > Tool Windows > Gradle).

  4. Jalankan aplikasi demo HelloCardboard di ponsel dengan memilih Jalankan > Run... dan pilih target hellocardboard-android.

Pindai kode QR

Untuk menyimpan parameter perangkat, pindai kode QR di penampil Cardboard:

Jika pengguna menekan "SKIP" dan tidak ada parameter yang disimpan sebelumnya, penyimpanan Cardboard Google Cardboard v1 (diluncurkan di Google I/O 2014).

Coba demo

Di HelloCardboard, Anda akan mencari dan mengumpulkan bola geodesi di ruang 3D.

Untuk menemukan dan mengumpulkan bola dunia:

  1. Gerakkan kepala Anda ke segala arah sampai melihat bentuk mengambang.

  2. Lihat tepat ke bola dunia. Ini menyebabkannya berubah warna.

  3. Tekan tombol penampil Cardboard untuk "mengumpulkan" lingkup bisnis.

Mengonfigurasi perangkat

Ketika pengguna mengetuk ikon roda gigi untuk beralih penampil Cardboard, nativeSwitchViewer dipanggil. nativeSwitchViewer panggilan CardboardQrCode_scanQrCodeAndSaveDeviceParams, yang membuka jendela untuk memindai kode QR penonton. Distorsi lensa penampil dan parameter lainnya diperbarui sekali kode QR dipindai.

// Called by JNI method
void HelloCardboardApp::SwitchViewer() {
  CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}

Mengaktifkan emulator Android Studio x86

Untuk membangun emulator Android Studio x86, hapus baris berikut dari build.gradle file di SDK dan Sample:

abiFilters 'armeabi-v7a', 'arm64-v8a'

Tindakan ini akan mengaktifkan semua ABI dan akan meningkatkan ukuran file yang dihasilkan secara signifikan File .aar. Lihat ABI Android untuk informasi selengkapnya.

Pelacakan gerak kepala

Membuat pelacak kepala

Pelacak head dibuat sekali dalam konstruktor HelloCardboardApp:

HelloCardboardApp::HelloCardboardApp(JavaVM* vm, jobject obj, jobject asset_mgr_obj) {
  Cardboard_initializeAndroid(vm, obj); // Must be called in constructor
  head_tracker_ = CardboardHeadTracker_create();
}

Saat VrActivity dibuat, instance class HelloCardboardApp akan dibuat dengan memanggil metode nativeOnCreate:

public void onCreate(Bundle savedInstance) {
  super.onCreate(savedInstance);
  nativeApp = nativeOnCreate(getAssets());
  //...
}

Menjeda dan melanjutkan pelacak kepala

Untuk menjeda, melanjutkan, dan menghancurkan pelacak kepala, CardboardHeadTracker_pause(head_tracker_), CardboardHeadTracker_resume(head_tracker_), dan CardboardHeadTracker_destroy(head_tracker_) harus dipanggil. Di kolom &quot;HelloCardboard&quot; kita memanggilnya di nativeOnPause, nativeOnResume, dan nativeOnDestroy:

// Code to pause head tracker in hello_cardboard_app.cc

void HelloCardboardApp::OnPause() { CardboardHeadTracker_pause(head_tracker_); }

// Call nativeOnPause in VrActivity
@Override
protected void onPause() {
  super.onPause();
  nativeOnPause(nativeApp);
  //...
}

// Code to resume head tracker in hello_cardboard_app.cc
void HelloCardboardApp::onResume() {
  CardboardHeadTracker_resume(head_tracker_);
  //...
}

// Call nativeOnResume in VrActivity
@Override
protected void onResume() {
  super.onResume();
  //...
  nativeOnResume(nativeApp);
}

// Code to destroy head tracker in hello_cardboard_app.cc
HelloCardboardApp::~HelloCardboardApp() {
  CardboardHeadTracker_destroy(head_tracker_);
  //...
}

// Call nativeOnDestroy in VrActivity
@Override
protected void onDestroy() {
  super.onDestroy();
  nativeOnDestroy(nativeApp);
  nativeApp = 0;
}

Distorsi lensa

Setiap kali Cardboard memindai kode QR baru, kode berikut akan membaca parameter yang disimpan. dan menggunakannya untuk membuat objek distorsi lensa, yang menerapkan distorsi lensa yang tepat ke konten yang dirender:

CardboardQrCode_getSavedDeviceParams(&buffer, &size);

CardboardLensDistortion_destroy(lens_distortion_);
lens_distortion_ = CardboardLensDistortion_create(
    buffer, size, screen_width_, screen_height_);

CardboardQrCode_destroy(buffer);

Rendering

Merender konten di Cardboard melibatkan hal-hal berikut:

  • Membuat tekstur
  • Mendapatkan matriks tampilan dan proyeksi untuk mata kiri dan kanan
  • Membuat perender dan menyetel mesh distorsi
  • Merender setiap frame

Membuat tekstur

Semua konten digambar di atas tekstur, yang dibagi menjadi beberapa bagian untuk mata kiri dan kanan. Bagian ini masing-masing diinisialisasi dalam _leftEyeTexture dan _rightEyeTexture.

void HelloCardboardApp::GlSetup() {
  LOGD("GL SETUP");

  if (framebuffer_ != 0) {
    GlTeardown();
  }

  // Create render texture.
  glGenTextures(1, &texture_);
  glBindTexture(GL_TEXTURE_2D, texture_);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screen_width_, screen_height_, 0,
               GL_RGB, GL_UNSIGNED_BYTE, 0);

  left_eye_texture_description_.texture = texture_;
  left_eye_texture_description_.left_u = 0;
  left_eye_texture_description_.right_u = 0.5;
  left_eye_texture_description_.top_v = 1;
  left_eye_texture_description_.bottom_v = 0;

  right_eye_texture_description_.texture = texture_;
  right_eye_texture_description_.left_u = 0.5;
  right_eye_texture_description_.right_u = 1;
  right_eye_texture_description_.top_v = 1;
  right_eye_texture_description_.bottom_v = 0;

  //...
  CHECKGLERROR("GlSetup");
}

Tekstur ini diteruskan sebagai parameter ke CardboardDistortionRenderer_renderEyeToDisplay.

Dapatkan matriks tampilan dan proyeksi untuk mata kiri dan kanan

Pertama, ambil matriks mata untuk mata kiri dan kanan:

CardboardLensDistortion_getEyeFromHeadMatrix(
    lens_distortion_, kLeft, eye_matrices_[0]);
CardboardLensDistortion_getEyeFromHeadMatrix(
    lens_distortion_, kRight, eye_matrices_[1]);
CardboardLensDistortion_getProjectionMatrix(
    lens_distortion_, kLeft, kZNear, kZFar, projection_matrices_[0]);
CardboardLensDistortion_getProjectionMatrix(
    lens_distortion_, kRight, kZNear, kZFar, projection_matrices_[1]);

Berikutnya, dapatkan mesh distorsi untuk setiap mata dan teruskan ke perender distorsi:

CardboardLensDistortion_getDistortionMesh(lens_distortion_, kLeft, &left_mesh);
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kRight, &right_mesh);

Buat perender dan setel mesh distorsi yang benar

Perender hanya perlu diinisialisasi sekali. Setelah perender dibuat, setel untuk mata kiri dan kanan sesuai dengan nilai mesh yang ditampilkan dari Fungsi CardboardLensDistortion_getDistortionMesh.

distortion_renderer_ = CardboardOpenGlEs2DistortionRenderer_create();
CardboardDistortionRenderer_setMesh(distortion_renderer_, &left_mesh, kLeft);
CardboardDistortionRenderer_setMesh(distortion_renderer_, &right_mesh, kRight);

Merender konten

Untuk setiap frame, ambil orientasi kepala saat ini dari CardboardHeadTracker_getPose:

CardboardHeadTracker_getPose(head_tracker_, monotonic_time_nano, &out_position[0], &out_orientation[0]);

Menggunakan orientasi head saat ini dengan matriks tampilan dan proyeksi untuk membuat tampilan matriks proyeksi untuk setiap mata dan {i>render<i} konten ke layar:

// Draw eyes views
for (int eye = 0; eye < 2; ++eye) {
  glViewport(eye == kLeft ? 0 : screen_width_ / 2, 0, screen_width_ / 2,
             screen_height_);

  Matrix4x4 eye_matrix = GetMatrixFromGlArray(eye_matrices_[eye]);
  Matrix4x4 eye_view = eye_matrix * head_view_;

  Matrix4x4 projection_matrix =
      GetMatrixFromGlArray(projection_matrices_[eye]);
  Matrix4x4 modelview_target = eye_view * model_target_;
  modelview_projection_target_ = projection_matrix * modelview_target;
  modelview_projection_room_ = projection_matrix * eye_view;

  // Draw room and target. Replace this to render your own content.
  DrawWorld();
}

Gunakan CardboardDistortionRenderer_renderEyeToDisplay untuk menerapkan distorsi pada konten, dan merender konten ke layar.

// Render
CardboardDistortionRenderer_renderEyeToDisplay(
    distortion_renderer_, /* target_display = */ 0, /* x = */ 0, /* y = */ 0,
    screen_width_, screen_height_, &left_eye_texture_description_,
    &right_eye_texture_description_);