3.6.0 Change Notes

Table of contents:

API support policies

iTwin.js now documents the official policies defining the level of stability and support afforded to its public APIs and each major release.

Electron 22 support

In addition to already supported Electron versions, iTwin.js now supports Electron 22.

Display system

Point cloud shading

Point clouds can provide valuable real-world context when visualizing an iTwin, but it can often be difficult to discern individual features within the cloud of points - especially when the point cloud lacks color data. You can now accentuate the depth, shape, and surface of a point cloud using a technique called "eye-dome lighting" that uses the relative depths of the points to compute a lighting effect.

Point cloud shading is specified by several properties of RealityModelDisplaySettings.pointCloud, all with names prefixed with edl (short for "eye-dome lighting"):

Each point cloud in a view can have its own independent EDL settings. You can configure those settings via ContextRealityModel.displaySettings for context reality models, and DisplayStyleSettings.setRealityModelDisplaySettings for persistent reality models. Adjusting related settings like PointCloudDisplaySettings.sizeMode and PointCloudDisplaySettings.shape can influence the shading effect.

A monochrome point cloud with (bottom) and without (top) shading:

Monochrome point cloud shading

A colorized point cloud with (bottom) and without (top) shading:

Colorized point cloud shading

Normal mapping

Normal mapping is a technique that simulates additional surface details by mapping a texture containing normal vectors onto a surface. RenderMaterials now support applying normal maps.

You can create a RenderMaterial with a normal map on the frontend via RenderSystem.createRenderMaterial. The normal map is specified by the MaterialTextureMappingProps.normalMapParams in your CreateRenderMaterialArgs.textureMapping.

To create a RenderMaterialElement with a normal map on the backend, use RenderMaterialElement.insert or RenderMaterialElement.create. Pass the normal map in RenderMaterialElementParams.normalMap.

The image below illustrates the effects of normal mapping. The cubes in the top row have no normal maps, while the cubes in the bottom row are normal mapped.

Normal mapping

Smooth viewport resizing

Previously, when a Viewport's canvas was resized there would be a delay of up to one second during which the viewport's contents would appear stretched or squished, before they were redrawn to match the new canvas dimensions. This was due to the unavailability of ResizeObserver in some browsers. Now that ResizeObserver is supported by all major browsers, we are able to use it to make the contents of the viewport update smoothly during a resize operation.

Pickable view overlays

A bug preventing users from interacting with pickable decorations defined as GraphicType.ViewOverlay has been fixed.

Element clipping example

In some cases it is useful to apply a clipping volume to a view that mimics the shape of one or more elements. For example, you may have a view displaying a reality mesh captured from a real-world asset like a factory, and a design model representing the same asset, and wish to isolate the portions of the reality mesh corresponding to a series of pipe elements in the design model.

display-test-app now provides an example tool demonstrating how this can be achieved. It uses IModelConnection.generateElementMeshes to produce Polyfaces from one or more elements; decomposes them into a set of convex hulls using VHACD.js; and creates a clipping volume from the hulls via ConvexClipPlaneSet.createConvexPolyface. The example tool can be accessed in display-test-app using the keyin dta clip element geometry.

Support larger terrain meshes

Previously, RealityMeshParams only supported 16-bit vertex indices, which limited the number of vertices that could be produced by a TerrainMeshProvider. That limit has been extended to 32 bits (the maximum supported by WebGL). The code has also been optimized to allocate only as many bytes per vertex index as required. For example, if a mesh contains fewer than 256 vertices, only one byte will be allocated per vertex index.


Query mesh convexity

A new method PolyfaceQuery.isConvexByDihedralAngleCount permits testing the convexity of a mesh by inspecting the dihedral angles of all of its edges. For an example of its usage, see the element clipping example.

Write-ahead logging

Previously, iTwin.js used DELETE journal mode for writes to local briefcase files. It now uses write-ahead logging (WAL) mode. This change should be invisible to applications, other than performance of IModelDb.saveChanges should improve in most cases. However, there are a few subtle implications of this change that may affect existing applications:

  • Attempting to open more than one simultaneous writeable connections to the same briefcase will now fail on open. Previously, both opens would succeed, followed by a failure on the first attempted write by one or the other connection.
  • Failure to close a writeable briefcase may leave a "-wal" file. Previously, if a program crashed or exited with an open briefcase, it would leave the briefcase file as-of its last call to IModelDb.saveChanges. Now, there will be another file with the name of the briefcase with "-wal" appended. This is not a problem and the briefcase is completely intact, except that the briefcase file itself is not sufficient for copying (it will not include recent changes.) The "-wal" file will be used by future connections and will be deleted the next time the briefcase is successfully closed.
  • Attempting to copy an open-for-write briefcase file may not include recent changes. This scenario generally only arises for tests. If you wish to copy an open-for-write briefcase file, you must now call IModelDb.performCheckpoint first.


