11// Copyright 2020-2024 CesiumGS, Inc. and Contributors
22
33#include " CesiumGltfComponent.h"
4+
45#include " Async/Async.h"
6+ #include " Cesium3DTilesetLifecycleEventReceiver.h"
57#include " CesiumCommon.h"
68#include " CesiumEncodedMetadataUtility.h"
79#include " CesiumFeatureIdSet.h"
@@ -1551,6 +1553,8 @@ static void loadPrimitive(
15511553 positionBuffer.Init (numVertices, false );
15521554
15531555 {
1556+ // Note: scaling from glTF vertices to Unreal's must match
1557+ // UCesiumGltfComponent::GetGltfToUnrealLocalVertexPositionScaleFactor
15541558 if (duplicateVertices) {
15551559 TRACE_CPUPROFILER_EVENT_SCOPE (Cesium::CopyDuplicatedPositions)
15561560 for (uint32 i = 0 ; i < numVertices; ++i) {
@@ -2471,7 +2475,6 @@ static void SetGltfParameterValues(
24712475 CesiumGltf::Model& model,
24722476 LoadedPrimitiveResult& loadResult,
24732477 const CesiumGltf::Material& material,
2474- const CesiumGltf::MaterialPBRMetallicRoughness& pbr,
24752478 UMaterialInstanceDynamic* pMaterial,
24762479 EMaterialParameterAssociation association,
24772480 int32 index) {
@@ -2483,7 +2486,9 @@ static void SetGltfParameterValues(
24832486 index),
24842487 static_cast <float >(textureCoordinateSet.second ));
24852488 }
2486-
2489+ const CesiumGltf::MaterialPBRMetallicRoughness& pbr =
2490+ material.pbrMetallicRoughness ? material.pbrMetallicRoughness .value ()
2491+ : defaultPbrMetallicRoughness;
24872492 if (pbr.baseColorFactor .size () > 3 ) {
24882493 pMaterial->SetVectorParameterValueByInfo (
24892494 FMaterialParameterInfo (" baseColorFactor" , association, index),
@@ -3138,11 +3143,6 @@ static void loadPrimitiveGameThreadPart(
31383143 const CesiumGltf::Material& material =
31393144 loadResult.materialIndex != -1 ? model.materials [loadResult.materialIndex ]
31403145 : defaultMaterial;
3141-
3142- const CesiumGltf::MaterialPBRMetallicRoughness& pbr =
3143- material.pbrMetallicRoughness ? material.pbrMetallicRoughness .value ()
3144- : defaultPbrMetallicRoughness;
3145-
31463146 const FName ImportedSlotName (
31473147 *(TEXT (" CesiumMaterial" ) + FString::FromInt (nextMaterialId++)));
31483148
@@ -3168,13 +3168,22 @@ static void loadPrimitiveGameThreadPart(
31683168 }
31693169#endif
31703170
3171- UMaterialInstanceDynamic* pMaterialForGltfPrimitive;
3171+ // Move this right now: CreateMaterial may need them!
3172+ // "Safe" even though loadResult is still used later, because the methods used
3173+ // during material setup (SetGltfParameterValues, etc.) below do not use these
3174+ // members.
3175+ primData.Features = std::move (loadResult.Features );
3176+ primData.Metadata = std::move (loadResult.Metadata );
3177+
3178+ UMaterialInstanceDynamic* pMaterialForGltfPrimitive = nullptr ;
3179+ ICesium3DTilesetLifecycleEventReceiver* pLifecycleEventReceiver =
3180+ pTilesetActor->GetLifecycleEventReceiver ();
31723181 {
31733182 TRACE_CPUPROFILER_EVENT_SCOPE (Cesium::SetupMaterial)
3183+ ensure (pUserDesignatedMaterial);
31743184
31753185 UMaterialInstanceDynamic* pUserDesignatedMaterialAsDynamic =
31763186 Cast<UMaterialInstanceDynamic>(pUserDesignatedMaterial);
3177-
31783187 // If the user-designated material is a UMaterialInstanceDynamic, Create()
31793188 // will reject it as a valid instance parent. Defer to its non-dynamic
31803189 // parent instead.
@@ -3183,18 +3192,33 @@ static void loadPrimitiveGameThreadPart(
31833192 ? pUserDesignatedMaterialAsDynamic->Parent .Get ()
31843193 : pUserDesignatedMaterial;
31853194
3186- pMaterialForGltfPrimitive = UMaterialInstanceDynamic::Create (
3187- pBaseMaterial,
3188- nullptr ,
3189- ImportedSlotName);
3195+ if (pLifecycleEventReceiver) {
3196+ // Possibility to override the material for this primitive
3197+ pMaterialForGltfPrimitive = pLifecycleEventReceiver->CreateMaterial (
3198+ *pCesiumPrimitive,
3199+ pBaseMaterial,
3200+ ImportedSlotName);
3201+ check (pMaterialForGltfPrimitive);
3202+ // pMaterialForGltfPrimitive created above may not have used the
3203+ // suggested pBaseMaterial passed as input
3204+ pBaseMaterial = pMaterialForGltfPrimitive->Parent .Get ();
3205+ // may have changed but we don't need it from now on:
3206+ pUserDesignatedMaterialAsDynamic = nullptr ;
3207+ } else {
3208+ // Same as ICesium3DTilesetLifecycleEventReceiver::CreateMaterial's
3209+ // default implementation
3210+ pMaterialForGltfPrimitive = UMaterialInstanceDynamic::Create (
3211+ pBaseMaterial,
3212+ nullptr ,
3213+ ImportedSlotName);
3214+ }
31903215
31913216 pMaterialForGltfPrimitive->SetFlags (
31923217 RF_Transient | RF_DuplicateTransient | RF_TextExportTransient);
31933218 SetGltfParameterValues (
31943219 model,
31953220 loadResult,
31963221 material,
3197- pbr,
31983222 pMaterialForGltfPrimitive,
31993223 EMaterialParameterAssociation::GlobalParameter,
32003224 INDEX_NONE);
@@ -3257,7 +3281,6 @@ static void loadPrimitiveGameThreadPart(
32573281 model,
32583282 loadResult,
32593283 material,
3260- pbr,
32613284 pMaterialForGltfPrimitive,
32623285 EMaterialParameterAssociation::LayerParameter,
32633286 0 );
@@ -3350,10 +3373,16 @@ static void loadPrimitiveGameThreadPart(
33503373 it.FontPage );
33513374 }
33523375 }
3353- }
33543376
3355- primData.Features = std::move (loadResult.Features );
3356- primData.Metadata = std::move (loadResult.Metadata );
3377+ // Extra material customizations
3378+ if (pLifecycleEventReceiver) {
3379+ pLifecycleEventReceiver->CustomizeMaterial (
3380+ *pCesiumPrimitive,
3381+ *pMaterialForGltfPrimitive,
3382+ pCesiumData,
3383+ material);
3384+ }
3385+ }
33573386
33583387 primData.EncodedFeatures = std::move (loadResult.EncodedFeatures );
33593388 primData.EncodedMetadata = std::move (loadResult.EncodedMetadata );
@@ -3426,6 +3455,11 @@ static void loadPrimitiveGameThreadPart(
34263455 TRACE_CPUPROFILER_EVENT_SCOPE (Cesium::RegisterComponent)
34273456 pMesh->RegisterComponent ();
34283457 }
3458+
3459+ // Call the observer callback (if any) once all is done
3460+ if (pLifecycleEventReceiver) {
3461+ pLifecycleEventReceiver->OnTileMeshPrimitiveLoaded (*pCesiumPrimitive);
3462+ }
34293463}
34303464
34313465/* static*/ CesiumAsync::Future<UCesiumGltfComponent::CreateOffGameThreadResult>
@@ -3464,6 +3498,7 @@ UCesiumGltfComponent::CreateOffGameThread(
34643498 // }
34653499
34663500 UCesiumGltfComponent* Gltf = NewObject<UCesiumGltfComponent>(pTilesetActor);
3501+ Gltf->pTile = &tile;
34673502 Gltf->SetMobility (pTilesetActor->GetRootComponent ()->Mobility );
34683503 Gltf->SetFlags (RF_Transient | RF_DuplicateTransient | RF_TextExportTransient);
34693504
@@ -3510,11 +3545,24 @@ UCesiumGltfComponent::CreateOffGameThread(
35103545 }
35113546 }
35123547
3548+ if (ICesium3DTilesetLifecycleEventReceiver* Receiver =
3549+ pTilesetActor->GetLifecycleEventReceiver ()) {
3550+ Receiver->OnTileLoaded (*Gltf);
3551+ }
3552+
35133553 Gltf->SetVisibility (false , true );
35143554 Gltf->SetCollisionEnabled (ECollisionEnabled::NoCollision);
35153555 return Gltf;
35163556}
35173557
3558+ void UCesiumGltfComponent::OnVisibilityChanged () {
3559+ USceneComponent::OnVisibilityChanged ();
3560+ ICesium3DTilesetLifecycleEventReceiver* pLifecycleEventReceiver =
3561+ GetTilesetActor ().GetLifecycleEventReceiver ();
3562+ if (pLifecycleEventReceiver)
3563+ pLifecycleEventReceiver->OnTileVisibilityChanged (*this , GetVisibleFlag ());
3564+ }
3565+
35183566UCesiumGltfComponent::UCesiumGltfComponent () : USceneComponent() {
35193567 // Structure to hold one-time initialization
35203568 struct FConstructorStatics {
@@ -3545,6 +3593,35 @@ UCesiumGltfComponent::UCesiumGltfComponent() : USceneComponent() {
35453593 PrimaryComponentTick.bCanEverTick = false ;
35463594}
35473595
3596+ const CesiumGltf::Model* UCesiumGltfComponent::GetGltfModel () const {
3597+ if (pTile) {
3598+ if (auto RenderContent = pTile->getContent ().getRenderContent ())
3599+ return &RenderContent->getModel ();
3600+ }
3601+ return nullptr ;
3602+ }
3603+
3604+ const FCesiumModelMetadata& UCesiumGltfComponent::GetModelMetadata () const {
3605+ return Metadata;
3606+ }
3607+
3608+ const Cesium3DTilesSelection::TileID& UCesiumGltfComponent::GetTileID () const {
3609+ return pTile->getTileID ();
3610+ }
3611+
3612+ ACesium3DTileset& UCesiumGltfComponent::GetTilesetActor () {
3613+ return *Cast<ACesium3DTileset>(GetOuter ());
3614+ }
3615+
3616+ FVector
3617+ UCesiumGltfComponent::GetGltfToUnrealLocalVertexPositionScaleFactor () const {
3618+ // Note: replicates logic from (static) loadPrimitive
3619+ return FVector (
3620+ CesiumPrimitiveData::positionScaleFactor,
3621+ -CesiumPrimitiveData::positionScaleFactor,
3622+ CesiumPrimitiveData::positionScaleFactor);
3623+ }
3624+
35483625void UCesiumGltfComponent::UpdateTransformFromCesium (
35493626 const glm::dmat4& cesiumToUnrealTransform) {
35503627 for (USceneComponent* pSceneComponent : this ->GetAttachChildren ()) {
0 commit comments