取得 HolographicSpace

注意

本文與舊版 WinRT 原生 API 相關。 針對新的原生應用程式專案,我們建議使用 OpenXR API

HolographicSpace類別是全像攝影世界中的入口網站。 它會控制沉浸式轉譯、提供相機資料,以及提供空間原因 API 的存取權。 您將為 UWP 應用程式的 CoreWindow 或 Win32 應用程式的 HWND 建立一個。

設定全像攝影空間

建立全像攝影空間物件是建立Windows Mixed Reality應用程式的第一個步驟。 傳統 Windows 應用程式會呈現為其應用程式檢視核心視窗所建立的 Direct3D 交換鏈結。 此交換鏈結會顯示在全像攝影 UI 中的平板。 若要讓應用程式檢視全像攝影而非 2D 平板,請為其核心視窗建立全像攝影空間,而不是交換鏈結。 呈現此全像攝影空間所建立的全像攝影畫面,讓您的 app 進入全螢幕轉譯模式。

如需Holographic DirectX 11 App (Universal Windows) 範本開始UWP 應用程式,請在 AppView.cpp 的SetWindow方法中尋找此程式碼:

m_holographicSpace = HolographicSpace::CreateForCoreWindow(window);

如果您要BasicHologram Win32 範例開始建置Win32 應用程式,請查看App::CreateWindowAndHolographicSpace以取得 HWND 範例。 然後,您可以建立相關聯的 HolographicSpace,將其轉換成沉浸式 HWND:

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);
}

取得 UWP CoreWindow 或 Win32 HWND 的 HolographicSpace 之後,HolographicSpace 可以處理全像攝影相機、建立座標系統,以及執行全像攝影轉譯。 目前的全像攝影空間用於 DirectX 範本中的多個位置:

  • DeviceResources類別需要從 HolographicSpace 物件取得一些資訊,才能建立 Direct3D 裝置。 這是與全像攝影顯示器相關聯的 DXGI 配接器識別碼。 HolographicSpace類別會使用您應用程式的 Direct3D 11 裝置來建立和管理裝置型資源,例如每個全像攝影相機的背景緩衝區。 如果您有興趣瞭解此函式在幕後執行的功能,您會在 DeviceResources.cpp 中找到它。
  • DeviceResources::InitializeUsingHolographicSpace函式會示範如何藉由查閱 LUID 來取得介面卡,以及如何在未指定慣用介面卡時選擇預設介面卡。
  • 應用程式的主要類別會使用 來自 AppView::SetWindowApp::CreateWindowAndHolographicSpace 的全像攝影空間進行更新和轉譯。

注意

雖然下列各節提及來自 AppView::SetWindow 等範本的函式名稱,但假設您已從全像攝影 UWP 應用程式範本開始,但您看到的程式碼片段會同樣適用于 UWP 和 Win32 應用程式。

接下來,我們將深入探討 SetHolographicSpace 在 AppMain 類別中負責的設定程式。

訂閱相機事件、建立和移除相機資源

您的應用程式全像攝影內容會位於全像攝影空間中,並透過一或多個全像攝影相機來檢視,代表場景中的不同觀點。 現在您已擁有全像攝影空間,您可以接收全像攝影機的資料。

您的應用程式需要藉由建立該相機專屬的任何資源來回應 CameraAdded 事件。 這類資源的範例是您的背景緩衝區轉譯目標檢視。 您可以在AppView::SetWindow呼叫的 DeviceResources::SetHolographicSpace函式中看到此程式碼,然後再建立任何全像攝影畫面:

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

您的應用程式也需要釋放為該相機建立的資源,以回應 CameraRemoved 事件。

DeviceResources::SetHolographicSpace

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

事件處理常式必須完成一些工作,才能讓全像攝影轉譯順暢地流動,以及您的應用程式完全轉譯。 閱讀詳細資料的程式碼和批註:您可以在主要類別中尋找OnCameraAddedOnCameraRemoved,以瞭解DeviceResources如何處理m_cameraResources地圖。