Hierarchy levels filtering

Ability to filter individual hierarchy levels was added for tree components that use PresentationTreeDataProvider. To enable this, PresentationTreeRenderer should be passed to ControlledTree through ControlledTreeProps.treeRenderer:

return <ControlledTree
  // other props
  treeRenderer={(treeProps) => <PresentationTreeRenderer {...treeProps} imodel={imodel} modelSource={modelSource} />}

PresentationTreeRenderer renders nodes with action buttons for applying and clearing filters. Some hierarchy levels might not be filterable depending on the presentation rules used to build them. In that case, action buttons for those hierarchy levels are not rendered. If applied filter does not produce any nodes, There are no child nodes matching current filter message is rendered in that hierarchy level.

Filtered Tree

Dialog component for creating hierarchy level filter is opened when node's Filter button is clicked. This dialog allows to create complex filters with multiple conditions based on properties from instances that are represented by the nodes in that hierarchy level.

Filter Builder Dialog

Grouping nodes HiliteSet

HiliteSetProvider.getHiliteSet now supports getting HiliteSet for grouping nodes. Previously, HiliteSetProvider.getHiliteSet used to return empty HiliteSet if called with key of the grouping node. Now it returns HiliteSet for all the instances that are grouped under grouping node. This also means that now elements will be hilited in viewport using Unified Selection when grouping node is selected in the tree.

API promotions

The following APIs have been promoted to @public, indicating they are now part of their respective packages' stability contract.








API deprecations


ByteStream's next property getters like ByteStream.nextUint32 and ByteStream.nextFloat64 have been deprecated and replaced with corresponding read methods like ByteStream.readUint32 and ByteStream.readFloat64. The property getters have the side effect of incrementing the stream's current read position, which can result in surprising behavior and may trip up code optimizers that assume property access is free of side effects.

Similarly, TransientIdSequence.next returns a new Id each time it is called. Code optimizers like Angular's may elide repeated calls to next assuming it will return the same value each time. Prefer to use the new TransientIdSequence.getNext method instead.


ScreenViewport.setEventController was only ever intended to be used by ViewManager. In the unlikely event that you are using it for some (probably misguided) purpose, it will continue to behave as before, but it will be removed in a future major version.

NativeApp.requestDownloadBriefcase parameter progress is deprecated in favor of progressCallback in DownloadBriefcaseOptions. Similarly, progressCallback in PullChangesOptions is now deprecated and should be replaced with downloadProgressCallback in PullChangesOptions. Both new variables are of type OnDownloadProgress, which more accurately represents information reported during downloads.

IModelConnection.displayedExtents and IModelConnection.expandDisplayedExtents are deprecated. The displayed extents are expanded every time a ContextRealityModel is added to any view in the iModel, and never shrink. They were previously used to compute the viewed extents of every SpatialViewState, which could produce an unnecessarily large frustum resulting in graphical artifacts. Now each spatial view computes its extents based on the extents of the models it is currently displaying. displayedExtents is still computed as before to support existing users of the API, but its use is not recommended.


RenderMaterialElement.Params is defined as a class, which makes it unwieldy to use. You can now use the interface RenderMaterialElementParams instead.


UiItemsProvider and other AppUI specific types and APIs are deprecated and moved to @itwin/appui-react package. For a replacement in case of API rename consult @deprecated tag in the documentation.


ModelsTree and CategoryTree were moved to @itwin/tree-widget-react package and deprecated in @itwin/appui-react packages. They will be removed from @itwin/appui-react in future major version.

SpatialContainmentTree were deprecated in favor of SpatialContainmentTree from @itwin/breakdown-trees-react package. SpatialContainmentTree will be removed in future major version.


A bunch of {api_name}JSON interfaces, completely matching their sibling {api_name} definition, thus having no real benefit, have been forcing us to map back and forth between {api_name} and {api_name}JSON with {api_name}.toJSON and {api_name}.fromJSON helper functions. Majority of them are marked public as they're part of public RPC interface, but are generally not expected to be directly used by consumer code. They have been deprecated with the recommendation to use {api_name}.

Last Updated: 17 March, 2023