Системы координат в DirectXCoordinate systems in DirectX

Примечание

Эта статья связана с устаревшими собственными API-интерфейсами WinRT.This article relates to the legacy WinRT native APIs. Для новых проектов собственных приложений рекомендуется использовать API опенкср.For new native app projects, we recommend using the OpenXR API.

Системы координат формируют базу для пространственного понимания, предлагаемого интерфейсами API Windows Mixed Reality.Coordinate systems form the basis for spatial understanding offered by Windows Mixed Reality APIs.

Современные устройства VR или с одним помещением в рабочее место устанавливают одну основную систему координат для их прослеживания.Today's seated VR or single-room VR devices establish one primary coordinate system for their tracked space. Устройства смешанной реальности, такие как HoloLens, предназначены для крупных неопределенных сред, при этом устройства обнаруживаются и изучены окружающую среду по мере пошагового изучения пользователя.Mixed Reality devices like HoloLens are designed for large undefined environments, with the device discovering and learning about its surroundings as the user walks around. Устройство адаптируется к постоянному улучшению знаний о комнатах пользователей, но приводит к системам координат, которые меняют их связь друг с другом по времени существования приложений.The device adapts to continually improving knowledge about the user's rooms, but results in coordinate systems that change their relationship to one another over the apps lifetime. Windows Mixed Reality поддерживает широкий спектр устройств, начиная от променяющихся впечатляющих головок с помощью связанных с миром кадров ссылок.Windows Mixed Reality supports a wide spectrum of devices, ranging from seated immersive headsets through world-attached reference frames.

Примечание

Фрагменты кода в этой статье в настоящее время демонстрируют использование C++/CX вместо C + +17, совместимого с C++/WinRT, как используется в шаблоне C++ holographic.The code snippets in this article currently demonstrate use of C++/CX rather than C++17-compliant C++/WinRT as used in the C++ holographic project template. Понятия эквивалентны для проекта C++/WinRT, хотя код необходимо преобразовать.The concepts are equivalent for a C++/WinRT project, though you will need to translate the code.

Пространственные системы координат в WindowsSpatial coordinate systems in Windows

Основной тип, используемый в качестве основания для реальных систем координат в Windows, — это спатиалкурдинатесистем.The core type used to reason about real-world coordinate systems in Windows is the SpatialCoordinateSystem. Экземпляр этого типа представляет произвольную систему координат, предоставляя метод для получения данных матрицы преобразования, которые можно использовать для преобразования между двумя системами координат, не зная сведений о них.An instance of this type represents an arbitrary coordinate system, providing a method for getting transformation matrix data that you can use to transform between two coordinate systems without understanding the details of each.

Методы, возвращающие пространственные данные, принимают параметр Спатиалкурдинатесистем, чтобы вы могли выбрать систему координат, в которой она наиболее полезна для возвращения этих координат.Methods that return spatial information will accept a SpatialCoordinateSystem parameter to let you decide the coordinate system in which it's most useful for those coordinates to be returned. Пространственные данные представлены в виде точек, лучей или томов в окружающей области пользователя, а единицы для этих координат всегда будут в метрах.Spatial information is represented as points, rays, or volumes in the user's surroundings, and the units for these coordinates will always be in meters.

Спатиалкурдинатесистем имеет динамическую связь с другими системами координат, включая те, которые представляют положение устройства.A SpatialCoordinateSystem has a dynamic relationship with other coordinate systems, including those that represent the device's position. На любом этапе устройство может размещать некоторые системы координат, а не другие.At any point, the device can locate some coordinate systems and not others. Для большинства систем координат приложение должно быть готово к обработке периодов времени, в течение которых они не могут быть найдены.For most coordinate systems, your app must be ready to handle periods of time during which they cannot be located.

Приложение не должно напрямую создавать Спатиалкурдинатесистемс, а должно использоваться через API-интерфейсы восприятия.Your application shouldn't create SpatialCoordinateSystems directly - rather they should be consumed via the Perception APIs. В API-интерфейсах восприятия есть три основных источника систем координат, каждая из которых соответствует концепции, описанной на странице системы координат .There are three primary sources of coordinate systems in the Perception APIs, each of which map to a concept described on the Coordinate systems page:

Все системы координат, возвращенные этими объектами, находятся справа, с + y вверх, + x справа и + z в обратном направлении.All of the coordinate systems returned by these objects are right-handed, with +y up, +x to the right and +z backwards. Вы можете вспомнить направление положительных точек по оси z, нажимая пальцы в левой или правой руки в положительном направлении x и заметив их положительным направлением по оси y.You can remember which direction the positive z-axis points by pointing the fingers of either your left or right hand in the positive x direction and curling them into the positive y direction. Направление, в котором указывают ваши пальцы (к вам или от вас), — это направление, в котором указывает положительная ось z в этой системе координат.The direction your thumb points, either toward or away from you, is the direction that the positive z-axis points for that coordinate system. На следующем рисунке показаны эти две системы координат.The following illustration shows these two coordinate systems.

Руки и правая система координатLeft-hand and right-hand coordinate systems
Руки и правая система координатLeft-hand and right-hand coordinate systems

Используйте класс спатиаллокатор , чтобы создать присоединенный или стационарный кадр ссылки для начальной загрузки в спатиалкурдинатесистем на основе расположения HoloLens.Use the SpatialLocator class to create either an attached or stationary frame of reference to bootstrap into a SpatialCoordinateSystem based on the HoloLens position. Перейдите к следующему разделу, чтобы узнать больше об этом процессе.Continue to the next section to learn more about this process.

Размещение голограмм в мире с помощью пространственного этапаPlace holograms in the world using a spatial stage

Доступ к системе координат для непрозрачных впечатляющих головных телефонов Windows Mixed Reality осуществляется с помощью статического свойства спатиалстажефрамеофреференце:: Current .The coordinate system for opaque Windows Mixed Reality immersive headsets is accessed using the static SpatialStageFrameOfReference::Current property. Этот API предоставляет следующие функции:This API provides:

  • Система координатA coordinate system
  • Сведения о том, установлен ли проигрыватель в рабочее состояние или мобильное устройствоInformation about whether the player is seated or mobile
  • Граница надежной области для обхода, если проигрыватель является мобильнымThe boundary of a safe area for walking around if the player is mobile
  • Указывает, является ли гарнитура направленной.An indication of whether the headset is directional.
  • Обработчик событий для обновлений на пространственном этапе.An event handler for updates to the spatial stage.

Во первых, мы получаем пространственный этап и подписались на его обновления:First, we get the spatial stage and subscribe for updates to it:

Код для инициализации пространственного этапаCode for Spatial stage initialization

