open-ar/src/chapter3.2.md

3.4 KiB

Runtime fetching models

Nella seconda applicazione d'esempio viene mostrato come sia possibile recuperare i modelli da renderizzare anche durante l'esecuzione dell'applicazione. Questa funzione risulta particolarmente utile quando si deve rilasciare un'applicazione che sfrutta numerosi modelli e non si vuole appesantire eccessivamente il volume del file APK. Inoltre concede maggiore libertà allo sviluppatore in quanto è possibile aggiungere nuovi modelli, o aggiornare quelli vecchi, senza dover operare sull'applicazione, ma lavorando esclusivamente lato server.

In questo caso specifico l'applicazione dovrà riconosce uno o più piani e in seguito ad un tocco dell'utente su di essi, mostrare un modello di Andy, la mascotte di Android (vedi fig. \ref{rfm}).

Per quest'applicazione oltre alle configurazioni già viste in precedenza è necessario aggiungere una nuova dipendenza che include le funzioni necessarie per il fetching del modello.

  implementation 'com.google.ar.sceneform:assets:$version'

Inoltre nell'Android Manifest bisogna aggiungere il permesso per accedere alla rete.

Interazione con l'utente

L'interazione con l'utente avviene mediante un tocco sul display in corrispondenza di un piano. Sceneform ci permette di personalizzare il comportamento al verificarsi di questo evento tramite il metodo setOnTapArPlaneListener.

override fun onCreate(savedInstanceState: Bundle?) {
  // ...
  arFragment.setOnTapArPlaneListener(
    this::fetchAndPlaceModel
  )
  // ...
}

Dove la funzione fetchAndPlaceModel si occupa di recuperare il modello e renderizzarlo.

private fun fetchAndPlaceModel(
	hitResult: HitResult,
	plane: Plane,
	motionEvent: MotionEvent
) {
  val modelUri = Uri.parse(MODEL_SOURCE)
  val fetchedModel = fetchModel(this, modelUri)
  buildRenderable(this, fetchedModel, modelUri) {
    addTransformableNodeToScene(
      arFragment,
      hitResult.createAnchor(),
      it
    )
  }
}

Fetching del model

Il recupero del modello avviene attraverso la funzione fetchModel, che a sua volta chiama la funzione di libreria RenderableSource.builder.

fun fetchModel(
  context: Context,
  source: Uri
) : RenderableSource {
	return RenderableSource.builder()
      .setSource(
        context,
        source,
        RenderableSource.SourceType.GLTF2
      )
      .setRecenterMode(
        RenderableSource.RecenterMode.ROOT
      )
      .build()
}

Attualmente1 Sceneform supporta unicamente il fetching di modelli gLTF.

Rendering e aggiunta del modello

Il rendering del modello avviene tramite la funzione buildRenderable, che riprende in buona parte quella vista precedentemente, con la differenza che in questo caso deve essere passato anche il modello recuperato.

fun buildRenderable(
  context: Context,
  model: RenderableSource,
  modelUri: Uri,
  onSuccess: (renderable: Renderable) -> Unit
) {
  ModelRenderable.builder()
    .setRegistryId(modelUri)
    .setSource(context, model)
    .build()
    .thenAccept(onSuccess)
    .exceptionally {
      Log.e("SCENEFORM", "unable to load model", it)
      return@exceptionally null
    }
}

Infine l'aggiunta del modello renderizzato alla scena avviene mediante la medesima funzione addTransformableNodeToScene vista in precedenza.

Rendering di un modello recuperato a runtime{#rfm width=225px height=400px}


  1. Sceneform 1.6.0. ↩︎