Fotografia/Câmara de Vídeo do HoloLens em Unreal

O HoloLens tem uma Câmara de Fotografia/Vídeo (PV) no visor que pode ser utilizada tanto para Mixed Reality Capture (MRC) como para localizar objetos no espaço do mundo irreal a partir de coordenadas de píxeis na moldura da câmara.

Importante

A Câmara PV não é suportada com a Comunicação Remota Holográfica, mas é possível utilizar uma câmara Web anexada ao PC para simular a funcionalidade Câmara PV do HoloLens.

Configuração do Feed de Câmara PV

Importante

A câmara PV é implementada em plug-ins Windows Mixed Reality e OpenXR. No entanto, o OpenXR precisa que o plug-in do Microsoft OpenXR seja instalado. Além disso, o OpenXR para Unreal 4.26 tem uma limitação: a câmara pode funcionar com DIRECTX11 RHI. Esta limitação foi corrigida em Unreal 4.27.1 ou posterior.

  • No HoloLens das Definições > do Projeto, ative a capacidade câmara Web :

Captura de ecrã das definições do projeto HoloLens com a propriedade Câmara Web realçada

  • Crie um novo ator chamado "CamCapture" e adicione um avião para compor o feed da câmara:

Captura de ecrã do ator com um plano adicionado

  • Adicione o ator à sua cena, crie um novo material chamado CamTextureMaterial com um Parâmetro de Objeto de Textura e uma amostra de textura. Envie os dados rgb da textura para a cor emissiva de saída:

Esquema de um exemplo de material e textura

Compor o Feed da Câmara PV

  • No esquema CamCapture, ative a Câmara PV:

Esquema da função Desativar ARCapture com a Câmara PV ativada

  • Crie uma instância de material dinâmico a partir de CamTextureMaterial e atribua este material ao plano do ator:

Esquema da função Criar Instância de Material Dinâmico

  • Obtenha a textura do feed da câmara e atribua-a ao material dinâmico, se for válido. Se a textura não for válida, inicie um temporizador e tente novamente após o tempo limite:

Esquema da textura do feed da câmara atribuída ao material dinâmico

  • Por fim, dimensione o plano pela proporção da imagem da câmara:

Esquema do plano dimensionado relativamente à proporção das imagens da câmara

Localizar Posições da Câmara no Espaço Mundial

A câmara no HoloLens 2 é desativada verticalmente do controlo de cabeça do dispositivo. Existem algumas funções para localizar a câmara no espaço mundial para contabilizar o desvio.

GetPVCameraToWorldTransform obtém a transformação no espaço mundial da Câmara de PV e será posicionado na lente da câmara:

Esquema da função Obter PVCamera para Transformação Mundial

GetWorldSpaceRayFromCameraPoint lança um raio da lente da câmara para a cena no espaço do mundo irreal para encontrar o conteúdo de um pixel na moldura da câmara:

Esquema do Get World Space Ray from Camera Point

GetPVCameraIntrinsics devolve os valores intrínsecos da câmara, que podem ser utilizados ao fazer o processamento de imagem digitalizada numa moldura da câmara:

Esquema das funções Intrínsecas Get PVCamera

Para encontrar o que existe no espaço mundial numa coordenada de píxeis específica, utilize um rastreio de linha com o raio espacial mundial:

Esquema do raio espacial mundial que está a ser usado para descobrir o que existe no espaço mundial numa coordenada específica

Aqui lançamos um raio de 2 metros da lente da câmara para a posição de espaço da câmara 1/4 a partir do canto superior esquerdo da moldura. Em seguida, utilize o resultado de êxito para compor algo em que o objeto exista no espaço mundial:

Esquema de um raio de 2 metros fundido da lente da câmara para a posição de espaço da câmara 1/4 a partir do canto superior esquerdo da moldura

Ao utilizar o mapeamento espacial, esta posição de acesso corresponderá à superfície que a câmara está a ver.

Compor o Feed de Câmara PV em C++

  • Criar um novo ator C++ chamado CamCapture
  • No build.cs do projeto, adicione "AugmentedReality" à lista PublicDependencyModuleNames:
PublicDependencyModuleNames.AddRange(
    new string[] {
        "Core",
        "CoreUObject",
        "Engine",
        "InputCore",
        "AugmentedReality"
});
  • Em CamCapture.h, inclua ARBlueprintLibrary.h
#include "ARBlueprintLibrary.h"
  • Também tem de adicionar variáveis locais para a malha e o material:
private:
    UStaticMesh* StaticMesh;
    UStaticMeshComponent* StaticMeshComponent;
    UMaterialInstanceDynamic* DynamicMaterial;
    bool IsTextureParamSet = false;
  • Em CamCapture.cpp, atualize o construtor para adicionar uma malha estática à cena:
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);
}

Em BeginPlay, crie uma instância de material dinâmico a partir do material da câmara do projeto, aplique-a ao componente de malha estática e inicie a câmara HoloLens.

No editor, clique com o botão direito do rato no CamTextureMaterial no browser de conteúdos e selecione "Copiar Referência" para obter a cadeia para 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);
}

Em Tique, obtenha a textura da câmara, defina-a para o parâmetro de textura no material CamTextureMaterial e dimensione o componente de malha estática pela proporção da moldura da 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));
    }
}

Próximo Ponto de Verificação de Desenvolvimento

Se estiver a seguir o percurso de desenvolvimento irreal que definimos, está a explorar as capacidades e APIs da plataforma Mixed Reality. A partir daqui, pode continuar para o tópico seguinte:

Em alternativa, avance diretamente para a implementação da sua aplicação num dispositivo ou emulador:

Pode sempre voltar aos pontos de verificação de desenvolvimento irreais em qualquer altura.

Ver também