SpatialStageManager::SpatialStageManager(
    const std::shared_ptr<DX::DeviceResources>& deviceResources, 
    const std::shared_ptr<SceneController>& sceneController)
    : m_deviceResources(deviceResources), m_sceneController(sceneController)
{
    // Get notified when the stage is updated.
    m_spatialStageChangedEventToken = SpatialStageFrameOfReference::CurrentChanged +=
        ref new EventHandler<Object^>(std::bind(&SpatialStageManager::OnCurrentChanged, this, _1));

    // Make sure to get the current spatial stage.
    OnCurrentChanged(nullptr);
}

В методе Онкуррентчанжед приложение должно проверить пространственный этап и обновить интерфейс проигрывателя.In the OnCurrentChanged method, your app should inspect the spatial stage and update the player experience. В этом примере мы предоставляем визуализацию границы этапа и начальную точку, заданную пользователем, а также диапазон представлений и диапазон свойств перемещения.In this example, we provide a visualization of the stage boundary and the start position specified by the user and the stage's range of view and range of movement properties. Мы также вернемся к нашей стационарной системе координат, когда невозможно предоставить этап.We also fall back to our own stationary coordinate system, when a stage cannot be provided.

Код для обновления пространственного этапаCode for Spatial stage update

void SpatialStageManager::OnCurrentChanged(Object^ /*o*/)
{
    // The event notifies us that a new stage is available.
    // Get the current stage.
    m_currentStage = SpatialStageFrameOfReference::Current;

    // Clear previous content.
    m_sceneController->ClearSceneObjects();

    if (m_currentStage != nullptr)
    {
        // Obtain stage geometry.
        auto stageCoordinateSystem = m_currentStage->CoordinateSystem;
        auto boundsVertexArray = m_currentStage->TryGetMovementBounds(stageCoordinateSystem);

        // Visualize the area where the user can move around.
        std::vector<float3> boundsVertices;
        boundsVertices.resize(boundsVertexArray->Length);
        memcpy(boundsVertices.data(), boundsVertexArray->Data, boundsVertexArray->Length * sizeof(float3));
        std::vector<unsigned short> indices = TriangulatePoints(boundsVertices);
        m_stageBoundsShape =
            std::make_shared<SceneObject>(
                    m_deviceResources,
                    reinterpret_cast<std::vector<XMFLOAT3>&>(boundsVertices),
                    indices,
                    XMFLOAT3(DirectX::Colors::SeaGreen),
                    stageCoordinateSystem);
        m_sceneController->AddSceneObject(m_stageBoundsShape);

        // In this sample, we draw a visual indicator for some spatial stage properties.
        // If the view is forward-only, the indicator is a half circle pointing forward - otherwise, it
        // is a full circle.
        // If the user can walk around, the indicator is blue. If the user is seated, it is red.

        // The indicator is rendered at the origin - which is where the user declared the center of the
        // stage to be during setup - above the plane of the stage bounds object.
        float3 visibleAreaCenter = float3(0.f, 0.001f, 0.f);

        // Its shape depends on the look direction range.
        std::vector<float3> visibleAreaIndicatorVertices;
        if (m_currentStage->LookDirectionRange == SpatialLookDirectionRange::ForwardOnly)
        {
            // Half circle for forward-only look direction range.
            visibleAreaIndicatorVertices = CreateCircle(visibleAreaCenter, 0.25f, 9, XM_PI);
        }
        else
        {
            // Full circle for omnidirectional look direction range.
            visibleAreaIndicatorVertices = CreateCircle(visibleAreaCenter, 0.25f, 16, XM_2PI);
        }

        // Its color depends on the movement range.
        XMFLOAT3 visibleAreaColor;
        if (m_currentStage->MovementRange == SpatialMovementRange::NoMovement)
        {
            visibleAreaColor = XMFLOAT3(DirectX::Colors::OrangeRed);
        }
        else
        {
            visibleAreaColor = XMFLOAT3(DirectX::Colors::Aqua);
        }

        std::vector<unsigned short> visibleAreaIndicatorIndices = TriangulatePoints(visibleAreaIndicatorVertices);

        // Visualize the look direction range.
        m_stageVisibleAreaIndicatorShape =
            std::make_shared<SceneObject>(
                    m_deviceResources,
                    reinterpret_cast<std::vector<XMFLOAT3>&>(visibleAreaIndicatorVertices),
                    visibleAreaIndicatorIndices,
                    visibleAreaColor,
                    stageCoordinateSystem);
        m_sceneController->AddSceneObject(m_stageVisibleAreaIndicatorShape);
    }
    else
    {
        // No spatial stage was found.
        // Fall back to a stationary coordinate system.
        auto locator = SpatialLocator::GetDefault();
        if (locator)
        {
            m_stationaryFrameOfReference = locator->CreateStationaryFrameOfReferenceAtCurrentLocation();

            // Render an indicator, so that we know we fell back to a mode without a stage.
            std::vector<float3> visibleAreaIndicatorVertices;
            float3 visibleAreaCenter = float3(0.f, -2.0f, 0.f);
            visibleAreaIndicatorVertices = CreateCircle(visibleAreaCenter, 0.125f, 16, XM_2PI);
            std::vector<unsigned short> visibleAreaIndicatorIndices = TriangulatePoints(visibleAreaIndicatorVertices);
            m_stageVisibleAreaIndicatorShape =
                std::make_shared<SceneObject>(
                    m_deviceResources,
                    reinterpret_cast<std::vector<XMFLOAT3>&>(visibleAreaIndicatorVertices),
                    visibleAreaIndicatorIndices,
                    XMFLOAT3(DirectX::Colors::LightSlateGray),
                    m_stationaryFrameOfReference->CoordinateSystem);
            m_sceneController->AddSceneObject(m_stageVisibleAreaIndicatorShape);
        }
    }
}

Набор вершин, определяющих границу этапа, указывается в порядке по часовой стрелке.The set of vertices that define the stage boundary are provided in clockwise order. Оболочка Windows Mixed Reality выводит ограждение на границе, когда пользователь его приближает, но вы можете захотеть триангуларизе область неанализируемой для собственных целей.The Windows Mixed Reality shell draws a fence at the boundary when the user approaches it, but you may want to triangularize the walkable area for your own purposes. Для триангуларизе этапа можно использовать следующий алгоритм.The following algorithm can be used to triangularize the stage.

Код для треугольия пространственного этапаCode for Spatial stage triangularization

