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;
	}
相关推荐
Pocker_Spades_A4 分钟前
飞算JavaAI家庭记账系统:从收支记录到财务分析的全流程管理方案
java·开发语言
CHEN5_021 小时前
【Java基础常见辨析】重载与重写,深拷贝与浅拷贝,抽象类与普通类
java·开发语言
Despacito0o1 小时前
C语言基础:变量与进制详解
java·c语言·开发语言
nightunderblackcat2 小时前
进阶向:人物关系三元组,解锁人物关系网络的钥匙
开发语言·python·开源·php
光头闪亮亮2 小时前
C++凡人修仙法典 - 宗门版-上
c++
光头闪亮亮2 小时前
C++凡人修仙法典 - 宗门版-下
c++
John_ToDebug3 小时前
Chromium base 库中的 Observer 模式实现:ObserverList 与 ObserverListThreadSafe 深度解析
c++·chrome·性能优化
科大饭桶3 小时前
C++入门自学Day11-- String, Vector, List 复习
c语言·开发语言·数据结构·c++·容器
范范之交3 小时前
JavaScript基础语法two
开发语言·前端·javascript
Felven3 小时前
C. Game of Mathletes
c语言·开发语言