Systèmes de coordonnées dans DirectXCoordinate systems in DirectX

Notes

Cet article s’applique aux API natives WinRT héritées.This article relates to the legacy WinRT native APIs. Pour les nouveaux projets d’application native, nous vous recommandons d’utiliser l' API OpenXR.For new native app projects, we recommend using the OpenXR API.

Les systèmes de coordonnées constituent la base de la compréhension spatiale offerte par les API Windows Mixed Reality.Coordinate systems form the basis for spatial understanding offered by Windows Mixed Reality APIs.

Les appareils en VR ou monolocal d’aujourd’hui établissent un système de coordonnées principal pour leur espace suivi.Today's seated VR or single-room VR devices establish one primary coordinate system for their tracked space. Les appareils de réalité mixte, tels que HoloLens, sont conçus pour les environnements non définis volumineux, avec la découverte des appareils et l’apprentissage de son environnement à mesure que l’utilisateur parcourt.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. L’appareil s’adapte à l’amélioration continue des connaissances sur les salles de l’utilisateur, mais génère des systèmes de coordonnées qui modifient leur relation les uns par rapport aux autres pendant la durée de vie des applications.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 prend en charge un large éventail d’appareils, allant des casques immersifs intégrés à des châssis de référence universels.Windows Mixed Reality supports a wide spectrum of devices, ranging from seated immersive headsets through world-attached reference frames.

Notes

Les extraits de code de cet article illustrent actuellement l’utilisation de C++/CX au lieu des/WinRT C++ conformes à C + +17, tels qu’ils sont utilisés dans le modèle de projet holographique c++.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. Les concepts sont équivalents pour un projet C++/WinRT, bien que vous deviez traduire le code.The concepts are equivalent for a C++/WinRT project, though you will need to translate the code.

Systèmes de coordonnées spatiales dans WindowsSpatial coordinate systems in Windows

Le type de cœur utilisé pour la raison des systèmes de coordonnées réels dans Windows est le SpatialCoordinateSystem.The core type used to reason about real-world coordinate systems in Windows is the SpatialCoordinateSystem. Une instance de ce type représente un système de coordonnées arbitraire, fournissant une méthode permettant d’obtenir des données de matrice de transformation que vous pouvez utiliser pour transformer deux systèmes de coordonnées sans comprendre les détails de chacun d’entre eux.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.

Les méthodes qui retournent des informations spatiales acceptent un paramètre SpatialCoordinateSystem pour vous permettre de choisir le système de coordonnées dans lequel elles sont les plus utiles pour que ces coordonnées soient retournées.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. Les informations spatiales sont représentées par des points, des rayons ou des volumes dans l’environnement de l’utilisateur, et les unités de ces coordonnées sont toujours exprimées en mètres.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.

Un SpatialCoordinateSystem a une relation dynamique avec d’autres systèmes de coordonnées, y compris ceux qui représentent la position de l’appareil.A SpatialCoordinateSystem has a dynamic relationship with other coordinate systems, including those that represent the device's position. À tout moment, l’appareil peut localiser certains systèmes de coordonnées et pas d’autres.At any point, the device can locate some coordinate systems and not others. Pour la plupart des systèmes de coordonnées, votre application doit être prête à gérer les périodes pendant lesquelles elles sont introuvables.For most coordinate systems, your app must be ready to handle periods of time during which they cannot be located.

Votre application ne doit pas créer de SpatialCoordinateSystems directement, mais elle doit être utilisée via les API de perception.Your application shouldn't create SpatialCoordinateSystems directly - rather they should be consumed via the Perception APIs. Il existe trois sources principales de systèmes de coordonnées dans les API de perception, chacune d’elles étant mappée à un concept décrit dans la page des systèmes de coordonnées :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:

