可可西

UE4获取玩家视角相机的位置和朝向

游戏线程(GameThread)

编辑器中(EWorldType::Editor,模拟运行或编辑状态)

bool GetObserverView(FVector& Location, FRotator& Rotation) const
{
    // We are in the SIE(Simulate In Editor)
    if (GEditor->bIsSimulatingInEditor  // class UEditorEngine* GEditor
        && GCurrentLevelEditingViewportClient->IsSimulateInEditorViewport())  // class FLevelEditorViewportClient* GCurrentLevelEditingViewportClient
    {
        Rotation = GCurrentLevelEditingViewportClient->GetViewRotation();
        Location = GCurrentLevelEditingViewportClient->GetViewLocation();
        return true;
    }

    // We are in the editor world
    if (GEditor->PlayWorld == nullptr)
    {
        for (const FLevelEditorViewportClient* ViewportClient : GEditor->GetLevelViewportClients())
        {
            if (ViewportClient && ViewportClient->IsPerspective())
            {
                Rotation = ViewportClient->GetViewRotation();
                Location = ViewportClient->GetViewLocation();
                return true;
            }
        }
    }

    return false;
}

 

编辑器中(EWorldType::PIE,Play状态)

bool GetPlayerView(FVector& Location, FRotator& Rotation) const
{
    if (GEditor->bIsSimulatingInEditor || GEditor->PlayWorld != NULL)
    {
        UWorld* SimulationWorld = GEditor->PlayWorld;
        for (FConstPlayerControllerIterator Iterator = SimulationWorld->GetPlayerControllerIterator(); Iterator; ++Iterator)
        {
            if (APlayerController* PlayerActor = Iterator->Get())
            {
                PlayerActor->GetPlayerViewPoint(Location, Rotation);
                return true;
            }
        }
    }
    
    return false;
}

 

游戏运行时(本地有多个LocalPlayer)

bool GetPlayerViews(TArray<FVector>& Locations, TArray<FRotator>& Rotations) const
{
    UWorld* PlayWorld = GetWorld();
    int32 NumPlayers = GEngine->GetNumGamePlayers(PlayWorld);
    if (NumPlayers == 0)
    {
        return false;
    }

    // calculate centroid location using local players views
    bool bCinematic = false;
    FVector CentroidLocation = FVector::ZeroVector;
        
    for (int32 PlayerIndex = 0; PlayerIndex < NumPlayers; ++PlayerIndex)
    {
        ULocalPlayer* Player = GEngine->GetGamePlayer(PlayWorld, PlayerIndex);
        if (Player && Player->PlayerController)
        {
            FVector ViewLocation;
            FRotator ViewRotation;
            Player->PlayerController->GetPlayerViewPoint(ViewLocation, ViewRotation);
            Locations.Add(ViewLocation);
            Rotations.Add(ViewRotation);
            CentroidLocation+= ViewLocation;
            bCinematic|= Player->PlayerController->bCinematicMode;
        }
    }
    
    return true;
}

 

游戏运行时(获取本地第一个LocalPlayer)

bool GetPlayerView(FVector& Location, FRotator& Rotation) const
{
    UWorld* PlayWorld = GetWorld();
    if (PlayWorld && PlayWorld->GetGameInstance())
    {
        APlayerController* PC = PlayWorld->GetGameInstance()->GetFirstLocalPlayerController(nullptr);
        if (PC)
        {
            PC->GetPlayerViewPoint(Location, Rotation);
        }
    }
    
    return true;
}

 

渲染线程(RenderThread)

将游戏线程(GameThread)的ULocalPlayer对象上的相机的位置和朝向传给渲染线程(RenderThread)的FSceneRender对象中,以供渲染线程(RenderThread)的逻辑使用

void UGameEngine::Tick( float DeltaSeconds, bool bIdleMode )
{
    UGameEngine::RedrawViewports()
    {
        void FViewport::Draw( bool bShouldPresent)
        {
            void UGameViewportClient::Draw()
            {
                // create the view family for rendering the world scene to the viewport's render target
                FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
                    InViewport,
                    MyWorld->Scene,
                    EngineShowFlags)
                    .SetRealtimeUpdate(true));for (FLocalPlayerIterator Iterator(GEngine, MyWorld); Iterator; ++Iterator)
                {
                    ULocalPlayer* LocalPlayer = *Iterator;
                    if (LocalPlayer)
                    {
                        APlayerController* PlayerController = LocalPlayer->PlayerController;
                        const int32 NumViews = bStereoRendering ? GEngine->StereoRenderingDevice->GetDesiredNumberOfViews(bStereoRendering) : 1;

                        for (int32 i = 0; i < NumViews; ++i)
                        {
                            // Calculate the player's view information.
                            FVector     ViewLocation;
                            FRotator    ViewRotation;

                            EStereoscopicPass PassType = bStereoRendering ? GEngine->StereoRenderingDevice->GetViewPassForIndex(bStereoRendering, i) : eSSP_FULL;

                            // CalcSceneView函数中会把ViewLocation、ViewRotation赋值给FSceneView,然后添加到TArray<const FSceneView*> ViewFamily->Views数组中
                            LocalPlayer->CalcSceneView(&ViewFamily, ViewLocation, ViewRotation, InViewport, nullptr, PassType); 
                            
                            // ... ...
                        }
                        
                        // ... ...
                    }
                }
                
                // 发送渲染命令
                GetRendererModule().BeginRenderingViewFamily(SceneCanvas,&ViewFamily);
                {
                    World->SendAllEndOfFrameUpdates();
                    // 创建场景渲染器
                    FSceneRenderer* SceneRenderer = FSceneRenderer::CreateSceneRenderer(ViewFamily, ...);  // 参数ViewFamily会赋值给FSceneRenderer的FSceneViewFamily ViewFamily变量
                    
                    // 向渲染线程发送绘制场景指令.
                    ENQUEUE_RENDER_COMMAND(FDrawSceneCommand)(
                    [SceneRenderer](FRHICommandListImmediate& RHICmdList)
                    {
                        RenderViewFamily_RenderThread(RHICmdList, SceneRenderer)
                        {
                            (......)
                            // 调用场景渲染器的绘制接口.
                            SceneRenderer->Render(RHICmdList);
                            (......)
                        }
                        FlushPendingDeleteRHIResources_RenderThread();
                    });
                }
}}}}

 

渲染线程(RenderThread)从FSceneRenderer的ViewFamily.Views或Views上取FSceneView中的ViewLocation和ViewRotation,即为当前相机的位置和朝向     注:ViewFamily.Views和Views上存放的是同一个FSceneView对象

 

需要注意的是,一帧内可能同时存在多个FSceneRenderer实例

除了玩家视角相机的FSceneRender实例外,各个USceneCaptureComponent的相机也会有自己的FSceneRender实例

UActorComponent (184)
  USceneComponent (528)
    USceneCaptureComponent (720)
      USceneCaptureComponent2D (2368)
      UPlanarReflectionComponent (960)
      USceneCaptureComponentCube (768)

 

posted on 2024-09-16 19:39  可可西  阅读(15)  评论(0编辑  收藏  举报

导航