Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Modelos de Renderização OpenXR

Uma pedra angular do design da API do OpenXR é ser o mais agnóstico em relação à plataforma possível. Um ótimo exemplo disso é o sistema de mapa de ações do OpenXR, onde os runtimes de XR precisam suportar perfis de interação principais para recorrer a eles (fallback) caso não exista um perfil de interação para o hardware que está sendo usado. Isso garante que os aplicativos OpenXR continuem funcionando mesmo quando usados em hardwares que não existiam quando o aplicativo foi lançado, ou aos quais os desenvolvedores do aplicativo não tinham acesso.

Uma consequência disso é que o desenvolvedor do aplicativo não sabe com certeza qual hardware está sendo usado, já que o runtime de XR poderia estar imitando outro hardware. O desenvolvedor do aplicativo, portanto, não pode mostrar nada em relação ao hardware real utilizado, sendo o caso de uso mais comum exibir os controladores que o usuário está segurando no momento.

Mostrar os modelos de controladores corretos e ter esses modelos posicionados corretamente é importante para uma sensação adequada de imersão.

É aqui que entra a API de modelos de renderização do OpenXR. Esta API nos permite consultar o runtime de XR por assets 3D que sejam corretos para o hardware físico que está sendo usado. A API também nos permite consultar a posição deste hardware dentro do volume de rastreamento e o posicionamento correto dos subcomponentes deste hardware.

Por exemplo, podemos posicionar e animar corretamente o gatilho ou mostrar botões sendo pressionados.

Para os runtimes que suportam a fonte de dados do controlador para rastreamento de mãos , também podemos posicionar corretamente os dedos e a mão do usuário de acordo com o formato do controlador. Note que isso funciona em combinação com a extensão de amplitude de movimento das articulações da mão para evitar o corte (clipping) dos dedos.

Nó de modelos de renderização OpenXR

O nó OpenXRRenderModelManager pode ser usado para automatizar a maior parte da funcionalidade dos modelos de renderização. Este nó acompanha os modelos de renderização ativos atualmente disponibilizados pelo runtime de XR.

Ele criará nós filhos para cada modelo de renderização ativo, resultando na exibição desse modelo de renderização.

Este nó deve ter um nó XROrigin3D como ancestral.

Se o tracker estiver definido como Any, nosso nó mostrará todos os modelos de renderização que estão sendo rastreados no momento. Neste cenário, este nó deve ser um filho direto do nosso nó XROrigin3D.

Se o tracker estiver definido como None set, nosso nó mostrará apenas os modelos de renderização para os quais nenhum rastreador foi identificado. Neste cenário, este nó também deve ser um filho direto do nosso nó XROrigin3D.

Se o tracker estiver definido como Left Hand ou Right Hand, nosso nó mostrará apenas os modelos de renderização relacionados à nossa mão esquerda ou direita, respectivamente. Neste cenário, nosso nó pode ser colocado mais profundamente na árvore da cena.

Aviso

Para a maioria dos runtimes de XR, isso significa que o modelo de renderização representa um controlador que está realmente sendo segurado pelo usuário, mas isso não é uma garantia. Alguns runtimes de XR sempre definirão o rastreador para a mão esquerda ou direita, mesmo se o controlador não estiver sendo segurado no momento, mas estiver sendo rastreado. Você deve sempre testar isso, pois pode levar a comportamentos indesejados.

Neste cenário, também podemos especificar uma ação para uma pose no mapa de ações, definindo a propriedade make_local_to_pose para a ação da pose. Use isso em combinação com um nó XRController3D que esteja usando a mesma pose e agora você pode adicionar uma camada que lhe permite desviar da posição rastreada tanto do seu controlador quanto do modelo de renderização relacionado (veja o exemplo abaixo).

Nota

Combinar o procedimento acima com o rastreamento de mãos introduz o problema de que o rastreamento de mãos é completamente independente do sistema de mapa de ações. Você precisará combinar as poses de rastreamento de mãos e de rastreamento de controlador para deslocar (offset) adequadamente os modelos de renderização.

Isso foge do escopo desta documentação.

Exemplo de gerenciador de modelos de renderização

Você pode baixar nosso demo de modelos de renderização que implementa a configuração descrita abaixo.

../../_images/openxr_render_models_setup.webp

Nesta configuração, encontramos um nó OpenXRRenderModelManager diretamente abaixo do nosso nó XROrigin3D. Neste nó, nossa propriedade target está definida como None set e cuidará da exibição de todos os modelos de renderização que atualmente não estão relacionados aos nossos controladores de mão esquerda ou direita.

Em seguida, vemos a mesma configuração para nossa mão esquerda e direita, então vamos nos concentrar apenas na mão esquerda.

Temos um nó XRController3D que rastreará a localização da nossa mão.

Nota

Estamos usando a pose grip neste exemplo. A pose palm é reconhecidamente mais adequada e previsível, no entanto, ela não é suportada por todos os runtimes de XR. Veja o projeto de demonstração de rastreamento de mãos para uma solução de alternância entre essas poses com base no que é suportado.