Tous les systèmes de coordonnées retournés par ces objets sont droitiers, avec + y vers le haut, + x vers la droite et + z vers l’arrière.All of the coordinate systems returned by these objects are right-handed, with +y up, +x to the right and +z backwards. Vous pouvez vous souvenir de la direction vers laquelle pointe l’axe z positif en pointant les doigts de votre gauche ou de droite dans la direction x positive et en les plaçant dans la direction y positive.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. La direction vers laquelle votre Thumb pointe, que ce soit vers vous ou en dehors, est la direction dans laquelle les points positifs de l’axe z pour ce système de coordonnées.The direction your thumb points, either toward or away from you, is the direction that the positive z-axis points for that coordinate system. L’illustration suivante montre ces deux systèmes de coordonnées.The following illustration shows these two coordinate systems.

Systèmes de coordonnées à gauche et à droiteLeft-hand and right-hand coordinate systems
Systèmes de coordonnées à gauche et à droiteLeft-hand and right-hand coordinate systems

Utilisez la classe SpatialLocator pour créer une image jointe ou stationnaire de référence au démarrage dans un SpatialCoordinateSystem en fonction de la position 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. Passez à la section suivante pour en savoir plus sur ce processus.Continue to the next section to learn more about this process.

Placer des hologrammes dans le monde à l’aide d’une étape spatialePlace holograms in the world using a spatial stage

Le système de coordonnées pour les casques immersifs immersifs de la réalité Windows mixed est accessible à l’aide de la propriété statique SpatialStageFrameOfReference :: Current .The coordinate system for opaque Windows Mixed Reality immersive headsets is accessed using the static SpatialStageFrameOfReference::Current property. Cette API fournit les éléments suivants :This API provides:

  • Système de coordonnéesA coordinate system
  • Informations indiquant si le joueur est assis ou mobileInformation about whether the player is seated or mobile
  • Limite d’une zone sécurisée pour se déplacer si le joueur est mobileThe boundary of a safe area for walking around if the player is mobile
  • Indique si le casque est directionnel.An indication of whether the headset is directional.
  • Gestionnaire d’événements pour les mises à jour de la phase spatiale.An event handler for updates to the spatial stage.

Tout d’abord, nous obtenons la phase spatiale et m’abonnons aux mises à jour :First, we get the spatial stage and subscribe for updates to it:

Code pour l’initialisation de la phase spatialeCode 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);
}

Dans la méthode OnCurrentChanged, votre application doit inspecter la phase spatiale et mettre à jour l’expérience du joueur.In the OnCurrentChanged method, your app should inspect the spatial stage and update the player experience. Dans cet exemple, nous fournissons une visualisation de la limite de la phase et de la position de départ spécifiée par l’utilisateur, ainsi que de la plage de la vue et de la plage de propriétés de déplacement de l’étape.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. Nous revenons également à notre propre système de coordonnées stationnaires, lorsqu’une étape ne peut pas être fournie.We also fall back to our own stationary coordinate system, when a stage cannot be provided.

Code pour la mise à jour de la phase spatialeCode 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);
        }
    }
}

L’ensemble des vertex qui définissent les limites de l’étape sont fournis dans l’ordre des aiguilles d’une montre.The set of vertices that define the stage boundary are provided in clockwise order. Le shell Windows Mixed Reality dessine une clôture à la limite lorsque l’utilisateur l’approche, mais vous pouvez souhaiter triangulairer la zone à votre propre usage.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. L’algorithme suivant peut être utilisé pour triangulairer la phase.The following algorithm can be used to triangularize the stage.

Code pour triangulaire de la phase spatialeCode 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;
}

Placez des hologrammes dans le monde à l’aide d’un cadre stationnaire de référencePlace holograms in the world using a stationary frame of reference

