首页 > 其他分享 >UE4获取玩家视角相机的位置和朝向

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

时间:2024-09-16 19:34:57浏览次数:9  
标签:视角 PlayWorld return ViewFamily Iterator ViewLocation 朝向 UE4 GEditor

游戏线程(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)

 

标签:视角,PlayWorld,return,ViewFamily,Iterator,ViewLocation,朝向,UE4,GEditor
From: https://www.cnblogs.com/kekec/p/18415498

相关文章

  • 信息架构的战略视角:驱动数字化转型的设计原则与实践创新
    在数字经济快速发展的今天,企业的成功越来越依赖于其信息架构的稳健性和灵活性数字化转型不仅要求技术创新,更需要架构设计上的深思熟虑。《信息架构:商业智能&分析与元数据管理参考模型》作为信息架构领域的权威指南,为企业提供了宝贵的实践经验和应用策略。《信息架构:商业智能&......
  • (不用互三)人工智能时代开启个人潜能探索的全新视角
    ......
  • UE4(5)逆向学习笔记(三)——UEDumper源码学习
    目录0.前言1.准备2.开始阅读2.1设置版本和Offset2.2获取GName2.3使用GName2.4获取GUObjectArray2.5使用GUObjectArray2.6寻找dump主流程2.6.1ObjectsManager::copyGObjectPtrs2.6.2ObjectsManager::copyUBigObjects2.6.3EngineCore::cacheFNames2.6.4EngineCo......
  • Cesium 展示——视角漫游飞行效果
    文章目录需求分析需求指定区域进行视角漫游飞行20240910_152908后续我又添加了无人机模型......
  • 防患于未然,智能监控新视角:EasyCVR视频平台在高校安全防控中的关键角色
    有网民发视频称,某大学食堂内发生争执打斗事件。一男一女两名学生疑似因座位问题发生争执,女子被打倒在地。此事引发网友关注。高校食堂作为师生日常用餐的聚集地,人员密集且流动性大,极易因排队、价格、口味等问题引发争执,甚至升级为打斗事件。这些事件不仅破坏了校园和谐氛围,还可能......
  • 全面解析智慧医院:从建设到应用的全新视角
    智慧医院是什么?智慧医院是一种新型的医疗机构,它利用先进的信息技术、数据分析和智能化系统,优化医院的管理和服务流程,提高医疗质量和效率。在智慧医院中,所有的运营和管理环节都可以通过数据驱动的方式来实现优化,从而使医院的服务更精准、更高效。智慧医院不仅仅是引入电子病历、......
  • Vue2 - 最新实现百度地图3D立体感视角教程及示例代码,利用WebGL实现3d百度地图详细流程
    前言如果您需要Vue3版本,请访问在vue2|nuxt2项目开发中,详解实现“安装引入百度地图webgl技术,实现3d地图教程”将百度地图变成3D视角效果,让百度地图平面2D视图和3D立体视图进行切换渲染显示,vue如何实现百度地图的三维立体地图效果,解决WebGL引入报错或无效、3D地图......
  • UE4 中射线检测的简单探索
    通过源码了解实现简单的实现原理。非常粗浅,只涉及一些基本的调用路径。LineTrace...这个函数实际上是调用的TSceneCastCommon这个模板函数template<typenameTraits,typenameTGeomInputs>boolTSceneCastCommon(constUWorld*World,typenameTraits::TOutHits&OutHits,c......
  • 快递时效新视角:‌批量分析派件与签收策略
    在快递行业日益竞争的今天,时效成为了衡量快递服务质量的重要指标之一。对于商家和消费者而言,了解快递从到达最后站点到派件以及签收的时效,对于优化物流流程、提升客户体验具有重要意义。本文将介绍如何利用快递批量查询高手软件,批量分析快递到最站后的派件时效与签收时效,为快递时效......
  • 停止在 AWS 中使用 SSH!原因如下!DevSecOps 视角
    我们要解决什么问题?欢迎来到雲闪世界。我见过多少次安全组从10.0.0.0/8或更糟的0.0.0.0/0开放端口22?太多次了!但为什么,为什么在有更好的替代方案的情况下,我们在2024年仍在使用SSH?作为一名安全专家,我经常被要求说服人们“一种更好的工作方式”。我经常失败。人们喜欢快......