Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Source/CesiumRuntime/Private/CesiumGltfComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ static void loadPrimitiveFeaturesMetadata(
pFeatures ? FCesiumPrimitiveFeatures(model, primitive, *pFeatures)
: FCesiumPrimitiveFeatures();
primitiveResult.Metadata =
pMetadata ? FCesiumPrimitiveMetadata(primitive, *pMetadata)
pMetadata ? FCesiumPrimitiveMetadata(model, primitive, *pMetadata)
: FCesiumPrimitiveMetadata();

PRAGMA_DISABLE_DEPRECATION_WARNINGS
Expand Down
50 changes: 40 additions & 10 deletions Source/CesiumRuntime/Private/CesiumPrimitiveMetadata.cpp
Original file line number Diff line number Diff line change
@@ -1,26 +1,50 @@
// Copyright 2020-2024 CesiumGS, Inc. and Contributors

#include "CesiumPrimitiveMetadata.h"
#include "CesiumGltf/AccessorView.h"
#include "CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h"
#include "CesiumGltf/Model.h"
#include "CesiumGltfPrimitiveComponent.h"
#include "CesiumPropertyAttribute.h"

#include <CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h>
#include <CesiumGltf/ExtensionModelExtStructuralMetadata.h>
#include <CesiumGltf/Model.h>

static FCesiumPrimitiveMetadata EmptyPrimitiveMetadata;

FCesiumPrimitiveMetadata::FCesiumPrimitiveMetadata(
const CesiumGltf::MeshPrimitive& Primitive,
const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& Metadata)
: _propertyTextureIndices(), _propertyAttributeIndices() {
this->_propertyTextureIndices.Reserve(Metadata.propertyTextures.size());
for (const int64 propertyTextureIndex : Metadata.propertyTextures) {
const CesiumGltf::Model& model,
const CesiumGltf::MeshPrimitive& primitive,
const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& metadata)
: _propertyTextureIndices(),
_propertyAttributes(),
_propertyAttributeIndices() {
this->_propertyTextureIndices.Reserve(metadata.propertyTextures.size());
for (const int64 propertyTextureIndex : metadata.propertyTextures) {
this->_propertyTextureIndices.Emplace(propertyTextureIndex);
}

this->_propertyAttributeIndices.Reserve(Metadata.propertyAttributes.size());
for (const int64 propertyAttributeIndex : Metadata.propertyAttributes) {
this->_propertyAttributeIndices.Reserve(metadata.propertyAttributes.size());
for (const int64 propertyAttributeIndex : metadata.propertyAttributes) {
this->_propertyAttributeIndices.Emplace(propertyAttributeIndex);
}

const auto* pModelMetadata =
model.getExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
if (metadata.propertyAttributes.empty() && pModelMetadata) {
return;
}

for (const int64 propertyAttributeIndex : metadata.propertyAttributes) {
if (propertyAttributeIndex < 0 ||
propertyAttributeIndex >=
int64_t(pModelMetadata->propertyAttributes.size())) {
continue;
}

this->_propertyAttributes.Emplace(FCesiumPropertyAttribute(
model,
primitive,
pModelMetadata->propertyAttributes[propertyAttributeIndex]));
}
}

const FCesiumPrimitiveMetadata&
Expand All @@ -41,6 +65,12 @@ UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyTextureIndices(
return PrimitiveMetadata._propertyTextureIndices;
}

const TArray<FCesiumPropertyAttribute>&
UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyAttributes(
UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata) {
return PrimitiveMetadata._propertyAttributes;
}

const TArray<int64>&
UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyAttributeIndices(
UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata) {
Expand Down
127 changes: 127 additions & 0 deletions Source/CesiumRuntime/Private/CesiumPropertyAttribute.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright 2020-2024 CesiumGS, Inc. and Contributors

#include "CesiumPropertyAttribute.h"
#include <CesiumGltf/PropertyAttributeView.h>

static FCesiumPropertyAttributeProperty EmptyPropertyAttributeProperty;

FCesiumPropertyAttribute::FCesiumPropertyAttribute(
const CesiumGltf::Model& model,
const CesiumGltf::MeshPrimitive& primitive,
const CesiumGltf::PropertyAttribute& propertyAttribute,
const TSharedPtr<FCesiumMetadataEnumCollection>& pEnumCollection)
: _status(
ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttributeClass),
_name(propertyAttribute.name.value_or("").c_str()),
_className(propertyAttribute.classProperty.c_str()),
_properties() {
CesiumGltf::PropertyAttributeView propertyAttributeView{
model,
propertyAttribute};
switch (propertyAttributeView.status()) {
case CesiumGltf::PropertyAttributeViewStatus::Valid:
_status = ECesiumPropertyAttributeStatus::Valid;
break;
default:
// Status was already set in initializer list.
return;
}

const CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension =
model.getExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
// If there was no schema, we would've gotten ErrorMissingSchema for the
// propertyAttributeView status.
check(pExtension != nullptr && pExtension->schema != nullptr);

propertyAttributeView.forEachProperty(
primitive,
[&properties = _properties,
&Schema = *pExtension->schema,
&propertyAttributeView,
&pEnumCollection](
const std::string& propertyName,
auto propertyValue) mutable {
FString key(UTF8_TO_TCHAR(propertyName.data()));
const CesiumGltf::ClassProperty* pClassProperty =
propertyAttributeView.getClassProperty(propertyName);
check(pClassProperty);

TSharedPtr<FCesiumMetadataEnum> pEnumDefinition(nullptr);
if (pEnumCollection.IsValid() && pClassProperty->enumType.has_value()) {
pEnumDefinition = pEnumCollection->Get(
FString(UTF8_TO_TCHAR(pClassProperty->enumType.value().c_str())));
}

properties.Add(
key,
FCesiumPropertyAttributeProperty(propertyValue, pEnumDefinition));
});
}

/*static*/ ECesiumPropertyAttributeStatus
UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus(
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) {
return PropertyAttribute._status;
}

/*static*/ const FString&
UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeName(
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) {
return PropertyAttribute._name;
}

/*static*/ const TMap<FString, FCesiumPropertyAttributeProperty>&
UCesiumPropertyAttributeBlueprintLibrary::GetProperties(
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) {
return PropertyAttribute._properties;
}

/*static*/ const TArray<FString>
UCesiumPropertyAttributeBlueprintLibrary::GetPropertyNames(
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) {
TArray<FString> names;
PropertyAttribute._properties.GenerateKeyArray(names);
return names;
}

/*static*/ const FCesiumPropertyAttributeProperty&
UCesiumPropertyAttributeBlueprintLibrary::FindProperty(
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute,
const FString& PropertyName) {
const FCesiumPropertyAttributeProperty* property =
PropertyAttribute._properties.Find(PropertyName);
return property ? *property : EmptyPropertyAttributeProperty;
}

/*static*/ TMap<FString, FCesiumMetadataValue>
UCesiumPropertyAttributeBlueprintLibrary::GetMetadataValuesAtIndex(
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute,
int64 Index) {
TMap<FString, FCesiumMetadataValue> values;
if (Index < 0) {
return values;
}

for (const auto& pair : PropertyAttribute._properties) {
const FCesiumPropertyAttributeProperty& property = pair.Value;
ECesiumPropertyAttributePropertyStatus status =
UCesiumPropertyAttributePropertyBlueprintLibrary::
GetPropertyAttributePropertyStatus(property);
if (status == ECesiumPropertyAttributePropertyStatus::Valid) {
values.Add(
pair.Key,
UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue(
pair.Value,
Index));
} else if (
status ==
ECesiumPropertyAttributePropertyStatus::EmptyPropertyWithDefault) {
values.Add(
pair.Key,
UCesiumPropertyAttributePropertyBlueprintLibrary::GetDefaultValue(
pair.Value));
}
}

return values;
}
Loading
Loading