La classe SpatialStationaryFrameOfReference représente une image de référence qui reste stationnaire par rapport à l’environnement de l’utilisateur au fur et à mesure que l’utilisateur se déplace.The SpatialStationaryFrameOfReference class represents a frame of reference that remains stationary relative to the user's surroundings as the user moves around. Ce cadre de référence établit une priorité pour maintenir les coordonnées stables près de l’appareil.This frame of reference prioritizes keeping coordinates stable near the device. L’une des principales utilisation d’un SpatialStationaryFrameOfReference consiste à agir comme système de coordonnées universelles sous-jacent dans un moteur de rendu lors du rendu d’hologrammes.One key use of a SpatialStationaryFrameOfReference is to act as the underlying world coordinate system within a rendering engine when rendering holograms.

Pour obtenir un SpatialStationaryFrameOfReference, utilisez la classe SpatialLocator et appelez CreateStationaryFrameOfReferenceAtCurrentLocation.To get a SpatialStationaryFrameOfReference, use the SpatialLocator class and call CreateStationaryFrameOfReferenceAtCurrentLocation.

À partir du code du modèle d’application holographique Windows :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();
  • Les frames de référence stationnaires sont conçus pour fournir une position la mieux adaptée par rapport à l’espace global.Stationary reference frames are designed to provide a best-fit position relative to the overall space. Les positions individuelles dans ce frame de référence sont autorisées à dériver légèrement.Individual positions within that reference frame are allowed to drift slightly. Cela est normal, car l’appareil en apprend davantage sur l’environnement.This is normal as the device learns more about the environment.
  • Lorsque le positionnement précis des hologrammes individuels est requis, un SpatialAnchor doit être utilisé pour ancrer l’hologramme individuel à une position dans le monde réel (par exemple, un point que l’utilisateur indique d’avoir un intérêt particulier).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. Les positions d’ancrage ne dérivent pas, mais peuvent être corrigées ; le point d’ancrage utilise la position corrigée à partir de l’image suivante, une fois la correction effectuée.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.

Placer des hologrammes dans le monde à l’aide d’ancres spatialesPlace holograms in the world using spatial anchors

Les ancres spatiales sont un excellent moyen de placer des hologrammes à un endroit précis dans le monde réel, le système garantissant que l’ancre reste en place au fil du temps.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. Cette rubrique explique comment créer et utiliser une ancre, et comment utiliser les données d’ancrage.This topic explains how to create and use an anchor, and how to work with anchor data.

Vous pouvez créer un SpatialAnchor à n’importe quelle position et orientation dans le SpatialCoordinateSystem de votre choix.You can create a SpatialAnchor at any position and orientation within the SpatialCoordinateSystem of your choosing. L’appareil doit être en mesure de localiser ce système de coordonnées pour le moment et le système ne doit pas avoir atteint sa limite d’ancrages spatiaux.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.

Une fois défini, le système de coordonnées d’un SpatialAnchor s’ajuste continuellement pour conserver la position et l’orientation précises de son emplacement initial.Once defined, the coordinate system of a SpatialAnchor adjusts continually to keep the precise position and orientation of its initial location. Vous pouvez ensuite utiliser ce SpatialAnchor pour afficher des hologrammes qui seront corrigés dans l’environnement de l’utilisateur à cet emplacement exact.You can then use this SpatialAnchor to render holograms that will appear fixed in the user's surroundings at that exact location.

Les effets des ajustements qui maintiennent l’ancre sont agrandis à mesure que la distance entre l’ancrage augmente.The effects of the adjustments that keep the anchor in place are magnified as distance from the anchor increases. Vous devez éviter de rendre le contenu relatif à une ancre qui est supérieure à environ 3 mètres de l’origine de cette ancre.You should avoid rendering content relative to an anchor that is more than about 3 meters from that anchor's origin.

La propriété CoordinateSystem obtient un système de coordonnées qui vous permet de placer du contenu par rapport à l’ancre, avec une accélération appliquée lorsque l’appareil ajuste l’emplacement précis de l’ancre.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.

