Skip to content

Commit

Permalink
Merge pull request #364 from CesiumGS/CollisionSettingsExclusionZones
Browse files Browse the repository at this point in the history
Further work to collision settings and exclusion zones
  • Loading branch information
kring authored Apr 19, 2021
2 parents 25433b8 + 2f9bca7 commit 3daac11
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
- Changed the log level for the tile selection output from `Display` to `Verbose`. With default settings, the output will no longer be displayed in the console, but only written to the log file.
- Added more diagnostic details to error messages for invalid glTF inputs.
- Added diagnostic details to error messages for failed OAuth2 authorization with `CesiumIonClient::Connection`.
- Added a `BodyInstance` property to `Cesium3DTileset` so that collision profiles can be configured.
- Added an experimental "Exclusion Zones" property to `Cesium3DTileset`. While likely to change in the future, it already provides a way to exclude parts of a 3D Tiles tileset to make room for another.

##### Fixes :wrench:

Expand Down
75 changes: 72 additions & 3 deletions Source/CesiumRuntime/Private/Cesium3DTileset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "CesiumGeospatial/Ellipsoid.h"
#include "CesiumGeospatial/Transforms.h"
#include "CesiumGltfComponent.h"
#include "CesiumGltfPrimitiveComponent.h"
#include "CesiumRasterOverlay.h"
#include "CesiumRuntime.h"
#include "CesiumTransforms.h"
Expand All @@ -26,6 +27,7 @@
#include "IPhysXCookingModule.h"
#include "LevelSequenceActor.h"
#include "Math/UnrealMathUtility.h"
#include "Misc/EnumRange.h"
#include "PhysicsPublicCore.h"
#include "UnrealAssetAccessor.h"
#include "UnrealTaskProcessor.h"
Expand Down Expand Up @@ -291,6 +293,18 @@ void ACesium3DTileset::OnConstruction(const FTransform& Transform) {
#endif // EDITOR

this->LoadTileset();

// Hide all existing tiles. The still-visible ones will be shown next time we
// tick.
TArray<UCesiumGltfComponent*> gltfComponents;
this->GetComponents<UCesiumGltfComponent>(gltfComponents);

for (UCesiumGltfComponent* pGltf : gltfComponents) {
if (pGltf && IsValid(pGltf) && pGltf->IsVisible()) {
pGltf->SetVisibility(false, true);
pGltf->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
}
}

void ACesium3DTileset::NotifyHit(
Expand Down Expand Up @@ -462,8 +476,8 @@ class UnrealResourcePreparer : public Cesium3DTiles::IPrepareRendererResources {
textureCoordinateRectangle);
}
}
// UE_LOG(LogCesium, VeryVerbose, TEXT("No content for detaching raster from
// tile"));
// UE_LOG(LogCesium, VeryVerbose, TEXT("No content for detaching raster
// from tile"));
}

