O SDK do Jetpack XR permite usar o SceneCore para criar, controlar e gerenciar
Entity instâncias como modelos 3D, vídeos estereoscópicos e
PanelEntity.
O Jetpack SceneCore adota dois padrões arquitetônicos comuns para oferecer suporte ao desenvolvimento 3D: um gráfico de cena e um sistema de componente de entidade (ECS, na sigla em inglês).
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 acessar o gráfico de 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 acessar o gráfico de cena, use as APIs no Jetpack
Compose para XR para criar uma interface espacial (por exemplo, SpatialPanel e
Orbiter instâncias) dentro do gráfico 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 da 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 é a Entity de nível superior no gráfico de cena.
O ActivitySpace representa um espaço tridimensional com um sistema de coordenadas destro (o eixo x aponta para a direita, o eixo y aponta para cima e o eixo z aponta para trás em relação à origem) e com metros para unidades que correspondem ao mundo real. A origem do ActivitySpace é um pouco arbitrária, já que os usuários podem redefinir a posição do ActivitySpace no mundo real. Portanto, é 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 mudar a posição, a rotação ou a visibilidade. Subclasses Entity
específicas, como GltfModelEntity, têm comportamentos adicionais que
oferecem suporte à subclasse.
Manipular entidades
Quando você faz uma mudança em uma propriedade Entity que pertence à classe Entity de base, a mudança é transmitida para todos os filhos. Por exemplo,
ajustar o Pose de um Entity resulta em todos os filhos
com o mesmo ajuste. Fazer uma mudança em uma Entity filha não afeta a mãe.
Uma Pose representa a localização e a rotação da entidade no espaço 3D. A
localização é um Vector3 que consiste em posições numéricas x, y, z. A
rotação é representada por um Quaternion. A posição de uma Entity é sempre relativa à entidade pai. Em outras palavras, uma Entity cuja posição é (0, 0, 0) será colocada 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 desativar um Entity, use setEnabled(). Isso a torna invisível e interrompe todo o processamento feito nela.
// Disable the entity. entity.setEnabled(false)
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 comportamento comum a entidades:
MovableComponent: permite que o usuário mova entidades.ResizableComponent: permite que o usuário redimensione entidades com padrões de interface 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 do componente específico a um Entity, use o
addComponent() método.
Usar MovableComponent para tornar uma entidade móvel para o usuário
O MovableComponent permite que uma Entity seja movida pelo usuário.
Os eventos de movimento são enviados ao componente quando as decorações são interagidas. O comportamento padrão do sistema, criado com
MovableComponent.createSystemMovable(), move sua 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 é movida para longe 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 pai afeta todos os filhos.
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 ancoragem, especifique um conjunto de AnchorPlacement
ao criar o MovableComponent. Neste exemplo, a entidade pode ser movida e ancorada a 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 tornar uma entidade redimensionável para o usuário
O ResizableComponent permite que os usuários redimensionem uma Entity. O ResizableComponent inclui dicas de interação visual que convidam o usuário a redimensionar uma Entity. Ao criar o ResizableComponent, é 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.
Ao criar um ResizableComponent, especifique um resizeEventListener que processe os eventos de atualização. É possível responder a diferentes ResizeState
eventos, como RESIZE_STATE_ONGOING ou RESIZE_STATE_END.
Confira um exemplo de como usar o ResizableComponent com uma proporção fixa em uma SurfaceEntity:
val resizableComponent = ResizableComponent.create(session) { event -> if (event.resizeState == ResizeEvent.ResizeState.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 se envolve 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 InputEvent parâmetro.
InputEvent.actionespecifica o tipo de entrada, como passar o cursor ou tocar em uma entidade.InputEvent.sourceespecifica de onde a entrada veio, como entrada de mão ou controladorInputEvent.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 mão 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.RIGHT) { entity.setScale(1.5f) } else if (it.pointerType == InputEvent.Pointer.LEFT) { entity.setScale(0.5f) } } } entity.addComponent(interactableComponent)
Criar modelos 3D personalizados no ambiente de execução
A API Custom Mesh permite gerar formas 3D de maneira programática diretamente no código, em vez de carregar recursos estáticos, como arquivos glTF. Ao criar uma geometria personalizada em tempo real, é possível renderizar dados processuais, formas personalizadas dinâmicas e ambientes 3D aparentemente infinitos, como terrenos que são gerados continuamente à medida que os usuários exploram. Além disso, a geração de malhas no ambiente de execução contribui para tamanhos binários menores, eliminando a necessidade de empacotar inúmeras variações de um único recurso 3D.