753 lines
26 KiB
C++
753 lines
26 KiB
C++
// Copyright 2020-2024 CesiumGS, Inc. and Contributors
|
|
|
|
#include "CesiumPrimitiveFeatures.h"
|
|
#include "CesiumGltf/ExtensionExtMeshFeatures.h"
|
|
#include "CesiumGltfSpecUtility.h"
|
|
#include "Misc/AutomationTest.h"
|
|
|
|
BEGIN_DEFINE_SPEC(
|
|
FCesiumPrimitiveFeaturesSpec,
|
|
"Cesium.Unit.PrimitiveFeatures",
|
|
EAutomationTestFlags::EditorContext | EAutomationTestFlags::ClientContext |
|
|
EAutomationTestFlags::ServerContext |
|
|
EAutomationTestFlags::CommandletContext |
|
|
EAutomationTestFlags::ProductFilter)
|
|
CesiumGltf::Model model;
|
|
CesiumGltf::MeshPrimitive* pPrimitive;
|
|
CesiumGltf::ExtensionExtMeshFeatures* pExtension;
|
|
END_DEFINE_SPEC(FCesiumPrimitiveFeaturesSpec)
|
|
|
|
void FCesiumPrimitiveFeaturesSpec::Define() {
|
|
Describe("Constructor", [this]() {
|
|
BeforeEach([this]() {
|
|
model = CesiumGltf::Model();
|
|
CesiumGltf::Mesh& mesh = model.meshes.emplace_back();
|
|
pPrimitive = &mesh.primitives.emplace_back();
|
|
pExtension =
|
|
&pPrimitive->addExtension<CesiumGltf::ExtensionExtMeshFeatures>();
|
|
});
|
|
|
|
It("constructs with no feature ID sets", [this]() {
|
|
// This is technically disallowed by the spec, but just make sure it's
|
|
// handled reasonably.
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
TArray<FCesiumFeatureIdSet> featureIDSets =
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(
|
|
primitiveFeatures);
|
|
TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 0);
|
|
});
|
|
|
|
It("constructs with single feature ID set", [this]() {
|
|
CesiumGltf::FeatureId& featureID = pExtension->featureIds.emplace_back();
|
|
featureID.featureCount = 10;
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
const TArray<FCesiumFeatureIdSet>& featureIDSets =
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(
|
|
primitiveFeatures);
|
|
TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 1);
|
|
|
|
const FCesiumFeatureIdSet& featureIDSet = featureIDSets[0];
|
|
TestEqual(
|
|
"Feature Count",
|
|
UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet),
|
|
static_cast<int64>(featureID.featureCount));
|
|
TestEqual(
|
|
"FeatureIDType",
|
|
UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType(
|
|
featureIDSet),
|
|
ECesiumFeatureIdSetType::Implicit);
|
|
});
|
|
|
|
It("constructs with multiple feature ID sets", [this]() {
|
|
const std::vector<uint8_t> attributeIDs{0, 0, 0};
|
|
AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 1, 0);
|
|
|
|
const std::vector<uint8_t> textureIDs{1, 2, 3};
|
|
const std::vector<glm::vec2> texCoords{
|
|
glm::vec2(0, 0),
|
|
glm::vec2(0.34, 0),
|
|
glm::vec2(0.67, 0)};
|
|
AddFeatureIDsAsTextureToModel(
|
|
model,
|
|
*pPrimitive,
|
|
textureIDs,
|
|
3,
|
|
3,
|
|
1,
|
|
texCoords,
|
|
0);
|
|
|
|
CesiumGltf::FeatureId& implicitIDs =
|
|
pExtension->featureIds.emplace_back();
|
|
implicitIDs.featureCount = 3;
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
const TArray<FCesiumFeatureIdSet>& featureIDSets =
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(
|
|
primitiveFeatures);
|
|
TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 3);
|
|
|
|
const std::vector<ECesiumFeatureIdSetType> expectedTypes{
|
|
ECesiumFeatureIdSetType::Attribute,
|
|
ECesiumFeatureIdSetType::Texture,
|
|
ECesiumFeatureIdSetType::Implicit};
|
|
|
|
for (size_t i = 0; i < featureIDSets.Num(); i++) {
|
|
const FCesiumFeatureIdSet& featureIDSet =
|
|
featureIDSets[static_cast<int32>(i)];
|
|
const CesiumGltf::FeatureId& gltfFeatureID = pExtension->featureIds[i];
|
|
TestEqual(
|
|
"Feature Count",
|
|
UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(featureIDSet),
|
|
static_cast<int64>(gltfFeatureID.featureCount));
|
|
TestEqual(
|
|
"FeatureIDType",
|
|
UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType(
|
|
featureIDSet),
|
|
expectedTypes[i]);
|
|
}
|
|
});
|
|
});
|
|
|
|
Describe("GetFeatureIDSetsOfType", [this]() {
|
|
BeforeEach([this]() {
|
|
model = CesiumGltf::Model();
|
|
CesiumGltf::Mesh& mesh = model.meshes.emplace_back();
|
|
pPrimitive = &mesh.primitives.emplace_back();
|
|
pExtension =
|
|
&pPrimitive->addExtension<CesiumGltf::ExtensionExtMeshFeatures>();
|
|
|
|
const std::vector<uint8_t> attributeIDs{0, 0, 0};
|
|
AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 1, 0);
|
|
|
|
const std::vector<uint8_t> textureIDs{1, 2, 3};
|
|
const std::vector<glm::vec2> texCoords{
|
|
glm::vec2(0, 0),
|
|
glm::vec2(0.34, 0),
|
|
glm::vec2(0.67, 0)};
|
|
AddFeatureIDsAsTextureToModel(
|
|
model,
|
|
*pPrimitive,
|
|
textureIDs,
|
|
3,
|
|
3,
|
|
1,
|
|
texCoords,
|
|
0);
|
|
|
|
CesiumGltf::FeatureId& implicitIDs =
|
|
pExtension->featureIds.emplace_back();
|
|
implicitIDs.featureCount = 3;
|
|
});
|
|
|
|
It("gets feature ID attribute", [this]() {
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
const TArray<FCesiumFeatureIdSet> featureIDSets =
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType(
|
|
primitiveFeatures,
|
|
ECesiumFeatureIdSetType::Attribute);
|
|
TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 1);
|
|
|
|
const FCesiumFeatureIdSet& featureIDSet = featureIDSets[0];
|
|
TestEqual(
|
|
"FeatureIDType",
|
|
UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType(
|
|
featureIDSet),
|
|
ECesiumFeatureIdSetType::Attribute);
|
|
|
|
const FCesiumFeatureIdAttribute& attribute =
|
|
UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute(
|
|
featureIDSet);
|
|
TestEqual(
|
|
"AttributeStatus",
|
|
UCesiumFeatureIdAttributeBlueprintLibrary::
|
|
GetFeatureIDAttributeStatus(attribute),
|
|
ECesiumFeatureIdAttributeStatus::Valid);
|
|
});
|
|
|
|
It("gets feature ID texture", [this]() {
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
const TArray<FCesiumFeatureIdSet> featureIDSets =
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType(
|
|
primitiveFeatures,
|
|
ECesiumFeatureIdSetType::Texture);
|
|
TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 1);
|
|
|
|
const FCesiumFeatureIdSet& featureIDSet = featureIDSets[0];
|
|
TestEqual(
|
|
"FeatureIDType",
|
|
UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType(
|
|
featureIDSet),
|
|
ECesiumFeatureIdSetType::Texture);
|
|
|
|
const FCesiumFeatureIdTexture& texture =
|
|
UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture(
|
|
featureIDSet);
|
|
TestEqual(
|
|
"TextureStatus",
|
|
UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDTextureStatus(
|
|
texture),
|
|
ECesiumFeatureIdTextureStatus::Valid);
|
|
});
|
|
|
|
It("gets implicit feature ID", [this]() {
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
const TArray<FCesiumFeatureIdSet> featureIDSets =
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSetsOfType(
|
|
primitiveFeatures,
|
|
ECesiumFeatureIdSetType::Implicit);
|
|
TestEqual("Number of FeatureIDSets", featureIDSets.Num(), 1);
|
|
|
|
const FCesiumFeatureIdSet& featureIDSet = featureIDSets[0];
|
|
TestEqual(
|
|
"FeatureIDType",
|
|
UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType(
|
|
featureIDSet),
|
|
ECesiumFeatureIdSetType::Implicit);
|
|
});
|
|
});
|
|
|
|
Describe("GetFirstVertexFromFace", [this]() {
|
|
BeforeEach([this]() {
|
|
model = CesiumGltf::Model();
|
|
CesiumGltf::Mesh& mesh = model.meshes.emplace_back();
|
|
pPrimitive = &mesh.primitives.emplace_back();
|
|
pExtension =
|
|
&pPrimitive->addExtension<CesiumGltf::ExtensionExtMeshFeatures>();
|
|
});
|
|
|
|
It("returns -1 for out-of-bounds face index", [this]() {
|
|
const std::vector<uint8_t> indices{0, 1, 2, 0, 2, 3};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
TestEqual(
|
|
"VertexIndexForNegativeFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace(
|
|
primitiveFeatures,
|
|
-1),
|
|
-1);
|
|
TestEqual(
|
|
"VertexIndexForOutOfBoundsFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace(
|
|
primitiveFeatures,
|
|
2),
|
|
-1);
|
|
});
|
|
|
|
It("returns correct value for primitive without indices", [this]() {
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 9;
|
|
const int64 numFaces = accessor.count / 3;
|
|
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
for (int64 i = 0; i < numFaces; i++) {
|
|
TestEqual(
|
|
"VertexIndexForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace(
|
|
primitiveFeatures,
|
|
i),
|
|
i * 3);
|
|
}
|
|
});
|
|
|
|
It("returns correct value for primitive with indices", [this]() {
|
|
const std::vector<uint8_t> indices{0, 1, 2, 0, 2, 3, 4, 5, 6};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 7;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
const size_t numFaces = indices.size() / 3;
|
|
for (size_t i = 0; i < numFaces; i++) {
|
|
TestEqual(
|
|
"VertexIndexForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFirstVertexFromFace(
|
|
primitiveFeatures,
|
|
static_cast<int64>(i)),
|
|
indices[i * 3]);
|
|
}
|
|
});
|
|
});
|
|
|
|
Describe("GetFeatureIDFromFace", [this]() {
|
|
BeforeEach([this]() {
|
|
model = CesiumGltf::Model();
|
|
CesiumGltf::Mesh& mesh = model.meshes.emplace_back();
|
|
pPrimitive = &mesh.primitives.emplace_back();
|
|
pExtension =
|
|
&pPrimitive->addExtension<CesiumGltf::ExtensionExtMeshFeatures>();
|
|
});
|
|
|
|
It("returns -1 for primitive with empty feature ID sets", [this]() {
|
|
const std::vector<uint8_t> indices{0, 1, 2, 0, 2, 3};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 6;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
// Adds empty feature ID.
|
|
pExtension->featureIds.emplace_back();
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
const TArray<FCesiumFeatureIdSet>& featureIDSets =
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(
|
|
primitiveFeatures);
|
|
|
|
TestEqual(
|
|
"FeatureIDForPrimitiveWithNoSets",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
0),
|
|
-1);
|
|
});
|
|
|
|
It("returns -1 for out of bounds feature ID set index", [this]() {
|
|
std::vector<uint8_t> attributeIDs{1, 1, 1, 1, 0, 0, 0};
|
|
AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 2, 0);
|
|
|
|
const std::vector<uint8_t> indices{0, 1, 2, 0, 2, 3, 4, 5, 6};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 7;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
const TArray<FCesiumFeatureIdSet>& featureIDSets =
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(
|
|
primitiveFeatures);
|
|
|
|
TestEqual(
|
|
"FeatureIDForOutOfBoundsSetIndex",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
0,
|
|
-1),
|
|
-1);
|
|
TestEqual(
|
|
"FeatureIDForOutOfBoundsSetIndex",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
0,
|
|
2),
|
|
-1);
|
|
});
|
|
|
|
Describe("FeatureIDAttribute", [this]() {
|
|
It("returns -1 for out-of-bounds face index", [this]() {
|
|
std::vector<uint8_t> attributeIDs{1, 1, 1};
|
|
AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 1, 0);
|
|
|
|
const std::vector<uint8_t> indices{0, 1, 2};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 3;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
TestEqual(
|
|
"FeatureIDForNegativeFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
-1),
|
|
-1);
|
|
TestEqual(
|
|
"FeatureIDForOutOfBoundsFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
2),
|
|
-1);
|
|
});
|
|
|
|
It("returns correct values for primitive without indices", [this]() {
|
|
std::vector<uint8_t> attributeIDs{1, 1, 1, 2, 2, 2, 0, 0, 0};
|
|
AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 3, 0);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 9;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
const size_t numFaces = static_cast<size_t>(accessor.count / 3);
|
|
for (size_t i = 0; i < numFaces; i++) {
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
static_cast<int64>(i)),
|
|
attributeIDs[i * 3]);
|
|
}
|
|
});
|
|
|
|
It("returns correct values for primitive with indices", [this]() {
|
|
std::vector<uint8_t> attributeIDs{1, 1, 1, 1, 0, 0, 0};
|
|
AddFeatureIDsAsAttributeToModel(model, *pPrimitive, attributeIDs, 2, 0);
|
|
|
|
const std::vector<uint8_t> indices{0, 1, 2, 0, 2, 3, 4, 5, 6};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 7;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
const size_t numFaces = indices.size() / 3;
|
|
for (size_t i = 0; i < numFaces; i++) {
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
static_cast<int64>(i)),
|
|
attributeIDs[i * 3]);
|
|
}
|
|
});
|
|
});
|
|
|
|
Describe("FeatureIDTexture", [this]() {
|
|
It("returns -1 for out-of-bounds face index", [this]() {
|
|
const std::vector<uint8_t> textureIDs{0};
|
|
const std::vector<glm::vec2> texCoords{
|
|
glm::vec2(0, 0),
|
|
glm::vec2(0, 0),
|
|
glm::vec2(0, 0)};
|
|
AddFeatureIDsAsTextureToModel(
|
|
model,
|
|
*pPrimitive,
|
|
textureIDs,
|
|
4,
|
|
4,
|
|
1,
|
|
texCoords,
|
|
0);
|
|
|
|
const std::vector<uint8_t> indices{0, 1, 2};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 3;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
TestEqual(
|
|
"FeatureIDForNegativeFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
-1),
|
|
-1);
|
|
TestEqual(
|
|
"FeatureIDForOutOfBoundsFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
2),
|
|
-1);
|
|
});
|
|
|
|
It("returns correct values for primitive without indices", [this]() {
|
|
const std::vector<uint8_t> textureIDs{0, 1, 2, 3};
|
|
const std::vector<glm::vec2> texCoords{
|
|
glm::vec2(0, 0),
|
|
glm::vec2(0, 0),
|
|
glm::vec2(0, 0),
|
|
glm::vec2(0.75, 0),
|
|
glm::vec2(0.75, 0),
|
|
glm::vec2(0.75, 0)};
|
|
AddFeatureIDsAsTextureToModel(
|
|
model,
|
|
*pPrimitive,
|
|
textureIDs,
|
|
4,
|
|
4,
|
|
1,
|
|
texCoords,
|
|
0);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 6;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
0),
|
|
0);
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
1),
|
|
3);
|
|
});
|
|
|
|
It("returns correct values for primitive with indices", [this]() {
|
|
const std::vector<uint8_t> textureIDs{0, 1, 2, 3};
|
|
const std::vector<glm::vec2> texCoords{
|
|
glm::vec2(0, 0),
|
|
glm::vec2(0.25, 0),
|
|
glm::vec2(0.5, 0),
|
|
glm::vec2(0.75, 0)};
|
|
AddFeatureIDsAsTextureToModel(
|
|
model,
|
|
*pPrimitive,
|
|
textureIDs,
|
|
4,
|
|
4,
|
|
1,
|
|
texCoords,
|
|
0);
|
|
|
|
const std::vector<uint8_t> indices{0, 1, 2, 2, 0, 3};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 4;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
0),
|
|
0);
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
1),
|
|
2);
|
|
});
|
|
});
|
|
|
|
Describe("ImplicitFeatureIDs", [this]() {
|
|
BeforeEach([this]() {
|
|
CesiumGltf::FeatureId& implicitIDs =
|
|
pExtension->featureIds.emplace_back();
|
|
implicitIDs.featureCount = 6;
|
|
});
|
|
|
|
It("returns -1 for out-of-bounds face index", [this]() {
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 6;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
TestEqual(
|
|
"FeatureIDForNegativeFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
-1),
|
|
-1);
|
|
TestEqual(
|
|
"FeatureIDForOutOfBoundsFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
10),
|
|
-1);
|
|
});
|
|
|
|
It("returns correct values for primitive without indices", [this]() {
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 6;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
0),
|
|
0);
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
1),
|
|
3);
|
|
});
|
|
|
|
It("returns correct values for primitive with indices", [this]() {
|
|
const std::vector<uint8_t> indices{2, 1, 0, 3, 4, 5};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 4;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
0),
|
|
2);
|
|
TestEqual(
|
|
"FeatureIDForFace",
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
1),
|
|
3);
|
|
});
|
|
});
|
|
|
|
It("gets feature ID from correct set with specified feature ID set index",
|
|
[this]() {
|
|
// First feature ID set is attribute
|
|
std::vector<uint8_t> attributeIDs{1, 1, 1, 1, 0, 0, 0};
|
|
AddFeatureIDsAsAttributeToModel(
|
|
model,
|
|
*pPrimitive,
|
|
attributeIDs,
|
|
2,
|
|
0);
|
|
|
|
const std::vector<uint8_t> indices{0, 1, 2, 0, 2, 3, 4, 5, 6};
|
|
CreateIndicesForPrimitive(
|
|
model,
|
|
*pPrimitive,
|
|
CesiumGltf::AccessorSpec::ComponentType::UNSIGNED_BYTE,
|
|
indices);
|
|
|
|
CesiumGltf::Accessor& accessor = model.accessors.emplace_back();
|
|
accessor.count = 7;
|
|
pPrimitive->attributes.insert(
|
|
{"POSITION", static_cast<int32_t>(model.accessors.size() - 1)});
|
|
|
|
// Second feature ID set is implicit
|
|
CesiumGltf::FeatureId& implicitIDs =
|
|
pExtension->featureIds.emplace_back();
|
|
implicitIDs.featureCount = 7;
|
|
|
|
FCesiumPrimitiveFeatures primitiveFeatures =
|
|
FCesiumPrimitiveFeatures(model, *pPrimitive, *pExtension);
|
|
|
|
const TArray<FCesiumFeatureIdSet>& featureIDSets =
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDSets(
|
|
primitiveFeatures);
|
|
TestEqual("FeatureIDSetCount", featureIDSets.Num(), 2);
|
|
|
|
int64 setIndex = 0;
|
|
for (size_t index = 0; index < indices.size(); index += 3) {
|
|
std::string label("FeatureIDAttribute" + std::to_string(index));
|
|
int64 faceIndex = static_cast<int64>(index) / 3;
|
|
int64 featureID = static_cast<int64>(attributeIDs[indices[index]]);
|
|
TestEqual(
|
|
FString(label.c_str()),
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
faceIndex,
|
|
setIndex),
|
|
featureID);
|
|
}
|
|
|
|
setIndex = 1;
|
|
for (size_t index = 0; index < indices.size(); index += 3) {
|
|
std::string label("ImplicitFeatureID" + std::to_string(index));
|
|
int64 faceIndex = static_cast<int64>(index) / 3;
|
|
int64 featureID = static_cast<int64>(indices[index]);
|
|
TestEqual(
|
|
FString(label.c_str()),
|
|
UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromFace(
|
|
primitiveFeatures,
|
|
faceIndex,
|
|
setIndex),
|
|
featureID);
|
|
}
|
|
});
|
|
});
|
|
}
|