O ARCore para Jetpack XR permite que os apps funcionem com conceitos básicos de realidade aumentada (RA), usando primitivas de compreensão de cena de baixo nível e rastreamento de movimento. Use o ARCore para Jetpack XR ao criar experiências de RA e precisar usar dados planares ou ancorar conteúdo a um local fixo no espaço.
Entender o ciclo de vida de uma sessão
Todos os objetos rastreados pelo ARCore para Jetpack XR precisam ser acessados por uma sessão. Semelhante ao ciclo de vida de uma atividade, os objetos de sessão também têm um ciclo de vida que precisa ser mantido de acordo com o uso dos recursos de um objeto de sessão pelo app. Se o app tiver uma única atividade com suporte a XR, considere gerenciar o ciclo de vida da sessão usando um componente ciente do ciclo de vida.
Criar uma sessão
Uma sessão precisa ser criada antes de ser usada. A criação de uma sessão exige que o
usuário tenha concedido a permissão android.permission.SCENE_UNDERSTANDING
ao
seu app.
Para criar uma sessão:
when (val result = Session.create(owner)) {
is SessionCreateSuccess -> {
session = result.session
}
is SessionCreatePermissionsNotGranted -> {
// Request android.permission.SCENE_UNDERSTANDING.
}
}
Consulte SessionCreateResult
para saber por que uma sessão pode não ser
criada.
Retomar uma sessão
A retomada de uma sessão precisa ser feita quando o app estiver pronto para processar mudanças de estado
do ARCore para o Jetpack XR. Em muitos casos, isso é feito no callback
onResume()
da atividade, mas o app pode atrasar
o processamento até a interação do usuário.
O snippet de código abaixo mostra um exemplo de como retomar uma sessão.
when (val result = session.resume()) {
is SessionResumeSuccess -> {
// Session has been created successfully.
// Attach any successful handlers here.
}
is SessionResumePermissionsNotGranted -> {
// Request android.permission.SCENE_UNDERSTANDING.
}
Consulte SessionResumeResult
para saber por que uma sessão pode
não ser retomada.
Pausar uma sessão
Quando a atividade for para segundo plano, pause a sessão usando
Session.pause()
. Pausar uma sessão interrompe temporariamente
o rastreamento até que ela seja retomada, mantendo o estado do sistema de
percepção.
Destruir uma sessão
Para descartar uma sessão permanentemente, use
Session.destroy()
. Isso libera os recursos usados pela
sessão e destrói todos os estados da sessão.
Recuperar o estado das superfícies percebidas
O ARCore para Jetpack XR fornece o estado dos planos por meio de um
StateFlow
que emite o estado dos planos. A inscrição
em planos em uma sessão notifica seu app quando os planos são adicionados, atualizados ou
removidos.
Plane.subscribe(session).collect { planes ->
// Planes have changed; update plane rendering
}
Um plano tem as seguintes propriedades:
label
: uma descrição semântica de um determinadoPlane
. Pode ser umWall
,Floor
,Ceiling
ouTable
.centerPose
: a pose do centro do plano detectado.extents
: as dimensões do plano detectado, em metros.vertices
: uma lista de vértices de um polígono convexo que se aproxima do plano.
Realizar um teste de hit em planos
Um teste de hit é um método de cálculo da interseção de um raio com objetos rastreados pela sessão. Uma aplicação comum de um teste de hit é apontar para uma tabela e colocar um objeto nesse local. A realização de um teste de hit resulta em uma lista de objetos de hit. Em outras palavras, um hit-test não para no primeiro objeto atingido. No entanto, muitas vezes você só tem interesse no primeiro objeto encontrado de um determinado tipo.
Para realizar um teste de hit, use Interaction.hitTest()
com um
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
}
Fixar o conteúdo em um local fixo no espaço
Para dar aos objetos virtuais uma posição no mundo real, use um
Anchor
. Um objeto de âncora ajuda seu app a acompanhar um
local fixo no espaço físico.
Uma âncora é criada usando um Pose
, que pode ser
interpretado em relação a um Trackable
existente ou não.
Criar uma âncora relativa a um rastreável
Quando uma âncora é criada em relação a um Trackable
, como um Plane
, que
faz com que a âncora siga o Trackable
anexado quando ele se move pelo espaço.
val anchor = trackable.createAnchor(pose)
Criar uma âncora sem um rastreável
Para criar uma âncora que não esteja anexada a um Trackable
:
when (val result = Anchor.create(session, pose)) {
is AnchorCreateSuccess -> // ...
else -> // handle failure
}
Anexar uma entidade a uma âncora
Para renderizar um modelo nesse local, crie um GltfModel
e defina a pose
como a âncora. Confira se o modelo fica oculto quando o
TrackingState
da âncora é 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)
}
}
Entender o TrackingState
Cada Trackable
tem um TrackingState
que precisa ser verificado antes de ser usado.
Um Trackable
com um TrackableState
de Tracking
tem o Pose
atualizado
ativamente pelo sistema. Um Trackable
que é Paused
pode se tornar Tracking
no
futuro, enquanto um que é Stopped
nunca se tornará Tracking
.
Manter uma âncora em todas as sessões
Uma âncora que não é mantida desaparece depois que uma sessão é destruída. Ao persistir uma âncora, o app lembra a posição dela nos dados particulares. Essa âncora pode ser recuperada em uma sessão subsequente e é ancorada no mesmo local do mundo.
Para manter uma âncora, use anchor.persist()
, conforme mostrado
aqui:
val uuid = anchor.persist()
Seu app pode recuperar a âncora usando a UUID
em uma
sessão futura:
when (val result = Anchor.load(session, uuid)) {
is AnchorCreateSuccess -> // Loading was successful. The anchor is stored in result.anchor.
else -> // handle failure
}
Quando você não precisar mais de uma âncora, chame
unpersist()
. Isso remove a âncora do armazenamento
do app e torna o UUID fornecido irrecuperável para chamadas para
Anchor.load()
.
Anchor.unpersist(session, uuid)
O app também pode solicitar uma lista de todas as âncoras persistidas que ainda estão presentes no armazenamento do app:
val uuids = Anchor.getPersistedAnchorUuids(session)