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 componente de entidade 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 em relação à
origem.
Trabalhar com entidades
As entidades são o centro do SceneCore. A maioria dos elementos 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 ao longo do 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. Específicas 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 a mãe.
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 a posição (0,
0, 0) será colocado na origem da entidade pai.
// Place the entity forward 2 meters val newPosition = 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
ResizableComponent.create()
.
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 = MovableComponent.create( session = session, systemMovable = false, scaleInZ = false, anchorPlacement = setOf(anchorPlacement) ) entity.addComponent(movableComponent)
À medida que o usuário move a entidade, o parâmetro scaleInZ
ajusta automaticamente a
escala da entidade à medida que ela se afasta do usuário, de forma semelhante à forma como
os painéis são dimensionados pelo sistema no espaço de início. Devido à
natureza "em cascata" do sistema de componentes de entidade, a escala da mãe vai
afetar todas as filhas.
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 uso da ResizableComponent
com uma proporção fixa:
val resizableComponent = ResizableComponent.create(session) 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
esquerda.
val executor = Executors.newSingleThreadExecutor() val interactableComponent = InteractableComponent.create(session, 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)