Cámara de fotos y vídeo de HoloLens en Unreal
HoloLens tiene una cámara foto/vídeo (PV) en el visor que se puede usar tanto para Mixed Reality Capture (MRC) como para localizar objetos en el espacio unreal world a partir de coordenadas de píxeles en el marco de la cámara.
Importante
La cámara PV no es compatible con la comunicación remota holográfica, pero es posible usar una cámara web conectada a su PC para simular la funcionalidad de la cámara PV de HoloLens.
Configuración de la fuente de la cámara PV
Importante
La cámara fotovoltaica se implementa en complementos Windows Mixed Reality y OpenXR. Sin embargo, OpenXR necesita que se instale el complemento Microsoft OpenXR . Además, OpenXR para Unreal 4.26 tiene una limitación: la cámara puede trabajar con DirectX11 RHI. Esta limitación se corrige en Unreal 4.27.1 o posterior.
- En Configuración del > proyecto HoloLens, habilite la funcionalidad Webcam :
- Cree un actor llamado "CamCapture" y agregue un plano para representar la fuente de la cámara:
- Agregue el actor a la escena, cree un nuevo material denominado CamTextureMaterial con un parámetro de objeto texture y una muestra de textura. Envíe los datos rgb de la textura al color emisivo de salida:
Representación de la fuente de cámara PV
- En el plano técnico de CamCapture, active la cámara PV:
- Cree una instancia de material dinámico a partir de CamTextureMaterial y asigne este material al plano del actor:
- Obtenga la textura de la fuente de la cámara y asígnela al material dinámico si es válida. Si la textura no es válida, inicie un temporizador e inténtelo de nuevo después del tiempo de espera:
- Por último, escale el plano según la relación de aspecto de la imagen de la cámara:
Buscar posiciones de cámara en el espacio mundial
La cámara del HoloLens 2 se desplaza verticalmente desde el seguimiento de la cabeza del dispositivo. Existen algunas funciones para localizar la cámara en el espacio del mundo para tener en cuenta el desplazamiento.
GetPVCameraToWorldTransform obtiene la transformación en el espacio mundial de la cámara fotovoltaica y se colocará en la lente de la cámara:
GetWorldSpaceRayFromCameraPoint convierte un rayo de la lente de la cámara en la escena en el espacio unreal world para encontrar el contenido de un píxel en el marco de la cámara:
GetPVCameraIntrinsics devuelve los valores intrínsecos de la cámara, que se pueden usar al realizar el procesamiento de computer vision en un marco de cámara:
Para encontrar lo que existe en el espacio mundial en una coordenada de píxel determinada, use un seguimiento de línea con el rayo espacial del mundo:
Aquí lanzamos un rayo de 2 metros desde la lente de la cámara a la posición del espacio de la cámara 1/4 desde la parte superior izquierda del marco. A continuación, use el resultado de aciertos para representar algo donde el objeto existe en el espacio mundial:
Cuando se usa la asignación espacial, esta posición de posicionamiento coincidirá con la superficie que ve la cámara.
Representación de la fuente de cámara PV en C++
- Creación de un nuevo actor de C++ llamado CamCapture
- En el build.cs del proyecto, agregue "AugmentedReality" a la lista PublicDependencyModuleNames:
PublicDependencyModuleNames.AddRange(
new string[] {
"Core",
"CoreUObject",
"Engine",
"InputCore",
"AugmentedReality"
});
- En CamCapture.h, incluya ARBlueprintLibrary.h.
#include "ARBlueprintLibrary.h"
- También debe agregar variables locales para la malla y el material:
private:
UStaticMesh* StaticMesh;
UStaticMeshComponent* StaticMeshComponent;
UMaterialInstanceDynamic* DynamicMaterial;
bool IsTextureParamSet = false;
- En CamCapture.cpp, actualice el constructor para agregar una malla estática a la escena:
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);
}
En BeginPlay, cree una instancia de material dinámico a partir del material de cámara del proyecto, aplíquela al componente de malla estática e inicie la cámara HoloLens.
En el editor, haga clic con el botón derecho en CamTextureMaterial en el explorador de contenido y seleccione "Copiar referencia" para obtener la cadena 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);
}
En Tick, obtenga la textura de la cámara, establézcala en el parámetro texture del material CamTextureMaterial y escale el componente de malla estática por la relación de aspecto del marco de la cámara:
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));
}
}
Siguiente punto de comprobación de desarrollo
Si sigue el recorrido de desarrollo de Unreal que hemos diseñado, se encuentra en medio de la exploración de las funcionalidades y las API de la plataforma de Mixed Reality. Desde aquí, puede continuar con el tema siguiente:
O vaya directamente a la implementación de la aplicación en un dispositivo o emulador:
Siempre puede volver a los puntos de control de desarrollo de Unreal en cualquier momento.