From 4cc828e5d619e7712558cad6ea809e1363ffcc05 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Wed, 19 Feb 2025 22:10:29 +1100 Subject: [PATCH 01/16] Hacky support for view groups. --- .../CesiumRuntime/Private/Cesium3DTileset.cpp | 101 +++++++++++++++++- .../Private/CesiumGltfComponent.cpp | 33 ++++++ .../Private/CesiumGltfComponent.h | 5 + .../Private/CesiumGltfPrimitiveComponent.cpp | 98 +++++++++++++++++ .../Private/CesiumGltfPrimitiveComponent.h | 8 ++ .../Private/CesiumSceneCapture2D.cpp | 27 +++++ .../Private/CesiumSceneCaptureComponent2D.cpp | 11 ++ Source/CesiumRuntime/Public/Cesium3DTileset.h | 7 +- .../Public/CesiumCameraManager.h | 16 ++- .../Public/CesiumSceneCapture2D.h | 35 ++++++ .../Public/CesiumSceneCaptureComponent2D.h | 30 ++++++ extern/cesium-native | 2 +- 12 files changed, 364 insertions(+), 9 deletions(-) create mode 100644 Source/CesiumRuntime/Private/CesiumSceneCapture2D.cpp create mode 100644 Source/CesiumRuntime/Private/CesiumSceneCaptureComponent2D.cpp create mode 100644 Source/CesiumRuntime/Public/CesiumSceneCapture2D.h create mode 100644 Source/CesiumRuntime/Public/CesiumSceneCaptureComponent2D.h diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 7e6618583..5d0689fa7 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -1685,11 +1685,15 @@ void removeVisibleTilesFromList( * * @param tiles The tiles to hide */ -void hideTiles(const std::vector& tiles) { +void hideTiles( + const AActor* pViewActor, + const std::vector& tiles) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::HideTiles) forEachRenderableTile( tiles, - [](Cesium3DTilesSelection::Tile* /*pTile*/, UCesiumGltfComponent* pGltf) { + [pViewActor]( + Cesium3DTilesSelection::Tile* /*pTile*/, + UCesiumGltfComponent* pGltf) { if (pGltf->IsVisible()) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityFalse) pGltf->SetVisibility(false, true); @@ -1700,6 +1704,8 @@ void hideTiles(const std::vector& tiles) { Verbose, TEXT("Tile to no longer render does not have a visible Gltf")); } + + pGltf->SetViewGroupVisibility(pViewActor, false); }); } @@ -1894,11 +1900,13 @@ void ACesium3DTileset::updateLastViewUpdateResultState( } void ACesium3DTileset::showTilesToRender( + const AActor* pViewActor, const std::vector& tiles) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ShowTilesToRender) forEachRenderableTile( tiles, - [&RootComponent = this->RootComponent, + [pViewActor, + &RootComponent = this->RootComponent, &BodyInstance = this->BodyInstance]( Cesium3DTilesSelection::Tile* pTile, UCesiumGltfComponent* pGltf) { @@ -1928,6 +1936,8 @@ void ACesium3DTileset::showTilesToRender( pGltf->SetVisibility(true, true); } + pGltf->SetViewGroupVisibility(pViewActor, true); + { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetCollisionEnabled) pGltf->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); @@ -2038,7 +2048,7 @@ void ACesium3DTileset::Tick(float DeltaTime) { removeVisibleTilesFromList( _tilesToHideNextFrame, pResult->tilesToRenderThisFrame); - hideTiles(_tilesToHideNextFrame); + hideTiles(nullptr, _tilesToHideNextFrame); _tilesToHideNextFrame.clear(); for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) { @@ -2051,7 +2061,7 @@ void ACesium3DTileset::Tick(float DeltaTime) { } } - showTilesToRender(pResult->tilesToRenderThisFrame); + showTilesToRender(nullptr, pResult->tilesToRenderThisFrame); if (this->UseLodTransitions) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades) @@ -2060,6 +2070,87 @@ void ACesium3DTileset::Tick(float DeltaTime) { } this->UpdateLoadStatus(); + + ACesiumCameraManager* pCameraManager = + ACesiumCameraManager::GetDefaultCameraManager(this); + if (pCameraManager) { + this->_viewGroups.SetNum(pCameraManager->ViewGroups.Num()); + for (int32 i = 0; i < pCameraManager->ViewGroups.Num(); ++i) { + const FCesiumViewGroup& group = pCameraManager->ViewGroups[i]; + + std::vector frustums; + for (const TSoftObjectPtr& actor : + group.CamerasAndSceneCaptures) { + AActor* pActor = actor.Get(); + if (!pActor) + continue; + + USceneCaptureComponent2D* pSceneCaptureComponent = + pActor->GetComponentByClass(); + if (pSceneCaptureComponent) { + UTextureRenderTarget2D* pRenderTarget = + pSceneCaptureComponent->TextureTarget; + if (pRenderTarget && pSceneCaptureComponent->ProjectionType == + ECameraProjectionMode::Type::Perspective) { + + FVector2D renderTargetSize( + pRenderTarget->SizeX, + pRenderTarget->SizeY); + if (renderTargetSize.X >= 1.0 && renderTargetSize.Y >= 1.0) { + FVector captureLocation = + pSceneCaptureComponent->GetComponentLocation(); + FRotator captureRotation = + pSceneCaptureComponent->GetComponentRotation(); + double captureFov = pSceneCaptureComponent->FOVAngle; + + frustums.emplace_back(CreateViewStateFromViewParameters( + FCesiumCamera{ + renderTargetSize, + captureLocation, + captureRotation, + captureFov}, + unrealWorldToCesiumTileset, + ellipsoid)); + } + } + } + + UCameraComponent* pCameraComponent = + pActor->GetComponentByClass(); + if (pCameraComponent) { + APlayerController* pPlayerController = + GetWorld()->GetFirstPlayerController(); + if (pPlayerController) { + int32 sizeX, sizeY; + pPlayerController->GetViewportSize(sizeX, sizeY); + FVector2D renderTargetSize(sizeX, sizeY); + + frustums.emplace_back(CreateViewStateFromViewParameters( + FCesiumCamera{ + renderTargetSize, + pCameraComponent->GetComponentLocation(), + pCameraComponent->GetComponentRotation(), + pCameraComponent->FieldOfView}, + unrealWorldToCesiumTileset, + ellipsoid)); + } + } + } + + const Cesium3DTilesSelection::ViewUpdateResult& result = + this->_pTileset->updateView( + this->_viewGroups[i], + frustums, + DeltaTime); + + showTilesToRender(group.ViewActor.Get(), result.tilesToRenderThisFrame); + hideTiles( + group.ViewActor.Get(), + std::vector( + result.tilesFadingOut.begin(), + result.tilesFadingOut.end())); + } + } } void ACesium3DTileset::EndPlay(const EEndPlayReason::Type EndPlayReason) { diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp index 5522f8136..88da9a8a1 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -3623,6 +3623,39 @@ void UCesiumGltfComponent::UpdateFade(float fadePercentage, bool fadingIn) { } } +void UCesiumGltfComponent::SetViewGroupVisibility( + const AActor* ViewActor, + bool visibility) { + bool* pVisibility = this->_viewGroupVisibility.Find(ViewActor); + if (!pVisibility || *pVisibility != visibility) { + this->_viewGroupVisibility.FindOrAdd(ViewActor) = visibility; + + for (const TObjectPtr& pComponent : + this->GetAttachChildren()) { + UCesiumGltfPrimitiveComponent* pPrimitive = + Cast(pComponent); + if (!pPrimitive) + continue; + + if (!pPrimitive->SceneProxy) + continue; + + ENQUEUE_RENDER_COMMAND(Cesium_UpdateViewGroupVisibility) + ([viewGroupVisibility = this->_viewGroupVisibility, + pProxy = pPrimitive->SceneProxy](FRHICommandListImmediate& RHICmdList) mutable { + UCesiumGltfPrimitiveComponent::updateVisibilityInRenderThread( + pProxy, + std::move(viewGroupVisibility)); + }); + } + } +} + +bool UCesiumGltfComponent::GetViewGroupVisibility(const AActor* ViewActor) { + bool* pResult = this->_viewGroupVisibility.Find(ViewActor); + return pResult && *pResult; +} + template #if ENGINE_VERSION_5_4_OR_HIGHER static Chaos::FTriangleMeshImplicitObjectPtr diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.h b/Source/CesiumRuntime/Private/CesiumGltfComponent.h index e78b2d273..0ebd14d8a 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.h +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.h @@ -134,7 +134,12 @@ class UCesiumGltfComponent : public USceneComponent { void UpdateFade(float fadePercentage, bool fadingIn); + void SetViewGroupVisibility(const AActor* ViewActor, bool visibility); + bool GetViewGroupVisibility(const AActor* ViewActor); + private: UPROPERTY() UTexture2D* Transparent1x1 = nullptr; + + TMap _viewGroupVisibility; }; diff --git a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp index 68951e5f9..92ed82dfa 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp @@ -2,11 +2,14 @@ #include "CesiumGltfPrimitiveComponent.h" #include "CalcBounds.h" +#include "CesiumCameraManager.h" +#include "CesiumGltfComponent.h" #include "CesiumLifetime.h" #include "CesiumMaterialUserData.h" #include "Engine/Texture.h" #include "Materials/MaterialInstanceDynamic.h" #include "PhysicsEngine/BodySetup.h" +#include "StaticMeshSceneProxy.h" #include "VecMath.h" #include @@ -90,6 +93,93 @@ FBoxSphereBounds UCesiumGltfPrimitiveComponent::CalcBounds( return Super::CalcBounds(LocalToWorld); } +namespace { + +class FCesiumGltfPrimitiveSceneProxy : public FStaticMeshSceneProxy { +public: + FCesiumGltfPrimitiveSceneProxy( + UStaticMeshComponent* Component, + bool bForceLODsShareStaticLighting, + TMap&& viewGroupVisibility) + : FStaticMeshSceneProxy(Component, bForceLODsShareStaticLighting), + _viewsVisibility(std::move(viewGroupVisibility)) {} + + FPrimitiveViewRelevance + GetViewRelevance(const FSceneView* View) const override { + FPrimitiveViewRelevance relevance = + FStaticMeshSceneProxy::GetViewRelevance(View); + + const bool* pVisibility = this->_viewsVisibility.Find(View->ViewActor); + if (pVisibility) { + // We have visibility information for the view group corresponding to this + // ViewActor. It may be the default view group if ViewActor==nullptr. + if (!*pVisibility) { + relevance.bDrawRelevance = false; + relevance.bShadowRelevance = false; + } + } else { + // We don't have visibility information for a view group corresponding to + // this ViewActor, so use the visibility information for the default view + // group. + pVisibility = this->_viewsVisibility.Find(nullptr); + check(pVisibility); + if (pVisibility && !*pVisibility) { + relevance.bDrawRelevance = false; + relevance.bShadowRelevance = false; + } + } + + return relevance; + } + + void updateVisibility(TMap&& newVisibility) { + this->_viewsVisibility = std::move(newVisibility); + } + +private: + // An entry per ViewActor assigned to a view group, plus an entry for nullptr + // which is the visibility of this primitive in the default view group. + TMap _viewsVisibility; +}; + +} // namespace + +FPrimitiveSceneProxy* UCesiumGltfPrimitiveComponent::CreateStaticMeshSceneProxy( + Nanite::FMaterialAudit& NaniteMaterials, + bool bCreateNanite) { + check(!bCreateNanite); + + ACesiumCameraManager* pCameraManager = + ACesiumCameraManager::GetDefaultCameraManager(this->GetOwner()); + + UCesiumGltfComponent* pGltf = + Cast(this->GetAttachParent()); + + TMap viewGroupVisibility{ + {nullptr, pGltf ? pGltf->GetViewGroupVisibility(nullptr) : false}}; + if (pCameraManager) { + for (const FCesiumViewGroup& group : pCameraManager->ViewGroups) { + if (group.ViewActor != nullptr) + viewGroupVisibility.Add( + group.ViewActor.Get(), + pGltf ? pGltf->GetViewGroupVisibility(group.ViewActor.Get()) + : false); + } + } else { + viewGroupVisibility = {{nullptr, false}}; + } + + auto* Proxy = ::new FCesiumGltfPrimitiveSceneProxy( + this, + false, + std::move(viewGroupVisibility)); +#if STATICMESH_ENABLE_DEBUG_RENDERING + SendRenderDebugPhysics(Proxy); +#endif + + return Proxy; +} + FBoxSphereBounds UCesiumGltfInstancedComponent::CalcBounds( const FTransform& LocalToWorld) const { if (auto bounds = calcBounds(*this, LocalToWorld)) { @@ -159,6 +249,14 @@ UCesiumGltfPrimitiveComponent::getPrimitiveData() const { return _cesiumData; } +void UCesiumGltfPrimitiveComponent::updateVisibilityInRenderThread( + FPrimitiveSceneProxy* pProxy, + TMap&& visibility) { + check(pProxy); + static_cast(pProxy)->updateVisibility( + std::move(visibility)); +} + CesiumPrimitiveData& UCesiumGltfInstancedComponent::getPrimitiveData() { return _cesiumData; } diff --git a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h index 081fe682c..9d8364637 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h +++ b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h @@ -34,12 +34,20 @@ class UCesiumGltfPrimitiveComponent : public UStaticMeshComponent, FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override; + FPrimitiveSceneProxy* CreateStaticMeshSceneProxy( + Nanite::FMaterialAudit& NaniteMaterials, + bool bCreateNanite) override; + void UpdateTransformFromCesium(const glm::dmat4& CesiumToUnrealTransform) override; CesiumPrimitiveData& getPrimitiveData() override; const CesiumPrimitiveData& getPrimitiveData() const override; + static void updateVisibilityInRenderThread( + FPrimitiveSceneProxy* pProxy, + TMap&& visibility); + private: CesiumPrimitiveData _cesiumData; }; diff --git a/Source/CesiumRuntime/Private/CesiumSceneCapture2D.cpp b/Source/CesiumRuntime/Private/CesiumSceneCapture2D.cpp new file mode 100644 index 000000000..3bb25b00f --- /dev/null +++ b/Source/CesiumRuntime/Private/CesiumSceneCapture2D.cpp @@ -0,0 +1,27 @@ +// Copyright 2020-2025 CesiumGS, Inc. and Contributors + +#include "CesiumSceneCapture2D.h" +#include "CesiumSceneCaptureComponent2D.h" + +ACesiumSceneCapture2D::ACesiumSceneCapture2D( + const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) { + CaptureComponent2D = CreateDefaultSubobject( + TEXT("NewSceneCaptureComponent2D")); + CaptureComponent2D->SetupAttachment(RootComponent); +} + +void ACesiumSceneCapture2D::OnInterpToggle(bool bEnable) { + CaptureComponent2D->SetVisibility(bEnable); +} + +void ACesiumSceneCapture2D::CalcCamera( + float DeltaTime, + FMinimalViewInfo& OutMinimalViewInfo) { + if (UCesiumSceneCaptureComponent2D* SceneCaptureComponent = + GetCaptureComponent2D()) { + SceneCaptureComponent->GetCameraView(DeltaTime, OutMinimalViewInfo); + } else { + Super::CalcCamera(DeltaTime, OutMinimalViewInfo); + } +} diff --git a/Source/CesiumRuntime/Private/CesiumSceneCaptureComponent2D.cpp b/Source/CesiumRuntime/Private/CesiumSceneCaptureComponent2D.cpp new file mode 100644 index 000000000..22db8bcff --- /dev/null +++ b/Source/CesiumRuntime/Private/CesiumSceneCaptureComponent2D.cpp @@ -0,0 +1,11 @@ +// Copyright 2020-2025 CesiumGS, Inc. and Contributors + +#include "CesiumSceneCaptureComponent2D.h" + +UCesiumSceneCaptureComponent2D::UCesiumSceneCaptureComponent2D( + const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) {} + +const AActor* UCesiumSceneCaptureComponent2D::GetViewOwner() const { + return this->GetOwner(); +} diff --git a/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Source/CesiumRuntime/Public/Cesium3DTileset.h index 50de411ff..4ce085b9d 100644 --- a/Source/CesiumRuntime/Public/Cesium3DTileset.h +++ b/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -1228,8 +1228,9 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { * * @param tiles The tiles */ - void - showTilesToRender(const std::vector& tiles); + void showTilesToRender( + const AActor* pViewActor, + const std::vector& tiles); /** * Will be called after the tileset is loaded or spawned, to register @@ -1309,6 +1310,8 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { int32 _tilesetsBeingDestroyed; + TArray _viewGroups; + friend class UnrealPrepareRendererResources; friend class UCesiumGltfPointsComponent; }; diff --git a/Source/CesiumRuntime/Public/CesiumCameraManager.h b/Source/CesiumRuntime/Public/CesiumCameraManager.h index 4575a7dd2..445351a33 100644 --- a/Source/CesiumRuntime/Public/CesiumCameraManager.h +++ b/Source/CesiumRuntime/Public/CesiumCameraManager.h @@ -2,12 +2,23 @@ #pragma once +#include "Camera/CameraComponent.h" #include "CesiumCamera.h" #include "Containers/Map.h" #include "GameFramework/Actor.h" - #include "CesiumCameraManager.generated.h" +USTRUCT(BlueprintType) +struct CESIUMRUNTIME_API FCesiumViewGroup { + GENERATED_USTRUCT_BODY() + + UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) + TSoftObjectPtr ViewActor; + + UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) + TArray> CamerasAndSceneCaptures; +}; + /** * @brief Manages custom {@link FCesiumCamera}s for all * {@link ACesium3DTileset}s in the world. @@ -72,6 +83,9 @@ class CESIUMRUNTIME_API ACesiumCameraManager : public AActor { virtual void Tick(float DeltaTime) override; + UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) + TArray ViewGroups; + private: int32 _currentCameraId = 0; TMap _cameras; diff --git a/Source/CesiumRuntime/Public/CesiumSceneCapture2D.h b/Source/CesiumRuntime/Public/CesiumSceneCapture2D.h new file mode 100644 index 000000000..17370e41e --- /dev/null +++ b/Source/CesiumRuntime/Public/CesiumSceneCapture2D.h @@ -0,0 +1,35 @@ +// Copyright 2020-2025 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/SceneCapture.h" +#include "UObject/ObjectMacros.h" +#include "CesiumSceneCapture2D.generated.h" + +UCLASS(hidecategories = (Collision, Material, Attachment, Actor), MinimalAPI) +class ACesiumSceneCapture2D : public ASceneCapture { + GENERATED_UCLASS_BODY() + +private: + /** Scene capture component. */ + UPROPERTY( + Category = Cesium, + VisibleAnywhere, + BlueprintReadOnly, + meta = (AllowPrivateAccess = "true")) + TObjectPtr CaptureComponent2D; + +public: + UFUNCTION(BlueprintCallable, Category = "Rendering") + void OnInterpToggle(bool bEnable); + + CESIUMRUNTIME_API virtual void CalcCamera( + float DeltaTime, + struct FMinimalViewInfo& OutMinimalViewInfo) override; + + /** Returns CaptureComponent2D subobject **/ + class UCesiumSceneCaptureComponent2D* GetCaptureComponent2D() const { + return CaptureComponent2D; + } +}; diff --git a/Source/CesiumRuntime/Public/CesiumSceneCaptureComponent2D.h b/Source/CesiumRuntime/Public/CesiumSceneCaptureComponent2D.h new file mode 100644 index 000000000..e6d9ec25b --- /dev/null +++ b/Source/CesiumRuntime/Public/CesiumSceneCaptureComponent2D.h @@ -0,0 +1,30 @@ +// Copyright 2020-2025 CesiumGS, Inc. and Contributors + +#pragma once + +#include "Components/SceneCaptureComponent2D.h" +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "CesiumSceneCaptureComponent2D.generated.h" + +/** + * Used to capture a 'snapshot' of the scene from a single plane and feed it to + * a render target. + * + * This is identical to Unreal Engine's built-in + * `USceneCaptureCaptureComponent2D` except that it overrides `GetViewOwner` to + * returning `GetOwner`. This allows the capture component to be used as a view + * of a `Cesium3DTileset`. + */ +UCLASS( + hidecategories = (Collision, Object, Physics, SceneComponent), + ClassGroup = Rendering, + editinlinenew, + meta = (BlueprintSpawnableComponent), + MinimalAPI) +class UCesiumSceneCaptureComponent2D : public USceneCaptureComponent2D { + GENERATED_UCLASS_BODY() + +public: + const AActor* GetViewOwner() const override; +}; diff --git a/extern/cesium-native b/extern/cesium-native index b659f724a..3f7fed867 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit b659f724ac3f736e062b039c59d7a92b6b87ac78 +Subproject commit 3f7fed867bb424ffe36100be14b7c8fc98fff11e From c8c1a62d2fb847e70e6e50970fbc8fffd41d76e6 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Tue, 25 Feb 2025 18:16:55 +1100 Subject: [PATCH 02/16] Manage visibility only using view relevance. --- Source/CesiumRuntime/Private/Cesium3DTileset.cpp | 6 +++--- Source/CesiumRuntime/Private/CesiumGltfComponent.cpp | 2 +- Source/CesiumRuntime/Private/CesiumGltfComponent.h | 2 +- .../CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 260e72fe5..e35ddd143 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -799,7 +799,7 @@ void ACesium3DTileset::OnConstruction(const FTransform& Transform) { for (UCesiumGltfComponent* pGltf : gltfComponents) { if (pGltf && IsValid(pGltf) && pGltf->IsVisible()) { - pGltf->SetVisibility(false, true); + //pGltf->SetVisibility(false, true); pGltf->SetCollisionEnabled(ECollisionEnabled::NoCollision); } } @@ -1717,7 +1717,7 @@ void hideTiles( UCesiumGltfComponent* pGltf) { if (pGltf->IsVisible()) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityFalse) - pGltf->SetVisibility(false, true); + //pGltf->SetVisibility(false, true); } else { // TODO: why is this happening? UE_LOG( @@ -1954,7 +1954,7 @@ void ACesium3DTileset::showTilesToRender( if (!pGltf->IsVisible()) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityTrue) - pGltf->SetVisibility(true, true); + //pGltf->SetVisibility(true, true); } pGltf->SetViewGroupVisibility(pViewActor, true); diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp index 1d53f6cb2..7e8e32cc3 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -3372,7 +3372,7 @@ UCesiumGltfComponent::CreateOffGameThread( } } - Gltf->SetVisibility(false, true); + //Gltf->SetVisibility(false, true); Gltf->SetCollisionEnabled(ECollisionEnabled::NoCollision); return Gltf; } diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.h b/Source/CesiumRuntime/Private/CesiumGltfComponent.h index 0ebd14d8a..4ae448a62 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.h +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.h @@ -141,5 +141,5 @@ class UCesiumGltfComponent : public USceneComponent { UPROPERTY() UTexture2D* Transparent1x1 = nullptr; - TMap _viewGroupVisibility; + TMap _viewGroupVisibility{{nullptr, false}}; }; diff --git a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp index 92ed82dfa..17bcaf5fe 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp @@ -253,6 +253,7 @@ void UCesiumGltfPrimitiveComponent::updateVisibilityInRenderThread( FPrimitiveSceneProxy* pProxy, TMap&& visibility) { check(pProxy); + check(visibility.Contains(nullptr)); static_cast(pProxy)->updateVisibility( std::move(visibility)); } From 6162c9a5437c747a1172b89d103a8a7cea03c16c Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 27 Feb 2025 13:01:20 +1100 Subject: [PATCH 03/16] Control tile visibility only with view relevance. --- Source/CesiumRuntime/Private/Cesium3DTileset.cpp | 10 ++++++---- Source/CesiumRuntime/Public/Cesium3DTileset.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index e35ddd143..097cfa039 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -799,7 +799,7 @@ void ACesium3DTileset::OnConstruction(const FTransform& Transform) { for (UCesiumGltfComponent* pGltf : gltfComponents) { if (pGltf && IsValid(pGltf) && pGltf->IsVisible()) { - //pGltf->SetVisibility(false, true); + // pGltf->SetVisibility(false, true); pGltf->SetCollisionEnabled(ECollisionEnabled::NoCollision); } } @@ -1717,7 +1717,7 @@ void hideTiles( UCesiumGltfComponent* pGltf) { if (pGltf->IsVisible()) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityFalse) - //pGltf->SetVisibility(false, true); + // pGltf->SetVisibility(false, true); } else { // TODO: why is this happening? UE_LOG( @@ -1954,7 +1954,7 @@ void ACesium3DTileset::showTilesToRender( if (!pGltf->IsVisible()) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityTrue) - //pGltf->SetVisibility(true, true); + // pGltf->SetVisibility(true, true); } pGltf->SetViewGroupVisibility(pViewActor, true); @@ -2095,7 +2095,9 @@ void ACesium3DTileset::Tick(float DeltaTime) { ACesiumCameraManager* pCameraManager = ACesiumCameraManager::GetDefaultCameraManager(this); if (pCameraManager) { - this->_viewGroups.SetNum(pCameraManager->ViewGroups.Num()); + this->_viewGroups.resize( + pCameraManager->ViewGroups.Num(), + this->_pTileset->createViewGroup()); for (int32 i = 0; i < pCameraManager->ViewGroups.Num(); ++i) { const FCesiumViewGroup& group = pCameraManager->ViewGroups[i]; diff --git a/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Source/CesiumRuntime/Public/Cesium3DTileset.h index 1338aa93c..2a98385c4 100644 --- a/Source/CesiumRuntime/Public/Cesium3DTileset.h +++ b/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -1371,7 +1371,7 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { int32 _tilesetsBeingDestroyed; - TArray _viewGroups; + std::vector _viewGroups; friend class UnrealPrepareRendererResources; friend class UCesiumGltfPointsComponent; From a147c99919bfff52d1cd2b6728c1a22330fb2c1d Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Tue, 4 Mar 2025 16:42:48 +1100 Subject: [PATCH 04/16] Release TilesetViewGroups along with the Tileset. --- Source/CesiumRuntime/Private/Cesium3DTileset.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index db92ba435..6cb601c54 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -1254,6 +1254,7 @@ void ACesium3DTileset::DestroyTileset() { ++this->_tilesetsBeingDestroyed; this->_pTileset->getAsyncDestructionCompleteEvent().thenInMainThread( [this]() { --this->_tilesetsBeingDestroyed; }); + this->_viewGroups.clear(); this->_pTileset.Reset(); switch (this->TilesetSource) { From 86adabcadddd67bfb44e11515b85cd63fab6c9f2 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Tue, 4 Mar 2025 19:20:28 +1100 Subject: [PATCH 05/16] Hacky view monitoring. --- .../CesiumRuntime/Private/Cesium3DTileset.cpp | 91 ++++++++++++------- .../Private/CesiumGltfComponent.cpp | 8 ++ Source/CesiumRuntime/Public/Cesium3DTileset.h | 1 + .../Public/CesiumCameraManager.h | 3 + 4 files changed, 68 insertions(+), 35 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 6cb601c54..5e5d8a9d9 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -2049,41 +2049,41 @@ void ACesium3DTileset::Tick(float DeltaTime) { ellipsoid)); } - const Cesium3DTilesSelection::ViewUpdateResult* pResult; - if (this->_captureMovieMode) { - TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateViewOffline) - pResult = &this->_pTileset->updateViewOffline(frustums); - } else { - TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateView) - pResult = &this->_pTileset->updateView(frustums, DeltaTime); - } - updateLastViewUpdateResultState(*pResult); - - removeCollisionForTiles(pResult->tilesFadingOut); - - removeVisibleTilesFromList( - _tilesToHideNextFrame, - pResult->tilesToRenderThisFrame); - hideTiles(nullptr, _tilesToHideNextFrame); - - _tilesToHideNextFrame.clear(); - for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) { - Cesium3DTilesSelection::TileRenderContent* pRenderContent = - pTile->getContent().getRenderContent(); - if (!this->UseLodTransitions || - (pRenderContent && - pRenderContent->getLodTransitionFadePercentage() >= 1.0f)) { - _tilesToHideNextFrame.push_back(pTile); - } - } - - showTilesToRender(nullptr, pResult->tilesToRenderThisFrame); - - if (this->UseLodTransitions) { - TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades) - updateTileFades(pResult->tilesToRenderThisFrame, true); - updateTileFades(pResult->tilesFadingOut, false); - } + // const Cesium3DTilesSelection::ViewUpdateResult* pResult; + // if (this->_captureMovieMode) { + // TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateViewOffline) + // pResult = &this->_pTileset->updateViewOffline(frustums); + // } else { + // TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateView) + // pResult = &this->_pTileset->updateView(frustums, DeltaTime); + // } + // updateLastViewUpdateResultState(*pResult); + + // removeCollisionForTiles(pResult->tilesFadingOut); + + // removeVisibleTilesFromList( + // _tilesToHideNextFrame, + // pResult->tilesToRenderThisFrame); + // hideTiles(nullptr, _tilesToHideNextFrame); + + //_tilesToHideNextFrame.clear(); + // for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) { + // Cesium3DTilesSelection::TileRenderContent* pRenderContent = + // pTile->getContent().getRenderContent(); + // if (!this->UseLodTransitions || + // (pRenderContent && + // pRenderContent->getLodTransitionFadePercentage() >= 1.0f)) { + // _tilesToHideNextFrame.push_back(pTile); + // } + //} + + // showTilesToRender(nullptr, pResult->tilesToRenderThisFrame); + + // if (this->UseLodTransitions) { + // TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades) + // updateTileFades(pResult->tilesToRenderThisFrame, true); + // updateTileFades(pResult->tilesFadingOut, false); + // } this->UpdateLoadStatus(); @@ -2167,6 +2167,27 @@ void ACesium3DTileset::Tick(float DeltaTime) { std::vector( result.tilesFadingOut.begin(), result.tilesFadingOut.end())); + + if (group.Monitor) { + if (this->_pLastMonitorViewActor != group.ViewActor) { + // Reset all tiles to non-visible + std::vector allTiles; + this->_pTileset->forEachLoadedTile( + [&allTiles](Cesium3DTilesSelection::Tile& tile) { + allTiles.emplace_back(&tile); + }); + hideTiles(nullptr, allTiles); + + this->_pLastMonitorViewActor = group.ViewActor.Get(); + } + + showTilesToRender(nullptr, result.tilesToRenderThisFrame); + hideTiles( + nullptr, + std::vector( + result.tilesFadingOut.begin(), + result.tilesFadingOut.end())); + } } } } diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp index a80be80a0..de13bd219 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -3643,6 +3643,14 @@ void UCesiumGltfComponent::SetViewGroupVisibility( if (!pVisibility || *pVisibility != visibility) { this->_viewGroupVisibility.FindOrAdd(ViewActor) = visibility; + //bool anyAreVisible = false; + + //for (const auto& kvp : this->_viewGroupVisibility) { + // anyAreVisible |= kvp.Value; + //} + + //this->_viewGroupVisibility.FindOrAdd(nullptr) = anyAreVisible; + for (const TObjectPtr& pComponent : this->GetAttachChildren()) { UCesiumGltfPrimitiveComponent* pPrimitive = diff --git a/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Source/CesiumRuntime/Public/Cesium3DTileset.h index 2a98385c4..115694abe 100644 --- a/Source/CesiumRuntime/Public/Cesium3DTileset.h +++ b/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -1372,6 +1372,7 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { int32 _tilesetsBeingDestroyed; std::vector _viewGroups; + TObjectPtr _pLastMonitorViewActor = nullptr; friend class UnrealPrepareRendererResources; friend class UCesiumGltfPointsComponent; diff --git a/Source/CesiumRuntime/Public/CesiumCameraManager.h b/Source/CesiumRuntime/Public/CesiumCameraManager.h index 445351a33..0c2f2c6fb 100644 --- a/Source/CesiumRuntime/Public/CesiumCameraManager.h +++ b/Source/CesiumRuntime/Public/CesiumCameraManager.h @@ -12,6 +12,9 @@ USTRUCT(BlueprintType) struct CESIUMRUNTIME_API FCesiumViewGroup { GENERATED_USTRUCT_BODY() + UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) + bool Monitor = false; + UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) TSoftObjectPtr ViewActor; From 9279975c0b91d177a113037ee4f5b8e9b074834f Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Fri, 7 Mar 2025 13:37:01 +1100 Subject: [PATCH 06/16] Specify weight on view groups. --- Source/CesiumRuntime/Private/Cesium3DTileset.cpp | 6 +++++- Source/CesiumRuntime/Public/CesiumCameraManager.h | 3 +++ extern/cesium-native | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 5e5d8a9d9..f3d162b35 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -2155,8 +2155,10 @@ void ACesium3DTileset::Tick(float DeltaTime) { } } + this->_viewGroups[i].setWeight(group.LoadWeight); + const Cesium3DTilesSelection::ViewUpdateResult& result = - this->_pTileset->updateView( + this->_pTileset->updateViewGroup( this->_viewGroups[i], frustums, DeltaTime); @@ -2189,6 +2191,8 @@ void ACesium3DTileset::Tick(float DeltaTime) { result.tilesFadingOut.end())); } } + + this->_pTileset->processViewGroupLoads(); } } diff --git a/Source/CesiumRuntime/Public/CesiumCameraManager.h b/Source/CesiumRuntime/Public/CesiumCameraManager.h index 0c2f2c6fb..68709a0d0 100644 --- a/Source/CesiumRuntime/Public/CesiumCameraManager.h +++ b/Source/CesiumRuntime/Public/CesiumCameraManager.h @@ -15,6 +15,9 @@ struct CESIUMRUNTIME_API FCesiumViewGroup { UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) bool Monitor = false; + UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) + double LoadWeight = 1.0; + UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) TSoftObjectPtr ViewActor; diff --git a/extern/cesium-native b/extern/cesium-native index 0092b7b84..db5602cf6 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit 0092b7b84e12a997dfe2731f239aa8d98b813084 +Subproject commit db5602cf6a2f7dd7c23092393d1888ad7c9c4bc4 From a97522b6c320f193d4b9d8f1f8b7c45bf0501a36 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Fri, 7 Mar 2025 14:47:09 +1100 Subject: [PATCH 07/16] Update cesium-native. --- extern/cesium-native | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/cesium-native b/extern/cesium-native index db5602cf6..a2dc5fd36 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit db5602cf6a2f7dd7c23092393d1888ad7c9c4bc4 +Subproject commit a2dc5fd36eb30afb164ad77d527592d7c83b61b4 From 9931afdb0c44aea9dc25cc46b51706dce8027546 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Fri, 7 Mar 2025 22:55:32 +1100 Subject: [PATCH 08/16] Update cesium-native. --- Source/CesiumRuntime/Private/Cesium3DTileset.cpp | 2 +- extern/cesium-native | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index f3d162b35..367e4700b 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -2192,7 +2192,7 @@ void ACesium3DTileset::Tick(float DeltaTime) { } } - this->_pTileset->processViewGroupLoads(); + this->_pTileset->loadTiles(); } } diff --git a/extern/cesium-native b/extern/cesium-native index a2dc5fd36..c5b5841ce 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit a2dc5fd36eb30afb164ad77d527592d7c83b61b4 +Subproject commit c5b5841cec9d51811498c7f2126964e97ddbb33b From 7a12b517b540cc0904a6b9cad7f950c6fe342a07 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 10 Mar 2025 17:22:27 +1100 Subject: [PATCH 09/16] Update cesium-native. --- Source/CesiumRuntime/Private/Cesium3DTileset.cpp | 4 +--- extern/cesium-native | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 367e4700b..7ecf6ea87 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -2090,9 +2090,7 @@ void ACesium3DTileset::Tick(float DeltaTime) { ACesiumCameraManager* pCameraManager = ACesiumCameraManager::GetDefaultCameraManager(this); if (pCameraManager) { - this->_viewGroups.resize( - pCameraManager->ViewGroups.Num(), - this->_pTileset->createViewGroup()); + this->_viewGroups.resize(pCameraManager->ViewGroups.Num()); for (int32 i = 0; i < pCameraManager->ViewGroups.Num(); ++i) { const FCesiumViewGroup& group = pCameraManager->ViewGroups[i]; diff --git a/extern/cesium-native b/extern/cesium-native index c5b5841ce..a64daeaf0 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit c5b5841cec9d51811498c7f2126964e97ddbb33b +Subproject commit a64daeaf0341005336701a7889fc21b0dadbff2a From 4d8eb21babdedc408deae3c6c419e67ddc3f5642 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Tue, 8 Apr 2025 19:04:48 +1000 Subject: [PATCH 10/16] Update for credit system changes. --- Source/CesiumRuntime/Private/CesiumCreditSystem.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp b/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp index 9ee39cedf..3f9dcc043 100644 --- a/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp +++ b/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp @@ -333,13 +333,14 @@ void ACesiumCreditSystem::Tick(float DeltaTime) { return; } + const CesiumUtility::CreditsSnapshot& credits = _pCreditSystem->getSnapshot(); + const std::vector& creditsToShowThisFrame = - _pCreditSystem->getCreditsToShowThisFrame(); + credits.currentCredits; // if the credit list has changed, we want to reformat the credits - CreditsUpdated = - creditsToShowThisFrame.size() != _lastCreditsCount || - _pCreditSystem->getCreditsToNoLongerShowThisFrame().size() > 0; + CreditsUpdated = creditsToShowThisFrame.size() != _lastCreditsCount || + credits.removedCredits.size() > 0; if (CreditsUpdated) { FString OnScreenCredits; @@ -385,7 +386,6 @@ void ACesiumCreditSystem::Tick(float DeltaTime) { CreditsWidget->SetCredits(Credits, OnScreenCredits); } - _pCreditSystem->startNextFrame(); } namespace { From 957f6f1498236187a66c582559b47a99a661fe9c Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Tue, 8 Apr 2025 19:04:48 +1000 Subject: [PATCH 11/16] Update for credit system changes. --- Source/CesiumRuntime/Private/CesiumCreditSystem.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp b/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp index 9ee39cedf..3f9dcc043 100644 --- a/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp +++ b/Source/CesiumRuntime/Private/CesiumCreditSystem.cpp @@ -333,13 +333,14 @@ void ACesiumCreditSystem::Tick(float DeltaTime) { return; } + const CesiumUtility::CreditsSnapshot& credits = _pCreditSystem->getSnapshot(); + const std::vector& creditsToShowThisFrame = - _pCreditSystem->getCreditsToShowThisFrame(); + credits.currentCredits; // if the credit list has changed, we want to reformat the credits - CreditsUpdated = - creditsToShowThisFrame.size() != _lastCreditsCount || - _pCreditSystem->getCreditsToNoLongerShowThisFrame().size() > 0; + CreditsUpdated = creditsToShowThisFrame.size() != _lastCreditsCount || + credits.removedCredits.size() > 0; if (CreditsUpdated) { FString OnScreenCredits; @@ -385,7 +386,6 @@ void ACesiumCreditSystem::Tick(float DeltaTime) { CreditsWidget->SetCredits(Credits, OnScreenCredits); } - _pCreditSystem->startNextFrame(); } namespace { From 21e260bab0a43ae817f471700bdccd76543ba210 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Tue, 8 Apr 2025 19:35:50 +1000 Subject: [PATCH 12/16] Update cesium-native. --- extern/cesium-native | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/cesium-native b/extern/cesium-native index ae62bd8c6..d0a70e05d 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit ae62bd8c6a7fbce08a541eecd86a313bfb906e15 +Subproject commit d0a70e05da13ec2abcbd862e9298e0922ad3c10d From 13c8a461c7492e8906e7f84d1c7926a55d2f3324 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 10 Apr 2025 09:27:25 +1000 Subject: [PATCH 13/16] Use view groups for editor viewports. --- .../CesiumRuntime/Private/Cesium3DTileset.cpp | 234 ++++++++---------- .../Private/CesiumCameraManager.cpp | 29 ++- .../Private/CesiumGltfComponent.cpp | 27 +- .../Private/CesiumGltfComponent.h | 6 +- .../Private/CesiumGltfPrimitiveComponent.cpp | 30 +-- .../Private/CesiumGltfPrimitiveComponent.h | 2 +- Source/CesiumRuntime/Public/Cesium3DTileset.h | 2 +- .../Public/CesiumCameraManager.h | 36 ++- 8 files changed, 199 insertions(+), 167 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index e3459e53e..0584d2237 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -1707,12 +1707,12 @@ void removeVisibleTilesFromList( * @param tiles The tiles to hide */ void hideTiles( - const AActor* pViewActor, + uint32 viewStateKey, const std::vector& tiles) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::HideTiles) forEachRenderableTile( tiles, - [pViewActor]( + [viewStateKey]( Cesium3DTilesSelection::Tile* /*pTile*/, UCesiumGltfComponent* pGltf) { if (pGltf->IsVisible()) { @@ -1726,7 +1726,7 @@ void hideTiles( TEXT("Tile to no longer render does not have a visible Gltf")); } - pGltf->SetViewGroupVisibility(pViewActor, false); + pGltf->SetViewGroupVisibility(viewStateKey, false); }); } @@ -1921,12 +1921,12 @@ void ACesium3DTileset::updateLastViewUpdateResultState( } void ACesium3DTileset::showTilesToRender( - const AActor* pViewActor, + uint32 viewStateKey, const std::vector& tiles) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ShowTilesToRender) forEachRenderableTile( tiles, - [pViewActor, + [viewStateKey, &RootComponent = this->RootComponent, &BodyInstance = this->BodyInstance]( Cesium3DTilesSelection::Tile* pTile, @@ -1957,7 +1957,7 @@ void ACesium3DTileset::showTilesToRender( // pGltf->SetVisibility(true, true); } - pGltf->SetViewGroupVisibility(pViewActor, true); + pGltf->SetViewGroupVisibility(viewStateKey, true); { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetCollisionEnabled) @@ -2047,48 +2047,51 @@ void ACesium3DTileset::Tick(float DeltaTime) { UCesiumEllipsoid* ellipsoid = this->ResolveGeoreference()->GetEllipsoid(); std::vector frustums; - for (const FCesiumCamera& camera : cameras) { - frustums.push_back(CreateViewStateFromViewParameters( - camera, - unrealWorldToCesiumTileset, - ellipsoid)); - } - - // const Cesium3DTilesSelection::ViewUpdateResult* pResult; - // if (this->_captureMovieMode) { - // TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateViewOffline) - // pResult = &this->_pTileset->updateViewOffline(frustums); - // } else { - // TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateView) - // pResult = &this->_pTileset->updateView(frustums, DeltaTime); - // } - // updateLastViewUpdateResultState(*pResult); - - // removeCollisionForTiles(pResult->tilesFadingOut); - - // removeVisibleTilesFromList( - // _tilesToHideNextFrame, - // pResult->tilesToRenderThisFrame); - // hideTiles(nullptr, _tilesToHideNextFrame); - - //_tilesToHideNextFrame.clear(); - // for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) { - // Cesium3DTilesSelection::TileRenderContent* pRenderContent = - // pTile->getContent().getRenderContent(); - // if (!this->UseLodTransitions || - // (pRenderContent && - // pRenderContent->getLodTransitionFadePercentage() >= 1.0f)) { - // _tilesToHideNextFrame.push_back(pTile); - // } + //for (const FCesiumCamera& camera : cameras) { + // frustums.push_back(CreateViewStateFromViewParameters( + // camera, + // unrealWorldToCesiumTileset, + // ellipsoid)); //} - // showTilesToRender(nullptr, pResult->tilesToRenderThisFrame); + const Cesium3DTilesSelection::ViewUpdateResult* pResult; + if (this->_captureMovieMode) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateViewOffline) + pResult = &this->_pTileset->updateViewOffline(frustums); + } else { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateView) + pResult = &this->_pTileset->updateViewGroup( + this->_pTileset->getDefaultViewGroup(), + frustums, + DeltaTime); + } + updateLastViewUpdateResultState(*pResult); + + removeCollisionForTiles(pResult->tilesFadingOut); + + removeVisibleTilesFromList( + _tilesToHideNextFrame, + pResult->tilesToRenderThisFrame); + hideTiles(0, _tilesToHideNextFrame); + + _tilesToHideNextFrame.clear(); + for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) { + Cesium3DTilesSelection::TileRenderContent* pRenderContent = + pTile->getContent().getRenderContent(); + if (!this->UseLodTransitions || + (pRenderContent && + pRenderContent->getLodTransitionFadePercentage() >= 1.0f)) { + _tilesToHideNextFrame.push_back(pTile); + } + } - // if (this->UseLodTransitions) { - // TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades) - // updateTileFades(pResult->tilesToRenderThisFrame, true); - // updateTileFades(pResult->tilesFadingOut, false); - // } + showTilesToRender(0, pResult->tilesToRenderThisFrame); + + if (this->UseLodTransitions) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades) + updateTileFades(pResult->tilesToRenderThisFrame, true); + updateTileFades(pResult->tilesFadingOut, false); + } this->UpdateLoadStatus(); @@ -2099,100 +2102,79 @@ void ACesium3DTileset::Tick(float DeltaTime) { for (int32 i = 0; i < pCameraManager->ViewGroups.Num(); ++i) { const FCesiumViewGroup& group = pCameraManager->ViewGroups[i]; - std::vector frustums; - for (const TSoftObjectPtr& actor : - group.CamerasAndSceneCaptures) { - AActor* pActor = actor.Get(); - if (!pActor) +#if WITH_EDITOR + if (group.EditorViewportIndex >= 0) { + TArray viewportClients = + GEditor->GetAllViewportClients(); + FEditorViewportClient* pEditorViewportClient = + viewportClients[group.EditorViewportIndex]; + + if (!pEditorViewportClient->IsVisible() || + !pEditorViewportClient->IsRealtime() || + !pEditorViewportClient->IsPerspective()) { continue; + } - USceneCaptureComponent2D* pSceneCaptureComponent = - pActor->GetComponentByClass(); - if (pSceneCaptureComponent) { - UTextureRenderTarget2D* pRenderTarget = - pSceneCaptureComponent->TextureTarget; - if (pRenderTarget && pSceneCaptureComponent->ProjectionType == - ECameraProjectionMode::Type::Perspective) { - - FVector2D renderTargetSize( - pRenderTarget->SizeX, - pRenderTarget->SizeY); - if (renderTargetSize.X >= 1.0 && renderTargetSize.Y >= 1.0) { - FVector captureLocation = - pSceneCaptureComponent->GetComponentLocation(); - FRotator captureRotation = - pSceneCaptureComponent->GetComponentRotation(); - double captureFov = pSceneCaptureComponent->FOVAngle; - - frustums.emplace_back(CreateViewStateFromViewParameters( - FCesiumCamera{ - renderTargetSize, - captureLocation, - captureRotation, - captureFov}, - unrealWorldToCesiumTileset, - ellipsoid)); - } - } + FRotator rotation; + if (pEditorViewportClient->bUsingOrbitCamera) { + rotation = (pEditorViewportClient->GetLookAtLocation() - + pEditorViewportClient->GetViewLocation()) + .Rotation(); + } else { + rotation = pEditorViewportClient->GetViewRotation(); } - UCameraComponent* pCameraComponent = - pActor->GetComponentByClass(); - if (pCameraComponent) { - APlayerController* pPlayerController = - GetWorld()->GetFirstPlayerController(); - if (pPlayerController) { - int32 sizeX, sizeY; - pPlayerController->GetViewportSize(sizeX, sizeY); - FVector2D renderTargetSize(sizeX, sizeY); - - frustums.emplace_back(CreateViewStateFromViewParameters( - FCesiumCamera{ - renderTargetSize, - pCameraComponent->GetComponentLocation(), - pCameraComponent->GetComponentRotation(), - pCameraComponent->FieldOfView}, - unrealWorldToCesiumTileset, - ellipsoid)); - } + const FVector& location = pEditorViewportClient->GetViewLocation(); + double fov = pEditorViewportClient->ViewFOV; + FIntPoint offset; + FIntPoint size; + pEditorViewportClient->GetViewportDimensions(offset, size); + + if (size.X < 1 || size.Y < 1) { + continue; } - } - this->_viewGroups[i].setWeight(group.LoadWeight); - - const Cesium3DTilesSelection::ViewUpdateResult& result = - this->_pTileset->updateViewGroup( - this->_viewGroups[i], - frustums, - DeltaTime); - - showTilesToRender(group.ViewActor.Get(), result.tilesToRenderThisFrame); - hideTiles( - group.ViewActor.Get(), - std::vector( - result.tilesFadingOut.begin(), - result.tilesFadingOut.end())); - - if (group.Monitor) { - if (this->_pLastMonitorViewActor != group.ViewActor) { - // Reset all tiles to non-visible - std::vector allTiles; - this->_pTileset->forEachLoadedTile( - [&allTiles](Cesium3DTilesSelection::Tile& tile) { - allTiles.emplace_back(&tile); - }); - hideTiles(nullptr, allTiles); - - this->_pLastMonitorViewActor = group.ViewActor.Get(); + if (this->_scaleUsingDPI) { + float dpiScalingFactor = pEditorViewportClient->GetDPIScale(); + size.X = static_cast(size.X) / dpiScalingFactor; + size.Y = static_cast(size.Y) / dpiScalingFactor; } - showTilesToRender(nullptr, result.tilesToRenderThisFrame); + std::vector frustums; + + if (pEditorViewportClient->IsAspectRatioConstrained()) { + frustums.emplace_back(CreateViewStateFromViewParameters( + FCesiumCamera( + FVector2D(size), + location, + rotation, + fov, + pEditorViewportClient->AspectRatio), + unrealWorldToCesiumTileset, + ellipsoid)); + } else { + frustums.emplace_back(CreateViewStateFromViewParameters( + FCesiumCamera(FVector2D(size), location, rotation, fov), + unrealWorldToCesiumTileset, + ellipsoid)); + } + + this->_viewGroups[i].setWeight(group.LoadWeight); + + const Cesium3DTilesSelection::ViewUpdateResult& result = + this->_pTileset->updateViewGroup( + this->_viewGroups[i], + frustums, + DeltaTime); + + showTilesToRender(group.ViewStateKey, result.tilesToRenderThisFrame); hideTiles( - nullptr, + group.ViewStateKey, std::vector( result.tilesFadingOut.begin(), result.tilesFadingOut.end())); } +#endif } this->_pTileset->loadTiles(); diff --git a/Source/CesiumRuntime/Private/CesiumCameraManager.cpp b/Source/CesiumRuntime/Private/CesiumCameraManager.cpp index 707885a5a..505907093 100644 --- a/Source/CesiumRuntime/Private/CesiumCameraManager.cpp +++ b/Source/CesiumRuntime/Private/CesiumCameraManager.cpp @@ -81,11 +81,38 @@ ACesiumCameraManager::ACesiumCameraManager() : AActor() { #if WITH_EDITOR this->SetIsSpatiallyLoaded(false); #endif + PrimaryActorTick.bCanEverTick = true; } bool ACesiumCameraManager::ShouldTickIfViewportsOnly() const { return true; } -void ACesiumCameraManager::Tick(float DeltaTime) { Super::Tick(DeltaTime); } +void ACesiumCameraManager::Tick(float DeltaTime) { + Super::Tick(DeltaTime); + + const TArray& viewportClients = + GEditor->GetAllViewportClients(); + + this->ViewGroups.SetNum(viewportClients.Num()); + + for (int32 i = 0; i < viewportClients.Num(); ++i) { + FEditorViewportClient* pClient = viewportClients[i]; + FCesiumViewGroup& group = this->ViewGroups[i]; + + group.ViewDescription = FString("Editor Viewport #"); + group.ViewDescription.AppendInt(i); + group.EditorViewportIndex = i; + group.ViewActor = nullptr; + + if (pClient->ViewState.GetReference() != nullptr) { + group.ViewStateKey = pClient->ViewState.GetReference()->GetViewKey(); + } else { + group.ViewStateKey = -1; + } + + if (group.LoadWeight <= 0.0) + group.LoadWeight = 1.0; + } +} int32 ACesiumCameraManager::AddCamera(UPARAM(ref) const FCesiumCamera& camera) { int32 cameraId = this->_currentCameraId++; diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp index 6fb1d6f60..83329f786 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -2314,7 +2314,7 @@ loadModelAnyThreadPart( return CesiumGltfTextures::createInWorkerThread(asyncSystem, *options.pModel) .thenInWorkerThread( [transform, ellipsoid, options = std::move(options)]() mutable - -> UCesiumGltfComponent::CreateOffGameThreadResult { + -> UCesiumGltfComponent::CreateOffGameThreadResult { auto pHalf = MakeUnique(); loadModelMetadata(pHalf->loadModelResult, options); @@ -3386,7 +3386,7 @@ UCesiumGltfComponent::CreateOffGameThread( } } - //Gltf->SetVisibility(false, true); + // Gltf->SetVisibility(false, true); Gltf->SetCollisionEnabled(ECollisionEnabled::NoCollision); return Gltf; } @@ -3644,19 +3644,19 @@ void UCesiumGltfComponent::UpdateFade(float fadePercentage, bool fadingIn) { } void UCesiumGltfComponent::SetViewGroupVisibility( - const AActor* ViewActor, + uint32 viewStateKey, bool visibility) { - bool* pVisibility = this->_viewGroupVisibility.Find(ViewActor); + bool* pVisibility = this->_viewGroupVisibility.Find(viewStateKey); if (!pVisibility || *pVisibility != visibility) { - this->_viewGroupVisibility.FindOrAdd(ViewActor) = visibility; + this->_viewGroupVisibility.FindOrAdd(viewStateKey) = visibility; - //bool anyAreVisible = false; + // bool anyAreVisible = false; - //for (const auto& kvp : this->_viewGroupVisibility) { - // anyAreVisible |= kvp.Value; - //} + // for (const auto& kvp : this->_viewGroupVisibility) { + // anyAreVisible |= kvp.Value; + // } - //this->_viewGroupVisibility.FindOrAdd(nullptr) = anyAreVisible; + // this->_viewGroupVisibility.FindOrAdd(nullptr) = anyAreVisible; for (const TObjectPtr& pComponent : this->GetAttachChildren()) { @@ -3670,7 +3670,8 @@ void UCesiumGltfComponent::SetViewGroupVisibility( ENQUEUE_RENDER_COMMAND(Cesium_UpdateViewGroupVisibility) ([viewGroupVisibility = this->_viewGroupVisibility, - pProxy = pPrimitive->SceneProxy](FRHICommandListImmediate& RHICmdList) mutable { + pProxy = pPrimitive->SceneProxy]( + FRHICommandListImmediate& RHICmdList) mutable { UCesiumGltfPrimitiveComponent::updateVisibilityInRenderThread( pProxy, std::move(viewGroupVisibility)); @@ -3679,8 +3680,8 @@ void UCesiumGltfComponent::SetViewGroupVisibility( } } -bool UCesiumGltfComponent::GetViewGroupVisibility(const AActor* ViewActor) { - bool* pResult = this->_viewGroupVisibility.Find(ViewActor); +bool UCesiumGltfComponent::GetViewGroupVisibility(uint32 viewStateKey) { + bool* pResult = this->_viewGroupVisibility.Find(viewStateKey); return pResult && *pResult; } diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.h b/Source/CesiumRuntime/Private/CesiumGltfComponent.h index 4ae448a62..feb92f9d4 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.h +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.h @@ -134,12 +134,12 @@ class UCesiumGltfComponent : public USceneComponent { void UpdateFade(float fadePercentage, bool fadingIn); - void SetViewGroupVisibility(const AActor* ViewActor, bool visibility); - bool GetViewGroupVisibility(const AActor* ViewActor); + void SetViewGroupVisibility(uint32 viewStateKey, bool visibility); + bool GetViewGroupVisibility(uint32 viewStateKey); private: UPROPERTY() UTexture2D* Transparent1x1 = nullptr; - TMap _viewGroupVisibility{{nullptr, false}}; + TMap _viewGroupVisibility{{0, false}}; }; diff --git a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp index 17bcaf5fe..d84afdbe4 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.cpp @@ -100,7 +100,7 @@ class FCesiumGltfPrimitiveSceneProxy : public FStaticMeshSceneProxy { FCesiumGltfPrimitiveSceneProxy( UStaticMeshComponent* Component, bool bForceLODsShareStaticLighting, - TMap&& viewGroupVisibility) + TMap&& viewGroupVisibility) : FStaticMeshSceneProxy(Component, bForceLODsShareStaticLighting), _viewsVisibility(std::move(viewGroupVisibility)) {} @@ -109,7 +109,8 @@ class FCesiumGltfPrimitiveSceneProxy : public FStaticMeshSceneProxy { FPrimitiveViewRelevance relevance = FStaticMeshSceneProxy::GetViewRelevance(View); - const bool* pVisibility = this->_viewsVisibility.Find(View->ViewActor); + const bool* pVisibility = + this->_viewsVisibility.Find(View->State->GetViewKey()); if (pVisibility) { // We have visibility information for the view group corresponding to this // ViewActor. It may be the default view group if ViewActor==nullptr. @@ -121,7 +122,7 @@ class FCesiumGltfPrimitiveSceneProxy : public FStaticMeshSceneProxy { // We don't have visibility information for a view group corresponding to // this ViewActor, so use the visibility information for the default view // group. - pVisibility = this->_viewsVisibility.Find(nullptr); + pVisibility = this->_viewsVisibility.Find(0); check(pVisibility); if (pVisibility && !*pVisibility) { relevance.bDrawRelevance = false; @@ -132,14 +133,14 @@ class FCesiumGltfPrimitiveSceneProxy : public FStaticMeshSceneProxy { return relevance; } - void updateVisibility(TMap&& newVisibility) { + void updateVisibility(TMap&& newVisibility) { this->_viewsVisibility = std::move(newVisibility); } private: - // An entry per ViewActor assigned to a view group, plus an entry for nullptr + // An entry per view assigned to a view group, plus an entry for nullptr // which is the visibility of this primitive in the default view group. - TMap _viewsVisibility; + TMap _viewsVisibility; }; } // namespace @@ -155,18 +156,17 @@ FPrimitiveSceneProxy* UCesiumGltfPrimitiveComponent::CreateStaticMeshSceneProxy( UCesiumGltfComponent* pGltf = Cast(this->GetAttachParent()); - TMap viewGroupVisibility{ - {nullptr, pGltf ? pGltf->GetViewGroupVisibility(nullptr) : false}}; + TMap viewGroupVisibility{ + {0, pGltf ? pGltf->GetViewGroupVisibility(0) : false}}; if (pCameraManager) { for (const FCesiumViewGroup& group : pCameraManager->ViewGroups) { - if (group.ViewActor != nullptr) + if (group.ViewStateKey > 0) viewGroupVisibility.Add( - group.ViewActor.Get(), - pGltf ? pGltf->GetViewGroupVisibility(group.ViewActor.Get()) - : false); + group.ViewStateKey, + pGltf ? pGltf->GetViewGroupVisibility(group.ViewStateKey) : false); } } else { - viewGroupVisibility = {{nullptr, false}}; + viewGroupVisibility = {{0, false}}; } auto* Proxy = ::new FCesiumGltfPrimitiveSceneProxy( @@ -251,9 +251,9 @@ UCesiumGltfPrimitiveComponent::getPrimitiveData() const { void UCesiumGltfPrimitiveComponent::updateVisibilityInRenderThread( FPrimitiveSceneProxy* pProxy, - TMap&& visibility) { + TMap&& visibility) { check(pProxy); - check(visibility.Contains(nullptr)); + check(visibility.Contains(0)); static_cast(pProxy)->updateVisibility( std::move(visibility)); } diff --git a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h index c46c134d4..ce551c824 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h +++ b/Source/CesiumRuntime/Private/CesiumGltfPrimitiveComponent.h @@ -50,7 +50,7 @@ class UCesiumGltfPrimitiveComponent : public UStaticMeshComponent, static void updateVisibilityInRenderThread( FPrimitiveSceneProxy* pProxy, - TMap&& visibility); + TMap&& visibility); private: CesiumPrimitiveData _cesiumData; diff --git a/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Source/CesiumRuntime/Public/Cesium3DTileset.h index 115694abe..43913fead 100644 --- a/Source/CesiumRuntime/Public/Cesium3DTileset.h +++ b/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -1290,7 +1290,7 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { * @param tiles The tiles */ void showTilesToRender( - const AActor* pViewActor, + uint32 viewStateKey, const std::vector& tiles); /** diff --git a/Source/CesiumRuntime/Public/CesiumCameraManager.h b/Source/CesiumRuntime/Public/CesiumCameraManager.h index 68709a0d0..83ed690b7 100644 --- a/Source/CesiumRuntime/Public/CesiumCameraManager.h +++ b/Source/CesiumRuntime/Public/CesiumCameraManager.h @@ -12,17 +12,39 @@ USTRUCT(BlueprintType) struct CESIUMRUNTIME_API FCesiumViewGroup { GENERATED_USTRUCT_BODY() - UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) - bool Monitor = false; + /** + * A human-readable description of this view group. + */ + UPROPERTY(Category = "Cesium", VisibleAnywhere, BlueprintReadOnly) + FString ViewDescription = "Unknown"; - UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) - double LoadWeight = 1.0; + /** + * The index of the viewing FEditorViewportClient in + * GEditor->GetAllViewportClients(), or -1 if this view is not an editor + * viewport client. + */ + UPROPERTY(Category = "Cesium", VisibleAnywhere, BlueprintReadOnly) + int32 EditorViewportIndex = -1; - UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) - TSoftObjectPtr ViewActor; + /** + * The viewing Actor, which is expected to have either a + * USceneCaptureComponent2D or a UCameraComponent attached to it. + */ + UPROPERTY(Category = "Cesium", VisibleAnywhere, BlueprintReadOnly) + TSoftObjectPtr ViewActor = nullptr; + + /** + * The unique ID of the FSceneViewStateInterface, as returned by its + * GetViewKey method. + */ + UPROPERTY(Category = "Cesium", VisibleAnywhere, BlueprintReadOnly) + int64 ViewStateKey = -1; + /** + * The weight of this view group, used to prioritize tile loading. + */ UPROPERTY(Category = "Cesium", EditAnywhere, BlueprintReadWrite) - TArray> CamerasAndSceneCaptures; + double LoadWeight = 1.0; }; /** From 472cf7c687be9876bfebd6703126928bbc68fd64 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Mon, 14 Apr 2025 09:19:10 +1000 Subject: [PATCH 14/16] Add support for orthographic Editor viewports. --- .../CesiumRuntime/Private/Cesium3DTileset.cpp | 112 +++++++++++++----- extern/cesium-native | 2 +- 2 files changed, 85 insertions(+), 29 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 0584d2237..29a65d6d1 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -2047,12 +2047,12 @@ void ACesium3DTileset::Tick(float DeltaTime) { UCesiumEllipsoid* ellipsoid = this->ResolveGeoreference()->GetEllipsoid(); std::vector frustums; - //for (const FCesiumCamera& camera : cameras) { - // frustums.push_back(CreateViewStateFromViewParameters( - // camera, - // unrealWorldToCesiumTileset, - // ellipsoid)); - //} + // for (const FCesiumCamera& camera : cameras) { + // frustums.push_back(CreateViewStateFromViewParameters( + // camera, + // unrealWorldToCesiumTileset, + // ellipsoid)); + // } const Cesium3DTilesSelection::ViewUpdateResult* pResult; if (this->_captureMovieMode) { @@ -2110,18 +2110,42 @@ void ACesium3DTileset::Tick(float DeltaTime) { viewportClients[group.EditorViewportIndex]; if (!pEditorViewportClient->IsVisible() || - !pEditorViewportClient->IsRealtime() || - !pEditorViewportClient->IsPerspective()) { + !pEditorViewportClient->IsRealtime()) { continue; } FRotator rotation; - if (pEditorViewportClient->bUsingOrbitCamera) { - rotation = (pEditorViewportClient->GetLookAtLocation() - - pEditorViewportClient->GetViewLocation()) - .Rotation(); - } else { - rotation = pEditorViewportClient->GetViewRotation(); + + switch (pEditorViewportClient->GetViewportType()) { + case LVT_OrthoXY: + rotation = FRotator(-90.0f, -90.0f, 0.0f); + break; + case LVT_OrthoNegativeXY: + rotation = FRotator(90.0f, 90.0f, 0.0f); + break; + case LVT_OrthoXZ: + rotation = FRotator(0.0f, -90.0f, 0.0f); + break; + case LVT_OrthoNegativeXZ: + rotation = FRotator(0.0f, 90.0f, 0.0f); + break; + case LVT_OrthoYZ: + rotation = FRotator(0.0f, 0.0f, 0.0f); + break; + case LVT_OrthoNegativeYZ: + rotation = FRotator(0.0f, 180.0f, 0.0f); + break; + case LVT_OrthoFreelook: + case LVT_Perspective: + case LVT_MAX: + case LVT_None: + if (pEditorViewportClient->bUsingOrbitCamera) { + rotation = (pEditorViewportClient->GetLookAtLocation() - + pEditorViewportClient->GetViewLocation()) + .Rotation(); + } else { + rotation = pEditorViewportClient->GetViewRotation(); + } } const FVector& location = pEditorViewportClient->GetViewLocation(); @@ -2142,21 +2166,53 @@ void ACesium3DTileset::Tick(float DeltaTime) { std::vector frustums; - if (pEditorViewportClient->IsAspectRatioConstrained()) { - frustums.emplace_back(CreateViewStateFromViewParameters( - FCesiumCamera( - FVector2D(size), - location, - rotation, - fov, - pEditorViewportClient->AspectRatio), - unrealWorldToCesiumTileset, - ellipsoid)); + if (pEditorViewportClient->IsPerspective()) { + if (pEditorViewportClient->IsAspectRatioConstrained()) { + frustums.emplace_back(CreateViewStateFromViewParameters( + FCesiumCamera( + FVector2D(size), + location, + rotation, + fov, + pEditorViewportClient->AspectRatio), + unrealWorldToCesiumTileset, + ellipsoid)); + } else { + frustums.emplace_back(CreateViewStateFromViewParameters( + FCesiumCamera(FVector2D(size), location, rotation, fov), + unrealWorldToCesiumTileset, + ellipsoid)); + } } else { - frustums.emplace_back(CreateViewStateFromViewParameters( - FCesiumCamera(FVector2D(size), location, rotation, fov), - unrealWorldToCesiumTileset, - ellipsoid)); + Cesium3DTilesSelection::ViewState fakePerspective = + CreateViewStateFromViewParameters( + FCesiumCamera(FVector2D(size), location, rotation, fov), + unrealWorldToCesiumTileset, + ellipsoid); + + double orthographicUnitsPerPixel = + pEditorViewportClient->GetOrthoUnitsPerPixel( + pEditorViewportClient->Viewport); + double orthographicWidth = orthographicUnitsPerPixel * (double)size.X; + + double right = orthographicWidth / 100.0; // centimeters to meters + double left = -right; + double top = pEditorViewportClient->IsAspectRatioConstrained() + ? right / pEditorViewportClient->AspectRatio + : right / (double(size.X) / double(size.Y)); + double bottom = -top; + + Cesium3DTilesSelection::ViewState orthographic( + fakePerspective.getPosition(), + fakePerspective.getDirection(), + fakePerspective.getUp(), + fakePerspective.getViewportSize(), + left, + right, + bottom, + top, + ellipsoid->GetNativeEllipsoid()); + frustums.emplace_back(orthographic); } this->_viewGroups[i].setWeight(group.LoadWeight); diff --git a/extern/cesium-native b/extern/cesium-native index d0a70e05d..2da2d3ecb 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit d0a70e05da13ec2abcbd862e9298e0922ad3c10d +Subproject commit 2da2d3ecbdc0a21c38546ca55758881785153fa8 From 0a308a716520b517c9ef8ac47cbbe7d865f4b6f6 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 17 Apr 2025 18:23:14 +1000 Subject: [PATCH 15/16] Merge in multiple-views-one-reference-count branch. --- .../CesiumRuntime/Private/Cesium3DTileset.cpp | 51 ++++++++++++------- Source/CesiumRuntime/Public/Cesium3DTileset.h | 7 ++- extern/cesium-native | 2 +- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 29a65d6d1..49335cb72 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -1655,7 +1655,8 @@ bool ACesium3DTileset::ShouldTickIfViewportsOnly() const { namespace { template void forEachRenderableTile(const auto& tiles, Func&& f) { - for (Cesium3DTilesSelection::Tile* pTile : tiles) { + for (const CesiumUtility::IntrusivePointer& + pTile : tiles) { if (!pTile || pTile->getState() != Cesium3DTilesSelection::TileLoadState::Done) { continue; @@ -1683,13 +1684,17 @@ void forEachRenderableTile(const auto& tiles, Func&& f) { } void removeVisibleTilesFromList( - std::vector& list, - const std::vector& visibleTiles) { + std::vector>& + list, + const std::vector< + CesiumUtility::IntrusivePointer>& + visibleTiles) { if (list.empty()) { return; } - for (Cesium3DTilesSelection::Tile* pTile : visibleTiles) { + for (const CesiumUtility::IntrusivePointer& + pTile : visibleTiles) { auto it = std::find(list.begin(), list.end(), pTile); if (it != list.end()) { list.erase(it); @@ -1708,12 +1713,14 @@ void removeVisibleTilesFromList( */ void hideTiles( uint32 viewStateKey, - const std::vector& tiles) { + const std::vector< + CesiumUtility::IntrusivePointer>& tiles) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::HideTiles) forEachRenderableTile( tiles, [viewStateKey]( - Cesium3DTilesSelection::Tile* /*pTile*/, + const CesiumUtility::IntrusivePointer< + Cesium3DTilesSelection::Tile>& /*pTile*/, UCesiumGltfComponent* pGltf) { if (pGltf->IsVisible()) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityFalse) @@ -1735,11 +1742,14 @@ void hideTiles( * list. This includes tiles that are fading out. */ void removeCollisionForTiles( - const std::unordered_set& tiles) { + const std::unordered_set< + CesiumUtility::IntrusivePointer>& tiles) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::RemoveCollisionForTiles) forEachRenderableTile( tiles, - [](Cesium3DTilesSelection::Tile* /*pTile*/, UCesiumGltfComponent* pGltf) { + [](const CesiumUtility::IntrusivePointer< + Cesium3DTilesSelection::Tile>& /*pTile*/, + UCesiumGltfComponent* pGltf) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetCollisionDisabled) pGltf->SetCollisionEnabled(ECollisionEnabled::NoCollision); }); @@ -1821,10 +1831,11 @@ void ACesium3DTileset::updateLastViewUpdateResultState( ResolveGeoreference(); check(Georeference); - for (Cesium3DTilesSelection::Tile* tile : result.tilesToRenderThisFrame) { + for (const CesiumUtility::IntrusivePointer& + pTile : result.tilesToRenderThisFrame) { CesiumGeometry::OrientedBoundingBox obb = Cesium3DTilesSelection::getOrientedBoundingBoxFromBoundingVolume( - tile->getBoundingVolume(), + pTile->getBoundingVolume(), Georeference->GetEllipsoid()->GetNativeEllipsoid()); FVector unrealCenter = @@ -1835,9 +1846,9 @@ void ACesium3DTileset::updateLastViewUpdateResultState( TEXT("ID %s (%p)"), UTF8_TO_TCHAR( Cesium3DTilesSelection::TileIdUtilities::createTileIdString( - tile->getTileID()) + pTile->getTileID()) .c_str()), - tile); + pTile.get()); DrawDebugString(World, unrealCenter, text, nullptr, FColor::Red, 0, true); } @@ -1922,14 +1933,16 @@ void ACesium3DTileset::updateLastViewUpdateResultState( void ACesium3DTileset::showTilesToRender( uint32 viewStateKey, - const std::vector& tiles) { + const std::vector< + CesiumUtility::IntrusivePointer>& tiles) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ShowTilesToRender) forEachRenderableTile( tiles, [viewStateKey, &RootComponent = this->RootComponent, &BodyInstance = this->BodyInstance]( - Cesium3DTilesSelection::Tile* pTile, + const CesiumUtility::IntrusivePointer& + pTile, UCesiumGltfComponent* pGltf) { applyActorCollisionSettings(BodyInstance, pGltf); @@ -1970,7 +1983,8 @@ static void updateTileFades(const auto& tiles, bool fadingIn) { forEachRenderableTile( tiles, [fadingIn]( - Cesium3DTilesSelection::Tile* pTile, + const CesiumUtility::IntrusivePointer& + pTile, UCesiumGltfComponent* pGltf) { float percentage = pTile->getContent() .getRenderContent() @@ -2070,12 +2084,13 @@ void ACesium3DTileset::Tick(float DeltaTime) { removeCollisionForTiles(pResult->tilesFadingOut); removeVisibleTilesFromList( - _tilesToHideNextFrame, + this->_tilesToHideNextFrame, pResult->tilesToRenderThisFrame); - hideTiles(0, _tilesToHideNextFrame); + hideTiles(0, this->_tilesToHideNextFrame); _tilesToHideNextFrame.clear(); - for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) { + for (const CesiumUtility::IntrusivePointer& + pTile : pResult->tilesFadingOut) { Cesium3DTilesSelection::TileRenderContent* pRenderContent = pTile->getContent().getRenderContent(); if (!this->UseLodTransitions || diff --git a/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Source/CesiumRuntime/Public/Cesium3DTileset.h index 43913fead..4f08f3f56 100644 --- a/Source/CesiumRuntime/Public/Cesium3DTileset.h +++ b/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -1291,7 +1291,9 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { */ void showTilesToRender( uint32 viewStateKey, - const std::vector& tiles); + const std::vector< + CesiumUtility::IntrusivePointer>& + tiles); /** * Will be called after the tileset is loaded or spawned, to register @@ -1367,7 +1369,8 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { // If we find a way to clear the wrong occlusion information in the // Unreal Engine, then this field may be removed, and the // tilesToHideThisFrame may be hidden immediately. - std::vector _tilesToHideNextFrame; + std::vector> + _tilesToHideNextFrame; int32 _tilesetsBeingDestroyed; diff --git a/extern/cesium-native b/extern/cesium-native index 2da2d3ecb..4de9c081f 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit 2da2d3ecbdc0a21c38546ca55758881785153fa8 +Subproject commit 4de9c081fb84c043e6453100b74b11cac2b6984a From a5b627f8847c748be4abceddd0522e30c397bb0a Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 17 Apr 2025 18:36:32 +1000 Subject: [PATCH 16/16] Update cesium-native. --- extern/cesium-native | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/cesium-native b/extern/cesium-native index 4de9c081f..73b7143ed 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit 4de9c081fb84c043e6453100b74b11cac2b6984a +Subproject commit 73b7143eda219ce9b91fdb06229be1e3fb960a4c