Utilisez la propriété RawCoordinateSystem et l’événement RawCoordinateSystemAdjusted correspondant pour gérer ces réglages vous-même.Use the RawCoordinateSystem property and the corresponding RawCoordinateSystemAdjusted event to manage these adjustments yourself.

Conserver et partager des ancres spatialesPersist and share spatial anchors

Vous pouvez conserver un SpatialAnchor localement à l’aide de la classe SpatialAnchorStore , puis le récupérer dans une session d’application future sur le même appareil 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.

En utilisant des ancres spatiales Azure, vous pouvez créer une ancre Cloud durable à partir d’un SpatialAnchor local, que votre application peut ensuite localiser sur plusieurs appareils HoloLens, iOS et 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. En partageant une ancre spatiale commune sur plusieurs appareils, chaque utilisateur peut voir le contenu rendu relatif à cette ancre dans le même emplacement physique en temps réel.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.

Vous pouvez également utiliser des ancres spatiales Azure pour la persistance des hologrammes asynchrones sur les appareils HoloLens, iOS et Android.You can also use Azure Spatial Anchors for asynchronous hologram persistence across HoloLens, iOS, and Android devices. En partageant une ancre spatiale Cloud durable, plusieurs appareils peuvent observer le même hologramme persistant dans le temps, même si ces appareils ne sont pas présents simultanément.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.

Pour commencer à créer des expériences partagées dans votre application HoloLens, essayez le démarrage rapide de 5 minutes d' ancrage spatial Azure HoloLens.To get started building shared experiences in your HoloLens app, try out the 5-minute Azure Spatial Anchors HoloLens quickstart.

Une fois que vous êtes opérationnel avec les ancres spatiales Azure, vous pouvez créer et localiser des ancres sur HoloLens.Once you're up and running with Azure Spatial Anchors, you can then create and locate anchors on HoloLens. Les procédures pas à pas sont également disponibles pour Android et iOS , ce qui vous permet de partager les mêmes ancres sur tous les appareils.Walkthroughs are available for Android and iOS as well, enabling you to share the same anchors on all devices.

Créer des SpatialAnchors pour le contenu holographiqueCreate SpatialAnchors for holographic content

Pour cet exemple de code, nous avons modifié le modèle d’application holographique Windows pour créer des ancres lorsque le geste appuyé est détecté.For this code sample, we modified the Windows Holographic app template to create anchors when the Pressed gesture is detected. Le cube est ensuite placé au point d’ancrage pendant la passe de rendu.The cube is then placed at the anchor during the render pass.

Étant donné que plusieurs ancres sont prises en charge par la classe d’assistance, nous pouvons placer autant de cubes que nous voulons utiliser cet exemple de code !Since multiple anchors are supported by the helper class, we can place as many cubes as we want to use this code sample!

Notes

Les ID des ancres sont des éléments que vous contrôlez dans votre application.The IDs for anchors are something you control in your app. Dans cet exemple, nous avons créé un modèle d’affectation de noms qui est séquentiel en fonction du nombre d’ancres actuellement stockées dans la collection d’ancres de l’application.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);
           }
       }
   }

Charger et mettre en cache de façon asynchrone SpatialAnchorStoreAsynchronously load, and cache, the SpatialAnchorStore

Voyons comment écrire une classe SampleSpatialAnchorHelper qui permet de gérer cette persistance, notamment :Let's see how to write a SampleSpatialAnchorHelper class that helps handle this persistence, including:

  • Stockage d’une collection d’ancres en mémoire, indexées par une clé Platform :: String.Storing a collection of in-memory anchors, indexed by a Platform::String key.
  • Chargement des ancres à partir du SpatialAnchorStore du système, qui est conservé distinct de la collection en mémoire locale.Loading anchors from the system's SpatialAnchorStore, which is kept separate from the local in-memory collection.
  • Enregistrement de la collection en mémoire locale des ancres dans le SpatialAnchorStore quand l’application choisit de le faire.Saving the local in-memory collection of anchors to the SpatialAnchorStore when the app chooses to do so.

