Files
BXSSP_Andriod/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/SampleHeightMostDetailed.spec.cpp

359 lines
14 KiB
C++
Raw Normal View History

2025-10-14 11:14:54 +08:00
// Copyright 2020-2024 CesiumGS, Inc. and Contributors
#include "Cesium3DTileset.h"
#include "CesiumSampleHeightMostDetailedAsyncAction.h"
#include "CesiumSceneGeneration.h"
#include "CesiumTestHelpers.h"
#include "Misc/AutomationTest.h"
#include "SampleHeightCallbackReceiver.h"
BEGIN_DEFINE_SPEC(
FSampleHeightMostDetailedSpec,
"Cesium.Unit.SampleHeightMostDetailed",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext |
EAutomationTestFlags::ServerContext |
EAutomationTestFlags::CommandletContext |
EAutomationTestFlags::ProductFilter)
TObjectPtr<ACesium3DTileset> pTileset;
END_DEFINE_SPEC(FSampleHeightMostDetailedSpec)
// The intention of these tests is not to verify that height querying produces
// correct heights, because the cesium-native tests already do that. It's just
// to verify that the Unreal wrapper API around cesium-native is working
// correctly.
void FSampleHeightMostDetailedSpec::Define() {
Describe("Cesium World Terrain", [this]() {
BeforeEach([this]() {
CesiumTestHelpers::pushAllowTickInEditor();
UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext();
pTileset = pWorld->SpawnActor<ACesium3DTileset>();
pTileset->SetIonAssetID(1);
#if WITH_EDITOR
pTileset->SetIonAccessToken(Cesium::SceneGenerationContext::testIonToken);
pTileset->SetActorLabel(TEXT("Cesium World Terrain"));
#endif
});
AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() {
pTileset->Destroy();
CesiumTestHelpers::popAllowTickInEditor();
});
LatentIt(
"works with an empty array of positions",
EAsyncExecution::TaskGraphMainThread,
[this](const FDoneDelegate& done) {
pTileset->SampleHeightMostDetailed(
{},
FCesiumSampleHeightMostDetailedCallback::CreateLambda(
[this, done](
ACesium3DTileset* pTileset,
const TArray<FCesiumSampleHeightResult>& result,
const TArray<FString>& warnings) {
TestEqual("Number of results", result.Num(), 0);
TestEqual("Number of warnings", warnings.Num(), 0);
done.ExecuteIfBound();
}));
});
LatentIt(
"works with a single position",
EAsyncExecution::TaskGraphMainThread,
[this](const FDoneDelegate& done) {
pTileset->SampleHeightMostDetailed(
{FVector(-105.1, 40.1, 1.0)},
FCesiumSampleHeightMostDetailedCallback::CreateLambda(
[this, done](
ACesium3DTileset* pTileset,
const TArray<FCesiumSampleHeightResult>& result,
const TArray<FString>& warnings) {
TestEqual("Number of results", result.Num(), 1);
TestEqual("Number of warnings", warnings.Num(), 0);
TestTrue("SampleSuccess", result[0].SampleSuccess);
TestEqual(
"Longitude",
result[0].LongitudeLatitudeHeight.X,
-105.1,
1e-12);
TestEqual(
"Latitude",
result[0].LongitudeLatitudeHeight.Y,
40.1,
1e-12);
TestTrue(
"Height",
!FMath::IsNearlyEqual(
result[0].LongitudeLatitudeHeight.Z,
1.0,
1.0));
done.ExecuteIfBound();
}));
});
LatentIt(
"works with multiple positions",
EAsyncExecution::TaskGraphMainThread,
[this](const FDoneDelegate& done) {
pTileset->SampleHeightMostDetailed(
{FVector(-105.1, 40.1, 1.0), FVector(105.1, -40.1, 1.0)},
FCesiumSampleHeightMostDetailedCallback::CreateLambda(
[this, done](
ACesium3DTileset* pTileset,
const TArray<FCesiumSampleHeightResult>& result,
const TArray<FString>& warnings) {
TestEqual("Number of results", result.Num(), 2);
TestEqual("Number of warnings", warnings.Num(), 0);
TestTrue("SampleSuccess", result[0].SampleSuccess);
TestEqual(
"Longitude",
result[0].LongitudeLatitudeHeight.X,
-105.1,
1e-12);
TestEqual(
"Latitude",
result[0].LongitudeLatitudeHeight.Y,
40.1,
1e-12);
TestTrue(
"Height",
!FMath::IsNearlyEqual(
result[0].LongitudeLatitudeHeight.Z,
1.0,
1.0));
TestTrue("SampleSuccess", result[1].SampleSuccess);
TestEqual(
"Longitude",
result[1].LongitudeLatitudeHeight.X,
105.1,
1e-12);
TestEqual(
"Latitude",
result[1].LongitudeLatitudeHeight.Y,
-40.1,
1e-12);
TestTrue(
"Height",
!FMath::IsNearlyEqual(
result[1].LongitudeLatitudeHeight.Z,
1.0,
1.0));
done.ExecuteIfBound();
}));
});
});
Describe("Melbourne Photogrammetry", [this]() {
BeforeEach([this]() {
CesiumTestHelpers::pushAllowTickInEditor();
UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext();
pTileset = pWorld->SpawnActor<ACesium3DTileset>();
pTileset->SetIonAssetID(69380);
#if WITH_EDITOR
pTileset->SetIonAccessToken(Cesium::SceneGenerationContext::testIonToken);
pTileset->SetActorLabel(TEXT("Melbourne Photogrammetry"));
#endif
});
AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() {
pTileset->Destroy();
CesiumTestHelpers::popAllowTickInEditor();
});
LatentIt(
"indicates !HeightSampled for position outside tileset",
EAsyncExecution::TaskGraphMainThread,
[this](const FDoneDelegate& done) {
pTileset->SampleHeightMostDetailed(
// Somewhere in Sydney, not Melbourne
{FVector(151.20972, -33.87100, 1.0)},
FCesiumSampleHeightMostDetailedCallback::CreateLambda(
[this, done](
ACesium3DTileset* pTileset,
const TArray<FCesiumSampleHeightResult>& result,
const TArray<FString>& warnings) {
TestEqual("Number of results", result.Num(), 1);
TestEqual("Number of warnings", warnings.Num(), 0);
TestTrue("SampleSuccess", !result[0].SampleSuccess);
TestEqual(
"Longitude",
result[0].LongitudeLatitudeHeight.X,
151.20972,
1e-12);
TestEqual(
"Latitude",
result[0].LongitudeLatitudeHeight.Y,
-33.87100,
1e-12);
TestEqual(
"Height",
result[0].LongitudeLatitudeHeight.Z,
1.0,
1e-12);
done.ExecuteIfBound();
}));
});
LatentIt(
"can be queried via Blueprint interface",
EAsyncExecution::TaskGraphMainThread,
[this](const FDoneDelegate& done) {
UCesiumSampleHeightMostDetailedAsyncAction* pAsync =
UCesiumSampleHeightMostDetailedAsyncAction::
SampleHeightMostDetailed(
pTileset,
{FVector(144.93406, -37.82457, 1.0)});
USampleHeightCallbackReceiver::Bind(
pAsync->OnHeightsSampled,
[this, done](
const TArray<FCesiumSampleHeightResult>& result,
const TArray<FString>& warnings) {
TestEqual("Number of results", result.Num(), 1);
TestEqual("Number of warnings", warnings.Num(), 0);
TestTrue("SampleSuccess", result[0].SampleSuccess);
TestEqual(
"Longitude",
result[0].LongitudeLatitudeHeight.X,
144.93406,
1e-12);
TestEqual(
"Latitude",
result[0].LongitudeLatitudeHeight.Y,
-37.82457,
1e-12);
TestTrue(
"Height",
!FMath::IsNearlyEqual(
result[0].LongitudeLatitudeHeight.Z,
1.0,
1.0));
done.ExecuteIfBound();
});
pAsync->Activate();
});
});
Describe("Two tilesets in rapid succession", [this]() {
BeforeEach([this]() { CesiumTestHelpers::pushAllowTickInEditor(); });
AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() {
CesiumTestHelpers::popAllowTickInEditor();
});
LatentIt(
"",
EAsyncExecution::TaskGraphMainThread,
[this](const FDoneDelegate& done) {
UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext();
ACesium3DTileset* pTileset1 = pWorld->SpawnActor<ACesium3DTileset>();
pTileset1->SetIonAssetID(1);
#if WITH_EDITOR
pTileset1->SetIonAccessToken(
Cesium::SceneGenerationContext::testIonToken);
#endif
pTileset1->SampleHeightMostDetailed(
{FVector(-105.1, 40.1, 1.0)},
FCesiumSampleHeightMostDetailedCallback::CreateLambda(
[this, pWorld, done](
ACesium3DTileset* pTileset,
const TArray<FCesiumSampleHeightResult>& result,
const TArray<FString>& warnings) {
TestEqual("Number of results", result.Num(), 1);
TestEqual("Number of warnings", warnings.Num(), 0);
TestTrue("SampleSuccess", result[0].SampleSuccess);
ACesium3DTileset* pTileset2 =
pWorld->SpawnActor<ACesium3DTileset>();
pTileset2->SetIonAssetID(1);
#if WITH_EDITOR
pTileset2->SetIonAccessToken(
Cesium::SceneGenerationContext::testIonToken);
#endif
pTileset2->SampleHeightMostDetailed(
{FVector(105.1, 40.1, 1.0)},
FCesiumSampleHeightMostDetailedCallback::CreateLambda(
[this, pWorld, done](
ACesium3DTileset* pTileset,
const TArray<FCesiumSampleHeightResult>& result,
const TArray<FString>& warnings) {
TestEqual("Number of results", result.Num(), 1);
TestEqual(
"Number of warnings",
warnings.Num(),
0);
TestTrue(
"SampleSuccess",
result[0].SampleSuccess);
done.ExecuteIfBound();
}));
}));
});
});
Describe("Broken tileset", [this]() {
BeforeEach([this]() { CesiumTestHelpers::pushAllowTickInEditor(); });
AfterEach(EAsyncExecution::TaskGraphMainThread, [this]() {
CesiumTestHelpers::popAllowTickInEditor();
});
LatentIt(
"",
EAsyncExecution::TaskGraphMainThread,
[this](const FDoneDelegate& done) {
// Two slightly different error messages will occur, depending on
// whether there's a web server running on localhost.
this->AddExpectedError(
TEXT("(Errors when loading)|(error occurred)"));
UWorld* pWorld = CesiumTestHelpers::getGlobalWorldContext();
ACesium3DTileset* pTileset = pWorld->SpawnActor<ACesium3DTileset>();
pTileset->SetTilesetSource(ETilesetSource::FromUrl);
pTileset->SetUrl("http://localhost/notgonnawork");
pTileset->SampleHeightMostDetailed(
{FVector(-105.1, 40.1, 1.0)},
FCesiumSampleHeightMostDetailedCallback::CreateLambda(
[this, done](
ACesium3DTileset* pTileset,
const TArray<FCesiumSampleHeightResult>& result,
const TArray<FString>& warnings) {
TestEqual("Number of results", result.Num(), 1);
TestEqual("Number of warnings", warnings.Num(), 1);
TestFalse("SampleSuccess", result[0].SampleSuccess);
TestEqual(
"Longitude",
result[0].LongitudeLatitudeHeight.X,
-105.1,
1e-12);
TestEqual(
"Latitude",
result[0].LongitudeLatitudeHeight.Y,
40.1,
1e-12);
TestEqual(
"Height",
result[0].LongitudeLatitudeHeight.Z,
1.0,
1e-12);
TestTrue(
"Error message",
warnings[0].Contains(TEXT("failed to load")));
done.ExecuteIfBound();
}));
});
});
}