Skip to content

Instantly share code, notes, and snippets.

@tilongzs
Last active January 22, 2024 08:32
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tilongzs/a233eca957551c0106d155ce6cd2cd36 to your computer and use it in GitHub Desktop.
Save tilongzs/a233eca957551c0106d155ce6cd2cd36 to your computer and use it in GitHub Desktop.
(Unreal Engine)场景捕捉组件2D坐标与世界坐标的相互转换
#include "Components/SceneCaptureComponent2D.h"
#include "Engine/TextureRenderTarget2D.h"
void ProjectSceneCaptureToWorld(const class USceneCaptureComponent2D* sceneCaptureCompone2D, const FVector2D& sceneCapturePosition, FVector& worldPosition, FVector& worldDirection)
{
// 计算视口矩阵
const FTransform& transform = sceneCaptureCompone2D->GetComponentToWorld();
FMatrix viewMatrix = transform.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 = sceneCaptureCompone2D->FOVAngle * (float)PI / 360.0f;
FIntPoint captureSize(sceneCaptureCompone2D->TextureTarget->GetSurfaceWidth(), sceneCaptureCompone2D->TextureTarget->GetSurfaceHeight());
float XAxisMultiplier;
float YAxisMultiplier;
if (captureSize.X > captureSize.Y)
{
XAxisMultiplier = 1.0f;
YAxisMultiplier = captureSize.X / (float)captureSize.Y;
}
else
{
XAxisMultiplier = captureSize.Y / (float)captureSize.X;
YAxisMultiplier = 1.0f;
}
FMatrix projectionMatrix = FReversedZPerspectiveMatrix(FOV, FOV, XAxisMultiplier, YAxisMultiplier, GNearClippingPlane, GNearClippingPlane);
const FMatrix inverseViewMatrix = viewMatrix.InverseFast();
const FMatrix invProjectionMatrix = projectionMatrix.Inverse();
const FIntRect viewRect = FIntRect(0, 0, captureSize.X, captureSize.Y);
FSceneView::DeprojectScreenToWorld(sceneCapturePosition, viewRect, inverseViewMatrix, invProjectionMatrix, worldPosition, worldDirection);
}
bool ProjectWorldToSceneCapture(const FVector& worldPosition, const class USceneCaptureComponent2D* sceneCaptureCompone2D, FVector2D& sceneCapturePosition)
{
// 计算视口矩阵
const FTransform& transform = sceneCaptureCompone2D->GetComponentToWorld();
FMatrix viewMatrix = transform.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 = sceneCaptureCompone2D->FOVAngle * (float)PI / 360.0f;
FIntPoint captureSize(sceneCaptureCompone2D->TextureTarget->GetSurfaceWidth(), sceneCaptureCompone2D->TextureTarget->GetSurfaceHeight());
float XAxisMultiplier;
float YAxisMultiplier;
if (captureSize.X > captureSize.Y)
{
XAxisMultiplier = 1.0f;
YAxisMultiplier = captureSize.X / (float)captureSize.Y;
}
else
{
XAxisMultiplier = captureSize.Y / (float)captureSize.X;
YAxisMultiplier = 1.0f;
}
FMatrix projectionMatrix = FReversedZPerspectiveMatrix(FOV, FOV, XAxisMultiplier, YAxisMultiplier, GNearClippingPlane, GNearClippingPlane);
FMatrix viewProjectionMatrix = viewMatrix * projectionMatrix;
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;
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;
FVector2D rayStartViewRectSpace(
(normalizedX * (float)viewRect.Width()),
(normalizedY * (float)viewRect.Height())
);
sceneCapturePosition = rayStartViewRectSpace + FVector2D(static_cast<float>(viewRect.Min.X), static_cast<float>(viewRect.Min.Y));
return true;
}
return false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment