Kurzanleitung für Google Cardboard für Android – NDK

In diesem Leitfaden erfährst du, wie du das Cardboard SDK verwendest. für Android, um eigene Virtual-Reality-Erlebnisse (VR) zu kreieren.

Mit dem Cardboard SDK kannst du ein Smartphone in eine VR-Plattform verwandeln. Ein Smartphone kann 3D-Szenen mit stereoskopischer Darstellung anzeigen, Kopfbewegungen verfolgen und darauf reagieren. und interagieren mit Apps, indem erkannt wird, wenn der Nutzer die Taste des VR-Geräts drückt.

Zum Einstieg verwenden Sie HelloCardboard, ein Demospiel, das die Kernfunktionen Funktionen des Cardboard SDK. In diesem Spiel erkunden die Nutzer eine virtuelle Welt, Gegenstände sammeln. Sie erfahren, wie Sie:

  • Entwicklungsumgebung einrichten
  • Demo-App herunterladen und erstellen
  • QR-Code eines Cardboard scannen, um die Parameter zu speichern
  • Die Kopfbewegungen der Nutzenden erfassen
  • Rendern stereoskopischer Bilder, indem für jedes Auge die korrekte Ansichtsprojektionsmatrix festgelegt wird

HelloCardboard verwendet das Android NDK. Für jede native Methode gilt:

  • Sie sind eindeutig auf eine HelloCardboardApp-Klassenmethode beschränkt oder
  • Erstellt oder löscht eine Instanz dieser Klasse

Entwicklungsumgebung einrichten

Hardwareanforderungen:

  • Android-Gerät mit Android 8.0 „Oreo“ (API-Level 26) oder höher
  • Cardboard-Gerät

Softwareanforderungen:

  • Android Studio-Version 2022.1.1 „Electric Eel“ oder höher
  • Android SDK 13.0 „Tiramisu“ (API-Level 33) oder höher
  • Aktuelle Version des Android NDK-Frameworks

    Wenn Sie installierte SDKs prüfen oder aktualisieren möchten, rufen Sie Einstellungen > Darstellung und Verhalten

    Systemeinstellungen > Android SDK in Android Studio

Demo-App herunterladen und erstellen

Das Cardboard SDK wird mit einem vorkompilierten Vulkan-Paket erstellt. Headerdatei für jeden Shader. Schritte zum Erstellen der Headerdateien von Grund auf finden Sie hier: hier.

  1. Führe den folgenden Befehl aus, um das Cardboard SDK und die HelloCardboard-Demo zu klonen App von GitHub:

    git clone https://github.com/googlevr/cardboard.git
  2. Wählen Sie in Android Studio Open an existing Android Studio Project (Vorhandenes Android Studio-Projekt öffnen) und dann Verzeichnis, in das das Cardboard SDK und die HelloCardboard-Demo-App geklont wurden.

    Ihr Code wird in Android Studio im Projektfenster angezeigt.

  3. Klicke doppelt auf die Option Zusammenbau Ordner cardboard/:sdk/Tasks/build im Gradle-Tab (Ansicht > Tool-Fenster > Gradle)

  4. Führen Sie die HelloCardboard-Demo-App auf Ihrem Smartphone aus. Wählen Sie dazu Ausführen > Ausführen... und wählen Sie das Ziel hellocardboard-android aus.

QR-Code scannen

Scanne den QR-Code auf der Cardboard-Brille, um die Geräteparameter zu speichern:

Wenn der Nutzer ÜBERSPRINGEN drückt und es keine bereits gespeicherten Parameter gibt, speichert die Karte in Cardboard. Parameter für Google Cardboard v1 (auf der Google I/O 2014 eingeführt).

Demo ansehen

In HelloCardboard suchen und sammeln Sie geodätische Kugeln im 3D-Raum.

So finden und sammeln Sie eine Kugel:

  1. Bewege deinen Kopf in eine beliebige Richtung, bis du eine schwebende Form siehst.

  2. Blicken Sie direkt in die Kugel. Dadurch ändert sich die Farbe.

  3. Drücke zum Aufnehmen die Taste der Cardboard-Brille. der Kugel.