std::vector<unsigned short> SpatialStageManager::TriangulatePoints(std::vector<float3> const& vertices)
{
    size_t const& vertexCount = vertices.size();

    // Segments of the shape are removed as they are triangularized.
    std::vector<bool> vertexRemoved;
    vertexRemoved.resize(vertexCount, false);
    unsigned int vertexRemovedCount = 0;

    // Indices are used to define triangles.
    std::vector<unsigned short> indices;

    // Decompose into convex segments.
    unsigned short currentVertex = 0;
    while (vertexRemovedCount < (vertexCount - 2))
    {
        // Get next triangle:
        // Start with the current vertex.
        unsigned short index1 = currentVertex;

        // Get the next available vertex.
        unsigned short index2 = index1 + 1;

        // This cycles to the next available index.
        auto CycleIndex = [=](unsigned short indexToCycle, unsigned short stopIndex)
        {
            // Make sure the index does not exceed bounds.
            if (indexToCycle >= unsigned short(vertexCount))
            {
                indexToCycle -= unsigned short(vertexCount);
            }

            while (vertexRemoved[indexToCycle])
            {
                // If the vertex is removed, go to the next available one.
                ++indexToCycle;

                // Make sure the index does not exceed bounds.
                if (indexToCycle >= unsigned short(vertexCount))
                {
                    indexToCycle -= unsigned short(vertexCount);
                }

                // Prevent cycling all the way around.
                // Should not be needed, as we limit with the vertex count.
                if (indexToCycle == stopIndex)
                {
                    break;
                }
            }

            return indexToCycle;
        };
        index2 = CycleIndex(index2, index1);

        // Get the next available vertex after that.
        unsigned short index3 = index2 + 1;
        index3 = CycleIndex(index3, index1);

        // Vertices that may define a triangle inside the 2D shape.
        auto& v1 = vertices[index1];
        auto& v2 = vertices[index2];
        auto& v3 = vertices[index3];

        // If the projection of the first segment (in clockwise order) onto the second segment is 
        // positive, we know that the clockwise angle is less than 180 degrees, which tells us 
        // that the triangle formed by the two segments is contained within the bounding shape.
        auto v2ToV1 = v1 - v2;
        auto v2ToV3 = v3 - v2;
        float3 normalToV2ToV3 = { -v2ToV3.z, 0.f, v2ToV3.x };
        float projectionOntoNormal = dot(v2ToV1, normalToV2ToV3);
        if (projectionOntoNormal >= 0)
        {
            // Triangle is contained within the 2D shape.

            // Remove peak vertex from the list.
            vertexRemoved[index2] = true;
            ++vertexRemovedCount;

            // Create the triangle.
            indices.push_back(index1);
            indices.push_back(index2);
            indices.push_back(index3);

            // Continue on to the next outer triangle.
            currentVertex = index3;
        }
        else
        {
            // Triangle is a cavity in the 2D shape.
            // The next triangle starts at the inside corner.
            currentVertex = index2;
        }
    }

    indices.shrink_to_fit();
    return indices;
}

Поместите голограммы в мир с помощью стационарной рамки ссылкиPlace holograms in the world using a stationary frame of reference

Класс спатиалстатионарифрамеофреференце представляет кадр ссылки, который остается стационарным по отношению к окружающей области пользователя при движении пользователя.The SpatialStationaryFrameOfReference class represents a frame of reference that remains stationary relative to the user's surroundings as the user moves around. Этот кадр ссылок указывает на то, что координаты на устройстве постоянно стабильны.This frame of reference prioritizes keeping coordinates stable near the device. Одним из ключевых способов использования Спатиалстатионарифрамеофреференце является система координат в основном мире в механизме визуализации при отрисовке голограмм.One key use of a SpatialStationaryFrameOfReference is to act as the underlying world coordinate system within a rendering engine when rendering holograms.

Чтобы получить Спатиалстатионарифрамеофреференце, используйте класс спатиаллокатор и вызовите креатестатионарифрамеофреференцеаткуррентлокатион.To get a SpatialStationaryFrameOfReference, use the SpatialLocator class and call CreateStationaryFrameOfReferenceAtCurrentLocation.

Из кода шаблона приложения Windows holographic:From the Windows Holographic app template code:

           // The simplest way to render world-locked holograms is to create a stationary reference frame
           // when the app is launched. This is roughly analogous to creating a "world" coordinate system
           // with the origin placed at the device's position as the app is launched.
           referenceFrame = locator.CreateStationaryFrameOfReferenceAtCurrentLocation();
  • Стационарные опорные кадры предназначены для обеспечения наилучшего позиционирования относительно общего пространства.Stationary reference frames are designed to provide a best-fit position relative to the overall space. Отдельные положения в рамках рамки ссылки могут немного отменяться.Individual positions within that reference frame are allowed to drift slightly. Это нормально, так как устройство более подробно рассказывает о среде.This is normal as the device learns more about the environment.
  • Если требуется точное размещение отдельных голограмм, следует использовать Спатиаланчор, чтобы закрепить отдельную голограмму до положения в реальной жизни, например, для того, чтобы пользователь указывал на специальный интерес.When precise placement of individual holograms is required, a SpatialAnchor should be used to anchor the individual hologram to a position in the real world - for example, a point the user indicates to be of special interest. Позиции привязки не имеют смещения, но могут быть исправлены; привязка будет использовать исправленную точку, начиная со следующего кадра после исправления.Anchor positions don't drift, but can be corrected; the anchor will use the corrected position starting in the next frame after the correction has occurred.

Размещайте голограммы в мире с помощью пространственных привязокPlace holograms in the world using spatial anchors

Пространственные привязки — это отличный способ размещения голограмм в определенном месте в реальном мире, где система гарантирует, что привязка остается на месте с течением времени.Spatial anchors are a great way to place holograms at a specific place in the real world, with the system ensuring the anchor stays in place over time. В этом разделе объясняется, как создать и использовать привязку, а также как работать с данными привязки.This topic explains how to create and use an anchor, and how to work with anchor data.

Вы можете создать Спатиаланчор в любой позиции и ориентации в пределах Спатиалкурдинатесистем выбора.You can create a SpatialAnchor at any position and orientation within the SpatialCoordinateSystem of your choosing. Устройство должно иметь возможность нахождение этой системы координат в данный момент, и система не должна достигнуть предельного числа пространственных привязок.The device must be able to locate that coordinate system at the moment, and the system must not have reached its limit of spatial anchors.

После определения система координат Спатиаланчор настраивается непрерывно, чтобы обеспечить точную позицию и ориентацию исходного расположения.Once defined, the coordinate system of a SpatialAnchor adjusts continually to keep the precise position and orientation of its initial location. Затем эту Спатиаланчор можно использовать для визуализации голограмм, которые будут отображаться в пользовательской области в определенном месте.You can then use this SpatialAnchor to render holograms that will appear fixed in the user's surroundings at that exact location.