Voici comment enregistrer des objets SpatialAnchor dans SpatialAnchorStore.Here's how to save SpatialAnchor objects in the SpatialAnchorStore.

Lorsque la classe démarre, nous recherchons le SpatialAnchorStore de manière asynchrone.When the class starts up, we request the SpatialAnchorStore asynchronously. Cela implique des e/s système, car l’API charge le magasin d’ancrage, et cette API est rendue asynchrone afin que les e/s soient non bloquantes.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;
   });

Vous disposez d’un SpatialAnchorStore que vous pouvez utiliser pour enregistrer les ancres.You'll be given a SpatialAnchorStore that you can use to save the anchors. Il s’agit d’un IMapView qui associe des valeurs de clés qui sont des chaînes, avec des valeurs de données qui sont SpatialAnchors.This is an IMapView that associates key values that are Strings, with data values that are SpatialAnchors. Dans notre exemple de code, nous le stockons dans une variable membre de classe privée qui est accessible par le biais d’une fonction publique de notre classe d’assistance.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^>();
   }

Notes

N’oubliez pas de raccorder les événements de suspension/reprise pour enregistrer et charger le magasin d’ancrage.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();
   }

Enregistrer le contenu dans le magasin d’ancrageSave content to the anchor store

Lorsque le système interrompt votre application, vous devez enregistrer vos ancres spatiales dans le magasin d’ancrage.When the system suspends your app, you need to save your spatial anchors to the anchor store. Vous pouvez également choisir d’enregistrer les ancres dans le magasin d’ancrage à d’autres moments, car vous en aurez besoin pour l’implémentation de votre application.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.

Lorsque vous êtes prêt à essayer d’enregistrer les ancres en mémoire dans le SpatialAnchorStore, vous pouvez parcourir votre collection et essayer d’enregistrer chacune d’elles.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;
   }

Charger le contenu à partir du magasin d’ancrage lorsque l’application reprendLoad content from the anchor store when the app resumes

Vous pouvez restaurer les ancres enregistrées dans le AnchorStore en les transférant du IMapView du magasin d’ancrage à votre propre base de données en mémoire de SpatialAnchors lorsque votre application reprend ou à tout moment.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.

Pour restaurer les ancres à partir du SpatialAnchorStore, restaurez chacune d’elles qui vous intéresse à votre propre collection en mémoire.To restore anchors from the SpatialAnchorStore, restore each one that you're interested in to your own in-memory collection.

Vous avez besoin de votre propre base de données en mémoire de SpatialAnchors pour associer des chaînes au SpatialAnchors que vous créez.You need your own in-memory database of SpatialAnchors to associate Strings with the SpatialAnchors that you create. Dans notre exemple de code, nous choisissons d’utiliser un Windows :: Foundation :: Collections :: IMap pour stocker les ancres, ce qui facilite l’utilisation de la même clé et de la même valeur de données pour SpatialAnchorStore.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;

Notes

Une ancre qui est restaurée peut ne pas être localisable immédiatement.An anchor that is restored might not be locatable right away. Par exemple, il peut s’agir d’une ancre dans une salle distincte ou dans une construction différente.For example, it might be an anchor in a separate room or in a different building altogether. Les ancres récupérées à partir du AnchorStore doivent être testées en vue de leur localisation avant de les utiliser.Anchors retrieved from the AnchorStore should be tested for locatability before using them.


Notes

Dans cet exemple de code, nous récupérons toutes les ancres du AnchorStore.In this example code, we retrieve all anchors from the AnchorStore. Ce n’est pas une condition requise. votre application peut tout aussi bien sélectionner et choisir un certain sous-ensemble d’ancres à l’aide de valeurs de clés de chaîne qui sont significatives pour votre implémentation.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);
           }
       }
   }

