Skip to content

Commit cb62131

Browse files
authored
Merge pull request #1694 from CesiumGS/property-attributes
Store property attributes in `FCesiumPrimitiveMetadata`
2 parents 8113044 + 02d7eed commit cb62131

23 files changed

+6831
-464
lines changed

CHANGES.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
### ? - ?
44

5+
##### Breaking Changes :mega:
6+
7+
- `FCesiumPrimitiveMetadata::GetPropertyAttributeIndices` is now deprecated. Use `GetPropertyAttributes` to directly get the `FCesiumPropertyAttribute`s instead.
8+
9+
##### Additions :tada:
10+
11+
- Added `FCesiumPropertyAttributeProperty` to represent glTF property attribute properties and `UCesiumPropertyAttributePropertyBlueprintLibrary` to retrieve their values.
12+
- Added `FCesiumPropertyAttribute` to represent glTF property attributes and `UCesiumPropertyAttributeBlueprintLibrary` to act upon them with Blueprints.
13+
- Added `UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyAttributes` to retrieve the property attributes from a `FCesiumPrimitiveMetadata`.
14+
- Added `UCesiumPropertyTexturePropertyBlueprintLibrary::GetInteger64`. Although 64-bit integers aren't directly supported by property textures, this enables the lossless retrieval of 32-bit unsigned integers.
15+
516
##### Fixes :wrench:
617

718
- Fixed error messages in the Unreal log about uninitialized fields in `FCesiumGeocoderServiceAttribution` and `FCesiumGeocoderServiceFeature`.

