Krótkie wprowadzenie do Google Cardboard na Androida NDK

Z tego przewodnika dowiesz się, jak korzystać z pakietu SDK Cardboard. na Androida do tworzenia własnych rozwiązań rzeczywistości wirtualnej.

Za pomocą pakietu SDK Cardboard możesz zamienić smartfona w platformę VR. Smartfon umożliwia wyświetlanie scen 3D z renderowaniem stereoskopowym, śledzenie ruchów głowy i reagowanie na nie, i interakcji z aplikacjami, wykrywając, kiedy użytkownik naciśnie przycisk na goglach.

Na początek skorzystaj z HelloCardboard – gry demonstracyjnej, która przedstawia podstawowe funkcje z pakietu SDK Cardboard. Gracze rozglądają się po wirtualnym świecie, aby znaleźć i zbierać obiekty. Pokazuje on, jak:

  • Konfigurowanie środowiska programistycznego
  • Pobierz i utwórz aplikację w wersji demonstracyjnej
  • Zeskanuj kod QR gogli Cardboard, aby zapisać jego parametry
  • Śledzenie ruchów głowy użytkownika
  • Renderuj obrazy stereoskopowe, ustawiając prawidłową macierz rzutowania obrazu dla każdego oka

HelloCardboard używa pakietu Android NDK. Każda metoda natywna:

  • powiązany wyłącznie z metodą klasy HelloCardboardApp lub
  • Tworzy lub usuwa instancję tej klasy

Konfigurowanie środowiska programistycznego

Wymagania sprzętowe:

.

Wymagania dotyczące oprogramowania:

  • Android Studio w wersji 2022.1.1 „Electric Eel” lub więcej
  • Pakiet SDK na Androida 13.0 „Tiramisu” (poziom interfejsu API 33) lub wyższy
  • Najnowsza wersja platformy Android NDK.

    Aby sprawdzić lub zaktualizować zainstalowane pakiety SDK, kliknij Preferencje > Wygląd i działanie

    Ustawienia systemu > Pakiet SDK do Androida w Android Studio.

Pobierz i utwórz aplikację w wersji demonstracyjnej

Pakiet SDK Cardboard został stworzony na podstawie wstępnie skompilowanego kodu Vulkan pliku nagłówkowego każdego modułu cieniowania. Instrukcje tworzenia plików nagłówka od zera znajdziesz w opisie tutaj.

  1. Uruchom następujące polecenie, aby skopiować pakiet SDK Cardboard i wersję demonstracyjną HelloCardboard z GitHuba:

    git clone https://github.com/googlevr/cardboard.git
  2. W Android Studio kliknij Otwórz istniejący projekt Android Studio, a potem wybierz katalogu, w którym sklonowano pakiet SDK Cardboard oraz aplikację demonstracyjną HelloCardboard.

    Kod pojawi się w oknie projektu w Android Studio.

  3. Aby złożyć pakiet SDK Cardboard, kliknij dwukrotnie opcję Zamontuj. cardboard/:sdk/Tasks/build i na karcie Gradle (Widok > Okna narzędzi > Gradle).

  4. Uruchom na telefonie aplikację demonstracyjną HelloCardboard, klikając Uruchom > Uruchom... i wybierz wartość docelową hellocardboard-android.

Zeskanuj kod QR

Aby zapisać parametry urządzenia, zeskanuj kod QR goglami Cardboard:

Jeśli użytkownik kliknie „POMIŃ” i nie ma żadnych zapisanych parametrów, Parametry Google Cardboard v1 (udostępnione na konferencji Google I/O 2014).

Wypróbuj wersję demonstracyjną

W HelloCardboard możesz wyszukiwać i zbierać kule geodezyjne w przestrzeni 3D.

Aby znaleźć i zebrać kulę:

  1. Poruszaj głową w dowolnym kierunku, aż zobaczysz pływający kształt.

  2. Patrz prosto w sferę. Powoduje to zmianę koloru.

  3. Naciśnij przycisk gogli Cardboard, aby zebrać dane w całej sferze.