Effacer le magasin d’ancrage, si nécessaireClear the anchor store, when needed

Parfois, vous devez effacer l’état de l’application et écrire de nouvelles données.Sometimes, you need to clear app state and write new data. Voici comment procéder avec SpatialAnchorStore.Here's how you do that with the SpatialAnchorStore.

À l’aide de la classe d’assistance, il est presque inutile d’encapsuler la fonction Clear.Using our helper class, it's almost unnecessary to wrap the Clear function. Nous choisissons cette opération dans notre exemple d’implémentation, car la responsabilité de la propriétaire de l’instance SpatialAnchorStore est attribuée à notre classe d’assistance.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();
       }
   }

Exemple : Association de systèmes de coordonnées d’ancrage à des systèmes de coordonnées de cadre de référence stationnaireExample: Relating anchor coordinate systems to stationary reference frame coordinate systems

Supposons que vous disposiez d’une ancre et que vous vouliez associer un nom du système de coordonnées de votre ancre au SpatialStationaryReferenceFrame que vous utilisez déjà pour votre autre contenu.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. Vous pouvez utiliser TryGetTransformTo pour obtenir une transformation du système de coordonnées de l’ancre à celle du cadre de référence fixe :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;
   }

Ce processus est utile de deux manières :This process is useful to you in two ways:

  1. Elle vous indique si les deux frames de référence peuvent être compris entre eux, et ;It tells you if the two reference frames can be understood relative to one another, and;
  2. Si c’est le cas, il vous fournit une transformation pour passer directement d’un système de coordonnées à l’autre.If so, it provides you a transform to go directly from one coordinate system to the other.

Avec ces informations, vous comprenez la relation spatiale entre les objets entre les deux frames de référence.With this information, you have an understanding of the spatial relation between objects between the two reference frames.

Pour le rendu, vous pouvez souvent obtenir de meilleurs résultats en regroupant des objets en fonction de leur frame de référence ou de leur ancre d’origine.For rendering, you can often obtain better results by grouping objects according to their original reference frame or anchor. Effectuez une passe de dessin distincte pour chaque groupe.Perform a separate drawing pass for each group. Les matrices de vue sont plus précises pour les objets avec des transformations de modèle créées initialement à l’aide du même système de coordonnées.The view matrices are more accurate for objects with model transforms that are created initially using the same coordinate system.

Créer des hologrammes à l’aide d’une image de référence associée à un appareilCreate holograms using a device-attached frame of reference

Il peut arriver que vous souhaitiez afficher un hologramme qui reste attaché à l’emplacement de l’appareil, par exemple un panneau avec des informations de débogage ou un message d’information lorsque l’appareil est uniquement en mesure de déterminer son orientation et non sa position dans l’espace.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. Pour ce faire, nous utilisons un cadre de référence attaché.To accomplish this, we use an attached frame of reference.

La classe SpatialLocatorAttachedFrameOfReference définit des systèmes de coordonnées, qui sont relatifs à l’appareil plutôt qu’au monde réel.The SpatialLocatorAttachedFrameOfReference class defines coordinate systems, which are relative to the device rather than to the real-world. Ce cadre a un titre fixe par rapport à l’environnement de l’utilisateur qui pointe dans la direction vers laquelle l’utilisateur était confronté lorsque le frame de référence a été créé.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. À partir de là, toutes les orientations dans ce frame de référence sont relatives à cet en-tête fixe, même lorsque l’utilisateur fait pivoter l’appareil.From then on, all orientations in this frame of reference are relative to that fixed heading, even as the user rotates the device.

Pour HoloLens, l’origine du système de coordonnées de ce frame se trouve au centre de rotation de la tête de l’utilisateur, de sorte que sa position n’est pas affectée par la rotation de la tête.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. Votre application peut spécifier un décalage par rapport à ce point pour positionner les hologrammes devant l’utilisateur.Your app can specify an offset relative to this point to position holograms in front of the user.

