Lavorare con ARCore per Jetpack XR

ARCore per Jetpack XR consente alle app di utilizzare i concetti di base della realtà virtuale (AR), utilizzando primitive di comprensione della scena di basso livello e il monitoraggio dei movimenti. Utilizza ARCore per Jetpack XR quando crei esperienze AR e devi utilizzare dati planari o ancorare i contenuti a una posizione fissa nello spazio.

Informazioni sul ciclo di vita di una sessione

Per accedere a tutti gli oggetti monitorati da ARCore per Jetpack XR è necessario utilizzare una sessione. Analogamente al ciclo di vita di un'attività, anche gli oggetti Sessione hanno un ciclo di vita che deve essere mantenuto in base all'utilizzo delle funzionalità di un oggetto Sessione da parte della tua app. Se la tua app contiene una singola attività compatibile con la realtà virtuale, ti consigliamo di gestire il ciclo di vita della sessione utilizzando un componente consapevole del ciclo di vita.

Crea una sessione

Una sessione deve essere creata prima di poter essere utilizzata. Per creare una sessione, è necessario che l'utente abbia concesso l'autorizzazione android.permission.SCENE_UNDERSTANDING alla tua app.

Per creare una sessione:

when (val result = Session.create(owner)) {
  is SessionCreateSuccess -> {
    session = result.session
  }
  is SessionCreatePermissionsNotGranted -> {
   // Request android.permission.SCENE_UNDERSTANDING.
  }
}

Consulta SessionCreateResult per i motivi per cui la creazione di una sessione potrebbe non riuscire.

Riprendere una sessione

La ripresa di una sessione deve essere eseguita quando l'app è pronta a gestire le modifiche dello stato da ARCore per Jetpack XR. In molti casi, questa operazione viene eseguita nel callback onResume() dell'attività, ma l'app potrebbe voler ritardare l'elaborazione fino all'interazione dell'utente.

Il seguente snippet di codice mostra un esempio di ripresa di una sessione.

when (val result = session.resume()) {
  is SessionResumeSuccess -> {
    // Session has been created successfully.
    // Attach any successful handlers here.
  }
  is SessionResumePermissionsNotGranted -> {
    // Request android.permission.SCENE_UNDERSTANDING.
}

Consulta SessionResumeResult per i motivi per cui la ripresa di una sessione potrebbe non riuscire.

Mettere in pausa una sessione

Quando la tua attività passa in background, metti in pausa la sessione utilizzando Session.pause(). La messa in pausa di una sessione interrompe temporaneamente il monitoraggio fino alla ripresa della sessione, mantenendo lo stato del sistema di percezione.

Terminare una sessione

Per eliminare definitivamente una sessione, utilizza Session.destroy(). In questo modo vengono liberate le risorse in uso dalla sessione e vengono distrutti tutti gli stati della sessione.

Recupera lo stato degli aerei percepiti

ARCore per Jetpack XR fornisce lo stato degli aerei tramite un StateFlow che emette lo stato degli aerei. L'iscrizione ai piani in una sessione consente di inviare notifiche all'app quando i piani vengono aggiunti, aggiornati o rimossi.

Plane.subscribe(session).collect { planes ->
 // Planes have changed; update plane rendering
}

Un piano ha le seguenti proprietà:

  • label: una descrizione semantica di un determinato Plane. Può essere Wall, Floor, Ceiling o Table.
  • centerPose: la posa del centro del piano rilevato.
  • extents: le dimensioni del piano rilevato, in metri.
  • vertices: un elenco di vertici di un poligono convesso che approssima il piano.

Esegui un test di collisione con gli aerei

Un test di hit è un metodo per calcolare l'intersezione di un raggio con gli oggetti monitorati dalla sessione. Un'applicazione comune di un test di hit è puntare a una tabella e posizionare un oggetto in quella posizione. L'esecuzione di un test di corrispondenza genera un elenco di oggetti corrispondenti. In altre parole, un test di hit non si ferma al primo oggetto colpito. Tuttavia, spesso potrebbe interessarti solo il primo oggetto colpito di un determinato tipo.

Per eseguire un test di corrispondenza, utilizza Interaction.hitTest() con un Ray:

val results = Interaction.hitTest(session, ray)
// When interested in the first Table hit:
val tableHit = results.firstOrNull {
  val trackable = it.trackable
  trackable is Plane && trackable.state.value.label == Plane.Label.Table
}

Ancorare i contenuti a una posizione fissa nello spazio

Per assegnare una posizione nel mondo reale agli oggetti virtuali, utilizza un Anchor. Un oggetto Anchor aiuta la tua app a tenere traccia di una posizione fissa nello spazio fisico.

Un'ancora viene creata utilizzando un Pose, che può essere interpretato in base a un Trackable esistente o meno.

Creare un'ancora rispetto a un elemento tracciabile

Quando viene creata un'ancora rispetto a un Trackable, ad esempio un Plane, che consente all'ancora di seguire il Trackable collegato quando si sposta nello spazio.

val anchor = trackable.createAnchor(pose)

Creare un'ancora senza un elemento tracciabile

Per creare un'ancora non collegata a un Trackable:

when (val result = Anchor.create(session, pose)) {
  is AnchorCreateSuccess -> // ...
  else -> // handle failure
}

Collegare un'entità a un'ancora

Per eseguire il rendering di un modello in questa posizione, crea un GltfModel e imposta la sua posa sulla posa dell'ancora. Assicurati che il modello sia nascosto quando il valore di TrackingState dell'ancora è Stopped.

// renderSession is androidx.xr.core.Session
anchor.state.collect { state ->
  if (state.trackingState == TrackingState.Tracking) {
    gltfEntity.setPose(
      renderSession.perceptionSpace.transformPoseTo(state.pose, renderSession.activitySpace)
    )
  } else if (state.trackingState == TrackingState.Stopped) {
    entity.setHidden(true)
  }
}

Informazioni su TrackingState

Ogni Trackable ha un TrackingState che deve essere controllato prima di essere utilizzato. Un Trackable con un TrackableState pari a Tracking ha il proprio Pose aggiornato attivamente dal sistema. Un Trackable che è Paused potrebbe diventare Tracking in futuro, mentre un Stopped non diventerà mai Tracking.

Mantenere un'ancora in tutte le sessioni

Un'ancora non persistente scompare dopo l'eliminazione di una sessione. Se mantieni un'ancora, la tua app ne memorizza la posizione nei suoi dati dell'app privati. Questo riferimento può essere recuperato in una sessione successiva ed è ancorato nella stessa posizione geografica.

Per mantenere un'ancora, utilizza anchor.persist() come mostrato qui:

val uuid = anchor.persist()

L'app può recuperare l'ancora utilizzando UUID in una sessione futura:

when (val result = Anchor.load(session, uuid)) {
  is AnchorCreateSuccess -> // Loading was successful. The anchor is stored in result.anchor.
  else -> // handle failure
}

Quando non hai più bisogno di un'ancora, chiama unpersist(). In questo modo, l'ancora viene rimossa dall'archiviazione della tua app e l'UUID specificato non può essere recuperato per le chiamate a Anchor.load().

Anchor.unpersist(session, uuid)

L'app può anche richiedere un elenco di tutte le ancore persistenti che sono ancora presenti nello spazio di archiviazione dell'app:

val uuids = Anchor.getPersistedAnchorUuids(session)