Source/CesiumRuntime/Private/CesiumGltfComponent.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,7 @@ static void loadPrimitiveFeaturesMetadata(
10931093
pFeatures ? FCesiumPrimitiveFeatures(model, primitive, *pFeatures)
10941094
: FCesiumPrimitiveFeatures();
10951095
primitiveResult.Metadata =
1096-
pMetadata ? FCesiumPrimitiveMetadata(primitive, *pMetadata)
1096+
pMetadata ? FCesiumPrimitiveMetadata(model, primitive, *pMetadata)
10971097
: FCesiumPrimitiveMetadata();
10981098

10991099
PRAGMA_DISABLE_DEPRECATION_WARNINGS

Source/CesiumRuntime/Private/CesiumPrimitiveMetadata.cpp

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,51 @@
11
// Copyright 2020-2024 CesiumGS, Inc. and Contributors
22

33
#include "CesiumPrimitiveMetadata.h"
4-
#include "CesiumGltf/AccessorView.h"
5-
#include "CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h"
6-
#include "CesiumGltf/Model.h"
74
#include "CesiumGltfPrimitiveComponent.h"
5+
#include "CesiumPropertyAttribute.h"
6+
7+
#include <CesiumGltf/ExtensionMeshPrimitiveExtStructuralMetadata.h>
8+
#include <CesiumGltf/ExtensionModelExtStructuralMetadata.h>
9+
#include <CesiumGltf/Model.h>
810

911
static FCesiumPrimitiveMetadata EmptyPrimitiveMetadata;
1012

1113
FCesiumPrimitiveMetadata::FCesiumPrimitiveMetadata(
12-
const CesiumGltf::MeshPrimitive& Primitive,
13-
const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& Metadata)
14-
: _propertyTextureIndices(), _propertyAttributeIndices() {
15-
this->_propertyTextureIndices.Reserve(Metadata.propertyTextures.size());
16-
for (const int64 propertyTextureIndex : Metadata.propertyTextures) {
14+
const CesiumGltf::Model& model,
15+
const CesiumGltf::MeshPrimitive& primitive,
16+
const CesiumGltf::ExtensionMeshPrimitiveExtStructuralMetadata& metadata)
17+
: _propertyTextureIndices(),
18+
_propertyAttributes(),
19+
_propertyAttributeIndices() {
20+
this->_propertyTextureIndices.Reserve(metadata.propertyTextures.size());
21+
for (const int64 propertyTextureIndex : metadata.propertyTextures) {
1722
this->_propertyTextureIndices.Emplace(propertyTextureIndex);
1823
}
1924

20-
this->_propertyAttributeIndices.Reserve(Metadata.propertyAttributes.size());
21-
for (const int64 propertyAttributeIndex : Metadata.propertyAttributes) {
25+
// For backwards compatibility with GetPropertyAttributeIndices().
26+
this->_propertyAttributeIndices.Reserve(metadata.propertyAttributes.size());
27+
for (const int64 propertyAttributeIndex : metadata.propertyAttributes) {
2228
this->_propertyAttributeIndices.Emplace(propertyAttributeIndex);
2329
}
30+
31+
const auto* pModelMetadata =
32+
model.getExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
33+
if (!pModelMetadata) {
34+
return;
35+
}
36+
37+
for (const int64 propertyAttributeIndex : metadata.propertyAttributes) {
38+
if (propertyAttributeIndex < 0 ||
39+
propertyAttributeIndex >=
40+
int64_t(pModelMetadata->propertyAttributes.size())) {
41+
continue;
42+
}
43+
44+
this->_propertyAttributes.Emplace(FCesiumPropertyAttribute(
45+
model,
46+
primitive,
47+
pModelMetadata->propertyAttributes[propertyAttributeIndex]));
48+
}
2449
}
2550

2651
const FCesiumPrimitiveMetadata&
@@ -41,6 +66,12 @@ UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyTextureIndices(
4166
return PrimitiveMetadata._propertyTextureIndices;
4267
}
4368

69+
const TArray<FCesiumPropertyAttribute>&
70+
UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyAttributes(
71+
UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata) {
72+
return PrimitiveMetadata._propertyAttributes;
73+
}
74+
4475
const TArray<int64>&
4576
UCesiumPrimitiveMetadataBlueprintLibrary::GetPropertyAttributeIndices(
4677
UPARAM(ref) const FCesiumPrimitiveMetadata& PrimitiveMetadata) {
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// Copyright 2020-2024 CesiumGS, Inc. and Contributors
2+
3+
#include "CesiumPropertyAttribute.h"
4+
#include <CesiumGltf/PropertyAttributeView.h>
5+
6+
static FCesiumPropertyAttributeProperty EmptyPropertyAttributeProperty;
7+
8+
FCesiumPropertyAttribute::FCesiumPropertyAttribute(
9+
const CesiumGltf::Model& model,
10+
const CesiumGltf::MeshPrimitive& primitive,
11+
const CesiumGltf::PropertyAttribute& propertyAttribute,
12+
const TSharedPtr<FCesiumMetadataEnumCollection>& pEnumCollection)
13+
: _status(
14+
ECesiumPropertyAttributeStatus::ErrorInvalidPropertyAttributeClass),
15+
_name(propertyAttribute.name.value_or("").c_str()),
16+
_className(propertyAttribute.classProperty.c_str()),
17+
_elementCount(0),
18+
_properties() {
19+
CesiumGltf::PropertyAttributeView propertyAttributeView{
20+
model,
21+
propertyAttribute};
22+
switch (propertyAttributeView.status()) {
23+
case CesiumGltf::PropertyAttributeViewStatus::Valid:
24+
_status = ECesiumPropertyAttributeStatus::Valid;
25+
break;
26+
default:
27+
// Status was already set in initializer list.
28+
return;
29+
}
30+
31+
const CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension =
32+
model.getExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
33+
// If there was no schema, we would've gotten ErrorMissingSchema for the
34+
// propertyAttributeView status.
35+
check(pExtension != nullptr && pExtension->schema != nullptr);
36+
37+
propertyAttributeView.forEachProperty(
38+
primitive,
39+
[&properties = _properties,
40+
&elementCount = _elementCount,
41+
&Schema = *pExtension->schema,
42+
&propertyAttributeView,
43+
&pEnumCollection](
44+
const std::string& propertyName,
45+
auto propertyValue) mutable {
46+
FString key(UTF8_TO_TCHAR(propertyName.data()));
47+
const CesiumGltf::ClassProperty* pClassProperty =
48+
propertyAttributeView.getClassProperty(propertyName);
49+
check(pClassProperty);
50+
51+
TSharedPtr<FCesiumMetadataEnum> pEnumDefinition(nullptr);
52+
if (pEnumCollection.IsValid() && pClassProperty->enumType.has_value()) {
53+
pEnumDefinition = pEnumCollection->Get(
54+
FString(UTF8_TO_TCHAR(pClassProperty->enumType.value().c_str())));
55+
}
56+
57+
if (elementCount == 0) {
58+
// Use the first non-zero property size to compare against all the
59+
// others.
60+
elementCount = propertyValue.size();
61+
}
62+
63+
if (propertyValue.size() > 0 && elementCount != propertyValue.size()) {
64+
UE_LOG(
65+
LogCesium,
66+
Error,
67+
TEXT(
68+
"The size of one or more property attribute properties does not match the others."));
69+
}
70+
71+
properties.Add(
72+
key,
73+
FCesiumPropertyAttributeProperty(propertyValue, pEnumDefinition));
74+
});
75+
}
76+
77+
/*static*/ ECesiumPropertyAttributeStatus
78+
UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeStatus(
79+
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) {
80+
return PropertyAttribute._status;
81+
}
82+
83+
/*static*/ const FString&
84+
UCesiumPropertyAttributeBlueprintLibrary::GetPropertyAttributeName(
85+
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) {
86+
return PropertyAttribute._name;
87+
}
88+
89+
/*static*/ const TMap<FString, FCesiumPropertyAttributeProperty>&
90+
UCesiumPropertyAttributeBlueprintLibrary::GetProperties(
91+
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) {
92+
return PropertyAttribute._properties;
93+
}
94+
95+
/*static*/ const TArray<FString>
96+
UCesiumPropertyAttributeBlueprintLibrary::GetPropertyNames(
97+
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute) {
98+
TArray<FString> names;
99+
PropertyAttribute._properties.GenerateKeyArray(names);
100+
return names;
101+
}
102+
103+
/*static*/ const FCesiumPropertyAttributeProperty&
104+
UCesiumPropertyAttributeBlueprintLibrary::FindProperty(
105+
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute,
106+
const FString& PropertyName) {
107+
const FCesiumPropertyAttributeProperty* property =
108+
PropertyAttribute._properties.Find(PropertyName);
109+
return property ? *property : EmptyPropertyAttributeProperty;
110+
}
111+
112+
/*static*/ TMap<FString, FCesiumMetadataValue>
113+
UCesiumPropertyAttributeBlueprintLibrary::GetMetadataValuesAtIndex(
114+
UPARAM(ref) const FCesiumPropertyAttribute& PropertyAttribute,
115+
int64 Index) {
116+
TMap<FString, FCesiumMetadataValue> values;
117+
if (Index < 0 || Index >= PropertyAttribute._elementCount) {
118+
return values;
119+
}
120+
121+
for (const auto& pair : PropertyAttribute._properties) {
122+
const FCesiumPropertyAttributeProperty& property = pair.Value;
123+
ECesiumPropertyAttributePropertyStatus status =
124+
UCesiumPropertyAttributePropertyBlueprintLibrary::
125+
GetPropertyAttributePropertyStatus(property);
126+
if (status == ECesiumPropertyAttributePropertyStatus::Valid) {
127+
values.Add(
128+
pair.Key,
129+
UCesiumPropertyAttributePropertyBlueprintLibrary::GetValue(
130+
pair.Value,
131+
Index));
132+
} else if (
133+
status ==
134+
ECesiumPropertyAttributePropertyStatus::EmptyPropertyWithDefault) {
135+
values.Add(
136+
pair.Key,
137+
UCesiumPropertyAttributePropertyBlueprintLibrary::GetDefaultValue(
138+
pair.Value));
139+
}
140+
}
141+
142+
return values;
143+
}

0 commit comments

Comments
 (0)