Pour obtenir un SpatialLocatorAttachedFrameOfReference, utilisez la classe SpatialLocator et appelez CreateAttachedFrameOfReferenceAtCurrentHeading.To get a SpatialLocatorAttachedFrameOfReference, use the SpatialLocator class and call CreateAttachedFrameOfReferenceAtCurrentHeading.

Cela s’applique à toute la plage d’appareils Windows Mixed Reality.This applies to the entire range of Windows Mixed Reality devices.

Utiliser un cadre de référence attaché à l’appareilUse a reference frame attached to the device

Ces sections décrivent ce que nous avons modifié dans le modèle d’application holographique Windows pour activer un cadre de référence associé à un appareil à l’aide de cette 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. Cet hologramme « attaché » fonctionne avec les hologrammes fixes ou ancrés, et peut également être utilisé lorsque l’appareil est momentanément incapable de trouver sa position dans le monde.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.

Tout d’abord, nous avons modifié le modèle pour stocker un SpatialLocatorAttachedFrameOfReference au lieu d’un SpatialStationaryFrameOfReference :First, we changed the template to store a SpatialLocatorAttachedFrameOfReference instead of a SpatialStationaryFrameOfReference:

À partir de HolographicTagAlongSampleMain. h:From HolographicTagAlongSampleMain.h:

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

À partir de HolographicTagAlongSampleMain. cpp:From HolographicTagAlongSampleMain.cpp:

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

Au cours de la mise à jour, nous obtenons désormais le système de coordonnées à l’horodatage obtenu à l’aide de la prédiction de cadre.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);

Obtenir une pose de pointeur spatial et suivre le point de regard de l’utilisateurGet a spatial pointer pose, and follow the user's Gaze

Nous souhaitons que notre exemple d’hologramme suive le regardde l’utilisateur, de la même façon que le shell holographique peut suivre le regard de l’utilisateur.We want our example hologram to follow the user's gaze, similar to how the holographic shell can follow the user's gaze. Pour cela, nous devons obtenir le SpatialPointerPose à partir du même horodatage.For this, we need to get the SpatialPointerPose from the same time stamp.

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

Ce SpatialPointerPose contient les informations nécessaires pour positionner l’hologramme en fonction de l' en-tête actuel de l’utilisateur.This SpatialPointerPose has the information needed to position the hologram according to the user's current heading.

Pour le confort de l’utilisateur, nous utilisons l’interpolation linéaire (« Lerp ») pour lisser le changement de position sur une période donnée.For user comfort, we use linear interpolation ("lerp") to smooth the change in position over a period of time. L’utilisateur est plus à l’aise avec le verrouillage de l’hologramme.This is more comfortable for the user than locking the hologram to their gaze. Lerping la position de la balise, le long de l’hologramme, nous permet également de stabiliser l’hologramme en amortissant le mouvement.Lerping the tag-along hologram's position also allows us to stabilize the hologram by dampening the movement. Si ce n’est pas le cas, l’utilisateur voit la gigue d’hologramme en raison de ce qui est normalement considéré comme étant des mouvements imperceptibles de la tête de l’utilisateur.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.

À partir de StationaryQuadRenderer ::P ositionhologram: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);
   }

Notes

Dans le cas d’un panneau de débogage, vous pouvez choisir de repositionner l’hologramme sur le côté afin qu’il n’obstrue pas votre affichage.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. Voici un exemple de ce que vous pouvez faire.Here's an example of how you might do that.

Pour StationaryQuadRenderer ::P ositionhologram: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));
       */

Faire pivoter l’hologramme pour faire face à l’appareil photoRotate the hologram to face the camera