Влияние корректировок, которые сохраняют привязку на месте, увеличивается по мере увеличения расстояния от точки привязки.The effects of the adjustments that keep the anchor in place are magnified as distance from the anchor increases. Следует избегать отрисовки содержимого относительно привязки, которая больше 3 метров от источника этой привязки.You should avoid rendering content relative to an anchor that is more than about 3 meters from that anchor's origin.

Свойство курдинатесистем получает систему координат, которая позволяет разместить содержимое относительно привязки с применением замедления, когда устройство корректирует точное расположение привязки.The CoordinateSystem property gets a coordinate system that lets you place content relative to the anchor, with easing applied when the device adjusts the anchor's precise location.

Для самостоятельного управления настройкой используйте свойство равкурдинатесистем и соответствующее событие равкурдинатесистемаджустед .Use the RawCoordinateSystem property and the corresponding RawCoordinateSystemAdjusted event to manage these adjustments yourself.

Сохранение и совместное использование пространственных привязокPersist and share spatial anchors

Вы можете сохранить Спатиаланчор локально с помощью класса спатиаланчорсторе , а затем вернуть его в будущем сеансе приложения на том же устройстве HoloLens.You can persist a SpatialAnchor locally using the SpatialAnchorStore class and then get it back in a future app session on the same HoloLens device.

С помощью пространственных привязок Azureможно создать устойчивую облачную привязку на основе локальной спатиаланчор, которую приложение может затем разместить на нескольких устройствах HoloLens, iOS и Android.By using Azure Spatial Anchors, you can create a durable cloud anchor from a local SpatialAnchor, which your app can then locate across multiple HoloLens, iOS and Android devices. При совместном использовании общей пространственной привязки на нескольких устройствах каждый пользователь может видеть содержимое, отображаемое относительно этой привязки в том же физическом расположении в режиме реального времени.By sharing a common spatial anchor across multiple devices, each user can see content rendered relative to that anchor in the same physical location in real time.

Можно также использовать Пространственные привязки Azure для асинхронного сохранения голограмм на устройствах HoloLens, iOS и Android.You can also use Azure Spatial Anchors for asynchronous hologram persistence across HoloLens, iOS, and Android devices. При совместном использовании пространственной геодоступной облачной привязки несколько устройств могут отслеживать одну и ту же голограмму с течением времени, даже если эти устройства не присутствуют одновременно.By sharing a durable cloud spatial anchor, multiple devices can observe the same persisted hologram over time, even if those devices aren't present together at the same time.

Чтобы приступить к созданию общих интерфейсов в приложении HoloLens, ознакомьтесь с кратким руководством по HoloLens в течение 5 минут для пространственных привязок Azure.To get started building shared experiences in your HoloLens app, try out the 5-minute Azure Spatial Anchors HoloLens quickstart.

После завершения работы с пространственными привязками Azure можно создавать и размещать привязки на HoloLens.Once you're up and running with Azure Spatial Anchors, you can then create and locate anchors on HoloLens. Также доступны пошаговые руководства для Android и iOS , что позволяет использовать одни и те же привязки на всех устройствах.Walkthroughs are available for Android and iOS as well, enabling you to share the same anchors on all devices.

Создание Спатиаланчорс для holographic содержимогоCreate SpatialAnchors for holographic content

В этом примере кода мы изменили шаблон приложения Windows holographic для создания привязок при обнаружении нажатого жеста.For this code sample, we modified the Windows Holographic app template to create anchors when the Pressed gesture is detected. Затем куб помещается на привязку во время передачи прорисовки.The cube is then placed at the anchor during the render pass.

Так как вспомогательный класс поддерживает несколько привязок, можно разместить столько кубов, сколько нужно для использования этого примера кода!Since multiple anchors are supported by the helper class, we can place as many cubes as we want to use this code sample!

Примечание

Идентификаторы для привязок — это то, что вы управляете в приложении.The IDs for anchors are something you control in your app. В этом примере мы создали схему именования, которая будет последовательной в зависимости от количества привязок, которые в настоящее время хранятся в коллекции привязок приложения.In this example, we have created a naming scheme that is sequential based on the number of anchors currently stored in the app's collection of anchors.

   // Check for new input state since the last frame.
   SpatialInteractionSourceState^ pointerState = m_spatialInputHandler->CheckForInput();
   if (pointerState != nullptr)
   {
       // Try to get the pointer pose relative to the SpatialStationaryReferenceFrame.
       SpatialPointerPose^ pointerPose = pointerState->TryGetPointerPose(currentCoordinateSystem);
       if (pointerPose != nullptr)
       {
           // When a Pressed gesture is detected, the anchor will be created two meters in front of the user.

           // Get the gaze direction relative to the given coordinate system.
           const float3 headPosition = pointerPose->Head->Position;
           const float3 headDirection = pointerPose->Head->ForwardDirection;

           // The anchor position in the StationaryReferenceFrame.
           static const float distanceFromUser = 2.0f; // meters
           const float3 gazeAtTwoMeters = headPosition + (distanceFromUser * headDirection);

           // Create the anchor at position.
           SpatialAnchor^ anchor = SpatialAnchor::TryCreateRelativeTo(currentCoordinateSystem, gazeAtTwoMeters);

           if ((anchor != nullptr) && (m_spatialAnchorHelper != nullptr))
           {
               // In this example, we store the anchor in an IMap.
               auto anchorMap = m_spatialAnchorHelper->GetAnchorMap();

               // Create an identifier for the anchor.
               String^ id = ref new String(L"HolographicSpatialAnchorStoreSample_Anchor") + anchorMap->Size;

               anchorMap->Insert(id->ToString(), anchor);
           }
       }
   }

Асинхронная загрузка и кэширование, СпатиаланчорстореAsynchronously load, and cache, the SpatialAnchorStore

Давайте посмотрим, как написать класс Самплеспатиаланчорхелпер, который помогает справиться с этим сохраняемостью, в том числе:Let's see how to write a SampleSpatialAnchorHelper class that helps handle this persistence, including:

  • Хранение коллекции привязок в памяти, индексируемых ключом Platform:: String.Storing a collection of in-memory anchors, indexed by a Platform::String key.
  • Загрузка привязок из Спатиаланчорсторе системы, которая хранится отдельно от локальной коллекции в памяти.Loading anchors from the system's SpatialAnchorStore, which is kept separate from the local in-memory collection.
  • Сохранение локальной коллекции привязок в памяти в Спатиаланчорсторе при выборе приложения.Saving the local in-memory collection of anchors to the SpatialAnchorStore when the app chooses to do so.

Ниже показано, как сохранить объекты спатиаланчор в спатиаланчорсторе.Here's how to save SpatialAnchor objects in the SpatialAnchorStore.

