diff --git a/CHANGES.md b/CHANGES.md index d8b65db4c..2967ca189 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ # Change Log {#changes} +### v?.??.? - ????-??-?? + +##### Additions :tada: + +- Added the `DoubleSidedCollisions` boolean property to the `ACesium3DTileset` actor, allowing intersections and collisions with geometry to also work when hitting "back" faces. + ### v2.21.0 - 2025-11-03 ##### Additions :tada: diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 7b1984758..dd323a1ec 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -492,6 +492,13 @@ void ACesium3DTileset::SetCreatePhysicsMeshes(bool bCreatePhysicsMeshes) { } } +void ACesium3DTileset::SetDoubleSidedCollisions(bool bDoubleSidedCollisions) { + if (this->DoubleSidedCollisions != bDoubleSidedCollisions) { + this->DoubleSidedCollisions = bDoubleSidedCollisions; + this->DestroyTileset(); + } +} + void ACesium3DTileset::SetCreateNavCollision(bool bCreateNavCollision) { if (this->CreateNavCollision != bCreateNavCollision) { this->CreateNavCollision = bCreateNavCollision; diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp index 62590d796..671e2c1b1 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -3021,6 +3021,7 @@ static void loadPrimitiveGameThreadPart( const glm::dmat4x4& cesiumToUnrealTransform, const Cesium3DTilesSelection::Tile& tile, bool createNavCollision, + bool doubleSidedCollisions, ACesium3DTileset* pTilesetActor, const std::vector& instanceTransforms, const TSharedPtr& pInstanceFeatures) { @@ -3431,6 +3432,7 @@ static void loadPrimitiveGameThreadPart( ECollisionTraceFlag::CTF_UseComplexAsSimple; if (loadResult.pCollisionMesh) { + pBodySetup->bDoubleSidedGeometry = doubleSidedCollisions; pBodySetup->TriMeshGeometries.Add(loadResult.pCollisionMesh); } @@ -3485,7 +3487,8 @@ UCesiumGltfComponent::CreateOffGameThread( UMaterialInterface* pBaseWaterMaterial, FCustomDepthParameters CustomDepthParameters, const Cesium3DTilesSelection::Tile& tile, - bool createNavCollision) { + bool createNavCollision, + bool doubleSidedCollisions) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadModel) HalfConstructedReal* pReal = @@ -3538,6 +3541,7 @@ UCesiumGltfComponent::CreateOffGameThread( cesiumToUnrealTransform, tile, createNavCollision, + doubleSidedCollisions, pTilesetActor, node.InstanceTransforms, node.pInstanceFeatures); @@ -3883,5 +3887,11 @@ static Chaos::FTriangleMeshImplicitObjectPtr BuildChaosTriangleMeshes( MoveTemp(materials), MoveTemp(pFaceRemap), nullptr, - false); + // Not sure what this is for: in my experience, whatever you pass here is + // overridden later on by a call to SetCullsBackFaceRaycast (from + // RegisterComponent) which will reset the property depending on the value + // of UBodySetup::bDoubleSidedGeometry. + // See ACesium3DTileset::DoubleSidedCollisions to effectively enable + // backface hits. + /*bInCullsBackFaceRaycast*/false); } diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.h b/Source/CesiumRuntime/Private/CesiumGltfComponent.h index ed60207a2..b9f29c90e 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.h +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.h @@ -90,7 +90,8 @@ class UCesiumGltfComponent : public USceneComponent, public ICesiumLoadedTile { UMaterialInterface* BaseWaterMaterial, FCustomDepthParameters CustomDepthParameters, const Cesium3DTilesSelection::Tile& tile, - bool createNavCollision); + bool createNavCollision, + bool doubleSidedCollisions); UCesiumGltfComponent(); diff --git a/Source/CesiumRuntime/Private/UnrealPrepareRendererResources.cpp b/Source/CesiumRuntime/Private/UnrealPrepareRendererResources.cpp index 9f35373d7..8e11ed8e1 100644 --- a/Source/CesiumRuntime/Private/UnrealPrepareRendererResources.cpp +++ b/Source/CesiumRuntime/Private/UnrealPrepareRendererResources.cpp @@ -85,7 +85,8 @@ void* UnrealPrepareRendererResources::prepareInMainThread( this->_pActor->GetWaterMaterial(), this->_pActor->GetCustomDepthParameters(), tile, - this->_pActor->GetCreateNavCollision()); + this->_pActor->GetCreateNavCollision(), + this->_pActor->GetDoubleSidedCollisions()); } // UE_LOG(LogCesium, VeryVerbose, TEXT("No content for tile")); return nullptr; diff --git a/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Source/CesiumRuntime/Public/Cesium3DTileset.h index 3f907fe1e..2a0e080b0 100644 --- a/Source/CesiumRuntime/Public/Cesium3DTileset.h +++ b/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -799,6 +799,17 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { Category = "Cesium|Physics") bool CreatePhysicsMeshes = true; + /** + * Whether to enable doubled-sided collisions (both "front" and "back" faces) + * on the physics meshes created when CreatePhysicsMeshes is true. + */ + UPROPERTY( + EditAnywhere, + BlueprintGetter = GetDoubleSidedCollisions, + BlueprintSetter = SetDoubleSidedCollisions, + Category = "Cesium|Physics") + bool DoubleSidedCollisions = false; + /** * Whether to generate navigation collisions for this tileset. * @@ -1095,6 +1106,12 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { UFUNCTION(BlueprintSetter, Category = "Cesium|Physics") void SetCreatePhysicsMeshes(bool bCreatePhysicsMeshes); + UFUNCTION(BlueprintGetter, Category = "Cesium|Physics") + bool GetDoubleSidedCollisions() const { return DoubleSidedCollisions; } + + UFUNCTION(BlueprintSetter, Category = "Cesium|Physics") + void SetDoubleSidedCollisions(bool bCreatePhysicsMeshes); + UFUNCTION(BlueprintGetter, Category = "Cesium|Navigation") bool GetCreateNavCollision() const { return CreateNavCollision; }