correzioni errori

This commit is contained in:
Raffaele Mignone 2019-01-21 19:18:58 +01:00
parent 1576f7414f
commit 283d10568e
Signed by: norangebit
GPG Key ID: 4B9DF72AB9508845
4 changed files with 16 additions and 16 deletions

View File

@ -22,7 +22,7 @@ Sempre nel file per il build del progetto è necessario aggiungere la dipendenza
implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.6.0'
```
Inoltre per sfruttare al massimo le potenzialità offerte da Sceneform e ridurre al minimo il lavoro extra per la gestione delle view si deve aggiungere il fragment di Sceneform al file di layout dell'activity principale mediante il seguente codice xml.
Inoltre per sfruttare al massimo le potenzialità offerte da Sceneform e ridurre al minimo il lavoro extra per la gestione delle view, si deve aggiungere il fragment di Sceneform al file di layout dell'activity principale mediante il seguente codice xml.
```xml
<fragment
@ -34,7 +34,7 @@ Inoltre per sfruttare al massimo le potenzialità offerte da Sceneform e ridurre
Infine nell'Android Manifest[^manifest] va dichiarato l'utilizzo del permesso della fotocamera[^camera] e l'utilizzo di ARCore[^arcore].
[^manifest]: File in cui vengono dichiarate tutte caratteristiche di un'applicazione Android, tra cui anche i permessi.
[^manifest]: File in cui vengono dichiarate tutte le caratteristiche di un'applicazione Android, tra cui anche i permessi.
[^camera]: Lo sviluppatore deve solo dichiarare l'utilizzo del permesso, la richiesta di concessione è gestita in automatico da Sceneform.

View File

@ -17,9 +17,8 @@ override fun onCreate(savedInstanceState: Bundle?) {
}
```
La verifica di una collisione può essere effettuata o attraverso il metodo `overlapTest`, che dato un nodo in input restituisce il primo nodo che entra in collisione con questo.
Oppure mediante il metodo `overlapTestAll`, che dato un nodo in input restituisce una lista con tutti i nodi che collidono con esso.
Nel caso in cui non sono state riscontrate collisioni i metodi restituiscono rispettivamente `null` e una lista vuota.
La verifica di una collisione può essere effettuata o attraverso il metodo `overlapTest`, che dato un nodo in input restituisce il primo nodo che entra in collisione con questo, oppure mediante il metodo `overlapTestAll`, che dato un nodo in input restituisce una lista con tutti i nodi che collidono con esso.
Nel caso in cui non siano state riscontrate collisioni, i metodi restituiscono rispettivamente `null` e una lista vuota.
La funzione `onUpdate` si occupa di verificare la presenza di collisioni.
@ -60,7 +59,7 @@ override fun onCreate(savedInstanceState: Bundle?) {
}
```
Con la funzione `addShape` che, utilizzando le funzioni `buildMaterial` e `buildShape` analizzate in precedenza, si occupa dell'effettiva aggiunta dell'aggetto alla scena.
La funzione `addShape`, utilizzando le funzioni `buildMaterial` e `buildShape` analizzate in precedenza, si occupa dell'effettiva aggiunta dell'aggetto alla scena.
```kotlin
private fun addShape(
@ -82,6 +81,6 @@ private fun addShape(
}
```
Risulta importante notare che attraverso questa strategia l'aggiunta del modello alla scena avvenga incondizionatamente, ed è solo all'aggiornamento di quest'ultima che si effettua il controllo di collisione sull'ultimo nodo aggiunto.
Risulta importante notare come attraverso questa strategia l'aggiunta del modello alla scena avvenga incondizionatamente, ed è solo all'aggiornamento di quest'ultima che si effettua il controllo di collisione sull'ultimo nodo aggiunto.
[^toast]: Oggetto nativo di Android mediante il quale è possibile informare l'utente in modo non invasivo.

View File

@ -2,7 +2,7 @@
Negli esempi discussi fino a questo momento sono stati usati unicamente asset tridimensionali statici.
Gli oggetti virtuali che di volta in volta sono stati integrati nel mondo reale non erano né dotati di animazioni, né erano in grado di muoversi all'interno dell'ambiente reale circostante.
La scelta di utilizzare modelli statici è stata dettata da un lato dalla filosofia *kiss*[^kiss], e quindi di concentrassi unicamente sull'aspetto rilevante del progetto, dall'altro da un supporto quasi inesistente alle animazioni e al movimento.
La scelta di utilizzare modelli statici è stata dettata da un lato dalla filosofia *kiss*[^kiss], e quindi di concentrarsi unicamente sull'aspetto rilevante del progetto, dall'altro da un supporto quasi inesistente alle animazioni e al movimento.
Come abbiamo avuto modo di vedere nel secondo capitolo, queste lacune sono da imputare principalmente alla libreria grafica.
Infatti sia per le animazioni, sia per la gestione del movimento, Sceneform non offre alcun supporto nativo o diretto.
@ -15,14 +15,14 @@ Questo è ancora più vero nello sviluppo di applicazioni AR su smartphone che,
Il mancato utilizzo di un'animazione potrebbe segnare in modo permanete l'esperienza utente e quindi determinare il fallimento del progetto.
Non a caso uno dei problemi più discussi nell'issues tracker di Sceneform su GitHub[@googlear:Animated3DObjects:2019], è proprio la totale mancanza di supporto alle animazioni.
Sebbene ci siano stati dei lavori in questo senso ed una prima contabilità con i modelli animati FBX si stata aggiunta alla code base, ad oggi non è possibile utilizzare questa funzione, in quanto è in fase di testing per il solo personale interno.
Sebbene ci siano stati dei lavori in questo senso ed una prima contabilità con i modelli animati FBX sia stata aggiunta alla code base, ad oggi non è possibile utilizzare questa funzione, in quanto è in fase di testing per il solo personale interno.
In attesa di un rilascio al pubblico, l'unica via percorribile è quella presentata dalla stessa Google durante un codelab[@googlear:ChromaKey:2019].
La soluzione consiste nel renderizzare un schermo trasparente nel mondo reale e proiettare su di esso un video.
Affinché l'*illusione* riesca è necessario usare un video che sfrutti il *chroma key*[^chroma-key], in questo modo l'integrazione con il mondo reale risulta migliore.
Inoltre per impedire che l'utente possa guardare il retro dello schermo è consigliabile rendere quest'ultimo solidale con l'utente.
Non solo risultano evidenti le limitazioni di questo metodo, ma anche la natura più di *pezza* che soluzione al problema.
Non solo risultano evidenti le limitazioni di questo metodo, ma anche la natura più di *pezza* che soluzione al problema, che non lo rendono adatto per un utilizzo commerciale.
[^kiss]: Acronimo di *Keep It Simple, Stupid*, è un principio di programmazione che consiglia di concentrarsi su un problema alla volta.