При запуске класса мы запрашиваете Спатиаланчорсторе асинхронно.When the class starts up, we request the SpatialAnchorStore asynchronously. Это подразумевает системный ввод-вывод, так как API загружает хранилище привязки, и этот API становится асинхронным, чтобы операции ввода-вывода не блокировались.This involves system I/O as the API loads the anchor store, and this API is made asynchronous so that the I/O is non-blocking.

   // Request the spatial anchor store, which is the WinRT object that will accept the imported anchor data.
   return create_task(SpatialAnchorManager::RequestStoreAsync())
       .then([](task<SpatialAnchorStore^> previousTask)
   {
       std::shared_ptr<SampleSpatialAnchorHelper> newHelper = nullptr;

       try
       {
           SpatialAnchorStore^ anchorStore = previousTask.get();

           // Once the SpatialAnchorStore has been loaded by the system, we can create our helper class.

           // Using "new" to access private constructor
           newHelper = std::shared_ptr<SampleSpatialAnchorHelper>(new SampleSpatialAnchorHelper(anchorStore));

           // Now we can load anchors from the store.
           newHelper->LoadFromAnchorStore();
       }
       catch (Exception^ exception)
       {
           PrintWstringToDebugConsole(
               std::wstring(L"Exception while loading the anchor store: ") +
               exception->Message->Data() +
               L"\n"
               );
       }

       // Return the initialized class instance.
       return newHelper;
   });

Вам будет предоставлен Спатиаланчорсторе, который можно использовать для сохранения привязок.You'll be given a SpatialAnchorStore that you can use to save the anchors. Это IMapView, связывающая значения ключей, которые являются строками, со значениями данных, которые являются Спатиаланчорс.This is an IMapView that associates key values that are Strings, with data values that are SpatialAnchors. В нашем примере кода мы сохраняем это в переменной-члене закрытого класса, доступной через открытую функцию нашего вспомогательного класса.In our sample code, we store this in a private class member variable that is accessible through a public function of our helper class.

   SampleSpatialAnchorHelper::SampleSpatialAnchorHelper(SpatialAnchorStore^ anchorStore)
   {
       m_anchorStore = anchorStore;
       m_anchorMap = ref new Platform::Collections::Map<String^, SpatialAnchor^>();
   }

Примечание

Не забудьте подключить события приостановки и возобновления для сохранения и загрузки хранилища привязки.Don't forget to hook up the suspend/resume events to save and load the anchor store.

   void HolographicSpatialAnchorStoreSampleMain::SaveAppState()
   {
       // For example, store information in the SpatialAnchorStore.
       if (m_spatialAnchorHelper != nullptr)
       {
           m_spatialAnchorHelper->TrySaveToAnchorStore();
       }
   }
   void HolographicSpatialAnchorStoreSampleMain::LoadAppState()
   {
       // For example, load information from the SpatialAnchorStore.
       LoadAnchorStore();
   }

Сохранение содержимого в хранилище привязкиSave content to the anchor store

Когда система приостанавливает работу приложения, необходимо сохранить пространственные привязки в хранилище привязки.When the system suspends your app, you need to save your spatial anchors to the anchor store. Вы также можете сохранить привязки в хранилище привязки в другое время, так как вы увидите, что это необходимо для реализации приложения.You may also choose to save anchors to the anchor store at other times, as you find to be necessary for your app's implementation.

Когда вы будете готовы сохранить привязки в памяти для Спатиаланчорсторе, вы можете перебрать коллекцию и попытаться сохранить каждую из них.When you're ready to try saving the in-memory anchors to the SpatialAnchorStore, you can loop through your collection and try to save each one.

   // TrySaveToAnchorStore: Stores all anchors from memory into the app's anchor store.
   //
   // For each anchor in memory, this function tries to store it in the app's AnchorStore. The operation will fail if
   // the anchor store already has an anchor by that name.
   //
   bool SampleSpatialAnchorHelper::TrySaveToAnchorStore()
   {
       // This function returns true if all the anchors in the in-memory collection are saved to the anchor
       // store. If zero anchors are in the in-memory collection, we will still return true because the
       // condition has been met.
       bool success = true;

       // If access is denied, 'anchorStore' will not be obtained.
       if (m_anchorStore != nullptr)
       {
           for each (auto& pair in m_anchorMap)
           {
               auto const& id = pair->Key;
               auto const& anchor = pair->Value;

               // Try to save the anchors.
               if (!m_anchorStore->TrySave(id, anchor))
               {
                   // This may indicate the anchor ID is taken, or the anchor limit is reached for the app.
                   success=false;
               }
           }
       }

       return success;
   }

Загружать содержимое из хранилища привязки при возобновлении работы приложенияLoad content from the anchor store when the app resumes

Вы можете восстановить сохраненные привязки в Анчорсторе, передавая их из IMapView хранилища привязки в собственную базу данных в памяти Спатиаланчорс, когда приложение возобновляется или в любое время.You can restore saved anchors in the AnchorStore by transferring them from the anchor store's IMapView to your own in-memory database of SpatialAnchors when your app resumes or at any time.

Чтобы восстановить привязки из Спатиаланчорсторе, восстановите каждый из них, который вас интересует, в собственную коллекцию в памяти.To restore anchors from the SpatialAnchorStore, restore each one that you're interested in to your own in-memory collection.

Вам потребуется собственная база данных в памяти Спатиаланчорс, чтобы связать строки с создаваемым Спатиаланчорс.You need your own in-memory database of SpatialAnchors to associate Strings with the SpatialAnchors that you create. В нашем примере кода мы решили использовать Windows:: Foundation:: Collections:: IMap для хранения привязок, что позволяет легко использовать тот же ключ и значение данных для Спатиаланчорсторе.In our sample code, we choose to use a Windows::Foundation::Collections::IMap to store the anchors, which makes it easy to use the same key and data value for the SpatialAnchorStore.

   // This is an in-memory anchor list that is separate from the anchor store.
   // These anchors may be used, reasoned about, and so on before committing the collection to the store.
   Windows::Foundation::Collections::IMap<Platform::String^, Windows::Perception::Spatial::SpatialAnchor^>^ m_anchorMap;

Примечание

Восстанавливаемая привязка может не размещаемые сразу.An anchor that is restored might not be locatable right away. Например, это может быть привязка в отдельной комнате или в другом здании.For example, it might be an anchor in a separate room or in a different building altogether. Привязки, извлеченные из Анчорсторе, должны быть протестированы для локатабилити перед их использованием.Anchors retrieved from the AnchorStore should be tested for locatability before using them.


Примечание

