2023. 5. 16. 16:32ㆍunreal engine
//RaceController.h : 플레이어 컨트롤러
UCLASS()
class KLSRACE_API ARaceController : public APlayerController
{
GENERATED_BODY()
public:
URaceCamera* lPlayer;
public:
virtual void BeginPlay() override;
virtual void Tick(float deltaSeconds) override;
};
//RaceController.cpp : 플레이어 컨트롤러
void ARaceController::BeginPlay()
{
Super::BeginPlay();
lPlayer = (URaceCamera*)GetLocalPlayer();
SetShowMouseCursor(true);
}
void ARaceController::Tick(float deltaSeconds)
{
float mouseX, mouseY;
if (GetMousePosition(mouseX, mouseY))
{
if (lPlayer)
{
auto XY = lPlayer->ViewportClient->Viewport->GetSizeXY();
float mX = 0.0f - (mouseX - XY.X / 2) / XY.X;
float mY = (mouseY - XY.Y / 2) / XY.Y; //UE상하 좌표축 반대
lPlayer->EyePosition.Set(mX * 2.0f, mY * 2.0f);
}
}
}
//RaceCamera.h : 로컬 플레이어
UCLASS()
class KLSRACE_API URaceCamera : public ULocalPlayer
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
FVector2D EyePosition;
public:
URaceCamera(FVTableHelper& Helper) : Super(Helper)
{
//relative positions : abs(0~1)
EyePosition.Set(0, 0);
}
virtual FSceneView* CalcSceneView(class FSceneViewFamily* ViewFamily,
FVector& OutViewLocation,
FRotator& OutViewRotation,
FViewport* Viewport,
class FViewElementDrawer* ViewDrawer = NULL,
int32 StereoViewIndex = INDEX_NONE);
};
//RaceCamera.cpp : 로컬 플레이어
FSceneView* URaceCamera::CalcSceneView(
class FSceneViewFamily* ViewFamily,
FVector& OutViewLocation,
FRotator& OutViewRotation,
FViewport* Viewport,
class FViewElementDrawer* ViewDrawer /*= NULL*/,
int32 StereoViewIndex /*= eSSP_FULL*/)
{
auto View = ULocalPlayer::CalcSceneView(ViewFamily, OutViewLocation, OutViewRotation, Viewport, ViewDrawer, StereoViewIndex);
if (View)
{
//Get Original ViewInfo : 이건 계산한 다음에 원래 카메라에 잡힌 fov와 가로세로 비율을 적용해 주기 위함.
FMinimalViewInfo ViewInfo;
GetViewPoint(ViewInfo);
// to compute screen edges and screen axes
auto screenSize = Viewport->GetSizeXY();
FVector pa(screenSize.X * -0.5f, screenSize.Y * -0.5f, GNearClippingPlane); //lower left
FVector pb(screenSize.X * 0.5f, screenSize.Y * -0.5f, GNearClippingPlane); //lower right
FVector pc(screenSize.X * -0.5f, screenSize.Y * 0.5f, GNearClippingPlane); //upper left
// compute eye position
FVector pe(EyePosition.X, EyePosition.Y, -1);
// to compute projection matrix
FVector va = pa - pe; // from pe to pa
FVector vb = pb - pe; // from pe to pb
FVector vc = pc - pe; // from pe to pc
FVector vr = pb - pa; // right axis of screen
FVector vu = pc - pa; // up axis of screen
FVector vn = FVector::CrossProduct(vr, vu); // normal vector of screen
vr.Normalize(); //right
vu.Normalize(); //up
vn.Normalize(); //normal
float n = GNearClippingPlane; //near : GNearClippingPlane은 따로 정의되어 있어서 가져올 수 있다.
float f = 10000.0f; //far
float d = -FVector::DotProduct(va, vn); // distance from eye to screen(ratio)
float nd = n / d; // distance from eye to screen
float l = FVector::DotProduct(vr, va) * nd; // distance to left screen edge
float r = FVector::DotProduct(vr, vb) * nd; // distance to right screen edge
float b = FVector::DotProduct(vu, va) * nd; // distance to bottom screen edge
float t = FVector::DotProduct(vu, vc) * nd; // distance to top screen edge
//projection matrix
FMatrix offAxis = FMatrix::Identity;
offAxis.M[0][0] = -2.0f * n / (r - l);
offAxis.M[0][1] = 0;
offAxis.M[0][2] = 0;
offAxis.M[0][3] = 0;
offAxis.M[1][0] = 0;
offAxis.M[1][1] = -2.0f * n / (t - b);
offAxis.M[1][2] = 0;
offAxis.M[1][3] = 0;
offAxis.M[2][0] = -(r + l) / (r - l);
offAxis.M[2][1] = -(t + b) / (t - b);
offAxis.M[2][2] = (f + n) / (f - n);
offAxis.M[2][3] = 1;
offAxis.M[3][0] = 0;
offAxis.M[3][1] = 0;
offAxis.M[3][2] = (2.0f * f * n) / (f - n);
offAxis.M[3][3] = 0;
FMatrix rm = FMatrix::Identity; //Rotation Matrix
rm.M[0][0] = vr.X;
rm.M[0][1] = vr.Y;
rm.M[0][2] = vr.Z;
rm.M[1][0] = vu.X;
rm.M[1][1] = vu.Y;
rm.M[1][2] = vu.Z;
rm.M[2][0] = vn.X;
rm.M[2][1] = vn.Y;
rm.M[2][2] = vn.Z;
FMatrix tm = FMatrix::Identity; //Translation Matrix
tm.M[3][0] = -pe.X;
tm.M[3][1] = -pe.Y;
tm.M[3][2] = -pe.Z;
FMatrix prj = tm * (offAxis * rm);
prj.M[2][2] = 0.0f;
prj.M[3][0] = 0.0f;
prj.M[3][1] = 0.0f;
prj *= 1.0f / prj.M[0][0];
float FOVratio = 1.0f / FMath::Tan(FMath::Max(0.001f, ViewInfo.FOV) * (float)PI / 360.0f);
prj.M[0][0] *= FOVratio;
prj.M[1][1] *= FOVratio;
prj.M[2][0] *= GNearClippingPlane;
prj.M[2][1] *= GNearClippingPlane;
prj.M[2][3] = 1;
prj.M[3][2] = GNearClippingPlane;
//Update Projection Matrix
View->ProjectionMatrixUnadjustedForRHI = prj;
FMatrix* pProjectionMatrix = (FMatrix*)(&View->ViewMatrices.GetProjectionMatrix());
*pProjectionMatrix = AdjustProjectionMatrixForRHI(View->ProjectionMatrixUnadjustedForRHI);
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, offAxis.ToString());
FMatrix* pViewProjectionMatrix = (FMatrix*)(&View->ViewMatrices.GetViewProjectionMatrix());
*pViewProjectionMatrix = View->ViewMatrices.GetViewMatrix() * View->ViewMatrices.GetProjectionMatrix();
FMatrix* pInvViewProjectionMatrix = (FMatrix*)&View->ViewMatrices.GetInvViewProjectionMatrix();
*pInvViewProjectionMatrix = View->ViewMatrices.GetViewProjectionMatrix().Inverse();
FMatrix TranslatedViewMatrix = FTranslationMatrix(-View->ViewMatrices.GetPreViewTranslation()) * View->ViewMatrices.GetViewMatrix();
FMatrix* pTranslatedViewProjectionMatrix = (FMatrix*)(&View->ViewMatrices.GetTranslatedViewProjectionMatrix());
*pTranslatedViewProjectionMatrix = TranslatedViewMatrix * View->ViewMatrices.GetProjectionMatrix();
FMatrix* pInvTranslatedViewProjectionMatrixx = (FMatrix*)(&View->ViewMatrices.GetInvTranslatedViewProjectionMatrix());
*pInvTranslatedViewProjectionMatrixx = View->ViewMatrices.GetTranslatedViewProjectionMatrix().Inverse();
View->ShadowViewMatrices = View->ViewMatrices;
GetViewFrustumBounds(View->ViewFrustum, View->ViewMatrices.GetViewProjectionMatrix(), false);
}
return View;
}
'unreal engine' 카테고리의 다른 글
Tickable Object (0) | 2024.02.23 |
---|---|
Unreal 에서 Opencv를 이용한 webcam 화면 불러오기 (0) | 2023.08.23 |
Animation이 적용된 Skeletal Mesh (0) | 2023.05.13 |
Gradient Material (0) | 2023.05.11 |
지형용 머터리얼 만들기 → 적용 (0) | 2023.03.28 |