Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle multiple feature ID sets in ModelExperimental #10018

Merged
merged 42 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3ec8430
Default to empty array
ptrgags Jan 13, 2022
fe5e5a0
Make model feature tables always defined
ptrgags Jan 13, 2022
e9e1ba7
Start handling IDs without property tables
ptrgags Jan 14, 2022
2b83629
Reorganize feature IDs in ModelComponents
ptrgags Jan 18, 2022
58e6d7c
Add featureIdIndex and instanceFeatureIdIndex
ptrgags Jan 18, 2022
7cc3265
Update pipeline stages
ptrgags Jan 18, 2022
e22c111
Split out FeatureIdPipelineStage
ptrgags Jan 18, 2022
e24eb37
Reorganize shaders
ptrgags Jan 18, 2022
15586dd
Add [fv]sInput.featureIds to CustomShader parser
ptrgags Jan 18, 2022
05915ac
Add feature IDs to the custom shader
ptrgags Jan 19, 2022
b042d79
Update custom shader specs
ptrgags Jan 19, 2022
30ffa8a
Fix ModelExperimentalPrimitive specs
ptrgags Jan 19, 2022
993922a
Update SelectedFeatureIdPipelineStage
ptrgags Jan 19, 2022
e56ef99
Fix picking
ptrgags Jan 19, 2022
85bbb21
Fix shader compilation error in VS
ptrgags Jan 19, 2022
9c01d4f
Update photogrammetry classification sandcastle
ptrgags Jan 19, 2022
28cc68e
Start fixing unit tests
ptrgags Jan 20, 2022
0fea72c
Merge branch 'main' into multi-feature-ids
ptrgags Jan 21, 2022
dd69bc7
Make new unit tests for FeatureIdPipelineStage
ptrgags Jan 21, 2022
754843e
Update SelectedFeatureIdPipelineStage specs
ptrgags Jan 21, 2022
6fef5c6
Mark tests as WebGL
ptrgags Jan 21, 2022
33c86b6
Add note in changelog about feature IDs in CustomShader
ptrgags Jan 21, 2022
9c45411
Update I3dmLoader
ptrgags Jan 21, 2022
71d8513
Select different feature ID sets at runtime
ptrgags Jan 21, 2022
2c3c315
Fix race condition
ptrgags Jan 21, 2022
b59697e
Update style when feature ID index is changed
ptrgags Jan 24, 2022
d114a53
Update feature ID in other sandcastle
ptrgags Jan 24, 2022
e0839b4
Update Custom Shader guide
ptrgags Jan 24, 2022
b551bac
Update documentation
ptrgags Jan 24, 2022
a187a94
Merge branch 'main' into multi-feature-ids
ptrgags Jan 24, 2022
7f336aa
Fix unit tests
ptrgags Jan 24, 2022
2563438
Fix typo
ptrgags Jan 24, 2022
f95f680
Update CHANGES.md
ptrgags Jan 24, 2022
004af76
Fix prettier
ptrgags Jan 24, 2022
42263c2
Fix JSDoc formatting
ptrgags Jan 24, 2022
b10e308
Demonstrate using multiple feature ID sets
ptrgags Jan 25, 2022
33b4bab
Update documentation
ptrgags Jan 26, 2022
7323aa9
Handle filtering by pass type
ptrgags Jan 26, 2022
f6df243
applyStyle doesn't need an if guard
ptrgags Jan 26, 2022
b937b9c
Merge tag 'pre-let-const' into lets-merge2
ptrgags Jan 26, 2022
6ff5186
Merge tag 'post-let-const' into lets-merge2
ptrgags Jan 26, 2022
2a61e4f
Simplify multi-feature ID sandcastle
ptrgags Jan 27, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@
"const float TOTAL_FEATURES = 12.0;",
"",
"void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {",
" // NOTE: This is exposing internal details of the shader. It would be better if this was added to fsInput somewhere...",
" float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);",
" float featureId = fsInput.featureIds.featureId_0;",
"",
" if (featureId == WINDOW || featureId == SKYLIGHT) {",
" material.alpha = 0.4;",
Expand Down Expand Up @@ -136,8 +135,7 @@
"const float TRAFFIC_LIGHT = 11.0;",
"",
"void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {",
" // NOTE: This is exposing internal details of the shader. It would be better if this was added to fsInput somewhere...",
" float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);",
" float featureId = fsInput.featureIds.featureId_0;",
"",
" if (featureId == CLOCK) {",
" // Shiny brass",
Expand Down Expand Up @@ -183,8 +181,7 @@
fragmentShaderText: [
"const float NOTHING_SELECTED = 12.0;",
"void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {",
" // NOTE: This is exposing internal details of the shader. It would be better if this was added to fsInput somewhere...",
" float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);",
" float featureId = fsInput.featureIds.featureId_0;",
"",
" if (u_selectedFeature < NOTHING_SELECTED && featureId == u_selectedFeature) {",
" material.specular = vec3(1.00, 0.85, 0.57);",
Expand Down
3 changes: 1 addition & 2 deletions Apps/Sandcastle/gallery/3D Tiles Next S2 Globe.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@
fragmentShaderText: [
"void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material)",
"{",
" // NOTE: this is exposing internal details of the shader.",
" float featureId = floor(texture2D(FEATURE_ID_TEXTURE, FEATURE_ID_TEXCOORD).FEATURE_ID_CHANNEL * 255.0 + 0.5);",
" float featureId = fsInput.featureIds.featureId_0;",
" // Use cartesian coordinates but scale to be roughly [-1, 1]",
" vec3 positionWC = fsInput.attributes.positionWC / 6.3e6;",
" if (featureId == 60.0)",
Expand Down
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

##### Additions :tada:

- Feature IDs for styling and picking in `ModelExperimental` can now be selected via `(tileset|model).featureIdIndex` and `(tileset|model).instanceFeatureIdIndex`. [#10018](https://github.com/CesiumGS/cesium/pull/10018)
- Added support for all types of feature IDs in `CustomShader`. [#10018](https://github.com/CesiumGS/cesium/pull/10018)
- Added getters `Cesium3DTileFeature.featureId` and `ModelFeature.featureId` so the feature ID or batch ID can be accessed from a picked feature. [#10022](https://github.com/CesiumGS/cesium/pull/10022)
- Added `I3dmLoader` to transcode .i3dm to `ModelExperimental`. [#9968](https://github.com/CesiumGS/cesium/pull/9968)
- Added `PntsLoader` to transcode .pnts to `ModelExperimental`. [#9978](https://github.com/CesiumGS/cesium/pull/9978)
Expand Down
22 changes: 22 additions & 0 deletions Source/Scene/Cesium3DTileset.js
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,28 @@ function Cesium3DTileset(options) {
ExperimentalFeatures.enableModelExperimental
);

/**
* The index into the list of primitive feature IDs used for picking and
* styling. For EXT_feature_metadata, feature ID attributes are listed before
* feature ID textures. If both per-primitive and per-instance feature IDs are
* present, the instance feature IDs take priority.
*
* @type {Number}
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
this.featureIdIndex = defaultValue(options.featureIdIndex, 0);

/**
* The index into the list of instance feature IDs used for picking and
* styling. If both per-primitive and per-instance feature IDs are present,
* the instance feature IDs take priority.
*
* @type {Number}
* @readonly
ptrgags marked this conversation as resolved.
Show resolved Hide resolved
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*/
this.instanceFeatureIdIndex = defaultValue(options.instanceFeatureIdIndex, 0);

this._schemaLoader = undefined;

var that = this;
Expand Down
174 changes: 109 additions & 65 deletions Source/Scene/GltfLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var Attribute = ModelComponents.Attribute;
var Indices = ModelComponents.Indices;
var FeatureIdAttribute = ModelComponents.FeatureIdAttribute;
var FeatureIdTexture = ModelComponents.FeatureIdTexture;
var FeatureIdImplicitRange = ModelComponents.FeatureIdImplicitRange;
var MorphTarget = ModelComponents.MorphTarget;
var Primitive = ModelComponents.Primitive;
var Instances = ModelComponents.Instances;
Expand Down Expand Up @@ -814,8 +815,6 @@ function loadFeatureIdAttribute(featureIds, propertyTableId) {
var featureIdAttribute = new FeatureIdAttribute();
featureIdAttribute.propertyTableId = propertyTableId;
featureIdAttribute.setIndex = featureIds.attribute;
featureIdAttribute.offset = defaultValue(featureIds.offset, 0);
featureIdAttribute.repeat = featureIds.repeat;
return featureIdAttribute;
}

Expand All @@ -825,6 +824,26 @@ function loadFeatureIdAttributeLegacy(gltfFeatureIdAttribute, featureTableId) {
var featureIds = gltfFeatureIdAttribute.featureIds;
featureIdAttribute.propertyTableId = featureTableId;
featureIdAttribute.setIndex = getSetIndex(featureIds.attribute);
return featureIdAttribute;
}

// for EXT_mesh_features
function loadFeatureIdImplicitRange(featureIds, propertyTableId) {
var featureIdAttribute = new FeatureIdImplicitRange();
featureIdAttribute.propertyTableId = propertyTableId;
featureIdAttribute.offset = defaultValue(featureIds.offset, 0);
featureIdAttribute.repeat = featureIds.repeat;
return featureIdAttribute;
}

// for backwards compatibility with EXT_feature_metadata
function loadFeatureIdImplicitRangeLegacy(
gltfFeatureIdAttribute,
featureTableId
) {
var featureIdAttribute = new FeatureIdImplicitRange();
var featureIds = gltfFeatureIdAttribute.featureIds;
featureIdAttribute.propertyTableId = featureTableId;
// constant/divisor was renamed to offset/repeat
featureIdAttribute.offset = defaultValue(featureIds.constant, 0);
// The default is now undefined
Expand All @@ -833,6 +852,7 @@ function loadFeatureIdAttributeLegacy(gltfFeatureIdAttribute, featureTableId) {
return featureIdAttribute;
}

// for EXT_mesh_features
function loadFeatureIdTexture(
loader,
gltf,
Expand Down Expand Up @@ -864,6 +884,7 @@ function loadFeatureIdTexture(
return featureIdTexture;
}

// for backwards compatibility with EXT_feature_metadata
function loadFeatureIdTextureLegacy(
loader,
gltf,
Expand Down Expand Up @@ -991,49 +1012,43 @@ function loadPrimitiveMetadata(
metadataExtension,
supportedImageFormats
) {
// Partition feature ID attributes and textures
var i;
var featureIdAttributes = [];
var featureIdTextures = [];
var featureIdsArray = metadataExtension.featureIds;
var propertyTablesArray = metadataExtension.propertyTables;

if (defined(featureIdsArray)) {
for (i = 0; i < featureIdsArray.length; i++) {
var featureIds = featureIdsArray[i];
if (defined(featureIds.channel)) {
featureIdTextures.push(featureIds);
} else {
featureIdAttributes.push(featureIds);
}
}
}
var featureIdsArray = defined(metadataExtension.featureIds)
? metadataExtension.featureIds
: [];
var propertyTables = defined(metadataExtension.propertyTables)
? metadataExtension.propertyTables
: [];

// Feature ID Attributes
var featureIdAttributesLength = featureIdAttributes.length;
for (i = 0; i < featureIdAttributesLength; ++i) {
primitive.featureIdAttributes.push(
loadFeatureIdAttribute(featureIdAttributes[i], propertyTablesArray[i])
);
}
for (var i = 0; i < featureIdsArray.length; i++) {
var featureIds = featureIdsArray[i];
// This may be undefined, as feature IDs are not required to have
// associated metadata.
var propertyTableId = propertyTables[i];

// Feature ID Textures
var featureIdTexturesLength = featureIdTextures.length;
for (i = 0; i < featureIdTexturesLength; ++i) {
primitive.featureIdTextures.push(
loadFeatureIdTexture(
var featureIdComponent;
if (defined(featureIds.channel)) {
featureIdComponent = loadFeatureIdTexture(
loader,
gltf,
featureIdTextures[i],
propertyTablesArray[i],
featureIds,
propertyTableId,
supportedImageFormats
)
);
);
} else if (defined(featureIds.attribute)) {
featureIdComponent = loadFeatureIdAttribute(featureIds, propertyTableId);
} else {
featureIdComponent = loadFeatureIdImplicitRange(
featureIds,
propertyTableId
);
}

primitive.featureIds.push(featureIdComponent);
}

// Feature Textures
// Property Textures
if (defined(metadataExtension.propertyTextures)) {
primitive.featureTextureIds = metadataExtension.propertyTextures;
primitive.propertyTextureIds = metadataExtension.propertyTextures;
}
}

Expand All @@ -1045,21 +1060,31 @@ function loadPrimitiveMetadataLegacy(
supportedImageFormats
) {
var i;
var featureIdComponent;
var featureTableId;
var propertyTableId;

// Feature ID Attributes
var featureIdAttributes = metadataExtension.featureIdAttributes;
if (defined(featureIdAttributes)) {
var featureIdAttributesLength = featureIdAttributes.length;
for (i = 0; i < featureIdAttributesLength; ++i) {
var featureIdAttribute = featureIdAttributes[i];
primitive.featureIdAttributes.push(
loadFeatureIdAttributeLegacy(
featureTableId = featureIdAttribute.featureTable;
propertyTableId = loader._sortedPropertyTableIds.indexOf(featureTableId);

if (defined(featureIdAttribute.featureIds.attribute)) {
featureIdComponent = loadFeatureIdAttributeLegacy(
featureIdAttribute,
loader._sortedPropertyTableIds.indexOf(
featureIdAttribute.featureTable
)
)
);
propertyTableId
);
} else {
featureIdComponent = loadFeatureIdImplicitRangeLegacy(
featureIdAttribute,
propertyTableId
);
}
primitive.featureIds.push(featureIdComponent);
}
}

Expand All @@ -1069,15 +1094,17 @@ function loadPrimitiveMetadataLegacy(
var featureIdTexturesLength = featureIdTextures.length;
for (i = 0; i < featureIdTexturesLength; ++i) {
var featureIdTexture = featureIdTextures[i];
primitive.featureIdTextures.push(
loadFeatureIdTextureLegacy(
loader,
gltf,
featureIdTexture,
loader._sortedPropertyTableIds.indexOf(featureIdTexture.featureTable),
supportedImageFormats
)
featureTableId = featureIdTexture.featureTable;
propertyTableId = loader._sortedPropertyTableIds.indexOf(featureTableId);
featureIdComponent = loadFeatureIdTextureLegacy(
loader,
gltf,
featureIdTexture,
propertyTableId,
supportedImageFormats
);
// Feature ID textures are added after feature ID attributes in the list
primitive.featureIds.push(featureIdComponent);
}
}

Expand All @@ -1086,7 +1113,7 @@ function loadPrimitiveMetadataLegacy(
// feature textures are now identified by an integer index. To convert the
// string IDs to integers, find their place in the sorted list of feature
// table names
primitive.featureTextureIds = metadataExtension.featureTextures.map(
primitive.propertyTextureIds = metadataExtension.featureTextures.map(
function (id) {
return loader._sortedFeatureTextureIds.indexOf(id);
}
Expand Down Expand Up @@ -1161,18 +1188,25 @@ function loadInstances(loader, gltf, nodeExtensions, frameState) {
// For EXT_mesh_features
function loadInstanceMetadata(instances, metadataExtension) {
// feature IDs are required in EXT_mesh_features
var featureIdAttributes = metadataExtension.featureIds;
var featureIdsArray = metadataExtension.featureIds;
var propertyTables = defined(metadataExtension.propertyTables)
? metadataExtension.propertyTables
: [];

var featureIdAttributesLength = featureIdAttributes.length;
for (var i = 0; i < featureIdAttributesLength; i++) {
var featureIds = featureIdAttributes[i];
for (var i = 0; i < featureIdsArray.length; i++) {
var featureIds = featureIdsArray[i];
var propertyTableId = propertyTables[i];
instances.featureIdAttributes.push(
loadFeatureIdAttribute(featureIds, propertyTableId)
);

var featureIdComponent;
if (defined(featureIds.attribute)) {
featureIdComponent = loadFeatureIdAttribute(featureIds, propertyTableId);
} else {
featureIdComponent = loadFeatureIdImplicitRange(
featureIds,
propertyTableId
);
}
instances.featureIds.push(featureIdComponent);
}
}

Expand All @@ -1187,12 +1221,22 @@ function loadInstanceMetadataLegacy(
var featureIdAttributesLength = featureIdAttributes.length;
for (var i = 0; i < featureIdAttributesLength; ++i) {
var featureIdAttribute = featureIdAttributes[i];
instances.featureIdAttributes.push(
loadFeatureIdAttributeLegacy(
var featureTableId = featureIdAttribute.featureTable;
var propertyTableId = sortedPropertyTableIds.indexOf(featureTableId);

var featureIdComponent;
if (defined(featureIdAttribute.featureIds.attribute)) {
featureIdComponent = loadFeatureIdAttributeLegacy(
featureIdAttribute,
sortedPropertyTableIds.indexOf(featureIdAttribute.featureTable)
)
);
propertyTableId
);
} else {
featureIdComponent = loadFeatureIdImplicitRangeLegacy(
featureIdAttribute,
propertyTableId
);
}
instances.featureIds.push(featureIdComponent);
}
}
}
Expand Down
Loading