Gerät konfigurieren

Wenn der Nutzer auf das Zahnradsymbol tippt, um zwischen den Cardboard-Geräten zu wechseln, wird die nativeSwitchViewer aufgerufen wird. nativeSwitchViewer Anrufe CardboardQrCode_scanQrCodeAndSaveDeviceParams, wodurch das Fenster zum Scannen geöffnet wird QR-Code angezeigt wird. Objektivverzerrung und andere Parameter des Betrachters werden einmal wird der QR-Code gescannt.

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

x86-Emulator von Android Studio aktivieren

Entfernen Sie zum Erstellen für den x86-Emulator von Android Studio die folgende Zeile aus build.gradle-Dateien im SDK und Beispiel:

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

Dadurch werden alle ABIs aktiviert und die generierten .aar-Datei. Siehe Android-ABIs .

Erfassung von Kopfbewegungen

Kopf-Tracker erstellen

Der Kopf-Tracker wird einmal im Konstruktor von HelloCardboardApp erstellt:

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

Beim Erstellen von VrActivity wird eine Instanz der Klasse HelloCardboardApp generiert. indem Sie die Methode nativeOnCreate aufrufen:

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

Kopf-Tracker pausieren und fortsetzen

Um den Kopf-Tracker zu pausieren, fortzusetzen und zu zerstören, CardboardHeadTracker_pause(head_tracker_), CardboardHeadTracker_resume(head_tracker_), und CardboardHeadTracker_destroy(head_tracker_) müssen jeweils aufgerufen werden. Im "HelloCardboard" werden sie in nativeOnPause, nativeOnResume und 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;
}

Objektivverzeichnung

Jedes Mal, wenn Cardboard einen neuen QR-Code scannt, werden die gespeicherten Parameter mit dem folgenden Code ausgelesen und erzeugt damit ein Objektiv mit Objektivverzeichnung, das die entsprechende den gerenderten Inhalt hinzufügen:

CardboardQrCode_getSavedDeviceParams(&buffer, &size);

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

CardboardQrCode_destroy(buffer);

Rendering

Das Rendern von Inhalten in Cardboard umfasst Folgendes:

  • Erstellen von Texturen
  • Ansichts- und Projektionsmatrizen für linkes und rechtes Auge abrufen
  • Renderer erstellen und Verzerrungsnetz festlegen
  • Jeden Frame rendern

Texturen erstellen

Der gesamte Inhalt wird auf eine Textur gezeichnet, die in Abschnitte für das linke und rechte Augen aufgeteilt ist. Diese Abschnitte werden in _leftEyeTexture bzw. _rightEyeTexture initialisiert.

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

Diese Texturen werden als Parameter an CardboardDistortionRenderer_renderEyeToDisplay übergeben.

Ansichts- und Projektionsmatrizen für linkes und rechtes Auge abrufen

Rufen Sie zunächst die Augenmatrizen für das linke und rechte Auge ab:

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

Rufen Sie als Nächstes das Verzerrungsnetz für jedes der Augen ab und übergeben Sie es an den Verzerrungs-Renderer:

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

Renderer erstellen und das richtige Verzerrungsnetz festlegen

Der Renderer muss nur einmal initialisiert werden. Legen Sie nach dem Erstellen des Renderers den neuen Verzerrungs-Mesh-Netzwerk für das linke und rechte Auge entsprechend den von der CardboardLensDistortion_getDistortionMesh.

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

Inhalt rendern

Rufen Sie für jeden Frame die aktuelle Kopfausrichtung von CardboardHeadTracker_getPose ab:

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

Verwenden Sie die aktuelle Kopfausrichtung mit den Ansichts- und Projektionsmatrizen, um eine Ansicht zu erstellen Projektionsmatrix für jedes der Augen und rendern Inhalte auf dem Bildschirm:

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

Mit CardboardDistortionRenderer_renderEyeToDisplay die Verzerrung anwenden und den Inhalt auf dem Bildschirm rendern.

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