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

255 lines
8.7 KiB
C++

// Copyright 2020-2024 CesiumGS, Inc. and Contributors
#include "CesiumFeatureIdSet.h"
#include "CesiumGltf/Accessor.h"
#include "CesiumGltf/ExtensionExtInstanceFeaturesFeatureId.h"
#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h"
#include "CesiumGltf/FeatureId.h"
#include "CesiumGltf/Model.h"
#include "CesiumGltfPrimitiveComponent.h"
static FCesiumFeatureIdAttribute EmptyFeatureIDAttribute;
static FCesiumFeatureIdTexture EmptyFeatureIDTexture;
FCesiumFeatureIdSet::FCesiumFeatureIdSet(
const CesiumGltf::Model& InModel,
const CesiumGltf::MeshPrimitive& Primitive,
const CesiumGltf::FeatureId& FeatureID)
: _featureID(),
_featureIDSetType(ECesiumFeatureIdSetType::None),
_featureCount(FeatureID.featureCount),
_nullFeatureID(FeatureID.nullFeatureId.value_or(-1)),
_propertyTableIndex(FeatureID.propertyTable),
_label(FString(FeatureID.label.value_or("").c_str())) {
FString propertyTableName;
// For backwards compatibility with GetFeatureTableName.
const CesiumGltf::ExtensionModelExtStructuralMetadata* pMetadata =
InModel.getExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
if (pMetadata && _propertyTableIndex >= 0) {
size_t index = static_cast<size_t>(_propertyTableIndex);
if (index < pMetadata->propertyTables.size()) {
const CesiumGltf::PropertyTable& propertyTable =
pMetadata->propertyTables[index];
std::string name = propertyTable.name.value_or("");
propertyTableName = FString(name.c_str());
}
}
if (FeatureID.attribute) {
_featureID = FCesiumFeatureIdAttribute(
InModel,
Primitive,
*FeatureID.attribute,
propertyTableName);
_featureIDSetType = ECesiumFeatureIdSetType::Attribute;
return;
}
if (FeatureID.texture) {
_featureID = FCesiumFeatureIdTexture(
InModel,
Primitive,
*FeatureID.texture,
propertyTableName);
_featureIDSetType = ECesiumFeatureIdSetType::Texture;
return;
}
if (_featureCount > 0) {
_featureIDSetType = ECesiumFeatureIdSetType::Implicit;
}
}
FCesiumFeatureIdSet::FCesiumFeatureIdSet(
const CesiumGltf::Model& InModel,
const CesiumGltf::Node& Node,
const CesiumGltf::ExtensionExtInstanceFeaturesFeatureId& InstanceFeatureID)
: _featureID(),
_featureIDSetType(ECesiumFeatureIdSetType::Instance),
_featureCount(InstanceFeatureID.featureCount),
_nullFeatureID(InstanceFeatureID.nullFeatureId.value_or(-1)),
_propertyTableIndex(InstanceFeatureID.propertyTable.value_or(-1)),
_label(FString(InstanceFeatureID.label.value_or("").c_str())) {
FString propertyTableName;
// For backwards compatibility with GetFeatureTableName.
const CesiumGltf::ExtensionModelExtStructuralMetadata* pMetadata =
InModel.getExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
if (pMetadata && this->_propertyTableIndex >= 0) {
size_t index = static_cast<size_t>(_propertyTableIndex);
if (index < pMetadata->propertyTables.size()) {
const CesiumGltf::PropertyTable& propertyTable =
pMetadata->propertyTables[index];
std::string name = propertyTable.name.value_or("");
propertyTableName = FString(name.c_str());
}
}
if (InstanceFeatureID.attribute) {
_featureID = FCesiumFeatureIdAttribute(
InModel,
Node,
*InstanceFeatureID.attribute,
propertyTableName);
} else if (_featureCount > 0) {
_featureIDSetType = ECesiumFeatureIdSetType::InstanceImplicit;
}
}
const ECesiumFeatureIdSetType
UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDSetType(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) {
return FeatureIDSet._featureIDSetType;
}
const FCesiumFeatureIdAttribute&
UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDAttribute(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) {
if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Attribute ||
FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Instance) {
return std::get<FCesiumFeatureIdAttribute>(FeatureIDSet._featureID);
}
return EmptyFeatureIDAttribute;
}
const FCesiumFeatureIdTexture&
UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) {
if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Texture) {
return std::get<FCesiumFeatureIdTexture>(FeatureIDSet._featureID);
}
return EmptyFeatureIDTexture;
}
const int64 UCesiumFeatureIdSetBlueprintLibrary::GetPropertyTableIndex(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) {
return FeatureIDSet._propertyTableIndex;
}
int64 UCesiumFeatureIdSetBlueprintLibrary::GetFeatureCount(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) {
return FeatureIDSet._featureCount;
}
const int64 UCesiumFeatureIdSetBlueprintLibrary::GetNullFeatureID(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) {
return FeatureIDSet._nullFeatureID;
}
const FString UCesiumFeatureIdSetBlueprintLibrary::GetLabel(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet) {
return FeatureIDSet._label;
}
int64 UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForVertex(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet,
int64 VertexIndex) {
if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Attribute) {
FCesiumFeatureIdAttribute attribute =
std::get<FCesiumFeatureIdAttribute>(FeatureIDSet._featureID);
return UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID(
attribute,
VertexIndex);
}
if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Texture) {
FCesiumFeatureIdTexture texture =
std::get<FCesiumFeatureIdTexture>(FeatureIDSet._featureID);
return UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDForVertex(
texture,
VertexIndex);
}
if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Implicit) {
return (VertexIndex >= 0 && VertexIndex < FeatureIDSet._featureCount)
? VertexIndex
: -1;
}
return -1;
}
int64 UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDForInstance(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet,
int64 InstanceIndex) {
ECesiumFeatureIdSetType type = FeatureIDSet._featureIDSetType;
if (type == ECesiumFeatureIdSetType::InstanceImplicit) {
return InstanceIndex;
} else if (
type != ECesiumFeatureIdSetType::Instance ||
!std::holds_alternative<FCesiumFeatureIdAttribute>(
FeatureIDSet._featureID) ||
InstanceIndex < 0) {
return -1;
}
const auto& featureIdAttribute =
std::get<FCesiumFeatureIdAttribute>(FeatureIDSet._featureID);
return UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID(
featureIdAttribute,
InstanceIndex);
}
int64 UCesiumFeatureIdSetBlueprintLibrary::GetFeatureIDFromHit(
UPARAM(ref) const FCesiumFeatureIdSet& FeatureIDSet,
const FHitResult& Hit) {
// FeatureIDs from instanced geometry take precedence.
const auto* pInstancedComponent =
Cast<UCesiumGltfInstancedComponent>(Hit.Component);
if (IsValid(pInstancedComponent)) {
const FCesiumPrimitiveFeatures& instanceFeatures =
*pInstancedComponent->pInstanceFeatures;
return UCesiumPrimitiveFeaturesBlueprintLibrary::GetFeatureIDFromInstance(
instanceFeatures,
Hit.Item);
}
if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Texture) {
FCesiumFeatureIdTexture texture =
std::get<FCesiumFeatureIdTexture>(FeatureIDSet._featureID);
return UCesiumFeatureIdTextureBlueprintLibrary::GetFeatureIDFromHit(
texture,
Hit);
}
// Find the first vertex of the face.
const UCesiumGltfPrimitiveComponent* pGltfComponent =
Cast<UCesiumGltfPrimitiveComponent>(Hit.Component);
if (!IsValid(pGltfComponent)) {
return -1;
}
const CesiumPrimitiveData& primData = pGltfComponent->getPrimitiveData();
if (!primData.pMeshPrimitive) {
return -1;
}
auto VertexIndices = std::visit(
CesiumGltf::IndicesForFaceFromAccessor{
Hit.FaceIndex,
primData.PositionAccessor.size(),
primData.pMeshPrimitive->mode},
primData.IndexAccessor);
int64 VertexIndex = VertexIndices[0];
if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Attribute) {
FCesiumFeatureIdAttribute attribute =
std::get<FCesiumFeatureIdAttribute>(FeatureIDSet._featureID);
return UCesiumFeatureIdAttributeBlueprintLibrary::GetFeatureID(
attribute,
VertexIndex);
}
if (FeatureIDSet._featureIDSetType == ECesiumFeatureIdSetType::Implicit) {
return (VertexIndex >= 0 && VertexIndex < FeatureIDSet._featureCount)
? VertexIndex
: -1;
}
return -1;
}