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.
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).
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.
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.
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).
Il codice d’esempio è reperibile su GitHub.