Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
##### Fixes :wrench:

- Fixed a bug that prevented `UCesiumPrimitiveFeaturesBlueprintLibrary::GetPrimitiveFeatures` from retrieving the features of instanced meshes.
- Removed `bHasKhrTextureTransform` from `FCesiumFeatureIdSetDescription` and `FCesiumPropertyTexturePropertyDescription`. This will not break any existing materials generated by `UCesiumFeaturesMetadataComponent`; instead, it will always generate additional nodes to handle the `KHR_texture_transform` extension if present.

### v2.21.0 Preview for Unreal Engine 5.7 - 2025-11-17

Expand Down
249 changes: 107 additions & 142 deletions Source/CesiumRuntime/Private/CesiumFeaturesMetadataComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,6 @@ void AutoFillPropertyTextureDescriptions(
propertyIt.Value);
property.PropertyDetails.bHasDefaultValue =
!UCesiumMetadataValueBlueprintLibrary::IsEmpty(defaultValue);

auto maybeTextureTransform = propertyIt.Value.getTextureTransform();
if (maybeTextureTransform) {
property.bHasKhrTextureTransform =
(maybeTextureTransform->status() ==
CesiumGltf::KhrTextureTransformStatus::Valid);
}
}
}
}
Expand Down Expand Up @@ -316,19 +309,6 @@ void AutoFillFeatureIdSetDescriptions(
PropertyTables[propertyTableIndex];
pDescription->PropertyTableName = getNameForPropertyTable(propertyTable);
}

if (type == ECesiumFeatureIdSetType::Texture) {
FCesiumFeatureIdTexture featureIdTexture =
UCesiumFeatureIdSetBlueprintLibrary::GetAsFeatureIDTexture(
featureIDSet);
auto maybeTextureTransform =
featureIdTexture.getFeatureIdTextureView().getTextureTransform();
if (maybeTextureTransform) {
pDescription->bHasKhrTextureTransform =
(maybeTextureTransform->status() ==
CesiumGltf::KhrTextureTransformStatus::Valid);
}
}
}
}