Ce n’est pas suffisant pour positionner l’hologramme, qui est dans ce cas un quadruple. Nous devons également faire pivoter l’objet pour faire face à l’utilisateur.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. Cette rotation se produit dans l’espace universel, car ce type de billboarding permet à l’hologramme de conserver une partie de l’environnement de l’utilisateur.This rotation occurs in world space, because this type of billboarding allows the hologram to remain a part of the user's environment. L’affichage de l’espace d’affichage n’est pas aussi agréable, car l’hologramme est verrouillé à l’orientation de l’affichage ; dans ce cas, vous devez également interpoler entre les matrices de vue de gauche et de droite pour acquérir une transformation d’affichage de l’espace d’affichage qui n’interrompt pas le rendu stéréo.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. Ici, nous allons faire pivoter sur les axes X et Z pour faire face à l’utilisateur.Here, we rotate on the X and Z axes to face the user.

À partir de StationaryQuadRenderer :: 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));

Rendre l’hologramme attachéRender the attached hologram

Pour cet exemple, nous choisissons également d’afficher l’hologramme dans le système de coordonnées du SpatialLocatorAttachedReferenceFrame, où nous avons positionné l’hologramme.For this example, we also choose to render the hologram in the coordinate system of the SpatialLocatorAttachedReferenceFrame, which is where we positioned the hologram. (Si nous avions décidé d’effectuer le rendu à l’aide d’un autre système de coordonnées, nous aurions besoin d’acquérir une transformation du système de coordonnées de l’appareil de référence associé à l’appareil vers ce système de coordonnées.)(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.)

À partir de HolographicTagAlongSampleMain :: 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)
       );

C’est tout !That's it! L’hologramme va à présent « débusquer » une position qui est de 2 mètres devant la direction du regard de l’utilisateur.The hologram will now "chase" a position that is 2 meters in front of the user's gaze direction.

Notes

Cet exemple charge également du contenu supplémentaire. consultez StationaryQuadRenderer. cpp.This example also loads additional content - see StationaryQuadRenderer.cpp.

Gestion des pertes de suiviHandling tracking loss

Lorsque l’appareil ne peut pas se trouver dans le monde entier, l’application rencontre une « perte de suivi ».When the device can't locate itself in the world, the app experiences "tracking loss". Les applications Windows Mixed Reality doivent être en mesure de gérer ces interruptions du système de suivi positionnel.Windows Mixed Reality apps should be able to handle such disruptions to the positional tracking system. Ces interruptions peuvent être observées et les réponses créées à l’aide de l’événement LocatabilityChanged sur le SpatialLocator par défaut.These disruptions can be observed, and responses created, by using the LocatabilityChanged event on the default SpatialLocator.

À partir de AppMain :: SetHolographicSpace :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)
               );

Lorsque votre application reçoit un événement LocatabilityChanged, elle peut modifier le comportement en fonction des besoins.When your app receives a LocatabilityChanged event, it can change behavior as needed. Par exemple, dans l’État PositionalTrackingInhibited, votre application peut suspendre une opération normale et afficher un message d’avertissement sur l’hologramme qui affiche un message d’avertissement.For example, in the PositionalTrackingInhibited state, your app can pause normal operation and render a tag-along hologram that displays a warning message.

Le modèle d’application holographique Windows est fourni avec un gestionnaire LocatabilityChanged déjà créé pour vous.The Windows Holographic app template comes with a LocatabilityChanged handler already created for you. Par défaut, il affiche un avertissement dans la console de débogage lorsque le suivi positionnel n’est pas disponible.By default, it displays a warning in the debug console when positional tracking is unavailable. Vous pouvez ajouter du code à ce gestionnaire pour fournir une réponse en fonction des besoins de votre application.You can add code to this handler to provide a response as needed from your app.

À partir de AppMain. 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;
       }
   }

Mappage spatialSpatial mapping

Les API de mappage spatial utilisent des systèmes de coordonnées pour obtenir des transformations de modèle pour les maillages de surface.The spatial mapping APIs make use of coordinate systems to get model transforms for surface meshes.

Voir aussiSee also