bmh/FlightSimulation/Plugins/CesiumForUnreal_5.4/Source/CesiumRuntime/Private/ExtensionImageAssetUnreal.cpp
2025-02-07 22:52:32 +08:00

115 lines
3.6 KiB
C++

#include "ExtensionImageAssetUnreal.h"
#include "CesiumRuntime.h"
#include "CesiumTextureUtility.h"
#include <CesiumGltf/ImageAsset.h>
#include <CesiumGltfReader/GltfReader.h>
using namespace CesiumAsync;
using namespace CesiumGltfReader;
namespace {
std::mutex createExtensionMutex;
std::pair<ExtensionImageAssetUnreal&, std::optional<Promise<void>>>
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<EPixelFormat>& 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<FCesiumTextureResource, FCesiumTextureResourceDeleter> 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 {
pResource->InitResource(
FRHICommandListImmediate::Get()); // Init Resource now requires a
// command list.
});
maybePromise->resolve();
return extension;
}
ExtensionImageAssetUnreal::ExtensionImageAssetUnreal(
const CesiumAsync::SharedFuture<void>& future)
: _pTextureResource(nullptr), _futureCreateResource(future) {}
const TSharedPtr<FCesiumTextureResource>&
ExtensionImageAssetUnreal::getTextureResource() const {
return this->_pTextureResource;
}
CesiumAsync::SharedFuture<void>& ExtensionImageAssetUnreal::getFuture() {
return this->_futureCreateResource;
}
const CesiumAsync::SharedFuture<void>&
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<ExtensionImageAssetUnreal&, std::optional<Promise<void>>>
getOrCreateImageFuture(
const AsyncSystem& asyncSystem,
CesiumGltf::ImageAsset& imageCesium) {
std::scoped_lock lock(createExtensionMutex);
ExtensionImageAssetUnreal* pExtension =
imageCesium.getExtension<ExtensionImageAssetUnreal>();
if (!pExtension) {
// This thread will work on this image.
Promise<void> promise = asyncSystem.createPromise<void>();
ExtensionImageAssetUnreal& extension =
imageCesium.addExtension<ExtensionImageAssetUnreal>(
promise.getFuture().share());
return {extension, std::move(promise)};
} else {
// Another thread is already working on this image.
return {*pExtension, std::nullopt};
}
}
} // namespace