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;
	}
相关推荐
感哥14 小时前
C++ STL 常用算法
c++
saltymilk1 天前
C++ 模板参数推导问题小记(模板类的模板构造函数)
c++·模板元编程
感哥1 天前
C++ lambda 匿名函数
c++
沐怡旸1 天前
【底层机制】std::unique_ptr 解决的痛点?是什么?如何实现?怎么正确使用?
c++·面试
感哥1 天前
C++ 内存管理
c++
博笙困了2 天前
AcWing学习——双指针算法
c++·算法
感哥2 天前
C++ 指针和引用
c++
感哥2 天前
C++ 多态
c++
沐怡旸2 天前
【底层机制】std::string 解决的痛点?是什么?怎么实现的?怎么正确用?
c++·面试
River4162 天前
Javer 学 c++(十三):引用篇
c++·后端