В этом примере кода мы получаем все привязки из Анчорсторе.In this example code, we retrieve all anchors from the AnchorStore. Это не обязательно; приложение может точно выбрать и выбрать определенное подмножество привязок, используя значения ключа строки, которые являются значимыми для вашей реализации.This is not a requirement; your app could just as well pick and choose a certain subset of anchors by using String key values that are meaningful to your implementation.

   // LoadFromAnchorStore: Loads all anchors from the app's anchor store into memory.
   //
   // The anchors are stored in memory using an IMap, which stores anchors using a string identifier. Any string can be used as
   // the identifier; it can have meaning to the app, such as "Game_Leve1_CouchAnchor," or it can be a GUID that is generated
   // by the app.
   //
   void SampleSpatialAnchorHelper::LoadFromAnchorStore()
   {
       // If access is denied, 'anchorStore' will not be obtained.
       if (m_anchorStore != nullptr)
       {
           // Get all saved anchors.
           auto anchorMapView = m_anchorStore->GetAllSavedAnchors();
           for each (auto const& pair in anchorMapView)
           {
               auto const& id = pair->Key;
               auto const& anchor = pair->Value;
               m_anchorMap->Insert(id, anchor);
           }
       }
   }

Очищать хранилище привязки при необходимостиClear the anchor store, when needed

Иногда необходимо очистить состояние приложения и записать новые данные.Sometimes, you need to clear app state and write new data. Вот как это делается с помощью спатиаланчорсторе.Here's how you do that with the SpatialAnchorStore.

С помощью нашего вспомогательного класса практически не нужно обернуть функцию Clear.Using our helper class, it's almost unnecessary to wrap the Clear function. Мы решили сделать это в нашем примере реализации, так как наш вспомогательный класс получает ответственность за владельца экземпляра Спатиаланчорсторе.We choose to do so in our sample implementation, because our helper class is given the responsibility of owning the SpatialAnchorStore instance.

   // ClearAnchorStore: Clears the AnchorStore for the app.
   //
   // This function clears the AnchorStore. It has no effect on the anchors stored in memory.
   //
   void SampleSpatialAnchorHelper::ClearAnchorStore()
   {
       // If access is denied, 'anchorStore' will not be obtained.
       if (m_anchorStore != nullptr)
       {
           // Clear all anchors from the store.
           m_anchorStore->Clear();
       }
   }

Пример. Связывание систем координат привязки с стационарными системными координатами опорных кадровExample: Relating anchor coordinate systems to stationary reference frame coordinate systems

Предположим, у вас есть привязка и вы хотите связать что-то в системе координат привязки с Спатиалстатионариреференцефраме, который вы уже используете для вашего другого содержимого.Let's say you have an anchor, and you want to relate something in your anchor's coordinate system to the SpatialStationaryReferenceFrame you’re already using for your other content. Вы можете использовать трижеттрансформто , чтобы получить преобразование из системы координат привязки к элементу стационарного ссылочного фрейма:You can use TryGetTransformTo to get a transform from the anchor’s coordinate system to that of the stationary reference frame:

   // In this code snippet, someAnchor is a SpatialAnchor^ that has been initialized and is valid in the current environment.
   float4x4 anchorSpaceToCurrentCoordinateSystem;
   SpatialCoordinateSystem^ anchorSpace = someAnchor->CoordinateSystem;
   const auto tryTransform = anchorSpace->TryGetTransformTo(currentCoordinateSystem);
   if (tryTransform != nullptr)
   {
       anchorSpaceToCurrentCoordinateSystem = tryTransform->Value;
   }

Этот процесс полезен в двух случаях:This process is useful to you in two ways:

  1. Он указывает, что два эталонных кадра могут быть понятны относительно друг друга, и;It tells you if the two reference frames can be understood relative to one another, and;
  2. Если это так, он предоставляет преобразование для непосредственного перехода от одной системы координат к другой.If so, it provides you a transform to go directly from one coordinate system to the other.

С помощью этих сведений вы получите представление о пространственной связи между объектами между двумя эталонными кадрами.With this information, you have an understanding of the spatial relation between objects between the two reference frames.

Для подготовки к просмотру часто можно получить лучшие результаты, группируя объекты в соответствии с их исходным эталонным фреймом или привязкой.For rendering, you can often obtain better results by grouping objects according to their original reference frame or anchor. Выполните отдельный этап отрисовки для каждой группы.Perform a separate drawing pass for each group. Матрицы представления более точны для объектов с преобразованиями модели, которые изначально создаются с использованием одной и той же системы координат.The view matrices are more accurate for objects with model transforms that are created initially using the same coordinate system.

Создание голограмм с помощью привязанного к устройству фрейма ссылкиCreate holograms using a device-attached frame of reference

Иногда требуется отобразить голограмму, которая остается прикрепленной к расположению устройства, например панель с отладочной информацией или информационное сообщение, если устройство может определить его ориентацию, а не его положение в пространстве.There are times when you want to render a hologram that remains attached to the device's location, for example a panel with debugging information or an informational message when the device is only able to determine its orientation and not its position in space. Для этого мы используем присоединенный фрейм ссылки.To accomplish this, we use an attached frame of reference.

Класс Спатиаллокатораттачедфрамеофреференце определяет системы координат, которые являются относительными для устройства, а не для реального мира.The SpatialLocatorAttachedFrameOfReference class defines coordinate systems, which are relative to the device rather than to the real-world. Этот кадр имеет фиксированный заголовок относительно окружающей среды пользователя, указывающий в направлении, в котором пользователь был направлен при создании эталонного фрейма.This frame has a fixed heading relative to the user's surroundings that points in the direction the user was facing when the reference frame was created. После этого все ориентации в этой рамке ссылки зависят от этого фиксированного заголовка, даже при вращении устройства пользователем.From then on, all orientations in this frame of reference are relative to that fixed heading, even as the user rotates the device.

Для HoloLens происхождение системы координат этого фрейма находится в центре вращения заголовка пользователя, чтобы его положение не влияло на поворот головного элемента.For HoloLens, the origin of this frame's coordinate system is located at the center of rotation of the user's head, so that its position is not affected by head rotation. Приложение может указать смещение относительно этой точки, чтобы разместить голограммы перед пользователем.Your app can specify an offset relative to this point to position holograms in front of the user.

Чтобы получить Спатиаллокатораттачедфрамеофреференце, используйте класс Спатиаллокатор и вызовите Креатеаттачедфрамеофреференцеаткурренсеадинг.To get a SpatialLocatorAttachedFrameOfReference, use the SpatialLocator class and call CreateAttachedFrameOfReferenceAtCurrentHeading.

