253 lines
8.7 KiB
C++
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());
|
|
}
|
|
}
|
|
}
|