diff --git a/CHANGES.md b/CHANGES.md index e7a58d762..9a72c231f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ ##### Additions :tada: - Added `CircumscribedGroundHeight` property to `CesiumSunSky`. It defaults to 0, which is consistent with the previous behavior. It can be set to a larger value (like 40) to avoid dark splotchy artifacts when zoomed out far from the globe in certain tilesets where geometry extends very far beyond the ellipsoid in the low-detail representation, such as Google Photorealistic 3D Tiles. +- Added a shared assets system that ensures external images referenced by different glTFs will only be loaded once per image. Previously, these images would be loaded again for each glTF that referenced them. This significantly reduces memory usage for tilesets that reuse the same textures. ##### Fixes :wrench: @@ -164,7 +165,7 @@ In addition to the above, this release updates [cesium-native](https://github.co ##### Additions :tada: - - Added support for multiple Cesium ion servers by creating `CesiumIonServer` data assets. +- Added support for multiple Cesium ion servers by creating `CesiumIonServer` data assets. In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.30.0 to v0.31.0. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. @@ -172,8 +173,8 @@ In addition to the above, this release updates [cesium-native](https://github.co ##### Additions :tada: - - Added support for styling with property textures in `EXT_structural_metadata`. - - Significantly improved tile download performance by adding `HttpThreadActiveFrameTimeInSeconds=0.001` to `Engine.ini`. This results in a major performance improvement for all tilesets, particularly Google Photorealistic 3D Tiles. +- Added support for styling with property textures in `EXT_structural_metadata`. +- Significantly improved tile download performance by adding `HttpThreadActiveFrameTimeInSeconds=0.001` to `Engine.ini`. This results in a major performance improvement for all tilesets, particularly Google Photorealistic 3D Tiles. - Added `HttpMaxConnectionsPerServer=40` to `Engine.ini`. By default, only 16 connections are allowed, which limits the performance when downloading tiles. ##### Fixes :wrench: @@ -193,7 +194,7 @@ This release no longer supports Unreal Engine v5.0. Unreal Engine v5.1, v5.2, or ##### Breaking Changes :mega: - Removed `FCesiumIntegerColor`, `FCesiumFloatColor`, `UCesiumFeatureTexturePropertyBlueprintLibrary::GetIntegerColorFromTextureCoordinates` and `UCesiumFeatureTexturePropertyBlueprintLibrary::GetFloatColorFromTextureCoordinates`. Check out the [upgrade guide](Documentation/upgrade-to-2.0-guide.md) for how retrieve metadata from property textures with the new API. -- Renamed `GetTextureCoordinateIndex` to `GetUnrealUVChannel` in both `UCesiumFeatureIdTextureBlueprintLibrary` and `UCesiumPropertyTexturePropertyBlueprintLibrary`. Contrary to what the documentation claimed, this function retrieved the index of the texture coordinate set in the *Unreal static mesh*, which is not necessarily equal to the texture coordinate set index in the *glTF primitive*. For the latter value, use `GetGltfTextureCoordinateSetIndex` instead. +- Renamed `GetTextureCoordinateIndex` to `GetUnrealUVChannel` in both `UCesiumFeatureIdTextureBlueprintLibrary` and `UCesiumPropertyTexturePropertyBlueprintLibrary`. Contrary to what the documentation claimed, this function retrieved the index of the texture coordinate set in the _Unreal static mesh_, which is not necessarily equal to the texture coordinate set index in the _glTF primitive_. For the latter value, use `GetGltfTextureCoordinateSetIndex` instead. - Removed the old "exclusion zones" feature, which has been deprecated since v1.11.0. Use `CesiumCartographicPolygon` or `CesiumTileExcluder` instead. ##### Additions :tada: @@ -342,7 +343,7 @@ In addition to the above, this release updates [cesium-native](https://github.co ##### Fixes :wrench: - Added a workaround for an apparent bug in Unreal Engine 5.1 that prevented collisions from working with Cesium3DTilesets. -- Fixed a bug that could cause the `AGlobeAwareDefaultPawn` / `DynamicPawn` to suddenly move to a very high height for one render frame just as it arrives at its destination during a flight. +- Fixed a bug that could cause the `AGlobeAwareDefaultPawn` / `DynamicPawn` to suddenly move to a very high height for one render frame just as it arrives at its destination during a flight. In addition to the above, this release updates [cesium-native](https://github.com/CesiumGS/cesium-native) from v0.25.0 to v0.25.1. See the [changelog](https://github.com/CesiumGS/cesium-native/blob/main/CHANGES.md) for a complete list of changes in cesium-native. @@ -405,7 +406,7 @@ This will be the _last_ release that supports Unreal Engine v4.27. Future versio ##### Additions :tada: -- The `FlyToAltitudeProfileCurve`, `FlyToProgressCurve`, `FlyToMaximumAltitudeCurve`, `FlyToDuration`, and `FlyToGranularityDegrees` properties of `GlobeAwareDefaultPawn` / `DynamicPawn` may now be read and written from Blueprints. +- The `FlyToAltitudeProfileCurve`, `FlyToProgressCurve`, `FlyToMaximumAltitudeCurve`, `FlyToDuration`, and `FlyToGranularityDegrees` properties of `GlobeAwareDefaultPawn` / `DynamicPawn` may now be read and written from Blueprints. - Added an option on `Cesium3DTileset` to ignore the `KHR_materials_unlit` extension entirely and use normal lighting and shadows. - Added `CreateNavCollision` property to `Cesium3DTileset`. When enabled, `CreateNavCollision` is called on the static meshes created for tiles. diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index e3a8226ba..26b8b2d14 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -8,16 +8,18 @@ #include "Cesium3DTilesSelection/Tile.h" #include "Cesium3DTilesSelection/TilesetLoadFailureDetails.h" #include "Cesium3DTilesSelection/TilesetOptions.h" +#include "Cesium3DTilesSelection/TilesetSharedAssetSystem.h" #include "Cesium3DTilesetLoadFailureDetails.h" #include "Cesium3DTilesetRoot.h" #include "CesiumActors.h" +#include "CesiumAsync/SharedAssetDepot.h" #include "CesiumBoundingVolumeComponent.h" #include "CesiumCamera.h" #include "CesiumCameraManager.h" #include "CesiumCommon.h" #include "CesiumCustomVersion.h" #include "CesiumGeospatial/GlobeTransforms.h" -#include "CesiumGltf/ImageCesium.h" +#include "CesiumGltf/ImageAsset.h" #include "CesiumGltf/Ktx2TranscodeTargets.h" #include "CesiumGltfComponent.h" #include "CesiumGltfPointsSceneProxyUpdater.h" @@ -40,6 +42,7 @@ #include "Engine/TextureRenderTarget2D.h" #include "Engine/World.h" #include "EngineUtils.h" +#include "ExtensionImageAssetUnreal.h" #include "GameFramework/PlayerController.h" #include "Kismet/GameplayStatics.h" #include "LevelSequenceActor.h" @@ -781,16 +784,14 @@ class UnrealResourcePreparer Cesium3DTilesSelection::TileLoadResult&& tileLoadResult, const glm::dmat4& transform, const std::any& rendererOptions) override { - CesiumGltf::Model* pModel = - std::get_if(&tileLoadResult.contentKind); - if (!pModel) + CreateGltfOptions::CreateModelOptions options(std::move(tileLoadResult)); + if (!options.pModel) { return asyncSystem.createResolvedFuture( Cesium3DTilesSelection::TileLoadResultAndRenderResources{ - std::move(tileLoadResult), + std::move(options.tileLoadResult), nullptr}); + } - CreateGltfOptions::CreateModelOptions options; - options.pModel = pModel; options.alwaysIncludeTangents = this->_pActor->GetAlwaysIncludeTangents(); options.createPhysicsMeshes = this->_pActor->GetCreatePhysicsMeshes(); @@ -807,16 +808,21 @@ class UnrealResourcePreparer const CesiumGeospatial::Ellipsoid& ellipsoid = tileLoadResult.ellipsoid; - TUniquePtr pHalf = - UCesiumGltfComponent::CreateOffGameThread( + CesiumAsync::Future + pHalfFuture = UCesiumGltfComponent::CreateOffGameThread( + asyncSystem, transform, - options, + std::move(options), ellipsoid); - return asyncSystem.createResolvedFuture( - Cesium3DTilesSelection::TileLoadResultAndRenderResources{ - std::move(tileLoadResult), - pHalf.Release()}); + return MoveTemp(pHalfFuture) + .thenImmediately( + [](UCesiumGltfComponent::CreateOffGameThreadResult&& result) + -> Cesium3DTilesSelection::TileLoadResultAndRenderResources { + return Cesium3DTilesSelection::TileLoadResultAndRenderResources{ + std::move(result.TileLoadResult), + result.HalfConstructed.Release()}; + }); } virtual void* prepareInMainThread( @@ -862,7 +868,7 @@ class UnrealResourcePreparer } virtual void* prepareRasterInLoadThread( - CesiumGltf::ImageCesium& image, + CesiumGltf::ImageAsset& image, const std::any& rendererOptions) override { auto ppOptions = std::any_cast(&rendererOptions); @@ -875,7 +881,7 @@ class UnrealResourcePreparer if (pOptions->useMipmaps) { std::optional errorMessage = - CesiumGltfReader::GltfReader::generateMipMaps(image); + CesiumGltfReader::ImageDecoder::generateMipMaps(image); if (errorMessage) { UE_LOG( LogCesium, @@ -885,6 +891,21 @@ class UnrealResourcePreparer } } + // TODO: sRGB should probably be configurable on the raster overlay. + bool sRGB = true; + + const ExtensionImageAssetUnreal& extension = + ExtensionImageAssetUnreal::getOrCreate( + CesiumAsync::AsyncSystem(nullptr), // TODO + image, + sRGB, + pOptions->useMipmaps, + std::nullopt); + + // Because raster overlay images are never shared (at least currently!), the + // future should already be resolved by the time we get here. + check(extension.getFuture().isReady()); + auto texture = CesiumTextureUtility::loadTextureAnyThreadPart( image, TextureAddress::TA_Clamp, @@ -892,10 +913,9 @@ class UnrealResourcePreparer pOptions->filter, pOptions->useMipmaps, pOptions->group, - // TODO: sRGB should probably be configurable on the raster overlay. - true, - std::nullopt, - nullptr); + sRGB, + std::nullopt); + return texture.Release(); } @@ -954,7 +974,7 @@ class UnrealResourcePreparer const Cesium3DTilesSelection::TileContent& content = tile.getContent(); const Cesium3DTilesSelection::TileRenderContent* pRenderContent = content.getRenderContent(); - if (pRenderContent) { + if (pMainThreadRendererResources != nullptr && pRenderContent != nullptr) { UCesiumGltfComponent* pGltfContent = reinterpret_cast( pRenderContent->getRenderResources()); @@ -984,7 +1004,7 @@ class UnrealResourcePreparer UCesiumGltfComponent* pGltfContent = reinterpret_cast( pRenderContent->getRenderResources()); - if (pGltfContent) { + if (pMainThreadRendererResources != nullptr && pGltfContent != nullptr) { pGltfContent->DetachRasterTile( tile, rasterTile, @@ -1941,7 +1961,38 @@ void ACesium3DTileset::updateLastViewUpdateResultState( const Cesium3DTilesSelection::ViewUpdateResult& result) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateLastViewUpdateResultState) - if (!this->LogSelectionStats) { + if (this->DrawTileInfo) { + const UWorld* World = GetWorld(); + check(World); + + const TSoftObjectPtr Georeference = + ResolveGeoreference(); + check(Georeference); + + for (Cesium3DTilesSelection::Tile* tile : result.tilesToRenderThisFrame) { + + CesiumGeometry::OrientedBoundingBox obb = + Cesium3DTilesSelection::getOrientedBoundingBoxFromBoundingVolume( + tile->getBoundingVolume(), + Georeference->GetEllipsoid()->GetNativeEllipsoid()); + + FVector unrealCenter = + Georeference->TransformEarthCenteredEarthFixedPositionToUnreal( + VecMath::createVector(obb.getCenter())); + + FString text = FString::Printf( + TEXT("ID %s (%p)"), + UTF8_TO_TCHAR( + Cesium3DTilesSelection::TileIdUtilities::createTileIdString( + tile->getTileID()) + .c_str()), + tile); + + DrawDebugString(World, unrealCenter, text, nullptr, FColor::Red, 0, true); + } + } + + if (!this->LogSelectionStats && !this->LogSharedAssetStats) { return; } @@ -1972,24 +2023,40 @@ void ACesium3DTileset::updateLastViewUpdateResultState( result.tilesWaitingForOcclusionResults; this->_lastMaxDepthVisited = result.maxDepthVisited; - UE_LOG( - LogCesium, - Display, - TEXT( - "%s: %d ms, Visited %d, Culled Visited %d, Rendered %d, Culled %d, Occluded %d, Waiting For Occlusion Results %d, Max Depth Visited: %d, Loading-Worker %d, Loading-Main %d, Loaded tiles %g%%"), - *this->GetName(), - (std::chrono::high_resolution_clock::now() - this->_startTime).count() / - 1000000, - result.tilesVisited, - result.culledTilesVisited, - result.tilesToRenderThisFrame.size(), - result.tilesCulled, - result.tilesOccluded, - result.tilesWaitingForOcclusionResults, - result.maxDepthVisited, - result.workerThreadTileLoadQueueLength, - result.mainThreadTileLoadQueueLength, - this->LoadProgress); + if (this->LogSelectionStats) { + UE_LOG( + LogCesium, + Display, + TEXT( + "%s: %d ms, Visited %d, Culled Visited %d, Rendered %d, Culled %d, Occluded %d, Waiting For Occlusion Results %d, Max Depth Visited: %d, Loading-Worker %d, Loading-Main %d, Loaded tiles %g%%"), + *this->GetName(), + (std::chrono::high_resolution_clock::now() - this->_startTime) + .count() / + 1000000, + result.tilesVisited, + result.culledTilesVisited, + result.tilesToRenderThisFrame.size(), + result.tilesCulled, + result.tilesOccluded, + result.tilesWaitingForOcclusionResults, + result.maxDepthVisited, + result.workerThreadTileLoadQueueLength, + result.mainThreadTileLoadQueueLength, + this->LoadProgress); + } + + if (this->LogSharedAssetStats && this->_pTileset) { + const Cesium3DTilesSelection::TilesetSharedAssetSystem::ImageDepot& + imageDepot = *this->_pTileset->getSharedAssetSystem().pImage; + UE_LOG( + LogCesium, + Display, + TEXT( + "Images shared asset depot: %d distinct assets, %d inactive assets pending deletion (%d bytes)"), + imageDepot.getAssetCount(), + imageDepot.getInactiveAssetCount(), + imageDepot.getInactiveAssetTotalSizeBytes()); + } } } diff --git a/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.cpp b/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.cpp index 7396acc97..9528d8734 100644 --- a/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.cpp +++ b/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.cpp @@ -99,7 +99,7 @@ encodeFeatureIdAttribute(const FCesiumFeatureIdAttribute& attribute) { std::optional encodeFeatureIdTexture( const FCesiumFeatureIdTexture& texture, - TMap>& + TMap>& featureIdTextureMap) { const ECesiumFeatureIdTextureStatus status = UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus( @@ -114,7 +114,7 @@ std::optional encodeFeatureIdTexture( const CesiumGltf::FeatureIdTextureView& featureIdTextureView = texture.getFeatureIdTextureView(); - const CesiumGltf::ImageCesium* pFeatureIdImage = + const CesiumGltf::ImageAsset* pFeatureIdImage = featureIdTextureView.getImage(); TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodeFeatureIdTexture) @@ -143,10 +143,11 @@ std::optional encodeFeatureIdTexture( } // Copy the image, so that we can keep a copy of it in the glTF. - CesiumGltf::ImageCesium imageCopy(*pFeatureIdImage); + CesiumUtility::IntrusivePointer pImageCopy = + new CesiumGltf::ImageAsset(*pFeatureIdImage); encodedFeatureIdTexture.pTexture = MakeShared(std::move(*loadTextureAnyThreadPart( - imageCopy, + *pImageCopy, addressX, addressY, TextureFilter::TF_Nearest, @@ -154,8 +155,7 @@ std::optional encodeFeatureIdTexture( TEXTUREGROUP_8BitData, false, // TODO: currently this is always the case, but doesn't have to be - EPixelFormat::PF_R8G8B8A8_UINT, - nullptr))); + EPixelFormat::PF_R8G8B8A8_UINT))); featureIdTextureMap.Emplace( pFeatureIdImage, encodedFeatureIdTexture.pTexture); @@ -177,7 +177,7 @@ EncodedPrimitiveFeatures encodePrimitiveFeaturesAnyThreadPart( // Not all feature ID sets are necessarily textures, but reserve the max // amount just in case. - TMap> + TMap> featureIdTextureMap; featureIdTextureMap.Reserve(featureIDSetDescriptions.Num()); @@ -510,11 +510,12 @@ EncodedPropertyTable encodePropertyTableAnyThreadPart( ? floorSqrtFeatureCount : (floorSqrtFeatureCount + 1); - CesiumGltf::ImageCesium image; - image.width = image.height = textureDimension; - image.bytesPerChannel = encodedFormat.bytesPerChannel; - image.channels = encodedFormat.channels; - image.pixelData.resize( + CesiumUtility::IntrusivePointer pImage = + new CesiumGltf::ImageAsset(); + pImage->width = pImage->height = textureDimension; + pImage->bytesPerChannel = encodedFormat.bytesPerChannel; + pImage->channels = encodedFormat.channels; + pImage->pixelData.resize( textureDimension * textureDimension * encodedFormat.bytesPerChannel * encodedFormat.channels); @@ -523,26 +524,25 @@ EncodedPropertyTable encodePropertyTableAnyThreadPart( CesiumEncodedMetadataParseColorFromString::encode( *pDescription, property, - gsl::span(image.pixelData), + gsl::span(pImage->pixelData), encodedFormat.bytesPerChannel * encodedFormat.channels); } else /* info.Conversion == ECesiumEncodedMetadataConversion::Coerce */ { CesiumEncodedMetadataCoerce::encode( *pDescription, property, - gsl::span(image.pixelData), + gsl::span(pImage->pixelData), encodedFormat.bytesPerChannel * encodedFormat.channels); } encodedProperty.pTexture = loadTextureAnyThreadPart( - image, + *pImage, TextureAddress::TA_Clamp, TextureAddress::TA_Clamp, TextureFilter::TF_Nearest, false, TEXTUREGROUP_8BitData, false, - encodedFormat.format, - nullptr); + encodedFormat.format); } if (pDescription->PropertyDetails.bHasOffset) { @@ -592,7 +592,7 @@ EncodedPropertyTable encodePropertyTableAnyThreadPart( EncodedPropertyTexture encodePropertyTextureAnyThreadPart( const FCesiumPropertyTextureDescription& propertyTextureDescription, const FCesiumPropertyTexture& propertyTexture, - TMap>& + TMap>& propertyTexturePropertyMap) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::EncodePropertyTexture) @@ -641,7 +641,7 @@ EncodedPropertyTexture encodePropertyTextureAnyThreadPart( encodedProperty.channels[i] = channels[i]; } - const CesiumGltf::ImageCesium* pImage = property.getImage(); + const CesiumGltf::ImageAsset* pImage = property.getImage(); TWeakPtr* pMappedUnrealImageIt = propertyTexturePropertyMap.Find(pImage); @@ -658,10 +658,11 @@ EncodedPropertyTexture encodePropertyTextureAnyThreadPart( } // Copy the image, so that we can keep a copy of it in the glTF. - CesiumGltf::ImageCesium imageCopy(*pImage); + CesiumUtility::IntrusivePointer pImageCopy = + new CesiumGltf::ImageAsset(*pImage); encodedProperty.pTexture = MakeShared(std::move(*loadTextureAnyThreadPart( - imageCopy, + *pImageCopy, addressX, addressY, // TODO: account for texture filter @@ -671,8 +672,7 @@ EncodedPropertyTexture encodePropertyTextureAnyThreadPart( false, // This assumes that the texture's image only contains one byte // per channel. - EPixelFormat::PF_R8G8B8A8_UINT, - nullptr))); + EPixelFormat::PF_R8G8B8A8_UINT))); propertyTexturePropertyMap.Emplace(pImage, encodedProperty.pTexture); } }; @@ -772,7 +772,7 @@ EncodedModelMetadata encodeModelMetadataAnyThreadPart( UCesiumModelMetadataBlueprintLibrary::GetPropertyTextures(metadata); result.propertyTextures.Reserve(propertyTextures.Num()); - TMap> + TMap> propertyTexturePropertyMap; propertyTexturePropertyMap.Reserve(propertyTextures.Num()); diff --git a/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.h b/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.h index 31ec20866..0bb838505 100644 --- a/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.h +++ b/Source/CesiumRuntime/Private/CesiumEncodedFeaturesMetadata.h @@ -476,7 +476,7 @@ EncodedPropertyTexture encodePropertyTextureAnyThreadPart( const FCesiumPropertyTextureDescription& propertyTextureDescription, const FCesiumPropertyTexture& propertyTexture, TMap< - const CesiumGltf::ImageCesium*, + const CesiumGltf::ImageAsset*, TWeakPtr>& propertyTexturePropertyMap); diff --git a/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp b/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp index a9d989dd8..28f6fa3d1 100644 --- a/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp +++ b/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.cpp @@ -205,18 +205,20 @@ EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( ? floorSqrtFeatureCount : (floorSqrtFeatureCount + 1); - CesiumGltf::ImageCesium image; - image.bytesPerChannel = encodedFormat.bytesPerChannel; - image.channels = encodedFormat.channels; - image.compressedPixelFormat = CesiumGltf::GpuCompressedPixelFormat::NONE; - image.height = image.width = ceilSqrtFeatureCount; - image.pixelData.resize(size_t( - image.width * image.height * image.channels * image.bytesPerChannel)); + CesiumUtility::IntrusivePointer pImage = + new CesiumGltf::ImageAsset(); + pImage->bytesPerChannel = encodedFormat.bytesPerChannel; + pImage->channels = encodedFormat.channels; + pImage->compressedPixelFormat = CesiumGltf::GpuCompressedPixelFormat::NONE; + pImage->height = pImage->width = ceilSqrtFeatureCount; + pImage->pixelData.resize(size_t( + pImage->width * pImage->height * pImage->channels * + pImage->bytesPerChannel)); if (isArray) { switch (gpuType) { case ECesiumMetadataPackedGpuType_DEPRECATED::Uint8_DEPRECATED: { - uint8* pWritePos = reinterpret_cast(image.pixelData.data()); + uint8* pWritePos = reinterpret_cast(pImage->pixelData.data()); int64_t pixelSize = encodedFormat.channels * encodedFormat.bytesPerChannel; for (int64 i = 0; i < featureCount; ++i) { @@ -232,7 +234,7 @@ EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( } } break; case ECesiumMetadataPackedGpuType_DEPRECATED::Float_DEPRECATED: { - uint8* pWritePos = reinterpret_cast(image.pixelData.data()); + uint8* pWritePos = reinterpret_cast(pImage->pixelData.data()); int64_t pixelSize = encodedFormat.channels * encodedFormat.bytesPerChannel; for (int64 i = 0; i < featureCount; ++i) { @@ -256,7 +258,7 @@ EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( } else { switch (gpuType) { case ECesiumMetadataPackedGpuType_DEPRECATED::Uint8_DEPRECATED: { - uint8* pWritePos = reinterpret_cast(image.pixelData.data()); + uint8* pWritePos = reinterpret_cast(pImage->pixelData.data()); for (int64 i = 0; i < featureCount; ++i) { *pWritePos = UCesiumPropertyTablePropertyBlueprintLibrary::GetByte( property, @@ -265,7 +267,7 @@ EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( } } break; case ECesiumMetadataPackedGpuType_DEPRECATED::Float_DEPRECATED: { - float* pWritePosF = reinterpret_cast(image.pixelData.data()); + float* pWritePosF = reinterpret_cast(pImage->pixelData.data()); for (int64 i = 0; i < featureCount; ++i) { *pWritePosF = UCesiumPropertyTablePropertyBlueprintLibrary::GetFloat( property, @@ -277,22 +279,21 @@ EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( } encodedProperty.pTexture = loadTextureAnyThreadPart( - image, + *pImage, TextureAddress::TA_Clamp, TextureAddress::TA_Clamp, TextureFilter::TF_Nearest, false, TEXTUREGROUP_8BitData, false, - encodedFormat.format, - nullptr); + encodedFormat.format); } return encodedFeatureTable; } EncodedFeatureTexture encodeFeatureTextureAnyThreadPart( - TMap>& + TMap>& featureTexturePropertyMap, const FFeatureTextureDescription& featureTextureDescription, const FString& featureTextureName, @@ -321,7 +322,7 @@ EncodedFeatureTexture encodeFeatureTextureAnyThreadPart( const FCesiumPropertyTextureProperty& featureTextureProperty = propertyIt.Value; - const CesiumGltf::ImageCesium* pImage = featureTextureProperty.getImage(); + const CesiumGltf::ImageAsset* pImage = featureTextureProperty.getImage(); if (!pImage) { UE_LOG( @@ -410,10 +411,11 @@ EncodedFeatureTexture encodeFeatureTextureAnyThreadPart( if (pMappedUnrealImageIt) { encodedFeatureTextureProperty.pTexture = pMappedUnrealImageIt->Pin(); } else { - CesiumGltf::ImageCesium imageCopy(*pImage); + CesiumUtility::IntrusivePointer pImageCopy = + new CesiumGltf::ImageAsset(*pImage); encodedFeatureTextureProperty.pTexture = MakeShared(std::move(*loadTextureAnyThreadPart( - imageCopy, + *pImageCopy, TextureAddress::TA_Clamp, TextureAddress::TA_Clamp, TextureFilter::TF_Nearest, @@ -424,8 +426,7 @@ EncodedFeatureTexture encodeFeatureTextureAnyThreadPart( // R8G8B8A8 form, but this does not necessarily need to be the // case in the future. isNormalized ? EPixelFormat::PF_R8G8B8A8 - : EPixelFormat::PF_R8G8B8A8_UINT, - nullptr))); + : EPixelFormat::PF_R8G8B8A8_UINT))); featureTexturePropertyMap.Emplace( pImage, encodedFeatureTextureProperty.pTexture); @@ -461,7 +462,7 @@ EncodedMetadataPrimitive encodeMetadataPrimitiveAnyThreadPart( } } - TMap> + TMap> featureIdTextureMap; featureIdTextureMap.Reserve(featureIdTextures.Num()); @@ -489,7 +490,7 @@ EncodedMetadataPrimitive encodeMetadataPrimitiveAnyThreadPart( if (pFeatureIdTexture) { const CesiumGltf::FeatureIdTextureView& featureIdTextureView = pFeatureIdTexture->getFeatureIdTextureView(); - const CesiumGltf::ImageCesium* pFeatureIdImage = + const CesiumGltf::ImageAsset* pFeatureIdImage = featureIdTextureView.getImage(); if (!pFeatureIdImage) { @@ -516,10 +517,11 @@ EncodedMetadataPrimitive encodeMetadataPrimitiveAnyThreadPart( if (pMappedUnrealImageIt) { encodedFeatureIdTexture.pTexture = pMappedUnrealImageIt->Pin(); } else { - CesiumGltf::ImageCesium imageCopy(*pFeatureIdImage); + CesiumUtility::IntrusivePointer pImageCopy = + new CesiumGltf::ImageAsset(*pFeatureIdImage); encodedFeatureIdTexture.pTexture = MakeShared( std::move(*loadTextureAnyThreadPart( - imageCopy, + *pImageCopy, TextureAddress::TA_Clamp, TextureAddress::TA_Clamp, TextureFilter::TF_Nearest, @@ -528,8 +530,7 @@ EncodedMetadataPrimitive encodeMetadataPrimitiveAnyThreadPart( false, // TODO: currently this is always the case, but doesn't have // to be - EPixelFormat::PF_R8G8B8A8_UINT, - nullptr))); + EPixelFormat::PF_R8G8B8A8_UINT))); featureIdTextureMap.Emplace( pFeatureIdImage, encodedFeatureIdTexture.pTexture); @@ -598,7 +599,7 @@ EncodedMetadata encodeMetadataAnyThreadPart( const TMap& featureTextures = UCesiumModelMetadataBlueprintLibrary::GetFeatureTextures(metadata); result.encodedFeatureTextures.Reserve(featureTextures.Num()); - TMap> + TMap> featureTexturePropertyMap; featureTexturePropertyMap.Reserve(featureTextures.Num()); for (const auto& featureTextureIt : featureTextures) { diff --git a/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h b/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h index 070f2b00c..84c4b3d23 100644 --- a/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h +++ b/Source/CesiumRuntime/Private/CesiumEncodedMetadataUtility.h @@ -106,7 +106,7 @@ EncodedMetadataFeatureTable encodeMetadataFeatureTableAnyThreadPart( EncodedFeatureTexture encodeFeatureTextureAnyThreadPart( TMap< - const CesiumGltf::ImageCesium*, + const CesiumGltf::ImageAsset*, TWeakPtr>& featureTexturePropertyMap, const FFeatureTextureDescription& featureTextureDescription, diff --git a/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp b/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp index 4b0b07d1c..919f6f47a 100644 --- a/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp +++ b/Source/CesiumRuntime/Private/CesiumFeatureIdAttribute.cpp @@ -4,11 +4,9 @@ #include #include -using namespace CesiumGltf; - FCesiumFeatureIdAttribute::FCesiumFeatureIdAttribute( - const Model& Model, - const MeshPrimitive& Primitive, + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, const int64 FeatureIDAttribute, const FString& PropertyTableName) : _status(ECesiumFeatureIdAttributeStatus::ErrorInvalidAttribute), @@ -23,9 +21,9 @@ FCesiumFeatureIdAttribute::FCesiumFeatureIdAttribute( return; } - const Accessor* accessor = - Model.getSafe(&Model.accessors, featureID->second); - if (!accessor || accessor->type != Accessor::Type::SCALAR) { + const CesiumGltf::Accessor* accessor = + Model.getSafe(&Model.accessors, featureID->second); + if (!accessor || accessor->type != CesiumGltf::Accessor::Type::SCALAR) { this->_status = ECesiumFeatureIdAttributeStatus::ErrorInvalidAccessor; return; } @@ -37,7 +35,7 @@ FCesiumFeatureIdAttribute::FCesiumFeatureIdAttribute( this->_status = std::visit( [](auto view) { - if (view.status() != AccessorViewStatus::Valid) { + if (view.status() != CesiumGltf::AccessorViewStatus::Valid) { return ECesiumFeatureIdAttributeStatus::ErrorInvalidAccessor; } @@ -59,13 +57,15 @@ UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureIDAttributeStatus( int64 UCesiumFeatureIdAttributeBlueprintLibrary::GetVertexCount( UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute) { - return std::visit(CountFromAccessor{}, FeatureIDAttribute._featureIdAccessor); + return std::visit( + CesiumGltf::CountFromAccessor{}, + FeatureIDAttribute._featureIdAccessor); } int64 UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureIDForVertex( UPARAM(ref) const FCesiumFeatureIdAttribute& FeatureIDAttribute, int64 VertexIndex) { return std::visit( - FeatureIdFromAccessor{VertexIndex}, + CesiumGltf::FeatureIdFromAccessor{VertexIndex}, FeatureIDAttribute._featureIdAccessor); } diff --git a/Source/CesiumRuntime/Private/CesiumFeatureIdSet.cpp b/Source/CesiumRuntime/Private/CesiumFeatureIdSet.cpp index 4adc304ab..6f846a6c6 100644 --- a/Source/CesiumRuntime/Private/CesiumFeatureIdSet.cpp +++ b/Source/CesiumRuntime/Private/CesiumFeatureIdSet.cpp @@ -7,15 +7,13 @@ #include "CesiumGltf/Model.h" #include "CesiumGltfPrimitiveComponent.h" -using namespace CesiumGltf; - static FCesiumFeatureIdAttribute EmptyFeatureIDAttribute; static FCesiumFeatureIdTexture EmptyFeatureIDTexture; FCesiumFeatureIdSet::FCesiumFeatureIdSet( - const Model& InModel, - const MeshPrimitive& Primitive, - const FeatureId& FeatureID) + const CesiumGltf::Model& InModel, + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::FeatureId& FeatureID) : _featureID(), _featureIDSetType(ECesiumFeatureIdSetType::None), _featureCount(FeatureID.featureCount), @@ -25,12 +23,13 @@ FCesiumFeatureIdSet::FCesiumFeatureIdSet( FString propertyTableName; // For backwards compatibility with GetFeatureTableName. - const ExtensionModelExtStructuralMetadata* pMetadata = - InModel.getExtension(); + const CesiumGltf::ExtensionModelExtStructuralMetadata* pMetadata = + InModel.getExtension(); if (pMetadata && _propertyTableIndex >= 0) { size_t index = static_cast(_propertyTableIndex); if (index < pMetadata->propertyTables.size()) { - const PropertyTable& propertyTable = pMetadata->propertyTables[index]; + const CesiumGltf::PropertyTable& propertyTable = + pMetadata->propertyTables[index]; std::string name = propertyTable.name.value_or(""); propertyTableName = FString(name.c_str()); } diff --git a/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp b/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp index 7b5125dcb..8ee2edb37 100644 --- a/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp +++ b/Source/CesiumRuntime/Private/CesiumFeatureIdTexture.cpp @@ -8,19 +8,17 @@ #include -using namespace CesiumGltf; - FCesiumFeatureIdTexture::FCesiumFeatureIdTexture( - const Model& Model, - const MeshPrimitive& Primitive, - const FeatureIdTexture& FeatureIdTexture, + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::FeatureIdTexture& FeatureIdTexture, const FString& PropertyTableName) : _status(ECesiumFeatureIdTextureStatus::ErrorInvalidTexture), _featureIdTextureView(), _texCoordAccessor(), _textureCoordinateSetIndex(FeatureIdTexture.texCoord), _propertyTableName(PropertyTableName) { - TextureViewOptions options; + CesiumGltf::TextureViewOptions options; options.applyKhrTextureTransformExtension = true; if (FeatureIdTexture.extras.find("makeImageCopy") != @@ -30,13 +28,13 @@ FCesiumFeatureIdTexture::FCesiumFeatureIdTexture( } this->_featureIdTextureView = - FeatureIdTextureView(Model, FeatureIdTexture, options); + CesiumGltf::FeatureIdTextureView(Model, FeatureIdTexture, options); switch (_featureIdTextureView.status()) { - case FeatureIdTextureViewStatus::Valid: + case CesiumGltf::FeatureIdTextureViewStatus::Valid: this->_status = ECesiumFeatureIdTextureStatus::Valid; break; - case FeatureIdTextureViewStatus::ErrorInvalidChannels: + case CesiumGltf::FeatureIdTextureViewStatus::ErrorInvalidChannels: this->_status = ECesiumFeatureIdTextureStatus::ErrorInvalidTextureAccess; return; default: diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp index 59b555bde..b2781a59a 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.cpp @@ -8,6 +8,7 @@ #include "CesiumFeatureIdSet.h" #include "CesiumGltfPointsComponent.h" #include "CesiumGltfPrimitiveComponent.h" +#include "CesiumGltfTextures.h" #include "CesiumMaterialUserData.h" #include "CesiumRasterOverlays.h" #include "CesiumRuntime.h" @@ -66,7 +67,6 @@ #include "ScopedTransaction.h" #endif -using namespace CesiumGltf; using namespace CesiumTextureUtility; using namespace CreateGltfOptions; using namespace LoadGltfResult; @@ -98,12 +98,13 @@ template struct IsAccessorView; template struct IsAccessorView : std::false_type {}; -template struct IsAccessorView> : std::true_type {}; +template +struct IsAccessorView> : std::true_type {}; template static uint32_t updateTextureCoordinates( - const Model& model, - const MeshPrimitive& primitive, + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, bool duplicateVertices, TArray& vertices, const TArray& indices, @@ -124,8 +125,8 @@ static uint32_t updateTextureCoordinates( } uint32_t updateTextureCoordinates( - const Model& model, - const MeshPrimitive& primitive, + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, bool duplicateVertices, TArray& vertices, const TArray& indices, @@ -147,8 +148,8 @@ uint32_t updateTextureCoordinates( size_t textureCoordinateIndex = gltfToUnrealTexCoordMap.size(); gltfToUnrealTexCoordMap[uvAccessorID] = textureCoordinateIndex; - AccessorView uvAccessor(model, uvAccessorID); - if (uvAccessor.status() != AccessorViewStatus::Valid) { + CesiumGltf::AccessorView uvAccessor(model, uvAccessorID); + if (uvAccessor.status() != CesiumGltf::AccessorViewStatus::Valid) { return 0; } @@ -323,18 +324,21 @@ BuildChaosTriangleMeshes( const TArray& vertexData, const TArray& indices); -static const Material defaultMaterial; -static const MaterialPBRMetallicRoughness defaultPbrMetallicRoughness; +static const CesiumGltf::Material defaultMaterial; +static const CesiumGltf::MaterialPBRMetallicRoughness + defaultPbrMetallicRoughness; struct ColorVisitor { bool duplicateVertices; TArray& StaticMeshBuildVertices; const TArray& indices; - bool operator()(AccessorView&& invalidView) { return false; } + bool operator()(CesiumGltf::AccessorView&& invalidView) { + return false; + } template bool operator()(TColorView&& colorView) { - if (colorView.status() != AccessorViewStatus::Valid) { + if (colorView.status() != CesiumGltf::AccessorViewStatus::Valid) { return false; } @@ -365,8 +369,9 @@ struct ColorVisitor { } template - static bool - convertColor(const AccessorTypes::VEC3& color, FColor& out) { + static bool convertColor( + const CesiumGltf::AccessorTypes::VEC3& color, + FColor& out) { out.A = 255; return convertElement(color.value[0], out.R) && convertElement(color.value[1], out.G) && @@ -374,8 +379,9 @@ struct ColorVisitor { } template - static bool - convertColor(const AccessorTypes::VEC4& color, FColor& out) { + static bool convertColor( + const CesiumGltf::AccessorTypes::VEC4& color, + FColor& out) { return convertElement(color.value[0], out.R) && convertElement(color.value[1], out.G) && convertElement(color.value[2], out.B) && @@ -410,36 +416,30 @@ struct ColorVisitor { template static TUniquePtr loadTexture( CesiumGltf::Model& model, - const std::optional& gltfTexture, - bool sRGB, - std::vector& textureResources) { - if (!gltfTexture || gltfTexture.value().index < 0 || - gltfTexture.value().index >= model.textures.size()) { - if (gltfTexture && gltfTexture.value().index >= 0) { + const std::optional& gltfTextureInfo, + bool sRGB) { + if (!gltfTextureInfo || gltfTextureInfo.value().index < 0 || + gltfTextureInfo.value().index >= model.textures.size()) { + if (gltfTextureInfo && gltfTextureInfo.value().index >= 0) { UE_LOG( LogCesium, Warning, TEXT("Texture index must be less than %d, but is %d"), model.textures.size(), - gltfTexture.value().index); + gltfTextureInfo.value().index); } return nullptr; } - int32_t textureIndex = gltfTexture.value().index; + int32_t textureIndex = gltfTextureInfo.value().index; CesiumGltf::Texture& texture = model.textures[textureIndex]; - return loadTextureFromModelAnyThreadPart( - model, - texture, - sRGB, - textureResources); + return loadTextureFromModelAnyThreadPart(model, texture, sRGB); } static void applyWaterMask( - Model& model, - const MeshPrimitive& primitive, - LoadPrimitiveResult& primitiveResult, - std::vector& textureResources) { + CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, + LoadPrimitiveResult& primitiveResult) { // Initialize water mask if needed. auto onlyWaterIt = primitive.extras.find("OnlyWater"); auto onlyLandIt = primitive.extras.find("OnlyLand"); @@ -457,15 +457,12 @@ static void applyWaterMask( waterMaskTextureIdIt->second.isInt64()) { int32_t waterMaskTextureId = static_cast( waterMaskTextureIdIt->second.getInt64OrDefault(-1)); - TextureInfo waterMaskInfo; + CesiumGltf::TextureInfo waterMaskInfo; waterMaskInfo.index = waterMaskTextureId; if (waterMaskTextureId >= 0 && waterMaskTextureId < model.textures.size()) { - primitiveResult.waterMaskTexture = loadTexture( - model, - std::make_optional(waterMaskInfo), - false, - textureResources); + primitiveResult.waterMaskTexture = + loadTexture(model, std::make_optional(waterMaskInfo), false); } } } @@ -512,7 +509,7 @@ static bool hasMaterialTextureConflicts( const CesiumGltf::Material& material, int32_t imageIndex) { if (material.pbrMetallicRoughness) { - const std::optional& maybeBaseColorTexture = + const std::optional& maybeBaseColorTexture = material.pbrMetallicRoughness->baseColorTexture; if (maybeBaseColorTexture && textureUsesSpecifiedImage( model, @@ -521,8 +518,9 @@ static bool hasMaterialTextureConflicts( return true; } - const std::optional& maybeMetallicRoughnessTexture = - material.pbrMetallicRoughness->metallicRoughnessTexture; + const std::optional& + maybeMetallicRoughnessTexture = + material.pbrMetallicRoughness->metallicRoughnessTexture; if (maybeMetallicRoughnessTexture && textureUsesSpecifiedImage( model, @@ -562,8 +560,8 @@ static bool hasMaterialTextureConflicts( * without requiring UVs in the physics bodies. */ static void createTexCoordAccessorsForFeaturesMetadata( - const Model& model, - const MeshPrimitive& primitive, + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, const FCesiumPrimitiveFeatures& primitiveFeatures, const FCesiumPrimitiveMetadata& primitiveMetadata, const FCesiumModelMetadata& modelMetadata, @@ -634,8 +632,8 @@ static void createTexCoordAccessorsForFeaturesMetadata( * coordinates for attribute and implicit feature ID sets. */ static void updateTextureCoordinatesForFeaturesMetadata( - const Model& model, - const MeshPrimitive& primitive, + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, bool duplicateVertices, TArray& vertices, const TArray& indices, @@ -797,8 +795,8 @@ static void updateTextureCoordinatesForFeaturesMetadata( PRAGMA_DISABLE_DEPRECATION_WARNINGS static void updateTextureCoordinatesForMetadata_DEPRECATED( - const Model& model, - const MeshPrimitive& primitive, + const CesiumGltf::Model& model, + const CesiumGltf::MeshPrimitive& primitive, bool duplicateVertices, TArray& vertices, const TArray& indices, @@ -851,8 +849,8 @@ static void updateTextureCoordinatesForMetadata_DEPRECATED( } } - const ExtensionExtMeshFeatures* pFeatures = - primitive.getExtension(); + const CesiumGltf::ExtensionExtMeshFeatures* pFeatures = + primitive.getExtension(); if (pFeatures) { for (const CesiumEncodedMetadataUtility::EncodedFeatureIdAttribute& @@ -921,11 +919,10 @@ static void loadPrimitiveFeaturesMetadata( CesiumGltf::MeshPrimitive& primitive, bool duplicateVertices, TArray& vertices, - const TArray& indices, - std::vector& textureResources) { + const TArray& indices) { - ExtensionExtMeshFeatures* pFeatures = - primitive.getExtension(); + CesiumGltf::ExtensionExtMeshFeatures* pFeatures = + primitive.getExtension(); if (pFeatures) { int32_t materialIndex = primitive.material; @@ -963,8 +960,9 @@ static void loadPrimitiveFeaturesMetadata( } } - const ExtensionMeshPrimitiveExtStructuralMetadata* pMetadata = - primitive.getExtension(); + const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata* pMetadata = + primitive.getExtension< + CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata>(); const CreateGltfOptions::CreateModelOptions* pModelOptions = options.pMeshOptions->pNodeOptions->pModelOptions; @@ -1138,21 +1136,22 @@ static void loadPrimitive( LoadPrimitiveResult& primitiveResult, const glm::dmat4x4& transform, const CreatePrimitiveOptions& options, - const Accessor& positionAccessor, - const AccessorView& positionView, + const CesiumGltf::Accessor& positionAccessor, + const CesiumGltf::AccessorView& positionView, const TIndexAccessor& indicesView, - std::vector& textureResources, const CesiumGeospatial::Ellipsoid& ellipsoid) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadPrimitive) - Model& model = *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; - Mesh& mesh = *options.pMeshOptions->pMesh; - MeshPrimitive& primitive = *options.pPrimitive; + CesiumGltf::Model& model = + *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; + CesiumGltf::Mesh& mesh = model.meshes[options.pMeshOptions->meshIndex]; + CesiumGltf::MeshPrimitive& primitive = + mesh.primitives[options.primitiveIndex]; - if (primitive.mode != MeshPrimitive::Mode::TRIANGLES && - primitive.mode != MeshPrimitive::Mode::TRIANGLE_STRIP && - primitive.mode != MeshPrimitive::Mode::POINTS) { + if (primitive.mode != CesiumGltf::MeshPrimitive::Mode::TRIANGLES && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::TRIANGLE_STRIP && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS) { // TODO: add support for other primitive types. UE_LOG( LogCesium, @@ -1173,7 +1172,9 @@ static void loadPrimitive( auto meshIt = std::find_if( model.meshes.begin(), model.meshes.end(), - [&mesh](const Mesh& candidate) { return &candidate == &mesh; }); + [&mesh](const CesiumGltf::Mesh& candidate) { + return &candidate == &mesh; + }); if (meshIt != model.meshes.end()) { int64_t meshIndex = meshIt - model.meshes.begin(); name += " mesh " + std::to_string(meshIndex); @@ -1182,7 +1183,7 @@ static void loadPrimitive( auto primitiveIt = std::find_if( mesh.primitives.begin(), mesh.primitives.end(), - [&primitive](const MeshPrimitive& candidate) { + [&primitive](const CesiumGltf::MeshPrimitive& candidate) { return &candidate == &primitive; }); if (primitiveIt != mesh.primitives.end()) { @@ -1192,7 +1193,7 @@ static void loadPrimitive( primitiveResult.name = name; - if (positionView.status() != AccessorViewStatus::Valid) { + if (positionView.status() != CesiumGltf::AccessorViewStatus::Valid) { UE_LOG( LogCesium, Warning, @@ -1202,7 +1203,7 @@ static void loadPrimitive( } if constexpr (IsAccessorView::value) { - if (indicesView.status() != AccessorViewStatus::Valid) { + if (indicesView.status() != CesiumGltf::AccessorViewStatus::Valid) { UE_LOG( LogCesium, Warning, @@ -1213,12 +1214,14 @@ static void loadPrimitive( } auto normalAccessorIt = primitive.attributes.find("NORMAL"); - AccessorView normalAccessor; + CesiumGltf::AccessorView normalAccessor; bool hasNormals = false; if (normalAccessorIt != primitive.attributes.end()) { int normalAccessorID = normalAccessorIt->second; - normalAccessor = AccessorView(model, normalAccessorID); - hasNormals = normalAccessor.status() == AccessorViewStatus::Valid; + normalAccessor = + CesiumGltf::AccessorView(model, normalAccessorID); + hasNormals = + normalAccessor.status() == CesiumGltf::AccessorViewStatus::Valid; if (!hasNormals) { UE_LOG( LogCesium, @@ -1230,37 +1233,42 @@ static void loadPrimitive( } int materialID = primitive.material; - const Material& material = + const CesiumGltf::Material& material = materialID >= 0 && materialID < model.materials.size() ? model.materials[materialID] : defaultMaterial; + primitiveResult.materialIndex = materialID; + primitiveResult.isUnlit = - material.hasExtension() && + material.hasExtension() && !options.pMeshOptions->pNodeOptions->pModelOptions ->ignoreKhrMaterialsUnlit; // We can't calculate flat normals for points or lines, so we have to force // them to be unlit if no normals are specified. Otherwise this causes a // crash when attempting to calculate flat normals. - bool isTriangles = primitive.mode == MeshPrimitive::Mode::TRIANGLES || - primitive.mode == MeshPrimitive::Mode::TRIANGLE_FAN || - primitive.mode == MeshPrimitive::Mode::TRIANGLE_STRIP; + bool isTriangles = + primitive.mode == CesiumGltf::MeshPrimitive::Mode::TRIANGLES || + primitive.mode == CesiumGltf::MeshPrimitive::Mode::TRIANGLE_FAN || + primitive.mode == CesiumGltf::MeshPrimitive::Mode::TRIANGLE_STRIP; if (!isTriangles && !hasNormals) { primitiveResult.isUnlit = true; } - const MaterialPBRMetallicRoughness& pbrMetallicRoughness = + const CesiumGltf::MaterialPBRMetallicRoughness& pbrMetallicRoughness = material.pbrMetallicRoughness ? material.pbrMetallicRoughness.value() : defaultPbrMetallicRoughness; bool hasNormalMap = material.normalTexture.has_value(); if (hasNormalMap) { - const CesiumGltf::Texture* pTexture = - Model::getSafe(&model.textures, material.normalTexture->index); - hasNormalMap = pTexture != nullptr && - Model::getSafe(&model.images, pTexture->source) != nullptr; + const CesiumGltf::Texture* pTexture = CesiumGltf::Model::getSafe( + &model.textures, + material.normalTexture->index); + hasNormalMap = + pTexture != nullptr && + CesiumGltf::Model::getSafe(&model.images, pTexture->source) != nullptr; } bool needsTangents = @@ -1269,11 +1277,13 @@ static void loadPrimitive( bool hasTangents = false; auto tangentAccessorIt = primitive.attributes.find("TANGENT"); - AccessorView tangentAccessor; + CesiumGltf::AccessorView tangentAccessor; if (tangentAccessorIt != primitive.attributes.end()) { int tangentAccessorID = tangentAccessorIt->second; - tangentAccessor = AccessorView(model, tangentAccessorID); - hasTangents = tangentAccessor.status() == AccessorViewStatus::Valid; + tangentAccessor = + CesiumGltf::AccessorView(model, tangentAccessorID); + hasTangents = + tangentAccessor.status() == CesiumGltf::AccessorViewStatus::Valid; if (!hasTangents) { UE_LOG( LogCesium, @@ -1283,7 +1293,7 @@ static void loadPrimitive( } } - applyWaterMask(model, primitive, primitiveResult, textureResources); + applyWaterMask(model, primitive, primitiveResult); // The water effect works by animating the normal, and the normal is // expressed in tangent space. So if we have water, we need tangents. @@ -1305,7 +1315,7 @@ static void loadPrimitive( glm::dvec3 minPosition{std::numeric_limits::max()}; glm::dvec3 maxPosition{std::numeric_limits::lowest()}; if (min.size() != 3 || max.size() != 3) { - for (int32_t i = 0; i < positionView.size(); ++i) { + for (int64_t i = 0; i < positionView.size(); ++i) { minPosition.x = glm::min(minPosition.x, positionView[i].X); minPosition.y = glm::min(minPosition.y, positionView[i].Y); minPosition.z = glm::min(minPosition.z, positionView[i].Z); @@ -1336,8 +1346,8 @@ static void loadPrimitive( } TArray indices; - if (primitive.mode == MeshPrimitive::Mode::TRIANGLES || - primitive.mode == MeshPrimitive::Mode::POINTS) { + if (primitive.mode == CesiumGltf::MeshPrimitive::Mode::TRIANGLES || + primitive.mode == CesiumGltf::MeshPrimitive::Mode::POINTS) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CopyIndices) indices.SetNum(static_cast::SizeType>(indicesView.size())); @@ -1371,8 +1381,8 @@ static void loadPrimitive( bool needToGenerateFlatNormals = normalsAreRequired && !hasNormals; bool needToGenerateTangents = needsTangents && !hasTangents; bool duplicateVertices = needToGenerateFlatNormals || needToGenerateTangents; - duplicateVertices = - duplicateVertices && primitive.mode != MeshPrimitive::Mode::POINTS; + duplicateVertices = duplicateVertices && + primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS; TArray StaticMeshBuildVertices; StaticMeshBuildVertices.SetNum( @@ -1441,27 +1451,22 @@ static void loadPrimitive( primitive, duplicateVertices, StaticMeshBuildVertices, - indices, - textureResources); + indices); { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadTextures) - primitiveResult.baseColorTexture = loadTexture( - model, - pbrMetallicRoughness.baseColorTexture, - true, - textureResources); + primitiveResult.baseColorTexture = + loadTexture(model, pbrMetallicRoughness.baseColorTexture, true); primitiveResult.metallicRoughnessTexture = loadTexture( model, pbrMetallicRoughness.metallicRoughnessTexture, - false, - textureResources); + false); primitiveResult.normalTexture = - loadTexture(model, material.normalTexture, false, textureResources); + loadTexture(model, material.normalTexture, false); primitiveResult.occlusionTexture = - loadTexture(model, material.occlusionTexture, false, textureResources); + loadTexture(model, material.occlusionTexture, false); primitiveResult.emissiveTexture = - loadTexture(model, material.emissiveTexture, true, textureResources); + loadTexture(model, material.emissiveTexture, true); } { @@ -1685,7 +1690,8 @@ static void loadPrimitive( section.FirstIndex = 0; section.MinVertexIndex = 0; section.MaxVertexIndex = StaticMeshBuildVertices.Num() - 1; - section.bEnableCollision = primitive.mode != MeshPrimitive::Mode::POINTS; + section.bEnableCollision = + primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS; section.bCastShadow = true; section.MaterialIndex = 0; @@ -1709,15 +1715,14 @@ static void loadPrimitive( LODResources.bHasReversedIndices = false; LODResources.bHasReversedDepthOnlyIndices = false; - primitiveResult.pModel = &model; - primitiveResult.pMeshPrimitive = &primitive; + primitiveResult.meshIndex = options.pMeshOptions->meshIndex; + primitiveResult.primitiveIndex = options.primitiveIndex; primitiveResult.RenderData = std::move(RenderData); - primitiveResult.pMaterial = &material; primitiveResult.pCollisionMesh = nullptr; primitiveResult.transform = transform * yInvertMatrix * scaleMatrix; - if (primitive.mode != MeshPrimitive::Mode::POINTS && + if (primitive.mode != CesiumGltf::MeshPrimitive::Mode::POINTS && options.pMeshOptions->pNodeOptions->pModelOptions->createPhysicsMeshes) { if (StaticMeshBuildVertices.Num() != 0 && indices.Num() != 0) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::ChaosCook) @@ -1737,18 +1742,20 @@ static void loadIndexedPrimitive( LoadPrimitiveResult& primitiveResult, const glm::dmat4x4& transform, const CreatePrimitiveOptions& options, - const Accessor& positionAccessor, - const AccessorView& positionView, - std::vector& textureResources, + const CesiumGltf::Accessor& positionAccessor, + const CesiumGltf::AccessorView& positionView, const CesiumGeospatial::Ellipsoid& ellipsoid) { - const Model& model = + const CesiumGltf::Model& model = *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; - const MeshPrimitive& primitive = *options.pPrimitive; + const CesiumGltf::MeshPrimitive& primitive = + model.meshes[options.pMeshOptions->meshIndex] + .primitives[options.primitiveIndex]; - const Accessor& indexAccessorGltf = model.accessors[primitive.indices]; + const CesiumGltf::Accessor& indexAccessorGltf = + model.accessors[primitive.indices]; if (indexAccessorGltf.componentType == - Accessor::ComponentType::UNSIGNED_BYTE) { - AccessorView indexAccessor(model, primitive.indices); + CesiumGltf::Accessor::ComponentType::UNSIGNED_BYTE) { + CesiumGltf::AccessorView indexAccessor(model, primitive.indices); loadPrimitive( primitiveResult, transform, @@ -1756,13 +1763,12 @@ static void loadIndexedPrimitive( positionAccessor, positionView, indexAccessor, - textureResources, ellipsoid); primitiveResult.IndexAccessor = indexAccessor; } else if ( indexAccessorGltf.componentType == - Accessor::ComponentType::UNSIGNED_SHORT) { - AccessorView indexAccessor(model, primitive.indices); + CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT) { + CesiumGltf::AccessorView indexAccessor(model, primitive.indices); loadPrimitive( primitiveResult, transform, @@ -1770,13 +1776,12 @@ static void loadIndexedPrimitive( positionAccessor, positionView, indexAccessor, - textureResources, ellipsoid); primitiveResult.IndexAccessor = indexAccessor; } else if ( indexAccessorGltf.componentType == - Accessor::ComponentType::UNSIGNED_INT) { - AccessorView indexAccessor(model, primitive.indices); + CesiumGltf::Accessor::ComponentType::UNSIGNED_INT) { + CesiumGltf::AccessorView indexAccessor(model, primitive.indices); loadPrimitive( primitiveResult, transform, @@ -1784,15 +1789,15 @@ static void loadIndexedPrimitive( positionAccessor, positionView, indexAccessor, - textureResources, ellipsoid); primitiveResult.IndexAccessor = indexAccessor; } else { UE_LOG( LogCesium, - VeryVerbose, + Warning, TEXT( - "Skip loading primitive due to invalid component type in its index accessor.")); + "Ignoring a glTF primitive because the componentType (%d) of its indices is not supported."), + indexAccessorGltf.componentType); } } @@ -1800,13 +1805,14 @@ static void loadPrimitive( LoadPrimitiveResult& result, const glm::dmat4x4& transform, const CreatePrimitiveOptions& options, - std::vector& textureResources, const CesiumGeospatial::Ellipsoid& ellipsoid) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadPrimitive) - const Model& model = + const CesiumGltf::Model& model = *options.pMeshOptions->pNodeOptions->pModelOptions->pModel; - const MeshPrimitive& primitive = *options.pPrimitive; + const CesiumGltf::MeshPrimitive& primitive = + model.meshes[options.pMeshOptions->meshIndex] + .primitives[options.primitiveIndex]; auto positionAccessorIt = primitive.attributes.find("POSITION"); if (positionAccessorIt == primitive.attributes.end()) { @@ -1815,14 +1821,16 @@ static void loadPrimitive( } int positionAccessorID = positionAccessorIt->second; - const Accessor* pPositionAccessor = - Model::getSafe(&model.accessors, positionAccessorID); + const CesiumGltf::Accessor* pPositionAccessor = + CesiumGltf::Model::getSafe(&model.accessors, positionAccessorID); if (!pPositionAccessor) { // Position accessor does not exist, so ignore this primitive. return; } - AccessorView positionView(model, *pPositionAccessor); + CesiumGltf::AccessorView positionView( + model, + *pPositionAccessor); if (primitive.indices < 0 || primitive.indices >= model.accessors.size()) { std::vector syntheticIndexBuffer(positionView.size()); @@ -1837,7 +1845,6 @@ static void loadPrimitive( *pPositionAccessor, positionView, syntheticIndexBuffer, - textureResources, ellipsoid); } else { loadIndexedPrimitive( @@ -1846,7 +1853,6 @@ static void loadPrimitive( options, *pPositionAccessor, positionView, - textureResources, ellipsoid); } result.PositionAccessor = std::move(positionView); @@ -1855,26 +1861,20 @@ static void loadPrimitive( static void loadMesh( std::optional& result, const glm::dmat4x4& transform, - const CreateMeshOptions& options, - std::vector& textureResources, + CreateMeshOptions& options, const CesiumGeospatial::Ellipsoid& ellipsoid) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadMesh) - const Model& model = *options.pNodeOptions->pModelOptions->pModel; - Mesh& mesh = *options.pMesh; + CesiumGltf::Model& model = *options.pNodeOptions->pModelOptions->pModel; + CesiumGltf::Mesh& mesh = model.meshes[options.meshIndex]; result = LoadMeshResult(); result->primitiveResults.reserve(mesh.primitives.size()); - for (CesiumGltf::MeshPrimitive& primitive : mesh.primitives) { - CreatePrimitiveOptions primitiveOptions = {&options, &*result, &primitive}; + for (size_t i = 0; i < mesh.primitives.size(); i++) { + CreatePrimitiveOptions primitiveOptions = {&options, &*result, i}; auto& primitiveResult = result->primitiveResults.emplace_back(); - loadPrimitive( - primitiveResult, - transform, - primitiveOptions, - textureResources, - ellipsoid); + loadPrimitive(primitiveResult, transform, primitiveOptions, ellipsoid); // if it doesn't have render data, then it can't be loaded if (!primitiveResult.RenderData) { @@ -1906,19 +1906,20 @@ inline constexpr bool is_int_quat_v = is_int_quat::value; } // namespace static void loadInstancingData( - const Model& model, + const CesiumGltf::Model& model, LoadNodeResult& result, - const ExtensionExtMeshGpuInstancing* pGpuInstancing) { - auto getInstanceAccessor = [&](const char* name) -> const Accessor* { + const CesiumGltf::ExtensionExtMeshGpuInstancing* pGpuInstancing) { + auto getInstanceAccessor = + [&](const char* name) -> const CesiumGltf::Accessor* { if (auto accessorItr = pGpuInstancing->attributes.find(name); accessorItr != pGpuInstancing->attributes.end()) { - return Model::getSafe(&model.accessors, accessorItr->second); + return CesiumGltf::Model::getSafe(&model.accessors, accessorItr->second); } return nullptr; }; - const Accessor* translations = getInstanceAccessor("TRANSLATION"); - const Accessor* rotations = getInstanceAccessor("ROTATION"); - const Accessor* scales = getInstanceAccessor("SCALE"); + const CesiumGltf::Accessor* translations = getInstanceAccessor("TRANSLATION"); + const CesiumGltf::Accessor* rotations = getInstanceAccessor("ROTATION"); + const CesiumGltf::Accessor* scales = getInstanceAccessor("SCALE"); int64_t count = 0; if (translations) { @@ -1969,8 +1970,10 @@ static void loadInstancingData( // argument by the new transform. E.g., translate() does *not* translate the // matrix. if (translations) { - AccessorView translationAccessor(model, *translations); - if (translationAccessor.status() == AccessorViewStatus::Valid) { + CesiumGltf::AccessorView translationAccessor( + model, + *translations); + if (translationAccessor.status() == CesiumGltf::AccessorViewStatus::Valid) { for (int64_t i = 0; i < count; ++i) { glm::dvec3 translation(translationAccessor[i]); instanceTransforms[i] = glm::translate( @@ -2010,7 +2013,7 @@ static void loadInstancingData( }); } if (scales) { - AccessorView scaleAccessor(model, *scales); + CesiumGltf::AccessorView scaleAccessor(model, *scales); for (int64_t i = 0; i < count; ++i) { glm::dvec3 scaleFactors(scaleAccessor[i]); instanceTransforms[i] = glm::scale(instanceTransforms[i], scaleFactors); @@ -2030,8 +2033,7 @@ static void loadInstancingData( static void loadNode( std::vector& loadNodeResults, const glm::dmat4x4& transform, - const CreateNodeOptions& options, - std::vector& textureResources, + CreateNodeOptions& options, const CesiumGeospatial::Ellipsoid& ellipsoid) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadNode) @@ -2054,8 +2056,8 @@ static void loadNode( 0.0, 1.0}; - Model& model = *options.pModelOptions->pModel; - const Node& node = *options.pNode; + CesiumGltf::Model& model = *options.pModelOptions->pModel; + const CesiumGltf::Node& node = *options.pNode; LoadNodeResult& result = loadNodeResults.emplace_back(); @@ -2108,16 +2110,11 @@ static void loadNode( int meshId = node.mesh; if (meshId >= 0 && meshId < model.meshes.size()) { if (const auto* pGpuInstancingExtension = - node.getExtension()) { + node.getExtension()) { loadInstancingData(model, result, pGpuInstancingExtension); } - CreateMeshOptions meshOptions = {&options, &result, &model.meshes[meshId]}; - loadMesh( - result.meshResult, - nodeTransform, - meshOptions, - textureResources, - ellipsoid); + CreateMeshOptions meshOptions = {&options, &result, meshId}; + loadMesh(result.meshResult, nodeTransform, meshOptions, ellipsoid); } for (int childNodeId : node.children) { @@ -2126,12 +2123,7 @@ static void loadNode( options.pModelOptions, options.pHalfConstructedModelResult, &model.nodes[childNodeId]}; - loadNode( - loadNodeResults, - nodeTransform, - childNodeOptions, - textureResources, - ellipsoid); + loadNode(loadNodeResults, nodeTransform, childNodeOptions, ellipsoid); } } } @@ -2154,7 +2146,9 @@ namespace { * @param model The glTF model * @param rootTransform The matrix that will be multiplied with the transform */ -void applyGltfUpAxisTransform(const Model& model, glm::dmat4x4& rootTransform) { +void applyGltfUpAxisTransform( + const CesiumGltf::Model& model, + glm::dmat4x4& rootTransform) { auto gltfUpAxisIt = model.extras.find("gltfUpAxis"); if (gltfUpAxisIt == model.extras.end()) { @@ -2175,8 +2169,8 @@ void applyGltfUpAxisTransform(const Model& model, glm::dmat4x4& rootTransform) { } else { UE_LOG( LogCesium, - VeryVerbose, - TEXT("Unknown gltfUpAxis value: {}"), + Warning, + TEXT("Ignoring unknown gltfUpAxis value: {}"), gltfUpAxisValue); } } @@ -2185,10 +2179,10 @@ void applyGltfUpAxisTransform(const Model& model, glm::dmat4x4& rootTransform) { static void loadModelMetadata(LoadModelResult& result, const CreateModelOptions& options) { - Model& model = *options.pModel; + CesiumGltf::Model& model = *options.pModel; - ExtensionModelExtStructuralMetadata* pModelMetadata = - model.getExtension(); + CesiumGltf::ExtensionModelExtStructuralMetadata* pModelMetadata = + model.getExtension(); if (!pModelMetadata) { return; } @@ -2201,9 +2195,9 @@ loadModelMetadata(LoadModelResult& result, const CreateModelOptions& options) { CesiumGltf::Mesh& /*mesh*/, CesiumGltf::MeshPrimitive& primitive, const glm::dmat4& /*nodeTransform*/) { - const ExtensionMeshPrimitiveExtStructuralMetadata* pPrimitiveMetadata = - primitive - .getExtension(); + const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata* + pPrimitiveMetadata = primitive.getExtension< + CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata>(); if (!pPrimitiveMetadata) { return; } @@ -2274,119 +2268,99 @@ loadModelMetadata(LoadModelResult& result, const CreateModelOptions& options) { PRAGMA_ENABLE_DEPRECATION_WARNINGS } -static void loadModelAnyThreadPart( - LoadModelResult& result, +static CesiumAsync::Future +loadModelAnyThreadPart( + const CesiumAsync::AsyncSystem& asyncSystem, const glm::dmat4x4& transform, - const CreateModelOptions& options, - std::vector& textureResources, + CreateModelOptions&& options, const CesiumGeospatial::Ellipsoid& ellipsoid) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::loadModelAnyThreadPart) - Model& model = *options.pModel; - - // Generate mipmaps if needed. - // An image needs mipmaps generated for it if: - // 1. It is used by a Texture that has a Sampler with a mipmap filtering - // mode, and - // 2. It does not already have mipmaps. - // It's ok if an image has mipmaps even if not all textures will use them. - // There's no reason to have two RHI textures, one with and one without - // mips. - for (const Texture& texture : model.textures) { - const Sampler& sampler = model.getSafe(model.samplers, texture.sampler); - - bool needsMipmaps; - switch (sampler.minFilter.value_or( - CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR)) { - case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR: - case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_NEAREST: - case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_LINEAR: - case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_NEAREST: - needsMipmaps = true; - break; - default: // LINEAR and NEAREST - needsMipmaps = false; - break; - } + return CesiumGltfTextures::createInWorkerThread(asyncSystem, *options.pModel) + .thenInWorkerThread( + [transform, ellipsoid, options = std::move(options)]() mutable + -> UCesiumGltfComponent::CreateOffGameThreadResult { + auto pHalf = MakeUnique(); - if (!needsMipmaps) - continue; + loadModelMetadata(pHalf->loadModelResult, options); - Image* pImage = model.getSafe(&model.images, texture.source); - if (!pImage || pImage->cesium.pixelData.empty()) - continue; + glm::dmat4x4 rootTransform = transform; - std::optional errorMessage = - CesiumGltfReader::GltfReader::generateMipMaps(pImage->cesium); - if (errorMessage) { - UE_LOG( - LogCesium, - Warning, - TEXT("%s"), - UTF8_TO_TCHAR(errorMessage->c_str())); - } - } + CesiumGltf::Model& model = *options.pModel; - loadModelMetadata(result, options); + { + rootTransform = CesiumGltfContent::GltfUtilities::applyRtcCenter( + model, + rootTransform); + applyGltfUpAxisTransform(model, rootTransform); + } - glm::dmat4x4 rootTransform = transform; + if (model.scene >= 0 && model.scene < model.scenes.size()) { + // Show the default scene + const CesiumGltf::Scene& defaultScene = model.scenes[model.scene]; + for (int nodeId : defaultScene.nodes) { + CreateNodeOptions nodeOptions = { + &options, + &pHalf->loadModelResult, + &model.nodes[nodeId]}; + loadNode( + pHalf->loadModelResult.nodeResults, + rootTransform, + nodeOptions, + ellipsoid); + } + } else if (model.scenes.size() > 0) { + // There's no default, so show the first scene + const CesiumGltf::Scene& defaultScene = model.scenes[0]; + for (int nodeId : defaultScene.nodes) { + CreateNodeOptions nodeOptions = { + &options, + &pHalf->loadModelResult, + &model.nodes[nodeId]}; + loadNode( + pHalf->loadModelResult.nodeResults, + rootTransform, + nodeOptions, + ellipsoid); + } + } else if (model.nodes.size() > 0) { + // No scenes at all, use the first node as the root node. + CreateNodeOptions nodeOptions = { + &options, + &pHalf->loadModelResult, + &model.nodes[0]}; + loadNode( + pHalf->loadModelResult.nodeResults, + rootTransform, + nodeOptions, + ellipsoid); + } else if (model.meshes.size() > 0) { + // No nodes either, show all the meshes. + for (size_t i = 0; i < model.meshes.size(); i++) { + CreateNodeOptions dummyNodeOptions = { + &options, + &pHalf->loadModelResult, + nullptr}; + LoadNodeResult& dummyNodeResult = + pHalf->loadModelResult.nodeResults.emplace_back(); + CreateMeshOptions meshOptions = { + &dummyNodeOptions, + &dummyNodeResult, + i}; + loadMesh( + dummyNodeResult.meshResult, + rootTransform, + meshOptions, + ellipsoid); + } + } - { - rootTransform = - CesiumGltfContent::GltfUtilities::applyRtcCenter(model, rootTransform); - applyGltfUpAxisTransform(model, rootTransform); - } - - if (model.scene >= 0 && model.scene < model.scenes.size()) { - // Show the default scene - const Scene& defaultScene = model.scenes[model.scene]; - for (int nodeId : defaultScene.nodes) { - CreateNodeOptions nodeOptions = {&options, &result, &model.nodes[nodeId]}; - loadNode( - result.nodeResults, - rootTransform, - nodeOptions, - textureResources, - ellipsoid); - } - } else if (model.scenes.size() > 0) { - // There's no default, so show the first scene - const Scene& defaultScene = model.scenes[0]; - for (int nodeId : defaultScene.nodes) { - CreateNodeOptions nodeOptions = {&options, &result, &model.nodes[nodeId]}; - loadNode( - result.nodeResults, - rootTransform, - nodeOptions, - textureResources, - ellipsoid); - } - } else if (model.nodes.size() > 0) { - // No scenes at all, use the first node as the root node. - CreateNodeOptions nodeOptions = {&options, &result, &model.nodes[0]}; - loadNode( - result.nodeResults, - rootTransform, - nodeOptions, - textureResources, - ellipsoid); - } else if (model.meshes.size() > 0) { - // No nodes either, show all the meshes. - for (Mesh& mesh : model.meshes) { - CreateNodeOptions dummyNodeOptions = {&options, &result, nullptr}; - LoadNodeResult& dummyNodeResult = result.nodeResults.emplace_back(); - CreateMeshOptions meshOptions = { - &dummyNodeOptions, - &dummyNodeResult, - &mesh}; - loadMesh( - dummyNodeResult.meshResult, - rootTransform, - meshOptions, - textureResources, - ellipsoid); - } - } + UCesiumGltfComponent::CreateOffGameThreadResult result; + result.HalfConstructed = std::move(pHalf); + result.TileLoadResult = std::move(options.tileLoadResult); + + return result; + }); } bool applyTexture( @@ -2413,8 +2387,8 @@ bool applyTexture( static void SetGltfParameterValues( CesiumGltf::Model& model, LoadPrimitiveResult& loadResult, - const Material& material, - const MaterialPBRMetallicRoughness& pbr, + const CesiumGltf::Material& material, + const CesiumGltf::MaterialPBRMetallicRoughness& pbr, UMaterialInstanceDynamic* pMaterial, EMaterialParameterAssociation association, int32 index) { @@ -2484,16 +2458,19 @@ static void SetGltfParameterValues( FMaterialParameterInfo("occlusionTexture", association, index), loadResult.occlusionTexture.Get()); - KhrTextureTransform textureTransform; + CesiumGltf::KhrTextureTransform textureTransform; FLinearColor baseColorMetallicRoughnessRotation(0.0f, 1.0f, 0.0f, 1.0f); - const ExtensionKhrTextureTransform* pBaseColorTextureTransform = + const CesiumGltf::ExtensionKhrTextureTransform* pBaseColorTextureTransform = pbr.baseColorTexture - ? pbr.baseColorTexture->getExtension() + ? pbr.baseColorTexture + ->getExtension() : nullptr; if (pBaseColorTextureTransform) { - textureTransform = KhrTextureTransform(*pBaseColorTextureTransform); - if (textureTransform.status() == KhrTextureTransformStatus::Valid) { + textureTransform = + CesiumGltf::KhrTextureTransform(*pBaseColorTextureTransform); + if (textureTransform.status() == + CesiumGltf::KhrTextureTransformStatus::Valid) { const glm::dvec2& scale = textureTransform.scale(); const glm::dvec2& offset = textureTransform.offset(); pMaterial->SetVectorParameterValueByInfo( @@ -2507,15 +2484,18 @@ static void SetGltfParameterValues( } } - const ExtensionKhrTextureTransform* pMetallicRoughnessTextureTransform = - pbr.metallicRoughnessTexture - ? pbr.metallicRoughnessTexture - ->getExtension() - : nullptr; + const CesiumGltf::ExtensionKhrTextureTransform* + pMetallicRoughnessTextureTransform = + pbr.metallicRoughnessTexture + ? pbr.metallicRoughnessTexture + ->getExtension() + : nullptr; if (pMetallicRoughnessTextureTransform) { - textureTransform = KhrTextureTransform(*pMetallicRoughnessTextureTransform); - if (textureTransform.status() == KhrTextureTransformStatus::Valid) { + textureTransform = + CesiumGltf::KhrTextureTransform(*pMetallicRoughnessTextureTransform); + if (textureTransform.status() == + CesiumGltf::KhrTextureTransformStatus::Valid) { const glm::dvec2& scale = textureTransform.scale(); const glm::dvec2& offset = textureTransform.offset(); pMaterial->SetVectorParameterValueByInfo( @@ -2543,14 +2523,15 @@ static void SetGltfParameterValues( FLinearColor emissiveNormalRotation(0.0f, 1.0f, 0.0f, 1.0f); - const ExtensionKhrTextureTransform* pEmissiveTextureTransform = + const CesiumGltf::ExtensionKhrTextureTransform* pEmissiveTextureTransform = material.emissiveTexture ? material.emissiveTexture - ->getExtension() + ->getExtension() : nullptr; if (pEmissiveTextureTransform) { - textureTransform = KhrTextureTransform(*pEmissiveTextureTransform); + textureTransform = + CesiumGltf::KhrTextureTransform(*pEmissiveTextureTransform); const glm::dvec2& scale = textureTransform.scale(); const glm::dvec2& offset = textureTransform.offset(); pMaterial->SetVectorParameterValueByInfo( @@ -2563,13 +2544,15 @@ static void SetGltfParameterValues( emissiveNormalRotation.G = rotationSineCosine[1]; } - const ExtensionKhrTextureTransform* pNormalTextureTransform = + const CesiumGltf::ExtensionKhrTextureTransform* pNormalTextureTransform = material.normalTexture - ? material.normalTexture->getExtension() + ? material.normalTexture + ->getExtension() : nullptr; if (pNormalTextureTransform) { - textureTransform = KhrTextureTransform(*pNormalTextureTransform); + textureTransform = + CesiumGltf::KhrTextureTransform(*pNormalTextureTransform); const glm::dvec2& scale = textureTransform.scale(); const glm::dvec2& offset = textureTransform.offset(); pMaterial->SetVectorParameterValueByInfo( @@ -2587,14 +2570,14 @@ static void SetGltfParameterValues( emissiveNormalRotation); } - const ExtensionKhrTextureTransform* pOcclusionTransform = + const CesiumGltf::ExtensionKhrTextureTransform* pOcclusionTransform = material.occlusionTexture ? material.occlusionTexture - ->getExtension() + ->getExtension() : nullptr; if (pOcclusionTransform) { - textureTransform = KhrTextureTransform(*pOcclusionTransform); + textureTransform = CesiumGltf::KhrTextureTransform(*pOcclusionTransform); const glm::dvec2& scale = textureTransform.scale(); const glm::dvec2& offset = textureTransform.offset(); pMaterial->SetVectorParameterValueByInfo( @@ -2902,9 +2885,12 @@ static void loadPrimitiveGameThreadPart( const Cesium3DTilesSelection::BoundingVolume& boundingVolume = tile.getContentBoundingVolume().value_or(tile.getBoundingVolume()); + CesiumGltf::MeshPrimitive& meshPrimitive = + model.meshes[loadResult.meshIndex].primitives[loadResult.primitiveIndex]; + UStaticMeshComponent* pMesh = nullptr; ICesiumPrimitive* pCesiumPrimitive = nullptr; - if (loadResult.pMeshPrimitive->mode == MeshPrimitive::Mode::POINTS) { + if (meshPrimitive.mode == CesiumGltf::MeshPrimitive::Mode::POINTS) { UCesiumGltfPointsComponent* pPointMesh = NewObject(pGltf, componentName); pPointMesh->UsesAdditiveRefinement = @@ -2946,8 +2932,8 @@ static void loadPrimitiveGameThreadPart( pMesh->SetCollisionObjectType(ECollisionChannel::ECC_WorldStatic); pMesh->SetFlags( RF_Transient | RF_DuplicateTransient | RF_TextExportTransient); - primData.pModel = loadResult.pModel; - primData.pMeshPrimitive = loadResult.pMeshPrimitive; + primData.pModel = &model; + primData.pMeshPrimitive = &meshPrimitive; primData.boundingVolume = boundingVolume; pMesh->SetRenderCustomDepth(pGltf->CustomDepthParameters.RenderCustomDepth); pMesh->SetCustomDepthStencilWriteMask( @@ -2968,19 +2954,21 @@ static void loadPrimitiveGameThreadPart( pStaticMesh->SetRenderData(std::move(loadResult.RenderData)); } - const Material& material = - loadResult.pMaterial ? *loadResult.pMaterial : defaultMaterial; + const CesiumGltf::Material& material = + loadResult.materialIndex != -1 ? model.materials[loadResult.materialIndex] + : defaultMaterial; - const MaterialPBRMetallicRoughness& pbr = + const CesiumGltf::MaterialPBRMetallicRoughness& pbr = material.pbrMetallicRoughness ? material.pbrMetallicRoughness.value() : defaultPbrMetallicRoughness; const FName ImportedSlotName( *(TEXT("CesiumMaterial") + FString::FromInt(nextMaterialId++))); - const auto is_in_blend_mode = [](auto& result) { - return !!result.pMaterial && result.pMaterial->alphaMode == - CesiumGltf::Material::AlphaMode::BLEND; + const auto is_in_blend_mode = [&model](auto& result) { + return result.materialIndex != -1 && + model.materials[result.materialIndex].alphaMode == + CesiumGltf::Material::AlphaMode::BLEND; }; #if PLATFORM_MAC @@ -3201,23 +3189,17 @@ static void loadPrimitiveGameThreadPart( } } -/*static*/ TUniquePtr +/*static*/ CesiumAsync::Future UCesiumGltfComponent::CreateOffGameThread( + const CesiumAsync::AsyncSystem& AsyncSystem, const glm::dmat4x4& Transform, - const CreateModelOptions& Options, + CreateModelOptions&& Options, const CesiumGeospatial::Ellipsoid& Ellipsoid) { - std::vector textureResources; - textureResources.resize(Options.pModel->images.size(), nullptr); - - auto pResult = MakeUnique(); - loadModelAnyThreadPart( - pResult->loadModelResult, + return loadModelAnyThreadPart( + AsyncSystem, Transform, - Options, - textureResources, + std::move(Options), Ellipsoid); - - return pResult; } /*static*/ UCesiumGltfComponent* UCesiumGltfComponent::CreateOnGameThread( @@ -3322,10 +3304,6 @@ UCesiumGltfComponent::UCesiumGltfComponent() : USceneComponent() { PrimaryComponentTick.bCanEverTick = false; } -UCesiumGltfComponent::~UCesiumGltfComponent() { - UE_LOG(LogCesium, VeryVerbose, TEXT("~UCesiumGltfComponent")); -} - void UCesiumGltfComponent::UpdateTransformFromCesium( const glm::dmat4& cesiumToUnrealTransform) { for (USceneComponent* pSceneComponent : this->GetAttachChildren()) { diff --git a/Source/CesiumRuntime/Private/CesiumGltfComponent.h b/Source/CesiumRuntime/Private/CesiumGltfComponent.h index dcefb5ecd..e78b2d273 100644 --- a/Source/CesiumRuntime/Private/CesiumGltfComponent.h +++ b/Source/CesiumRuntime/Private/CesiumGltfComponent.h @@ -12,6 +12,7 @@ #include "CoreMinimal.h" #include "CustomDepthParameters.h" #include "Interfaces/IHttpRequest.h" +#include #include #include #include "CesiumGltfComponent.generated.h" @@ -64,9 +65,16 @@ class UCesiumGltfComponent : public USceneComponent { virtual ~HalfConstructed() = default; }; - static TUniquePtr CreateOffGameThread( + class CreateOffGameThreadResult { + public: + TUniquePtr HalfConstructed; + Cesium3DTilesSelection::TileLoadResult TileLoadResult; + }; + + static CesiumAsync::Future CreateOffGameThread( + const CesiumAsync::AsyncSystem& AsyncSystem, const glm::dmat4x4& Transform, - const CreateGltfOptions::CreateModelOptions& Options, + CreateGltfOptions::CreateModelOptions&& Options, const CesiumGeospatial::Ellipsoid& Ellipsoid = CesiumGeospatial::Ellipsoid::WGS84); @@ -83,7 +91,6 @@ class UCesiumGltfComponent : public USceneComponent { bool createNavCollision); UCesiumGltfComponent(); - virtual ~UCesiumGltfComponent(); UPROPERTY(EditAnywhere, Category = "Cesium") UMaterialInterface* BaseMaterial = nullptr; diff --git a/Source/CesiumRuntime/Private/CesiumGltfTextures.cpp b/Source/CesiumRuntime/Private/CesiumGltfTextures.cpp new file mode 100644 index 000000000..d0787ccc6 --- /dev/null +++ b/Source/CesiumRuntime/Private/CesiumGltfTextures.cpp @@ -0,0 +1,258 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#include "CesiumGltfTextures.h" +#include "CesiumRuntime.h" +#include "CesiumTextureResource.h" +#include "CesiumTextureUtility.h" +#include "ExtensionImageAssetUnreal.h" +#include +#include +#include +#include + +using namespace CesiumAsync; + +namespace { + +// Determines if a glTF primitive is usable for our purposes. +bool isValidPrimitive( + const CesiumGltf::Model& gltf, + const CesiumGltf::MeshPrimitive& primitive); + +// Determines if an Accessor's componentType is valid for an index buffer. +bool isSupportedIndexComponentType(int32_t componentType); + +// Determines if the given Primitive mode is one that we support. +bool isSupportedPrimitiveMode(int32_t primitiveMode); + +// Determines if the given texture uses mipmaps. +bool doesTextureUseMipmaps( + const CesiumGltf::Model& gltf, + const CesiumGltf::Texture& texture); + +// Creates a single texture in the load thread. +SharedFuture createTextureInLoadThread( + const AsyncSystem& asyncSystem, + CesiumGltf::Model& gltf, + CesiumGltf::TextureInfo& textureInfo, + bool sRGB, + const std::vector& imageNeedsMipmaps); + +} // namespace + +/*static*/ CesiumAsync::Future CesiumGltfTextures::createInWorkerThread( + const CesiumAsync::AsyncSystem& asyncSystem, + CesiumGltf::Model& model) { + // This array is parallel to model.images and indicates whether each image + // requires mipmaps. An image requires mipmaps if any of its textures have a + // sampler that will use them. + std::vector imageNeedsMipmaps(model.images.size(), false); + for (const CesiumGltf::Texture& texture : model.textures) { + int32_t imageIndex = texture.source; + if (imageIndex < 0 || imageIndex >= model.images.size()) { + continue; + } + + if (!imageNeedsMipmaps[imageIndex]) { + imageNeedsMipmaps[imageIndex] = doesTextureUseMipmaps(model, texture); + } + } + + std::vector> futures; + + model.forEachPrimitiveInScene( + -1, + [&imageNeedsMipmaps, &asyncSystem, &futures]( + CesiumGltf::Model& gltf, + CesiumGltf::Node& node, + CesiumGltf::Mesh& mesh, + CesiumGltf::MeshPrimitive& primitive, + const glm::dmat4& transform) { + if (!isValidPrimitive(gltf, primitive)) { + return; + } + + CesiumGltf::Material* pMaterial = + CesiumGltf::Model::getSafe(&gltf.materials, primitive.material); + if (!pMaterial) { + // A primitive using the default material will not have any textures. + return; + } + + if (pMaterial->pbrMetallicRoughness) { + if (pMaterial->pbrMetallicRoughness->baseColorTexture) { + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->pbrMetallicRoughness->baseColorTexture, + true, + imageNeedsMipmaps)); + } + if (pMaterial->pbrMetallicRoughness->metallicRoughnessTexture) { + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->pbrMetallicRoughness->metallicRoughnessTexture, + false, + imageNeedsMipmaps)); + } + } + + if (pMaterial->emissiveTexture) + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->emissiveTexture, + true, + imageNeedsMipmaps)); + if (pMaterial->normalTexture) + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->normalTexture, + false, + imageNeedsMipmaps)); + if (pMaterial->occlusionTexture) + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + *pMaterial->occlusionTexture, + false, + imageNeedsMipmaps)); + + // Initialize water mask if needed. + auto onlyWaterIt = primitive.extras.find("OnlyWater"); + auto onlyLandIt = primitive.extras.find("OnlyLand"); + if (onlyWaterIt != primitive.extras.end() && + onlyWaterIt->second.isBool() && + onlyLandIt != primitive.extras.end() && + onlyLandIt->second.isBool()) { + bool onlyWater = onlyWaterIt->second.getBoolOrDefault(false); + bool onlyLand = onlyLandIt->second.getBoolOrDefault(true); + + if (!onlyWater && !onlyLand) { + // We have to use the water mask + auto waterMaskTextureIdIt = primitive.extras.find("WaterMaskTex"); + if (waterMaskTextureIdIt != primitive.extras.end() && + waterMaskTextureIdIt->second.isInt64()) { + int32_t waterMaskTextureId = static_cast( + waterMaskTextureIdIt->second.getInt64OrDefault(-1)); + CesiumGltf::TextureInfo waterMaskInfo; + waterMaskInfo.index = waterMaskTextureId; + if (waterMaskTextureId >= 0 && + waterMaskTextureId < gltf.textures.size()) { + futures.emplace_back(createTextureInLoadThread( + asyncSystem, + gltf, + waterMaskInfo, + false, + imageNeedsMipmaps)); + } + } + } + } + }); + + return asyncSystem.all(std::move(futures)); +} + +namespace { + +bool isSupportedIndexComponentType(int32_t componentType) { + return componentType == CesiumGltf::Accessor::ComponentType::UNSIGNED_BYTE || + componentType == CesiumGltf::Accessor::ComponentType::UNSIGNED_SHORT || + componentType == CesiumGltf::Accessor::ComponentType::UNSIGNED_INT; +} + +bool isSupportedPrimitiveMode(int32_t primitiveMode) { + return primitiveMode == CesiumGltf::MeshPrimitive::Mode::TRIANGLES || + primitiveMode == CesiumGltf::MeshPrimitive::Mode::TRIANGLE_STRIP || + primitiveMode == CesiumGltf::MeshPrimitive::Mode::POINTS; +} + +// Determines if a glTF primitive is usable for our purposes. +bool isValidPrimitive( + const CesiumGltf::Model& gltf, + const CesiumGltf::MeshPrimitive& primitive) { + if (!isSupportedPrimitiveMode(primitive.mode)) { + // This primitive's mode is not supported. + return false; + } + + auto positionAccessorIt = + primitive.attributes.find(CesiumGltf::VertexAttributeSemantics::POSITION); + if (positionAccessorIt == primitive.attributes.end()) { + // This primitive doesn't have a POSITION semantic, so it's not valid. + return false; + } + + CesiumGltf::AccessorView positionView( + gltf, + positionAccessorIt->second); + if (positionView.status() != CesiumGltf::AccessorViewStatus::Valid) { + // This primitive's POSITION accessor is invalid, so the primitive is not + // valid. + return false; + } + + const CesiumGltf::Accessor* pIndexAccessor = + CesiumGltf::Model::getSafe(&gltf.accessors, primitive.indices); + if (pIndexAccessor && + !isSupportedIndexComponentType(pIndexAccessor->componentType)) { + // This primitive's indices are not a supported type, so the primitive is + // not valid. + return false; + } + + return true; +} + +bool doesTextureUseMipmaps( + const CesiumGltf::Model& gltf, + const CesiumGltf::Texture& texture) { + const CesiumGltf::Sampler& sampler = + CesiumGltf::Model::getSafe(gltf.samplers, texture.sampler); + + switch (sampler.minFilter.value_or( + CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR)) { + case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR: + case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_NEAREST: + case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_LINEAR: + case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_NEAREST: + return true; + default: // LINEAR and NEAREST + return false; + } +} + +SharedFuture createTextureInLoadThread( + const AsyncSystem& asyncSystem, + CesiumGltf::Model& gltf, + CesiumGltf::TextureInfo& textureInfo, + bool sRGB, + const std::vector& imageNeedsMipmaps) { + CesiumGltf::Texture* pTexture = + CesiumGltf::Model::getSafe(&gltf.textures, textureInfo.index); + if (pTexture == nullptr) + return asyncSystem.createResolvedFuture().share(); + + CesiumGltf::Image* pImage = + CesiumGltf::Model::getSafe(&gltf.images, pTexture->source); + if (pImage == nullptr) + return asyncSystem.createResolvedFuture().share(); + + check(pTexture->source >= 0 && pTexture->source < imageNeedsMipmaps.size()); + bool needsMips = imageNeedsMipmaps[pTexture->source]; + + const ExtensionImageAssetUnreal& extension = + ExtensionImageAssetUnreal::getOrCreate( + asyncSystem, + *pImage->pAsset, + sRGB, + needsMips, + std::nullopt); + + return extension.getFuture(); +} + +} // namespace diff --git a/Source/CesiumRuntime/Private/CesiumGltfTextures.h b/Source/CesiumRuntime/Private/CesiumGltfTextures.h new file mode 100644 index 000000000..64540f7e9 --- /dev/null +++ b/Source/CesiumRuntime/Private/CesiumGltfTextures.h @@ -0,0 +1,25 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include + +namespace CesiumAsync { +class AsyncSystem; +} + +namespace CesiumGltf { +struct Model; +} + +class CesiumGltfTextures { +public: + /** + * Creates all of the texture resources that are required by the given glTF, + * and adds `ExtensionImageCesiumUnreal` to each. This is intended to be + * called from a worker thread. + */ + static CesiumAsync::Future createInWorkerThread( + const CesiumAsync::AsyncSystem& asyncSystem, + CesiumGltf::Model& model); +}; diff --git a/Source/CesiumRuntime/Private/CesiumLifetime.cpp b/Source/CesiumRuntime/Private/CesiumLifetime.cpp index f2ec767aa..6ea2c2a21 100644 --- a/Source/CesiumRuntime/Private/CesiumLifetime.cpp +++ b/Source/CesiumRuntime/Private/CesiumLifetime.cpp @@ -129,6 +129,7 @@ void AmortizedDestructor::finalizeDestroy(UObject* pObject) const { UTexture2D* pTexture2D = Cast(pObject); if (pTexture2D) { + pTexture2D->ReleaseResource(); FTexturePlatformData* pPlatformData = pTexture2D->GetPlatformData(); pTexture2D->SetPlatformData(nullptr); delete pPlatformData; diff --git a/Source/CesiumRuntime/Private/CesiumMetadataValue.cpp b/Source/CesiumRuntime/Private/CesiumMetadataValue.cpp index 42d351535..8fac58f33 100644 --- a/Source/CesiumRuntime/Private/CesiumMetadataValue.cpp +++ b/Source/CesiumRuntime/Private/CesiumMetadataValue.cpp @@ -6,8 +6,6 @@ #include #include -using namespace CesiumGltf; - FCesiumMetadataValue::FCesiumMetadataValue(FCesiumMetadataValue&& rhs) = default; @@ -18,7 +16,7 @@ FCesiumMetadataValue::FCesiumMetadataValue(const FCesiumMetadataValue& rhs) : _value(), _valueType(rhs._valueType), _storage(rhs._storage) { swl::visit( [this](const auto& value) { - if constexpr (IsMetadataArray::value) { + if constexpr (CesiumGltf::IsMetadataArray::value) { if (!this->_storage.empty()) { this->_value = decltype(value)(this->_storage); } else { @@ -274,9 +272,9 @@ FString UCesiumMetadataValueBlueprintLibrary::GetString( [&DefaultValue](auto value) -> FString { using ValueType = decltype(value); if constexpr ( - IsMetadataVecN::value || - IsMetadataMatN::value || - IsMetadataString::value) { + CesiumGltf::IsMetadataVecN::value || + CesiumGltf::IsMetadataMatN::value || + CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toString(value); } else { auto maybeString = CesiumGltf:: diff --git a/Source/CesiumRuntime/Private/CesiumModelMetadata.cpp b/Source/CesiumRuntime/Private/CesiumModelMetadata.cpp index 63866a624..4deb6615b 100644 --- a/Source/CesiumRuntime/Private/CesiumModelMetadata.cpp +++ b/Source/CesiumRuntime/Private/CesiumModelMetadata.cpp @@ -6,16 +6,14 @@ #include "CesiumGltfComponent.h" #include "CesiumGltfPrimitiveComponent.h" -using namespace CesiumGltf; - static FCesiumModelMetadata EmptyModelMetadata; static FCesiumPropertyTable EmptyPropertyTable; static FCesiumPropertyTexture EmptyPropertyTexture; FCesiumModelMetadata::FCesiumModelMetadata( - const Model& InModel, - const ExtensionModelExtStructuralMetadata& Metadata) { + const CesiumGltf::Model& InModel, + const CesiumGltf::ExtensionModelExtStructuralMetadata& Metadata) { this->_propertyTables.Reserve(Metadata.propertyTables.size()); for (const auto& propertyTable : Metadata.propertyTables) { this->_propertyTables.Emplace(FCesiumPropertyTable(InModel, propertyTable)); diff --git a/Source/CesiumRuntime/Private/CesiumPrimitiveFeatures.cpp b/Source/CesiumRuntime/Private/CesiumPrimitiveFeatures.cpp index ee31b4e58..f0ec01c09 100644 --- a/Source/CesiumRuntime/Private/CesiumPrimitiveFeatures.cpp +++ b/Source/CesiumRuntime/Private/CesiumPrimitiveFeatures.cpp @@ -5,20 +5,18 @@ #include "CesiumGltf/Model.h" #include "CesiumGltfPrimitiveComponent.h" -using namespace CesiumGltf; - static FCesiumPrimitiveFeatures EmptyPrimitiveFeatures; FCesiumPrimitiveFeatures::FCesiumPrimitiveFeatures( - const Model& Model, - const MeshPrimitive& Primitive, - const ExtensionExtMeshFeatures& Features) + const CesiumGltf::Model& Model, + const CesiumGltf::MeshPrimitive& Primitive, + const CesiumGltf::ExtensionExtMeshFeatures& Features) : _vertexCount(0), _primitiveMode(Primitive.mode) { this->_indexAccessor = CesiumGltf::getIndexAccessorView(Model, Primitive); auto positionIt = Primitive.attributes.find("POSITION"); if (positionIt != Primitive.attributes.end()) { - const Accessor& positionAccessor = + const CesiumGltf::Accessor& positionAccessor = Model.getSafe(Model.accessors, positionIt->second); _vertexCount = positionAccessor.count; } diff --git a/Source/CesiumRuntime/Private/CesiumPropertyArray.cpp b/Source/CesiumRuntime/Private/CesiumPropertyArray.cpp index a40fc0c7e..9003116c3 100644 --- a/Source/CesiumRuntime/Private/CesiumPropertyArray.cpp +++ b/Source/CesiumRuntime/Private/CesiumPropertyArray.cpp @@ -3,8 +3,6 @@ #include "CesiumPropertyArray.h" #include -using namespace CesiumGltf; - FCesiumPropertyArray::FCesiumPropertyArray(FCesiumPropertyArray&& rhs) = default; @@ -15,7 +13,7 @@ FCesiumPropertyArray::FCesiumPropertyArray(const FCesiumPropertyArray& rhs) : _value(), _elementType(rhs._elementType), _storage(rhs._storage) { swl::visit( [this](const auto& value) { - if constexpr (IsMetadataArray::value) { + if constexpr (CesiumGltf::IsMetadataArray::value) { if (!this->_storage.empty()) { this->_value = decltype(value)(this->_storage); } else { diff --git a/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp b/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp index 9f803e9f6..83a16af47 100644 --- a/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp +++ b/Source/CesiumRuntime/Private/CesiumPropertyTable.cpp @@ -3,21 +3,19 @@ #include "CesiumPropertyTable.h" #include "CesiumGltf/PropertyTableView.h" -using namespace CesiumGltf; - static FCesiumPropertyTableProperty EmptyPropertyTableProperty; FCesiumPropertyTable::FCesiumPropertyTable( - const Model& Model, - const PropertyTable& PropertyTable) + const CesiumGltf::Model& Model, + const CesiumGltf::PropertyTable& PropertyTable) : _status(ECesiumPropertyTableStatus::ErrorInvalidPropertyTableClass), _name(PropertyTable.name.value_or("").c_str()), _className(PropertyTable.classProperty.c_str()), _count(PropertyTable.count), _properties() { - PropertyTableView propertyTableView{Model, PropertyTable}; + CesiumGltf::PropertyTableView propertyTableView{Model, PropertyTable}; switch (propertyTableView.status()) { - case PropertyTableViewStatus::Valid: + case CesiumGltf::PropertyTableViewStatus::Valid: _status = ECesiumPropertyTableStatus::Valid; break; default: diff --git a/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp b/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp index 6e086f752..dda61f6f2 100644 --- a/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp +++ b/Source/CesiumRuntime/Private/CesiumPropertyTableProperty.cpp @@ -6,8 +6,6 @@ #include "UnrealMetadataConversions.h" #include -using namespace CesiumGltf; - namespace { /** * Callback on a std::any, assuming that it contains a PropertyTablePropertyView @@ -29,14 +27,15 @@ template < typename Callback> TResult propertyTablePropertyCallback(const std::any& property, Callback&& callback) { - const PropertyTablePropertyView* pProperty = - std::any_cast>( + const CesiumGltf::PropertyTablePropertyView* + pProperty = std::any_cast< + CesiumGltf::PropertyTablePropertyView>( &property); if (pProperty) { return callback(*pProperty); } - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } /** @@ -113,7 +112,7 @@ TResult scalarPropertyTablePropertyCallback( property, std::forward(callback)); default: - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } } @@ -139,66 +138,66 @@ TResult scalarArrayPropertyTablePropertyCallback( switch (valueType.ComponentType) { case ECesiumMetadataComponentType::Int8: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint8: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int16: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint16: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int32: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint32: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int64: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint64: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Float32: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, false, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Float64: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, false, TResult, Callback>(property, std::forward(callback)); default: - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } } @@ -283,7 +282,7 @@ TResult vecNPropertyTablePropertyCallback( TResult, Callback>(property, std::forward(callback)); default: - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } } @@ -326,7 +325,7 @@ TResult vecNPropertyTablePropertyCallback( std::forward(callback)); } - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } /** @@ -352,66 +351,66 @@ TResult vecNArrayPropertyTablePropertyCallback( switch (valueType.ComponentType) { case ECesiumMetadataComponentType::Int8: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint8: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int16: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint16: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int32: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint32: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int64: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint64: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Float32: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, false, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Float64: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, false, TResult, Callback>(property, std::forward(callback)); default: - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } } @@ -458,7 +457,7 @@ TResult vecNArrayPropertyTablePropertyCallback( Callback>(property, valueType, std::forward(callback)); } - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } /** @@ -542,7 +541,7 @@ TResult matNPropertyTablePropertyCallback( TResult, Callback>(property, std::forward(callback)); default: - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } } @@ -585,7 +584,7 @@ TResult matNPropertyTablePropertyCallback( std::forward(callback)); } - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } /** @@ -611,66 +610,66 @@ TResult matNArrayPropertyTablePropertyCallback( switch (valueType.ComponentType) { case ECesiumMetadataComponentType::Int8: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint8: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int16: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint16: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int32: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint32: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int64: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint64: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Float32: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, false, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Float64: return propertyTablePropertyCallback< - PropertyArrayView>, + CesiumGltf::PropertyArrayView>, false, TResult, Callback>(property, std::forward(callback)); default: - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } } @@ -717,7 +716,7 @@ TResult matNArrayPropertyTablePropertyCallback( Callback>(property, valueType, std::forward(callback)); } - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } template @@ -747,18 +746,18 @@ TResult arrayPropertyTablePropertyCallback( Callback>(property, valueType, std::forward(callback)); case ECesiumMetadataType::Boolean: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, false, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataType::String: return propertyTablePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, false, TResult, Callback>(property, std::forward(callback)); default: - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } } @@ -826,7 +825,7 @@ TResult propertyTablePropertyCallback( TResult, Callback>(property, std::forward(callback)); default: - return callback(PropertyTablePropertyView()); + return callback(CesiumGltf::PropertyTablePropertyView()); } } @@ -1044,7 +1043,7 @@ FIntPoint UCesiumPropertyTablePropertyBlueprintLibrary::GetIntPoint( } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toIntPoint(value, DefaultValue); } else { auto maybeVec2 = CesiumGltf:: @@ -1074,7 +1073,7 @@ FVector2D UCesiumPropertyTablePropertyBlueprintLibrary::GetVector2D( } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toVector2D(value, DefaultValue); } else { auto maybeVec2 = CesiumGltf:: @@ -1104,7 +1103,7 @@ FIntVector UCesiumPropertyTablePropertyBlueprintLibrary::GetIntVector( } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toIntVector(value, DefaultValue); } else { auto maybeVec3 = CesiumGltf:: @@ -1134,7 +1133,7 @@ FVector3f UCesiumPropertyTablePropertyBlueprintLibrary::GetVector3f( } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toVector3f(value, DefaultValue); } else { auto maybeVec3 = CesiumGltf:: @@ -1164,7 +1163,7 @@ FVector UCesiumPropertyTablePropertyBlueprintLibrary::GetVector( } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toVector(value, DefaultValue); } else { auto maybeVec3 = CesiumGltf:: @@ -1194,7 +1193,7 @@ FVector4 UCesiumPropertyTablePropertyBlueprintLibrary::GetVector4( } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toVector4(value, DefaultValue); } else { auto maybeVec4 = CesiumGltf:: @@ -1254,9 +1253,9 @@ FString UCesiumPropertyTablePropertyBlueprintLibrary::GetString( using ValueType = decltype(value); if constexpr ( - IsMetadataVecN::value || - IsMetadataMatN::value || - IsMetadataString::value) { + CesiumGltf::IsMetadataVecN::value || + CesiumGltf::IsMetadataMatN::value || + CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toString(value); } else { auto maybeString = CesiumGltf:: @@ -1316,15 +1315,15 @@ FCesiumMetadataValue UCesiumPropertyTablePropertyBlueprintLibrary::GetRawValue( Property._normalized, [FeatureID](const auto& view) -> FCesiumMetadataValue { // Return an empty value if the property is empty. - if (view.status() == - PropertyTablePropertyViewStatus::EmptyPropertyWithDefault) { + if (view.status() == CesiumGltf::PropertyTablePropertyViewStatus:: + EmptyPropertyWithDefault) { return FCesiumMetadataValue(); } // size() returns zero if the view is invalid. if (FeatureID >= 0 && FeatureID < view.size()) { return FCesiumMetadataValue( - propertyValueViewToCopy(view.getRaw(FeatureID))); + CesiumGltf::propertyValueViewToCopy(view.getRaw(FeatureID))); } return FCesiumMetadataValue(); @@ -1344,7 +1343,8 @@ FCesiumMetadataValue UCesiumPropertyTablePropertyBlueprintLibrary::GetOffset( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no offset is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.offset())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.offset())); }); } @@ -1356,7 +1356,8 @@ FCesiumMetadataValue UCesiumPropertyTablePropertyBlueprintLibrary::GetScale( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no scale is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.scale())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.scale())); }); } @@ -1369,7 +1370,8 @@ UCesiumPropertyTablePropertyBlueprintLibrary::GetMinimumValue( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no min is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.min())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.min())); }); } @@ -1382,7 +1384,8 @@ UCesiumPropertyTablePropertyBlueprintLibrary::GetMaximumValue( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no max is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.max())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.max())); }); } @@ -1395,7 +1398,8 @@ UCesiumPropertyTablePropertyBlueprintLibrary::GetNoDataValue( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no "no data" value is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.noData())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.noData())); }); } @@ -1409,7 +1413,7 @@ UCesiumPropertyTablePropertyBlueprintLibrary::GetDefaultValue( [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no default value is specified. return FCesiumMetadataValue( - propertyValueViewToCopy(view.defaultValue())); + CesiumGltf::propertyValueViewToCopy(view.defaultValue())); }); } diff --git a/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp b/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp index e69be7349..ffefd3e3b 100644 --- a/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp +++ b/Source/CesiumRuntime/Private/CesiumPropertyTexture.cpp @@ -6,8 +6,6 @@ #include "CesiumGltf/PropertyTextureView.h" #include "CesiumMetadataPickingBlueprintLibrary.h" -using namespace CesiumGltf; - static FCesiumPropertyTextureProperty EmptyPropertyTextureProperty; FCesiumPropertyTexture::FCesiumPropertyTexture( @@ -16,9 +14,9 @@ FCesiumPropertyTexture::FCesiumPropertyTexture( : _status(ECesiumPropertyTextureStatus::ErrorInvalidPropertyTextureClass), _name(PropertyTexture.name.value_or("").c_str()), _className(PropertyTexture.classProperty.c_str()) { - PropertyTextureView propertyTextureView(Model, PropertyTexture); + CesiumGltf::PropertyTextureView propertyTextureView(Model, PropertyTexture); switch (propertyTextureView.status()) { - case PropertyTextureViewStatus::Valid: + case CesiumGltf::PropertyTextureViewStatus::Valid: _status = ECesiumPropertyTextureStatus::Valid; break; default: @@ -35,7 +33,7 @@ FCesiumPropertyTexture::FCesiumPropertyTexture( continue; } - TextureViewOptions options; + CesiumGltf::TextureViewOptions options; options.applyKhrTextureTransformExtension = true; if (propertyPair->second.extras.find("makeImageCopy") != diff --git a/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp b/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp index 0cd8653fa..082e2ffb1 100644 --- a/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp +++ b/Source/CesiumRuntime/Private/CesiumPropertyTextureProperty.cpp @@ -8,8 +8,6 @@ #include #include -using namespace CesiumGltf; - namespace { /** * Callback on a std::any, assuming that it contains a @@ -32,14 +30,15 @@ template < typename Callback> TResult propertyTexturePropertyCallback(const std::any& property, Callback&& callback) { - const PropertyTexturePropertyView* pProperty = - std::any_cast>( + const CesiumGltf::PropertyTexturePropertyView* + pProperty = std::any_cast< + CesiumGltf::PropertyTexturePropertyView>( &property); if (pProperty) { return callback(*pProperty); } - return callback(PropertyTexturePropertyView()); + return callback(CesiumGltf::PropertyTexturePropertyView()); } /** @@ -103,7 +102,7 @@ TResult scalarPropertyTexturePropertyCallback( property, std::forward(callback)); default: - return callback(PropertyTexturePropertyView()); + return callback(CesiumGltf::PropertyTexturePropertyView()); } } @@ -129,30 +128,30 @@ TResult scalarArrayPropertyTexturePropertyCallback( switch (valueType.ComponentType) { case ECesiumMetadataComponentType::Int8: return propertyTexturePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint8: return propertyTexturePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Int16: return propertyTexturePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); case ECesiumMetadataComponentType::Uint16: return propertyTexturePropertyCallback< - PropertyArrayView, + CesiumGltf::PropertyArrayView, Normalized, TResult, Callback>(property, std::forward(callback)); default: - return callback(PropertyTexturePropertyView()); + return callback(CesiumGltf::PropertyTexturePropertyView()); } } @@ -202,7 +201,7 @@ TResult vecNPropertyTexturePropertyCallback( TResult, Callback>(property, std::forward(callback)); default: - return callback(PropertyTexturePropertyView()); + return callback(CesiumGltf::PropertyTexturePropertyView()); } } @@ -249,7 +248,7 @@ TResult vecNPropertyTexturePropertyCallback( Callback>(property, valueType, std::forward(callback)); } - return callback(PropertyTexturePropertyView()); + return callback(CesiumGltf::PropertyTexturePropertyView()); } template @@ -262,7 +261,7 @@ TResult propertyTexturePropertyCallback( if (valueType.bIsArray && valueType.Type != ECesiumMetadataType::Scalar) { // Only scalar property arrays are supported. - return callback(PropertyTexturePropertyView()); + return callback(CesiumGltf::PropertyTexturePropertyView()); } if (valueType.bIsArray) { @@ -309,7 +308,7 @@ TResult propertyTexturePropertyCallback( valueType, std::forward(callback)); default: - return callback(PropertyTexturePropertyView()); + return callback(CesiumGltf::PropertyTexturePropertyView()); } } @@ -333,13 +332,12 @@ const CesiumGltf::Sampler* FCesiumPropertyTextureProperty::getSampler() const { }); } -const CesiumGltf::ImageCesium* -FCesiumPropertyTextureProperty::getImage() const { - return propertyTexturePropertyCallback( +const CesiumGltf::ImageAsset* FCesiumPropertyTextureProperty::getImage() const { + return propertyTexturePropertyCallback( this->_property, this->_valueType, this->_normalized, - [](const auto& view) -> const CesiumGltf::ImageCesium* { + [](const auto& view) -> const CesiumGltf::ImageAsset* { return view.getImage(); }); } @@ -475,7 +473,8 @@ uint8 UCesiumPropertyTexturePropertyBlueprintLibrary::GetByte( Property._valueType, Property._normalized, [&UV, DefaultValue](const auto& view) -> uint8 { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return DefaultValue; } auto maybeValue = view.get(UV.X, UV.Y); @@ -498,7 +497,8 @@ int32 UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger( Property._valueType, Property._normalized, [&UV, DefaultValue](const auto& view) -> int32 { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return DefaultValue; } auto maybeValue = view.get(UV.X, UV.Y); @@ -521,7 +521,8 @@ float UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat( Property._valueType, Property._normalized, [&UV, DefaultValue](const auto& view) -> float { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return DefaultValue; } auto maybeValue = view.get(UV.X, UV.Y); @@ -544,7 +545,8 @@ double UCesiumPropertyTexturePropertyBlueprintLibrary::GetFloat64( Property._valueType, Property._normalized, [&UV, DefaultValue](const auto& view) -> double { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return DefaultValue; } auto maybeValue = view.get(UV.X, UV.Y); @@ -567,7 +569,8 @@ FIntPoint UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntPoint( Property._valueType, Property._normalized, [&UV, &DefaultValue](const auto& view) -> FIntPoint { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return DefaultValue; } auto maybeValue = view.get(UV.X, UV.Y); @@ -575,7 +578,7 @@ FIntPoint UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntPoint( return DefaultValue; } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toIntPoint( *maybeValue, DefaultValue); @@ -597,7 +600,8 @@ FVector2D UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector2D( Property._valueType, Property._normalized, [&UV, &DefaultValue](const auto& view) -> FVector2D { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return DefaultValue; } auto maybeValue = view.get(UV.X, UV.Y); @@ -605,7 +609,7 @@ FVector2D UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector2D( return DefaultValue; } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toVector2D(value, DefaultValue); } else { auto maybeVec2 = CesiumGltf:: @@ -625,7 +629,8 @@ FIntVector UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntVector( Property._valueType, Property._normalized, [&UV, &DefaultValue](const auto& view) -> FIntVector { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return DefaultValue; } auto maybeValue = view.get(UV.X, UV.Y); @@ -633,7 +638,7 @@ FIntVector UCesiumPropertyTexturePropertyBlueprintLibrary::GetIntVector( return DefaultValue; } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toIntVector(value, DefaultValue); } else { auto maybeVec3 = CesiumGltf:: @@ -653,7 +658,8 @@ FVector UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( Property._valueType, Property._normalized, [&UV, &DefaultValue](const auto& view) -> FVector { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return DefaultValue; } auto maybeValue = view.get(UV.X, UV.Y); @@ -661,7 +667,7 @@ FVector UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector( return DefaultValue; } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toVector(value, DefaultValue); } else { auto maybeVec3 = CesiumGltf:: @@ -681,7 +687,8 @@ FVector4 UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector4( Property._valueType, Property._normalized, [&UV, &DefaultValue](const auto& view) -> FVector4 { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return DefaultValue; } auto maybeValue = view.get(UV.X, UV.Y); @@ -689,7 +696,7 @@ FVector4 UCesiumPropertyTexturePropertyBlueprintLibrary::GetVector4( return DefaultValue; } auto value = *maybeValue; - if constexpr (IsMetadataString::value) { + if constexpr (CesiumGltf::IsMetadataString::value) { return UnrealMetadataConversions::toVector(value, DefaultValue); } else { auto maybeVec4 = CesiumGltf:: @@ -708,7 +715,8 @@ FCesiumPropertyArray UCesiumPropertyTexturePropertyBlueprintLibrary::GetArray( Property._valueType, Property._normalized, [&UV](const auto& view) -> FCesiumPropertyArray { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return FCesiumPropertyArray(); } auto maybeValue = view.get(UV.X, UV.Y); @@ -730,9 +738,10 @@ FCesiumMetadataValue UCesiumPropertyTexturePropertyBlueprintLibrary::GetValue( Property._valueType, Property._normalized, [&UV](const auto& view) -> FCesiumMetadataValue { - if (view.status() != PropertyTexturePropertyViewStatus::Valid && - view.status() != - PropertyTexturePropertyViewStatus::EmptyPropertyWithDefault) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid && + view.status() != CesiumGltf::PropertyTexturePropertyViewStatus:: + EmptyPropertyWithDefault) { return FCesiumMetadataValue(); } @@ -749,7 +758,8 @@ UCesiumPropertyTexturePropertyBlueprintLibrary::GetRawValue( Property._valueType, Property._normalized, [&UV](const auto& view) -> FCesiumMetadataValue { - if (view.status() != PropertyTexturePropertyViewStatus::Valid) { + if (view.status() != + CesiumGltf::PropertyTexturePropertyViewStatus::Valid) { return FCesiumMetadataValue(); } @@ -770,7 +780,8 @@ FCesiumMetadataValue UCesiumPropertyTexturePropertyBlueprintLibrary::GetOffset( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no offset is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.offset())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.offset())); }); } @@ -782,7 +793,8 @@ FCesiumMetadataValue UCesiumPropertyTexturePropertyBlueprintLibrary::GetScale( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no scale is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.scale())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.scale())); }); } @@ -795,7 +807,8 @@ UCesiumPropertyTexturePropertyBlueprintLibrary::GetMinimumValue( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no min is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.min())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.min())); }); } @@ -808,7 +821,8 @@ UCesiumPropertyTexturePropertyBlueprintLibrary::GetMaximumValue( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no max is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.max())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.max())); }); } @@ -821,7 +835,8 @@ UCesiumPropertyTexturePropertyBlueprintLibrary::GetNoDataValue( Property._normalized, [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no "no data" value is specified. - return FCesiumMetadataValue(propertyValueViewToCopy(view.noData())); + return FCesiumMetadataValue( + CesiumGltf::propertyValueViewToCopy(view.noData())); }); } @@ -835,6 +850,6 @@ UCesiumPropertyTexturePropertyBlueprintLibrary::GetDefaultValue( [](const auto& view) -> FCesiumMetadataValue { // Returns an empty value if no default value is specified. return FCesiumMetadataValue( - propertyValueViewToCopy(view.defaultValue())); + CesiumGltf::propertyValueViewToCopy(view.defaultValue())); }); } diff --git a/Source/CesiumRuntime/Private/CesiumTextureResource.cpp b/Source/CesiumRuntime/Private/CesiumTextureResource.cpp index 1bbeb5a59..ea715d522 100644 --- a/Source/CesiumRuntime/Private/CesiumTextureResource.cpp +++ b/Source/CesiumRuntime/Private/CesiumTextureResource.cpp @@ -1,11 +1,94 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors #include "CesiumTextureResource.h" +#include "CesiumRuntime.h" +#include "CesiumTextureUtility.h" #include "Misc/CoreStats.h" #include "RenderUtils.h" +#include namespace { +/** + * A Cesium texture resource that uses an already-created `FRHITexture`. This is + * used when `GRHISupportsAsyncTextureCreation` is true and so we were already + * able to create the FRHITexture in a worker thread. It is also used when a + * single glTF `Image` is referenced by multiple glTF `Texture` instances. We + * only need one `FRHITexture` is this case, but we need multiple + * `FTextureResource` instances to support the different sampler settings that + * are likely used in the different textures. + */ +class FCesiumUseExistingTextureResource : public FCesiumTextureResource { +public: + FCesiumUseExistingTextureResource( + FTextureRHIRef existingTexture, + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData, + bool isPrimary); + + FCesiumUseExistingTextureResource( + const TSharedPtr& pExistingTexture, + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData, + bool isPrimary); + +protected: + virtual FTextureRHIRef InitializeTextureRHI() override; + +private: + TSharedPtr _pExistingTexture; +}; + +/** + * A Cesium texture resource that creates an `FRHITexture` from a glTF + * `ImageCesium` when `InitRHI` is called from the render thread. When + * `GRHISupportsAsyncTextureCreation` is false (everywhere but Direct3D), we can + * only create a `FRHITexture` on the render thread, so this is the code that + * does it. + * + * Upon passing an `ImageAsset` to this class's constructor, its `pixelData` and + * `mipPositions` fields are cleared. That is, this class takes ownership of + * that data. + */ +class FCesiumCreateNewTextureResource : public FCesiumTextureResource { +public: + FCesiumCreateNewTextureResource( + CesiumGltf::ImageAsset& image, + TextureGroup textureGroup, + uint32 width, + uint32 height, + EPixelFormat format, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipsIfAvailable, + uint32 extData); + +protected: + virtual FTextureRHIRef InitializeTextureRHI() override; + +private: + std::vector _mipPositions; + std::vector _pixelData; +}; + ESamplerFilter convertFilter(TextureFilter filter) { switch (filter) { case TF_Nearest: @@ -48,25 +131,27 @@ void CopyMip( void* pDest, uint32 destPitch, EPixelFormat format, - const CesiumGltf::ImageCesium& src, + int32_t width, + int32_t height, + const std::vector& srcPixelData, + const std::vector& srcMipPositions, uint32 mipIndex) { size_t byteOffset = 0; size_t byteSize = 0; - if (src.mipPositions.empty()) { + if (srcMipPositions.empty()) { byteOffset = 0; - byteSize = src.pixelData.size(); + byteSize = srcPixelData.size(); } else { - const CesiumGltf::ImageCesiumMipPosition& mipPos = - src.mipPositions[mipIndex]; + const CesiumGltf::ImageAssetMipPosition& mipPos = srcMipPositions[mipIndex]; byteOffset = mipPos.byteOffset; byteSize = mipPos.byteSize; } uint32 mipWidth = - FMath::Max(static_cast(src.width) >> mipIndex, 1); + FMath::Max(static_cast(width) >> mipIndex, 1); uint32 mipHeight = - FMath::Max(static_cast(src.height) >> mipIndex, 1); + FMath::Max(static_cast(height) >> mipIndex, 1); - const void* pSrcData = static_cast(&src.pixelData[byteOffset]); + const void* pSrcData = static_cast(&srcPixelData[byteOffset]); // for platforms that returned 0 pitch from Lock, we need to just use the bulk // data directly, never do runtime block size checking, conversion, or the @@ -98,9 +183,271 @@ void CopyMip( } } +FTexture2DRHIRef createAsyncTextureAndWait( + uint32 SizeX, + uint32 SizeY, + uint8 Format, + uint32 NumMips, + ETextureCreateFlags Flags, + void** InitialMipData, + uint32 NumInitialMips) { + +#if ENGINE_VERSION_5_4_OR_HIGHER + FGraphEventRef CompletionEvent; + + FTexture2DRHIRef result = RHIAsyncCreateTexture2D( + SizeX, + SizeY, + Format, + NumMips, + Flags, + ERHIAccess::Unknown, + InitialMipData, + NumInitialMips, + TEXT("CesiumTexture"), + CompletionEvent); + + if (CompletionEvent) { + CompletionEvent->Wait(); + } + + return result; +#elif ENGINE_VERSION_5_3_OR_HIGHER + FGraphEventRef CompletionEvent; + + FTexture2DRHIRef result = RHIAsyncCreateTexture2D( + SizeX, + SizeY, + Format, + NumMips, + Flags, + InitialMipData, + NumInitialMips, + CompletionEvent); + + if (CompletionEvent) { + CompletionEvent->Wait(); + } + + return result; +#else + return RHIAsyncCreateTexture2D( + SizeX, + SizeY, + Format, + NumMips, + Flags, + InitialMipData, + NumInitialMips); +#endif +} + +/** + * @brief Create an RHI texture on this thread. This requires + * GRHISupportsAsyncTextureCreation to be true. + * + * @param image The CPU image to create on the GPU. + * @param format The pixel format of the image. + * @param Whether to use a sRGB color-space. + * @return The RHI texture reference. + */ +FTexture2DRHIRef CreateRHITexture2D_Async( + const CesiumGltf::ImageAsset& image, + EPixelFormat format, + bool sRGB) { + check(GRHISupportsAsyncTextureCreation); + + ETextureCreateFlags textureFlags = TexCreate_ShaderResource; + + // Just like in FCesiumCreateNewTextureResource, we're assuming here that we + // can create an FRHITexture as sRGB, and later create another + // UTexture2D / FTextureResource pointing to the same FRHITexture that is not + // sRGB (or vice-versa), and that Unreal will effectively ignore the flag on + // FRHITexture. + if (sRGB) { + textureFlags |= TexCreate_SRGB; + } + + if (!image.mipPositions.empty()) { + // Here 16 is a generously large (but arbitrary) hard limit for number of + // mips. + uint32 mipCount = static_cast(image.mipPositions.size()); + if (mipCount > 16) { + mipCount = 16; + } + + void* mipsData[16]; + for (size_t i = 0; i < mipCount; ++i) { + const CesiumGltf::ImageAssetMipPosition& mipPos = image.mipPositions[i]; + mipsData[i] = (void*)(&image.pixelData[mipPos.byteOffset]); + } + + return createAsyncTextureAndWait( + static_cast(image.width), + static_cast(image.height), + format, + mipCount, + textureFlags, + mipsData, + mipCount); + } else { + void* pTextureData = (void*)(image.pixelData.data()); + return createAsyncTextureAndWait( + static_cast(image.width), + static_cast(image.height), + format, + 1, + textureFlags, + &pTextureData, + 1); + } +} + } // namespace -FCesiumTextureResourceBase::FCesiumTextureResourceBase( +void FCesiumTextureResourceDeleter::operator()(FCesiumTextureResource* p) { + FCesiumTextureResource::Destroy(p); +} + +/*static*/ FCesiumTextureResourceUniquePtr FCesiumTextureResource::CreateNew( + CesiumGltf::ImageAsset& imageCesium, + TextureGroup textureGroup, + const std::optional& overridePixelFormat, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool needsMipMaps) { + if (imageCesium.pixelData.empty()) { + return nullptr; + } + + if (needsMipMaps) { + std::optional errorMessage = + CesiumGltfReader::ImageDecoder::generateMipMaps(imageCesium); + if (errorMessage) { + UE_LOG( + LogCesium, + Warning, + TEXT("%s"), + UTF8_TO_TCHAR(errorMessage->c_str())); + } + } + + std::optional maybePixelFormat = + CesiumTextureUtility::getPixelFormatForImageAsset( + imageCesium, + overridePixelFormat); + if (!maybePixelFormat) { + UE_LOG( + LogCesium, + Warning, + TEXT( + "Image cannot be created because it has an unsupported compressed pixel format (%d)."), + imageCesium.compressedPixelFormat); + return nullptr; + } + + // Store the current size of the pixel data, because + // we're about to clear it but we still want to have + // an accurate estimation of the size of the image for + // caching purposes. + imageCesium.sizeBytes = int64_t(imageCesium.pixelData.size()); + + if (GRHISupportsAsyncTextureCreation) { + // Create RHI texture resource on this worker + // thread, and then hand it off to the renderer + // thread. + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CreateRHITexture2D) + + FTexture2DRHIRef textureReference = + CreateRHITexture2D_Async(imageCesium, *maybePixelFormat, sRGB); + // textureReference->SetName( + // FName(UTF8_TO_TCHAR(imageCesium.getUniqueAssetId().c_str()))); + auto pResult = + FCesiumTextureResourceUniquePtr(new FCesiumUseExistingTextureResource( + textureReference, + textureGroup, + imageCesium.width, + imageCesium.height, + *maybePixelFormat, + filter, + addressX, + addressY, + sRGB, + needsMipMaps, + 0, + true)); + + // Clear the now-unnecessary copy of the pixel data. + // Calling clear() isn't good enough because it + // won't actually release the memory. + std::vector pixelData; + imageCesium.pixelData.swap(pixelData); + + std::vector mipPositions; + imageCesium.mipPositions.swap(mipPositions); + + return pResult; + } else { + // The RHI texture will be created later on the + // render thread, directly from this texture source. + // We need valid pixelData here, though. + auto pResult = + FCesiumTextureResourceUniquePtr(new FCesiumCreateNewTextureResource( + imageCesium, + textureGroup, + imageCesium.width, + imageCesium.height, + *maybePixelFormat, + filter, + addressX, + addressY, + sRGB, + needsMipMaps, + 0)); + return pResult; + } +} + +FCesiumTextureResourceUniquePtr FCesiumTextureResource::CreateWrapped( + const TSharedPtr& pExistingResource, + TextureGroup textureGroup, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipMapsIfAvailable) { + if (pExistingResource == nullptr) + return nullptr; + + return FCesiumTextureResourceUniquePtr(new FCesiumUseExistingTextureResource( + pExistingResource, + textureGroup, + pExistingResource->_width, + pExistingResource->_height, + pExistingResource->_format, + filter, + addressX, + addressY, + sRGB, + useMipMapsIfAvailable, + 0, + false)); +} + +/*static*/ void FCesiumTextureResource::Destroy(FCesiumTextureResource* p) { + if (p == nullptr) + return; + + ENQUEUE_RENDER_COMMAND(DeleteResource) + ([p](FRHICommandListImmediate& RHICmdList) { + p->ReleaseResource(); + delete p; + }); +} + +FCesiumTextureResource::FCesiumTextureResource( TextureGroup textureGroup, uint32 width, uint32 height, @@ -110,7 +457,8 @@ FCesiumTextureResourceBase::FCesiumTextureResourceBase( TextureAddress addressY, bool sRGB, bool useMipsIfAvailable, - uint32 extData) + uint32 extData, + bool isPrimary) : _textureGroup(textureGroup), _width(width), _height(height), @@ -119,16 +467,17 @@ FCesiumTextureResourceBase::FCesiumTextureResourceBase( _addressX(convertAddressMode(addressX)), _addressY(convertAddressMode(addressY)), _useMipsIfAvailable(useMipsIfAvailable), - _platformExtData(extData) { + _platformExtData(extData), + _isPrimary(isPrimary) { this->bGreyScaleFormat = (_format == PF_G8) || (_format == PF_BC4); this->bSRGB = sRGB; STAT(this->_lodGroupStatName = TextureGroupStatFNames[this->_textureGroup]); } #if ENGINE_VERSION_5_3_OR_HIGHER -void FCesiumTextureResourceBase::InitRHI(FRHICommandListBase& RHICmdList) { +void FCesiumTextureResource::InitRHI(FRHICommandListBase& RHICmdList) { #else -void FCesiumTextureResourceBase::InitRHI() { +void FCesiumTextureResource::InitRHI() { #endif FSamplerStateInitializerRHI samplerStateInitializer( this->_filter, @@ -165,32 +514,40 @@ void FCesiumTextureResourceBase::InitRHI() { RHIUpdateTextureReference(TextureReferenceRHI, this->TextureRHI); #if STATS - ETextureCreateFlags textureFlags = TexCreate_ShaderResource; - if (this->bSRGB) { - textureFlags |= TexCreate_SRGB; - } - - const FIntPoint MipExtents = - CalcMipMapExtent(this->_width, this->_height, this->_format, 0); - uint32 alignment; - this->_textureSize = RHICalcTexture2DPlatformSize( - MipExtents.X, - MipExtents.Y, - this->_format, - this->GetCurrentMipCount(), - 1, - textureFlags, - FRHIResourceCreateInfo(this->_platformExtData), - alignment); + if (this->_isPrimary) { + ETextureCreateFlags textureFlags = TexCreate_ShaderResource; + if (this->bSRGB) { + textureFlags |= TexCreate_SRGB; + } - INC_DWORD_STAT_BY(STAT_TextureMemory, this->_textureSize); - INC_DWORD_STAT_FNAME_BY(this->_lodGroupStatName, this->_textureSize); + const FIntPoint MipExtents = + CalcMipMapExtent(this->_width, this->_height, this->_format, 0); + const FRHIResourceCreateInfo CreateInfo(this->_platformExtData); + + uint32 alignment; + this->_textureSize = RHICalcTexture2DPlatformSize( + MipExtents.X, + MipExtents.Y, + this->_format, + this->GetCurrentMipCount(), + 1, + textureFlags, + FRHIResourceCreateInfo(this->_platformExtData), + alignment); + + INC_DWORD_STAT_BY(STAT_TextureMemory, this->_textureSize); + INC_DWORD_STAT_FNAME_BY(this->_lodGroupStatName, this->_textureSize); + } #endif } -void FCesiumTextureResourceBase::ReleaseRHI() { - DEC_DWORD_STAT_BY(STAT_TextureMemory, this->_textureSize); - DEC_DWORD_STAT_FNAME_BY(this->_lodGroupStatName, this->_textureSize); +void FCesiumTextureResource::ReleaseRHI() { +#if STATS + if (this->_isPrimary) { + DEC_DWORD_STAT_BY(STAT_TextureMemory, this->_textureSize); + DEC_DWORD_STAT_FNAME_BY(this->_lodGroupStatName, this->_textureSize); + } +#endif RHIUpdateTextureReference(TextureReferenceRHI, nullptr); @@ -216,7 +573,7 @@ FOREACH_ENUM_TEXTUREGROUP(DECLARETEXTUREGROUPSTAT) #undef DECLARETEXTUREGROUPSTAT } // namespace -FName FCesiumTextureResourceBase::TextureGroupStatFNames[TEXTUREGROUP_MAX] = { +FName FCesiumTextureResource::TextureGroupStatFNames[TEXTUREGROUP_MAX] = { #define ASSIGNTEXTUREGROUPSTATNAME(Group) GET_STATFNAME(STAT_##Group), FOREACH_ENUM_TEXTUREGROUP(ASSIGNTEXTUREGROUPSTATNAME) #undef ASSIGNTEXTUREGROUPSTATNAME @@ -235,8 +592,9 @@ FCesiumUseExistingTextureResource::FCesiumUseExistingTextureResource( TextureAddress addressY, bool sRGB, bool useMipsIfAvailable, - uint32 extData) - : FCesiumTextureResourceBase( + uint32 extData, + bool isPrimary) + : FCesiumTextureResource( textureGroup, width, height, @@ -246,13 +604,14 @@ FCesiumUseExistingTextureResource::FCesiumUseExistingTextureResource( addressY, sRGB, useMipsIfAvailable, - extData), + extData, + isPrimary), _pExistingTexture(nullptr) { this->TextureRHI = std::move(existingTexture); } FCesiumUseExistingTextureResource::FCesiumUseExistingTextureResource( - FTextureResource* pExistingTexture, + const TSharedPtr& pExistingTexture, TextureGroup textureGroup, uint32 width, uint32 height, @@ -262,8 +621,9 @@ FCesiumUseExistingTextureResource::FCesiumUseExistingTextureResource( TextureAddress addressY, bool sRGB, bool useMipsIfAvailable, - uint32 extData) - : FCesiumTextureResourceBase( + uint32 extData, + bool isPrimary) + : FCesiumTextureResource( textureGroup, width, height, @@ -273,7 +633,8 @@ FCesiumUseExistingTextureResource::FCesiumUseExistingTextureResource( addressY, sRGB, useMipsIfAvailable, - extData), + extData, + isPrimary), _pExistingTexture(pExistingTexture) {} FTextureRHIRef FCesiumUseExistingTextureResource::InitializeTextureRHI() { @@ -285,7 +646,7 @@ FTextureRHIRef FCesiumUseExistingTextureResource::InitializeTextureRHI() { } FCesiumCreateNewTextureResource::FCesiumCreateNewTextureResource( - CesiumGltf::ImageCesium&& image, + CesiumGltf::ImageAsset& image, TextureGroup textureGroup, uint32 width, uint32 height, @@ -296,7 +657,7 @@ FCesiumCreateNewTextureResource::FCesiumCreateNewTextureResource( bool sRGB, bool useMipsIfAvailable, uint32 extData) - : FCesiumTextureResourceBase( + : FCesiumTextureResource( textureGroup, width, height, @@ -306,11 +667,20 @@ FCesiumCreateNewTextureResource::FCesiumCreateNewTextureResource( addressY, sRGB, useMipsIfAvailable, - extData), - _image(std::move(image)) {} + extData, + true), + _mipPositions(std::move(image.mipPositions)), + _pixelData(std::move(image.pixelData)) {} FTextureRHIRef FCesiumCreateNewTextureResource::InitializeTextureRHI() { - FRHIResourceCreateInfo createInfo{TEXT("CesiumTextureUtility")}; + // Use the asset ID as the name of the texture so it will be visible in the + // Render Resource Viewer. + FString debugName = TEXT("CesiumTextureUtility"); + // if (!this->_image.getUniqueAssetId().empty()) { + // debugName = UTF8_TO_TCHAR(this->_image.getUniqueAssetId().c_str()); + // } + + FRHIResourceCreateInfo createInfo{*debugName}; createInfo.BulkData = nullptr; createInfo.ExtData = _platformExtData; @@ -333,7 +703,7 @@ FTextureRHIRef FCesiumCreateNewTextureResource::InitializeTextureRHI() { } uint32 mipCount = - FMath::Max(1, static_cast(this->_image.mipPositions.size())); + FMath::Max(1, static_cast(this->_mipPositions.size())); // Create a new RHI texture, initially empty. @@ -357,17 +727,25 @@ FTextureRHIRef FCesiumCreateNewTextureResource::InitializeTextureRHI() { uint32 DestPitch; void* pDestination = RHILockTexture2D(rhiTexture, i, RLM_WriteOnly, DestPitch, false); - CopyMip(pDestination, DestPitch, _format, this->_image, i); + CopyMip( + pDestination, + DestPitch, + this->_format, + this->_width, + this->_height, + this->_pixelData, + this->_mipPositions, + i); RHIUnlockTexture2D(rhiTexture, i, false); } // Clear the now-unnecessary copy of the pixel data. Calling clear() isn't // good enough because it won't actually release the memory. std::vector pixelData; - this->_image.pixelData.swap(pixelData); + this->_pixelData.swap(pixelData); - std::vector mipPositions; - this->_image.mipPositions.swap(mipPositions); + std::vector mipPositions; + this->_mipPositions.swap(mipPositions); return rhiTexture; } diff --git a/Source/CesiumRuntime/Private/CesiumTextureResource.h b/Source/CesiumRuntime/Private/CesiumTextureResource.h index 1ee0e5889..4e7906c18 100644 --- a/Source/CesiumRuntime/Private/CesiumTextureResource.h +++ b/Source/CesiumRuntime/Private/CesiumTextureResource.h @@ -5,16 +5,82 @@ #include "CesiumCommon.h" #include "Engine/Texture.h" #include "TextureResource.h" -#include +#include +#include + +class FCesiumTextureResource; + +struct FCesiumTextureResourceDeleter { + void operator()(FCesiumTextureResource* p); +}; + +using FCesiumTextureResourceUniquePtr = + TUniquePtr; /** * The base class for Cesium texture resources, making Cesium's texture data * available to Unreal's RHI. The actual creation of the RHI texture is deferred * to a pure virtual method, `InitializeTextureRHI`. */ -class FCesiumTextureResourceBase : public FTextureResource { +class FCesiumTextureResource : public FTextureResource { public: - FCesiumTextureResourceBase( + /** + * Create a new FCesiumTextureResource from an `ImageAsset` and the given + * sampling parameters. This method is intended to be called from a worker + * thread, not from the game or render thread. + * + * @param imageCesium The image data from which to create the texture + * resource. After this method returns, the `pixelData` will be empty, and + * `sizeBytes` will be set to its previous size. + * @param textureGroup The texture group in which to create this texture. + * @param overridePixelFormat Overrides the pixel format. If std::nullopt, the + * format is inferred from the `ImageAsset`. + * @param filter The texture filtering to use when sampling this texture. + * @param addressX The X texture addressing mode to use when sampling this + * texture. + * @param addressY The Y texture addressing mode to use when sampling this + * texture. + * @param sRGB True if the image data stored in this texture should be treated + * as sRGB. + * @param needsMipMaps True if this texture requires mipmaps. They will be + * generated if they don't already exist. + * @return The created texture resource, or nullptr if a texture could not be + * created. + */ + static FCesiumTextureResourceUniquePtr CreateNew( + CesiumGltf::ImageAsset& imageCesium, + TextureGroup textureGroup, + const std::optional& overridePixelFormat, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool needsMipMaps); + + /** + * Create a new FCesiumTextureResource wrapping an existing one and providing + * new sampling parameters. This method is intended to be called from a worker + * thread, not from the game or render thread. + */ + static FCesiumTextureResourceUniquePtr CreateWrapped( + const TSharedPtr& pExistingResource, + TextureGroup textureGroup, + TextureFilter filter, + TextureAddress addressX, + TextureAddress addressY, + bool sRGB, + bool useMipMapsIfAvailable); + + /** + * Destroys an FCesiumTextureResource. Unreal TextureResources must be + * destroyed on the render thread, so it is important not to call `delete` + * directly. + * + * \param p + */ + static void Destroy(FCesiumTextureResource* p); + + FCesiumTextureResource( TextureGroup textureGroup, uint32 width, uint32 height, @@ -24,7 +90,8 @@ class FCesiumTextureResourceBase : public FTextureResource { TextureAddress addressY, bool sRGB, bool useMipsIfAvailable, - uint32 extData); + uint32 extData, + bool isPrimary); uint32 GetSizeX() const override { return this->_width; } uint32 GetSizeY() const override { return this->_height; } @@ -54,77 +121,5 @@ class FCesiumTextureResourceBase : public FTextureResource { uint32 _platformExtData; FName _lodGroupStatName; uint64 _textureSize; -}; - -/** - * A Cesium texture resource that uses an already-created `FRHITexture`. This is - * used when `GRHISupportsAsyncTextureCreation` is true and so we were already - * able to create the FRHITexture in a worker thread. It is also used when a - * single glTF `Image` is referenced by multiple glTF `Texture` instances. We - * only need one `FRHITexture` is this case, but we need multiple - * `FTextureResource` instances to support the different sampler settings that - * are likely used in the different textures. - */ -class FCesiumUseExistingTextureResource : public FCesiumTextureResourceBase { -public: - FCesiumUseExistingTextureResource( - FTextureRHIRef existingTexture, - TextureGroup textureGroup, - uint32 width, - uint32 height, - EPixelFormat format, - TextureFilter filter, - TextureAddress addressX, - TextureAddress addressY, - bool sRGB, - bool useMipsIfAvailable, - uint32 extData); - - FCesiumUseExistingTextureResource( - FTextureResource* pExistingTexture, - TextureGroup textureGroup, - uint32 width, - uint32 height, - EPixelFormat format, - TextureFilter filter, - TextureAddress addressX, - TextureAddress addressY, - bool sRGB, - bool useMipsIfAvailable, - uint32 extData); - -protected: - virtual FTextureRHIRef InitializeTextureRHI() override; - -private: - FTextureResource* _pExistingTexture; -}; - -/** - * A Cesium texture resource that creates an `FRHITexture` from a glTF - * `ImageCesium` when `InitRHI` is called from the render thread. When - * `GRHISupportsAsyncTextureCreation` is false (everywhere but Direct3D), we can - * only create a `FRHITexture` on the render thread, so this is the code that - * does it. - */ -class FCesiumCreateNewTextureResource : public FCesiumTextureResourceBase { -public: - FCesiumCreateNewTextureResource( - CesiumGltf::ImageCesium&& image, - TextureGroup textureGroup, - uint32 width, - uint32 height, - EPixelFormat format, - TextureFilter filter, - TextureAddress addressX, - TextureAddress addressY, - bool sRGB, - bool useMipsIfAvailable, - uint32 extData); - -protected: - virtual FTextureRHIRef InitializeTextureRHI() override; - -private: - CesiumGltf::ImageCesium _image; + bool _isPrimary; }; diff --git a/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp b/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp index 5bb64b8c9..4522422c1 100644 --- a/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp +++ b/Source/CesiumRuntime/Private/CesiumTextureUtility.cpp @@ -10,6 +10,7 @@ #include "CesiumTextureResource.h" #include "Containers/ResourceArray.h" #include "DynamicRHI.h" +#include "ExtensionImageAssetUnreal.h" #include "GenericPlatform/GenericPlatformProcess.h" #include "PixelFormat.h" #include "RHICommandList.h" @@ -22,141 +23,20 @@ #include "UObject/Package.h" #include #include -#include +#include #include #include #include -using namespace CesiumGltf; - namespace { -FTexture2DRHIRef createAsyncTextureAndWait( - uint32 SizeX, - uint32 SizeY, - uint8 Format, - uint32 NumMips, - ETextureCreateFlags Flags, - void** InitialMipData, - uint32 NumInitialMips) { -#if ENGINE_VERSION_5_4_OR_HIGHER - FGraphEventRef CompletionEvent; - - FTexture2DRHIRef result = RHIAsyncCreateTexture2D( - SizeX, - SizeY, - Format, - NumMips, - Flags, - ERHIAccess::Unknown, - InitialMipData, - NumInitialMips, - TEXT("CesiumTexture"), - CompletionEvent); - - if (CompletionEvent) { - CompletionEvent->Wait(); - } - - return result; -#elif ENGINE_VERSION_5_3_OR_HIGHER - FGraphEventRef CompletionEvent; - - FTexture2DRHIRef result = RHIAsyncCreateTexture2D( - SizeX, - SizeY, - Format, - NumMips, - Flags, - InitialMipData, - NumInitialMips, - CompletionEvent); - - if (CompletionEvent) { - CompletionEvent->Wait(); - } - - return result; -#else - return RHIAsyncCreateTexture2D( - SizeX, - SizeY, - Format, - NumMips, - Flags, - InitialMipData, - NumInitialMips); -#endif -} - -/** - * @brief Create an RHI texture on this thread. This requires - * GRHISupportsAsyncTextureCreation to be true. - * - * @param image The CPU image to create on the GPU. - * @param format The pixel format of the image. - * @param Whether to use a sRGB color-space. - * @return The RHI texture reference. - */ -FTexture2DRHIRef CreateRHITexture2D_Async( - const CesiumGltf::ImageCesium& image, - EPixelFormat format, - bool sRGB) { - check(GRHISupportsAsyncTextureCreation); - - ETextureCreateFlags textureFlags = TexCreate_ShaderResource; - - // Just like in FCesiumCreateNewTextureResource, we're assuming here that we - // can create an FRHITexture as sRGB, and later create another - // UTexture2D / FTextureResource pointing to the same FRHITexture that is not - // sRGB (or vice-versa), and that Unreal will effectively ignore the flag on - // FRHITexture. - if (sRGB) { - textureFlags |= TexCreate_SRGB; - } - - if (!image.mipPositions.empty()) { - // Here 16 is a generously large (but arbitrary) hard limit for number of - // mips. - uint32 mipCount = static_cast(image.mipPositions.size()); - if (mipCount > 16) { - mipCount = 16; - } - - void* mipsData[16]; - for (size_t i = 0; i < mipCount; ++i) { - const CesiumGltf::ImageCesiumMipPosition& mipPos = image.mipPositions[i]; - mipsData[i] = (void*)(&image.pixelData[mipPos.byteOffset]); - } - - return createAsyncTextureAndWait( - static_cast(image.width), - static_cast(image.height), - format, - mipCount, - textureFlags, - mipsData, - mipCount); - } else { - void* pTextureData = (void*)(image.pixelData.data()); - return createAsyncTextureAndWait( - static_cast(image.width), - static_cast(image.height), - format, - 1, - textureFlags, - &pTextureData, - 1); - } -} - struct ExtensionUnrealTexture { static inline constexpr const char* TypeName = "ExtensionUnrealTexture"; static inline constexpr const char* ExtensionName = "PRIVATE_unreal_texture"; CesiumUtility::IntrusivePointer< CesiumTextureUtility::ReferenceCountedUnrealTexture> - pTexture; + pTexture = nullptr; }; } // namespace @@ -203,49 +83,24 @@ void ReferenceCountedUnrealTexture::setUnrealTexture( this->_pUnrealTexture = p; } -const TUniquePtr& +const FCesiumTextureResourceUniquePtr& ReferenceCountedUnrealTexture::getTextureResource() const { return this->_pTextureResource; } -TUniquePtr& +FCesiumTextureResourceUniquePtr& ReferenceCountedUnrealTexture::getTextureResource() { return this->_pTextureResource; } void ReferenceCountedUnrealTexture::setTextureResource( - TUniquePtr&& p) { + FCesiumTextureResourceUniquePtr&& p) { this->_pTextureResource = std::move(p); } -TUniquePtr loadTextureFromModelAnyThreadPart( - CesiumGltf::Model& model, - CesiumGltf::Texture& texture, - bool sRGB, - std::vector& textureResources) { - check(textureResources.size() == model.images.size()); - - int64_t textureIndex = - model.textures.empty() ? -1 : &texture - &model.textures[0]; - if (textureIndex < 0 || size_t(textureIndex) >= model.textures.size()) { - textureIndex = -1; - } - - ExtensionUnrealTexture& extension = - texture.addExtension(); - - if (extension.pTexture && (extension.pTexture->getUnrealTexture() || - extension.pTexture->getTextureResource())) { - // There's an existing Unreal texture for this glTF texture. This will - // happen if this texture is used by multiple primitives on the same model. - // It will also be the case when this model was upsampled from a parent - // tile. - TUniquePtr pResult = MakeUnique(); - pResult->pTexture = extension.pTexture; - pResult->textureIndex = textureIndex; - return pResult; - } - +std::optional getSourceIndexFromModelAndTexture( + const CesiumGltf::Model& model, + const CesiumGltf::Texture& texture) { const CesiumGltf::ExtensionKhrTextureBasisu* pKtxExtension = texture.getExtension(); const CesiumGltf::ExtensionTextureWebp* pWebpExtension = @@ -262,9 +117,9 @@ TUniquePtr loadTextureFromModelAnyThreadPart( "KTX texture source index must be non-negative and less than %d, but is %d"), model.images.size(), pKtxExtension->source); - return nullptr; + return std::nullopt; } - source = pKtxExtension->source; + return std::optional(pKtxExtension->source); } else if (pWebpExtension) { if (pWebpExtension->source < 0 || pWebpExtension->source >= model.images.size()) { @@ -275,9 +130,9 @@ TUniquePtr loadTextureFromModelAnyThreadPart( "WebP texture source index must be non-negative and less than %d, but is %d"), model.images.size(), pWebpExtension->source); - return nullptr; + return std::nullopt; } - source = pWebpExtension->source; + return std::optional(pWebpExtension->source); } else { if (texture.source < 0 || texture.source >= model.images.size()) { UE_LOG( @@ -287,56 +142,58 @@ TUniquePtr loadTextureFromModelAnyThreadPart( "Texture source index must be non-negative and less than %d, but is %d"), model.images.size(), texture.source); - return nullptr; + return std::nullopt; } - source = texture.source; + return std::optional(texture.source); } +} - CesiumGltf::Image& image = model.images[source]; - const CesiumGltf::ImageCesium& imageCesium = image.cesium; - const CesiumGltf::Sampler& sampler = - model.getSafe(model.samplers, texture.sampler); - - FCesiumTextureResourceBase* pExistingImageResource = nullptr; +TUniquePtr loadTextureFromModelAnyThreadPart( + CesiumGltf::Model& model, + CesiumGltf::Texture& texture, + bool sRGB) { + int64_t textureIndex = + model.textures.empty() ? -1 : &texture - &model.textures[0]; + if (textureIndex < 0 || size_t(textureIndex) >= model.textures.size()) { + textureIndex = -1; + } - if (image.cesium.pixelData.empty() && source >= 0 && - source < textureResources.size()) { - // An RHI texture has already been created for this image; reuse it. - pExistingImageResource = textureResources[source]; + ExtensionUnrealTexture& extension = + texture.addExtension(); + if (extension.pTexture && (extension.pTexture->getUnrealTexture() || + extension.pTexture->getTextureResource())) { + // There's an existing Unreal texture for this glTF texture. This will + // happen if this texture is used by multiple primitives on the same + // model. It will also be the case when this model was upsampled from a + // parent tile. + TUniquePtr pResult = MakeUnique(); + pResult->pTexture = extension.pTexture; + pResult->textureIndex = textureIndex; + return pResult; } - TUniquePtr pResult = - loadTextureFromImageAndSamplerAnyThreadPart( - image, - sampler, - sRGB, - pExistingImageResource); - if (pResult) { - extension.pTexture = pResult->pTexture; + std::optional optionalSourceIndex = + getSourceIndexFromModelAndTexture(model, texture); + if (!optionalSourceIndex.has_value()) { + return nullptr; + }; - // Note the index of this texture within the glTF. - pResult->textureIndex = textureIndex; + CesiumGltf::Image& image = model.images[*optionalSourceIndex]; + const CesiumGltf::Sampler& sampler = + model.getSafe(model.samplers, texture.sampler); - if (source >= 0 && source < textureResources.size()) { - // Make the RHI resource known so it can be used by other textures that - // reference this same image. - textureResources[source] = pResult->pTexture->getTextureResource().Get(); - } - } - return pResult; -} + TUniquePtr result = + loadTextureFromImageAndSamplerAnyThreadPart(*image.pAsset, sampler, sRGB); -TUniquePtr loadTextureFromImageAndSamplerAnyThreadPart( - CesiumGltf::Image& image, - const CesiumGltf::Sampler& sampler, - bool sRGB, - FCesiumTextureResourceBase* pExistingImageResource) { - TextureAddress addressX = convertGltfWrapSToUnreal(sampler.wrapS); - TextureAddress addressY = convertGltfWrapTToUnreal(sampler.wrapT); + if (result) { + extension.pTexture = result->pTexture; + result->textureIndex = textureIndex; + } - TextureFilter filter = TextureFilter::TF_Default; - bool useMipMapsIfAvailable = false; + return result; +} +TextureFilter getTextureFilterFromSampler(const CesiumGltf::Sampler& sampler) { // Unreal Engine's available filtering modes are only nearest, bilinear, // trilinear, and "default". Default means "use the texture group settings", // and the texture group settings are defined in a config file and can @@ -352,54 +209,54 @@ TUniquePtr loadTextureFromImageAndSamplerAnyThreadPart( if (sampler.magFilter && !sampler.minFilter) { // Only a magnification filter is specified, so use it. - filter = - sampler.magFilter.value() == CesiumGltf::Sampler::MagFilter::NEAREST - ? TextureFilter::TF_Nearest - : TextureFilter::TF_Default; + return sampler.magFilter.value() == CesiumGltf::Sampler::MagFilter::NEAREST + ? TextureFilter::TF_Nearest + : TextureFilter::TF_Default; } else if (sampler.minFilter) { // Use specified minFilter. switch (sampler.minFilter.value()) { case CesiumGltf::Sampler::MinFilter::NEAREST: case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_NEAREST: - filter = TextureFilter::TF_Nearest; - break; + return TextureFilter::TF_Nearest; case CesiumGltf::Sampler::MinFilter::LINEAR: case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_NEAREST: - filter = TextureFilter::TF_Bilinear; - break; + return TextureFilter::TF_Bilinear; default: - filter = TextureFilter::TF_Default; - break; + return TextureFilter::TF_Default; } } else { // No filtering specified at all, let the texture group decide. - filter = TextureFilter::TF_Default; + return TextureFilter::TF_Default; } +} +bool getUseMipmapsIfAvailableFromSampler(const CesiumGltf::Sampler& sampler) { switch (sampler.minFilter.value_or( CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR)) { case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR: case CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_NEAREST: case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_LINEAR: case CesiumGltf::Sampler::MinFilter::NEAREST_MIPMAP_NEAREST: - useMipMapsIfAvailable = true; - break; + return true; default: // LINEAR and NEAREST - useMipMapsIfAvailable = false; - break; + return false; } +} +TUniquePtr loadTextureFromImageAndSamplerAnyThreadPart( + CesiumGltf::ImageAsset& image, + const CesiumGltf::Sampler& sampler, + bool sRGB) { return loadTextureAnyThreadPart( - image.cesium, - addressX, - addressY, - filter, - useMipMapsIfAvailable, + image, + convertGltfWrapSToUnreal(sampler.wrapS), + convertGltfWrapTToUnreal(sampler.wrapT), + getTextureFilterFromSampler(sampler), + getUseMipmapsIfAvailableFromSampler(sampler), // TODO: allow texture group to be configured on Cesium3DTileset. TEXTUREGROUP_World, sRGB, - std::nullopt, - pExistingImageResource); + std::nullopt); } static UTexture2D* CreateTexture2D(LoadedTextureResult* pHalfLoadedTexture) { @@ -432,72 +289,37 @@ static UTexture2D* CreateTexture2D(LoadedTextureResult* pHalfLoadedTexture) { } TUniquePtr loadTextureAnyThreadPart( - CesiumGltf::ImageCesium& imageCesium, + CesiumGltf::ImageAsset& image, TextureAddress addressX, TextureAddress addressY, TextureFilter filter, bool useMipMapsIfAvailable, TextureGroup group, bool sRGB, - std::optional overridePixelFormat, - FCesiumTextureResourceBase* pExistingImageResource) { - EPixelFormat pixelFormat; - if (imageCesium.compressedPixelFormat != GpuCompressedPixelFormat::NONE) { - switch (imageCesium.compressedPixelFormat) { - case GpuCompressedPixelFormat::ETC1_RGB: - pixelFormat = EPixelFormat::PF_ETC1; - break; - case GpuCompressedPixelFormat::ETC2_RGBA: - pixelFormat = EPixelFormat::PF_ETC2_RGBA; - break; - case GpuCompressedPixelFormat::BC1_RGB: - pixelFormat = EPixelFormat::PF_DXT1; - break; - case GpuCompressedPixelFormat::BC3_RGBA: - pixelFormat = EPixelFormat::PF_DXT5; - break; - case GpuCompressedPixelFormat::BC4_R: - pixelFormat = EPixelFormat::PF_BC4; - break; - case GpuCompressedPixelFormat::BC5_RG: - pixelFormat = EPixelFormat::PF_BC5; - break; - case GpuCompressedPixelFormat::BC7_RGBA: - pixelFormat = EPixelFormat::PF_BC7; - break; - case GpuCompressedPixelFormat::ASTC_4x4_RGBA: - pixelFormat = EPixelFormat::PF_ASTC_4x4; - break; - case GpuCompressedPixelFormat::PVRTC2_4_RGBA: - pixelFormat = EPixelFormat::PF_PVRTC2; - break; - case GpuCompressedPixelFormat::ETC2_EAC_R11: - pixelFormat = EPixelFormat::PF_ETC2_R11_EAC; - break; - case GpuCompressedPixelFormat::ETC2_EAC_RG11: - pixelFormat = EPixelFormat::PF_ETC2_RG11_EAC; - break; - default: - // Unsupported compressed texture format. - return nullptr; - }; - } else if (overridePixelFormat) { - pixelFormat = *overridePixelFormat; - } else { - switch (imageCesium.channels) { - case 1: - pixelFormat = PF_R8; - break; - case 2: - pixelFormat = PF_R8G8; - break; - case 3: - case 4: - default: - pixelFormat = PF_R8G8B8A8; - }; + std::optional overridePixelFormat) { + // The FCesiumTextureResource for the ImageAsset should already be created at + // this point, if it can be. + const ExtensionImageAssetUnreal& extension = + ExtensionImageAssetUnreal::getOrCreate( + CesiumAsync::AsyncSystem(nullptr), + image, + sRGB, + useMipMapsIfAvailable, + overridePixelFormat); + check(extension.getFuture().isReady()); + if (extension.getTextureResource() == nullptr) { + return nullptr; } + auto pResource = FCesiumTextureResource::CreateWrapped( + extension.getTextureResource(), + group, + filter, + addressX, + addressY, + sRGB, + useMipMapsIfAvailable); + TUniquePtr pResult = MakeUnique(); pResult->pTexture = new ReferenceCountedUnrealTexture(); @@ -506,78 +328,7 @@ TUniquePtr loadTextureAnyThreadPart( pResult->filter = filter; pResult->group = group; pResult->sRGB = sRGB; - - // Store the current size of the pixel data, because we're about to clear it - // but we still want to have an accurate estimation of the size of the image - // for caching purposes. - imageCesium.sizeBytes = int64_t(imageCesium.pixelData.size()); - - if (pExistingImageResource) { - pResult->pTexture->setTextureResource( - MakeUnique( - pExistingImageResource, - group, - imageCesium.width, - imageCesium.height, - pixelFormat, - filter, - addressX, - addressY, - sRGB, - useMipMapsIfAvailable, - 0)); - } else if ( - GRHISupportsAsyncTextureCreation && !imageCesium.pixelData.empty()) { - // Create RHI texture resource on this worker thread, and then hand it off - // to the renderer thread. - TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::CreateRHITexture2D) - - FTexture2DRHIRef textureReference = - CreateRHITexture2D_Async(imageCesium, pixelFormat, sRGB); - pResult->pTexture->setTextureResource( - MakeUnique( - textureReference, - group, - imageCesium.width, - imageCesium.height, - pixelFormat, - filter, - addressX, - addressY, - sRGB, - useMipMapsIfAvailable, - 0)); - - // Clear the now-unnecessary copy of the pixel data. Calling clear() isn't - // good enough because it won't actually release the memory. - std::vector pixelData; - imageCesium.pixelData.swap(pixelData); - - std::vector mipPositions; - imageCesium.mipPositions.swap(mipPositions); - } else { - // The RHI texture will be created later on the render thread, directly - // from this texture source. We need valid pixelData here, though. - if (imageCesium.pixelData.empty()) { - return nullptr; - } - - pResult->pTexture->setTextureResource( - MakeUnique( - std::move(imageCesium), - group, - imageCesium.width, - imageCesium.height, - pixelFormat, - filter, - addressX, - addressY, - sRGB, - useMipMapsIfAvailable, - 0)); - } - - check(pResult->pTexture->getTextureResource() != nullptr); + pResult->pTexture->setTextureResource(MoveTemp(pResource)); return pResult; } @@ -608,7 +359,7 @@ CesiumUtility::IntrusivePointer loadTextureGameThreadPart(LoadedTextureResult* pHalfLoadedTexture) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::LoadTexture) - TUniquePtr& pTextureResource = + FCesiumTextureResourceUniquePtr& pTextureResource = pHalfLoadedTexture->pTexture->getTextureResource(); if (pTextureResource == nullptr) { // Texture is already loaded (or unloadable). @@ -620,21 +371,21 @@ loadTextureGameThreadPart(LoadedTextureResult* pHalfLoadedTexture) { return nullptr; } - FCesiumTextureResourceBase* pCesiumTextureResource = - pTextureResource.Release(); - if (pCesiumTextureResource) { - pTexture->SetResource(pCesiumTextureResource); + if (pTextureResource) { + // Give the UTexture2D exclusive ownership of this FCesiumTextureResource. + pTexture->SetResource(pTextureResource.Release()); ENQUEUE_RENDER_COMMAND(Cesium_InitResource) - ([pTexture, pCesiumTextureResource](FRHICommandListImmediate& RHICmdList) { - pCesiumTextureResource->SetTextureReference( + ([pTexture, pTextureResource = pTexture->GetResource()]( + FRHICommandListImmediate& RHICmdList) { + pTextureResource->SetTextureReference( pTexture->TextureReference.TextureReferenceRHI); #if ENGINE_VERSION_5_3_OR_HIGHER - pCesiumTextureResource->InitResource( + pTextureResource->InitResource( FRHICommandListImmediate::Get()); // Init Resource now requires a // command list. #else - pCesiumTextureResource->InitResource(); + pTextureResource->InitResource(); #endif }); } @@ -670,4 +421,67 @@ TextureAddress convertGltfWrapTToUnreal(int32_t wrapT) { } } +std::optional getPixelFormatForImageAsset( + const CesiumGltf::ImageAsset& imageCesium, + const std::optional overridePixelFormat) { + if (imageCesium.compressedPixelFormat != + CesiumGltf::GpuCompressedPixelFormat::NONE) { + switch (imageCesium.compressedPixelFormat) { + case CesiumGltf::GpuCompressedPixelFormat::ETC1_RGB: + return EPixelFormat::PF_ETC1; + break; + case CesiumGltf::GpuCompressedPixelFormat::ETC2_RGBA: + return EPixelFormat::PF_ETC2_RGBA; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC1_RGB: + return EPixelFormat::PF_DXT1; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC3_RGBA: + return EPixelFormat::PF_DXT5; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC4_R: + return EPixelFormat::PF_BC4; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC5_RG: + return EPixelFormat::PF_BC5; + break; + case CesiumGltf::GpuCompressedPixelFormat::BC7_RGBA: + return EPixelFormat::PF_BC7; + break; + case CesiumGltf::GpuCompressedPixelFormat::ASTC_4x4_RGBA: + return EPixelFormat::PF_ASTC_4x4; + break; + case CesiumGltf::GpuCompressedPixelFormat::PVRTC2_4_RGBA: + return EPixelFormat::PF_PVRTC2; + break; + case CesiumGltf::GpuCompressedPixelFormat::ETC2_EAC_R11: + return EPixelFormat::PF_ETC2_R11_EAC; + break; + case CesiumGltf::GpuCompressedPixelFormat::ETC2_EAC_RG11: + return EPixelFormat::PF_ETC2_RG11_EAC; + break; + default: + // Unsupported compressed texture format. + return std::nullopt; + }; + } else if (overridePixelFormat) { + return *overridePixelFormat; + } else { + switch (imageCesium.channels) { + case 1: + return PF_R8; + break; + case 2: + return PF_R8G8; + break; + case 3: + case 4: + default: + return PF_R8G8B8A8; + }; + } + + return std::nullopt; +} + } // namespace CesiumTextureUtility diff --git a/Source/CesiumRuntime/Private/CesiumTextureUtility.h b/Source/CesiumRuntime/Private/CesiumTextureUtility.h index 2592dabc3..a6989684b 100644 --- a/Source/CesiumRuntime/Private/CesiumTextureUtility.h +++ b/Source/CesiumRuntime/Private/CesiumTextureUtility.h @@ -2,7 +2,9 @@ #pragma once +#include "CesiumAsync/SharedAssetDepot.h" #include "CesiumGltf/Model.h" +#include "CesiumGltf/Texture.h" #include "CesiumMetadataValueType.h" #include "CesiumTextureResource.h" #include "Engine/Texture.h" @@ -15,7 +17,7 @@ #include namespace CesiumGltf { -struct ImageCesium; +struct ImageAsset; struct Texture; } // namespace CesiumGltf @@ -46,13 +48,13 @@ struct ReferenceCountedUnrealTexture void setUnrealTexture(const TObjectPtr& p); // The renderer / RHI FTextureResource holding the pixel data. - const TUniquePtr& getTextureResource() const; - TUniquePtr& getTextureResource(); - void setTextureResource(TUniquePtr&& p); + const FCesiumTextureResourceUniquePtr& getTextureResource() const; + FCesiumTextureResourceUniquePtr& getTextureResource(); + void setTextureResource(FCesiumTextureResourceUniquePtr&& p); private: TObjectPtr _pUnrealTexture; - TUniquePtr _pTextureResource; + FCesiumTextureResourceUniquePtr _pTextureResource; }; /** @@ -88,8 +90,6 @@ struct LoadedTextureResult { * associated Unreal texture. * @param sRGB True if the texture should be treated as sRGB; false if it should * be treated as linear. - * @param textureResources Unreal RHI texture resources that have already been - * created for this model. This array must have the same size as `model`'s * {@link CesiumGltf::Model::images}, and all pointers must be initialized to * nullptr before the first call to `loadTextureFromModelAnyThreadPart` during * the glTF load process. @@ -97,8 +97,7 @@ struct LoadedTextureResult { TUniquePtr loadTextureFromModelAnyThreadPart( CesiumGltf::Model& model, CesiumGltf::Texture& texture, - bool sRGB, - std::vector& textureResources); + bool sRGB); /** * Does the asynchronous part of renderer resource preparation for a glTF @@ -111,25 +110,20 @@ TUniquePtr loadTextureFromModelAnyThreadPart( * @param sampler The sampler settings to use with the texture. * @param sRGB True if the texture should be treated as sRGB; false if it should * be treated as linear. - * @param pExistingImageResource An existing RHI texture resource that has been - * created for this image, or nullptr if one hasn't been created yet. When this - * parameter is not nullptr, the provided image's `pixelData` is not required - * and can be empty. */ TUniquePtr loadTextureFromImageAndSamplerAnyThreadPart( - CesiumGltf::Image& image, + CesiumGltf::ImageAsset& image, const CesiumGltf::Sampler& sampler, - bool sRGB, - FCesiumTextureResourceBase* pExistingImageResource); + bool sRGB); /** * @brief Does the asynchronous part of renderer resource preparation for - * this image. Should be called in a background thread. - * - * The `pixelData` will be removed from the image so that it can be - * passed to Unreal's renderer thread without copying it. + * a texture.The given image _must_ be prepared before calling this method by + * calling {@link ExtensionImageAssetUnreal::getOrCreate} and then waiting + * for {@link ExtensionImageAssetUnreal::getFuture} to resolve. This method + * should be called in a background thread. * - * @param imageCesium The image. + * @param image The image. * @param addressX The X addressing mode. * @param addressY The Y addressing mode. * @param filter The sampler filtering to use for this texture. @@ -139,22 +133,17 @@ TUniquePtr loadTextureFromImageAndSamplerAnyThreadPart( * @param sRGB Whether this texture uses a sRGB color space. * @param overridePixelFormat The explicit pixel format to use. If std::nullopt, * the pixel format is inferred from the image. - * @param pExistingImageResource An existing RHI texture resource that has been - * created for this image, or nullptr if one hasn't been created yet. When this - * parameter is not nullptr, the provided image's `pixelData` is not required - * and can be empty. * @return The loaded texture. */ TUniquePtr loadTextureAnyThreadPart( - CesiumGltf::ImageCesium& imageCesium, + CesiumGltf::ImageAsset& image, TextureAddress addressX, TextureAddress addressY, TextureFilter filter, bool useMipMapsIfAvailable, TextureGroup group, bool sRGB, - std::optional overridePixelFormat, - FCesiumTextureResourceBase* pExistingImageResource); + std::optional overridePixelFormat); /** * @brief Does the main-thread part of render resource preparation for this @@ -203,4 +192,11 @@ TextureAddress convertGltfWrapSToUnreal(int32_t wrapS); */ TextureAddress convertGltfWrapTToUnreal(int32_t wrapT); +std::optional getPixelFormatForImageAsset( + const CesiumGltf::ImageAsset& imageCesium, + const std::optional overridePixelFormat); + +std::optional +getUnrealTextureFromGltfTexture(const CesiumGltf::Texture& texture); + } // namespace CesiumTextureUtility diff --git a/Source/CesiumRuntime/Private/CreateGltfOptions.h b/Source/CesiumRuntime/Private/CreateGltfOptions.h index a09d6914f..c809652e7 100644 --- a/Source/CesiumRuntime/Private/CreateGltfOptions.h +++ b/Source/CesiumRuntime/Private/CreateGltfOptions.h @@ -12,18 +12,39 @@ // TODO: internal documentation namespace CreateGltfOptions { struct CreateModelOptions { - /** - * A pointer to the glTF model. - */ - CesiumGltf::Model* pModel = nullptr; const FCesiumFeaturesMetadataDescription* pFeaturesMetadataDescription = nullptr; + CesiumGltf::Model* pModel = nullptr; + PRAGMA_DISABLE_DEPRECATION_WARNINGS const FMetadataDescription* pEncodedMetadataDescription_DEPRECATED = nullptr; PRAGMA_ENABLE_DEPRECATION_WARNINGS bool alwaysIncludeTangents = false; bool createPhysicsMeshes = true; bool ignoreKhrMaterialsUnlit = false; + + Cesium3DTilesSelection::TileLoadResult tileLoadResult; + +public: + CreateModelOptions(Cesium3DTilesSelection::TileLoadResult&& tileLoadResult_) + : tileLoadResult(std::move(tileLoadResult_)) { + pModel = std::get_if(&this->tileLoadResult.contentKind); + } + + CreateModelOptions(CreateModelOptions&& other) + : pFeaturesMetadataDescription(other.pFeaturesMetadataDescription), + pEncodedMetadataDescription_DEPRECATED( + other.pEncodedMetadataDescription_DEPRECATED), + alwaysIncludeTangents(other.alwaysIncludeTangents), + createPhysicsMeshes(other.createPhysicsMeshes), + ignoreKhrMaterialsUnlit(other.ignoreKhrMaterialsUnlit), + tileLoadResult(std::move(other.tileLoadResult)) { + pModel = std::get_if(&this->tileLoadResult.contentKind); + } + + CreateModelOptions(const CreateModelOptions&) = delete; + CreateModelOptions& operator=(const CreateModelOptions&) = delete; + CreateModelOptions& operator=(CreateModelOptions&&) = delete; }; struct CreateNodeOptions { @@ -35,12 +56,12 @@ struct CreateNodeOptions { struct CreateMeshOptions { const CreateNodeOptions* pNodeOptions = nullptr; const LoadGltfResult::LoadNodeResult* pHalfConstructedNodeResult = nullptr; - CesiumGltf::Mesh* pMesh = nullptr; + int32_t meshIndex = -1; }; struct CreatePrimitiveOptions { const CreateMeshOptions* pMeshOptions = nullptr; const LoadGltfResult::LoadMeshResult* pHalfConstructedMeshResult = nullptr; - CesiumGltf::MeshPrimitive* pPrimitive = nullptr; + int32_t primitiveIndex = -1; }; } // namespace CreateGltfOptions diff --git a/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.cpp b/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.cpp new file mode 100644 index 000000000..c9f75ae97 --- /dev/null +++ b/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.cpp @@ -0,0 +1,118 @@ +#include "ExtensionImageAssetUnreal.h" +#include "CesiumRuntime.h" +#include "CesiumTextureUtility.h" +#include +#include + +using namespace CesiumAsync; +using namespace CesiumGltfReader; + +namespace { + +std::mutex createExtensionMutex; + +std::pair>> +getOrCreateImageFuture( + const AsyncSystem& asyncSystem, + CesiumGltf::ImageAsset& imageCesium); + +} // namespace + +/*static*/ const ExtensionImageAssetUnreal& +ExtensionImageAssetUnreal::getOrCreate( + const CesiumAsync::AsyncSystem& asyncSystem, + CesiumGltf::ImageAsset& imageCesium, + bool sRGB, + bool needsMipMaps, + const std::optional& overridePixelFormat) { + auto [extension, maybePromise] = + getOrCreateImageFuture(asyncSystem, imageCesium); + if (!maybePromise) { + // Another thread is already working on this image. + return extension; + } + + // Proceed to load the image in this thread. + TUniquePtr pResource = + FCesiumTextureResource::CreateNew( + imageCesium, + TextureGroup::TEXTUREGROUP_World, + overridePixelFormat, + TextureFilter::TF_Default, + TextureAddress::TA_Clamp, + TextureAddress::TA_Clamp, + sRGB, + needsMipMaps); + + extension._pTextureResource = + MakeShareable(pResource.Release(), [](FCesiumTextureResource* p) { + FCesiumTextureResource ::Destroy(p); + }); + + // For texture resources created from glTF _textures_, this will happen later + // (after we created the UTexture2D). But this texture resource, created for + // an ImageAsset, will never have a UTexture2D, so we initialize its resources + // here. + ENQUEUE_RENDER_COMMAND(Cesium_InitResource) + ([pResource = extension._pTextureResource]( + FRHICommandListImmediate& RHICmdList) mutable { +#if ENGINE_VERSION_5_3_OR_HIGHER + pResource->InitResource( + FRHICommandListImmediate::Get()); // Init Resource now requires a + // command list. +#else + pResource->InitResource(); +#endif + }); + + maybePromise->resolve(); + + return extension; +} + +ExtensionImageAssetUnreal::ExtensionImageAssetUnreal( + const CesiumAsync::SharedFuture& future) + : _pTextureResource(nullptr), _futureCreateResource(future) {} + +const TSharedPtr& +ExtensionImageAssetUnreal::getTextureResource() const { + return this->_pTextureResource; +} + +CesiumAsync::SharedFuture& ExtensionImageAssetUnreal::getFuture() { + return this->_futureCreateResource; +} + +const CesiumAsync::SharedFuture& +ExtensionImageAssetUnreal::getFuture() const { + return this->_futureCreateResource; +} + +namespace { + +// Returns the ExtensionImageAssetUnreal, which is created if it does not +// already exist. It _may_ also return a Promise, in which case the calling +// thread is responsible for doing the loading and should resolve the Promise +// when it's done. +std::pair>> +getOrCreateImageFuture( + const AsyncSystem& asyncSystem, + CesiumGltf::ImageAsset& imageCesium) { + std::scoped_lock lock(createExtensionMutex); + + ExtensionImageAssetUnreal* pExtension = + imageCesium.getExtension(); + if (!pExtension) { + // This thread will work on this image. + Promise promise = asyncSystem.createPromise(); + ExtensionImageAssetUnreal& extension = + imageCesium.addExtension( + promise.getFuture().share()); + return {extension, std::move(promise)}; + } else { + // Another thread is already working on this image. + return {*pExtension, std::nullopt}; + } +} + +} // namespace diff --git a/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.h b/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.h new file mode 100644 index 000000000..824bc4d27 --- /dev/null +++ b/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.h @@ -0,0 +1,90 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#pragma once + +#include "CesiumTextureResource.h" +#include "PixelFormat.h" +#include "Templates/SharedPointer.h" +#include +#include + +namespace CesiumGltf { +struct ImageAsset; +} + +/** + * @brief An extension attached to an ImageAsset in order to hold + * Unreal-specific information about it. + * + * ImageAsset instances are shared between multiple textures on a single model, + * and even between models in some cases, but we strive to have only one copy of + * the image bytes in GPU memory. + * + * The Unreal / GPU resource is held in `pTextureResource`, which may be either + * a `FCesiumCreateNewTextureResource` or a `FCesiumUseExistingTextureResource` + * depending on how it was created. We'll never actually sample directly from + * this resource, however. Instead, a separate + * `FCesiumUseExistingTextureResource` will be created for each glTF Texture + * that references this image, and it will point to the instance managed by this + * extension. + * + * Because we'll never be sampling from this texture resource, the texture + * filtering and addressing parameters have default values. + */ +struct ExtensionImageAssetUnreal { + static inline constexpr const char* TypeName = "ExtensionImageAssetUnreal"; + static inline constexpr const char* ExtensionName = + "PRIVATE_ImageAsset_Unreal"; + + /** + * @brief Gets an Unreal texture resource from the given `ImageAsset`, + * creating it if necessary. + * + * When this function is called for the first time on a particular + * `ImageAsset`, the asynchronous process to create an Unreal + * `FTextureResource` from it is kicked off. On successive invocations + * (perhaps from other threads), the existing instance is returned. It is safe + * to call this method on the same `ImageAsset` instance from multiple + * threads simultaneously as long as no other thread is modifying the instance + * at the same time. + * + * To determine if the asynchronous `FTextureResource` creation process has + * completed, use {@link getFuture}. + */ + static const ExtensionImageAssetUnreal& getOrCreate( + const CesiumAsync::AsyncSystem& asyncSystem, + CesiumGltf::ImageAsset& imageCesium, + bool sRGB, + bool needsMipMaps, + const std::optional& overridePixelFormat); + + /** + * Constructs a new instance. + * + * @param future The future that will resolve when loading of the + * {@link getTextureResource} is complete. + */ + ExtensionImageAssetUnreal(const CesiumAsync::SharedFuture& future); + + /** + * Gets the created texture resource. This resource should not be accessed or + * used before the future returned by {@link getFuture} resolves. + */ + const TSharedPtr& getTextureResource() const; + + /** + * Gets the future that will resolve when loading of the + * {@link getTextureResource} is complete. This future will not reject. + */ + CesiumAsync::SharedFuture& getFuture(); + + /** + * Gets the future that will resolve when loading of the + * {@link getTextureResource} is complete. This future will not reject. + */ + const CesiumAsync::SharedFuture& getFuture() const; + +private: + TSharedPtr _pTextureResource; + CesiumAsync::SharedFuture _futureCreateResource; +}; diff --git a/Source/CesiumRuntime/Private/LoadGltfResult.h b/Source/CesiumRuntime/Private/LoadGltfResult.h index f9f55843a..72280855c 100644 --- a/Source/CesiumRuntime/Private/LoadGltfResult.h +++ b/Source/CesiumRuntime/Private/LoadGltfResult.h @@ -45,9 +45,11 @@ struct LoadPrimitiveResult { TUniquePtr RenderData = nullptr; /** - * A pointer to the glTF material. + * The index of the material for this primitive within the parent model, or -1 + * if none. */ - const CesiumGltf::Material* pMaterial = nullptr; + int32_t materialIndex = -1; + glm::dmat4x4 transform{1.0}; #if ENGINE_VERSION_5_4_OR_HIGHER Chaos::FTriangleMeshImplicitObjectPtr pCollisionMesh = nullptr; @@ -89,8 +91,8 @@ struct LoadPrimitiveResult { #pragma endregion #pragma region CesiumGltfPrimitiveComponent data - const CesiumGltf::Model* pModel = nullptr; - const CesiumGltf::MeshPrimitive* pMeshPrimitive = nullptr; + int32_t meshIndex = -1; + int32_t primitiveIndex = -1; /** Parses EXT_mesh_features from a mesh primitive.*/ FCesiumPrimitiveFeatures Features{}; diff --git a/Source/CesiumRuntime/Private/Tests/Cesium3DTileset.spec.cpp b/Source/CesiumRuntime/Private/Tests/Cesium3DTileset.spec.cpp new file mode 100644 index 000000000..3b123524c --- /dev/null +++ b/Source/CesiumRuntime/Private/Tests/Cesium3DTileset.spec.cpp @@ -0,0 +1,92 @@ +// Copyright 2020-2024 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "Cesium3DTileset.h" +#include "CesiumGlobeAnchorComponent.h" +#include "CesiumGltfComponent.h" +#include "CesiumLoadTestCore.h" +#include "CesiumSceneGeneration.h" +#include "CesiumSunSky.h" +#include "CesiumTestHelpers.h" +#include "Engine/World.h" +#include "GlobeAwareDefaultPawn.h" +#include "Interfaces/IPluginManager.h" +#include "Misc/AutomationTest.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationTestSettings.h" +#include +#include + +#define TEST_SCREEN_WIDTH 1280 +#define TEST_SCREEN_HEIGHT 720 + +namespace Cesium { + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FCesium3DTilesetSharedImages, + "Cesium.Unit.3DTileset.SharedImages", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter); + +static void setupForSharedImages(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(21.16677692, -67.38013505, -6375355.1944), + FVector(-12, -1300, -5), + FRotator(0, 90, 0), + 60.0f); + + context.georeference->SetOriginEarthCenteredEarthFixed(FVector(0, 0, 0)); + context.pawn->SetActorLocation(FVector(485.0, 2400.0, 520.0)); + context.pawn->SetActorRotation(FQuat::MakeFromEuler(FVector(0, 0, 270))); + + context.sunSky->TimeZone = 9.0f; + context.sunSky->UpdateSun(); + + ACesiumGeoreference* georeference = + context.world->SpawnActor(); + check(georeference != nullptr); + georeference->SetOriginPlacement(EOriginPlacement::TrueOrigin); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + tileset->SetIonAssetID(2757071); + tileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + + tileset->SetActorLabel(TEXT("SharedImages")); + tileset->SetGeoreference(georeference); + tileset->SuspendUpdate = false; + tileset->LogSelectionStats = true; + context.tilesets.push_back(tileset); + + UCesiumGlobeAnchorComponent* GlobeAnchorComponent = + NewObject(tileset, TEXT("GlobeAnchor")); + tileset->AddInstanceComponent(GlobeAnchorComponent); + GlobeAnchorComponent->SetAdjustOrientationForGlobeWhenMoving(false); + GlobeAnchorComponent->SetGeoreference(georeference); + GlobeAnchorComponent->RegisterComponent(); + GlobeAnchorComponent->MoveToEarthCenteredEarthFixedPosition( + FVector(0.0, 0.0, 0.0)); + + ADirectionalLight* Light = context.world->SpawnActor(); + Light->SetActorRotation(FQuat::MakeFromEuler(FVector(0, 0, 270))); +} + +void tilesetPass( + SceneGenerationContext& context, + TestPass::TestingParameter parameter) {} + +bool FCesium3DTilesetSharedImages::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Refresh Pass", tilesetPass, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForSharedImages, + testPasses, + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); +} + +} // namespace Cesium + +#endif diff --git a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp index c2b283985..4cb47a251 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp @@ -5,22 +5,20 @@ #include "CesiumGltfSpecUtility.h" #include "Misc/AutomationTest.h" -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumFeatureIdAttributeSpec, "Cesium.Unit.FeatureIdAttribute", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) -Model model; -MeshPrimitive* pPrimitive; +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; END_DEFINE_SPEC(FCesiumFeatureIdAttributeSpec) void FCesiumFeatureIdAttributeSpec::Define() { Describe("Constructor", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); @@ -76,9 +74,10 @@ void FCesiumFeatureIdAttributeSpec::Define() { It("constructs invalid instance for attribute with invalid accessor", [this]() { - Accessor& accessor = model.accessors.emplace_back(); - accessor.type = AccessorSpec::Type::VEC2; - accessor.componentType = AccessorSpec::ComponentType::FLOAT; + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); + accessor.type = CesiumGltf::AccessorSpec::Type::VEC2; + accessor.componentType = + CesiumGltf::AccessorSpec::ComponentType::FLOAT; const int64 attributeIndex = 0; pPrimitive->attributes.insert({"_FEATURE_ID_0", 0}); @@ -127,8 +126,8 @@ void FCesiumFeatureIdAttributeSpec::Define() { Describe("GetVertexCount", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); @@ -184,8 +183,8 @@ void FCesiumFeatureIdAttributeSpec::Define() { Describe("GetFeatureIDForVertex", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp index e44678a02..881fe1d0c 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp @@ -7,31 +7,29 @@ #include "CesiumGltfSpecUtility.h" #include "Misc/AutomationTest.h" -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumFeatureIdSetSpec, "Cesium.Unit.FeatureIdSet", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) -Model model; -MeshPrimitive* pPrimitive; +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; TObjectPtr pPrimitiveComponent; END_DEFINE_SPEC(FCesiumFeatureIdSetSpec) void FCesiumFeatureIdSetSpec::Define() { Describe("Constructor", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); - pPrimitive->addExtension(); + pPrimitive->addExtension(); }); It("constructs from empty feature ID set", [this]() { // This is technically disallowed by the spec, but just make sure it's // handled reasonably. - FeatureId featureId; + CesiumGltf::FeatureId featureId; FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); TestEqual( @@ -46,7 +44,7 @@ void FCesiumFeatureIdSetSpec::Define() { }); It("constructs implicit feature ID set", [this]() { - FeatureId featureId; + CesiumGltf::FeatureId featureId; featureId.featureCount = 10; FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); @@ -64,7 +62,7 @@ void FCesiumFeatureIdSetSpec::Define() { It("constructs set with feature ID attribute", [this]() { const int64 attributeIndex = 0; const std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureID = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs, @@ -91,7 +89,7 @@ void FCesiumFeatureIdSetSpec::Define() { glm::vec2(0, 0.5), glm::vec2(0.5, 0.5)}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -114,7 +112,7 @@ void FCesiumFeatureIdSetSpec::Define() { }); It("constructs with null feature ID", [this]() { - FeatureId featureId; + CesiumGltf::FeatureId featureId; featureId.featureCount = 10; featureId.nullFeatureId = 0; @@ -135,7 +133,7 @@ void FCesiumFeatureIdSetSpec::Define() { }); It("constructs with property table index", [this]() { - FeatureId featureId; + CesiumGltf::FeatureId featureId; featureId.featureCount = 10; featureId.propertyTable = 1; @@ -159,13 +157,13 @@ void FCesiumFeatureIdSetSpec::Define() { Describe("GetAsFeatureIDAttribute", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); It("returns empty instance for non-attribute feature ID set", [this]() { - FeatureId featureId; + CesiumGltf::FeatureId featureId; featureId.featureCount = 10; FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); @@ -183,7 +181,7 @@ void FCesiumFeatureIdSetSpec::Define() { It("returns valid instance for attribute feature ID set", [this]() { const int64 attributeIndex = 0; const std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureID = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs, @@ -208,13 +206,13 @@ void FCesiumFeatureIdSetSpec::Define() { Describe("GetAsFeatureIDTexture", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); It("returns empty instance for non-texture feature ID set", [this]() { - FeatureId featureId; + CesiumGltf::FeatureId featureId; featureId.featureCount = 10; FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); @@ -231,7 +229,7 @@ void FCesiumFeatureIdSetSpec::Define() { TestEqual( "FeatureIDTextureViewStatus", featureIDTextureView.status(), - FeatureIdTextureViewStatus::ErrorUninitialized); + CesiumGltf::FeatureIdTextureViewStatus::ErrorUninitialized); }); It("returns valid instance for texture feature ID set", [this]() { @@ -242,7 +240,7 @@ void FCesiumFeatureIdSetSpec::Define() { glm::vec2(0, 0.5), glm::vec2(0.5, 0.5)}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -266,14 +264,14 @@ void FCesiumFeatureIdSetSpec::Define() { TestEqual( "FeatureIDTextureViewStatus", featureIDTextureView.status(), - FeatureIdTextureViewStatus::Valid); + CesiumGltf::FeatureIdTextureViewStatus::Valid); }); }); Describe("GetFeatureIDForVertex", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); @@ -288,7 +286,7 @@ void FCesiumFeatureIdSetSpec::Define() { }); It("returns -1 for out of bounds index", [this]() { - FeatureId featureId; + CesiumGltf::FeatureId featureId; featureId.featureCount = 10; FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); @@ -307,7 +305,7 @@ void FCesiumFeatureIdSetSpec::Define() { }); It("returns correct value for implicit set", [this]() { - FeatureId featureId; + CesiumGltf::FeatureId featureId; featureId.featureCount = 10; FCesiumFeatureIdSet featureIDSet(model, *pPrimitive, featureId); @@ -324,7 +322,7 @@ void FCesiumFeatureIdSetSpec::Define() { It("returns correct value for attribute set", [this]() { const int64 attributeIndex = 0; const std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureID = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs, @@ -350,7 +348,7 @@ void FCesiumFeatureIdSetSpec::Define() { glm::vec2(0, 0.5), glm::vec2(0.5, 0.5)}; - FeatureId& featureID = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -374,8 +372,8 @@ void FCesiumFeatureIdSetSpec::Define() { Describe("GetFeatureIDFromHit", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; pPrimitiveComponent = NewObject(); @@ -394,8 +392,8 @@ void FCesiumFeatureIdSetSpec::Define() { model, *pPrimitive, "POSITION", - AccessorSpec::Type::VEC3, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, positions); }); @@ -410,7 +408,7 @@ void FCesiumFeatureIdSetSpec::Define() { }); It("returns -1 for invalid hit component", [this]() { - FeatureId featureId; + CesiumGltf::FeatureId featureId; featureId.featureCount = 6; CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.PositionAccessor = CesiumGltf::AccessorView( @@ -446,7 +444,7 @@ void FCesiumFeatureIdSetSpec::Define() { glm::vec2(0, 1), glm::vec2(1, 0)}; const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureID = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -461,7 +459,7 @@ void FCesiumFeatureIdSetSpec::Define() { CesiumGltf::AccessorView(model, positionAccessorIndex); primData.TexCoordAccessorMap.emplace( 0, - AccessorView>( + CesiumGltf::AccessorView>( model, static_cast(model.accessors.size() - 1))); @@ -489,7 +487,7 @@ void FCesiumFeatureIdSetSpec::Define() { }); It("returns correct value for implicit set", [this]() { - FeatureId featureId; + CesiumGltf::FeatureId featureId; featureId.featureCount = 6; CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); @@ -526,7 +524,7 @@ void FCesiumFeatureIdSetSpec::Define() { static_cast(model.accessors.size() - 1); const int64 attributeIndex = 0; const std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs, @@ -565,8 +563,8 @@ void FCesiumFeatureIdSetSpec::Define() { Describe("Deprecated", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); @@ -574,7 +572,7 @@ void FCesiumFeatureIdSetSpec::Define() { [this]() { const int64 attributeIndex = 0; const std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureID = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs, @@ -584,9 +582,10 @@ void FCesiumFeatureIdSetSpec::Define() { const std::string expectedName = "PropertyTableName"; - ExtensionModelExtStructuralMetadata& metadataExtension = - model.addExtension(); - PropertyTable& propertyTable = + CesiumGltf::ExtensionModelExtStructuralMetadata& metadataExtension = + model.addExtension< + CesiumGltf::ExtensionModelExtStructuralMetadata>(); + CesiumGltf::PropertyTable& propertyTable = metadataExtension.propertyTables.emplace_back(); propertyTable.name = expectedName; @@ -615,7 +614,7 @@ void FCesiumFeatureIdSetSpec::Define() { glm::vec2(0, 0.5), glm::vec2(0.5, 0.5)}; - FeatureId& featureID = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureID = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -628,9 +627,10 @@ void FCesiumFeatureIdSetSpec::Define() { const std::string expectedName = "PropertyTableName"; - ExtensionModelExtStructuralMetadata& metadataExtension = - model.addExtension(); - PropertyTable& propertyTable = + CesiumGltf::ExtensionModelExtStructuralMetadata& metadataExtension = + model.addExtension< + CesiumGltf::ExtensionModelExtStructuralMetadata>(); + CesiumGltf::PropertyTable& propertyTable = metadataExtension.propertyTables.emplace_back(); propertyTable.name = expectedName; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp index ad1f08197..370dd3688 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp @@ -8,15 +8,13 @@ #include #include -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumFeatureIdTextureSpec, "Cesium.Unit.FeatureIdTexture", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) -Model model; -MeshPrimitive* pPrimitive; +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; const std::vector texCoords{ glm::vec2(0, 0), glm::vec2(0.5, 0), @@ -28,8 +26,8 @@ END_DEFINE_SPEC(FCesiumFeatureIdTextureSpec) void FCesiumFeatureIdTextureSpec::Define() { Describe("Constructor", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); @@ -45,11 +43,11 @@ void FCesiumFeatureIdTextureSpec::Define() { TestEqual( "FeatureIDTextureViewStatus", featureIDTextureView.status(), - FeatureIdTextureViewStatus::ErrorUninitialized); + CesiumGltf::FeatureIdTextureViewStatus::ErrorUninitialized); }); It("constructs invalid instance for nonexistent texture", [this]() { - FeatureIdTexture texture; + CesiumGltf::FeatureIdTexture texture; texture.index = -1; texture.texCoord = 0; texture.channels = {0}; @@ -70,14 +68,14 @@ void FCesiumFeatureIdTextureSpec::Define() { TestEqual( "FeatureIDTextureViewStatus", featureIDTextureView.status(), - FeatureIdTextureViewStatus::ErrorInvalidTexture); + CesiumGltf::FeatureIdTextureViewStatus::ErrorInvalidTexture); }); It("constructs invalid instance for texture with invalid image", [this]() { CesiumGltf::Texture& gltfTexture = model.textures.emplace_back(); gltfTexture.source = -1; - FeatureIdTexture texture; + CesiumGltf::FeatureIdTexture texture; texture.index = 0; texture.texCoord = 0; texture.channels = {0}; @@ -98,13 +96,13 @@ void FCesiumFeatureIdTextureSpec::Define() { TestEqual( "FeatureIDTextureViewStatus", featureIDTextureView.status(), - FeatureIdTextureViewStatus::ErrorInvalidImage); + CesiumGltf::FeatureIdTextureViewStatus::ErrorInvalidImage); }); It("constructs valid instance", [this]() { const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -130,25 +128,26 @@ void FCesiumFeatureIdTextureSpec::Define() { TestEqual( "FeatureIDTextureViewStatus", featureIDTextureView.status(), - FeatureIdTextureViewStatus::Valid); + CesiumGltf::FeatureIdTextureViewStatus::Valid); }); It("constructs valid instance for texture with nonexistent texcoord attribute", [this]() { - Image& image = model.images.emplace_back(); - image.cesium.width = image.cesium.height = 1; - image.cesium.channels = 1; - image.cesium.pixelData.push_back(std::byte(42)); + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset.emplace(); + image.pAsset->width = image.pAsset->height = 1; + image.pAsset->channels = 1; + image.pAsset->pixelData.push_back(std::byte(42)); - Sampler& sampler = model.samplers.emplace_back(); - sampler.wrapS = Sampler::WrapS::CLAMP_TO_EDGE; - sampler.wrapT = Sampler::WrapT::CLAMP_TO_EDGE; + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.wrapS = CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE; + sampler.wrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE; CesiumGltf::Texture& gltfTexture = model.textures.emplace_back(); gltfTexture.source = 0; gltfTexture.sampler = 0; - FeatureIdTexture texture; + CesiumGltf::FeatureIdTexture texture; texture.index = 0; texture.texCoord = 0; texture.channels = {0}; @@ -169,25 +168,26 @@ void FCesiumFeatureIdTextureSpec::Define() { TestEqual( "FeatureIDTextureViewStatus", featureIDTextureView.status(), - FeatureIdTextureViewStatus::Valid); + CesiumGltf::FeatureIdTextureViewStatus::Valid); }); It("constructs valid instance for texture with invalid texcoord accessor", [this]() { - Image& image = model.images.emplace_back(); - image.cesium.width = image.cesium.height = 1; - image.cesium.channels = 1; - image.cesium.pixelData.push_back(std::byte(42)); + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset.emplace(); + image.pAsset->width = image.pAsset->height = 1; + image.pAsset->channels = 1; + image.pAsset->pixelData.push_back(std::byte(42)); - Sampler& sampler = model.samplers.emplace_back(); - sampler.wrapS = Sampler::WrapS::CLAMP_TO_EDGE; - sampler.wrapT = Sampler::WrapT::CLAMP_TO_EDGE; + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.wrapS = CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE; + sampler.wrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE; CesiumGltf::Texture& gltfTexture = model.textures.emplace_back(); gltfTexture.source = 0; gltfTexture.sampler = 0; - FeatureIdTexture texture; + CesiumGltf::FeatureIdTexture texture; texture.index = 0; texture.texCoord = 0; texture.channels = {0}; @@ -210,14 +210,14 @@ void FCesiumFeatureIdTextureSpec::Define() { TestEqual( "FeatureIDTextureViewStatus", featureIDTextureView.status(), - FeatureIdTextureViewStatus::Valid); + CesiumGltf::FeatureIdTextureViewStatus::Valid); }); }); Describe("GetFeatureIDForUV", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); @@ -225,7 +225,7 @@ void FCesiumFeatureIdTextureSpec::Define() { CesiumGltf::Texture& gltfTexture = model.textures.emplace_back(); gltfTexture.source = -1; - FeatureIdTexture texture; + CesiumGltf::FeatureIdTexture texture; texture.index = 0; texture.texCoord = 0; texture.channels = {0}; @@ -253,7 +253,7 @@ void FCesiumFeatureIdTextureSpec::Define() { It("returns correct value for valid attribute", [this]() { const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -293,7 +293,7 @@ void FCesiumFeatureIdTextureSpec::Define() { glm::vec2(0, 1), glm::vec2(1, 1)}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -302,12 +302,13 @@ void FCesiumFeatureIdTextureSpec::Define() { 2, rawTexCoords, 0, - Sampler::WrapS::REPEAT, - Sampler::WrapT::REPEAT); + CesiumGltf::Sampler::WrapS::REPEAT, + CesiumGltf::Sampler::WrapT::REPEAT); assert(featureId.texture != std::nullopt); - ExtensionKhrTextureTransform& textureTransform = - featureId.texture->addExtension(); + CesiumGltf::ExtensionKhrTextureTransform& textureTransform = + featureId.texture + ->addExtension(); textureTransform.offset = {0.5, -0.5}; textureTransform.rotation = UE_DOUBLE_HALF_PI; textureTransform.scale = {0.5, 0.5}; @@ -343,13 +344,13 @@ void FCesiumFeatureIdTextureSpec::Define() { Describe("GetFeatureIDForVertex", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); }); It("returns -1 for invalid texture", [this]() { - FeatureIdTexture texture; + CesiumGltf::FeatureIdTexture texture; texture.index = -1; texture.texCoord = 0; texture.channels = {0}; @@ -377,7 +378,7 @@ void FCesiumFeatureIdTextureSpec::Define() { It("returns -1 for out-of-bounds index", [this]() { const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -417,7 +418,7 @@ void FCesiumFeatureIdTextureSpec::Define() { It("returns correct value for valid texture", [this]() { const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -462,8 +463,8 @@ void FCesiumFeatureIdTextureSpec::Define() { model, *pPrimitive, "TEXCOORD_0", - AccessorSpec::Type::VEC2, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC2, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, std::move(values)); const std::vector texCoord1{ @@ -473,7 +474,7 @@ void FCesiumFeatureIdTextureSpec::Define() { glm::vec2(0.0, 0.5)}; const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -508,8 +509,8 @@ void FCesiumFeatureIdTextureSpec::Define() { Describe("GetFeatureIDFromHit", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; pPrimitiveComponent = NewObject(); @@ -528,13 +529,13 @@ void FCesiumFeatureIdTextureSpec::Define() { model, *pPrimitive, "POSITION", - AccessorSpec::Type::VEC3, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, positions); }); It("returns -1 for invalid texture", [this]() { - FeatureIdTexture texture; + CesiumGltf::FeatureIdTexture texture; texture.index = -1; texture.texCoord = 0; texture.channels = {0}; @@ -581,7 +582,7 @@ void FCesiumFeatureIdTextureSpec::Define() { glm::vec2(1, 0)}; const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -595,7 +596,7 @@ void FCesiumFeatureIdTextureSpec::Define() { CesiumGltf::AccessorView(model, positionAccessorIndex); primData.TexCoordAccessorMap.emplace( 0, - AccessorView>( + CesiumGltf::AccessorView>( model, static_cast(model.accessors.size() - 1))); @@ -641,7 +642,7 @@ void FCesiumFeatureIdTextureSpec::Define() { glm::vec2(1, 0)}; const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -656,7 +657,7 @@ void FCesiumFeatureIdTextureSpec::Define() { CesiumGltf::AccessorView(model, positionAccessorIndex); primData.TexCoordAccessorMap.emplace( 1, - AccessorView>( + CesiumGltf::AccessorView>( model, static_cast(model.accessors.size() - 1))); @@ -702,7 +703,7 @@ void FCesiumFeatureIdTextureSpec::Define() { glm::vec2(1, 0)}; const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -717,7 +718,7 @@ void FCesiumFeatureIdTextureSpec::Define() { CesiumGltf::AccessorView(model, positionAccessorIndex); primData.TexCoordAccessorMap.emplace( 0, - AccessorView>( + CesiumGltf::AccessorView>( model, static_cast(model.accessors.size() - 1))); @@ -769,7 +770,7 @@ void FCesiumFeatureIdTextureSpec::Define() { glm::vec2(1, 0)}; const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -784,7 +785,7 @@ void FCesiumFeatureIdTextureSpec::Define() { CesiumGltf::AccessorView(model, positionAccessorIndex); primData.TexCoordAccessorMap.emplace( 0, - AccessorView>( + CesiumGltf::AccessorView>( model, static_cast(model.accessors.size() - 1))); @@ -839,8 +840,8 @@ void FCesiumFeatureIdTextureSpec::Define() { model, *pPrimitive, "TEXCOORD_0", - AccessorSpec::Type::VEC2, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC2, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, GetValuesAsBytes(texCoords0)); int32 texCoord0AccessorIndex = static_cast(model.accessors.size() - 1); @@ -854,7 +855,7 @@ void FCesiumFeatureIdTextureSpec::Define() { glm::vec2(1, 0), }; const std::vector featureIDs{0, 3, 1, 2}; - FeatureId& featureId = AddFeatureIDsAsTextureToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel( model, *pPrimitive, featureIDs, @@ -875,15 +876,17 @@ void FCesiumFeatureIdTextureSpec::Define() { CesiumGltf::AccessorView(model, positionAccessorIndex); primData.TexCoordAccessorMap.emplace( 0, - AccessorView>( + CesiumGltf::AccessorView>( model, texCoord0AccessorIndex)); primData.TexCoordAccessorMap.emplace( 0, - AccessorView>(model, 1)); + CesiumGltf::AccessorView>( + model, + 1)); primData.TexCoordAccessorMap.emplace( 1, - AccessorView>( + CesiumGltf::AccessorView>( model, static_cast(model.accessors.size() - 1))); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.cpp b/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.cpp index 45c4d8149..3af0ffc69 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.cpp @@ -1,7 +1,5 @@ #include "CesiumGltfSpecUtility.h" -using namespace CesiumGltf; - int32_t AddBufferToModel( CesiumGltf::Model& model, const std::string& type, @@ -22,8 +20,8 @@ int32_t AddBufferToModel( accessor.componentType = componentType; const int64_t elementByteSize = - Accessor::computeByteSizeOfComponent(componentType) * - Accessor::computeNumberOfComponents(type); + CesiumGltf::Accessor::computeByteSizeOfComponent(componentType) * + CesiumGltf::Accessor::computeNumberOfComponents(type); accessor.count = buffer.byteLength / elementByteSize; return static_cast(model.accessors.size() - 1); @@ -45,13 +43,14 @@ CesiumGltf::FeatureId& AddFeatureIDsAsAttributeToModel( CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, std::move(values)); - ExtensionExtMeshFeatures* pExtension = - primitive.getExtension(); + CesiumGltf::ExtensionExtMeshFeatures* pExtension = + primitive.getExtension(); if (pExtension == nullptr) { - pExtension = &primitive.addExtension(); + pExtension = + &primitive.addExtension(); } - FeatureId& featureID = pExtension->featureIds.emplace_back(); + CesiumGltf::FeatureId& featureID = pExtension->featureIds.emplace_back(); featureID.featureCount = featureCount; featureID.attribute = setIndex; @@ -70,16 +69,17 @@ CesiumGltf::FeatureId& AddFeatureIDsAsTextureToModel( const int32_t samplerWrapS, const int32_t samplerWrapT) { CesiumGltf::Image& image = model.images.emplace_back(); - image.cesium.bytesPerChannel = 1; - image.cesium.channels = 1; - image.cesium.width = imageWidth; - image.cesium.height = imageHeight; + image.pAsset.emplace(); + image.pAsset->bytesPerChannel = 1; + image.pAsset->channels = 1; + image.pAsset->width = imageWidth; + image.pAsset->height = imageHeight; - std::vector& data = image.cesium.pixelData; + std::vector& data = image.pAsset->pixelData; data.resize(imageWidth * imageHeight); std::memcpy(data.data(), featureIDs.data(), data.size()); - Sampler& sampler = model.samplers.emplace_back(); + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); sampler.wrapS = samplerWrapS; sampler.wrapT = samplerWrapT; @@ -96,16 +96,17 @@ CesiumGltf::FeatureId& AddFeatureIDsAsTextureToModel( CesiumGltf::AccessorSpec::ComponentType::FLOAT, std::move(values)); - ExtensionExtMeshFeatures* pExtension = - primitive.getExtension(); + CesiumGltf::ExtensionExtMeshFeatures* pExtension = + primitive.getExtension(); if (pExtension == nullptr) { - pExtension = &primitive.addExtension(); + pExtension = + &primitive.addExtension(); } - FeatureId& featureID = pExtension->featureIds.emplace_back(); + CesiumGltf::FeatureId& featureID = pExtension->featureIds.emplace_back(); featureID.featureCount = featureCount; - FeatureIdTexture featureIDTexture; + CesiumGltf::FeatureIdTexture featureIDTexture; featureIDTexture.channels = {0}; featureIDTexture.index = 0; featureIDTexture.texCoord = texcoordSetIndex; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h b/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h index b5dd72df8..a166f8d8c 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h @@ -200,15 +200,16 @@ CesiumGltf::PropertyTextureProperty& AddPropertyTexturePropertyToModel( classProperty.componentType = componentType; CesiumGltf::Image& image = model.images.emplace_back(); - image.cesium.width = 2; - image.cesium.height = 2; - image.cesium.channels = sizeof(T); - image.cesium.bytesPerChannel = 1; - image.cesium.pixelData.resize(values.size() * sizeof(T)); + image.pAsset.emplace(); + image.pAsset->width = 2; + image.pAsset->height = 2; + image.pAsset->channels = sizeof(T); + image.pAsset->bytesPerChannel = 1; + image.pAsset->pixelData.resize(values.size() * sizeof(T)); std::memcpy( - image.cesium.pixelData.data(), + image.pAsset->pixelData.data(), values.data(), - image.cesium.pixelData.size()); + image.pAsset->pixelData.size()); CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); sampler.wrapS = CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp index 2ce9db0ff..ff8c52312 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp @@ -1,5 +1,6 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "CesiumMetadataPickingBlueprintLibrary.h" #include "CesiumGltf/ExtensionExtMeshFeatures.h" #include "CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h" #include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" @@ -7,23 +8,20 @@ #include "CesiumGltfComponent.h" #include "CesiumGltfPrimitiveComponent.h" #include "CesiumGltfSpecUtility.h" -#include "CesiumMetadataPickingBlueprintLibrary.h" #include "Misc/AutomationTest.h" -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumMetadataPickingSpec, "Cesium.Unit.MetadataPicking", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) -Model model; -MeshPrimitive* pPrimitive; -ExtensionExtMeshFeatures* pMeshFeatures; -ExtensionModelExtStructuralMetadata* pModelMetadata; -ExtensionMeshPrimitiveExtStructuralMetadata* pPrimitiveMetadata; -PropertyTable* pPropertyTable; -PropertyTexture* pPropertyTexture; +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; +CesiumGltf::ExtensionExtMeshFeatures* pMeshFeatures; +CesiumGltf::ExtensionModelExtStructuralMetadata* pModelMetadata; +CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata* pPrimitiveMetadata; +CesiumGltf::PropertyTable* pPropertyTable; +CesiumGltf::PropertyTexture* pPropertyTexture; TObjectPtr pModelComponent; TObjectPtr pPrimitiveComponent; END_DEFINE_SPEC(FCesiumMetadataPickingSpec) @@ -31,8 +29,8 @@ END_DEFINE_SPEC(FCesiumMetadataPickingSpec) void FCesiumMetadataPickingSpec::Define() { Describe("FindUVFromHit", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; pPrimitiveComponent = NewObject(); @@ -50,8 +48,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPrimitive, "POSITION", - AccessorSpec::Type::VEC3, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, positions); int32_t positionAccessorIndex = static_cast(model.accessors.size() - 1); @@ -70,16 +68,16 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPrimitive, "TEXCOORD_0", - AccessorSpec::Type::VEC2, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC2, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, texCoords); CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.PositionAccessor = - AccessorView(model, positionAccessorIndex); + CesiumGltf::AccessorView(model, positionAccessorIndex); primData.TexCoordAccessorMap.emplace( 0, - AccessorView>( + CesiumGltf::AccessorView>( model, static_cast(model.accessors.size() - 1))); }); @@ -152,11 +150,11 @@ void FCesiumMetadataPickingSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); - primData.IndexAccessor = AccessorView( + primData.IndexAccessor = CesiumGltf::AccessorView( model, static_cast(model.accessors.size() - 1)); @@ -199,10 +197,10 @@ void FCesiumMetadataPickingSpec::Define() { Describe("GetPropertyTableValuesFromHit", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); - pPrimitive->mode = MeshPrimitive::Mode::TRIANGLES; + pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; // Two disconnected triangles. std::vector positions{ @@ -219,13 +217,15 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPrimitive, "POSITION", - AccessorSpec::Type::VEC3, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, std::move(positionData)); - pMeshFeatures = &pPrimitive->addExtension(); + pMeshFeatures = + &pPrimitive->addExtension(); pModelMetadata = - &model.addExtension(); + &model + .addExtension(); std::string className = "testClass"; pModelMetadata->schema.emplace(); @@ -248,13 +248,13 @@ void FCesiumMetadataPickingSpec::Define() { static_cast(model.accessors.size() - 1); std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureId = + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel(model, *pPrimitive, featureIDs, 2, 0); featureId.propertyTable = static_cast(pModelMetadata->propertyTables.size() - 1); CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.PositionAccessor = - AccessorView(model, positionAccessorIndex); + CesiumGltf::AccessorView(model, positionAccessorIndex); std::vector scalarValues{1, 2}; pPropertyTable->count = static_cast(scalarValues.size()); @@ -263,8 +263,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); @@ -286,14 +286,14 @@ void FCesiumMetadataPickingSpec::Define() { static_cast(model.accessors.size() - 1); std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureId = + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel(model, *pPrimitive, featureIDs, 2, 0); featureId.propertyTable = static_cast(pModelMetadata->propertyTables.size() - 1); CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.PositionAccessor = - AccessorView(model, positionAccessorIndex); + CesiumGltf::AccessorView(model, positionAccessorIndex); std::vector scalarValues{1, 2}; pPropertyTable->count = static_cast(scalarValues.size()); @@ -302,8 +302,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); @@ -340,7 +340,7 @@ void FCesiumMetadataPickingSpec::Define() { CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.PositionAccessor = - AccessorView(model, positionAccessorIndex); + CesiumGltf::AccessorView(model, positionAccessorIndex); std::vector scalarValues{1, 2}; pPropertyTable->count = static_cast(scalarValues.size()); @@ -349,8 +349,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::vector vec2Values{ @@ -361,8 +361,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); pModelComponent->Metadata = @@ -384,14 +384,14 @@ void FCesiumMetadataPickingSpec::Define() { static_cast(model.accessors.size() - 1); std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureId = + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel(model, *pPrimitive, featureIDs, 2, 0); featureId.propertyTable = static_cast(pModelMetadata->propertyTables.size() - 1); CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.PositionAccessor = - AccessorView(model, positionAccessorIndex); + CesiumGltf::AccessorView(model, positionAccessorIndex); std::vector scalarValues{1, 2}; pPropertyTable->count = static_cast(scalarValues.size()); @@ -400,8 +400,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::vector vec2Values{ @@ -412,8 +412,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); @@ -469,14 +469,14 @@ void FCesiumMetadataPickingSpec::Define() { static_cast(model.accessors.size() - 1); std::vector featureIDs0{1, 1, 1, 0, 0, 0}; - FeatureId& featureId0 = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureId0 = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs0, 2, 0); std::vector featureIDs1{0, 0, 0, 1, 1, 1}; - FeatureId& featureId1 = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureId1 = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs1, @@ -487,7 +487,7 @@ void FCesiumMetadataPickingSpec::Define() { CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.PositionAccessor = - AccessorView(model, positionAccessorIndex); + CesiumGltf::AccessorView(model, positionAccessorIndex); std::vector scalarValues{1, 2}; pPropertyTable->count = static_cast(scalarValues.size()); @@ -496,8 +496,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::vector vec2Values{ @@ -508,8 +508,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); pModelComponent->Metadata = FCesiumModelMetadata(model, *pModelMetadata); @@ -562,10 +562,10 @@ void FCesiumMetadataPickingSpec::Define() { Describe("GetPropertyTextureValuesFromHit", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); - pPrimitive->mode = MeshPrimitive::Mode::TRIANGLES; + pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES; std::vector positions{ glm::vec3(-1, 0, 0), @@ -580,8 +580,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPrimitive, "POSITION", - AccessorSpec::Type::VEC3, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, GetValuesAsBytes(positions)); int32_t positionAccessorIndex = @@ -602,12 +602,13 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPrimitive, "TEXCOORD_0", - AccessorSpec::Type::VEC2, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC2, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, texCoords0); pModelMetadata = - &model.addExtension(); + &model + .addExtension(); std::string className = "testClass"; pModelMetadata->schema.emplace(); @@ -616,9 +617,8 @@ void FCesiumMetadataPickingSpec::Define() { pPropertyTexture = &pModelMetadata->propertyTextures.emplace_back(); pPropertyTexture->classProperty = className; - pPrimitiveMetadata = - &pPrimitive - ->addExtension(); + pPrimitiveMetadata = &pPrimitive->addExtension< + CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata>(); pPrimitiveMetadata->propertyTextures.push_back(0); pModelComponent = NewObject(); @@ -632,10 +632,10 @@ void FCesiumMetadataPickingSpec::Define() { CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData(); primData.pMeshPrimitive = pPrimitive; primData.PositionAccessor = - AccessorView(model, positionAccessorIndex); + CesiumGltf::AccessorView(model, positionAccessorIndex); primData.TexCoordAccessorMap.emplace( 0, - AccessorView>( + CesiumGltf::AccessorView>( model, static_cast(model.accessors.size() - 1))); }); @@ -647,8 +647,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTexture, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT8, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, scalarValues, {0}); @@ -675,8 +675,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTexture, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT8, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, scalarValues, {0}); @@ -710,8 +710,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTexture, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT8, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, scalarValues, {0}); @@ -741,8 +741,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTexture, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT8, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, scalarValues, {0}); @@ -756,8 +756,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTexture, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::UINT8, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::UINT8, vec2Values, {0, 1}); @@ -831,13 +831,13 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTexture, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT8, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, scalarValues, {0}); // Make another property texture - PropertyTexture& propertyTexture = + CesiumGltf::PropertyTexture& propertyTexture = pModelMetadata->propertyTextures.emplace_back(); propertyTexture.classProperty = "testClass"; std::array newScalarValues = {100, -20, 33, -4}; @@ -845,8 +845,8 @@ void FCesiumMetadataPickingSpec::Define() { model, propertyTexture, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT8, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT8, newScalarValues, {0}); @@ -897,8 +897,8 @@ void FCesiumMetadataPickingSpec::Define() { Describe("Deprecated", [this]() { Describe("GetMetadataValuesForFace", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); // Two disconnected triangles. @@ -917,13 +917,14 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPrimitive, "POSITION", - AccessorSpec::Type::VEC3, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, std::move(positionData)); - pMeshFeatures = &pPrimitive->addExtension(); - pModelMetadata = - &model.addExtension(); + pMeshFeatures = + &pPrimitive->addExtension(); + pModelMetadata = &model.addExtension< + CesiumGltf::ExtensionModelExtStructuralMetadata>(); std::string className = "testClass"; pModelMetadata->schema.emplace(); @@ -944,7 +945,7 @@ void FCesiumMetadataPickingSpec::Define() { It("returns empty map for invalid face index", [this]() { std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs, @@ -960,8 +961,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); pModelComponent->Metadata = @@ -987,7 +988,7 @@ void FCesiumMetadataPickingSpec::Define() { It("returns empty map for invalid feature ID set index", [this]() { std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs, @@ -1003,8 +1004,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); pModelComponent->Metadata = @@ -1047,8 +1048,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::vector vec2Values{ @@ -1059,8 +1060,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); pModelComponent->Metadata = @@ -1079,7 +1080,7 @@ void FCesiumMetadataPickingSpec::Define() { It("returns values for first feature ID set by default", [this]() { std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs, @@ -1095,8 +1096,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::vector vec2Values{ @@ -1107,8 +1108,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); pModelComponent->Metadata = @@ -1159,14 +1160,14 @@ void FCesiumMetadataPickingSpec::Define() { It("returns values for specified feature ID set", [this]() { std::vector featureIDs0{1, 1, 1, 0, 0, 0}; - FeatureId& featureId0 = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureId0 = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs0, 2, 0); std::vector featureIDs1{0, 0, 0, 1, 1, 1}; - FeatureId& featureId1 = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureId1 = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs1, @@ -1182,8 +1183,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::vector vec2Values{ @@ -1194,8 +1195,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); pModelComponent->Metadata = @@ -1242,8 +1243,8 @@ void FCesiumMetadataPickingSpec::Define() { Describe("GetMetadataValuesForFaceAsStrings", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); // Two disconnected triangles. @@ -1262,13 +1263,14 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPrimitive, "POSITION", - AccessorSpec::Type::VEC3, - AccessorSpec::ComponentType::FLOAT, + CesiumGltf::AccessorSpec::Type::VEC3, + CesiumGltf::AccessorSpec::ComponentType::FLOAT, std::move(positionData)); - pMeshFeatures = &pPrimitive->addExtension(); - pModelMetadata = - &model.addExtension(); + pMeshFeatures = + &pPrimitive->addExtension(); + pModelMetadata = &model.addExtension< + CesiumGltf::ExtensionModelExtStructuralMetadata>(); std::string className = "testClass"; pModelMetadata->schema.emplace(); @@ -1289,7 +1291,7 @@ void FCesiumMetadataPickingSpec::Define() { It("returns values for first feature ID set by default", [this]() { std::vector featureIDs{0, 0, 0, 1, 1, 1}; - FeatureId& featureId = AddFeatureIDsAsAttributeToModel( + CesiumGltf::FeatureId& featureId = AddFeatureIDsAsAttributeToModel( model, *pPrimitive, featureIDs, @@ -1305,8 +1307,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::vector vec2Values{ @@ -1317,8 +1319,8 @@ void FCesiumMetadataPickingSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); pModelComponent->Metadata = diff --git a/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp index bc3c37589..49858c73e 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp @@ -6,8 +6,6 @@ #include -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumMetadataValueSpec, "Cesium.Unit.MetadataValue", @@ -90,7 +88,7 @@ void FCesiumMetadataValueSpec::Define() { }); It("constructs array value with correct type", [this]() { - PropertyArrayCopy arrayView; + CesiumGltf::PropertyArrayCopy arrayView; FCesiumMetadataValue value(arrayView); FCesiumMetadataValueType valueType = UCesiumMetadataValueBlueprintLibrary::GetValueType(value); @@ -1131,7 +1129,8 @@ void FCesiumMetadataValueSpec::Define() { It("gets array from array value", [this]() { std::vector arrayValues{1, 2}; - PropertyArrayCopy arrayView = std::vector(arrayValues); + CesiumGltf::PropertyArrayCopy arrayView = + std::vector(arrayValues); FCesiumMetadataValue value(arrayView); FCesiumPropertyArray array = @@ -1196,7 +1195,7 @@ void FCesiumMetadataValueSpec::Define() { }); It("returns false for array value", [this]() { - PropertyArrayCopy arrayView; + CesiumGltf::PropertyArrayCopy arrayView; FCesiumMetadataValue value(arrayView); TestFalse( "IsEmpty", @@ -1217,7 +1216,9 @@ void FCesiumMetadataValueSpec::Define() { values.Add({"scalar", FCesiumMetadataValue(-1)}); values.Add({"vec2", FCesiumMetadataValue(glm::u8vec2(2, 3))}); values.Add( - {"array", FCesiumMetadataValue(PropertyArrayCopy({1, 2, 3}))}); + {"array", + FCesiumMetadataValue( + CesiumGltf::PropertyArrayCopy({1, 2, 3}))}); const auto strings = UCesiumMetadataValueBlueprintLibrary::GetValuesAsStrings(values); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp index 5f76fd5ed..e9a2d1efd 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp @@ -2,9 +2,9 @@ #if WITH_EDITOR +#include "CesiumOriginShiftComponent.h" #include "CesiumGeoreference.h" #include "CesiumGlobeAnchorComponent.h" -#include "CesiumOriginShiftComponent.h" #include "CesiumSubLevelComponent.h" #include "CesiumTestHelpers.h" #include "Editor.h" diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp index bdd3741db..63fac56c6 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp @@ -1,29 +1,28 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "CesiumPrimitiveFeatures.h" #include "CesiumGltf/ExtensionExtMeshFeatures.h" #include "CesiumGltfSpecUtility.h" -#include "CesiumPrimitiveFeatures.h" #include "Misc/AutomationTest.h" -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumPrimitiveFeaturesSpec, "Cesium.Unit.PrimitiveFeatures", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) -Model model; -MeshPrimitive* pPrimitive; -ExtensionExtMeshFeatures* pExtension; +CesiumGltf::Model model; +CesiumGltf::MeshPrimitive* pPrimitive; +CesiumGltf::ExtensionExtMeshFeatures* pExtension; END_DEFINE_SPEC(FCesiumPrimitiveFeaturesSpec) void FCesiumPrimitiveFeaturesSpec::Define() { Describe("Constructor", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); - pExtension = &pPrimitive->addExtension(); + pExtension = + &pPrimitive->addExtension(); }); It("constructs with no feature ID sets", [this]() { @@ -39,7 +38,7 @@ void FCesiumPrimitiveFeaturesSpec::Define() { }); It("constructs with single feature ID set", [this]() { - FeatureId& featureID = pExtension->featureIds.emplace_back(); + CesiumGltf::FeatureId& featureID = pExtension->featureIds.emplace_back(); featureID.featureCount = 10; FCesiumPrimitiveFeatures primitiveFeatures = @@ -81,7 +80,8 @@ void FCesiumPrimitiveFeaturesSpec::Define() { texCoords, 0); - FeatureId& implicitIDs = pExtension->featureIds.emplace_back(); + CesiumGltf::FeatureId& implicitIDs = + pExtension->featureIds.emplace_back(); implicitIDs.featureCount = 3; FCesiumPrimitiveFeatures primitiveFeatures = @@ -100,7 +100,7 @@ void FCesiumPrimitiveFeaturesSpec::Define() { for (size_t i = 0; i < featureIDSets.Num(); i++) { const FCesiumFeatureIdSet& featureIDSet = featureIDSets[static_cast(i)]; - const FeatureId& gltfFeatureID = pExtension->featureIds[i]; + const CesiumGltf::FeatureId& gltfFeatureID = pExtension->featureIds[i]; TestEqual( "Feature Count", UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet), @@ -116,10 +116,11 @@ void FCesiumPrimitiveFeaturesSpec::Define() { Describe("GetFeatureIDSetsOfType", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); - pExtension = &pPrimitive->addExtension(); + pExtension = + &pPrimitive->addExtension(); const std::vector attributeIDs{0, 0, 0}; AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 1, 0); @@ -139,7 +140,8 @@ void FCesiumPrimitiveFeaturesSpec::Define() { texCoords, 0); - FeatureId& implicitIDs = pExtension->featureIds.emplace_back(); + CesiumGltf::FeatureId& implicitIDs = + pExtension->featureIds.emplace_back(); implicitIDs.featureCount = 3; }); @@ -218,10 +220,11 @@ void FCesiumPrimitiveFeaturesSpec::Define() { Describe("GetFirstVertexFromFace", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); - pExtension = &pPrimitive->addExtension(); + pExtension = + &pPrimitive->addExtension(); }); It("returns -1 for out-of-bounds face index", [this]() { @@ -229,7 +232,7 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); FCesiumPrimitiveFeatures primitiveFeatures = @@ -249,7 +252,7 @@ void FCesiumPrimitiveFeaturesSpec::Define() { }); It("returns correct value for primitive without indices", [this]() { - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 9; const int64 numFaces = accessor.count / 3; @@ -273,10 +276,10 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 7; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -298,10 +301,11 @@ void FCesiumPrimitiveFeaturesSpec::Define() { Describe("GetFeatureIDFromFace", [this]() { BeforeEach([this]() { - model = Model(); - Mesh& mesh = model.meshes.emplace_back(); + model = CesiumGltf::Model(); + CesiumGltf::Mesh& mesh = model.meshes.emplace_back(); pPrimitive = &mesh.primitives.emplace_back(); - pExtension = &pPrimitive->addExtension(); + pExtension = + &pPrimitive->addExtension(); }); It("returns -1 for primitive with empty feature ID sets", [this]() { @@ -309,10 +313,10 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 6; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -342,10 +346,10 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 7; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -381,10 +385,10 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 3; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -410,7 +414,7 @@ void FCesiumPrimitiveFeaturesSpec::Define() { std::vector attributeIDs{1, 1, 1, 2, 2, 2, 0, 0, 0}; AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 3, 0); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 9; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -437,10 +441,10 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 7; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -481,10 +485,10 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 3; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -525,7 +529,7 @@ void FCesiumPrimitiveFeaturesSpec::Define() { texCoords, 0); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 6; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -568,10 +572,10 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 4; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -596,12 +600,13 @@ void FCesiumPrimitiveFeaturesSpec::Define() { Describe("ImplicitFeatureIDs", [this]() { BeforeEach([this]() { - FeatureId& implicitIDs = pExtension->featureIds.emplace_back(); + CesiumGltf::FeatureId& implicitIDs = + pExtension->featureIds.emplace_back(); implicitIDs.featureCount = 6; }); It("returns -1 for out-of-bounds face index", [this]() { - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 6; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -624,7 +629,7 @@ void FCesiumPrimitiveFeaturesSpec::Define() { }); It("returns correct values for primitive without indices", [this]() { - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 6; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -651,10 +656,10 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 4; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); @@ -692,16 +697,17 @@ void FCesiumPrimitiveFeaturesSpec::Define() { CreateIndicesForPrimitive( model, *pPrimitive, - AccessorSpec::ComponentType::UNSIGNED_BYTE, + CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE, indices); - Accessor& accessor = model.accessors.emplace_back(); + CesiumGltf::Accessor& accessor = model.accessors.emplace_back(); accessor.count = 7; pPrimitive->attributes.insert( {"POSITION", static_cast(model.accessors.size() - 1)}); // Second feature ID set is implicit - FeatureId& implicitIDs = pExtension->featureIds.emplace_back(); + CesiumGltf::FeatureId& implicitIDs = + pExtension->featureIds.emplace_back(); implicitIDs.featureCount = 7; FCesiumPrimitiveFeatures primitiveFeatures = diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp index c631610da..6eae0eb5d 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp @@ -4,8 +4,6 @@ #include "CesiumPropertyArrayBlueprintLibrary.h" #include "Misc/AutomationTest.h" -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumPropertyArraySpec, "Cesium.Unit.PropertyArray", @@ -37,7 +35,7 @@ void FCesiumPropertyArraySpec::Define() { }); It("constructs empty array from empty view", [this]() { - PropertyArrayCopy arrayView; + CesiumGltf::PropertyArrayCopy arrayView; FCesiumPropertyArray array(arrayView); TestEqual( "size", @@ -60,7 +58,7 @@ void FCesiumPropertyArraySpec::Define() { It("constructs non-empty array", [this]() { std::vector values{1, 2, 3, 4}; - PropertyArrayCopy arrayView = std::vector(values); + CesiumGltf::PropertyArrayCopy arrayView = std::vector(values); FCesiumPropertyArray array(arrayView); TestEqual( "size", @@ -85,7 +83,7 @@ void FCesiumPropertyArraySpec::Define() { Describe("GetValue", [this]() { It("gets bogus value for out-of-bounds index", [this]() { std::vector values{1}; - PropertyArrayCopy arrayView = std::vector(values); + CesiumGltf::PropertyArrayCopy arrayView = std::vector(values); FCesiumPropertyArray array(arrayView); TestEqual( "size", @@ -114,7 +112,7 @@ void FCesiumPropertyArraySpec::Define() { It("gets value for valid index", [this]() { std::vector values{1, 2, 3, 4}; - PropertyArrayCopy arrayView = std::vector(values); + CesiumGltf::PropertyArrayCopy arrayView = std::vector(values); FCesiumPropertyArray array(arrayView); TestEqual( "size", diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp index b196ec3ea..6f3a89394 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp @@ -1,29 +1,28 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "CesiumPropertyTable.h" #include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" #include "CesiumGltf/Model.h" #include "CesiumGltfSpecUtility.h" -#include "CesiumPropertyTable.h" #include "Misc/AutomationTest.h" #include -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumPropertyTableSpec, "Cesium.Unit.PropertyTable", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) -Model model; -ExtensionModelExtStructuralMetadata* pExtension; -PropertyTable* pPropertyTable; +CesiumGltf::Model model; +CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension; +CesiumGltf::PropertyTable* pPropertyTable; END_DEFINE_SPEC(FCesiumPropertyTableSpec) void FCesiumPropertyTableSpec::Define() { BeforeEach([this]() { - model = Model(); - pExtension = &model.addExtension(); - pExtension->schema = Schema(); + model = CesiumGltf::Model(); + pExtension = + &model.addExtension(); + pExtension->schema = CesiumGltf::Schema(); pPropertyTable = &pExtension->propertyTables.emplace_back(); }); @@ -83,8 +82,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, propertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -111,8 +110,9 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, propertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, // Incorrect component type + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, // Incorrect + // component type values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -152,8 +152,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::string vec2PropertyName("vec2Property"); @@ -167,8 +167,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -251,8 +251,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, propertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -311,8 +311,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::string vec2PropertyName("vec2Property"); @@ -326,8 +326,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); std::string invalidPropertyName("badProperty"); @@ -336,8 +336,9 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, invalidPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, // Incorrect component type + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, // Incorrect + // component type invalidPropertyValues); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -378,8 +379,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, propertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -418,8 +419,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::string vec2PropertyName("vec2Property"); @@ -433,8 +434,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -513,8 +514,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::string vec2PropertyName("vec2Property"); @@ -528,8 +529,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -568,8 +569,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::string vec2PropertyName("vec2Property"); @@ -583,8 +584,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -642,8 +643,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, propertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, propertyValues); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -696,8 +697,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::string vec2PropertyName("vec2Property"); @@ -711,8 +712,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -747,8 +748,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, scalarPropertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, scalarValues); std::string vec2PropertyName("vec2Property"); @@ -762,8 +763,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, vec2PropertyName, - ClassProperty::Type::VEC2, - ClassProperty::ComponentType::FLOAT32, + CesiumGltf::ClassProperty::Type::VEC2, + CesiumGltf::ClassProperty::ComponentType::FLOAT32, vec2Values); FCesiumPropertyTable propertyTable(model, *pPropertyTable); @@ -817,8 +818,8 @@ void FCesiumPropertyTableSpec::Define() { model, *pPropertyTable, propertyName, - ClassProperty::Type::SCALAR, - ClassProperty::ComponentType::INT32, + CesiumGltf::ClassProperty::Type::SCALAR, + CesiumGltf::ClassProperty::ComponentType::INT32, propertyValues); FCesiumPropertyTable propertyTable(model, *pPropertyTable); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp index cfb476b03..1ed3f52b4 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp @@ -1,8 +1,8 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "CesiumPropertyTableProperty.h" #include "CesiumGltfSpecUtility.h" #include "CesiumPropertyArrayBlueprintLibrary.h" -#include "CesiumPropertyTableProperty.h" #include "Misc/AutomationTest.h" #include @@ -39,8 +39,9 @@ void FCesiumPropertyTablePropertySpec::Define() { It("constructs invalid instance from view with invalid definition", [this]() { - PropertyTablePropertyView propertyView( - PropertyTablePropertyViewStatus::ErrorArrayTypeMismatch); + CesiumGltf::PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyViewStatus:: + ErrorArrayTypeMismatch); FCesiumPropertyTableProperty property(propertyView); TestEqual( "PropertyTablePropertyStatus", @@ -61,8 +62,9 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("constructs invalid instance from view with invalid data", [this]() { - PropertyTablePropertyView propertyView( - PropertyTablePropertyViewStatus::ErrorBufferViewOutOfBounds); + CesiumGltf::PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyViewStatus:: + ErrorBufferViewOutOfBounds); FCesiumPropertyTableProperty property(propertyView); TestEqual( "PropertyTablePropertyStatus", @@ -83,14 +85,14 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("constructs valid instance", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; std::vector values{1, 2, 3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -163,15 +165,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("constructs valid normalized instance", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::UINT8; classProperty.normalized = true; std::vector values{0, 1, 255, 128}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -220,8 +222,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("constructs instance for fixed-length array property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; classProperty.array = true; @@ -232,15 +234,16 @@ void FCesiumPropertyTablePropertySpec::Define() { static_cast(values.size()) / *classProperty.count; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView> propertyView( - propertyTableProperty, - classProperty, - size, - gsl::span(data.data(), data.size()), - gsl::span(), - gsl::span(), - PropertyComponentType::None, - PropertyComponentType::None); + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + gsl::span(data.data(), data.size()), + gsl::span(), + gsl::span(), + PropertyComponentType::None, + PropertyComponentType::None); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -284,8 +287,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("constructs instance for variable-length array property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; classProperty.array = true; @@ -297,15 +300,18 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector offsetsData = GetValuesAsBytes(offsets); int64_t size = static_cast(offsets.size()) - 1; - PropertyTablePropertyView> propertyView( - propertyTableProperty, - classProperty, - size, - gsl::span(data.data(), data.size()), - gsl::span(offsetsData.data(), offsetsData.size()), - gsl::span(), - PropertyComponentType::Uint16, - PropertyComponentType::None); + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + gsl::span(data.data(), data.size()), + gsl::span( + offsetsData.data(), + offsetsData.size()), + gsl::span(), + PropertyComponentType::Uint16, + PropertyComponentType::None); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -350,8 +356,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("constructs valid instance with additional properties", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; classProperty.normalized = true; @@ -372,7 +378,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{1, 2, 3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -462,8 +468,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("constructs valid array instance with additional properties", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; classProperty.normalized = true; @@ -486,11 +492,12 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{1, 2, 3, 4, 5, 6, -1, -1}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView, true> propertyView( - propertyTableProperty, - classProperty, - static_cast(values.size()), - gsl::span(data.data(), data.size())); + CesiumGltf::PropertyTablePropertyView, true> + propertyView( + propertyTableProperty, + classProperty, + static_cast(values.size()), + gsl::span(data.data(), data.size())); FCesiumPropertyTableProperty property(propertyView); TestEqual( @@ -676,13 +683,13 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::BOOLEAN; std::vector data{static_cast(0b10110001)}; - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(8), @@ -712,13 +719,13 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from boolean property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::BOOLEAN; std::vector data{static_cast(0b10110001)}; - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(8), @@ -771,11 +778,11 @@ void FCesiumPropertyTablePropertySpec::Define() { offsets[offsets.size() - 1] = currentOffset; std::vector offsetsData = GetValuesAsBytes(offsets); - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::STRING; - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -825,15 +832,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::UINT8; std::vector values{1, 2, 3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -861,15 +868,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from uint8 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::UINT8; std::vector values{1, 2, 3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -898,15 +905,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; std::vector values{1, 24, 255, 256, -1, 28}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -936,8 +943,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with noData / default value", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::UINT8; @@ -950,7 +957,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{1, 2, 3, 0, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1004,15 +1011,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; std::vector values{-1, 2, -3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1044,15 +1051,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from int32 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; std::vector values{-1, 2, -3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1081,8 +1088,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; @@ -1095,7 +1102,7 @@ void FCesiumPropertyTablePropertySpec::Define() { }; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1125,8 +1132,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with noData / default value", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; @@ -1139,7 +1146,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{-1, 2, -3, 0, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1197,15 +1204,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this, defaultInt64]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT64; std::vector values{-1, 2, -3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1237,15 +1244,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from int64 property", [this, defaultInt64]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT64; std::vector values{-1, 2, -3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1274,8 +1281,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this, defaultInt64]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::UINT64; @@ -1286,7 +1293,7 @@ void FCesiumPropertyTablePropertySpec::Define() { static_cast(std::numeric_limits::max()) + 100}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1316,8 +1323,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with noData / default value", [this, defaultInt64]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT64; @@ -1330,7 +1337,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{-1, 2, 0, -3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1386,15 +1393,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; std::vector values{-1.1f, 2.2f, -3.3f, 4.0f}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1422,15 +1429,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from float property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; std::vector values{-1.1f, 2.2f, -3.3f, 4.0f}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1466,12 +1473,12 @@ void FCesiumPropertyTablePropertySpec::Define() { std::numeric_limits::max()}; std::vector data = GetValuesAsBytes(values); - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1506,8 +1513,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with offset / scale", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; @@ -1520,7 +1527,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{-1.1f, 2.2f, -3.3f, 4.0f}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1566,15 +1573,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; std::vector values{-1.1, 2.2, -3.3, 4.0}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1606,15 +1613,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from double property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; std::vector values{-1.1, 2.2, -3.3, 4.0}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1643,8 +1650,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from normalized uint8 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::UINT8; classProperty.normalized = true; @@ -1652,7 +1659,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{0, 128, 255, 0}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1685,8 +1692,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::STRING; std::vector values{"not a number", "10", "-2"}; @@ -1709,7 +1716,7 @@ void FCesiumPropertyTablePropertySpec::Define() { offsets[offsets.size() - 1] = currentOffset; std::vector offsetsData = GetValuesAsBytes(offsets); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1746,8 +1753,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with offset / scale", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -1760,7 +1767,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{-1.1, 2.2, -3.3, 4.0}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1807,8 +1814,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC2; classProperty.componentType = ClassProperty::ComponentType::INT32; @@ -1818,7 +1825,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::ivec2(10, 4)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1852,8 +1859,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from glm::ivec2 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC2; classProperty.componentType = ClassProperty::ComponentType::INT32; @@ -1863,7 +1870,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::ivec2(10, 4)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1893,8 +1900,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; @@ -1904,7 +1911,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::vec3(std::numeric_limits::max(), -1.0f, 2.0f)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -1937,8 +1944,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with noData / default value", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC2; classProperty.componentType = ClassProperty::ComponentType::INT32; @@ -1954,7 +1961,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::ivec2(10, 4)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2008,8 +2015,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC2; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -2019,7 +2026,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec2(1.5, -1.5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2053,8 +2060,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from glm::dvec2 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC2; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -2064,7 +2071,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec2(1.5, -1.5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2094,8 +2101,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from normalized glm::u8vec2 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC2; classProperty.componentType = ClassProperty::ComponentType::UINT8; classProperty.normalized = true; @@ -2106,7 +2113,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::u8vec2(10, 4)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2140,8 +2147,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::STRING; std::vector values{"X=10 Y=3", "not a vector", "X=-2 Y=4"}; @@ -2164,7 +2171,7 @@ void FCesiumPropertyTablePropertySpec::Define() { offsets[offsets.size() - 1] = currentOffset; std::vector offsetsData = GetValuesAsBytes(offsets); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2201,8 +2208,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with offset / scale", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC2; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -2218,7 +2225,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec2(1.5, -1.5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2269,8 +2276,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::INT32; @@ -2280,7 +2287,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::ivec3(10, 4, 5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2314,8 +2321,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from glm::ivec3 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::INT32; @@ -2325,7 +2332,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::ivec3(10, 4, 5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2355,8 +2362,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; @@ -2367,7 +2374,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::vec3(std::numeric_limits::max(), -1.0f, 2.0f)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2401,8 +2408,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with noData / default value", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::INT32; @@ -2422,7 +2429,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::ivec3(10, 4, 5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2476,8 +2483,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; @@ -2487,7 +2494,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::vec3(10.0f, 4.4f, 5.4f)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2521,8 +2528,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from glm::vec3 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; @@ -2532,7 +2539,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::vec3(10.0f, 4.4f, 5.4f)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2562,8 +2569,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC2; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -2574,7 +2581,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec2(std::numeric_limits::max(), -1.0)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2612,8 +2619,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with offset / scale", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; @@ -2629,7 +2636,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::vec3(10.0f, 4.4f, 5.4f)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2680,8 +2687,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -2691,7 +2698,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec3(1.5, -1.5, -2.01)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2725,8 +2732,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from glm::dvec3 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -2736,7 +2743,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec3(1.5, -1.5, -2.01)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2766,8 +2773,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from normalized glm::i8vec3 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::INT8; classProperty.normalized = true; @@ -2778,7 +2785,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::i8vec3(1, -1, -2)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2813,8 +2820,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::STRING; std::vector values{ @@ -2840,7 +2847,7 @@ void FCesiumPropertyTablePropertySpec::Define() { offsets[offsets.size() - 1] = currentOffset; std::vector offsetsData = GetValuesAsBytes(offsets); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2877,8 +2884,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with offset / scale", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC3; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -2894,7 +2901,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec3(1.5, -1.5, -2.01)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2945,8 +2952,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC4; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -2956,7 +2963,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec4(1.5, -1.5, -2.01, 5.5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -2990,8 +2997,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from glm::dvec4 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC4; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -3001,7 +3008,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec4(1.5, -1.5, -2.01, 5.5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3035,8 +3042,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from glm::i8vec4 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC4; classProperty.componentType = ClassProperty::ComponentType::INT8; classProperty.normalized = true; @@ -3047,7 +3054,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::i8vec4(1, -1, -2, 5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3087,8 +3094,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::STRING; std::vector values{ @@ -3114,7 +3121,7 @@ void FCesiumPropertyTablePropertySpec::Define() { offsets[offsets.size() - 1] = currentOffset; std::vector offsetsData = GetValuesAsBytes(offsets); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3151,8 +3158,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with offset / scale", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC4; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -3168,7 +3175,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::dvec4(1.5, -1.5, -2.01, 5.5)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3220,8 +3227,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::MAT4; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -3241,7 +3248,7 @@ void FCesiumPropertyTablePropertySpec::Define() { // clang-format on std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3276,8 +3283,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from glm::dmat4 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::MAT4; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -3297,7 +3304,7 @@ void FCesiumPropertyTablePropertySpec::Define() { // clang-format on std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3338,8 +3345,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets from glm::u8mat4x4 property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::MAT4; classProperty.componentType = ClassProperty::ComponentType::INT8; classProperty.normalized = true; @@ -3360,7 +3367,7 @@ void FCesiumPropertyTablePropertySpec::Define() { // clang-format on std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3405,15 +3412,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("converts compatible values", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; std::vector values{-2.0, 10.5}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3453,8 +3460,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns default values for incompatible type", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::VEC2; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; @@ -3463,7 +3470,7 @@ void FCesiumPropertyTablePropertySpec::Define() { glm::vec2(1.5f, 0.1f)}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3492,8 +3499,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with offset / scale", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::MAT4; classProperty.componentType = ClassProperty::ComponentType::FLOAT64; @@ -3526,7 +3533,7 @@ void FCesiumPropertyTablePropertySpec::Define() { // clang-format on std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3569,15 +3576,15 @@ void FCesiumPropertyTablePropertySpec::Define() { Describe("GetArray", [this]() { It("returns empty array for non-array property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; std::vector values{1, 2, 3, 4, 5, 6}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -3629,8 +3636,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns empty array for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; classProperty.array = true; @@ -3640,15 +3647,16 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector data = GetValuesAsBytes(values); int64 size = static_cast(values.size()) / *classProperty.count; - PropertyTablePropertyView> propertyView( - propertyTableProperty, - classProperty, - size, - gsl::span(data.data(), data.size()), - gsl::span(), - gsl::span(), - PropertyComponentType::None, - PropertyComponentType::None); + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + gsl::span(data.data(), data.size()), + gsl::span(), + gsl::span(), + PropertyComponentType::None, + PropertyComponentType::None); FCesiumPropertyTableProperty property(propertyView); TestEqual( "PropertyTablePropertyStatus", @@ -3686,8 +3694,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns array for fixed-length array property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; classProperty.array = true; @@ -3697,15 +3705,16 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector data = GetValuesAsBytes(values); int64 size = static_cast(values.size()) / *classProperty.count; - PropertyTablePropertyView> propertyView( - propertyTableProperty, - classProperty, - size, - gsl::span(data.data(), data.size()), - gsl::span(), - gsl::span(), - PropertyComponentType::None, - PropertyComponentType::None); + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + gsl::span(data.data(), data.size()), + gsl::span(), + gsl::span(), + PropertyComponentType::None, + PropertyComponentType::None); FCesiumPropertyTableProperty property(propertyView); TestEqual( "PropertyTablePropertyStatus", @@ -3751,8 +3760,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns array for variable-length array property", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; classProperty.array = true; @@ -3764,15 +3773,18 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector offsetsData = GetValuesAsBytes(offsets); int64 size = static_cast(offsets.size() - 1); - PropertyTablePropertyView> propertyView( - propertyTableProperty, - classProperty, - size, - gsl::span(data.data(), data.size()), - gsl::span(offsetsData.data(), offsetsData.size()), - gsl::span(), - PropertyComponentType::Uint16, - PropertyComponentType::None); + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + gsl::span(data.data(), data.size()), + gsl::span( + offsetsData.data(), + offsetsData.size()), + gsl::span(), + PropertyComponentType::Uint16, + PropertyComponentType::None); FCesiumPropertyTableProperty property(propertyView); TestEqual( "PropertyTablePropertyStatus", @@ -3824,8 +3836,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with noData value", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; classProperty.array = true; @@ -3837,15 +3849,16 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector data = GetValuesAsBytes(values); int64 size = static_cast(values.size()) / *classProperty.count; - PropertyTablePropertyView> propertyView( - propertyTableProperty, - classProperty, - size, - gsl::span(data.data(), data.size()), - gsl::span(), - gsl::span(), - PropertyComponentType::None, - PropertyComponentType::None); + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + gsl::span(data.data(), data.size()), + gsl::span(), + gsl::span(), + PropertyComponentType::None, + PropertyComponentType::None); FCesiumPropertyTableProperty property(propertyView); TestEqual( "PropertyTablePropertyStatus", @@ -3910,8 +3923,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with noData / default value", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; classProperty.array = true; @@ -3924,15 +3937,16 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector data = GetValuesAsBytes(values); int64 size = static_cast(values.size()) / *classProperty.count; - PropertyTablePropertyView> propertyView( - propertyTableProperty, - classProperty, - size, - gsl::span(data.data(), data.size()), - gsl::span(), - gsl::span(), - PropertyComponentType::None, - PropertyComponentType::None); + CesiumGltf::PropertyTablePropertyView> + propertyView( + propertyTableProperty, + classProperty, + size, + gsl::span(data.data(), data.size()), + gsl::span(), + gsl::span(), + PropertyComponentType::None, + PropertyComponentType::None); FCesiumPropertyTableProperty property(propertyView); TestEqual( "PropertyTablePropertyStatus", @@ -4019,15 +4033,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("returns empty value for invalid feature ID", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; std::vector values{-1, 2, -3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -4061,15 +4075,15 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets value for valid feature IDs", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; std::vector values{-1, 2, -3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -4105,8 +4119,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with offset / scale", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::FLOAT32; @@ -4119,7 +4133,7 @@ void FCesiumPropertyTablePropertySpec::Define() { classProperty.offset = offset; classProperty.scale = scale; - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -4155,8 +4169,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with noData", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; @@ -4166,7 +4180,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{-1, 2, -3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), @@ -4210,8 +4224,8 @@ void FCesiumPropertyTablePropertySpec::Define() { }); It("gets with noData / default value", [this]() { - PropertyTableProperty propertyTableProperty; - ClassProperty classProperty; + CesiumGltf::PropertyTableProperty propertyTableProperty; + CesiumGltf::ClassProperty classProperty; classProperty.type = ClassProperty::Type::SCALAR; classProperty.componentType = ClassProperty::ComponentType::INT32; @@ -4224,7 +4238,7 @@ void FCesiumPropertyTablePropertySpec::Define() { std::vector values{-1, 2, -3, 4}; std::vector data = GetValuesAsBytes(values); - PropertyTablePropertyView propertyView( + CesiumGltf::PropertyTablePropertyView propertyView( propertyTableProperty, classProperty, static_cast(values.size()), diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTexture.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTexture.spec.cpp index ae7e097b5..512597a5a 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTexture.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTexture.spec.cpp @@ -1,16 +1,14 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "CesiumPropertyTexture.h" #include "CesiumGltf/ExtensionModelExtStructuralMetadata.h" #include "CesiumGltf/Model.h" #include "CesiumGltfComponent.h" #include "CesiumGltfPrimitiveComponent.h" #include "CesiumGltfSpecUtility.h" -#include "CesiumPropertyTexture.h" #include "Misc/AutomationTest.h" #include -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumPropertyTextureSpec, "Cesium.Unit.PropertyTexture", diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp index 41e728f16..8229b5ef8 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTextureProperty.spec.cpp @@ -1,13 +1,11 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "CesiumPropertyTextureProperty.h" #include "CesiumGltfSpecUtility.h" #include "CesiumPropertyArrayBlueprintLibrary.h" -#include "CesiumPropertyTextureProperty.h" #include "Misc/AutomationTest.h" #include -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FCesiumPropertyTexturePropertySpec, "Cesium.Unit.PropertyTextureProperty", @@ -81,7 +79,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::UINT8; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 1; @@ -170,7 +168,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.normalized = true; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 1; @@ -235,7 +233,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.count = 2; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -312,7 +310,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.defaultProperty = defaultValue; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 1; @@ -434,7 +432,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::UINT8; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 1; @@ -472,7 +470,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::INT16; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -526,7 +524,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.defaultProperty = defaultValue; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 1; @@ -590,7 +588,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::INT32; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -634,7 +632,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::FLOAT32; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -688,7 +686,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.defaultProperty = defaultValue; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -758,7 +756,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::FLOAT32; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -804,7 +802,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::UINT8; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 1; @@ -848,7 +846,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.scale = scale; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -912,7 +910,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.normalized = true; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 1; @@ -955,7 +953,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::FLOAT32; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -1008,7 +1006,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.scale = scale; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 1; @@ -1066,7 +1064,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::INT8; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -1110,7 +1108,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::FLOAT32; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -1168,7 +1166,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.defaultProperty = {defaultValue[0], defaultValue[1]}; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -1239,7 +1237,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.normalized = true; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -1290,7 +1288,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::UINT8; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -1342,7 +1340,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.scale = {scale[0], scale[1]}; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -1409,7 +1407,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::INT8; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 3; @@ -1453,7 +1451,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::FLOAT32; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -1514,7 +1512,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { defaultValue[2]}; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 3; @@ -1585,7 +1583,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.normalized = true; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 3; @@ -1637,7 +1635,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::INT8; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 3; @@ -1689,7 +1687,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.scale = {scale[0], scale[1], scale[2]}; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 3; @@ -1757,7 +1755,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.normalized = true; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -1814,7 +1812,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::INT8; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -1872,7 +1870,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.scale = {scale[0], scale[1], scale[2], scale[3]}; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -1923,7 +1921,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::INT32; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -1999,7 +1997,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.count = 2; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -2067,7 +2065,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.noData = {0, 0}; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -2155,7 +2153,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.defaultProperty = {10, 20}; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 2; @@ -2256,7 +2254,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.componentType = ClassProperty::ComponentType::INT32; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -2316,7 +2314,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.scale = scale; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -2373,7 +2371,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.noData = noData; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; @@ -2441,7 +2439,7 @@ void FCesiumPropertyTexturePropertySpec::Define() { classProperty.defaultProperty = defaultValue; Sampler sampler; - ImageCesium image; + ImageAsset image; image.width = 2; image.height = 2; image.channels = 4; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.cpp b/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.cpp index 01fda781b..34dcdf0a0 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.cpp @@ -6,6 +6,7 @@ #if WITH_EDITOR #include "Editor/EditorPerformanceSettings.h" +#include "Interfaces/IPluginManager.h" #endif namespace CesiumTestHelpers { diff --git a/Source/CesiumRuntime/Private/Tests/CesiumTextureUtility.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumTextureUtility.spec.cpp index 10b8ba83b..764efa69d 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumTextureUtility.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumTextureUtility.spec.cpp @@ -1,10 +1,14 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors #include "CesiumTextureUtility.h" +#include "CesiumAsync/AsyncSystem.h" +#include "ExtensionImageAssetUnreal.h" #include "Misc/AutomationTest.h" #include "RenderingThread.h" +#include +#include +#include -using namespace CesiumGltf; using namespace CesiumTextureUtility; using namespace CesiumUtility; @@ -15,12 +19,14 @@ BEGIN_DEFINE_SPEC( EAutomationTestFlags::ProductFilter | EAutomationTestFlags::NonNullRHI) std::vector originalPixels; std::vector originalMipPixels; -ImageCesium imageCesium; +std::vector expectedMipPixelsIfGenerated; +CesiumUtility::IntrusivePointer pImageAsset; void RunTests(); void CheckPixels( - const IntrusivePointer& pRefCountedTexture); + const IntrusivePointer& pRefCountedTexture, + bool requireMips = false); void CheckSRGB( const IntrusivePointer& pRefCountedTexture, bool expectedSRGB); @@ -44,20 +50,35 @@ void CesiumTextureUtilitySpec::Define() { 0x24, 0x44, 0x84, 0xF4, 0x25, 0x45, 0x85, 0xF5}; originalMipPixels.clear(); - imageCesium = {}; - imageCesium.width = 3; - imageCesium.height = 2; + pImageAsset.emplace(); + pImageAsset->width = 3; + pImageAsset->height = 2; TestEqual( "image buffer size is correct", originalPixels.size(), - imageCesium.width * imageCesium.height * imageCesium.bytesPerChannel * - imageCesium.channels); - imageCesium.pixelData.resize(originalPixels.size()); + pImageAsset->width * pImageAsset->height * + pImageAsset->bytesPerChannel * pImageAsset->channels); + pImageAsset->pixelData.resize(originalPixels.size()); std::memcpy( - imageCesium.pixelData.data(), + pImageAsset->pixelData.data(), originalPixels.data(), originalPixels.size()); + + CesiumUtility::IntrusivePointer pCopy = + new CesiumGltf::ImageAsset(*pImageAsset); + CesiumGltfReader::ImageDecoder::generateMipMaps(*pCopy); + + expectedMipPixelsIfGenerated.clear(); + + if (pCopy->mipPositions.size() >= 2) { + expectedMipPixelsIfGenerated.resize(pCopy->mipPositions[1].byteSize); + for (size_t iSrc = pCopy->mipPositions[1].byteOffset, iDest = 0; + iDest < pCopy->mipPositions[1].byteSize; + ++iSrc, ++iDest) { + expectedMipPixelsIfGenerated[iDest] = uint8_t(pCopy->pixelData[iSrc]); + } + } }); RunTests(); @@ -65,31 +86,31 @@ void CesiumTextureUtilitySpec::Define() { Describe("With Mips", [this]() { BeforeEach([this]() { - imageCesium = {}; - imageCesium.width = 3; - imageCesium.height = 2; + pImageAsset.emplace(); + pImageAsset->width = 3; + pImageAsset->height = 2; // Original image (3x2) originalPixels = {0x20, 0x40, 0x80, 0xF0, 0x21, 0x41, 0x81, 0xF1, 0x22, 0x42, 0x82, 0xF2, 0x23, 0x43, 0x83, 0xF3, 0x24, 0x44, 0x84, 0xF4, 0x25, 0x45, 0x85, 0xF5}; - imageCesium.mipPositions.emplace_back( - ImageCesiumMipPosition{0, originalPixels.size()}); + pImageAsset->mipPositions.emplace_back( + CesiumGltf::ImageAssetMipPosition{0, originalPixels.size()}); // Mip 1 (1x1) originalMipPixels = {0x26, 0x46, 0x86, 0xF6}; - imageCesium.mipPositions.emplace_back(ImageCesiumMipPosition{ - imageCesium.mipPositions[0].byteSize, + pImageAsset->mipPositions.emplace_back(CesiumGltf::ImageAssetMipPosition{ + pImageAsset->mipPositions[0].byteSize, originalMipPixels.size()}); - imageCesium.pixelData.resize( + pImageAsset->pixelData.resize( originalPixels.size() + originalMipPixels.size()); std::memcpy( - imageCesium.pixelData.data(), + pImageAsset->pixelData.data(), originalPixels.data(), originalPixels.size()); std::memcpy( - imageCesium.pixelData.data() + originalPixels.size(), + pImageAsset->pixelData.data() + originalPixels.size(), originalMipPixels.data(), originalMipPixels.size()); }); @@ -99,22 +120,21 @@ void CesiumTextureUtilitySpec::Define() { } void CesiumTextureUtilitySpec::RunTests() { - It("ImageCesium non-sRGB", [this]() { + It("ImageAsset non-sRGB", [this]() { TUniquePtr pHalfLoaded = loadTextureAnyThreadPart( - imageCesium, + *pImageAsset, TextureAddress::TA_Mirror, TextureAddress::TA_Wrap, TextureFilter::TF_Bilinear, true, TextureGroup::TEXTUREGROUP_Cinematic, false, - std::nullopt, - nullptr); + std::nullopt); TestNotNull("pHalfLoaded", pHalfLoaded.Get()); IntrusivePointer pRefCountedTexture = loadTextureGameThreadPart(pHalfLoaded.Get()); - CheckPixels(pRefCountedTexture); + CheckPixels(pRefCountedTexture, true); CheckSRGB(pRefCountedTexture, false); CheckAddress( pRefCountedTexture, @@ -124,22 +144,21 @@ void CesiumTextureUtilitySpec::RunTests() { CheckGroup(pRefCountedTexture, TextureGroup::TEXTUREGROUP_Cinematic); }); - It("ImageCesium sRGB", [this]() { + It("ImageAsset sRGB", [this]() { TUniquePtr pHalfLoaded = loadTextureAnyThreadPart( - imageCesium, + *pImageAsset, TextureAddress::TA_Clamp, TextureAddress::TA_Mirror, TextureFilter::TF_Trilinear, true, TextureGroup::TEXTUREGROUP_Bokeh, true, - std::nullopt, - nullptr); + std::nullopt); TestNotNull("pHalfLoaded", pHalfLoaded.Get()); IntrusivePointer pRefCountedTexture = loadTextureGameThreadPart(pHalfLoaded.Get()); - CheckPixels(pRefCountedTexture); + CheckPixels(pRefCountedTexture, true); CheckSRGB(pRefCountedTexture, true); CheckAddress( pRefCountedTexture, @@ -150,26 +169,22 @@ void CesiumTextureUtilitySpec::RunTests() { }); It("Image and Sampler", [this]() { - Image image; - image.cesium = imageCesium; - - Sampler sampler; - sampler.minFilter = Sampler::MinFilter::NEAREST; - sampler.magFilter = Sampler::MagFilter::NEAREST; - sampler.wrapS = Sampler::WrapS::MIRRORED_REPEAT; - sampler.wrapT = Sampler::WrapT::CLAMP_TO_EDGE; + CesiumGltf::Sampler sampler; + sampler.minFilter = CesiumGltf::Sampler::MinFilter::NEAREST; + sampler.magFilter = CesiumGltf::Sampler::MagFilter::NEAREST; + sampler.wrapS = CesiumGltf::Sampler::WrapS::MIRRORED_REPEAT; + sampler.wrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE; TUniquePtr pHalfLoaded = loadTextureFromImageAndSamplerAnyThreadPart( - image, + *pImageAsset, sampler, - false, - nullptr); + false); TestNotNull("pHalfLoaded", pHalfLoaded.Get()); IntrusivePointer pRefCountedTexture = loadTextureGameThreadPart(pHalfLoaded.Get()); - CheckPixels(pRefCountedTexture); + CheckPixels(pRefCountedTexture, false); CheckSRGB(pRefCountedTexture, false); CheckAddress( pRefCountedTexture, @@ -180,40 +195,29 @@ void CesiumTextureUtilitySpec::RunTests() { }); It("Model", [this]() { - Model model; + CesiumGltf::Model model; - Image& image = model.images.emplace_back(); - image.cesium = imageCesium; + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset = pImageAsset; - Sampler& sampler = model.samplers.emplace_back(); - sampler.minFilter = Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; - sampler.magFilter = Sampler::MagFilter::LINEAR; - sampler.wrapS = Sampler::WrapS::REPEAT; - sampler.wrapT = Sampler::WrapT::MIRRORED_REPEAT; + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.minFilter = CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; + sampler.magFilter = CesiumGltf::Sampler::MagFilter::LINEAR; + sampler.wrapS = CesiumGltf::Sampler::WrapS::REPEAT; + sampler.wrapT = CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT; - Texture& texture = model.textures.emplace_back(); + CesiumGltf::Texture& texture = model.textures.emplace_back(); texture.source = 0; texture.sampler = 0; - std::vector textureResources; - textureResources.resize(model.images.size(), nullptr); - TUniquePtr pHalfLoaded = - loadTextureFromModelAnyThreadPart( - model, - texture, - true, - textureResources); + loadTextureFromModelAnyThreadPart(model, texture, true); TestNotNull("pHalfLoaded", pHalfLoaded.Get()); TestNotNull("pHalfLoaded->pTexture", pHalfLoaded->pTexture.get()); - TestEqual( - "textureResources[0]", - textureResources[0], - pHalfLoaded->pTexture->getTextureResource().Get()); IntrusivePointer pRefCountedTexture = loadTextureGameThreadPart(model, pHalfLoaded.Get()); - CheckPixels(pRefCountedTexture); + CheckPixels(pRefCountedTexture, true); CheckSRGB(pRefCountedTexture, true); CheckAddress( pRefCountedTexture, @@ -224,66 +228,47 @@ void CesiumTextureUtilitySpec::RunTests() { }); It("Two textures referencing one image", [this]() { - Model model; + CesiumGltf::Model model; - Image& image = model.images.emplace_back(); - image.cesium = imageCesium; + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset = pImageAsset; - Sampler& sampler1 = model.samplers.emplace_back(); - sampler1.minFilter = Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; - sampler1.magFilter = Sampler::MagFilter::LINEAR; - sampler1.wrapS = Sampler::WrapS::REPEAT; - sampler1.wrapT = Sampler::WrapT::MIRRORED_REPEAT; + CesiumGltf::Sampler& sampler1 = model.samplers.emplace_back(); + sampler1.minFilter = CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; + sampler1.magFilter = CesiumGltf::Sampler::MagFilter::LINEAR; + sampler1.wrapS = CesiumGltf::Sampler::WrapS::REPEAT; + sampler1.wrapT = CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT; - Texture& texture1 = model.textures.emplace_back(); + CesiumGltf::Texture& texture1 = model.textures.emplace_back(); texture1.source = 0; texture1.sampler = 0; - Sampler& sampler2 = model.samplers.emplace_back(); - sampler2.minFilter = Sampler::MinFilter::NEAREST; - sampler2.magFilter = Sampler::MagFilter::NEAREST; - sampler2.wrapS = Sampler::WrapS::MIRRORED_REPEAT; - sampler2.wrapT = Sampler::WrapT::REPEAT; + CesiumGltf::Sampler& sampler2 = model.samplers.emplace_back(); + sampler2.minFilter = CesiumGltf::Sampler::MinFilter::NEAREST; + sampler2.magFilter = CesiumGltf::Sampler::MagFilter::NEAREST; + sampler2.wrapS = CesiumGltf::Sampler::WrapS::MIRRORED_REPEAT; + sampler2.wrapT = CesiumGltf::Sampler::WrapT::REPEAT; - Texture& texture2 = model.textures.emplace_back(); + CesiumGltf::Texture& texture2 = model.textures.emplace_back(); texture2.source = 0; texture2.sampler = 1; - std::vector textureResources; - textureResources.resize(model.images.size(), nullptr); - TUniquePtr pHalfLoaded1 = - loadTextureFromModelAnyThreadPart( - model, - model.textures[0], - true, - textureResources); + loadTextureFromModelAnyThreadPart(model, model.textures[0], true); TestNotNull("pHalfLoaded1", pHalfLoaded1.Get()); TestNotNull("pHalfLoaded1->pTexture", pHalfLoaded1->pTexture.get()); - TestEqual( - "textureResources[0]", - textureResources[0], - pHalfLoaded1->pTexture->getTextureResource().Get()); TUniquePtr pHalfLoaded2 = - loadTextureFromModelAnyThreadPart( - model, - model.textures[1], - false, - textureResources); + loadTextureFromModelAnyThreadPart(model, model.textures[1], false); TestNotNull("pHalfLoaded2", pHalfLoaded2.Get()); TestNotNull("pHalfLoaded2->pTexture", pHalfLoaded2->pTexture.get()); - TestEqual( - "textureResources[0]", - textureResources[0], - pHalfLoaded2->pTexture->getTextureResource().Get()); IntrusivePointer pRefCountedTexture1 = loadTextureGameThreadPart(model, pHalfLoaded1.Get()); IntrusivePointer pRefCountedTexture2 = loadTextureGameThreadPart(model, pHalfLoaded2.Get()); - CheckPixels(pRefCountedTexture1); + CheckPixels(pRefCountedTexture1, true); CheckSRGB(pRefCountedTexture1, true); CheckAddress( pRefCountedTexture1, @@ -292,7 +277,7 @@ void CesiumTextureUtilitySpec::RunTests() { CheckFilter(pRefCountedTexture1, TextureFilter::TF_Default); CheckGroup(pRefCountedTexture1, TextureGroup::TEXTUREGROUP_World); - CheckPixels(pRefCountedTexture2); + CheckPixels(pRefCountedTexture2, false); CheckSRGB(pRefCountedTexture2, false); CheckAddress( pRefCountedTexture2, @@ -310,40 +295,29 @@ void CesiumTextureUtilitySpec::RunTests() { }); It("Loading the same texture twice", [this]() { - Model model; + CesiumGltf::Model model; - Image& image = model.images.emplace_back(); - image.cesium = imageCesium; + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset = pImageAsset; - Sampler& sampler = model.samplers.emplace_back(); - sampler.minFilter = Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; - sampler.magFilter = Sampler::MagFilter::LINEAR; - sampler.wrapS = Sampler::WrapS::REPEAT; - sampler.wrapT = Sampler::WrapT::MIRRORED_REPEAT; + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.minFilter = CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; + sampler.magFilter = CesiumGltf::Sampler::MagFilter::LINEAR; + sampler.wrapS = CesiumGltf::Sampler::WrapS::REPEAT; + sampler.wrapT = CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT; - Texture& texture = model.textures.emplace_back(); + CesiumGltf::Texture& texture = model.textures.emplace_back(); texture.source = 0; texture.sampler = 0; - std::vector textureResources; - textureResources.resize(model.images.size(), nullptr); - TUniquePtr pHalfLoaded = - loadTextureFromModelAnyThreadPart( - model, - texture, - true, - textureResources); + loadTextureFromModelAnyThreadPart(model, texture, true); TestNotNull("pHalfLoaded", pHalfLoaded.Get()); TestNotNull("pHalfLoaded->pTexture", pHalfLoaded->pTexture.get()); - TestEqual( - "textureResources[0]", - textureResources[0], - pHalfLoaded->pTexture->getTextureResource().Get()); IntrusivePointer pRefCountedTexture = loadTextureGameThreadPart(model, pHalfLoaded.Get()); - CheckPixels(pRefCountedTexture); + CheckPixels(pRefCountedTexture, true); CheckSRGB(pRefCountedTexture, true); CheckAddress( pRefCountedTexture, @@ -352,19 +326,12 @@ void CesiumTextureUtilitySpec::RunTests() { CheckFilter(pRefCountedTexture, TextureFilter::TF_Default); CheckGroup(pRefCountedTexture, TextureGroup::TEXTUREGROUP_World); - std::vector textureResources2; - textureResources2.resize(model.images.size(), nullptr); - // Copy the model and load the same texture again. // This time there's no more pixel data, so it's necessary to use the // previously-created texture. - Model model2 = model; + CesiumGltf::Model model2 = model; TUniquePtr pHalfLoaded2 = - loadTextureFromModelAnyThreadPart( - model2, - model.textures[0], - true, - textureResources2); + loadTextureFromModelAnyThreadPart(model2, model.textures[0], true); TestNotNull("pHalfLoaded2", pHalfLoaded2.Get()); TestNotNull("pHalfLoaded2->pTexture", pHalfLoaded2->pTexture.get()); TestNull( @@ -377,40 +344,29 @@ void CesiumTextureUtilitySpec::RunTests() { }); It("Loading the same texture twice from one model", [this]() { - Model model; + CesiumGltf::Model model; - Image& image = model.images.emplace_back(); - image.cesium = imageCesium; + CesiumGltf::Image& image = model.images.emplace_back(); + image.pAsset = pImageAsset; - Sampler& sampler = model.samplers.emplace_back(); - sampler.minFilter = Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; - sampler.magFilter = Sampler::MagFilter::LINEAR; - sampler.wrapS = Sampler::WrapS::REPEAT; - sampler.wrapT = Sampler::WrapT::MIRRORED_REPEAT; + CesiumGltf::Sampler& sampler = model.samplers.emplace_back(); + sampler.minFilter = CesiumGltf::Sampler::MinFilter::LINEAR_MIPMAP_LINEAR; + sampler.magFilter = CesiumGltf::Sampler::MagFilter::LINEAR; + sampler.wrapS = CesiumGltf::Sampler::WrapS::REPEAT; + sampler.wrapT = CesiumGltf::Sampler::WrapT::MIRRORED_REPEAT; - Texture& texture = model.textures.emplace_back(); + CesiumGltf::Texture& texture = model.textures.emplace_back(); texture.source = 0; texture.sampler = 0; - std::vector textureResources; - textureResources.resize(model.images.size(), nullptr); - TUniquePtr pHalfLoaded = - loadTextureFromModelAnyThreadPart( - model, - texture, - true, - textureResources); + loadTextureFromModelAnyThreadPart(model, texture, true); TestNotNull("pHalfLoaded", pHalfLoaded.Get()); TestNotNull("pHalfLoaded->pTexture", pHalfLoaded->pTexture.get()); - TestEqual( - "textureResources[0]", - textureResources[0], - pHalfLoaded->pTexture->getTextureResource().Get()); IntrusivePointer pRefCountedTexture = loadTextureGameThreadPart(model, pHalfLoaded.Get()); - CheckPixels(pRefCountedTexture); + CheckPixels(pRefCountedTexture, true); CheckSRGB(pRefCountedTexture, true); CheckAddress( pRefCountedTexture, @@ -419,18 +375,11 @@ void CesiumTextureUtilitySpec::RunTests() { CheckFilter(pRefCountedTexture, TextureFilter::TF_Default); CheckGroup(pRefCountedTexture, TextureGroup::TEXTUREGROUP_World); - std::vector textureResources2; - textureResources2.resize(model.images.size(), nullptr); - // Load the same texture again. // This time there's no more pixel data, so it's necessary to use the // previously-created texture. TUniquePtr pHalfLoaded2 = - loadTextureFromModelAnyThreadPart( - model, - model.textures[0], - true, - textureResources2); + loadTextureFromModelAnyThreadPart(model, model.textures[0], true); TestNotNull("pHalfLoaded2", pHalfLoaded2.Get()); TestNotNull("pHalfLoaded2->pTexture", pHalfLoaded2->pTexture.get()); TestNull( @@ -444,7 +393,8 @@ void CesiumTextureUtilitySpec::RunTests() { } void CesiumTextureUtilitySpec::CheckPixels( - const IntrusivePointer& pRefCountedTexture) { + const IntrusivePointer& pRefCountedTexture, + bool requireMips) { TestNotNull("pRefCountedTexture", pRefCountedTexture.get()); TestNotNull( "pRefCountedTexture->getUnrealTexture()", @@ -494,27 +444,35 @@ void CesiumTextureUtilitySpec::CheckPixels( TestEqual("pixel-alpha", readPixels[i].A, originalPixels[i * 4 + 3]); } + if (requireMips) { + TestTrue("Has Mips", !readPixelsMip1.IsEmpty()); + } + if (!readPixelsMip1.IsEmpty()) { + std::vector& pixelsToMatch = originalMipPixels.empty() + ? expectedMipPixelsIfGenerated + : originalMipPixels; + TestEqual( "read buffer size", readPixelsMip1.Num() * 4, - originalMipPixels.size()); + pixelsToMatch.size()); for (size_t i = 0; - i < readPixelsMip1.Num() && (i * 4 + 3) < originalMipPixels.size(); + i < readPixelsMip1.Num() && (i * 4 + 3) < pixelsToMatch.size(); ++i) { - TestEqual("mip pixel-red", readPixelsMip1[i].R, originalMipPixels[i * 4]); + TestEqual("mip pixel-red", readPixelsMip1[i].R, pixelsToMatch[i * 4]); TestEqual( "mip pixel-green", readPixelsMip1[i].G, - originalMipPixels[i * 4 + 1]); + pixelsToMatch[i * 4 + 1]); TestEqual( "mip pixel-blue", readPixelsMip1[i].B, - originalMipPixels[i * 4 + 2]); + pixelsToMatch[i * 4 + 2]); TestEqual( "mip pixel-alpha", readPixelsMip1[i].A, - originalMipPixels[i * 4 + 3]); + pixelsToMatch[i * 4 + 3]); } } } diff --git a/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp b/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp index cc8bd38b1..2ab9e6f9d 100644 --- a/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp @@ -1,8 +1,8 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "GeoTransforms.h" #include "CesiumGeospatial/Ellipsoid.h" #include "CesiumUtility/Math.h" -#include "GeoTransforms.h" #include "Misc/AutomationTest.h" using namespace CesiumGeospatial; diff --git a/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp b/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp index 8e5517ebb..fbe751339 100644 --- a/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp @@ -2,6 +2,7 @@ #if WITH_EDITOR +#include "GlobeAwareDefaultPawn.h" #include "CesiumFlyToComponent.h" #include "CesiumGeoreference.h" #include "CesiumGlobeAnchorComponent.h" @@ -10,7 +11,6 @@ #include "Editor.h" #include "Engine/World.h" #include "EngineUtils.h" -#include "GlobeAwareDefaultPawn.h" #include "Misc/AutomationTest.h" #include "Tests/AutomationEditorCommon.h" diff --git a/Source/CesiumRuntime/Private/Tests/UnrealAssetAccessor.spec.cpp b/Source/CesiumRuntime/Private/Tests/UnrealAssetAccessor.spec.cpp index 539949770..23ad0b24d 100644 --- a/Source/CesiumRuntime/Private/Tests/UnrealAssetAccessor.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/UnrealAssetAccessor.spec.cpp @@ -1,5 +1,6 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "UnrealAssetAccessor.h" #include "Async/Async.h" #include "CesiumAsync/IAssetResponse.h" #include "CesiumRuntime.h" @@ -7,7 +8,6 @@ #include "Misc/AutomationTest.h" #include "Misc/FileHelper.h" #include "Misc/Paths.h" -#include "UnrealAssetAccessor.h" BEGIN_DEFINE_SPEC( FUnrealAssetAccessorSpec, diff --git a/Source/CesiumRuntime/Private/Tests/UnrealMetadataConversions.spec.cpp b/Source/CesiumRuntime/Private/Tests/UnrealMetadataConversions.spec.cpp index a39999677..f4c9e9af0 100644 --- a/Source/CesiumRuntime/Private/Tests/UnrealMetadataConversions.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/UnrealMetadataConversions.spec.cpp @@ -1,13 +1,11 @@ // Copyright 2020-2024 CesiumGS, Inc. and Contributors +#include "UnrealMetadataConversions.h" #include "CesiumTestHelpers.h" #include "Misc/AutomationTest.h" -#include "UnrealMetadataConversions.h" #include -using namespace CesiumGltf; - BEGIN_DEFINE_SPEC( FUnrealMetadataConversionsSpec, "Cesium.Unit.MetadataConversions", diff --git a/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Source/CesiumRuntime/Public/Cesium3DTileset.h index 955ea533f..8fa0b4c6c 100644 --- a/Source/CesiumRuntime/Public/Cesium3DTileset.h +++ b/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -626,6 +626,20 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { UPROPERTY(EditAnywhere, Category = "Cesium|Debug") bool LogSelectionStats = false; + /** + * If true, logs stats on the assets in this tileset's shared asset system to + * the Output Log. + */ + UPROPERTY(EditAnywhere, Category = "Cesium|Debug") + bool LogSharedAssetStats = false; + + /** + * If true, draws debug text above each tile being rendered with information + * about that tile. + */ + UPROPERTY(EditAnywhere, Category = "Cesium|Debug") + bool DrawTileInfo = false; + /** * Define the collision profile for all the 3D tiles created inside this * actor. diff --git a/Source/CesiumRuntime/Public/CesiumMetadataValueType.h b/Source/CesiumRuntime/Public/CesiumMetadataValueType.h index e01f6a6ee..ce6c3dd3b 100644 --- a/Source/CesiumRuntime/Public/CesiumMetadataValueType.h +++ b/Source/CesiumRuntime/Public/CesiumMetadataValueType.h @@ -5,7 +5,6 @@ #include "CesiumGltf/PropertyArrayView.h" #include "CesiumGltf/PropertyType.h" #include "CesiumGltf/PropertyTypeTraits.h" -#include "UObject/ObjectMacros.h" #include "CesiumMetadataValueType.generated.h" /** diff --git a/Source/CesiumRuntime/Public/CesiumPropertyTable.h b/Source/CesiumRuntime/Public/CesiumPropertyTable.h index c2c1304de..5312f75e6 100644 --- a/Source/CesiumRuntime/Public/CesiumPropertyTable.h +++ b/Source/CesiumRuntime/Public/CesiumPropertyTable.h @@ -2,7 +2,6 @@ #pragma once -#include "CesiumGltf/Class.h" #include "CesiumMetadataValue.h" #include "CesiumPropertyTableProperty.h" #include "Kismet/BlueprintFunctionLibrary.h" diff --git a/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h b/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h index c9c855b5a..7d4b9a056 100644 --- a/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h +++ b/Source/CesiumRuntime/Public/CesiumPropertyTextureProperty.h @@ -98,7 +98,7 @@ struct CESIUMRUNTIME_API FCesiumPropertyTextureProperty { const int64 getTexCoordSetIndex() const; const CesiumGltf::Sampler* getSampler() const; - const CesiumGltf::ImageCesium* getImage() const; + const CesiumGltf::ImageAsset* getImage() const; const std::optional getTextureTransform() const; diff --git a/extern/cesium-native b/extern/cesium-native index f8b38abbb..750d5f91d 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit f8b38abbbaa24ec2984ff663182240d06285b36c +Subproject commit 750d5f91d18f7d8e203d89e6906edc67c1a7101c diff --git a/package-lock.json b/package-lock.json index d1873851a..7cd411f99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,27 +1,27 @@ { "name": "cesium-unreal", - "version": "2.4.0", + "version": "2.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cesium-unreal", - "version": "2.4.0", + "version": "2.8.0", "license": "Apache-2.0", "devDependencies": { "clang-format": "^1.5.0" } }, "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true }, "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "node_modules/brace-expansion": { @@ -35,12 +35,12 @@ } }, "node_modules/clang-format": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.5.0.tgz", - "integrity": "sha512-C1LucFX7E+ABVYcPEbBHM4PYQ2+WInXsqsLpFlQ9cmRfSbk7A7b1I06h/nE4bQ3MsyEkb31jY2gC0Dtc76b4IA==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz", + "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==", "dev": true, "dependencies": { - "async": "^1.5.2", + "async": "^3.2.3", "glob": "^7.0.0", "resolve": "^1.1.6" }, @@ -53,31 +53,35 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -88,22 +92,23 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1" + "function-bind": "^1.1.2" }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" } }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "dependencies": { "once": "^1.3.0", @@ -117,12 +122,15 @@ "dev": true }, "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -143,7 +151,7 @@ "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { "wrappy": "1" @@ -152,26 +160,42 @@ "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -180,7 +204,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true } }