Utiliser ARCore pour Jetpack XR

ARCore pour Jetpack XR permet aux applications de travailler avec les concepts de base de la réalité augmentée (RA), à l'aide de primitives de compréhension de scène de bas niveau et de suivi des mouvements. Utilisez ARCore pour Jetpack XR lorsque vous créez des expériences de RA et que vous devez utiliser des données planaires ou ancrer du contenu à un emplacement fixe dans l'espace.

Comprendre le cycle de vie d'une session

Tous les objets suivis par ARCore pour Jetpack XR doivent être accessibles via une session. Comme pour le cycle de vie d'une activité, les objets Session ont également un cycle de vie qui doit être géré en fonction de l'utilisation que votre application fait des fonctionnalités d'un objet Session. Si votre application ne contient qu'une seule activité compatible avec la RA, envisagez de gérer le cycle de vie de la session à l'aide d'un composant compatible avec le cycle de vie.

Créer une session

Une session doit être créée avant de pouvoir être utilisée. Pour créer une session, l'utilisateur doit avoir accordé l'autorisation android.permission.SCENE_UNDERSTANDING à votre application.

Pour créer une session:

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

Consultez SessionCreateResult pour connaître les raisons pour lesquelles la création d'une session peut échouer.

Reprendre une session

La reprise d'une session doit être effectuée lorsque votre application est prête à gérer les modifications d'état d'ARCore pour Jetpack XR. Dans de nombreux cas, cela se fait dans le rappel onResume() de votre activité, mais votre application peut vouloir retarder le traitement jusqu'à l'interaction de l'utilisateur.

L'extrait de code suivant présente un exemple de reprise d'une session.

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

Consultez SessionResumeResult pour connaître les raisons pour lesquelles une session ne peut pas être reprise.

Suspendre une session

Lorsque votre activité passe en arrière-plan, mettez la session en pause à l'aide de Session.pause(). La suspension d'une session interrompt temporairement le suivi jusqu'à sa reprise, tout en conservant l'état du système de perception.

Détruire une session

Pour supprimer définitivement une session, utilisez Session.destroy(). Cela libère les ressources utilisées par la session et détruit tous les états de session.

Récupérer l'état des plans perçus

ARCore pour Jetpack XR fournit l'état des plans via un StateFlow qui émet l'état des plans. S'abonner à des plans dans une session informe votre application lorsque des plans sont ajoutés, mis à jour ou supprimés.

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

Un plan possède les propriétés suivantes:

Effectuer un test de positionnement sur des plans

Un test de positionnement est une méthode permettant de calculer l'intersection d'un rayon avec les objets suivis par la session. Une application courante d'un test de positionnement consiste à pointer sur un tableau et à placer un objet à cet emplacement. Un test de positionnement génère une liste d'objets touchés. En d'autres termes, un test de collision ne s'arrête pas au premier objet touché. Toutefois, vous ne serez souvent intéressé que par le premier objet touché d'un type donné.

Pour effectuer un test de positionnement, utilisez Interaction.hitTest() avec un élément 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
}

Ancrer le contenu à un emplacement fixe dans l'espace

Pour donner une position aux objets virtuels dans le monde réel, utilisez un Anchor. Un objet Anchor aide votre application à suivre un emplacement fixe dans l'espace physique.

Une ancre est créée à l'aide d'un Pose, qui peut être interprété par rapport à un Trackable existant ou non.

Créer une ancre par rapport à un élément Trackable

Lorsqu'une ancre est créée par rapport à un Trackable, tel qu'un Plane, l'ancre suit le Trackable associé lorsqu'il se déplace dans l'espace.

val anchor = trackable.createAnchor(pose)

Créer une ancre sans traceur

Pour créer une ancre qui n'est pas associée à un Trackable:

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

Associer une entité à une ancre

Pour afficher un modèle à cet emplacement, créez un GltfModel et définissez sa position sur celle de l'ancre. Assurez-vous que le modèle est masqué lorsque l'TrackingState de l'ancrage est 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)
  }
}

Comprendre TrackingState

Chaque Trackable possède un TrackingState qui doit être vérifié avant d'être utilisé. Un Trackable dont la valeur TrackableState est Tracking voit son Pose mis à jour activement par le système. Un Trackable qui est Paused peut devenir Tracking à l'avenir, tandis qu'un Stopped ne deviendra jamais Tracking.

Persistance d'une ancre entre les sessions

Une ancre qui n'est pas persistante disparaît après la destruction d'une session. En persistant un ancrage, votre application mémorise la position de cet ancrage dans ses données d'application privées. Cette ancre peut être récupérée dans une session ultérieure et est ancrée au même endroit dans le monde.

Pour conserver une ancre, utilisez anchor.persist() comme indiqué ci-dessous:

val uuid = anchor.persist()

Votre application peut récupérer l'ancre à l'aide de UUID dans une future session:

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

Lorsque vous n'avez plus besoin d'une ancre, appelez unpersist(). Cette action supprime l'ancre du stockage de votre application et rend l'UUID donné introuvable pour les appels à Anchor.load().

Anchor.unpersist(session, uuid)

Votre application peut également demander la liste de tous les ancrages persistants qui sont toujours présents dans l'espace de stockage de votre application:

val uuids = Anchor.getPersistedAnchorUuids(session)