現在,我們將焦點放在 AppMain 及其設定上,讓您的 app 知道全像攝影相機。 請記住,請務必記下下列兩個需求:

  1. 針對 CameraAdded 事件處理常式,應用程式可以非同步方式運作,以完成為新的全像攝影機建立資源和載入資產。 需要一個以上的畫面來完成這項工作的應用程式應該要求延遲,並在非同步載入之後完成延遲。 PPL 工作可用來執行非同步工作。 您的應用程式必須確定它已準備好在結束事件處理常式或完成延遲時立即轉譯至該相機。 結束事件處理常式或完成延遲會告知系統您的應用程式現在已準備好接收包含該相機的全像攝影畫面。

  2. 當應用程式收到 CameraRemoved 事件時,它必須釋放回緩衝區的所有參考,並立即結束函式。 這包括轉譯目標檢視,以及可能保存 IDXGIResource參考的任何其他資源。 應用程式也必須確保後端緩衝區不會附加為轉譯目標,如 CameraResources::ReleaseResourcesForBackBuffer所示。 為了協助加快速度,您的應用程式可以釋放背景緩衝區,然後啟動工作,以非同步方式完成相機的任何其他終止工作。 全像攝影應用程式範本包含 PPL 工作,可供您用於此用途。

注意

如果您想要判斷新增或移除的相機何時顯示在畫面上,請使用 HolographicFrameAddedCamerasRemovedCameras 屬性。

建立全像攝影內容的參考框架

您的應用程式內容必須放置在 空間座標系統中 ,才能在 HolographicSpace 中轉譯。 系統提供兩個主要參考框架,可讓您用來建立全像投影的座標系統。

Windows 全像攝影版中有兩種參考框架:附加至裝置的參考畫面,以及當裝置在使用者環境中移動時保持固定的參考畫面格。 全像攝影應用程式範本預設會使用固定參考框架;這是呈現世界鎖定全像投影的最簡單方式之一。

固定參考畫面的設計目的是要穩定裝置目前位置附近的位置。 這表示裝置進一步的座標可能會稍微相對於使用者的環境漂移,因為裝置會深入瞭解其周圍的空間。 有兩種方式可以建立固定的參考框架:從 空間階段取得座標系統,或使用預設 的 SpatialLocator。 如果您要為沉浸式頭戴裝置建立Windows Mixed Reality應用程式,建議的起點是空間階段。 空間階段也提供玩家沉浸式頭戴式裝置裝置功能的相關資訊。 在這裡,我們將示範如何使用預設 的 SpatialLocator

空間定位器代表Windows Mixed Reality裝置,並追蹤裝置的動作,並提供可與其位置相對理解的座標系統。

AppMain::OnHolographicDisplayIsAvailableChanged

spatialLocator = SpatialLocator::GetDefault();

啟動應用程式時,建立固定參考框架一次。 這類似于定義全局座標系統,並在啟動應用程式時放置於裝置位置的原點。 此參考框架不會與裝置一起移動。

AppMain::SetHolographicSpace

m_stationaryReferenceFrame =
    m_spatialLocator.CreateStationaryFrameOfReferenceAtCurrentLocation();

所有參考框架都是旋轉對齊的,這表示 Y 軸指向與使用者環境相關的「向上」。 由於 Windows 使用「右手」座標系統,所以 –Z 軸的方向會與建立參考框架時裝置所面向的「正向」方向一致。

注意

當您的應用程式需要精確放置個別全像投影時,請使用 SpatialAnchor 將個別全像投影錨定在真實世界中的位置。 例如,當使用者指出要特別感興趣的點時,請使用空間錨點。 錨點位置不會漂移,但可以調整。 根據預設,調整錨點時,它會在修正發生修正之後,將其位置放寬到下幾個畫面格上。 視您的應用程式而定,當發生這種情況時,您可能會想要以不同的方式處理調整 (,例如延遲調整,直到全像投影不在檢視) 為止。 RawCoordinateSystem屬性和RawCoordinateSystemAdjusted事件會啟用這些自訂。

回應 locatability 已變更的事件

轉譯世界鎖定的全像投影需要裝置在世界中找到自己。 這可能會因為環境狀況而不一定可行,若是如此,使用者可能會預期追蹤中斷的視覺指示。 此視覺指示必須使用附加至裝置的參考畫面來轉譯,而不是固定到世界。

如果追蹤因任何原因而中斷,您的應用程式可以要求收到通知。 註冊 LocatabilityChanged 事件,以偵測裝置何時能夠在世界變更中尋找本身。 從 AppMain::SetHolographicSpace:

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

然後使用這個事件來判斷何時無法將全像投影轉譯成固定到世界。

另請參閱