cesium
cesium copied to clipboard
Add support for Building Scene Layer (BSL) OGC I3S standard
Esri Contribution: Adds support for OGC I3S Building Scene Layer (BSL) in CesiumJS. Co-authored-by: Anton Smirnov [email protected] Co-authored-by: Maxim Kuznetsov [email protected] Co-authored-by: Tamrat Belayneh [email protected]
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.
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 https://github.com/CesiumGS/cesium/pull/9634.
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 👏 🙏
Really appreciate the work by you and the team.
We'll chat with @lilleyse and @ggetz to find some cycles for a code review.
Thanks @Tamrat-B! Exciting! We'll take a review pass of this before the end of the week.
Thanks @ggetz. Looking forward to it.
@ggetz please have a look for the requested changes based on your reviews.
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.
@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: https://github.com/CesiumGS/cesium/issues/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.
@ggetz updated based on latest review. Thanks.
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.
-
Would it be possible to start in "Overview" mode? I think it's a bit confusing that nothing appears on screen to start.
-
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.
- 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?
@ggetz we've resolved all the issues you brought up in the latest reviews (1-3 above). Thanks!
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.
🎉 Thanks again @Tamrat-B and team!
Thanks much @ggetz @pjcozzi @lilleyse. Looking forward for users using this workflow!