Appareil photo/vidéo HoloLens dans UnrealHoloLens Photo/Video Camera in Unreal

Le casque HoloLens a une caméra photo/vidéo (PV) sur la visière, qui peut être utilisée à la fois pour la capture de réalité mixte et pour localiser des objets dans l’espace universel Unreal à partir des coordonnées de pixels dans le cadre de la caméra.The HoloLens has a Photo/Video (PV) Camera on the visor that can be used for both Mixed Reality Capture (MRC) and locating objects in Unreal world space from pixel coordinates in the camera frame.

Important

L’appareil photo/vidéo n’est pas pris en charge avec la communication à distance holographique, mais il est possible d’utiliser une webcam connectée à votre PC pour simuler la fonctionnalité d’appareil photo/vidéo HoloLens.The PV Camera isn't supported with Holographic Remoting, but it's possible to use a webcam attached to your PC to simulate the HoloLens PV Camera functionality.

Configuration du flux de la caméra PVPV Camera Feed Setup

Important

La caméra PV est implémentée dans les plug-ins Windows Mixed Reality et OpenXR.PV camera is implemented in both Windows Mixed Reality and OpenXR plugins. Cependant, OpenXR a besoin que le plug-in Microsoft OpenXR soit installé.However OpenXR needs Microsoft OpenXR plugin to be installed. OpenXR a également une limitation actuelle : la caméra peut fonctionner avec DirectX11 RHI.Also OpenXR has current limitation, camera can work with DirectX11 RHI. Cette limitation sera levée dans une version d’Unreal à venir.This limitation will be fixed in a further Unreal version.

  • Dans Project Settings > HoloLens, activez la fonctionnalité Webcam :In Project Settings > HoloLens, enable the Webcam capability:

Capture d’écran des paramètres du projet HoloLens avec la propriété Webcam mise en surbrillance

  • Créez un acteur appelé « CamCapture » et ajoutez un plan pour rendre le flux de la caméra :Create a new actor called “CamCapture” and add a plane to render the camera feed:

Capture d’écran d’un acteur avec un plan ajouté

  • Ajoutez l’acteur à votre scène, créez un matériau appelé CamTextureMaterial avec un paramètre d’objet de texture et un échantillon de texture.Add the actor to your scene, create a new material called CamTextureMaterial with a Texture Object Parameter, and a texture sample. Envoyez les données RVB de la texture à la couleur d’émission en sortie :Send the texture’s rgb data to the output emissive color:

Blueprint d’un échantillon de matériau et de texture

Rendu du flux de la caméra PVRendering the PV Camera Feed

  • Dans le blueprint CamCapture, activez la caméra PV :In the CamCapture blueprint, turn on the PV Camera:

Blueprint de la fonction Activer/désactiver ARCapture avec la caméra PV activée

  • Créez une instance de matériau dynamique à partir de CamTextureMaterial et affectez ce matériau au plan de l’acteur :Create a dynamic material instance from CamTextureMaterial and assign this material to the actor’s plane:

Blueprint de la fonction Créer une instance de matériau dynamique

  • Récupérez la texture du flux de la caméra, et affectez-la au matériau dynamique, si elle est valide.Get the texture from the camera feed and assign it to the dynamic material if it's valid. Si la texture n’est pas valide, démarrez un minuteur, puis réessayez une fois le délai d’expiration écoulé :If the texture isn't valid, start a timer and try again after the timeout:

Blueprint de la texture du flux de la caméra affectée au matériau dynamique

  • Enfin, mettez à l’échelle le plan selon les proportions de l’image de la caméra :Finally, scale the plane by the camera image’s aspect ratio:

Blueprint du plan mis à l’échelle par rapport aux proportions des images de la caméra

Rechercher des positions de la caméra dans l’espace universelFind Camera Positions in World Space

La caméra sur le casque HoloLens 2 est décalée verticalement par rapport au suivi de la tête de l’appareil.The camera on the HoloLens 2 is offset vertically from the device’s head tracking. Pour tenir compte du décalage, il existe quelques fonctions qui permettent de localiser la caméra dans l’espace universel.A few functions exist to locate the camera in world space to account for the offset.

GetPVCameraToWorldTransform obtient la transformation dans l’espace universel de la caméra PV, et est positionné sur l’objectif de la caméra :GetPVCameraToWorldTransform gets the transform in world space of the PV Camera and will be positioned on the camera lens:

Blueprint de la fonction Obtenir la transformation de la caméra PV en monde

GetWorldSpaceRayFromCameraPoint diffuse un rayon de l’objectif de la caméra vers la scène dans l’espace universel Unreal pour rechercher le contenu d’un pixel dans le cadre de la caméra :GetWorldSpaceRayFromCameraPoint casts a ray from the camera lens into the scene in Unreal world space to find a pixel's content in the camera frame:

Blueprint de la fonction Obtenir un rayon de l’espace universel depuis un point de la caméra

GetPVCameraIntrinsics retourne les valeurs intrinsèques de la caméra, qui peuvent être utilisées lors du traitement de la vision par ordinateur sur un cadre de la caméra :GetPVCameraIntrinsics returns the camera intrinsic values, which can be used when doing computer vision processing on a camera frame:

Blueprint de fonctions intrinsèques de la caméra PV

Pour trouver ce qui existe dans l’espace universel à une coordonnée d’un pixel particulier, utilisez un suivi de ligne avec le rayon d’espace universel :To find what exists in world space at a particular pixel coordinate, use a line trace with the world space ray:

Blueprint du rayon d’espace universel utilisé pour déterminer ce qui existe dans l’espace universel à une coordonnée particulière

Nous convertissons ici un rayon à 2 mètres de l’objectif de la caméra en une position dans l’espace de la caméra à ¼ à partir du coin supérieur gauche du cadre.Here we cast a 2-meter ray from the camera lens to the camera-space position ¼ from the top left of the frame. Nous utilisons ensuite le résultat du pointage pour rendre quelque chose là où l’objet existe dans l’espace universel :Then use the hit result to render something where the object exists in world space:

Blueprint de la conversion d’un rayon à 2 mètres de l’objectif de la caméra en une position dans l’espace de la caméra à 1/4 à partir du coin supérieur gauche du cadre.

Quand vous utilisez le mappage spatial, cette position du pointage correspond à la surface vue par la caméra.When using spatial mapping, this hit position will match the surface that the camera is seeing.

Rendu du flux de la caméra PV en C++Rendering the PV Camera Feed in C++

  • Créer un acteur C++ appelé CamCaptureCreate a new C++ actor called CamCapture
  • Dans le fichier build.cs du projet, ajoutez « AugmentedReality » à la liste PublicDependencyModuleNames :In the project’s build.cs, add “AugmentedReality” to the PublicDependencyModuleNames list:
PublicDependencyModuleNames.AddRange(
    new string[] {
        "Core",
        "CoreUObject",
        "Engine",
        "InputCore",
        "AugmentedReality"
});
  • Dans CamCapture. h, incluez ARBlueprintLibrary.hIn CamCapture.h, include ARBlueprintLibrary.h
#include "ARBlueprintLibrary.h"
  • Vous devez aussi ajouter des variables locales pour le maillage et le matériau :You also need to add local variables for the mesh and material:
private:
    UStaticMesh* StaticMesh;
    UStaticMeshComponent* StaticMeshComponent;
    UMaterialInstanceDynamic* DynamicMaterial;
    bool IsTextureParamSet = false;
  • Dans CamCapture.cpp, mettez à jour le constructeur en ajoutant un maillage statique à la scène :In CamCapture.cpp, update the constructor to add a static mesh to the scene:
