Virtual Reality con Android e Google Cardboard

9 agosto 2017

La realtà virtuale (virtual reality, VR) ha sempre affascinato il grande pubblico trovando applicazione in diversi ambiti, dai videogiochi al cinema, passando per settori quali l’archeologia e il settore militare. Grazie alla realtà simulata vissuta attraverso dispositivi ad-hoc come guanti, visori e auricolari, l’utilizzatore finale viene completamente immerso in un mondo artificialmente ricostruito dove tutto diventa possibile e i cui limiti sono imposti solo dalla fantasia dello sviluppatore. Oggigiorno, la VR è diventata accessibile a chiunque mediante il proprio smartphone e visori low-cost che l’hanno resa sempre più popolare.

In questo articolo, si focalizzerà l’attenzione sugli aspetti basilari per permettere ad un’applicazione Android di offrire contenuti VR. Per farlo, è necessario rispettare i seguenti prerequisiti:

Strumento Versione Descrizione
Android Studio 2.2.2 o superiori IDE di sviluppo ufficiale per sviluppare app Android, come illustrato qui
Dispositivo Android 4.4 o superiori Dispositivo fisico su cui eseguire e testare l’applicazione
Android SDK 24 o superiori API per lo sviluppo di applicazioni Android, per dettagli consultare la guida
Gradle 23.0.1 strumento per la build automation. Qualora fosse installata una versione più vecchia del Gradle, Android Studio chiederà di aggiornarla
Google VR SDK (GVRSDK) 1.60.0 o superiori Libreria open source (reperibile su GitHub) sviluppata da Google per rendere le applicazioni Android VR-friendly
Cardboard Visore in cartone composto da lenti con una distanza focale di 40mm che può essere acquistato o costruito scaricando il modelli per la costruzione, come riportato sulla pagina ufficiale

In particolare, la GVRSDK offre un set di API per semplificare lo sviluppo di tipiche funzionalità di VR, come la correzione della distorsione delle lenti e la calibrazione 3D. Inoltre, la GVRSDK è una libreria cross-platform (Androd e iOS) e offre pieno supporto ai framework Unity e Unreal per lo sviluppo di giochi e ambienti 3D interattivi.

Google VR SDK – codice d’esempio

Diversamente da molte librerie Android, la GVRSDK può essere importata all’interno di un progetto esclusivamente attraverso le dipendenze di Gradle. Ciò nonostante, essendo una libreria open source è possibile scaricare il repository e i relativi esempi tramite il seguente comando Git:

git clone https://github.com/googlevr/gvr-android-sdk.git

Aprendo il progetto in Android Studio (Figura 1), sarà possibile compilare ed eseguire sul proprio dispositivo i vari progetti d’esempio. Tra i template di progetto disponibili, selezioniamo quello per Daydream, un visore per la realtà virtuale munito di controller addizionale e supportato solo da un insieme limitato di dispositivi Android. Per questo motivo, non verrà trattato in questo articolo.

Figura 1. Progetto GVRSDK su Android Studio (click per ingrandire)

Progetto GVRSDK su Android Studio

Nota: se la compilazione del Gradle fallisce, è possibile che ci siano problemi legati alla versione della GVRSDK. Per ovviare al problema, basterà impostare una versione precedente dell’SDK dal Gradle.Script come verrà mostrato in seguito.

Set-up GVRSDK

Creiamo un nuovo progetto Android con le seguenti impostazioni:

Nome Progetto AndroidVRTutorial
Minimum SDK API 19: Android 4.4 (KitKat)

Una volta inizializzato il progetto, all’interno del build.gradle sarà presente il metodo jcenter() per l’integrazione degli archivi Android (Android Archive – AAR), tra cui quelli per la GVRSDK, all’interno dell’applicazione.

allprojects {
	repositories {
		jcenter()
	}
}
...

A questo punto, devono essere impostate le dipendenze alle API di interesse della libreria nel build.gradle del modulo app. Ad esempio, con il seguente codice verrà aggiunto il supporto per il widget della visualizzazione delle immagini panorama.

dependencies {
	. . .
	compile 'com.google.vr:sdk-panowidget:1.60.0'
}

In particolare, la GVRSDK è composta da sette package: uno come parte della NDK, mentre i restanti sei come parte della SDK. Si riporta una breve descrizione di questi:

Repository Descrizione
com.google.vr.ndk.base API per il core delle API GVR
com.google.vr.sdk.base API per il core delle API GVR
com.google.vr.sdk.audio API per la gestione dell’audio 3D
com.google.vr.sdk.controller API per la gestione del controller del Daydream
com.google.vr.sdk.widgets.common API condivise per le VR view (API sperimentali in sostituzione delle seguenti)
com.google.vr.sdk.widgets.pano API per la gestione delle VR view per le immagini Panorama
com.google.vr.sdk.widgets.video API per la gestione delle VR view per i video

Le VR View sono i componenti specializzati della SDK per il supporto e l’integrazione dei contenuti a 360 gradi che gestiscono le operazioni riguardanti il caricamento e la gestione del contenuto. Inoltre, per ovviare al problema della decompilazione degli APK, è consigliato impostare Proguard usando il file proguard-gvr.txt, sostituendo la porzione di codice esistente come segue:

