Como obter um HolographicSpace

Observação

Este artigo está relacionado às APIs nativas herdadas do WinRT. Para novos projetos de aplicativo nativo, é recomendável usar a API OpenXR.

A classe HolographicSpace é seu portal para o mundo holográfico. Ele controla a renderização imersiva, fornece dados da câmera e fornece acesso a APIs de raciocínio espacial. Você criará um para o CoreWindow do aplicativo UWP ou o HWND do aplicativo Win32.

Configurar o espaço holográfico

A criação do objeto de espaço holográfico é a primeira etapa na criação do aplicativo Windows Mixed Reality. Os aplicativos tradicionais do Windows são renderizados em uma cadeia de troca do Direct3D criada para a janela principal da exibição do aplicativo. Essa cadeia de troca é exibida em um slate na interface do usuário holográfica. Para tornar sua exibição de aplicativo holográfica em vez de um slate 2D, crie um espaço holográfico para sua janela principal em vez de uma cadeia de troca. Apresentar quadros holográficos criados por esse espaço holográfico coloca seu aplicativo no modo de renderização em tela inteira.

Para um aplicativo UWPa partir do modelo aplicativo Holographic DirectX 11 (Universal do Windows), procure esse código no método SetWindow em AppView.cpp:

m_holographicSpace = HolographicSpace::CreateForCoreWindow(window);

Se você estiver criando um aplicativo Win32a partir do exemplo BasicHologram Win32, examine App::CreateWindowAndHolographicSpace para obter um exemplo de HWND. Em seguida, você pode convertê-lo em um HWND imersivo criando um HolographicSpace associado:

void App::CreateWindowAndHolographicSpace(HINSTANCE hInstance, int nCmdShow)
{
    // Store the instance handle in our class variable.
    m_hInst = hInstance;

    // Create the window for the HolographicSpace.
    hWnd = CreateWindowW(
        m_szWindowClass, 
        m_szTitle,
        WS_VISIBLE,
        CW_USEDEFAULT, 
        0, 
        CW_USEDEFAULT, 
        0, 
        nullptr, 
        nullptr, 
        hInstance, 
        nullptr);

    if (!hWnd)
    {
        winrt::check_hresult(E_FAIL);
    }

    {
        // Use WinRT factory to create the holographic space.
        using namespace winrt::Windows::Graphics::Holographic;
        winrt::com_ptr<IHolographicSpaceInterop> holographicSpaceInterop =
            winrt::get_activation_factory<HolographicSpace, IHolographicSpaceInterop>();
        winrt::com_ptr<ABI::Windows::Graphics::Holographic::IHolographicSpace> spHolographicSpace;
        winrt::check_hresult(holographicSpaceInterop->CreateForWindow(
            hWnd, __uuidof(ABI::Windows::Graphics::Holographic::IHolographicSpace),
            winrt::put_abi(spHolographicSpace)));

        if (!spHolographicSpace)
        {
            winrt::check_hresult(E_FAIL);
        }

        // Store the holographic space.
        m_holographicSpace = spHolographicSpace.as<HolographicSpace>();
    }

    // The DeviceResources class uses the preferred DXGI adapter ID from the holographic
    // space (when available) to create a Direct3D device. The HolographicSpace
    // uses this ID3D11Device to create and manage device-based resources such as
    // swap chains.
    m_deviceResources->SetHolographicSpace(m_holographicSpace);

    // The main class uses the holographic space for updates and rendering.
    m_main->SetHolographicSpace(hWnd, m_holographicSpace);

    // Show the window. This will activate the holographic view and switch focus
    // to the app in Windows Mixed Reality.
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
}

Depois de obter um HolographicSpace para seu UWP CoreWindow ou Win32 HWND, o HolographicSpace pode lidar com câmeras holográficas, criar sistemas de coordenadas e fazer renderização holográfica. O espaço holográfico atual é usado em vários locais no modelo DirectX:

  • A classe DeviceResources precisa obter algumas informações do objeto HolographicSpace para criar o dispositivo Direct3D. Essa é a ID do adaptador DXGI associada à exibição holográfica. A classe HolographicSpace usa o dispositivo Direct3D 11 do aplicativo para criar e gerenciar recursos baseados em dispositivo, como os buffers de fundo para cada câmera holográfica. Se você estiver interessado em ver o que essa função faz nos bastidores, você a encontrará em DeviceResources.cpp.
  • A função DeviceResources::InitializeUsingHolographicSpace demonstra como obter o adaptador pesquisando o LUID e como escolher um adaptador padrão quando nenhum adaptador preferencial for especificado.
  • A classe main do aplicativo usa o espaço holográfico de AppView::SetWindow ou App::CreateWindowAndHolographicSpace para atualizações e renderização.

Observação

Embora as seções abaixo menção nomes de função do modelo, como AppView::SetWindow, que pressupõem que você tenha iniciado a partir do modelo de aplicativo UWP holográfico, os snippets de código que você vê serão aplicados igualmente em aplicativos UWP e Win32.

Em seguida, vamos nos aprofundar no processo de instalação pelo qual SetHolographicSpace é responsável na classe AppMain.

Assinar eventos de câmera, criar e remover recursos da câmera

O conteúdo holográfico do aplicativo reside em seu espaço holográfico e é exibido por meio de uma ou mais câmeras holográficas, que representam diferentes perspectivas na cena. Agora que você tem o espaço holográfico, pode receber dados para câmeras holográficas.

Seu aplicativo precisa responder a eventos CameraAdded criando todos os recursos específicos para essa câmera. Um exemplo desse recurso é a exibição de destino de renderização do buffer de fundo. Você pode ver esse código na função DeviceResources::SetHolographicSpace , chamada por AppView::SetWindow antes que o aplicativo crie quadros holográficos:

m_cameraAddedToken = m_holographicSpace.CameraAdded(
    std::bind(&AppMain::OnCameraAdded, this, _1, _2));

Seu aplicativo também precisa responder aos eventos CameraRemoved liberando recursos que foram criados para essa câmera.

De DeviceResources::SetHolographicSpace:

m_cameraRemovedToken = m_holographicSpace.CameraRemoved(
    std::bind(&AppMain::OnCameraRemoved, this, _1, _2));

Os manipuladores de eventos devem concluir algum trabalho para manter a renderização holográfica fluindo sem problemas e a renderização do aplicativo. Leia o código e os comentários para obter os detalhes: você pode procurar OnCameraAdded e OnCameraRemoved em sua classe main para entender como o mapa de m_cameraResources é tratado por DeviceResources.

No momento, estamos focados no AppMain e na configuração que ele faz para permitir que seu aplicativo saiba sobre câmeras holográficas. Com isso em mente, é importante tomar nota dos dois requisitos a seguir:

  1. Para o manipulador de eventos CameraAdded , o aplicativo pode funcionar de forma assíncrona para concluir a criação de recursos e o carregamento de ativos para a nova câmera holográfica. Os aplicativos que levam mais de um quadro para concluir esse trabalho devem solicitar um adiamento e concluir o adiamento após o carregamento assíncrono. Uma tarefa PPL pode ser usada para fazer um trabalho assíncrono. Seu aplicativo deve garantir que ele esteja pronto para renderizar para essa câmera imediatamente quando sair do manipulador de eventos ou quando concluir o adiamento. Sair do manipulador de eventos ou concluir o adiamento informa ao sistema que seu aplicativo agora está pronto para receber quadros holográficos com essa câmera incluída.

  2. Quando o aplicativo recebe um evento CameraRemoved , ele deve liberar todas as referências ao buffer de fundo e sair da função imediatamente. Isso inclui exibições de destino de renderização e qualquer outro recurso que possa conter uma referência ao IDXGIResource. O aplicativo também deve garantir que o buffer traseiro não esteja anexado como um destino de renderização, conforme mostrado em CameraResources::ReleaseResourcesForBackBuffer. Para ajudar a acelerar as coisas, seu aplicativo pode liberar o buffer de fundo e, em seguida, iniciar uma tarefa para concluir de forma assíncrona qualquer outro trabalho de desativação para a câmera. O modelo de aplicativo holográfico inclui uma tarefa PPL que você pode usar para essa finalidade.

Observação

Se você quiser determinar quando uma câmera adicionada ou removida aparece no quadro, use as propriedades HolographicFrameAddedCameras e RemovedCameras .

Criar um quadro de referência para seu conteúdo holográfico

O conteúdo do aplicativo deve ser posicionado em um sistema de coordenadas espaciais para ser renderizado no HolographicSpace. O sistema fornece dois quadros de referência primários, que você pode usar para estabelecer um sistema de coordenadas para seus hologramas.

Há dois tipos de quadros de referência no Windows Holographic: quadros de referência anexados ao dispositivo e quadros de referência que permanecem estacionários à medida que o dispositivo se move pelo ambiente do usuário. O modelo de aplicativo holográfico usa um quadro de referência estacionário por padrão; essa é uma das maneiras mais simples de renderizar hologramas bloqueados pelo mundo.

Os quadros de referência estacionários são projetados para estabilizar posições próximas à localização atual do dispositivo. Isso significa que coordenadas mais distantes do dispositivo podem descompassar um pouco em relação ao ambiente do usuário à medida que o dispositivo aprende mais sobre o espaço ao seu redor. Há duas maneiras de criar um quadro estacionário de referência: adquirir o sistema de coordenadas do estágio espacial ou usar o SpatialLocator padrão. Se você estiver criando um aplicativo Windows Mixed Reality para headsets imersivos, o ponto de partida recomendado será o estágio espacial. O estágio espacial também fornece informações sobre os recursos do headset imersivo usado pelo jogador. Aqui, mostramos como usar o SpatialLocator padrão.

O localizador espacial representa o dispositivo Windows Mixed Reality e rastreia o movimento do dispositivo e fornece sistemas de coordenadas que podem ser compreendidos em relação à sua localização.

De AppMain::OnHolographicDisplayIsAvailableChanged:

spatialLocator = SpatialLocator::GetDefault();

Crie o quadro de referência estacionária uma vez quando o aplicativo for iniciado. Isso é análogo à definição de um sistema de coordenadas do mundo, com a origem colocada na posição do dispositivo quando o aplicativo é iniciado. Esse quadro de referência não se move com o dispositivo.

De AppMain::SetHolographicSpace:

m_stationaryReferenceFrame =
    m_spatialLocator.CreateStationaryFrameOfReferenceAtCurrentLocation();

Todos os quadros de referência são alinhados à gravidade, o que significa que o eixo y aponta "para cima" em relação ao ambiente do usuário. Como o Windows usa sistemas de coordenadas "destros", a direção do eixo –z coincide com a direção "avançar" que o dispositivo está enfrentando quando o quadro de referência é criado.

Observação

Quando seu aplicativo exigir o posicionamento preciso de hologramas individuais, use um SpatialAnchor para ancorar o holograma individual a uma posição no mundo real. Por exemplo, use uma âncora espacial quando o usuário indicar um ponto de interesse especial. As posições de âncora não descompassam, mas podem ser ajustadas. Por padrão, quando uma âncora é ajustada, ela facilita sua posição em relação aos próximos vários quadros após a correção. Dependendo do aplicativo, quando isso ocorrer, talvez você queira lidar com o ajuste de uma maneira diferente (por exemplo, adiando-o até que o holograma esteja fora de exibição). A propriedade RawCoordinateSystem e os eventos RawCoordinateSystemAdjusted habilitam essas personalizações.

Responder a eventos alterados de localização

A renderização de hologramas bloqueados pelo mundo exige que o dispositivo se localize no mundo. Isso pode nem sempre ser possível devido às condições ambientais e, nesse caso, o usuário pode esperar uma indicação visual da interrupção do rastreamento. Essa indicação visual deve ser renderizada usando quadros de referência anexados ao dispositivo, em vez de estacionários ao mundo.

Seu aplicativo poderá solicitar que seja notificado se o rastreamento for interrompido por qualquer motivo. Registre-se para o evento LocatabilityChanged para detectar quando a capacidade do dispositivo de se localizar no mundo muda. De AppMain::SetHolographicSpace:

m_locatabilityChangedToken = m_spatialLocator.LocatabilityChanged(
    std::bind(&HolographicApp6Main::OnLocatabilityChanged, this, _1, _2));

Em seguida, use esse evento para determinar quando os hologramas não podem ser renderizados estacionários para o mundo.

Confira também