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"
@@ -1555,6 +1557,8 @@ static void loadPrimitive(
15551557 positionBuffer.Init (numVertices, false );
15561558
15571559 {
1560+ // Note: scaling from glTF vertices to Unreal's must match
1561+ // UCesiumGltfComponent::GetGltfToUnrealLocalVertexPositionScaleFactor
15581562 if (duplicateVertices) {
15591563 TRACE_CPUPROFILER_EVENT_SCOPE (Cesium::CopyDuplicatedPositions)
15601564 for (uint32 i = 0 ; i < numVertices; ++i) {
@@ -2626,7 +2630,6 @@ static void SetGltfParameterValues(
26262630 CesiumGltf::Model& model,
26272631 LoadedPrimitiveResult& loadResult,
26282632 const CesiumGltf::Material& material,
2629- const CesiumGltf::MaterialPBRMetallicRoughness& pbr,
26302633 UMaterialInstanceDynamic* pMaterial,
26312634 EMaterialParameterAssociation association,
26322635 int32 index) {
@@ -2638,7 +2641,9 @@ static void SetGltfParameterValues(
26382641 index),
26392642 static_cast <float >(textureCoordinateSet.second ));
26402643 }
2641-
2644+ const CesiumGltf::MaterialPBRMetallicRoughness& pbr =
2645+ material.pbrMetallicRoughness ? material.pbrMetallicRoughness .value ()
2646+ : defaultPbrMetallicRoughness;
26422647 if (pbr.baseColorFactor .size () > 3 ) {
26432648 pMaterial->SetVectorParameterValueByInfo (
26442649 FMaterialParameterInfo (" baseColorFactor" , association, index),
@@ -3293,11 +3298,6 @@ static void loadPrimitiveGameThreadPart(
32933298 const CesiumGltf::Material& material =
32943299 loadResult.materialIndex != -1 ? model.materials [loadResult.materialIndex ]
32953300 : defaultMaterial;
3296-
3297- const CesiumGltf::MaterialPBRMetallicRoughness& pbr =
3298- material.pbrMetallicRoughness ? material.pbrMetallicRoughness .value ()
3299- : defaultPbrMetallicRoughness;
3300-
33013301 const FName ImportedSlotName (
33023302 *(TEXT (" CesiumMaterial" ) + FString::FromInt (nextMaterialId++)));
33033303
@@ -3323,13 +3323,22 @@ static void loadPrimitiveGameThreadPart(
33233323 }
33243324#endif
33253325
3326- UMaterialInstanceDynamic* pMaterialForGltfPrimitive;
3326+ // Move this right now: CreateMaterial may need them!
3327+ // "Safe" even though loadResult is still used later, because the methods used
3328+ // during material setup (SetGltfParameterValues, etc.) below do not use these
3329+ // members.
3330+ primData.Features = std::move (loadResult.Features );
3331+ primData.Metadata = std::move (loadResult.Metadata );
3332+
3333+ UMaterialInstanceDynamic* pMaterialForGltfPrimitive = nullptr ;
3334+ ICesium3DTilesetLifecycleEventReceiver* pLifecycleEventReceiver =
3335+ pTilesetActor->GetLifecycleEventReceiver ();
33273336 {
33283337 TRACE_CPUPROFILER_EVENT_SCOPE (Cesium::SetupMaterial)
3338+ ensure (pUserDesignatedMaterial);
33293339
33303340 UMaterialInstanceDynamic* pUserDesignatedMaterialAsDynamic =
33313341 Cast<UMaterialInstanceDynamic>(pUserDesignatedMaterial);
3332-
33333342 // If the user-designated material is a UMaterialInstanceDynamic, Create()
33343343 // will reject it as a valid instance parent. Defer to its non-dynamic
33353344 // parent instead.
@@ -3338,18 +3347,33 @@ static void loadPrimitiveGameThreadPart(
33383347 ? pUserDesignatedMaterialAsDynamic->Parent .Get ()
33393348 : pUserDesignatedMaterial;
33403349
3341- pMaterialForGltfPrimitive = UMaterialInstanceDynamic::Create (
3342- pBaseMaterial,
3343- nullptr ,
3344- ImportedSlotName);
3350+ if (pLifecycleEventReceiver) {
3351+ // Possibility to override the material for this primitive
3352+ pMaterialForGltfPrimitive = pLifecycleEventReceiver->CreateMaterial (
3353+ *pCesiumPrimitive,
3354+ pBaseMaterial,
3355+ ImportedSlotName);
3356+ check (pMaterialForGltfPrimitive);
3357+ // pMaterialForGltfPrimitive created above may not have used the
3358+ // suggested pBaseMaterial passed as input
3359+ pBaseMaterial = pMaterialForGltfPrimitive->Parent .Get ();
3360+ // may have changed but we don't need it from now on:
3361+ pUserDesignatedMaterialAsDynamic = nullptr ;
3362+ } else {
3363+ // Same as ICesium3DTilesetLifecycleEventReceiver::CreateMaterial's
3364+ // default implementation
3365+ pMaterialForGltfPrimitive = UMaterialInstanceDynamic::Create (
3366+ pBaseMaterial,
3367+ nullptr ,
3368+ ImportedSlotName);
3369+ }
33453370
33463371 pMaterialForGltfPrimitive->SetFlags (
33473372 RF_Transient | RF_DuplicateTransient | RF_TextExportTransient);
33483373 SetGltfParameterValues (
33493374 model,
33503375 loadResult,
33513376 material,
3352- pbr,
33533377 pMaterialForGltfPrimitive,
33543378 EMaterialParameterAssociation::GlobalParameter,
33553379 INDEX_NONE);
@@ -3412,7 +3436,6 @@ static void loadPrimitiveGameThreadPart(
34123436 model,
34133437 loadResult,
34143438 material,
3415- pbr,
34163439 pMaterialForGltfPrimitive,
34173440 EMaterialParameterAssociation::LayerParameter,
34183441 0 );
@@ -3505,10 +3528,16 @@ static void loadPrimitiveGameThreadPart(
35053528 it.FontPage );
35063529 }
35073530 }
3508- }
35093531
3510- primData.Features = std::move (loadResult.Features );
3511- primData.Metadata = std::move (loadResult.Metadata );
3532+ // Extra material customizations
3533+ if (pLifecycleEventReceiver) {
3534+ pLifecycleEventReceiver->CustomizeMaterial (
3535+ *pCesiumPrimitive,
3536+ *pMaterialForGltfPrimitive,
3537+ pCesiumData,
3538+ material);
3539+ }
3540+ }
35123541
35133542 primData.EncodedFeatures = std::move (loadResult.EncodedFeatures );
35143543 primData.EncodedMetadata = std::move (loadResult.EncodedMetadata );
@@ -3581,6 +3610,11 @@ static void loadPrimitiveGameThreadPart(
35813610 TRACE_CPUPROFILER_EVENT_SCOPE (Cesium::RegisterComponent)
35823611 pMesh->RegisterComponent ();
35833612 }
3613+
3614+ // Call the observer callback (if any) once all is done
3615+ if (pLifecycleEventReceiver) {
3616+ pLifecycleEventReceiver->OnTileMeshPrimitiveLoaded (*pCesiumPrimitive);
3617+ }
35843618}
35853619
35863620static void loadVoxelsGameThreadPart (
@@ -3667,6 +3701,7 @@ UCesiumGltfComponent::CreateOffGameThread(
36673701 // }
36683702
36693703 UCesiumGltfComponent* pGltf = NewObject<UCesiumGltfComponent>(pTilesetActor);
3704+ pGltf->pTile = &tile;
36703705 pGltf->SetMobility (pTilesetActor->GetRootComponent ()->Mobility );
36713706 pGltf->SetFlags (
36723707 RF_Transient | RF_DuplicateTransient | RF_TextExportTransient);
@@ -3723,11 +3758,24 @@ UCesiumGltfComponent::CreateOffGameThread(
37233758 }
37243759 }
37253760
3761+ if (ICesium3DTilesetLifecycleEventReceiver* Receiver =
3762+ pTilesetActor->GetLifecycleEventReceiver ()) {
3763+ Receiver->OnTileLoaded (*pGltf);
3764+ }
3765+
37263766 pGltf->SetVisibility (false , true );
37273767 pGltf->SetCollisionEnabled (ECollisionEnabled::NoCollision);
37283768 return pGltf;
37293769}
37303770
3771+ void UCesiumGltfComponent::OnVisibilityChanged () {
3772+ USceneComponent::OnVisibilityChanged ();
3773+ ICesium3DTilesetLifecycleEventReceiver* pLifecycleEventReceiver =
3774+ GetTilesetActor ().GetLifecycleEventReceiver ();
3775+ if (pLifecycleEventReceiver)
3776+ pLifecycleEventReceiver->OnTileVisibilityChanged (*this , GetVisibleFlag ());
3777+ }
3778+
37313779UCesiumGltfComponent::UCesiumGltfComponent () : USceneComponent() {
37323780 // Structure to hold one-time initialization
37333781 struct FConstructorStatics {
@@ -3758,6 +3806,35 @@ UCesiumGltfComponent::UCesiumGltfComponent() : USceneComponent() {
37583806 PrimaryComponentTick.bCanEverTick = false ;
37593807}
37603808
3809+ const CesiumGltf::Model* UCesiumGltfComponent::GetGltfModel () const {
3810+ if (pTile) {
3811+ if (auto RenderContent = pTile->getContent ().getRenderContent ())
3812+ return &RenderContent->getModel ();
3813+ }
3814+ return nullptr ;
3815+ }
3816+
3817+ const FCesiumModelMetadata& UCesiumGltfComponent::GetModelMetadata () const {
3818+ return Metadata;
3819+ }
3820+
3821+ const Cesium3DTilesSelection::TileID& UCesiumGltfComponent::GetTileID () const {
3822+ return pTile->getTileID ();
3823+ }
3824+
3825+ ACesium3DTileset& UCesiumGltfComponent::GetTilesetActor () {
3826+ return *Cast<ACesium3DTileset>(GetOuter ());
3827+ }
3828+
3829+ FVector
3830+ UCesiumGltfComponent::GetGltfToUnrealLocalVertexPositionScaleFactor () const {
3831+ // Note: replicates logic from (static) loadPrimitive
3832+ return FVector (
3833+ CesiumPrimitiveData::positionScaleFactor,
3834+ -CesiumPrimitiveData::positionScaleFactor,
3835+ CesiumPrimitiveData::positionScaleFactor);
3836+ }
3837+
37613838void UCesiumGltfComponent::UpdateTransformFromCesium (
37623839 const glm::dmat4& cesiumToUnrealTransform) {
37633840 for (USceneComponent* pSceneComponent : this ->GetAttachChildren ()) {
0 commit comments