Konfigurowanie urządzenia

Gdy użytkownik kliknie ikonę koła zębatego, aby przełączyć gogle Cardboard, nativeSwitchViewer . nativeSwitchViewer połączenia CardboardQrCode_scanQrCodeAndSaveDeviceParams, który otwiera okno skanowania. kod QR widza. Zniekształcenie obiektywu widza oraz inne parametry są aktualizowane raz kod QR zostanie zeskanowany.

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

Włącz emulator Android Studio x86

Aby utworzyć emulator Androida Studio x86, usuń ten wiersz z Pliki build.gradle w pakiecie SDK i Przykład:

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

Włącza to wszystkie interfejsy ABI i znacznie zwiększa rozmiar generowanych .aar. Zobacz interfejsy ABI Androida .

Monitorowanie ruchów głowy

Utwórz tracker aktywności

Tag śledzenia głowy jest tworzony raz w konstruktorze HelloCardboardApp:

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

Po utworzeniu klasy VrActivity generowana jest instancja klasy HelloCardboardApp wywołując metodę nativeOnCreate:

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

Wstrzymaj i wznów tracker na głowie

Aby wstrzymać, wznowić lub zniszczyć tracker, CardboardHeadTracker_pause(head_tracker_), CardboardHeadTracker_resume(head_tracker_), i CardboardHeadTracker_destroy(head_tracker_) muszą być wywoływane odpowiednio. W "HelloCardboard" dzwonimy za nativeOnPause, nativeOnResume i 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;
}

Zniekształcenie obiektywu

Za każdym razem, gdy Cardboard skanuje nowy kod QR, ten kod odczytuje zapisane parametry. i używa ich do utworzenia obiektu zniekształcenia w obiektywie, który stosuje odpowiednie zniekształcenia. do wyrenderowanej treści:

CardboardQrCode_getSavedDeviceParams(&buffer, &size);

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

CardboardQrCode_destroy(buffer);

renderowanie,

Renderowanie treści w aplikacji Cardboard obejmuje:

  • Tworzenie tekstur
  • Pobieranie matryc obrazu i rzutu dla lewej i prawej gałki ocznej
  • Tworzenie mechanizmu renderowania i konfigurowanie siatki zniekształceń
  • Renderowanie każdej klatki

Tworzenie tekstur

Cała zawartość jest narysowana na teksturze, która jest podzielona na sekcje dla lewego i prawego oka. Te sekcje są zainicjowane odpowiednio w _leftEyeTexture i _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");
}

Te tekstury są przekazywane jako parametry do funkcji CardboardDistortionRenderer_renderEyeToDisplay.

Pobierz macierze obrazu i projekcji dla lewego i prawego oka

Najpierw pobierz macierze dla lewego i prawego oka:

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

Następnie pobierz siatki zniekształceń dla każdego oka i przekaż je do mechanizmu renderowania zniekształceń:

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

Tworzenie mechanizmu renderowania i ustawianie prawidłowej siatki zniekształceń

Mechanizm renderowania wystarczy zainicjować tylko raz. Po utworzeniu mechanizmu renderowania ustaw nowy dla lewego i prawego oka zgodnie z wartościami siatki zwróconymi przez CardboardLensDistortion_getDistortionMesh.

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

Renderowanie treści

Dla każdej klatki pobierz bieżącą orientację głowy z CardboardHeadTracker_getPose:

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

Aby utworzyć widok, użyj bieżącej orientacji głowy z matrycami widoku i projekcji. matrycy projekcji dla każdego oczu i renderują zawartość ekranu:

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

Aby zastosować zniekształcenie, użyj funkcji CardboardDistortionRenderer_renderEyeToDisplay poprawienie treści i wyświetlenie jej na ekranie.

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