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

Add support for Building Scene Layer (BSL) OGC I3S standard #11678

Merged
merged 33 commits into from
Feb 28, 2024

Conversation

Tamrat-B
Copy link
Contributor

@Tamrat-B Tamrat-B commented Dec 6, 2023

Esri Contribution: Adds support for OGC I3S Building Scene Layer (BSL) in CesiumJS.
Co-authored-by: Anton Smirnov anton.smirnov@actionengine.com
Co-authored-by: Maxim Kuznetsov maxim.kuznetsov@actionengine.com
Co-authored-by: Tamrat Belayneh tbelayneh@esri.com

This PR adds a new functionality to support an OGC Indexed 3D Scene Layer (I3S) 1.3 : Building Scene Layer (BSL) type. The PR also adds a new I3S Building Scene Layer – Cesium Sandcastle application showcasing BSL consumption of a BIM data in CesiumJS. The PR is largely based on extending the original contribution to PR #9634 supporting I3S 3D Object and IntegratedMesh Scene Layers.

…r color space profile

Purpose: Helper function to fix color saturation
…ibute driven filter.

Added new initialization option: enableFeatureFiltering, adjustMaterialAlphaMode, applySymbology and calculateNormals
…tIds property

- Added validation for actual and expected binary buffer size
- Fixed material color saturation by converting sRGB colors in I3S data to linear color space profile
- Added support for the generic feature attribute driven filter
- Added support for I3S symbology
…extensions with the feature index data

Added support for 3D objects transparency
Added support  for CESIUM_primitive_outline glTF extensions with the generated outlines indices
Added support for flat normals calculation if vertex normals are stripped out from I3S geometry
Fixed vertex color saturation by converting sRGB colors in I3S geometry to linear color space profile
@Tamrat-B
Copy link
Contributor Author

Tamrat-B commented Dec 6, 2023

PR Description

This PR adds a new functionality to support an OGC Indexed 3D Scene Layer (I3S) 1.3 : Building Scene Layer (BSL) type. The I3S Building Scene Layer – Cesium Sandcastle application showcases BSL consumption of BIM data for Turanga Library in Christchurch (NZ) in CesiumJS. The PR is largely based on extending the original contribution to #9634.

image

Find here a running version of I3S Building Scene Layer - Cesium SandCastle show case.

Below are overviews detailing changes brought about by this PR on both UI and Engine level.

UI Changes Overview

  • Application creates I3S data provider and adds it as a primitive data type to Cesium Viewer
  • I3S BSL Explorer UI is implemented as Cesium widget and is located @ /packages/widgets/Source/I3SBSLExplorer
  • I3S BSL Explorer widget implementation follows MVVM pattern and uses knockout js:
  • Model is created as I3S data provider in the application
  • View is represented by js file I3SBSLExplorer.js, defines html elements and data binding between the elements and ViewModel
  • ViewModel is represented by I3SBSLExplorerViewModel.js, creates ViewModel based on I3S data provider and handles the following user events:
  • selecting top layer for exploring
  • checking/unchecking layers and sublayers visibility
  • expanding/collapsing BSL tree view
  • To display I3S Explorer widget the showcase application passes two arguments to Cesium.I3SBSLExplorer – id of the container html element where the widget is planned to be displayed and I3S data provider

List of files added/modified:

Apps/Sandcastle/gallery/
    I3S Building Scene Layer.html
    I3S Building Scene Layer.jpg

packages/widgets/Source/
    I3SBSLExplorer/
    I3SBSLExplorer.css
    I3SBSLExplorer.js
    I3SBSLExplorerViewModel.js
    widgets.css – added import url of the I3SBSLExplorer widget styles (I3SBSLExplorer.css)

Engine Changes Overview

High-level structure of changes:

Scene layer initialization became dependent on the layer type ("Building", "3DObject" and "IntegratedMesh" layer types are supported). Common 3D Scene Layer initialization is not changed.I3S Layer class still represents a single user-visible layer: 3D Object or Integrated Mesh.