ACamCapture::ACamCapture()
{
    PrimaryActorTick.bCanEverTick = true;

    // Load a mesh from the engine to render the camera feed to.
    StaticMesh = LoadObject<UStaticMesh>(nullptr, TEXT("/Engine/EngineMeshes/Cube.Cube"), nullptr, LOAD_None, nullptr);

    // Create a static mesh component to render the static mesh
    StaticMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CameraPlane"));
    StaticMeshComponent->SetStaticMesh(StaticMesh);

    // Scale and add to the scene
    StaticMeshComponent->SetWorldScale3D(FVector(0.1f, 1, 1));
    this->SetRootComponent(StaticMeshComponent);
}

Dans BeginPlay, créez une instance de matériau dynamique à partir du matériau de la caméra du projet, appliquez-la au composant de maillage statique et démarrez la caméra HoloLens.In BeginPlay create a dynamic material instance from the project’s camera material, apply it to the static mesh component, and start the HoloLens camera.

Dans l’éditeur, cliquez avec le bouton droit sur CamTextureMaterial dans l’explorateur de contenu, puis sélectionnez Copy Reference pour obtenir la chaîne de CameraMatPath.In the editor, right-click on the CamTextureMaterial in the content browser and select “Copy Reference” to get the string for CameraMatPath.

void ACamCapture::BeginPlay()
{
    Super::BeginPlay();

    // Create a dynamic material instance from the game's camera material.
    // Right-click on a material in the project and select "Copy Reference" to get this string.
    FString CameraMatPath("Material'/Game/Materials/CamTextureMaterial.CamTextureMaterial'");
    UMaterial* BaseMaterial = (UMaterial*)StaticLoadObject(UMaterial::StaticClass(), nullptr, *CameraMatPath, nullptr, LOAD_None, nullptr);
    DynamicMaterial = UMaterialInstanceDynamic::Create(BaseMaterial, this);

    // Use the dynamic material instance when rendering the camera mesh.
    StaticMeshComponent->SetMaterial(0, DynamicMaterial);

    // Start the webcam.
    UARBlueprintLibrary::ToggleARCapture(true, EARCaptureType::Camera);
}

Dans Tick, récupérez la texture de la caméra, définissez-la sur le paramètre de texture dans le matériau CamTextureMaterial et mettez à l’échelle le composant de maillage statique selon les proportions du cadre de la caméra :In Tick get the texture from the camera, set it to the texture parameter in the CamTextureMaterial material, and scale the static mesh component by the camera frame’s aspect ratio:

void ACamCapture::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    // Dynamic material instance only needs to be set once.
    if(IsTextureParamSet)
    {
        return;
    }

    // Get the texture from the camera.
    UARTexture* ARTexture = UARBlueprintLibrary::GetARTexture(EARTextureType::CameraImage);
    if(ARTexture != nullptr)
    {
        // Set the shader's texture parameter (named "Param") to the camera image.
        DynamicMaterial->SetTextureParameterValue("Param", ARTexture);
        IsTextureParamSet = true;

        // Get the camera instrincs
        FARCameraIntrinsics Intrinsics;
        UARBlueprintLibrary::GetCameraIntrinsics(Intrinsics);

        // Scale the camera mesh by the aspect ratio.
        float R = (float)Intrinsics.ImageResolution.X / (float)Intrinsics.ImageResolution.Y;
        StaticMeshComponent->SetWorldScale3D(FVector(0.1f, R, 1));
    }
}

Point de contrôle de développement suivantNext Development Checkpoint

Si vous suivez le parcours de développement Unreal que nous avons mis en place, vous explorez actuellement les API et les fonctionnalités de la plateforme Mixed Reality.If you're following the Unreal development journey we've laid out, you're in the midst of exploring the Mixed Reality platform capabilities and APIs. À partir d’ici, vous pouvez passer au sujet suivant :From here, you can continue to the next topic:

Ou accéder directement au déploiement de votre application sur un appareil ou un émulateur :Or jump directly to deploying your app on a device or emulator:

Vous pouvez revenir aux points de contrôle de développement Unreal à tout moment.You can always go back to the Unreal development checkpoints at any time.

Voir aussiSee also