Appareil photo/vidéo HoloLens dans 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.

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.

Configuration du flux de la caméra PV

Important

La caméra PV est implémentée dans les plug-ins Windows Mixed Reality et OpenXR. Cependant, OpenXR a besoin que le plug-in Microsoft OpenXR soit installé. En outre, OpenXR pour Unreal 4,26 a une limitation : la caméra peut fonctionner avec DirectX11 RHI. Cette limitation est corrigée dans 4.27.1 ou ultérieur.

  • Dans Project Settings > HoloLens, activez la fonctionnalité Webcam :

Screenshot of the HoloLens project settings with the Webcam property highlighted

  • Créez un acteur appelé « CamCapture » et ajoutez un plan pour rendre le flux de la caméra :

Screenshot of the an actor with an added plane

  • 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. Envoyez les données RVB de la texture à la couleur d’émission en sortie :

Blueprint of a material and texture sample

Rendu du flux de la caméra PV

  • Dans le blueprint CamCapture, activez la caméra PV :

Blueprint of the Toggle ARCapture function with the PV Camera turned on

  • Créez une instance de matériau dynamique à partir de CamTextureMaterial et affectez ce matériau au plan de l’acteur :

Blueprint of the Create Dynamic Material Instance function

  • Récupérez la texture du flux de la caméra, et affectez-la au matériau dynamique, si elle est valide. Si la texture n’est pas valide, démarrez un minuteur, puis réessayez une fois le délai d’expiration écoulé :

Blueprint of camera feed texture assigned to the dynamic material

  • Enfin, mettez à l’échelle le plan selon les proportions de l’image de la caméra :

Blueprint of plane scaled relative to the camera images aspect ratio

Rechercher des positions de la caméra dans l’espace universel

La caméra sur le casque HoloLens 2 est décalée verticalement par rapport au suivi de la tête de l’appareil. Pour tenir compte du décalage, il existe quelques fonctions qui permettent de localiser la caméra dans l’espace universel.

GetPVCameraToWorldTransform obtient la transformation dans l’espace universel de la caméra PV, et est positionné sur l’objectif de la caméra :

Blueprint of the Get PVCamera to World Transform function

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 :

Blueprint of the Get World Space Ray from Camera Point

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 :

Blueprint of Get PVCamera Intrinsics functions

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 :

Blueprint of the world space ray being used to find out what exists in the world space at a particular coordinate

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. Nous utilisons ensuite le résultat du pointage pour rendre quelque chose là où l’objet existe dans l’espace universel :

Blueprint of a 2-meter ray cast from the camera lens to the camera-space position 1/4 from the top left of the frame

Quand vous utilisez le mappage spatial, cette position du pointage correspond à la surface vue par la caméra.

Rendu du flux de la caméra PV en C++

  • Créer un acteur C++ appelé CamCapture
  • Dans le fichier build.cs du projet, ajoutez « AugmentedReality » à la liste PublicDependencyModuleNames :
PublicDependencyModuleNames.AddRange(
    new string[] {
        "Core",
        "CoreUObject",
        "Engine",
        "InputCore",
        "AugmentedReality"
});
  • Dans CamCapture. h, incluez ARBlueprintLibrary.h
#include "ARBlueprintLibrary.h"
  • Vous devez aussi ajouter des variables locales pour le maillage et le matériau :
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 :
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.

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.

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 :

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 suivant

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. À partir d’ici, vous pouvez passer au sujet suivant :

Ou accéder directement au déploiement de votre application sur un appareil ou un émulateur :

Vous pouvez revenir aux points de contrôle de développement Unreal à tout moment.

Voir aussi