android {
	...
	buildTypes {
		release {
			minifyEnabled true
			proguardFiles.add(file('../../proguard-gvr.txt'))
		}
	}
}

Una volta salvato il file e sincronizzati i file del Gradle, siamo finalmente pronti ad usare la GVRSDK nel nostro progetto.

VR View e immagini Panorama

Le VR View supportano due diverse tipologie di immagini panoramiche:

  • Mono 360, unica foto panoramica (Figura 2.a);
  • Stereo 360, due foto panoramiche impilate (Figura 2.b).

Figura 2. a) Mono 360, b) Stereo 360 (fonte: Google Developer) (click per ingrandire)

Mono 360 VS Stereo 360

Entrambe le tipologie devono rispettare determinate specifiche per poter essere processate correttamente dalla VR View:

Formati supportati jpg, png, o gif
Proporzioni Mono 360 2:1 (es: 4096 x 2048)
Proporzioni Stereo 360 1:1 (es: 4096 x 4096)

Inoltre, è importante che le immagini rispettino la proiezione cilindrica equidistante, e nel caso di immagini cubiche queste devono essere convertite secondo la suddetta proiezione.

Tenendo presenti tali informazioni, integriamo nell’applicazione un widget per la visualizzazione di un’immagine sferica.

Nel progetto Android, aggiungiamo una nuova cartella, assets, che conterrà l’immagine Mono 360 da mostrare nella schermata e riportata in Figura 3.

Figura 3. Immagine di esempio (fonte: pixabay) (click per ingrandire)

Immagine di esempio

All’interno del main_layout.xml inseriamo il widget della VrPanoramaView posizionandolo al centro del RelativeLayout, come segue:

<com.google.vr.sdk.widgets.pano.VrPanoramaView
android:id="@+id/vr_panorama"
android:layout_margin="5dip"
android:layout_width="match_parent"
android:layout_centerInParent="true"
android:scrollbars="none"
android:layout_height="250dip" />

In Java, apriamo la classe MainActivity e aggiungiamo all’interno del metodo onCreate il riferimento al widget.

private static final String TAG = "AndroidVRTutorial";
private VrPanoramaView vrPanoramaView;
@Override
protected void onCreate(Bundle savedInstanceState) {
	...
	vrPanoramaView = (VrPanoramaView) findViewById(R.id.vr_panorama);
}

Implementiamo, adesso, un semplice metodo da richiamare all’interno dell’onCreate per il caricamento dell’immagine 360° nella schermata.

private void loadPanoramaImage() {
	VrPanoramaView.Options options = null;
	InputStream inputStream = null;
	AssetManager assetManager = getAssets();
	try {
		inputStream = assetManager.open("panorama.jpg");
		options = new VrPanoramaView.Options();
		options.inputType = VrPanoramaView.Options.TYPE_MONO;
		vrPanoramaView.loadImageFromBitmap(BitmapFactory.decodeStream(inputStream), options);
		try {
			inputStream.close();
		} catch (IOException e) {
			Log.e(TAG, "Could not close input stream: " + e);
		}
	} catch (IOException e) {
		Log.e(TAG, "Exception in loadPhotoSphere: " + e.getMessage());
	}
}

In particolare, essendo l’immagine negli assets dell’applicazione, è necessario istanziare l’AssetManager per effettuare il caricamento del file richiamando il metodo open.

Successivamente, attraverso la proprietà Options del widget si può impostare la modalità per il caricamento dell’immagine. In questo caso, è stata definita la proprietà TYPE_MONO adatta per il caricamento dell’immagine di tipo Mono 360. Alternativamente, per le immagini Stereo 360 è necessario usare il tipo TYPE_STEREO_OVER_UNDER.

Infine, l’immagine panoramica viene caricata come un’immagine Bitmap passata come parametro al metodo loadImageFromBitmap dell’oggetto vrPanoramaView.

Non resta che gestire il ciclo di vita della VR Activity. Per farlo, è necessario gestire il rendering del VrPanoramaView come segue:

Metodo ciclo di vita Metodo da richiamare Descrizione
onPause pauseRendering() Mette in pausa il rendering dell’immagine al sorpaggiungere di altri eventi
onResume resumeRendering() Fa ripartire il rendering quando l’utente interagisce nuovamente con l’applicazione
onDestroy shutdown() Distrugge il widget e libera la memoria

Nota: per rendere l’esperienza utente più fruibile è consigliabile effettuare il caricamento dell’immagine panorama in background attraverso, ad esempio, un AsyncTask.

In Figura 4, è riportato il risultato finale dell’applicazione.

Figura 4. VR Panorama Activity (click per ingrandire)

VR Panorama Activity

In alternativa, è possibile impiegare la modalità fullscreen (Figura 5.a) per una visione più immersiva dell’immagine o in modalità Cardboard che permette all’utente di visualizzare l’immagine panorama usando la Cardboard (Figura 5.b).

Figura 5. VR Panorama Activity in modalità a) fullscreen, b) Cardboard (click per ingrandire)

VR Panorama Activity in modalità a) fullscreen, b) Cardboard

Il codice d’esempio è reperibile su GitHub.

Se vuoi aggiornamenti su Virtual Reality con Android e Google Cardboard inserisci la tua e-mail nel box qui sotto:
 
X
Se vuoi aggiornamenti su Virtual Reality con Android e Google Cardboard

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy