Fotocamera/videocamera HoloLens in Unreal

HoloLens include una fotocamera/videocamera sulla visiera che può essere usata per Acquisizione realtà mista (MRC) e per individuare gli oggetti presenti in uno spazio Unreal dalle coordinate dei pixel nel frame della fotocamera.

Importante

La fotocamera/videocamera non è supportata con Holographic Remoting, ma per simulare la funzionalità della fotocamera/videocamera di HoloLens è possibile usare una webcam collegata al PC.

Impostazione del feed della fotocamera/videocamera

Importante

La fotocamera PV viene implementata sia nei plug-in Windows Mixed Reality che in OpenXR. Tuttavia, OpenXR deve essere installato il plug-in Microsoft OpenXR . Inoltre, OpenXR per Unreal 4.26 ha una limitazione: la fotocamera può funzionare con DirectX11 RHI. Questa limitazione è fissa in Unreal 4.27.1 o versione successiva.

  • In Impostazioni > progetto HoloLens abilitare la funzionalità Webcam :

Screenshot delle impostazioni di progetto HoloLens con la proprietà Webcam evidenziata

  • Creare un nuovo attore denominato "CamCapture" e aggiungere un piano per il rendering del feed della fotocamera:

Screenshot di un attore con un piano aggiunto

  • Aggiungere l'attore alla scena, creare un nuovo materiale denominato CamTextureMaterial con un parametro di oggetto trama e un esempio di trama. Inviare i dati RGB della trama al colore emissivo di output:

Progetto di un materiale e un esempio di trama

Rendering del feed della fotocamera/videocamera

  • Nel progetto CamCapture attivare la fotocamera/videocamera:

Progetto della funzione Toggle ARCapture con la fotocamera/videocamera attivata

  • Creare un'istanza del materiale dinamico da CamTextureMaterial e assegnare questo materiale al piano dell'attore:

Progetto della funzione Create Dynamic Material Instance

  • Ottenere la trama dal feed della fotocamera e, se è valida, assegnarla al materiale dinamico. Se la trama non è valida, avviare un timer e riprovare dopo il timeout:

Progetto della trama del feed della fotocamera assegnata al materiale dinamico

  • Infine, ridimensionare il piano in base alle proporzioni dell'immagine della fotocamera:

Progetto del piano ridimensionato rispetto alle proporzioni delle immagini della fotocamera

Trovare le posizioni della fotocamera nello spazio globale

La fotocamera in HoloLens 2 presenta uno scostamento verticale rispetto al rilevamento della testa operato dal dispositivo. Per tenere in considerazione questo scostamento, sono disponibili alcune funzioni per individuare la fotocamera nello spazio globale.

GetPVCameraToWorldTransform ottiene la trasformazione nello spazio globale della fotocamera/videocamera e viene posizionata sull'obiettivo della fotocamera:

Progetto della funzione Get PVCamera to World Transform

GetWorldSpaceRayFromCameraPoint esegue il cast di un raggio dall'obiettivo della fotocamera alla scena nello spazio globale di Unreal per trovare un contenuto di pixel presente nel frame della fotocamera:

Progetto di Get World Space Ray from Camera Point

GetPVCameraIntrinsics restituisce i valori intrinseci della fotocamera, che possono essere usati quando si esegue l'elaborazione della visione artificiale su un frame della fotocamera:

Progetto delle funzioni di Get PVCamera Intrinsics

Per trovare un elemento presente nello spazio globale in corrispondenza di una particolare coordinata del pixel, usare una traccia lineare con il raggio dello spazio globale:

Progetto del raggio dello spazio globale usato per individuare un elemento presente nello spazio globale in corrispondenza di una particolare coordinata

A questo punto viene eseguito il cast di un raggio di 2 metri dall'obiettivo della fotocamera alla posizione dello spazio della fotocamera con uno scostamento di 1/4 dalla parte superiore sinistra del frame. Usare quindi il risultato ottenuto per eseguire il rendering di un elemento nel punto in cui è presente l'oggetto nello spazio globale:

Progetto del cast di un raggio di 2 metri dall'obiettivo della fotocamera alla posizione dello spazio della fotocamera con uno scostamento di 1/4 dalla parte superiore sinistra del frame

Quando si usa il mapping spaziale, la posizione ottenuta corrisponde alla superficie visualizzata dalla fotocamera.

Rendering del feed della fotocamera/videocamera in C++

  • Creare un nuovo attore C++ denominato CamCapture
  • Nel file build.cs del progetto aggiungere "AugmentedReality" all'elenco PublicDependencyModuleNames:
PublicDependencyModuleNames.AddRange(
    new string[] {
        "Core",
        "CoreUObject",
        "Engine",
        "InputCore",
        "AugmentedReality"
});
  • In CamCapture.h includere ARBlueprintLibrary.h
#include "ARBlueprintLibrary.h"
  • È anche necessario aggiungere variabili locali per la mesh e il materiale:
private:
    UStaticMesh* StaticMesh;
    UStaticMeshComponent* StaticMeshComponent;
    UMaterialInstanceDynamic* DynamicMaterial;
    bool IsTextureParamSet = false;
  • In CamCapture.cpp aggiornare il costruttore per aggiungere una mesh statica alla scena:
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);
}

In BeginPlay creare un'istanza di materiale dinamico dal materiale della fotocamera del progetto, applicarla al componente della mesh statica e avviare la fotocamera HoloLens.

Per ottenere la stringa per CameraMatPath, nell'editor fare clic con il pulsante destro del mouse su CamTextureMaterial nel browser del contenuto e selezionare "Copy Reference" (Copia riferimento).

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

In Tick ottenere la trama dalla fotocamera, impostarla sul parametro della trama nel materiale CamTextureMaterial e ridimensionare il componente della mesh statica in base alle proporzioni del frame della fotocamera:

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

Successivo checkpoint di sviluppo

Se si segue il percorso per lo sviluppo con Unreal che è stato delineato, si stanno esplorando le API e le funzionalità della piattaforma di realtà mista. Da qui, è possibile passare all'argomento successivo:

In alternativa, passare direttamente alla distribuzione dell'app in un dispositivo o emulatore:

È sempre possibile tornare ai checkpoint per lo sviluppo con Unreal in qualsiasi momento.

Vedere anche