Custom Mesh FOV

Thanks staticvoidlol for point out the issue. The last code I wrote which invoke a game thread function in render thread. The following code is my latest fix. Although it looks clumsy about calculating project/view matrix for viewport, it works perfectly here.

FMatrix CustomFOVMeshComponent::GetRenderMatrix() const
{
	//Get camera perspectiveMatrix
	APlayerController* playerController = ()->GetFirstPlayerController();
	if (playerController)
	{
		ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(playerController->Player);

		if (LocalPlayer != NULL && LocalPlayer->ViewportClient != NULL && LocalPlayer->ViewportClient->Viewport != NULL)
		{
			FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
				LocalPlayer->ViewportClient->Viewport,
				()->Scene,
				LocalPlayer->ViewportClient->EngineShowFlags)
				.SetWorldTimes(0.0f, 0.0f, 0.0f)
				.SetRealtimeUpdate(false));

			FVector ViewLocation;
			FRotator ViewRotation;

			float MinZ = 3.0f;
			float MaxZ = MinZ;

			// Avoid zero ViewFOV's which cause divide by zero's in projection matrix
			float MatrixFOV = FMath::Max(0.001f, WeaponFOV) * (float)PI / 360.0f;

			FMatrix projMatrix = FReversedZPerspectiveMatrix(
					MatrixFOV,
					MatrixFOV,
					1.0f,
					LocalPlayer->Size.X * LocalPlayer->ViewportClient->Viewport->GetSizeXY().X / (LocalPlayer->Size.Y * LocalPlayer->ViewportClient->Viewport->GetSizeXY().Y),
					MinZ,
					MaxZ
					);

			FScaleMatrix ClipSpaceFixScale(FVector(1.0f, 1.0f, 1.0f - 0.0f));
			FTranslationMatrix ClipSpaceFixTranslate(FVector(0.0f, 0.0f, 0.0f));
			projMatrix =  projMatrix * ClipSpaceFixScale * ClipSpaceFixTranslate;

			FMatrix viewMatrix;
			FMatrix invViewProjectionMatrix;

			GetViewMatrices(viewMatrix, invViewProjectionMatrix);

			FMatrix adjustedViewProjectMatrix = viewMatrix * projMatrix;
			FMatrix inverseOldViewProjectMatrix = invViewProjectionMatrix;
			FMatrix adjTransform = ComponentToWorld.ToMatrixWithScale() * adjustedViewProjectMatrix * inverseOldViewProjectMatrix;

			return adjTransform;
		}
		else
		{
			return Super::GetRenderMatrix();
		}
	}
	else
	{
		return Super::GetRenderMatrix();
	}
}

void CustomFOVMeshComponent::GetViewMatrices(FMatrix& viewMatrix, FMatrix& invViewProjectionMatrix) const
{
	APlayerController* playerController = ()->GetFirstPlayerController();
	ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(playerController->Player);

	//Get View Origin
	FVector ViewOrigin;
	FRotator ViewRotation;
	playerController->GetPlayerViewPoint(/*out*/ ViewOrigin, /*out*/ ViewRotation);

	FMatrix ViewRotationMatrix = FInverseRotationMatrix(ViewRotation) * FMatrix(
		FPlane(0, 0, 1, 0),
		FPlane(1, 0, 0, 0),
		FPlane(0, 1, 0, 0),
		FPlane(0, 0, 0, 1));

	if (!ViewRotationMatrix.GetOrigin().IsNearlyZero(0.0f))
	{
		ViewOrigin += ViewRotationMatrix.InverseTransformPosition(FVector::ZeroVector);
		ViewRotationMatrix = ViewRotationMatrix.RemoveTranslation();
	}

	// Calculate view matrix
	viewMatrix = FTranslationMatrix(-ViewOrigin) * ViewRotationMatrix;

	// Calculate project matrix
	int32 X = FMath::TruncToInt(LocalPlayer->Origin.X * LocalPlayer->ViewportClient->Viewport->GetSizeXY().X);
	int32 Y = FMath::TruncToInt(LocalPlayer->Origin.Y * LocalPlayer->ViewportClient->Viewport->GetSizeXY().Y);
	uint32 SizeX = FMath::TruncToInt(LocalPlayer->Size.X * LocalPlayer->ViewportClient->Viewport->GetSizeXY().X);
	uint32 SizeY = FMath::TruncToInt(LocalPlayer->Size.Y * LocalPlayer->ViewportClient->Viewport->GetSizeXY().Y);

	FIntRect UnconstrainedRectangle = FIntRect(X, Y, X + SizeX, Y + SizeY);

	FSceneViewProjectionData ProjectionData;
	ProjectionData.SetViewRectangle(UnconstrainedRectangle);

	FMinimalViewInfo OutViewInfo;

	if (playerController->PlayerCameraManager != NULL)
	{
		OutViewInfo = playerController->PlayerCameraManager->CameraCache.POV;
		OutViewInfo.FOV = playerController->PlayerCameraManager->GetFOVAngle();
		playerController->GetPlayerViewPoint(/*out*/ OutViewInfo.Location, /*out*/ OutViewInfo.Rotation);
	}
	else
	{
		playerController->GetPlayerViewPoint(/*out*/ OutViewInfo.Location, /*out*/ OutViewInfo.Rotation);
	}

	FMinimalViewInfo::CalculateProjectionMatrixGivenView(OutViewInfo, LocalPlayer->AspectRatioAxisConstraint, LocalPlayer->ViewportClient->Viewport, /*inout*/ ProjectionData);

	FMatrix ProjMatrix = ProjectionData.ProjectionMatrix;

	FViewMatrices ViewMatrices;
	ViewMatrices.ViewMatrix = viewMatrix;
	ViewMatrices.ProjMatrix = ProjMatrix;
	invViewProjectionMatrix = ViewMatrices.GetInvViewProjMatrix();
}