UE C++ 相机视口变换(World与相机互转)

UE C++ 相机视口变换(World与相机互转)

cpp 复制代码
UFUNCTION(BlueprintCallable, BlueprintPure)
static void ProjectSceneCaptureToWorld(const class USceneCaptureComponent2D* SceneCaptureComponent2D,
                                       const FVector2D& SceneCapturePosition, FVector& WorldPosition,
                                       FVector& WorldDirection)
{
	if (!IsValid(SceneCaptureComponent2D))
	{
		return;
	}
	// 视口矩阵
	const FTransform& ViewTransform = SceneCaptureComponent2D->GetComponentToWorld();
	FMatrix ViewMatrix = ViewTransform.ToInverseMatrixWithScale();
	ViewMatrix = ViewMatrix * FMatrix(FPlane(0, 0, 1, 0), FPlane(1, 0, 0, 0), FPlane(0, 1, 0, 0),
	                                  FPlane(0, 0, 0, 1));
	const float FOV = SceneCaptureComponent2D->FOVAngle * (float)PI / 360.0f;
	const FIntPoint CaptureSize(SceneCaptureComponent2D->TextureTarget->GetSurfaceWidth(),
	                            SceneCaptureComponent2D->TextureTarget->GetSurfaceHeight());
	float XAxisMultiplier;
	float YAxisMultiplier;
	if (CaptureSize.X > CaptureSize.Y)
	{
		XAxisMultiplier = 1.0f;
		YAxisMultiplier = CaptureSize.X / static_cast<float>(CaptureSize.Y);
	}
	else
	{
		XAxisMultiplier = CaptureSize.Y / static_cast<float>(CaptureSize.X);
		YAxisMultiplier = 1.0f;
	}
	// 投影矩阵
	const FMatrix ProjectionMatrix = FReversedZPerspectiveMatrix(FOV, FOV, XAxisMultiplier, YAxisMultiplier,
	                                                             GNearClippingPlane, GNearClippingPlane);
	//视口矩阵与投影矩阵的逆矩阵                                                           
	const FMatrix InverseViewMatrix = ViewMatrix.InverseFast();
	const FMatrix InverseProjectionMatrix = ProjectionMatrix.Inverse();

	const FIntRect ViewRect = FIntRect(0, 0, CaptureSize.X, CaptureSize.Y);
	FSceneView::DeprojectScreenToWorld(SceneCapturePosition, ViewRect, InverseViewMatrix, InverseProjectionMatrix,
	                                   WorldPosition, WorldDirection);
}
cpp 复制代码
	UFUNCTION(BlueprintCallable, BlueprintPure)
	static bool ProjectWorldToSceneCapture(const FVector& WorldPosition,
	                                       const class USceneCaptureComponent2D* SceneCaptureComponent2D,
	                                       FVector2D& SceneCapturePosition)
	{
		if (!IsValid(SceneCaptureComponent2D))
		{
			return false;
		}
		//视口矩阵
		const FTransform& ViewTransform = SceneCaptureComponent2D->GetComponentToWorld();
		FMatrix ViewMatrix = ViewTransform.ToInverseMatrixWithScale();
		ViewMatrix = ViewMatrix * FMatrix(FPlane(0, 0, 1, 0), FPlane(1, 0, 0, 0), FPlane(0, 1, 0, 0),
		                                  FPlane(0, 0, 0, 1));
		                                  
		const float FOV = SceneCaptureComponent2D->FOVAngle * (float)PI / 360.0f;
		const FIntPoint CaptureSize(SceneCaptureComponent2D->TextureTarget->GetSurfaceWidth(),
		                            SceneCaptureComponent2D->TextureTarget->GetSurfaceHeight());
		float XAxisMultiplier;
		float YAxisMultiplier;
		if (CaptureSize.X > CaptureSize.Y)
		{
			XAxisMultiplier = 1.0f;
			YAxisMultiplier = CaptureSize.X / static_cast<float>(CaptureSize.Y);
		}
		else
		{
			XAxisMultiplier = CaptureSize.Y / static_cast<float>(CaptureSize.X);
			YAxisMultiplier = 1.0f;
		}
		// 投影矩阵
		const FMatrix ProjectionMatrix = FReversedZPerspectiveMatrix(FOV, FOV, XAxisMultiplier, YAxisMultiplier,
		                                                             GNearClippingPlane, GNearClippingPlane);
		const FMatrix ViewProjectionMatrix = ViewMatrix * ProjectionMatrix;
		const FPlane Result = ViewProjectionMatrix.TransformFVector4(FVector4(WorldPosition, 1.f));
		const FIntRect viewRect = FIntRect(0, 0, CaptureSize.X, CaptureSize.Y);
		if (Result.W > 0.0f)
		{
			// the result of this will be x and y coords in -1..1 projection space
			const float RHW = 1.0f / Result.W;
			const FPlane PosInScreenSpace = FPlane(Result.X * RHW, Result.Y * RHW, Result.Z * RHW, Result.W);

			// Move from projection space to normalized 0..1 UI space
			const float NormalizedX = (PosInScreenSpace.X / 2.f) + 0.5f;
			const float NormalizedY = 1.f - (PosInScreenSpace.Y / 2.f) - 0.5f;

			const FVector2D RayStartViewRectSpace(
				(NormalizedX * static_cast<float>(viewRect.Width())),
				(NormalizedY * static_cast<float>(viewRect.Height()))
			);

			SceneCapturePosition = RayStartViewRectSpace + FVector2D(static_cast<float>(viewRect.Min.X),
			                                                         static_cast<float>(viewRect.Min.Y));

			return true;
		}
		return false;
	}
相关推荐
风中月隐6 分钟前
C语言中以坐标的方式图解“字母金字塔”的绘制
c语言·开发语言·算法·字母金子塔·坐标图解法
崇山峻岭之间6 分钟前
C++ Prime Plus 学习笔记041
c++·笔记·学习
_风华ts9 分钟前
虚函数与访问权限
c++
Arva .10 分钟前
说说线程的生命周期和状态
java·开发语言
1001101_QIA13 分钟前
C++中不能复制只能移动的类型
开发语言·c++
tryxr18 分钟前
HashTable、HashMap、ConcurrentHashMap 之间的区别
java·开发语言·hash
大土豆的bug记录19 分钟前
鸿蒙实现自定义类似活体检测功能
数码相机·华为·harmonyos·鸿蒙
serendipity_hky20 分钟前
【go语言 | 第5篇】channel——多个goroutine之间通信
开发语言·后端·golang
无事好时节23 分钟前
Linux 线程
java·开发语言·rpc
闻缺陷则喜何志丹24 分钟前
【组合数学】P9418 [POI 2021/2022 R1] Impreza krasnali|普及+
c++·数学·组合数学