Unreal 中的 HoloLens 相片/影片相機
HoloLens 的面板上有相片/影片 (PV) 相機,不僅可用於混合實境擷取 (MRC),也可用來透過相機框架中的像素座標定位 Unreal 世界空間中的物件。
重要
PV 攝影機不支援全像攝影遠端功能,但可以使用連接到您電腦的網路攝影機來模擬 HoloLens PV 攝影機功能。
PV 相機摘要設定
重要
PV 相機會在 Windows Mixed Reality 和 OpenXR 外掛程式中實作。 不過, OpenXR 需要安裝 Microsoft OpenXR 外掛程式 。 此外,OpenXR for Unreal 4.26 有限制:相機可以使用 DirectX11 RHI。 Unreal 4.27.1 或更新版本中已修正這項限制。
- 在 [專案設定 > HoloLens] 中,啟用 網路攝影機 功能:
- 建立名為 "CamCapture" 的新動作項目,並新增平面來呈現相機摘要:
- 將動作項目新增至您的場景,建立具有「材質物件參數」且名為 CamTextureMaterial 的新材質,以及材質範例。 將材質的 rgb 資料傳送至輸出放射色彩:
呈現 PV 相機摘要
- 在 CamCapture 藍圖中,開啟「PV 相機」:
- 從 CamTextureMaterial 建立動態材質執行個體,並將此材質指派給動作項目的平面:
- 從相機摘要取得材質,並將其指派給動態材質 (如果此材質有效的話)。 如果此材質無效,請啟動計時器,並在逾時後再試一次:
- 最後,依據相機影像的外觀比例來調整平面:
尋找世界空間中的相機位置
HoloLens 2 上的相機會與裝置的頭部追蹤垂直偏移。 有幾個函式可用來定位世界空間中的相機,以因應此情況。
GetPVCameraToWorldTransform 會取得 PV 相機世界空間中的轉換,並將其定位在相機鏡頭上:
GetWorldSpaceRayFromCameraPoint 會從相機鏡頭射出光線到 Unreal 世界空間中的場景,以找出相機框架中特定像素的內容:
GetPVCameraIntrinsics 會傳回相機內建值,這可在對相機框架進行電腦視覺處理時用到:
若要找出世界空間內的特定像素座標上有何項目,請搭配使用光線追蹤與世界空間光線:
在這裡,我們會從相機鏡頭射出 2 公尺的光線到框架左上角的相機空間位置 1/4 處。 然後,使用命中結果來呈現物件存在於世界空間中的某些內容:
使用空間對應時,此命中位置會符合相機所看到的表面。
在 C++ 中呈現 PV 相機摘要
- 建立名為 CamCapture 的新 C++ 動作項目
- 在專案的 build.cs 中,於 PublicDependencyModuleNames 清單中新增 “AugmentedReality”:
PublicDependencyModuleNames.AddRange(
new string[] {
"Core",
"CoreUObject",
"Engine",
"InputCore",
"AugmentedReality"
});
- 在 CamCapture.h 中,納入 ARBlueprintLibrary.h
#include "ARBlueprintLibrary.h"
- 您也需要為網格和材質新增本機變數:
private:
UStaticMesh* StaticMesh;
UStaticMeshComponent* StaticMeshComponent;
UMaterialInstanceDynamic* DynamicMaterial;
bool IsTextureParamSet = false;
- 在 CamCapture.cpp 中,更新建構函式以將靜態網格新增至場景:
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);
}
在 BeginPlay 中,從專案的相機材質建立動態材質執行個體,將其套用至靜態網格元件,然後啟動 HoloLens 相機。
在編輯器中,以滑鼠右鍵按一下內容瀏覽器中的 CamTextureMaterial,然後選取 [複製參考] 以取得 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);
}
在 [刻度] 中,從相機取得材質,將其設定為 CamTextureMaterial 材質中的材質參數,並根據相機框架的外觀比例調整靜態網格元件:
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));
}
}
下一個開發檢查點
依循我們配置的 Unreal 開發旅程,此時您會探索混合實境平台功能和 API。 接下來,您可以繼續進行下一個主題:
或者,直接跳到在裝置或模擬器上部署應用程式的主題:
您可以隨時回到 Unreal 開發檢查點。