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

922 lines
30 KiB
C++
Raw Normal View History

2025-10-14 11:14:54 +08:00
// Copyright 2020-2024 CesiumGS, Inc. and Contributors
#include "CesiumFeatureIdTexture.h"
#include "CesiumGltfPrimitiveComponent.h"
#include "CesiumGltfSpecUtility.h"
#include "Misc/AutomationTest.h"
#include <CesiumGltf/ExtensionExtMeshFeatures.h>
#include <CesiumGltf/ExtensionKhrTextureTransform.h>
#include <CesiumUtility/Math.h>
BEGIN_DEFINE_SPEC(
FCesiumFeatureIdTextureSpec,
"Cesium.Unit.FeatureIdTexture",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext |
EAutomationTestFlags::ServerContext |
EAutomationTestFlags::CommandletContext |
EAutomationTestFlags::ProductFilter)
CesiumGltf::Model model;
CesiumGltf::MeshPrimitive* pPrimitive;
const std::vector<glm::vec2> texCoords{
glm::vec2(0, 0),
glm::vec2(0.5, 0),
glm::vec2(0, 0.5),
glm::vec2(0.5, 0.5)};
TObjectPtr<UCesiumGltfPrimitiveComponent> pPrimitiveComponent;
END_DEFINE_SPEC(FCesiumFeatureIdTextureSpec)
void FCesiumFeatureIdTextureSpec::Define() {
Describe("Constructor", [this]() {
BeforeEach([this]() {
model = CesiumGltf::Model();
CesiumGltf::Mesh& mesh = model.meshes.emplace_back();
pPrimitive = &mesh.primitives.emplace_back();
});
It("constructs invalid instance for empty texture", [this]() {
FCesiumFeatureIdTexture featureIDTexture;
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::ErrorInvalidTexture);
auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView();
TestEqual(
"FeatureIDTextureViewStatus",
featureIDTextureView.status(),
CesiumGltf::FeatureIdTextureViewStatus::ErrorUninitialized);
});
It("constructs invalid instance for nonexistent texture", [this]() {
CesiumGltf::FeatureIdTexture texture;
texture.index = -1;
texture.texCoord = 0;
texture.channels = {0};
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::ErrorInvalidTexture);
auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView();
TestEqual(
"FeatureIDTextureViewStatus",
featureIDTextureView.status(),
CesiumGltf::FeatureIdTextureViewStatus::ErrorInvalidTexture);
});
It("constructs invalid instance for texture with invalid image", [this]() {
CesiumGltf::Texture& gltfTexture = model.textures.emplace_back();
gltfTexture.source = -1;
CesiumGltf::FeatureIdTexture texture;
texture.index = 0;
texture.texCoord = 0;
texture.channels = {0};
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::ErrorInvalidTexture);
auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView();
TestEqual(
"FeatureIDTextureViewStatus",
featureIDTextureView.status(),
CesiumGltf::FeatureIdTextureViewStatus::ErrorInvalidImage);
});
It("constructs valid instance", [this]() {
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoords,
0);
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView();
TestEqual(
"FeatureIDTextureViewStatus",
featureIDTextureView.status(),
CesiumGltf::FeatureIdTextureViewStatus::Valid);
});
It("constructs valid instance for texture with nonexistent texcoord attribute",
[this]() {
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));
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;
CesiumGltf::FeatureIdTexture texture;
texture.index = 0;
texture.texCoord = 0;
texture.channels = {0};
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView();
TestEqual(
"FeatureIDTextureViewStatus",
featureIDTextureView.status(),
CesiumGltf::FeatureIdTextureViewStatus::Valid);
});
It("constructs valid instance for texture with invalid texcoord accessor",
[this]() {
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));
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;
CesiumGltf::FeatureIdTexture texture;
texture.index = 0;
texture.texCoord = 0;
texture.channels = {0};
pPrimitive->attributes.insert({"TEXCOORD_0", 0});
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
auto featureIDTextureView = featureIDTexture.getFeatureIdTextureView();
TestEqual(
"FeatureIDTextureViewStatus",
featureIDTextureView.status(),
CesiumGltf::FeatureIdTextureViewStatus::Valid);
});
});
Describe("GetFeatureIDForUV", [this]() {
BeforeEach([this]() {
model = CesiumGltf::Model();
CesiumGltf::Mesh& mesh = model.meshes.emplace_back();
pPrimitive = &mesh.primitives.emplace_back();
});
It("returns -1 for invalid texture", [this]() {
CesiumGltf::Texture& gltfTexture = model.textures.emplace_back();
gltfTexture.source = -1;
CesiumGltf::FeatureIdTexture texture;
texture.index = 0;
texture.texCoord = 0;
texture.channels = {0};
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
texture,
"PropertyTableName");
TestNotEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
TestEqual(
"FeatureID",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForUV(
featureIDTexture,
FVector2D::Zero()),
-1);
});
It("returns correct value for valid attribute", [this]() {
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoords,
0);
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
for (size_t i = 0; i < texCoords.size(); i++) {
const glm::vec2& texCoord = texCoords[i];
int64 featureID =
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForUV(
featureIDTexture,
{texCoord.x, texCoord.y});
TestEqual("FeatureID", featureID, featureIDs[i]);
}
});
It("returns correct value with KHR_texture_transform", [this]() {
const std::vector<uint8_t> featureIDs{1, 2, 0, 7};
const std::vector<glm::vec2> rawTexCoords{
glm::vec2(0, 0),
glm::vec2(1, 0),
glm::vec2(0, 1),
glm::vec2(1, 1)};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
rawTexCoords,
0,
CesiumGltf::Sampler::WrapS::REPEAT,
CesiumGltf::Sampler::WrapT::REPEAT);
assert(featureId.texture != std::nullopt);
CesiumGltf::ExtensionKhrTextureTransform& textureTransform =
featureId.texture
->addExtension<CesiumGltf::ExtensionKhrTextureTransform>();
textureTransform.offset = {0.5, -0.5};
textureTransform.rotation = UE_DOUBLE_HALF_PI;
textureTransform.scale = {0.5, 0.5};
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
// (0, 0) -> (0.5, -0.5) -> wraps to (0.5, 0.5)
// (1, 0) -> (0.5, -1) -> wraps to (0.5, 0)
// (0, 1) -> (1, -0.5) -> wraps to (0, 0.5)
// (1, 1) -> (1, -1) -> wraps to (0.0, 0.0)
std::vector<uint8_t> expected{7, 2, 0, 1};
for (size_t i = 0; i < texCoords.size(); i++) {
const glm::vec2& texCoord = rawTexCoords[i];
int64 featureID =
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForUV(
featureIDTexture,
{texCoord.x, texCoord.y});
TestEqual("FeatureID", featureID, expected[i]);
}
});
});
Describe("GetFeatureIDForVertex", [this]() {
BeforeEach([this]() {
model = CesiumGltf::Model();
CesiumGltf::Mesh& mesh = model.meshes.emplace_back();
pPrimitive = &mesh.primitives.emplace_back();
});
It("returns -1 for invalid texture", [this]() {
CesiumGltf::FeatureIdTexture texture;
texture.index = -1;
texture.texCoord = 0;
texture.channels = {0};
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
texture,
"PropertyTableName");
TestNotEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
TestEqual(
"FeatureIDForVertex",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex(
featureIDTexture,
0),
-1);
});
It("returns -1 for out-of-bounds index", [this]() {
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoords,
0);
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
TestEqual(
"FeatureIDForNegativeVertex",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex(
featureIDTexture,
-1),
-1);
TestEqual(
"FeatureIDForOutOfBoundsVertex",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex(
featureIDTexture,
10),
-1);
});
It("returns correct value for valid texture", [this]() {
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoords,
0);
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
for (size_t i = 0; i < featureIDs.size(); i++) {
int64 featureID =
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex(
featureIDTexture,
static_cast<int64>(i));
TestEqual("FeatureIDForVertex", featureID, featureIDs[i]);
}
});
It("returns correct value for primitive with multiple texcoords", [this]() {
const std::vector<glm::vec2> texCoord0{
glm::vec2(0, 0),
glm::vec2(0.5, 0),
glm::vec2(0, 0.5),
glm::vec2(0.5, 0.5)};
std::vector<std::byte> values(texCoord0.size());
std::memcpy(values.data(), texCoord0.data(), values.size());
CreateAttributeForPrimitive(
model,
*pPrimitive,
"TEXCOORD_0",
CesiumGltf::AccessorSpec::Type::VEC2,
CesiumGltf::AccessorSpec::ComponentType::FLOAT,
std::move(values));
const std::vector<glm::vec2> texCoord1{
glm::vec2(0.5, 0.5),
glm::vec2(0, 0),
glm::vec2(0.5, 0),
glm::vec2(0.0, 0.5)};
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoord1,
1);
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
const std::vector<uint8_t> expected{2, 0, 3, 1};
for (size_t i = 0; i < featureIDs.size(); i++) {
int64 featureID =
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex(
featureIDTexture,
static_cast<int64>(i));
TestEqual("FeatureIDForVertex", featureID, expected[i]);
}
});
});
Describe("GetFeatureIDFromHit", [this]() {
BeforeEach([this]() {
model = CesiumGltf::Model();
CesiumGltf::Mesh& mesh = model.meshes.emplace_back();
pPrimitive = &mesh.primitives.emplace_back();
pPrimitive->mode = CesiumGltf::MeshPrimitive::Mode::TRIANGLES;
pPrimitiveComponent = NewObject<UCesiumGltfPrimitiveComponent>();
pPrimitiveComponent->getPrimitiveData().pMeshPrimitive = pPrimitive;
std::vector<glm::vec3> positions{
glm::vec3(-1, 0, 0),
glm::vec3(0, 1, 0),
glm::vec3(1, 0, 0),
glm::vec3(-1, 3, 0),
glm::vec3(0, 4, 0),
glm::vec3(1, 3, 0),
};
CreateAttributeForPrimitive(
model,
*pPrimitive,
"POSITION",
CesiumGltf::AccessorSpec::Type::VEC3,
CesiumGltf::AccessorSpec::ComponentType::FLOAT,
positions);
});
It("returns -1 for invalid texture", [this]() {
CesiumGltf::FeatureIdTexture texture;
texture.index = -1;
texture.texCoord = 0;
texture.channels = {0};
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
texture,
"PropertyTableName");
TestNotEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
FHitResult Hit;
Hit.Location = FVector_NetQuantize::Zero() *
CesiumPrimitiveData::positionScaleFactor;
Hit.Component = pPrimitiveComponent;
Hit.FaceIndex = 0;
TestEqual(
"FeatureIDFromHit",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit(
featureIDTexture,
Hit),
-1);
});
It("returns -1 if hit has no valid component", [this]() {
int32 positionAccessorIndex =
static_cast<int32_t>(model.accessors.size() - 1);
// For convenience when testing, the UVs are the same as the positions
// they correspond to. This means that the interpolated UV value should be
// directly equal to the barycentric coordinates of the triangle.
std::vector<glm::vec2> texCoords0{
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0),
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0)};
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoords0,
0);
CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData();
primData.PositionAccessor =
CesiumGltf::AccessorView<FVector3f>(model, positionAccessorIndex);
primData.TexCoordAccessorMap.emplace(
0,
CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::VEC2<float>>(
model,
static_cast<int32_t>(model.accessors.size() - 1)));
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
FHitResult Hit;
Hit.Location = FVector_NetQuantize(0, -1, 0) *
CesiumPrimitiveData::positionScaleFactor;
Hit.FaceIndex = 0;
Hit.Component = nullptr;
TestEqual(
"FeatureIDFromHit",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit(
featureIDTexture,
Hit),
-1);
});
It("returns -1 if specified texcoord set does not exist", [this]() {
int32 positionAccessorIndex =
static_cast<int32_t>(model.accessors.size() - 1);
// For convenience when testing, the UVs are the same as the positions
// they correspond to. This means that the interpolated UV value should be
// directly equal to the barycentric coordinates of the triangle.
std::vector<glm::vec2> texCoords0{
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0),
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0)};
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoords0,
0);
CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData();
primData.PositionAccessor =
CesiumGltf::AccessorView<FVector3f>(model, positionAccessorIndex);
primData.TexCoordAccessorMap.emplace(
1,
CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::VEC2<float>>(
model,
static_cast<int32_t>(model.accessors.size() - 1)));
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
FHitResult Hit;
Hit.Location = FVector_NetQuantize(0, -1, 0) *
CesiumPrimitiveData::positionScaleFactor;
Hit.FaceIndex = 0;
Hit.Component = pPrimitiveComponent;
TestEqual(
"FeatureIDFromHit",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit(
featureIDTexture,
Hit),
-1);
});
It("returns correct value for valid texture", [this]() {
int32 positionAccessorIndex =
static_cast<int32_t>(model.accessors.size() - 1);
// For convenience when testing, the UVs are the same as the positions
// they correspond to. This means that the interpolated UV value should be
// directly equal to the barycentric coordinates of the triangle.
std::vector<glm::vec2> texCoords0{
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0),
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0)};
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoords0,
0);
CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData();
primData.PositionAccessor =
CesiumGltf::AccessorView<FVector3f>(model, positionAccessorIndex);
primData.TexCoordAccessorMap.emplace(
0,
CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::VEC2<float>>(
model,
static_cast<int32_t>(model.accessors.size() - 1)));
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
FHitResult Hit;
Hit.FaceIndex = 0;
Hit.Component = pPrimitiveComponent;
std::array<FVector_NetQuantize, 3> locations{
FVector_NetQuantize(1, 0, 0),
FVector_NetQuantize(0, -1, 0),
FVector_NetQuantize(0.0, -0.25, 0)};
std::array<int64, 3> expected{3, 1, 0};
for (size_t i = 0; i < locations.size(); i++) {
Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor;
int64 featureID =
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit(
featureIDTexture,
Hit);
TestEqual("FeatureIDFromHit", featureID, expected[i]);
}
});
It("returns correct value for different face", [this]() {
int32 positionAccessorIndex =
static_cast<int32_t>(model.accessors.size() - 1);
// For convenience when testing, the UVs are the same as the positions
// they correspond to. This means that the interpolated UV value should be
// directly equal to the barycentric coordinates of the triangle.
std::vector<glm::vec2> texCoords0{
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0),
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0)};
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoords0,
0);
CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData();
primData.PositionAccessor =
CesiumGltf::AccessorView<FVector3f>(model, positionAccessorIndex);
primData.TexCoordAccessorMap.emplace(
0,
CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::VEC2<float>>(
model,
static_cast<int32_t>(model.accessors.size() - 1)));
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
FHitResult Hit;
Hit.FaceIndex = 1;
Hit.Component = pPrimitiveComponent;
std::array<FVector_NetQuantize, 3> locations{
FVector_NetQuantize(1, 3, 0),
FVector_NetQuantize(0, -4, 0),
FVector_NetQuantize(0.0, -3.25, 0)};
std::array<int64, 3> expected{3, 1, 0};
for (size_t i = 0; i < locations.size(); i++) {
Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor;
int64 featureID =
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit(
featureIDTexture,
Hit);
TestEqual("FeatureIDFromHit", featureID, expected[i]);
}
});
It("returns correct value for primitive with multiple texcoords", [this]() {
int32 positionAccessorIndex =
static_cast<int32_t>(model.accessors.size() - 1);
// For convenience when testing, the UVs are the same as the positions
// they correspond to. This means that the interpolated UV value should be
// directly equal to the barycentric coordinates of the triangle.
std::vector<glm::vec2> texCoords0{
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0),
glm::vec2(-1, 0),
glm::vec2(0, 1),
glm::vec2(1, 0)};
CreateAttributeForPrimitive(
model,
*pPrimitive,
"TEXCOORD_0",
CesiumGltf::AccessorSpec::Type::VEC2,
CesiumGltf::AccessorSpec::ComponentType::FLOAT,
GetValuesAsBytes(texCoords0));
int32 texCoord0AccessorIndex =
static_cast<int32_t>(model.accessors.size() - 1);
std::vector<glm::vec2> texCoords1{
glm::vec2(0.5, 0.5),
glm::vec2(0, 1.0),
glm::vec2(1, 0),
glm::vec2(0.5, 0.5),
glm::vec2(0, 1.0),
glm::vec2(1, 0),
};
const std::vector<uint8_t> featureIDs{0, 3, 1, 2};
CesiumGltf::FeatureId& featureId = AddFeatureIDsAsTextureToModel(
model,
*pPrimitive,
featureIDs,
4,
2,
2,
texCoords1,
1);
FCesiumFeatureIdTexture featureIDTexture(
model,
*pPrimitive,
*featureId.texture,
"PropertyTableName");
CesiumPrimitiveData& primData = pPrimitiveComponent->getPrimitiveData();
primData.PositionAccessor =
CesiumGltf::AccessorView<FVector3f>(model, positionAccessorIndex);
primData.TexCoordAccessorMap.emplace(
0,
CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::VEC2<float>>(
model,
texCoord0AccessorIndex));
primData.TexCoordAccessorMap.emplace(
0,
CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::VEC2<float>>(
model,
1));
primData.TexCoordAccessorMap.emplace(
1,
CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::VEC2<float>>(
model,
static_cast<int32_t>(model.accessors.size() - 1)));
TestEqual(
"FeatureIDTextureStatus",
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
featureIDTexture),
ECesiumFeatureIdTextureStatus::Valid);
FHitResult Hit;
Hit.FaceIndex = 0;
Hit.Component = pPrimitiveComponent;
std::array<FVector_NetQuantize, 3> locations{
FVector_NetQuantize(1, 0, 0),
FVector_NetQuantize(0, -1, 0),
FVector_NetQuantize(-1, 0, 0)};
std::array<int64, 3> expected{3, 1, 2};
for (size_t i = 0; i < locations.size(); i++) {
Hit.Location = locations[i] * CesiumPrimitiveData::positionScaleFactor;
int64 featureID =
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit(
featureIDTexture,
Hit);
TestEqual("FeatureIDFromHit", featureID, expected[i]);
}
});
});
}