Z tego przewodnika dowiesz się, jak używać pakietu Cardboard SDK na Androida do tworzenia własnych środowisk wirtualnej rzeczywistości (VR).
Za pomocą pakietu Cardboard SDK możesz przekształcić smartfona w platformę VR. Smartfon może wyświetlać sceny 3D z renderowaniem stereoskopowym, śledzić ruchy głowy i na nie reagować oraz wchodzić w interakcję z aplikacjami, wykrywając, kiedy użytkownik naciśnie przycisk gogli.
Na początek użyj HelloCardboard, czyli gry demonstracyjnej, która prezentuje podstawowe funkcje pakietu Cardboard SDK. W grze użytkownicy rozglądają się po wirtualnym świecie, aby znaleźć i zebrać obiekty. Dowiesz się z niego, jak:
- Konfigurowanie środowiska programistycznego
- Pobieranie i tworzenie aplikacji demonstracyjnej
- Zeskanuj kod QR gogli Cardboard, aby zapisać ich parametry.
- śledzić ruchy głowy użytkownika,
- Renderowanie obrazów stereoskopowych przez ustawienie prawidłowej macierzy projekcji widoku dla każdego oka
HelloCardboard korzysta z pakietu Android NDK. Każda metoda natywna:
- jest jednoznacznie powiązana z metodą klasy
HelloCardboardApp
, - tworzy lub usuwa instancję tej klasy;
Konfigurowanie środowiska programistycznego
Wymagania sprzętowe:
- urządzeniach z Androidem w wersji 8.0 „Oreo” (interfejs API na poziomie 26) lub nowszej,
- Gogle Cardboard
Wymagania dotyczące oprogramowania:
- Android Studio w wersji 2024.1.2 „Koala Feature Drop” lub nowszej
- Android SDK 15.0 „Vanilla Ice Cream” (API na poziomie 35) lub nowszy
najnowsza wersja platformy Android NDK;
Aby sprawdzić lub zaktualizować zainstalowane pakiety SDK, kliknij Ustawienia > Wygląd i zachowanie.
W Android Studio wybierz System Settings (Ustawienia systemu) > Android SDK (Pakiet SDK Androida).
Pobieranie i tworzenie aplikacji demonstracyjnej
Pakiet Cardboard SDK jest tworzony przy użyciu wstępnie skompilowanego pliku nagłówkowego Vulkan dla każdego shadera. Instrukcje tworzenia plików nagłówkowych od zera znajdziesz tutaj.
Aby sklonować pakiet Cardboard SDK i aplikację demonstracyjną HelloCardboard z GitHub, uruchom to polecenie:
git clone https://github.com/googlevr/cardboard.git
W Android Studio wybierz Open an existing Android Studio Project (Otwórz istniejący projekt Android Studio), a następnie wybierz katalog, do którego sklonowano pakiet Cardboard SDK i przykładową aplikację HelloCardboard.
Kod pojawi się w oknie Projekt w Androidzie Studio.
Aby złożyć pakiet Cardboard SDK, na karcie Gradle (Widok > Okna narzędzi > Gradle) w folderze cardboard/:sdk/Tasks/build kliknij dwukrotnie opcję assemble.
Uruchom aplikację demonstracyjną HelloCardboard na telefonie, klikając Uruchom > Uruchom... i wybierając cel
hellocardboard-android
.
Zeskanuj kod QR
Aby zapisać parametry urządzenia, zeskanuj kod QR na okularach Cardboard:
Jeśli użytkownik naciśnie „POMIŃ” i nie ma wcześniej zapisanych parametrów, Cardboard zapisze parametry Google Cardboard w wersji 1 (wprowadzonej na konferencji Google I/O w 2014 r.).
Wypróbuj wersję demonstracyjną
W HelloCardboard będziesz szukać i zbierać sfery geodezyjne w przestrzeni 3D.
Aby znaleźć i zebrać kulę:
Poruszaj głową w dowolnym kierunku, aż zobaczysz pływający kształt.
Patrz prosto na sferę. Spowoduje to zmianę kolorów.
Naciśnij przycisk na goglach Cardboard, aby „zebrać” kulę.
Konfigurowanie urządzenia
Gdy użytkownik naciśnie ikonę koła zębatego, aby przełączyć gogle Cardboard, wywoływana jest metoda nativeSwitchViewer
. nativeSwitchViewer
połączeniaCardboardQrCode_scanQrCodeAndSaveDeviceParams
, które otwiera okno skanowania kodu QR widza. Zniekształcenie obiektywu i inne parametry widza są aktualizowane po zeskanowaniu kodu QR.
// Called by JNI method
void HelloCardboardApp::SwitchViewer() {
CardboardQrCode_scanQrCodeAndSaveDeviceParams();
}
Włączanie emulatora Android Studio x86
Aby utworzyć kompilację dla emulatora x86 w Android Studio, usuń ten wiersz z plików build.gradle
w SDK i Sample:
abiFilters 'armeabi-v7a', 'arm64-v8a'
Włączy to wszystkie interfejsy ABI i znacznie zwiększy rozmiar wygenerowanego pliku .aar
. Więcej informacji znajdziesz w sekcji Android ABIs.
Monitorowanie ruchów głowy
Tworzenie trackera głowy
Śledzenie ruchu głowy jest tworzone 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();
}
Gdy tworzony jest obiekt VrActivity
, generowana jest instancja klasy HelloCardboardApp
przez wywołanie metody nativeOnCreate
:
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
nativeApp = nativeOnCreate(getAssets());
//...
}
Wstrzymywanie i wznawianie śledzenia ruchu głowy
Aby wstrzymać, wznowić i zniszczyć tracker głowy, należy odpowiednio wywołać funkcje CardboardHeadTracker_pause(head_tracker_)
, CardboardHeadTracker_resume(head_tracker_)
i CardboardHeadTracker_destroy(head_tracker_)
. W aplikacji „HelloCardboard” nazywamy je w ten sposób: 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, poniższy kod odczytuje zapisane parametry i używa ich do utworzenia obiektu zniekształcenia soczewki, który stosuje odpowiednie zniekształcenie soczewki do renderowanej 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 Cardboardzie obejmuje te czynności:
- Tworzenie tekstur
- Uzyskiwanie macierzy widoku i projekcji dla lewego i prawego oka
- Tworzenie renderera i ustawianie siatki zniekształceń
- renderowanie każdej klatki,
Tworzenie tekstur
Cała treść jest rysowana na teksturze, która jest podzielona na sekcje dla lewego i prawego oka.
Te sekcje są inicjowane 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");
}
Tekstury te są przekazywane jako parametry do funkcji CardboardDistortionRenderer_renderEyeToDisplay
.
Pobieranie macierzy widoku i projekcji dla lewego i prawego oka
Najpierw pobierz macierze oczu 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 renderera zniekształceń:
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kLeft, &left_mesh);
CardboardLensDistortion_getDistortionMesh(lens_distortion_, kRight, &right_mesh);
Utwórz moduł renderujący i ustaw prawidłową siatkę zniekształceń
Renderowanie trzeba zainicjować tylko raz. Po utworzeniu renderera ustaw nową siatkę zniekształceń dla lewego i prawego oka zgodnie z wartościami siatki zwróconymi przez funkcję CardboardLensDistortion_getDistortionMesh
.
distortion_renderer_ = CardboardOpenGlEs2DistortionRenderer_create();
CardboardDistortionRenderer_setMesh(distortion_renderer_, &left_mesh, kLeft);
CardboardDistortionRenderer_setMesh(distortion_renderer_, &right_mesh, kRight);
renderowanie treści;
W przypadku 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]);
Użyj bieżącej orientacji głowy z macierzami widoku i projekcji, aby utworzyć macierz widoku i projekcji dla każdego oka i wyświetlić treści na ekranie:
// 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();
}
Użyj atrybutu CardboardDistortionRenderer_renderEyeToDisplay
, aby zastosować korekcję zniekształceń do treści i wyświetlić je 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_);