0
点赞
收藏
分享

微信扫一扫

Kafka 技术指南:使用、特性、一致性保证与 Golang 中间件应用(上)

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

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);
}

	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;
	}
举报

相关推荐

0 条评论