Como filho do nó, temos um nó AnimatableBody3D que segue a localização rastreada da mão, mas interagirá com objetos físicos para impedir que a mão do jogador atravesse paredes, etc. Este nó possui uma forma de colisão (collision shape) que encapsula a mão.

Nota

É importante definir a prioridade de física (physics priority) para que essa lógica seja executada após qualquer lógica de física que mova o nó XROrigin3D, caso contrário, a mão ficará atrasada em um quadro (frame lag).

O script abaixo mostra uma implementação básica para isso, a qual você pode usar como base.

class_name CollisionHands3D
extends AnimatableBody3D

func _ready():
    # Make sure these are set correctly.
    top_level = true
    sync_to_physics = false
    process_physics_priority = -90

func _physics_process(_delta):
    # Follow our parent node around.
    var dest_transform = get_parent().global_transform

    # We just apply rotation for this example.
    global_basis = dest_transform.basis

    # Attempt to move to where our tracked hand is.
    move_and_collide(dest_transform.origin - global_position)

Finalmente, vemos outro nó OpenXRRenderModelManager, este com target definido para a mão apropriada e make_local_to_pose definido para a pose correta. Isso garantirá que os modelos de renderização relacionados a esta mão sejam exibidos e deslocados corretamente se o nosso manipulador de colisão tiver alterado a localização.

Nó de modelo de renderização

O nó OpenXRRenderModel implementa toda a lógica para exibir e posicionar um determinado modelo de renderização fornecido pela API de modelos de renderização.

Instâncias deste nó são adicionadas pelo nó gerenciador de modelos de renderização que usamos acima, mas você pode interagir com elas diretamente, se desejar.

Sempre que o Godot obtém informações sobre um novo modelo de renderização, um RID é criado para fazer referência a esse modelo de renderização.

Ao atribuir esse RID à propriedade render_model neste nó, o nó começará a exibir o modelo de renderização e gerenciará tanto a transformação que posiciona o modelo de renderização no local correto quanto a animação de todos os subobjetos.

A função get_top_level_path retornará o caminho de nível superior (top level path) associado a este modelo de renderização. Isso apontará para a mão esquerda ou direita. Como o caminho de nível superior pode ser definido ou limpo dependendo se o usuário pega ou solta o controlador, você pode se conectar ao sinal render_model_top_level_path_changes e reagir a essas mudanças.

Dependendo da sua configuração dos nós OpenXRRenderModelManager, os modelos de renderização serão removidos ou adicionados à medida que o caminho de nível superior deles muda.

Acesso ao backend

Os nós que detalhamos acima lidam com toda a lógica de exibição para nós, mas é possível interagir diretamente com os dados que conduzem isso e criar sua própria implementação.

Para isso, você pode acessar o singleton OpenXRRenderModelExtension.

Este objeto também permite que você consulte se os modelos de renderização são suportados e estão ativados no dispositivo atualmente em uso, chamando a função is_active neste objeto.

A lógica embutida implementa a API de modelo de renderização de interação que lista todos os modelos de renderização relacionados a controladores e dispositivos semelhantes que estão presentes no mapa de ações. Ela criará e removerá automaticamente as entidades de modelo de renderização que são expostas através desta API.

À medida que outras extensões se tornarem disponíveis, elas poderão ser implementadas em um plugin GDExtension. Esse plugin pode chamar render_model_create e render_model_destroy para criar o objeto que fornecerá acesso a esse modelo de renderização por meio da API principal de modelos de renderização.

Você não deve destruir um modelo de renderização fora desta lógica.

Você pode se conectar aos sinais render_model_added e render_model_removed para ser informado quando novos modelos de renderização forem adicionados ou removidos.

Os métodos principais para trabalhar com esta API estão listados abaixo:

Render model extension functions

Função

Descrição

render_model_get_all

Fornece uma matriz (array) de RIDs para todos os modelos de renderização que estão sendo rastreados.

render_model_new_scene_instance

Fornece uma nova cena que contém todas as malhas (meshes) necessárias para exibir o modelo de renderização.

render_model_get_subaction_paths

Fornece uma lista de caminhos de subação (subaction paths) do seu mapa de ações relacionados a este modo de renderização.

render_model_get_top_level_path

Retorna o caminho de nível superior associado a este modelo de renderização (se houver). Use o sinal render_model_top_level_path_changed para reagir à mudança disso.

render_model_get_confidence

Retorna a confiabilidade de rastreamento (tracking confidence) para os dados de rastreamento deste modelo de renderização.

render_model_get_root_transform

Retorna a transformação raiz (root transform) para este modelo de renderização dentro do nosso espaço de referência atual. Isso pode ser usado para posicionar o modelo de renderização no espaço.

render_model_get_animatable_node_count

Retorna o número de nós em nossa cena de modelo de renderização que podem ser animados

render_model_get_animatable_node_name

Retorna o nome do nó que podemos animar. Note que este nó pode estar em qualquer nível de profundidade dentro da cena.

render_model_is_animatable_node_visible

Retorna verdadeiro (true) se este nó animável deve estar visível

render_model_get_animatable_node_transform

Retorna a transformação para este nó animável. Esta é uma transformação local que pode ser aplicada diretamente.