Это относится ко всему диапазону устройств Windows Mixed Reality.This applies to the entire range of Windows Mixed Reality devices.

Использование ссылочного фрейма, присоединенного к устройствуUse a reference frame attached to the device

В этих разделах мы поговорим о том, что мы изменили в шаблоне приложения Windows holographic, чтобы включить связанный с устройством фрейм ссылки с помощью этого API.These sections talk about what we changed in the Windows Holographic app template to enable a device-attached frame of reference using this API. Эта «присоединенная» голограмма будет работать наряду с стационарными или прикрепленными голограммами, а также может использоваться, когда устройство временно не может найти свое местоположение в мире.This "attached" hologram will work alongside stationary or anchored holograms, and may also be used when the device is temporarily unable to find its position in the world.

Сначала мы изменили шаблон, чтобы сохранить Спатиаллокатораттачедфрамеофреференце вместо Спатиалстатионарифрамеофреференце:First, we changed the template to store a SpatialLocatorAttachedFrameOfReference instead of a SpatialStationaryFrameOfReference:

Из холографиктагалонгсамплемаин. h:From HolographicTagAlongSampleMain.h:

   // A reference frame attached to the holographic camera.
   Windows::Perception::Spatial::SpatialLocatorAttachedFrameOfReference^   m_referenceFrame;

Из холографиктагалонгсамплемаин. cpp:From HolographicTagAlongSampleMain.cpp:

   // In this example, we create a reference frame attached to the device.
   m_referenceFrame = m_locator->CreateAttachedFrameOfReferenceAtCurrentHeading();

В ходе обновления теперь мы получаем систему координат в отметке времени, полученной с помощью прогнозирования кадров.During the update, we now obtain the coordinate system at the time stamp obtained from with the frame prediction.

   // Next, we get a coordinate system from the attached frame of reference that is
   // associated with the current frame. Later, this coordinate system is used for
   // for creating the stereo view matrices when rendering the sample content.
   SpatialCoordinateSystem^ currentCoordinateSystem =
       m_referenceFrame->GetStationaryCoordinateSystemAtTimestamp(prediction->Timestamp);

Получение пространственного указателя a и отслеживание пользователяGet a spatial pointer pose, and follow the user's Gaze

Мы хотим, чтобы наш пример голограммы проследовала взглядпользователя, аналогично тому, как с помощью оболочки holographic можно следовать взгляду пользователя.We want our example hologram to follow the user's gaze, similar to how the holographic shell can follow the user's gaze. Для этого нам нужно получить Спатиалпоинтерпосе из той же метки времени.For this, we need to get the SpatialPointerPose from the same time stamp.

SpatialPointerPose^ pose = SpatialPointerPose::TryGetAtTimestamp(currentCoordinateSystem, prediction->Timestamp);

Этот Спатиалпоинтерпосе содержит сведения, необходимые для размещения голограммы в соответствии с текущим заголовком пользователя.This SpatialPointerPose has the information needed to position the hologram according to the user's current heading.

Для удобства пользователя мы используем линейную интерполяцию ("лерп"), чтобы сгладить изменение в положении в течение определенного периода времени.For user comfort, we use linear interpolation ("lerp") to smooth the change in position over a period of time. Это более удобно для пользователя, чем блокировка голограммы до их взгляда.This is more comfortable for the user than locking the hologram to their gaze. Лерпингая с тегом голограмма также позволяет нам стабилизировать голограмму путем ослабления движения.Lerping the tag-along hologram's position also allows us to stabilize the hologram by dampening the movement. Если это ослабление не было сделано, пользователь увидит неограниченную голограмму из-за того, что обычно считается незаметной передвижением заголовка пользователя.If we didn't do this dampening, the user would see the hologram jitter because of what are normally considered to be imperceptible movements of the user's head.

Из статионарикуадрендерер::P оситионхолограм:From StationaryQuadRenderer::PositionHologram:

   const float& dtime = static_cast<float>(timer.GetElapsedSeconds());

   if (pointerPose != nullptr)
   {
       // Get the gaze direction relative to the given coordinate system.
       const float3 headPosition  = pointerPose->Head->Position;
       const float3 headDirection = pointerPose->Head->ForwardDirection;

       // The tag-along hologram follows a point 2.0m in front of the user's gaze direction.
       static const float distanceFromUser = 2.0f; // meters
       const float3 gazeAtTwoMeters = headPosition + (distanceFromUser * headDirection);

       // Lerp the position, to keep the hologram comfortably stable.
       auto lerpedPosition = lerp(m_position, gazeAtTwoMeters, dtime * c_lerpRate);

       // This will be used as the translation component of the hologram's
       // model transform.
       SetPosition(lerpedPosition);
   }

Примечание

В случае панели отладки можно изменить положение голограммы на сторону немного, чтобы она не переходила на ваше представление.In the case of a debugging panel, you might choose to reposition the hologram off to the side a little so that it doesn't obstruct your view. Ниже приведен пример того, как это можно сделать.Here's an example of how you might do that.

Для статионарикуадрендерер::P оситионхолограм:For StationaryQuadRenderer::PositionHologram:

       // If you're making a debug view, you might not want the tag-along to be directly in the
       // center of your field of view. Use this code to position the hologram to the right of
       // the user's gaze direction.
       /*
       const float3 offset = float3(0.13f, 0.0f, 0.f);
       static const float distanceFromUser = 2.2f; // meters
       const float3 gazeAtTwoMeters = headPosition + (distanceFromUser * (headDirection + offset));
       */

Поворот голограммы на камеруRotate the hologram to face the camera

Не хватает для размещения голограммы, которая в данном случае является четырехъядерной; также необходимо повернуть объект, чтобы он был лицом к пользователю.It isn't enough to position the hologram, which in this case is a quad; we must also rotate the object to face the user. Этот поворот происходит в мировом пространстве, поскольку этот тип рекламы позволяет оставить голограмму частью среды пользователя.This rotation occurs in world space, because this type of billboarding allows the hologram to remain a part of the user's environment. Переход на пробелы в представлении не так удобен, так как голограмма становится заблокированной для ориентации экрана; в этом случае необходимо также выполнить интерполяцию между левым и правым матрицами представлений, чтобы получить преобразование стенда представления, которое не нарушает стерео отрисовку.View-space billboarding isn't as comfortable because the hologram becomes locked to the display orientation; in that case, you would also have to interpolate between the left and right view matrices to acquire a view-space billboard transform that doesn't disrupt stereo rendering. Здесь мы поворотим на оси X и Z пользователя.Here, we rotate on the X and Z axes to face the user.