Expand Down Expand Up @@ -1210,33 +1190,28 @@ UMaterialExpressionMaterialFunctionCall* GenerateNodesForFeatureIdTexture(
Channels->MaterialExpressionEditorY = NodeY;
AutoGeneratedNodes.Add(Channels);

// KHR_texture_transform parameters
UMaterialExpressionVectorParameter* TransformScaleOffset = nullptr;
UMaterialExpressionVectorParameter* TransformRotation = nullptr;

if (Description.bHasKhrTextureTransform) {
TransformScaleOffset =
NewObject<UMaterialExpressionVectorParameter>(TargetMaterialLayer);
TransformScaleOffset->ParameterName =
FName(SafeName + MaterialTextureScaleOffsetSuffix);
TransformScaleOffset->DefaultValue = {1, 1, 0, 0};
TransformScaleOffset->MaterialExpressionEditorX = NodeX;
TransformScaleOffset->MaterialExpressionEditorY = NodeY + 1.25 * Incr;
AutoGeneratedNodes.Add(TransformScaleOffset);
// Parameters to handle KHR_texture_transform if present.
UMaterialExpressionVectorParameter* TransformScaleOffset =
NewObject<UMaterialExpressionVectorParameter>(TargetMaterialLayer);
TransformScaleOffset->ParameterName =
FName(SafeName + MaterialTextureScaleOffsetSuffix);
TransformScaleOffset->DefaultValue = {1, 1, 0, 0};
TransformScaleOffset->MaterialExpressionEditorX = NodeX;
TransformScaleOffset->MaterialExpressionEditorY = NodeY + 1.25 * Incr;
AutoGeneratedNodes.Add(TransformScaleOffset);

MaximumParameterSectionX = FMath::Max(
MaximumParameterSectionX,
Incr * GetNameLengthScalar(TransformScaleOffset->ParameterName));
MaximumParameterSectionX = FMath::Max(
MaximumParameterSectionX,
Incr * GetNameLengthScalar(TransformScaleOffset->ParameterName));

TransformRotation =
NewObject<UMaterialExpressionVectorParameter>(TargetMaterialLayer);
TransformRotation->ParameterName =
FName(SafeName + MaterialTextureRotationSuffix);
TransformRotation->DefaultValue = {0, 1, 0, 1};
TransformRotation->MaterialExpressionEditorX = NodeX;
TransformRotation->MaterialExpressionEditorY = NodeY + 2.5 * Incr;
AutoGeneratedNodes.Add(TransformRotation);
}
UMaterialExpressionVectorParameter* TransformRotation =
NewObject<UMaterialExpressionVectorParameter>(TargetMaterialLayer);
TransformRotation->ParameterName =
FName(SafeName + MaterialTextureRotationSuffix);
TransformRotation->DefaultValue = {0, 1, 0, 1};
TransformRotation->MaterialExpressionEditorX = NodeX;
TransformRotation->MaterialExpressionEditorY = NodeY + 2.5 * Incr;
AutoGeneratedNodes.Add(TransformRotation);

NodeX += MaximumParameterSectionX + Incr;

Expand All @@ -1251,16 +1226,14 @@ UMaterialExpressionMaterialFunctionCall* GenerateNodesForFeatureIdTexture(

UMaterialExpressionAppendVector* AppendScaleOffset = nullptr;

if (Description.bHasKhrTextureTransform) {
AppendScaleOffset =
NewObject<UMaterialExpressionAppendVector>(TargetMaterialLayer);
AppendScaleOffset->MaterialExpressionEditorX = NodeX;
AppendScaleOffset->MaterialExpressionEditorY =
TransformScaleOffset->MaterialExpressionEditorY;
AppendScaleOffset->A.Connect(0, TransformScaleOffset);
AppendScaleOffset->B.Connect(4, TransformScaleOffset);
AutoGeneratedNodes.Add(AppendScaleOffset);
}
AppendScaleOffset =
NewObject<UMaterialExpressionAppendVector>(TargetMaterialLayer);
AppendScaleOffset->MaterialExpressionEditorX = NodeX;
AppendScaleOffset->MaterialExpressionEditorY =
TransformScaleOffset->MaterialExpressionEditorY;
AppendScaleOffset->A.Connect(0, TransformScaleOffset);
AppendScaleOffset->B.Connect(4, TransformScaleOffset);
AutoGeneratedNodes.Add(AppendScaleOffset);

NodeY -= 1.75 * Incr;
NodeX += 1.25 * Incr;
Expand All @@ -1281,15 +1254,12 @@ UMaterialExpressionMaterialFunctionCall* GenerateNodesForFeatureIdTexture(
FeatureIdTexture;
GetFeatureIdsFromTexture->FunctionInputs[2].Input.Expression = NumChannels;
GetFeatureIdsFromTexture->FunctionInputs[3].Input.Expression = AppendChannels;

if (Description.bHasKhrTextureTransform) {
GetFeatureIdsFromTexture->FunctionInputs[4].Input.Connect(
0,
AppendScaleOffset);
GetFeatureIdsFromTexture->FunctionInputs[5].Input.Connect(
0,
TransformRotation);
}
GetFeatureIdsFromTexture->FunctionInputs[4].Input.Connect(
0,
AppendScaleOffset);
GetFeatureIdsFromTexture->FunctionInputs[5].Input.Connect(
0,
TransformRotation);

AutoGeneratedNodes.Add(GetFeatureIdsFromTexture);

Expand Down Expand Up @@ -2044,84 +2014,79 @@ void GenerateNodesForPropertyTexture(
MaximumPropertyDataSectionX = NodeX + 2 * Incr;
NodeX = BeginSectionX;

if (Property.bHasKhrTextureTransform) {
PropertyDataSectionY += 1.25 * Incr;

UMaterialExpressionVectorParameter* TransformRotation =
NewObject<UMaterialExpressionVectorParameter>(TargetMaterialLayer);
TransformRotation->ParameterName =
FName(FullPropertyName + MaterialTextureRotationSuffix);
TransformRotation->DefaultValue = {0, 1, 0, 1};
TransformRotation->MaterialExpressionEditorX = NodeX;
TransformRotation->MaterialExpressionEditorY = PropertyDataSectionY;
AutoGeneratedNodes.Add(TransformRotation);

UMaterialExpressionVectorParameter* TransformScaleOffset =
NewObject<UMaterialExpressionVectorParameter>(TargetMaterialLayer);
TransformScaleOffset->ParameterName =
FName(FullPropertyName + MaterialTextureScaleOffsetSuffix);
TransformScaleOffset->DefaultValue = {1, 1, 0, 0};
TransformScaleOffset->MaterialExpressionEditorX = NodeX;
TransformScaleOffset->MaterialExpressionEditorY =
PropertyDataSectionY + Incr;
AutoGeneratedNodes.Add(TransformScaleOffset);

UMaterialExpressionAppendVector* AppendScale =
NewObject<UMaterialExpressionAppendVector>(TargetMaterialLayer);
AppendScale->MaterialExpressionEditorX =
NodeX + Incr * (0.5 + GetNameLengthScalar(
TransformScaleOffset->ParameterName));
AppendScale->MaterialExpressionEditorY =
TransformRotation->MaterialExpressionEditorY;
AppendScale->A.Connect(1, TransformScaleOffset);
AppendScale->B.Connect(2, TransformScaleOffset);
AutoGeneratedNodes.Add(AppendScale);

UMaterialExpressionAppendVector* AppendOffset =
NewObject<UMaterialExpressionAppendVector>(TargetMaterialLayer);
AppendOffset->MaterialExpressionEditorX =
AppendScale->MaterialExpressionEditorX;
AppendOffset->MaterialExpressionEditorY =
TransformScaleOffset->MaterialExpressionEditorY;
AppendOffset->A.Connect(3, TransformScaleOffset);
AppendOffset->B.Connect(4, TransformScaleOffset);
AutoGeneratedNodes.Add(AppendOffset);

MaximumPropertyDataSectionX = FMath::Max(
MaximumPropertyDataSectionX,
AppendOffset->MaterialExpressionEditorX + Incr - NodeX);
PropertyDataSectionY += 1.25 * Incr;

UMaterialExpressionMaterialFunctionCall* TransformTexCoords =
NewObject<UMaterialExpressionMaterialFunctionCall>(
TargetMaterialLayer);
TransformTexCoords->MaterialFunction =
FunctionLibrary.TransformTexCoords;
TransformTexCoords->MaterialExpressionEditorX =
SelectTexCoords->MaterialExpressionEditorX + Incr * 1.5;
TransformTexCoords->MaterialExpressionEditorY =
SelectTexCoords->MaterialExpressionEditorY;

FunctionLibrary.TransformTexCoords->GetInputsAndOutputs(
TransformTexCoords->FunctionInputs,
TransformTexCoords->FunctionOutputs);
// For some reason, Connect() doesn't work with this input...
TransformTexCoords->FunctionInputs[0].Input.Expression =
SelectTexCoords;
TransformTexCoords->FunctionInputs[0].Input.OutputIndex = 0;
TransformTexCoords->FunctionInputs[1].Input.Connect(
0,
TransformRotation);
TransformTexCoords->FunctionInputs[2].Input.Connect(0, AppendScale);
TransformTexCoords->FunctionInputs[3].Input.Connect(0, AppendOffset);
AutoGeneratedNodes.Add(TransformTexCoords);

TexCoordsInputFunction = TransformTexCoords;

MaximumPropertyDataSectionX = FMath::Max(
MaximumPropertyDataSectionX,
TransformTexCoords->MaterialExpressionEditorX + Incr * 1.5);
}
PropertyDataSectionY += 1.25 * Incr;

// Parameters to handle KHR_texture_transform, if present.
UMaterialExpressionVectorParameter* TransformRotation =
NewObject<UMaterialExpressionVectorParameter>(TargetMaterialLayer);
TransformRotation->ParameterName =
FName(FullPropertyName + MaterialTextureRotationSuffix);
TransformRotation->DefaultValue = {0, 1, 0, 1};
TransformRotation->MaterialExpressionEditorX = NodeX;
TransformRotation->MaterialExpressionEditorY = PropertyDataSectionY;
AutoGeneratedNodes.Add(TransformRotation);

UMaterialExpressionVectorParameter* TransformScaleOffset =
NewObject<UMaterialExpressionVectorParameter>(TargetMaterialLayer);
TransformScaleOffset->ParameterName =
FName(FullPropertyName + MaterialTextureScaleOffsetSuffix);
TransformScaleOffset->DefaultValue = {1, 1, 0, 0};
TransformScaleOffset->MaterialExpressionEditorX = NodeX;
TransformScaleOffset->MaterialExpressionEditorY =
PropertyDataSectionY + Incr;
AutoGeneratedNodes.Add(TransformScaleOffset);

UMaterialExpressionAppendVector* AppendScale =
NewObject<UMaterialExpressionAppendVector>(TargetMaterialLayer);
AppendScale->MaterialExpressionEditorX =
NodeX + Incr * (0.5 + GetNameLengthScalar(
TransformScaleOffset->ParameterName));
AppendScale->MaterialExpressionEditorY =
TransformRotation->MaterialExpressionEditorY;
AppendScale->A.Connect(1, TransformScaleOffset);
AppendScale->B.Connect(2, TransformScaleOffset);
AutoGeneratedNodes.Add(AppendScale);

UMaterialExpressionAppendVector* AppendOffset =
NewObject<UMaterialExpressionAppendVector>(TargetMaterialLayer);
AppendOffset->MaterialExpressionEditorX =
AppendScale->MaterialExpressionEditorX;
AppendOffset->MaterialExpressionEditorY =
TransformScaleOffset->MaterialExpressionEditorY;
AppendOffset->A.Connect(3, TransformScaleOffset);
AppendOffset->B.Connect(4, TransformScaleOffset);
AutoGeneratedNodes.Add(AppendOffset);

MaximumPropertyDataSectionX = FMath::Max(
MaximumPropertyDataSectionX,
AppendOffset->MaterialExpressionEditorX + Incr - NodeX);
PropertyDataSectionY += 1.25 * Incr;

UMaterialExpressionMaterialFunctionCall* TransformTexCoords =
NewObject<UMaterialExpressionMaterialFunctionCall>(
TargetMaterialLayer);
TransformTexCoords->MaterialFunction = FunctionLibrary.TransformTexCoords;
TransformTexCoords->MaterialExpressionEditorX =
SelectTexCoords->MaterialExpressionEditorX + Incr * 1.5;
TransformTexCoords->MaterialExpressionEditorY =
SelectTexCoords->MaterialExpressionEditorY;

FunctionLibrary.TransformTexCoords->GetInputsAndOutputs(
TransformTexCoords->FunctionInputs,
TransformTexCoords->FunctionOutputs);
// For some reason, Connect() doesn't work with this input...
TransformTexCoords->FunctionInputs[0].Input.Expression = SelectTexCoords;
TransformTexCoords->FunctionInputs[0].Input.OutputIndex = 0;
TransformTexCoords->FunctionInputs[1].Input.Connect(0, TransformRotation);
TransformTexCoords->FunctionInputs[2].Input.Connect(0, AppendScale);
TransformTexCoords->FunctionInputs[3].Input.Connect(0, AppendOffset);
AutoGeneratedNodes.Add(TransformTexCoords);

TexCoordsInputFunction = TransformTexCoords;

MaximumPropertyDataSectionX = FMath::Max(
MaximumPropertyDataSectionX,
TransformTexCoords->MaterialExpressionEditorX + Incr * 1.5);

PropertyDataSectionY += 0.8 * Incr;
}
Expand Down
4 changes: 1 addition & 3 deletions Source/CesiumRuntime/Private/EncodedFeaturesMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,9 +718,7 @@ EncodedPropertyTexture encodePropertyTextureAnyThreadPart(
property);
}

if (pDescription->bHasKhrTextureTransform) {
encodedProperty.textureTransform = property.getTextureTransform();
}
encodedProperty.textureTransform = property.getTextureTransform();
}

return encodedPropertyTexture;
Expand Down
17 changes: 0 additions & 17 deletions Source/CesiumRuntime/Public/CesiumFeaturesMetadataDescription.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,6 @@ struct CESIUMRUNTIME_API FCesiumFeatureIdSetDescription {
UPROPERTY(EditAnywhere, Category = "Cesium")
ECesiumFeatureIdSetType Type = ECesiumFeatureIdSetType::None;

/**
* Whether this feature ID set contains a KHR_texture_transform glTF
* extension. Only applicable if the feature ID set is a feature ID texture.
*/
UPROPERTY(
EditAnywhere,
Category = "Cesium",
Meta = (EditCondition = "Type == ECesiumFeatureIdSetType::Texture"))
bool bHasKhrTextureTransform = false;

/**
* The name of the property table that this feature ID set corresponds to.
*/
Expand Down Expand Up @@ -186,13 +176,6 @@ struct CESIUMRUNTIME_API FCesiumPropertyTexturePropertyDescription {
*/
UPROPERTY(EditAnywhere, Category = "Cesium")
FCesiumMetadataPropertyDetails PropertyDetails;

/**
* Whether this property texture property contains a KHR_texture_transform
* glTF extension.
*/
UPROPERTY(EditAnywhere, Category = "Cesium")
bool bHasKhrTextureTransform = false;
};

/**
Expand Down