Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Change Log {#changes}

- adding a function to change the collision response of a Cesium3DTileset by collision channel.

### v2.20.0 - 2025-10-01

##### Additions :tada:
Expand Down
69 changes: 59 additions & 10 deletions Source/CesiumRuntime/Private/Cesium3DTileset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,11 @@ void ACesium3DTileset::SampleHeightMostDetailed(
positions.reserve(LongitudeLatitudeHeightArray.Num());

for (const FVector& position : LongitudeLatitudeHeightArray) {
positions.emplace_back(CesiumGeospatial::Cartographic::fromDegrees(
position.X,
position.Y,
position.Z));
positions.emplace_back(
CesiumGeospatial::Cartographic::fromDegrees(
position.X,
position.Y,
position.Z));
}

auto sampleHeights = [this, &positions]() mutable {
Expand Down Expand Up @@ -1083,9 +1084,10 @@ void ACesium3DTileset::LoadTileset() {
options.requestHeaders.reserve(this->RequestHeaders.Num());

for (const auto& [Key, Value] : this->RequestHeaders) {
options.requestHeaders.emplace_back(CesiumAsync::IAssetAccessor::THeader{
TCHAR_TO_UTF8(*Key),
TCHAR_TO_UTF8(*Value)});
options.requestHeaders.emplace_back(
CesiumAsync::IAssetAccessor::THeader{
TCHAR_TO_UTF8(*Key),
TCHAR_TO_UTF8(*Value)});
}

switch (this->TilesetSource) {
Expand Down Expand Up @@ -1559,9 +1561,10 @@ ACesium3DTileset::CreateViewStateFromViewParameters(
glm::dvec3 tilesetCameraLocation = glm::dvec3(
unrealWorldToTileset *
glm::dvec4(camera.Location.X, camera.Location.Y, camera.Location.Z, 1.0));
glm::dvec3 tilesetCameraFront = glm::normalize(glm::dvec3(
unrealWorldToTileset *
glm::dvec4(direction.X, direction.Y, direction.Z, 0.0)));
glm::dvec3 tilesetCameraFront = glm::normalize(
glm::dvec3(
unrealWorldToTileset *
glm::dvec4(direction.X, direction.Y, direction.Z, 0.0)));
glm::dvec3 tilesetCameraUp = glm::normalize(
glm::dvec3(unrealWorldToTileset * glm::dvec4(up.X, up.Y, up.Z, 0.0)));

Expand Down Expand Up @@ -2315,3 +2318,49 @@ void ACesium3DTileset::RuntimeSettingsChanged(
}
}
#endif

void ACesium3DTileset::SetCollisionResponseToChannel(
ECollisionChannel Channel,
ECollisionResponse NewResponse) {
// Update the tileset's BodyInstance for future tiles
BodyInstance.SetResponseToChannel(Channel, NewResponse);

// Get all loaded glTF components
TArray<UCesiumGltfComponent*> GltfComponents;
GetComponents<UCesiumGltfComponent>(GltfComponents);

// Apply settings to existing tiles
for (UCesiumGltfComponent* Gltf : GltfComponents) {
if (Gltf && IsValid(Gltf)) {
applyActorCollisionSettings(BodyInstance, Gltf);
}
}

// Force refresh on each primitive component
for (UCesiumGltfComponent* Gltf : GltfComponents) {
if (Gltf && IsValid(Gltf)) {
const TArray<USceneComponent*>& Children = Gltf->GetAttachChildren();
for (USceneComponent* Child : Children) {
UCesiumGltfPrimitiveComponent* Prim =
Cast<UCesiumGltfPrimitiveComponent>(Child);
if (Prim && IsValid(Prim)) {
// Set to Custom profile if not already, to allow per-channel changes
Prim->SetCollisionProfileName("Custom");

// Set the specific channel response
Prim->SetCollisionResponseToChannel(Channel, NewResponse);

// Update collision profile to apply changes
Prim->UpdateCollisionProfile();

// Toggle collision enabled to force refresh
Prim->SetCollisionEnabled(ECollisionEnabled::NoCollision);
Prim->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);

// Recreate physics state for final application
Prim->RecreatePhysicsState();
}
}
}
}
}
24 changes: 24 additions & 0 deletions Source/CesiumRuntime/Public/Cesium3DTileset.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,30 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor {
const TArray<FVector>& LongitudeLatitudeHeightArray,
FCesiumSampleHeightMostDetailedCallback OnHeightsSampled);

/**
* @brief Sets the collision response of this tileset to a specific collision
* channel at runtime. This updates the actor's BodyInstance for future-loaded
* tiles and propagates the change to all currently loaded tiles by refreshing
* their primitive components, ensuring consistent collision behavior for both
* queries and physics interactions.
*
* The change takes effect immediately after propagation, including recreation
* of physics states on existing primitives. This function is
* blueprint-callable and suitable for dynamic adjustments, such as toggling
* interactions with pawns or projectiles during gameplay. Note that tiles
* must have physics meshes enabled (via CreatePhysicsMeshes) for physical
* collisions to apply.
*
* @param Channel The collision channel to modify (e.g., ECC_Pawn,
* ECC_Visibility).
* @param NewResponse The new response for the channel (e.g., ECR_Block,
* ECR_Ignore).
*/
UFUNCTION(BlueprintCallable, Category = "Cesium|Collision")
void SetCollisionResponseToChannel(
ECollisionChannel Channel,
ECollisionResponse NewResponse);

private:
/**
* The designated georeference actor controlling how the actor's
Expand Down