O SDK do Jetpack XR permite usar o Jetpack SceneCore para criar, controlar e gerenciar
instâncias Entity, como modelos 3D, vídeos estereoscópicos e
PanelEntity usando o Jetpack SceneCore.
O Jetpack SceneCore adota dois padrões de arquitetura comuns para oferecer suporte ao desenvolvimento 3D: um grafo de cena e um sistema de entidade-componente (ECS, na sigla em inglês).
Usar o grafo de cena para criar e controlar entidades
Para criar e controlar objetos no espaço 3D, use a API Session do Jetpack SceneCore para acessar o grafo de cena. O gráfico de cena se alinha com o 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 acessar o grafo de cena, use as APIs do Jetpack
Compose para XR e crie uma interface espacial (por exemplo, instâncias SpatialPanel e
Orbiter) no grafo de cena. Para conteúdo 3D, como modelos 3D, acesse a sessão diretamente. Para saber mais, consulte Sobre o
ActivitySpace nesta página.
Sistema de componentes de entidade
Um sistema de componentes de entidade segue o princípio da composição em vez de 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 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 orientado para a direita (o eixo x aponta para a direita, o eixo y 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 pouco arbitrária, já que os usuários podem redefinir a posição de ActivitySpace no mundo real. Por isso, é recomendável posicionar o conteúdo em relação um ao outro, em vez de em relação à origem.
Trabalhar com entidades
As entidades são fundamentais para o 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 ao longo do gráfico de cena definindo o parent ou usando addChild().
As entidades têm alguns comportamentos padrão para coisas universais a todas as entidades, como mudança de posição, rotação ou visibilidade. Subclasses Entity específicas, como GltfModelEntity, têm comportamentos adicionais que oferecem suporte a elas.
Manipular entidades
Quando você faz uma mudança em uma propriedade Entity que pertence à classe base Entity, a mudança é transmitida a todos os filhos dela. 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 mãe. Em outras palavras, um Entity cuja posição seja (0, 0, 0) será colocado na origem da entidade mãe.
// 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))
Entity
Para desativar um Entity, use setEnabled(). Isso o torna invisível e
interrompe todo o processamento feito nele.
// Disable the entity. entity.setEnabled(false)
Para redimensionar um Entity sem alterar o formato geral, use setScale().
// Double the size of the entity entity.setScale(2f)
Adicionar comportamento comum a entidades
Você pode 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 UI consistentes.InteractableComponent: permite capturar eventos de entrada para interações personalizadas.
A instanciação de componentes precisa ser feita usando o método de criação adequado 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 MovableComponent para tornar uma entidade móvel para o usuário
O MovableComponent permite que um Entity seja movido pelo usuário.
Os eventos de movimento são enviados ao componente quando há interação com as
decorações. O comportamento padrão do sistema, criado com
MovableComponent.createSystemMovable(), move seu Entity quando as
decorações são arrastadas:
val movableComponent = MovableComponent.createSystemMovable(session) entity.addComponent(movableComponent)
O parâmetro opcional scaleInZ (por padrão, definido como true) faz com que a entidade ajuste automaticamente a escala à medida que se afasta do usuário, de maneira semelhante a como os painéis são dimensionados pelo sistema no espaço inicial.
Devido à natureza "em cascata" do sistema de componentes de entidade, a escala do elemento pai afeta todos os elementos filhos.
Você também pode especificar se a entidade pode ser ancorada a um tipo de superfície, como horizontal ou vertical, ou a 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. Neste exemplo, a entidade que pode ser movida e ancorada em qualquer superfície horizontal de piso ou mesa:
val anchorPlacement = AnchorPlacement.createForPlanes( anchorablePlaneOrientations = setOf(PlaneOrientation.VERTICAL), anchorablePlaneSemanticTypes = setOf(PlaneSemanticType.FLOOR, PlaneSemanticType.TABLE) ) val movableComponent = MovableComponent.createAnchorable( session = session, anchorPlacement = setOf(anchorPlacement) ) entity.addComponent(movableComponent)
Usar ResizableComponent para permitir que o usuário redimensione uma entidade
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 ResizableComponent, é possível especificar um tamanho mínimo ou máximo (em metros). Você também pode especificar uma proporção fixa ao redimensionar para que a largura e a altura sejam redimensionadas proporcionalmente entre si.
Ao criar um ResizableComponent, especifique um resizeEventListener que
processe os eventos de atualização. Você pode responder a diferentes eventos de ResizeState, como RESIZE_STATE_ONGOING ou RESIZE_STATE_END.
Confira um exemplo de como usar o ResizableComponent com uma proporção fixa em um
SurfaceEntity:
val resizableComponent = ResizableComponent.create(session) { event -> if (event.resizeState == ResizeEvent.ResizeState.RESIZE_STATE_END) { // update the Entity to reflect the new size surfaceEntity.shape = SurfaceEntity.Shape.Quad(FloatSize2d(event.newSize.width, event.newSize.height)) } } resizableComponent.minimumEntitySize = FloatSize3d(177f, 100f, 1f) resizableComponent.isFixedAspectRatioEnabled = true // Maintain a fixed aspect ratio when resizing surfaceEntity.addComponent(resizableComponent)
Usar InteractableComponent para capturar eventos de entrada do usuário
O InteractableComponent permite capturar eventos de entrada do usuário,
como quando ele interage ou passa o cursor sobre um Entity. Ao criar um
InteractableComponent, especifique um listener que receba os eventos de entrada.
Quando o usuário realiza qualquer ação de entrada, o listener é chamado com as informações de entrada fornecidas no parâmetro InputEvent.
InputEvent.actionespecifica o tipo de entrada, como passar o cursor ou tocar em uma entidade.InputEvent.sourceespecifica de onde veio a entrada, como entrada de mão ou controlador.InputEvent.pointerTypeespecifica se a entrada veio da mão direita ou esquerda.
Para uma lista completa de todas as constantes InputEvent, consulte a documentação de referência.
O snippet de código a seguir 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.SOURCE_HANDS && it.action == InputEvent.Action.ACTION_UP) { // increase size with right hand and decrease with left if (it.pointerType == InputEvent.Pointer.POINTER_TYPE_RIGHT) { entity.setScale(1.5f) } else if (it.pointerType == InputEvent.Pointer.POINTER_TYPE_LEFT) { entity.setScale(0.5f) } } } entity.addComponent(interactableComponent)