一、得到当前运行的屏幕分辨率:
FVector2D ScreenPos = GEngine->GameViewport->Viewport->GetSizeXY();
二、使用DeprojectScreenPositionToWorld运算:
PlayerController->DeprojectScreenPositionToWorld(ScreenPos.X / 2.0f, ScreenPos.Y / 2.0f, MousePos, MouseDir);
其中,PlayerController为对应的控制器。
/** The view port representing the current game instance. Can be 0 so don't use without checking. */ UPROPERTY() class UGameViewportClient* GameViewport;
UGameViewportClient的说明:
/**
* A game viewport (FViewport) is a high-level abstract interface for the
* platform specific rendering, audio, and input subsystems.
* GameViewportClient is the engine's interface to a game viewport.
* Exactly one GameViewportClient is created for each instance of the game. The
* only case (so far) where you might have a single instance of Engine, but
* multiple instances of the game (and thus multiple GameViewportClients) is when
* you have more than one PIE window running.
*
* Responsibilities:
* propagating input events to the global interactions list
*
* @see UGameViewportClient
*/
UCLASS(Within=Engine, transient, config=Engine)
class ENGINE_API UGameViewportClient : public UScriptViewportClient, public FExec
解(反)投影?不确切这个词怎么译……。
/** Convert current mouse 2D position to World Space 3D position and direction. Returns false if unable to determine value. **/ UFUNCTION(BlueprintCallable, Category = "Game|Player", meta = (DisplayName = "ConvertScreenLocationToWorldSpace", Keywords = "deproject")) bool DeprojectScreenPositionToWorld(float ScreenX, float ScreenY, FVector& WorldLocation, FVector& WorldDirection) const;
DeprojectScreenPositionToWorld函数的实现:其实就是调用了UGameplayStatics中对应的函数,UGameplayStatics中所有的函数必须要了然于胸,抽时间看吧……。
继续扒代码:
/** * Transforms the given 2D screen space coordinate into a 3D world-space point and direction. * @param Player Deproject using this player's view. * @param ScreenPosition 2D screen space to deproject. * @param WorldPosition (out) Corresponding 3D position in world space. * @param WorldDirection (out) World space direction vector away from the camera at the given 2d point. */ UFUNCTION(BlueprintPure, Category = "Utilities", meta = (Keywords = "unproject")) static bool DeprojectScreenToWorld(APlayerController const* Player, const FVector2D& ScreenPosition, FVector& WorldPosition, FVector& WorldDirection);
对应的实现函数:
bool UGameplayStatics::DeprojectScreenToWorld(APlayerController const* Player, const FVector2D& ScreenPosition, FVector& WorldPosition, FVector& WorldDirection) { ULocalPlayer* const LP = Player ? Player->GetLocalPlayer() : nullptr; if (LP && LP->ViewportClient) { // get the projection data FSceneViewProjectionData ProjectionData; if (LP->GetProjectionData(LP->ViewportClient->Viewport, eSSP_FULL, /*out*/ ProjectionData)) { FMatrix const InvViewProjMatrix = ProjectionData.ComputeViewProjectionMatrix().InverseFast(); FSceneView::DeprojectScreenToWorld(ScreenPosition, ProjectionData.GetConstrainedViewRect(), InvViewProjMatrix, /*out*/ WorldPosition, /*out*/ WorldDirection); return true; } } // something went wrong, zero things and return false WorldPosition = FVector::ZeroVector; WorldDirection = FVector::ZeroVector; return false; }
擦,一看到InvViewProjMatrix = ……InverseFast(),不用研究了,就是World,View,Projection的逆矩阵。
下一步凭猜测就是屏幕空间变换的逆矩阵,,,唔,,,,没什么出彩的地方,但是得记住这个函数,至少也得知道,需要时到UGameplayStatics类中查找。。。