O SDK do Jetpack XR permite usar o Jetpack SceneCore para criar, controlar e
gerenciar instâncias de Entity
, como
modelos 3D, vídeo estereoscópico
e PanelEntity
usando o Jetpack SceneCore.
O Jetpack SceneCore adota dois padrões de arquitetura comuns para oferecer suporte ao desenvolvimento em 3D: um grafo de cena e um sistema de componentes de entidade (ECS).
Usar o gráfico de cena para criar e controlar entidades
Para criar e controlar objetos no espaço 3D, use a API Session do Jetpack SceneCore para ter acesso à cena. O gráfico de cena se alinha ao mundo real do usuário e permite organizar entidades 3D, como painéis e modelos 3D, em uma estrutura hierárquica e manter o estado dessas entidades.
Depois de ter acesso à cena, você pode usar as APIs do Jetpack
Compose para XR para criar uma interface espacial (por exemplo,
SpatialPanel
e Orbiter
s)
dentro da cena. Para conteúdo 3D, como modelos 3D, é possível acessar a
sessão diretamente. Para saber mais, consulte Sobre o ActivitySpace
nesta página.
Sistema de componentes de entidade
Um sistema de entidade-componente segue o princípio da composição sobre a herança. É possível expandir o comportamento das entidades anexando componentes que definem o comportamento, o que permite aplicar o mesmo comportamento a diferentes tipos de entidades. Para mais informações, consulte Adicionar comportamento comum a entidades nesta página.
Sobre o ActivitySpace
Cada Session
tem um ActivitySpace
que é
criado automaticamente com o Session
. O ActivitySpace
é o Entity
de nível superior no gráfico de cena.
O ActivitySpace representa um espaço tridimensional com um sistema de coordenadas
direito (o eixo x aponta para a direita, o eixo y aponta para cima e o
eixo z para trás em relação à origem) e com metros para unidades que correspondem ao
mundo real. A origem de ActivitySpace
é um tanto arbitrária (já que os usuários podem
redefinir a posição do ActivitySpace
no mundo real). Portanto, é
recomendado posicionar o conteúdo em relação a cada um dos outros, em vez de
relacionar à origem.
Trabalhar com entidades
As entidades são o centro do SceneCore. Quase tudo que o usuário vê e com que interage são entidades que representam painéis, modelos 3D e muito mais.
Como o ActivitySpace
é o nó de nível superior do gráfico de cena, por padrão,
todas as novas entidades são colocadas diretamente no ActivitySpace
. É possível realocar
entidades no gráfico de cena chamando setParent
ou
addChild
.
As entidades têm alguns comportamentos padrão para coisas que são universais para todas
as entidades, como mudar a posição, a rotação ou a visibilidade. Especificações Entity
subclasses, como GltfEntity
, têm outros
comportamentos que oferecem suporte à subclasse.
Manipular entidades
Quando você faz uma mudança em uma propriedade Entity
que pertence à classe Entity
base, a mudança é transmitida em cascata para todas as filhas. Por exemplo,
ajustar o Pose
de um Entity
pai faz com que todos
os filhos tenham o mesmo ajuste. Fazer uma mudança em uma Entity
filha
não afeta o elemento pai.
Um Pose
representa a localização e a rotação da entidade no espaço 3D. O
local é um Vector3
que consiste em posições numéricas x, y e z. A rotação é representada por um
Quaternion
. A posição de um Entity
é sempre
relativa à entidade pai. Em outras palavras, um Entity
com posição (0,
0, 0) será colocado na origem da entidade pai.
//place the entity forward 2 meters
val modelPosition = Vector3(0f, 0f, -2f)
//rotate the entity by 180 degrees on the up axis (upside-down)
val newOrientation = Quaternion.fromEulerAngles(0f, 0f, 180f)
//update the position and rotation on the entity
entity.setPose(Pose(newPosition, newOrientation))
Para mudar a visibilidade de um Entity
, use setHidden
.
//hide the entity
entity.setHidden(true)
Para redimensionar um Entity
mantendo a forma geral, use
setScale
.
//double the size of the entity
entity.setScale(2f)
Adicionar comportamento comum a entidades
É possível usar os seguintes componentes para adicionar comportamentos comuns às entidades:
MovableComponent
: permite que o usuário mova entidades.ResizableComponent
: permite que o usuário redimensione entidades com padrões de IU consistentes.InteractableComponent
: permite capturar eventos de entrada para interações personalizadas.
A instanciação de componentes precisa ser feita pelo método de criação apropriado na
classe Session
. Por exemplo, para criar um ResizableComponent
, chame
session.createResizableComponent()
.
Para adicionar o comportamento específico do componente a um Entity
, use o
método addComponent()
.
Usar o MovableComponent para permitir que o usuário mova uma entidade
O MovableComponent
permite que um Entity
seja movido
pelo usuário. Também é possível especificar se a entidade pode ser ancorada a um
tipo de superfície, como superfícies horizontais ou verticais, ou superfícies semânticas específicas,
como mesa, parede ou teto. Para especificar opções de âncora, especifique um conjunto de
AnchorPlacement
ao criar o MovableComponent
.
Confira um exemplo de entidade que pode ser movida e ancorada em qualquer superfície vertical e apenas em superfícies horizontais de piso e teto.
val anchorPlacement = AnchorPlacement.createForPlanes(
planeTypeFilter = setOf(PlaneSemantic.FLOOR, PlaneSemantic.TABLE),
planeSemanticFilter = setOf(PlaneType.VERTICAL))
val movableComponent = xrSession.createMovableComponent(
systemMovable = false,
scaleInZ = false,
anchorPlacement = setOf(anchorPlacement)
)
entity.addComponent(movableComponent)
Usar ResizableComponent para tornar uma entidade redimensionável pelo usuário
O ResizableComponent
permite que os usuários redimensionem um
Entity
. O ResizableComponent
inclui dicas de interação visual que convidam
o usuário a redimensionar um Entity
. Ao criar o ResizeableComponent
, é possível
especificar um tamanho mínimo ou máximo (em metros). Você também tem a opção de
especificar uma proporção fixa ao redimensionar para que a largura e a altura sejam redimensionadas
proporcionalmente.
Confira um exemplo de como usar ResizableComponent
com uma proporção fixa:
val resizableComponent = xrSession.createResizableComponent()
resizableComponent.minimumSize = Dimensions(177f, 100f, 1f )
resizableComponent.fixedAspectRatio = 16f / 9f //Specify a 16:9 aspect ratio
entity.addComponent(resizableComponent)
Usar o InteractableComponent para capturar eventos de entrada do usuário
O InteractableComponent
permite capturar eventos
de entrada do usuário, como quando o usuário interage ou passa o cursor sobre um Entity
.
Ao criar um InteractableComponent
, é necessário especificar um
InputEventListener
para receber os eventos de entrada. Quando
o usuário realiza qualquer ação de entrada, o método onInputEvent
é chamado com as informações de entrada específicas fornecidas no
parâmetro InputEvent
.
InputEvent.action
especifica o tipo de entrada, como pairar ou tocar em uma entidade.InputEvent.source
especifica de onde a entrada veio, como mão ou controlador.InputEvent.pointerType
especifica se a entrada veio da mão direita ou da esquerda
Para uma lista completa de todas as constantes InputEvent
, consulte a documentação
de referência.
O snippet de código abaixo mostra um exemplo de como usar um InteractableComponent
para aumentar o tamanho de uma entidade com a mão direita e diminuir com a
mão esquerda.
private val executor by lazy { Executors.newSingleThreadExecutor() }
val interactableComponent = xrSession.createInteractableComponent(executor) {
//when the user disengages with the entity with their hands
if (it.source == InputEvent.SOURCE_HANDS && it.action == InputEvent.ACTION_UP) {
// increase size with right hand and decrease with left
if (it.pointerType == InputEvent.POINTER_TYPE_RIGHT){
entity.setScale(1.5f)
} else if (it.pointerType == InputEvent.POINTER_TYPE_LEFT){
entity.setScale(0.5f)
}
}
}
entity.addComponent(interactableComponent)