View File

@ -10,8 +10,8 @@ Per mostrare il funzionamento degli animator è stato realizzato un progetto d'e
#### Recupero e rendering dei modelli
Visto l'elevato numero di modelli con cui si deve operare si è scelto di recuperarli da un server a runtime.
Il procedimento è simile a quello visto precedentemente, con la differenza che in questo caso si è scelto di non usare le callback, al fine di evitare il *callback hell*[^callback-hell], a favore delle *coroutines*, uno strumento messo a disposizione dal linguaggio Kotlin che permette di gestire codice asincrono come se fosse sequenziale.
Inoltre sempre attraverso le *coroutines* è stato possibile eseguire più rendering in parallelo e quindi ottimizzare il tempo di CPU dell'applicazione.
Il procedimento è simile a quello visto precedentemente, con la differenza che in questo caso non si è optato per l'utilizzo delle callback, al fine di evitare il *callback hell*[^callback-hell], a favore delle *coroutines*, uno strumento messo a disposizione dal linguaggio Kotlin che permette di gestire codice asincrono come se fosse sequenziale.
Sempre attraverso le *coroutines* è stato possibile eseguire più rendering in parallelo e quindi ottimizzare il tempo di CPU dell'applicazione.
All'interno del metodo `onCreate` viene avviata una coroutine che richiama la funzione `loadPlanets`.
Inoltre viene conservato un riferimento al `Job` della coroutine.
@ -49,7 +49,7 @@ suspend fun loadPlanets(
```
Nella funzione `loadPlanet` viene da prima recuperato il modello tridimensionale dal server e successivamente se ne effettua il rendering attraverso la funzione `buildFutureRenderable`.
Quest'ultima, come abbiamo già visto, restituisce un `CompletableFuture` che per poter essere utilizzarlo tramite delle coroutines deve essere trasformarlo in un `Deferred`[^deferred].
Quest'ultima, come abbiamo già visto, restituisce un `CompletableFuture` che per poter essere utilizzato tramite delle coroutines deve essere trasformarlo in un `Deferred`[^deferred].
Questa operazione avviene attraverso il costruttore di coroutines `async`.
Inoltre viene usato il dispatcher `IO` che ci consente di eseguire l'operazione in background.
@ -90,7 +90,7 @@ Per realizzare le orbite e i pianeti è stata implementata la classe `RotationNo
Componente principale di questa è la funzione `createAnimator` che si occupa della creazione dell'`ObjectAnimator` che permette di muovere i modelli.
All'interno della funzione vengono definiti i punti da cui ottenere la rotazione attraverso l'interpolatore.
Inoltre viene impostato l'`ObjectAnimator` affinché riproduca in loop l'animazione.
Infine viene impostato l'`ObjectAnimator` affinché riproduca in loop l'animazione.
```kotlin
private fun createAnimator(): ObjectAnimator {
@ -127,7 +127,8 @@ override fun onDeactivate() {
```
La creazione dei pianeti è gestita attraverso un ulteriore classe, `PlanetNode`, anch'essa estensione della classe `Node`.
Questa classe altro non è che un nodo che come attributo ha un `RotationNode`.
Quest'ultima viene definita come un nodo dotato di un `Renderable` ancorato ad un `RotationNode`.
Come vedremo in seguito questa operazione si rende necessaria per garantire il moto di rivoluzione.
La creazione delle orbite e dei pianeti avviene mediante la funzione `createPlanetNode`.
L'orbita del pianeta viene ancorata al nodo principale, nel caso specifico il sole, e il pianeta viene ancorato alla sua orbita.
@ -160,7 +161,7 @@ private fun createPlanetNode(
#### Creazione e aggiunta del sistema solare
La creazione del nostro sistema solare avviene mediante la funzione `createSolarSystem` che riceve in ingresso la `Map` con tutti i modelli dei pianeti, li posizionare intorno al sole e infine restituisce quest'ultimo.
La creazione del nostro sistema solare avviene mediante la funzione `createSolarSystem` che riceve in ingresso la `Map` con tutti i modelli dei pianeti, li posiziona intorno al sole e infine restituisce quest'ultimo.
```kotlin
private fun createSolarSystem(