Praca z ARCore w Jetpack XR

ARCore dla Jetpacka XR umożliwia aplikacjom korzystanie z podstawowych koncepcji rozszerzonej rzeczywistości (AR) przy użyciu prymitywnych funkcji niskiego poziomu zrozumienia sceny i śledzenia ruchu. Używaj ARCore w Jetpack XR podczas tworzenia doświadczeń AR, gdy musisz używać danych planarnych lub zakotwiczyć zawartość w konkretnym miejscu w przestrzeni.

Cykl życia sesji

Do wszystkich obiektów śledzonych przez ARCore for Jetpack XR można uzyskać dostęp w ramach sesji. Podobnie jak w przypadku cyklu życia aktywności, obiekty sesji również mają cykl życia, który musi być utrzymywany zgodnie z używaniem przez aplikację funkcji obiektu sesji. Jeśli Twoja aplikacja zawiera jedną aktywność z obsługą XR, rozważ zarządzanie cyklem życia sesji za pomocą elementu obsługującego cykl życia.

Tworzenie sesji

Zanim sesja zostanie użyta, musi zostać utworzona. Aby utworzyć sesję, użytkownik musi przyznać aplikacji uprawnienie android.permission.SCENE_UNDERSTANDING.

Aby utworzyć sesję:

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

Informacje o przyczynach, dla których nie udało się utworzyć sesji, znajdziesz w artykule SessionCreateResult.

Wznawianie sesji

Sesję należy wznowić, gdy aplikacja będzie gotowa do obsługi zmian stanu z ARCore dla Jetpacka XR. W większości przypadków jest to wykonywane w ramach wywołania zwrotnego onResume() aktywności, ale aplikacja może opóźnić przetwarzanie do momentu interakcji z użytkownikiem.

Poniższy fragment kodu pokazuje przykład wznowienia sesji.

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

Informacje o przyczynach, dla których nie można wznowić sesji, znajdziesz w artykule SessionResumeResult.

Wstrzymywanie sesji

Gdy Twoja aktywność przejdzie do działania w tle, wstrzymaj sesję, używając Session.pause(). Wstrzymanie sesji powoduje tymczasowe zatrzymanie śledzenia do momentu wznowienia sesji, przy zachowaniu stanu systemu percepcji.

Niszczenie sesji

Aby trwale usunąć sesję, użyj polecenia Session.destroy(). Zwalnia to zasoby używane przez sesję i niszczy wszystkie stany sesji.

Pobieranie stanu postrzeganych samolotów

ARCore dla Jetpack XR dostarcza stan samolotów za pomocą StateFlow, który emituje stan samolotów. Subskrypcja samolotów w sesji powiadamia aplikację o dodawaniu, aktualizowaniu i usuwaniu samolotów.

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

Samolot ma te właściwości:

  • label: semantyczne opisy danego Plane. Może to być Wall, Floor, Ceiling lub Table.
  • centerPose: postawa w centrum wykrytej płaszczyzny.
  • extents: wymiary wykrytej płaszczyzny w metrach.
  • vertices: lista wierzchołków wypukłego wielokąta, który przybliża się do płaszczyzny.

Przeprowadź test kolizji z samolotami.

Test kolizji to metoda obliczania przecięcia promienia z obiektmi śledzonymi przez sesję. Testowanie kolizji jest często wykorzystywane do wskazywania tabeli i umieszczania w niej obiektu. Przeprowadzenie testu uderzenia powoduje wyświetlenie listy obiektów, które zostały uderzenie. Inaczej mówiąc, test kolizji nie zatrzymuje się na pierwszym obiekcie. Często jednak interesuje Cię tylko pierwszy znaleziony obiekt danego typu.

Aby przeprowadzić test trafień, użyj Interaction.hitTest()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
}

zakotwiczanie treści w stałym miejscu w pokoju;

Aby nadać obiektom wirtualnym pozycję w świecie rzeczywistym, użyj Anchor. Obiekt Anchor pomaga aplikacji śledzić stałą lokalizację w przestrzeni fizycznej.

Kotwica jest tworzona za pomocą elementu Pose, który może być interpretowany w stosunku do istniejącego elementu Trackable lub nie.

Tworzenie kotwicy względem elementu śledzonego

Gdy kotwnik jest tworzony względem Trackable, np. Plane, co powoduje, że kotwnik podąża za dołączonym Trackable, gdy ten porusza się w przestrzeni.

val anchor = trackable.createAnchor(pose)

Tworzenie kotwicy bez śledzenia

Aby utworzyć kotwicę, która nie jest powiązana z Trackable:

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

Dołączanie elementu do kotwicy

Aby wyrenderować model w tym miejscu, utwórz GltfModel i ustaw jego pozę na taką samą jak w przypadku kotwicy. Upewnij się, że model jest ukryty, gdy parametr TrackingState w Anchor jest ustawiony na 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)
  }
}

Opis stanu śledzenia

Każdy Trackable ma TrackingState, który należy sprawdzić przed użyciem. TrackableTrackableState Tracking ma Pose aktywnie aktualizowane przez system. Element Trackable o wartości Paused może w przyszłości uzyskać wartość Tracking, ale element o wartości Stopped nigdy nie będzie miał wartości Tracking.

Zachowywanie punktu kotwiczenia w trakcie sesji

Kotwica, która nie jest trwała, znika po zakończeniu sesji. Dzięki zapisaniu kotwicy aplikacja zapamięta jej pozycję w swoich prywatnych danych. Ten punkt kotwiczenia można pobrać w kolejnych sesjach. Jest on zakotwiczony w tym samym miejscu na świecie.

Aby zachować kotwicę, użyj elementu anchor.persist(), jak pokazano tutaj:

val uuid = anchor.persist()

Aplikacja może pobrać kotwicę, używając parametru UUID w przyszłej sesji:

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

Gdy nie potrzebujesz już kotwicy, zadzwoń pod numer unpersist(). Spowoduje to usunięcie kotwicy z pamięci aplikacji i uniemożliwi odzyskanie podanego identyfikatora UUID w przypadku wywołań funkcji Anchor.load().

Anchor.unpersist(session, uuid)

Aplikacja może też poprosić o listę wszystkich zachowanych kotwic, które są nadal dostępne w pamięci aplikacji:

val uuids = Anchor.getPersistedAnchorUuids(session)