When a Building Scene Layer is initialized, it accomplishes the following:

  • It processes the [Building Scene Layer resource] (https://github.com/Esri/i3s-spec/blob/master/docs/1.8/layer.bld.md) of an I3S dataset, by creating the hierarchy of sublayers and loading statistics summary.
  • Each I3S Sublayer represents either a group of sublayers or a user-visible layer (I3S Layer), a 3D Scene Layer resource is requested for each I3S Layer.
  • I3S Data Provider stores the collection of all I3S layers in the scene (to control the life cycle of tilesets) as well as the collection of I3S sublayers (to manage sublayers and layers visibility).

Transcoding changes:

  • If requested, when creating an I3SDataProvider the user has now a new option enableFeatureFiltering to enable displaying geometries by I3S features against the default displaying by I3S nodes. By default, enableFeatureFiltering is disabled for Common 3D Scene Layer, but enabled for Building Scene Layer. When the enableFeatureFiltering option is enabled, we add EXT_mesh_features and EXT_structural_metadata extensions into a glTF document to force CesiumJS to create Cesium 3D Tile Feature for each feature in a node.
  • A new option, adjustMaterialAlphaMode is added to enable features transparency by adjusting the alpha mode of their material definition. By default, it is disabled for Common 3D Scene Layer, but enabled for Building Scene Layer. When the adjustMaterialAlphaMode option is enabled, we separate each geometry into two mesh primitives depending on whether the vertex color has transparency or not. Then the alpha mode in the material definition is updated for each mesh primitive based on its transparency.
  • A new option, applySymbology is added to enable displaying outlines if they are defined by the I3S layers' symbology. By default, it is disabled for Common 3D Scene Layer, but enabled for Building Scene Layer. When applySymbology option is enabled, we add CESIUM_primitive_outline extension into a glTF document to display outlines for 3D objects in the layers.
  • A new option, calculateNormals, is added to enable normals calculation if they are missing. By default, it is disabled for Common 3D Scene Layer with textures (if textureSetDefinitions details are present), but enabled for Common 3D Scene Layer without textures and Building Scene Layer.When the calculateNormals option is enabled, we generate the normals buffer with the flat normals per face for each geometry without the vertex normal attribute. Flat normals are calculated based on the vertex position attribute. The vertex normal attribute may be stripped out from the geometry buffer to reduce the size of the buffer. This is allowed by glTF specification where it states: "When normals are not specified, client implementations MUST calculate flat normals". However, the current CesiumJS implementation doesn’t automatically calculate flat normals for glTF 2.0 yet , which leads to unlit visualization for 3D objects.

About color saturation:

  • I3S material colors properties (baseColorFactor, emissiveFactor etc.) are assumed to be in the same color space as the textures, most commonly sRGB while in glTF they are interpreted as linear. The color vertex attribute is also assumed to be Standard RGB (sRGB space).We convert colors from sRGB color space to linear color space during transcoding I3S to glTF.

About feature attribute driven filter:

  • When the enableFeatureFiltering option is enabled (enabled by default for BSL) and any I3S node geometry contains features, there is now a new functionality to apply a filter driven by feature attribute values. A filter may contain one or multiple attributes and each attribute may specify one or multiple values. When a filter is applied, a 3D feature object will be hidden if its value for at least one attribute in the filter doesn't match to any attribute value of the filter. A filter can be applied either to specific I3S Layer or to all I3S layers in the scene.
  • When a filter is applied, it accomplishes the following: I3S Layer stores the copy of the filter attributes and requests the root node and all children of the root node to apply the filter. If any node is not visible or even not loaded yet, then the filter is applied once the content model is created and becomes ready. We then load an I3S Field for each attribute in the filter and set the visibility for each Cesium 3D Tile Feature based on the filter and the feature attribute values. We hide the whole model for I3S Node content while filtering is in progress to apply the filter for all features at once.

About transparency:

  • The color vertex attribute of the geometry buffer may contain transparent colors for any vertex. The interpretation of these alpha values depends on the alphaMode property of the material definition. The alphaMode value should be set to "BLEND" to render transparent objects. On the other hand, the blending mode for the fully opaque colors (100% alpha) also creates the effect of translucency. Processing the transparency in I3S layers is optional and can be configured by the adjustMaterialAlphaMode option (for BSL it is enabled by default). When the adjustMaterialAlphaMode option is enabled, the blending alpha mode is set for each geometry with the transparency in the color attribute.

About symbology:

  • Each I3S layer may define symbology details for rendering. Generally, it may specify the existence and the color for outlines (edges) and the material color. Symbology may be defined for all data in the layer or for particular 3D features, based on attribute values (unique or ranges).
  • When the applySymbology option is enabled, we parse data for the symbology during layers loading. As the result of parsing, we may have a list with specific symbology per feature and the default symbology for all other features. The outlines color from the default symbology is set as the default value for outlineColor option for 3D Tileset. Then we use additional processing during transcoding I3S to glTF.

List of files added/modified :

packages/engine/Source/
    Core/
      srgbToLinear.js
      - Added support for conversion from sRGB color space profile to linear color space profile
      Purpose: Helper function to fix color saturation
    Scene/
      I3SDataProvider.js
      - Added support for BSL structure per the OGC I3S standard
      Purpose: To display 3D BIM models and access the BSL sublayers hierarchy
      - Added support for BSL statistics
      Purpose: To provide the field names and values for BSL which may be used for the attribute driven filter UI
      - Added support for the generic feature attribute driven filter
      Purpose: To filter the drawn elements of all scene layers
      - Added new initialization option: enableFeatureFiltering
      Purpose: To provide an ability for common 3D Scene Layer to use the attribute driven filter
      - Added new initialization option: adjustMaterialAlphaMode
      Purpose: To set the 3D objects transparency based on the vertices color data
      - Added new initialization option: applySymbology
      Purpose: To define and show outlines for 3D Scene Layer based on symbology details in I3S Layer data
      - Added new initialization option: calculateNormals
      Purpose: To generate the buffer with flat normals per face if normals are stripped out from I3S geometry.
      - Added Support for BSL structure, BSL statistics, generic feature attribute driven filter.
      - Added new initialization option: enableFeatureFiltering, adjustMaterialAlphaMode, applySymbology and calculateNormals

    I3SField.js
      - Added support for binary attribute data with values stored in objectIds property
      Purpose: Some attribute data for Turanga_Library BSL stores values in objectIds property (not in attributeValues) which caused runtime errors
      - Added validation for actual and expected binary buffer size
      Purpose: Some attribute data for Turanga_Library BSL looks corrupted, the size of the binary buffer doesn't correspond to attributeStorageInfo which caused runtime errors
      - Added support for binary attribute data with values stored in objectIds property
      - Added validation for actual and expected binary buffer size

    I3SGeometry.js
      - Added support for extensions and extensionsUsed properties of the glTF root object
      Purpose: To add information about features into a glTF asset
      - Added support for 3D objects transparency
      - Fixed material color saturation by converting sRGB colors in I3S data to linear color space profile
I3SLayer.js
      - Added support for BSL hierarchy of layers: Scene -> Sublayer -> ... -> Layer versus common 3D SL hierarchy: Scene -> Layer
      Purpose: To adjust the URL to the 3DSceneLayerResource and manage the layers visibility
      - Added support for the generic feature attribute driven filter
      Purpose: To filter the drawn elements of a layer
      - Added support for I3S symbology
      Purpose: To display the outlines for 3D objects
      - Added support for BSL hierarchy of layers
      - Added support for the generic feature attribute driven filter
      - Added support for I3S symbology

    I3SNode.js
      - Added support for the generic feature attribute driven filter
      Purpose: To filter the drawn features of a node
      - Added support for I3S symbology
      Purpose: To display the outlines for 3D objects
      - Added support for the generic feature attribute driven filter
      - Added support for I3S symbology

    I3SStatistics.js
      - Added support for loading and parsing BSL statistics
      Purpose: To provide the field names and most frequent values for BSL
    I3SSublayer.js
      - Added support for BSL structure per the OGC I3S standard
      Purpose: To provide the BSL sublayers hierarchy and manage the layers visibility

    I3SSymbology.js
      - Added support for symbolization defined in I3S Layer data
      Purpose: To provide the outlines and material details for the Layer

    Workers/
      decodeI3S.js
      - Added support for EXT_mesh_features and EXT_structural_metadata glTF extensions with the feature index data
      Purpose: To add information about features into a glTF asset
      - Added support for 3D objects transparency
      - Fixed vertex color saturation by converting sRGB colors in I3S geometry to linear color space profile
      - Added support for CESIUM_primitive_outline glTF extensions with the generated outlines indices
      Purpose: To display the outlines for 3D objects
      - Added support for flat normals calculation if vertex normals are stripped out from I3S geometry
      Purpose: to enable lighting effects for I3S datasets without normals

@Tamrat-B Tamrat-B marked this pull request as ready for review December 6, 2023 08:01
@pjcozzi
Copy link
Contributor

pjcozzi commented Dec 10, 2023

@Tamrat-B 👏 🙏

Really appreciate the work by you and the team.

We'll chat with @lilleyse and @ggetz to find some cycles for a code review.

@ggetz
Copy link
Contributor

ggetz commented Dec 12, 2023

Thanks @Tamrat-B! Exciting! We'll take a review pass of this before the end of the week.

@Tamrat-B
Copy link
Contributor Author

Thanks @ggetz. Looking forward to it.

Copy link
Contributor

@ggetz ggetz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Tamrat-B I've taken an initial pass on the code and have a few questions, as well as some code suggestions based on our Coding Guide.

I noticed the demo is a bit slow. Is there anything we can do to address this? @lilleyse for advice.

Before this is merged, there a few things that should be addressed:

  • Update CHANGES.md with a summary of the fix
  • Any new contributors should be added to CONTRIBUTORS.md

packages/engine/Source/Core/srgbToLinear.js Show resolved Hide resolved
packages/engine/Source/Core/srgbToLinear.js Show resolved Hide resolved
Apps/Sandcastle/gallery/I3S Building Scene Layer.html Outdated Show resolved Hide resolved
Apps/Sandcastle/gallery/I3S Building Scene Layer.html Outdated Show resolved Hide resolved
Apps/Sandcastle/gallery/I3S Building Scene Layer.html Outdated Show resolved Hide resolved
packages/engine/Source/Scene/I3SSublayer.js Show resolved Hide resolved
packages/widgets/Source/I3SBSLExplorer/I3SBSLExplorer.js Outdated Show resolved Hide resolved
@Tamrat-B
Copy link
Contributor Author

@ggetz please have a look for the requested changes based on your reviews.

@ggetz
Copy link
Contributor

ggetz commented Jan 17, 2024

Thanks for the updates @Tamrat-B! We'll take another pass soon.

@lilleyse Let us know if you have any thoughts or suggestions on performance.

@Tamrat-B
Copy link
Contributor Author

@ggetz As to the question regarding performance, we believe there are two main things that affect performance: applySymbology option affecting I3S layer initialization and using a detailed terrain provider (such as ArcGIS elevation provider) seems to affect both initialization and navigation. With disabled terrain and outlines the performance looks quite good.

Unfortunately, if we were to use the default CesiumTerrainProvider provider there is a severe mismatch with the Turanga model and half of it will be submerged underground and is not a good option (though performance with quantized mesh looks good).

As per the open issue: #8481, it looks currently in CesiumJS the one or two globe picks per frame seems to slow down Cesium for height map based detailed terrain providers like ArcGIS. There is also some community discussions around same topic here. Note: as suggested in the work around of that issue setting Cesium.ScreenSpaceCameraController.enableCollisionDetection to false seems to help, which we can set in the sample.

that._parseBody(dataView, offset);
}
this._loadPromise = load(this).catch(function (error) {
console.error(error);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, the error should be thrown so that the developer can handle it in their app accordingly.

Can we remove the catch and console.log?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this one, we recommend keeping the catch. This logic handles any errors with availability or binaries for attributes. When such a condition is present (the issue is related to source I3S data not having complete information and/or unexpected buffer sizes) app developers can do nothing to fix it. Catching these errors allows working with valid attributes, considering invalid attributes as missing.
See below screenshot; the door asset would still be able to show the attributes associated with it with the error catching and logs the issue; without error catching, this asset wouldn’t be able to display the attribute pop up at all.
image

@Tamrat-B
Copy link
Contributor Author

Tamrat-B commented Feb 2, 2024

@ggetz updated based on latest review. Thanks.

@ggetz
Copy link
Contributor

ggetz commented Feb 27, 2024

Thanks @Tamrat-B! I was able to sync up with @lilleyse offline. He agrees that for the scope of this PR, the performance is acceptable.

I have a few comments after testing.

  1. Would it be possible to start in "Overview" mode? I think it's a bit confusing that nothing appears on screen to start.
image
  1. I also noticed in the example that the following is logged to the console for the Sandcastle example. I understand the first message, but would it be possible to pass the geoid service providers like is done in the other I3S examples?
Point layer LocationPoints is skipped as not supported.
No Geoid Terrain service provided - no geoid conversion will be performed.
  1. Given that we're already showing the metadata property values in the info box, can we skip the additional console.log(${fieldName}: ${fields[fieldName]}); when a feature is selected?

CHANGES.md Outdated Show resolved Hide resolved
@Tamrat-B
Copy link
Contributor Author

@ggetz we've resolved all the issues you brought up in the latest reviews (1-3 above). Thanks!

@ggetz
Copy link
Contributor

ggetz commented Feb 28, 2024

Thanks @Tamrat-B!

I did tweak the naming of "I3SBSL*" to "I3SBsl*" to be consistant with out naming conventions, and added an additional bullet in CHANGES.md for the updates to the widget package.

Assuming CI passes, this should be good to merge.

@ggetz
Copy link
Contributor

ggetz commented Feb 28, 2024

🎉 Thanks again @Tamrat-B and team!

@ggetz ggetz merged commit 09cc7e8 into CesiumGS:main Feb 28, 2024
4 checks passed
@Tamrat-B
Copy link
Contributor Author

Thanks much @ggetz @pjcozzi @lilleyse. Looking forward for users using this workflow!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants