Skip to content

Proof of concept for multiple views #1652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4cc828e
Hacky support for view groups.
kring Feb 19, 2025
851decc
Merge remote-tracking branch 'origin/main' into multiple-views
kring Feb 25, 2025
e2e974b
Merge remote-tracking branch 'origin/cylinder-region' into multiple-v…
kring Feb 25, 2025
c8c1a62
Manage visibility only using view relevance.
kring Feb 25, 2025
6162c9a
Control tile visibility only with view relevance.
kring Feb 27, 2025
7aa4a3f
Merge remote-tracking branch 'origin/main' into multiple-views
kring Feb 27, 2025
a2f4400
Merge remote-tracking branch 'origin/main' into multiple-views
kring Mar 4, 2025
a147c99
Release TilesetViewGroups along with the Tileset.
kring Mar 4, 2025
86adabc
Hacky view monitoring.
kring Mar 4, 2025
9279975
Specify weight on view groups.
kring Mar 7, 2025
a97522b
Update cesium-native.
kring Mar 7, 2025
9931afd
Update cesium-native.
kring Mar 7, 2025
7a12b51
Update cesium-native.
kring Mar 10, 2025
bfa8edf
Merge remote-tracking branch 'origin/main' into multiple-views
kring Apr 8, 2025
4d8eb21
Update for credit system changes.
kring Apr 8, 2025
957f6f1
Update for credit system changes.
kring Apr 8, 2025
21e260b
Update cesium-native.
kring Apr 8, 2025
e2dde47
Merge remote-tracking branch 'origin/update-for-multiple-views' into …
kring Apr 9, 2025
13c8a46
Use view groups for editor viewports.
kring Apr 9, 2025
472cf7c
Add support for orthographic Editor viewports.
kring Apr 13, 2025
0a308a7
Merge in multiple-views-one-reference-count branch.
kring Apr 17, 2025
a5b627f
Update cesium-native.
kring Apr 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 200 additions & 30 deletions Source/CesiumRuntime/Private/Cesium3DTileset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -1259,6 +1259,7 @@ void ACesium3DTileset::DestroyTileset() {
++this->_tilesetsBeingDestroyed;
this->_pTileset->getAsyncDestructionCompleteEvent().thenInMainThread(
[this]() { --this->_tilesetsBeingDestroyed; });
this->_viewGroups.clear();
this->_pTileset.Reset();

switch (this->TilesetSource) {
Expand Down Expand Up @@ -1654,7 +1655,8 @@ bool ACesium3DTileset::ShouldTickIfViewportsOnly() const {
namespace {
template <typename Func>
void forEachRenderableTile(const auto& tiles, Func&& f) {
for (Cesium3DTilesSelection::Tile* pTile : tiles) {
for (const CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>&
pTile : tiles) {
if (!pTile ||
pTile->getState() != Cesium3DTilesSelection::TileLoadState::Done) {
continue;
Expand Down Expand Up @@ -1682,13 +1684,17 @@ void forEachRenderableTile(const auto& tiles, Func&& f) {
}

void removeVisibleTilesFromList(
std::vector<Cesium3DTilesSelection::Tile*>& list,
const std::vector<Cesium3DTilesSelection::Tile*>& visibleTiles) {
std::vector<CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>>&
list,
const std::vector<
CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>>&
visibleTiles) {
if (list.empty()) {
return;
}

for (Cesium3DTilesSelection::Tile* pTile : visibleTiles) {
for (const CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>&
pTile : visibleTiles) {
auto it = std::find(list.begin(), list.end(), pTile);
if (it != list.end()) {
list.erase(it);
Expand All @@ -1705,21 +1711,29 @@ void removeVisibleTilesFromList(
*
* @param tiles The tiles to hide
*/
void hideTiles(const std::vector<Cesium3DTilesSelection::Tile*>& tiles) {
void hideTiles(
uint32 viewStateKey,
const std::vector<
CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>>& tiles) {
TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::HideTiles)
forEachRenderableTile(
tiles,
[](Cesium3DTilesSelection::Tile* /*pTile*/, UCesiumGltfComponent* pGltf) {
[viewStateKey](
const CesiumUtility::IntrusivePointer<
Cesium3DTilesSelection::Tile>& /*pTile*/,
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(
LogCesium,
Verbose,
TEXT("Tile to no longer render does not have a visible Gltf"));
}

pGltf->SetViewGroupVisibility(viewStateKey, false);
});
}

Expand All @@ -1728,11 +1742,14 @@ void hideTiles(const std::vector<Cesium3DTilesSelection::Tile*>& tiles) {
* list. This includes tiles that are fading out.
*/
void removeCollisionForTiles(
const std::unordered_set<Cesium3DTilesSelection::Tile*>& tiles) {
const std::unordered_set<
CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>>& 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);
});
Expand Down Expand Up @@ -1814,10 +1831,11 @@ void ACesium3DTileset::updateLastViewUpdateResultState(
ResolveGeoreference();
check(Georeference);

for (Cesium3DTilesSelection::Tile* tile : result.tilesToRenderThisFrame) {
for (const CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>&
pTile : result.tilesToRenderThisFrame) {
CesiumGeometry::OrientedBoundingBox obb =
Cesium3DTilesSelection::getOrientedBoundingBoxFromBoundingVolume(
tile->getBoundingVolume(),
pTile->getBoundingVolume(),
Georeference->GetEllipsoid()->GetNativeEllipsoid());

FVector unrealCenter =
Expand All @@ -1828,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);
}
Expand Down Expand Up @@ -1914,13 +1932,17 @@ void ACesium3DTileset::updateLastViewUpdateResultState(
}

void ACesium3DTileset::showTilesToRender(
const std::vector<Cesium3DTilesSelection::Tile*>& tiles) {
uint32 viewStateKey,
const std::vector<
CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>>& tiles) {
TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ShowTilesToRender)
forEachRenderableTile(
tiles,
[&RootComponent = this->RootComponent,
[viewStateKey,
&RootComponent = this->RootComponent,
&BodyInstance = this->BodyInstance](
Cesium3DTilesSelection::Tile* pTile,
const CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>&
pTile,
UCesiumGltfComponent* pGltf) {
applyActorCollisionSettings(BodyInstance, pGltf);

Expand All @@ -1945,9 +1967,11 @@ void ACesium3DTileset::showTilesToRender(

if (!pGltf->IsVisible()) {
TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetVisibilityTrue)
pGltf->SetVisibility(true, true);
// pGltf->SetVisibility(true, true);
}

pGltf->SetViewGroupVisibility(viewStateKey, true);

{
TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::SetCollisionEnabled)
pGltf->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
Expand All @@ -1959,7 +1983,8 @@ static void updateTileFades(const auto& tiles, bool fadingIn) {
forEachRenderableTile(
tiles,
[fadingIn](
Cesium3DTilesSelection::Tile* pTile,
const CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>&
pTile,
UCesiumGltfComponent* pGltf) {
float percentage = pTile->getContent()
.getRenderContent()
Expand Down Expand Up @@ -2036,32 +2061,36 @@ void ACesium3DTileset::Tick(float DeltaTime) {
UCesiumEllipsoid* ellipsoid = this->ResolveGeoreference()->GetEllipsoid();

std::vector<Cesium3DTilesSelection::ViewState> 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) {
TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateViewOffline)
pResult = &this->_pTileset->updateViewOffline(frustums);
} else {
TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateView)
pResult = &this->_pTileset->updateView(frustums, DeltaTime);
pResult = &this->_pTileset->updateViewGroup(
this->_pTileset->getDefaultViewGroup(),
frustums,
DeltaTime);
}
updateLastViewUpdateResultState(*pResult);

removeCollisionForTiles(pResult->tilesFadingOut);

removeVisibleTilesFromList(
_tilesToHideNextFrame,
this->_tilesToHideNextFrame,
pResult->tilesToRenderThisFrame);
hideTiles(_tilesToHideNextFrame);
hideTiles(0, this->_tilesToHideNextFrame);

_tilesToHideNextFrame.clear();
for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) {
for (const CesiumUtility::IntrusivePointer<Cesium3DTilesSelection::Tile>&
pTile : pResult->tilesFadingOut) {
Cesium3DTilesSelection::TileRenderContent* pRenderContent =
pTile->getContent().getRenderContent();
if (!this->UseLodTransitions ||
Expand All @@ -2071,7 +2100,7 @@ void ACesium3DTileset::Tick(float DeltaTime) {
}
}

showTilesToRender(pResult->tilesToRenderThisFrame);
showTilesToRender(0, pResult->tilesToRenderThisFrame);

if (this->UseLodTransitions) {
TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades)
Expand All @@ -2080,6 +2109,147 @@ void ACesium3DTileset::Tick(float DeltaTime) {
}

this->UpdateLoadStatus();

ACesiumCameraManager* pCameraManager =
ACesiumCameraManager::GetDefaultCameraManager(this);
if (pCameraManager) {
this->_viewGroups.resize(pCameraManager->ViewGroups.Num());
for (int32 i = 0; i < pCameraManager->ViewGroups.Num(); ++i) {
const FCesiumViewGroup& group = pCameraManager->ViewGroups[i];

#if WITH_EDITOR
if (group.EditorViewportIndex >= 0) {
TArray<FEditorViewportClient*> viewportClients =
GEditor->GetAllViewportClients();
FEditorViewportClient* pEditorViewportClient =
viewportClients[group.EditorViewportIndex];

if (!pEditorViewportClient->IsVisible() ||
!pEditorViewportClient->IsRealtime()) {
continue;
}

FRotator rotation;

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();
double fov = pEditorViewportClient->ViewFOV;
FIntPoint offset;
FIntPoint size;
pEditorViewportClient->GetViewportDimensions(offset, size);

if (size.X < 1 || size.Y < 1) {
continue;
}

if (this->_scaleUsingDPI) {
float dpiScalingFactor = pEditorViewportClient->GetDPIScale();
size.X = static_cast<float>(size.X) / dpiScalingFactor;
size.Y = static_cast<float>(size.Y) / dpiScalingFactor;
}

std::vector<Cesium3DTilesSelection::ViewState> frustums;

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 {
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);

const Cesium3DTilesSelection::ViewUpdateResult& result =
this->_pTileset->updateViewGroup(
this->_viewGroups[i],
frustums,
DeltaTime);

showTilesToRender(group.ViewStateKey, result.tilesToRenderThisFrame);
hideTiles(
group.ViewStateKey,
std::vector(
result.tilesFadingOut.begin(),
result.tilesFadingOut.end()));
}
#endif
}

this->_pTileset->loadTiles();
}
}

void ACesium3DTileset::EndPlay(const EEndPlayReason::Type EndPlayReason) {
Expand Down
Loading
Loading