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 :
- Creare un nuovo attore denominato "CamCapture" e aggiungere un piano per il rendering del feed della fotocamera:
- 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:
Rendering del feed della fotocamera/videocamera
- Nel progetto CamCapture attivare la fotocamera/videocamera:
- Creare un'istanza del materiale dinamico da CamTextureMaterial e assegnare questo materiale al piano dell'attore:
- 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:
- Infine, ridimensionare il piano in base alle proporzioni dell'immagine 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:
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:
GetPVCameraIntrinsics restituisce i valori intrinseci della fotocamera, che possono essere usati quando si esegue l'elaborazione della visione artificiale su un frame della fotocamera:
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:
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:
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.