Из статионарикуадрендерер:: Update:From StationaryQuadRenderer::Update:

   // Seconds elapsed since previous frame.
   const float& dTime = static_cast<float>(timer.GetElapsedSeconds());

   // Create a direction normal from the hologram's position to the origin of person space.
   // This is the z-axis rotation.
   XMVECTOR facingNormal = XMVector3Normalize(-XMLoadFloat3(&m_position));

   // Rotate the x-axis around the y-axis.
   // This is a 90-degree angle from the normal, in the xz-plane.
   // This is the x-axis rotation.
   XMVECTOR xAxisRotation = XMVector3Normalize(XMVectorSet(XMVectorGetZ(facingNormal), 0.f, -XMVectorGetX(facingNormal), 0.f));

   // Create a third normal to satisfy the conditions of a rotation matrix.
   // The cross product  of the other two normals is at a 90-degree angle to
   // both normals. (Normalize the cross product to avoid floating-point math
   // errors.)
   // Note how the cross product will never be a zero-matrix because the two normals
   // are always at a 90-degree angle from one another.
   XMVECTOR yAxisRotation = XMVector3Normalize(XMVector3Cross(facingNormal, xAxisRotation));

   // Construct the 4x4 rotation matrix.

   // Rotate the quad to face the user.
   XMMATRIX rotationMatrix = XMMATRIX(
       xAxisRotation,
       yAxisRotation,
       facingNormal,
       XMVectorSet(0.f, 0.f, 0.f, 1.f)
       );

   // Position the quad.
   const XMMATRIX modelTranslation = XMMatrixTranslationFromVector(XMLoadFloat3(&m_position));

   // The view and projection matrices are provided by the system; they are associated
   // with holographic cameras, and updated on a per-camera basis.
   // Here, we provide the model transform for the sample hologram. The model transform
   // matrix is transposed to prepare it for the shader.
   XMStoreFloat4x4(&m_modelConstantBufferData.model, XMMatrixTranspose(rotationMatrix * modelTranslation));

Подготовка присоединенной голограммыRender the attached hologram

В этом примере мы также решили визуализировать голограмму в системе координат Спатиаллокатораттачедреференцефраме, где мы разберем голограмму.For this example, we also choose to render the hologram in the coordinate system of the SpatialLocatorAttachedReferenceFrame, which is where we positioned the hologram. (Если бы мы решили подготовиться к просмотру с помощью другой системы координат, нам пришлось бы получить преобразование из системы координат связанного с устройством ссылочного фрейма в эту систему координат.)(If we had decided to render using another coordinate system, we would need to acquire a transform from the device-attached reference frame's coordinate system to that coordinate system.)

Из холографиктагалонгсамплемаин:: Render:From HolographicTagAlongSampleMain::Render:

   // The view and projection matrices for each holographic camera will change
   // every frame. This function refreshes the data in the constant buffer for
   // the holographic camera indicated by cameraPose.
   pCameraResources->UpdateViewProjectionBuffer(
       m_deviceResources,
       cameraPose,
       m_referenceFrame->GetStationaryCoordinateSystemAtTimestamp(prediction->Timestamp)
       );

Вот и все!That's it! Голограмма теперь будет «проследить» расположение, равное 2 метрах, перед направлением взгляда пользователя.The hologram will now "chase" a position that is 2 meters in front of the user's gaze direction.

Примечание

В этом примере также загружается дополнительное содержимое — см. Статионарикуадрендерер. cpp.This example also loads additional content - see StationaryQuadRenderer.cpp.

Обработка потерь отслеживанияHandling tracking loss

Если устройство не может располагаться в мире, в приложении происходит «отслеживание потерь».When the device can't locate itself in the world, the app experiences "tracking loss". Приложения Windows Mixed Reality должны иметь возможность обрабатывать такие нарушения в системе нацеленного отслеживания.Windows Mixed Reality apps should be able to handle such disruptions to the positional tracking system. Эти нарушения можно наблюдать и создавать ответы с помощью события Локатабилитичанжед по умолчанию Спатиаллокатор.These disruptions can be observed, and responses created, by using the LocatabilityChanged event on the default SpatialLocator.

Из аппмаин:: сесолографикспаце:From AppMain::SetHolographicSpace:

   // Be able to respond to changes in the positional tracking state.
   m_locatabilityChangedToken =
       m_locator->LocatabilityChanged +=
           ref new Windows::Foundation::TypedEventHandler<SpatialLocator^, Object^>(
               std::bind(&HolographicApp1Main::OnLocatabilityChanged, this, _1, _2)
               );

Когда приложение получает событие Локатабилитичанжед, оно может изменить поведение по мере необходимости.When your app receives a LocatabilityChanged event, it can change behavior as needed. Например, в состоянии Поситионалтраккингинхибитед приложение может приостановить нормальную работу и вывести на экран голограмму с пометкой , которая отображает предупреждающее сообщение.For example, in the PositionalTrackingInhibited state, your app can pause normal operation and render a tag-along hologram that displays a warning message.

Шаблон приложения Windows holographic поставляется с уже созданным обработчиком Локатабилитичанжед.The Windows Holographic app template comes with a LocatabilityChanged handler already created for you. По умолчанию в консоли отладки отображается предупреждение, если позиционированное отслеживание недоступно.By default, it displays a warning in the debug console when positional tracking is unavailable. Вы можете добавить код в этот обработчик, чтобы предоставить ответ по мере необходимости из приложения.You can add code to this handler to provide a response as needed from your app.

Из аппмаин. cpp:From AppMain.cpp:

   void HolographicApp1Main::OnLocatabilityChanged(SpatialLocator^ sender, Object^ args)
   {
       switch (sender->Locatability)
       {
       case SpatialLocatability::Unavailable:
           // Holograms cannot be rendered.
           {
               String^ message = L"Warning! Positional tracking is " +
                                           sender->Locatability.ToString() + L".\n";
               OutputDebugStringW(message->Data());
           }
           break;

       // In the following three cases, it is still possible to place holograms using a
       // SpatialLocatorAttachedFrameOfReference.
       case SpatialLocatability::PositionalTrackingActivating:
           // The system is preparing to use positional tracking.

       case SpatialLocatability::OrientationOnly:
           // Positional tracking has not been activated.

       case SpatialLocatability::PositionalTrackingInhibited:
           // Positional tracking is temporarily inhibited. User action may be required
           // in order to restore positional tracking.
           break;

       case SpatialLocatability::PositionalTrackingActive:
           // Positional tracking is active. World-locked content can be rendered.
           break;
       }
   }

пространственное сопоставлениеSpatial mapping

API-интерфейсы пространственного сопоставления используют системы координат для получения преобразований модели для сеток поверхности.The spatial mapping APIs make use of coordinate systems to get model transforms for surface meshes.

См. также разделSee also