private:
Expand Down Expand Up @@ -659,7 +673,8 @@ void ACesium3DTileset::DestroyTileset() {

// The way CesiumRasterOverlay::add is currently implemented, destroying the
// tileset without removing overlays will make it impossible to add it again
// once a new tileset is created (e.g. when switching between terrain assets)
// once a new tileset is created (e.g. when switching between terrain
// assets)
TArray<UCesiumRasterOverlay*> rasterOverlays;
this->GetComponents<UCesiumRasterOverlay>(rasterOverlays);
for (UCesiumRasterOverlay* pOverlay : rasterOverlays) {
Expand Down Expand Up @@ -919,6 +934,35 @@ void ACesium3DTileset::Tick(float DeltaTime) {
continue;
}

// Consider Exclusion zone to drop this tile... Ideally, should be
// considered in Cesium3DTiles::ViewState to avoid loading the tile
// first...
if (ExclusionZones.Num() > 0) {
const CesiumGeospatial::BoundingRegion* pRegion =
std::get_if<CesiumGeospatial::BoundingRegion>(
&pTile->getBoundingVolume());
if (pRegion) {
bool culled = false;

for (FCesiumExclusionZone ExclusionZone : ExclusionZones) {
CesiumGeospatial::GlobeRectangle cgExclusionZone =
CesiumGeospatial::GlobeRectangle::fromDegrees(
ExclusionZone.West,
ExclusionZone.South,
ExclusionZone.East,
ExclusionZone.North);
if (cgExclusionZone.intersect(pRegion->getRectangle())) {
culled = true;
continue;
}
}

if (culled) {
continue;
}
}
}

// const Cesium3DTiles::TileID& id = pTile->getTileID();
// const CesiumGeometry::QuadtreeTileID* pQuadtreeID =
// std::get_if<CesiumGeometry::QuadtreeTileID>(&id); if (!pQuadtreeID ||
Expand All @@ -935,6 +979,24 @@ void ACesium3DTileset::Tick(float DeltaTime) {
continue;
}

// Apply Actor-defined collision settings to the newly-created component.
UCesiumGltfPrimitiveComponent* PrimitiveComponent =
static_cast<UCesiumGltfPrimitiveComponent*>(Gltf->GetChildComponent(0));
if (PrimitiveComponent != nullptr) {
const UEnum* ChannelEnum = StaticEnum<ECollisionChannel>();
if (ChannelEnum) {
for (int32 ChannelValue = 0; ChannelValue < ECollisionChannel::ECC_MAX;
ChannelValue++) {
ECollisionResponse response =
BodyInstance.GetCollisionResponse().GetResponse(
ECollisionChannel(ChannelValue));
PrimitiveComponent->SetCollisionResponseToChannel(
ECollisionChannel(ChannelValue),
response);
}
}
}

if (Gltf->GetAttachParent() == nullptr) {
Gltf->AttachToComponent(
this->RootComponent,
Expand All @@ -953,6 +1015,13 @@ void ACesium3DTileset::EndPlay(const EEndPlayReason::Type EndPlayReason) {
AActor::EndPlay(EndPlayReason);
}

void ACesium3DTileset::PostLoad() {
BodyInstance.FixupData(this); // We need to call this one after Loading the
// actor to have correct BodyInstance values.

Super::PostLoad();
}

void ACesium3DTileset::BeginDestroy() {
this->DestroyTileset();

Expand Down
34 changes: 34 additions & 0 deletions Source/CesiumRuntime/Public/Cesium3DTileset.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

#include "Cesium3DTiles/ViewState.h"
#include "CesiumCreditSystem.h"
#include "CesiumExclusionZone.h"
#include "CesiumGeoreference.h"
#include "CesiumGeoreferenceable.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Interfaces/IHttpRequest.h"
#include <PhysicsEngine/BodyInstance.h>
#include <chrono>
#include <glm/mat4x4.hpp>
#include "Cesium3DTileset.generated.h"
Expand Down Expand Up @@ -50,6 +52,7 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor,
*/
UPROPERTY(
EditAnywhere,
BlueprintReadOnly,
Category = "Cesium",
meta = (EditCondition = "IonAssetID"))
FString IonAccessToken;
Expand Down Expand Up @@ -191,6 +194,25 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor,
UPROPERTY(EditAnywhere, Category = "Cesium|Tile Culling")
bool EnforceCulledScreenSpaceError = false;

/**
* A list of rectangles that are excluded from this tileset. Any tiles that
* overlap any of these rectangles are not shown. This is a crude method to
* avoid overlapping geometry coming from different tilesets. For example, to
* exclude Cesium OSM Buildings where there are photogrammetry assets.
*
* Note that in the current version, excluded tiles are still loaded, they're
* just not displayed. Also, because the tiles shown when zoomed out cover a
* large area, using an exclusion zone often means the tileset won't be shown
* at all when zoomed out.
*
* This property is currently only supported for 3D Tiles that use "region"
* for their bounding volumes. For other tilesets it is silently ignored.
*
* This is an experimental feature and may change in future versions.
*/
UPROPERTY(EditAnywhere, Category = "Cesium|Experimental")
TArray<FCesiumExclusionZone> ExclusionZones;

/**
* The screen-space error to be enforced for tiles that are outside the view
* frustum or hidden in fog.
Expand Down Expand Up @@ -239,6 +261,17 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor,
UPROPERTY(EditAnywhere, Category = "Cesium|Debug")
bool UpdateInEditor = true;

/**
* Define the collision profile for all the 3D tiles created inside this
* actor.
*/
UPROPERTY(
EditAnywhere,
BlueprintReadOnly,
Category = "Cesium|Collision",
meta = (ShowOnlyInnerProperties, SkipUCSModifiedProperties))
FBodyInstance BodyInstance;

UFUNCTION(BlueprintCallable, Category = "Cesium|Rendering")
void PlayMovieSequencer();

Expand Down Expand Up @@ -267,6 +300,7 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor,
virtual void BeginDestroy() override;
virtual void Destroyed() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void PostLoad() override;

protected:
// Called when the game starts or when spawned
Expand Down
27 changes: 27 additions & 0 deletions Source/CesiumRuntime/Public/CesiumExclusionZone.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

#include "CesiumExclusionZone.generated.h"

/**
*
*/
USTRUCT()
struct FCesiumExclusionZone {
GENERATED_BODY()

UPROPERTY(EditAnywhere, Category = "Cesium")
double South = 0.0;

UPROPERTY(EditAnywhere, Category = "Cesium")
double West = 0.0;

UPROPERTY(EditAnywhere, Category = "Cesium")
double North = 0.0;

UPROPERTY(EditAnywhere, Category = "Cesium")
double East = 0.0;
};

0 comments on commit 3daac11

Please sign in to comment.