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

253 lines
8.7 KiB
C++

#include "UnrealPrepareRendererResources.h"
#include "Cesium3DTileset.h"
#include "CesiumGltfComponent.h"
#include "CesiumLifetime.h"
#include "CesiumRasterOverlay.h"
#include "CesiumRuntime.h"
#include "CreateGltfOptions.h"
#include "ExtensionImageAssetUnreal.h"
#include <Cesium3DTilesSelection/Tile.h>
#include <Cesium3DTilesSelection/TileLoadResult.h>
#include <CesiumAsync/AsyncSystem.h>
#include <CesiumGeospatial/Ellipsoid.h>
#include <glm/mat4x4.hpp>
UnrealPrepareRendererResources::UnrealPrepareRendererResources(
ACesium3DTileset* pActor)
: _pActor(pActor) {}
CesiumAsync::Future<Cesium3DTilesSelection::TileLoadResultAndRenderResources>
UnrealPrepareRendererResources::prepareInLoadThread(
const CesiumAsync::AsyncSystem& asyncSystem,
Cesium3DTilesSelection::TileLoadResult&& tileLoadResult,
const glm::dmat4& transform,
const std::any& rendererOptions) {
CreateGltfOptions::CreateModelOptions options(std::move(tileLoadResult));
if (!options.pModel) {
return asyncSystem.createResolvedFuture(
Cesium3DTilesSelection::TileLoadResultAndRenderResources{
std::move(options.tileLoadResult),
nullptr});
}
options.alwaysIncludeTangents = this->_pActor->GetAlwaysIncludeTangents();
options.createPhysicsMeshes = this->_pActor->GetCreatePhysicsMeshes();
options.ignoreKhrMaterialsUnlit = this->_pActor->GetIgnoreKhrMaterialsUnlit();
if (this->_pActor->_featuresMetadataDescription) {
options.pFeaturesMetadataDescription =
&(*this->_pActor->_featuresMetadataDescription);
} else if (this->_pActor->_metadataDescription_DEPRECATED) {
options.pEncodedMetadataDescription_DEPRECATED =
&(*this->_pActor->_metadataDescription_DEPRECATED);
}
const CesiumGeospatial::Ellipsoid& ellipsoid = tileLoadResult.ellipsoid;
CesiumAsync::Future<UCesiumGltfComponent::CreateOffGameThreadResult>
pHalfFuture = UCesiumGltfComponent::CreateOffGameThread(
asyncSystem,
transform,
std::move(options),
ellipsoid);
return MoveTemp(pHalfFuture)
.thenImmediately(
[](UCesiumGltfComponent::CreateOffGameThreadResult&& result)
-> Cesium3DTilesSelection::TileLoadResultAndRenderResources {
return Cesium3DTilesSelection::TileLoadResultAndRenderResources{
std::move(result.TileLoadResult),
result.HalfConstructed.Release()};
});
}
void* UnrealPrepareRendererResources::prepareInMainThread(
Cesium3DTilesSelection::Tile& tile,
void* pLoadThreadResult) {
Cesium3DTilesSelection::TileContent& content = tile.getContent();
if (content.isRenderContent()) {
TUniquePtr<UCesiumGltfComponent::HalfConstructed> pHalf(
reinterpret_cast<UCesiumGltfComponent::HalfConstructed*>(
pLoadThreadResult));
Cesium3DTilesSelection::TileRenderContent& renderContent =
*content.getRenderContent();
return UCesiumGltfComponent::CreateOnGameThread(
renderContent.getModel(),
this->_pActor,
std::move(pHalf),
_pActor->GetCesiumTilesetToUnrealRelativeWorldTransform(),
this->_pActor->GetMaterial(),
this->_pActor->GetTranslucentMaterial(),
this->_pActor->GetWaterMaterial(),
this->_pActor->GetCustomDepthParameters(),
tile,
this->_pActor->GetCreateNavCollision());
}
// UE_LOG(LogCesium, VeryVerbose, TEXT("No content for tile"));
return nullptr;
}
void UnrealPrepareRendererResources::free(
Cesium3DTilesSelection::Tile& tile,
void* pLoadThreadResult,
void* pMainThreadResult) noexcept {
if (pLoadThreadResult) {
UCesiumGltfComponent::HalfConstructed* pHalf =
reinterpret_cast<UCesiumGltfComponent::HalfConstructed*>(
pLoadThreadResult);
delete pHalf;
} else if (pMainThreadResult) {
UCesiumGltfComponent* pGltf =
reinterpret_cast<UCesiumGltfComponent*>(pMainThreadResult);
CesiumLifetime::destroyComponentRecursively(pGltf);
}
}
void* UnrealPrepareRendererResources::prepareRasterInLoadThread(
CesiumGltf::ImageAsset& image,
const std::any& rendererOptions) {
auto ppOptions =
std::any_cast<FRasterOverlayRendererOptions*>(&rendererOptions);
check(ppOptions != nullptr && *ppOptions != nullptr);
if (ppOptions == nullptr || *ppOptions == nullptr) {
return nullptr;
}
auto pOptions = *ppOptions;
if (pOptions->useMipmaps) {
std::optional<std::string> errorMessage =
CesiumGltfReader::ImageDecoder::generateMipMaps(image);
if (errorMessage) {
UE_LOG(
LogCesium,
Warning,
TEXT("%s"),
UTF8_TO_TCHAR(errorMessage->c_str()));
}
}
// 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,
TextureAddress::TA_Clamp,
pOptions->filter,
pOptions->useMipmaps,
pOptions->group,
sRGB,
std::nullopt);
return texture.Release();
}
void* UnrealPrepareRendererResources::prepareRasterInMainThread(
CesiumRasterOverlays::RasterOverlayTile& rasterTile,
void* pLoadThreadResult) {
TUniquePtr<CesiumTextureUtility::LoadedTextureResult> pLoadedTexture{
static_cast<CesiumTextureUtility::LoadedTextureResult*>(
pLoadThreadResult)};
if (!pLoadedTexture) {
return nullptr;
}
CesiumUtility::IntrusivePointer<
CesiumTextureUtility::ReferenceCountedUnrealTexture>
pTexture =
CesiumTextureUtility::loadTextureGameThreadPart(pLoadedTexture.Get());
if (!pTexture) {
return nullptr;
}
// Don't let this ReferenceCountedUnrealTexture be destroyed when the
// intrusive pointer goes out of scope.
pTexture->addReference();
return pTexture.get();
}
void UnrealPrepareRendererResources::freeRaster(
const CesiumRasterOverlays::RasterOverlayTile& rasterTile,
void* pLoadThreadResult,
void* pMainThreadResult) noexcept {
if (pLoadThreadResult) {
CesiumTextureUtility::LoadedTextureResult* pLoadedTexture =
static_cast<CesiumTextureUtility::LoadedTextureResult*>(
pLoadThreadResult);
delete pLoadedTexture;
}
if (pMainThreadResult) {
CesiumTextureUtility::ReferenceCountedUnrealTexture* pTexture =
static_cast<CesiumTextureUtility::ReferenceCountedUnrealTexture*>(
pMainThreadResult);
pTexture->releaseReference();
}
}
void UnrealPrepareRendererResources::attachRasterInMainThread(
const Cesium3DTilesSelection::Tile& tile,
int32_t overlayTextureCoordinateID,
const CesiumRasterOverlays::RasterOverlayTile& rasterTile,
void* pMainThreadRendererResources,
const glm::dvec2& translation,
const glm::dvec2& scale) {
const Cesium3DTilesSelection::TileContent& content = tile.getContent();
const Cesium3DTilesSelection::TileRenderContent* pRenderContent =
content.getRenderContent();
if (pMainThreadRendererResources != nullptr && pRenderContent != nullptr) {
UCesiumGltfComponent* pGltfContent =
reinterpret_cast<UCesiumGltfComponent*>(
pRenderContent->getRenderResources());
if (pGltfContent) {
pGltfContent->AttachRasterTile(
tile,
rasterTile,
static_cast<CesiumTextureUtility::ReferenceCountedUnrealTexture*>(
pMainThreadRendererResources)
->getUnrealTexture(),
translation,
scale,
overlayTextureCoordinateID);
}
}
}
void UnrealPrepareRendererResources::detachRasterInMainThread(
const Cesium3DTilesSelection::Tile& tile,
int32_t overlayTextureCoordinateID,
const CesiumRasterOverlays::RasterOverlayTile& rasterTile,
void* pMainThreadRendererResources) noexcept {
const Cesium3DTilesSelection::TileContent& content = tile.getContent();
const Cesium3DTilesSelection::TileRenderContent* pRenderContent =
content.getRenderContent();
if (pRenderContent) {
UCesiumGltfComponent* pGltfContent =
reinterpret_cast<UCesiumGltfComponent*>(
pRenderContent->getRenderResources());
if (pMainThreadRendererResources != nullptr && pGltfContent != nullptr) {
pGltfContent->DetachRasterTile(
tile,
rasterTile,
static_cast<CesiumTextureUtility::ReferenceCountedUnrealTexture*>(
pMainThreadRendererResources)
->getUnrealTexture());
}
}
}