@cognite/reveal 2.1.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/core/cad.d.ts +4 -5
  2. package/core/index.d.ts +7 -7
  3. package/core/src/datamodels/base/SupportedModelTypes.d.ts +4 -4
  4. package/core/src/datamodels/base/index.d.ts +6 -6
  5. package/core/src/datamodels/base/types.d.ts +14 -14
  6. package/core/src/datamodels/cad/CadManager.d.ts +45 -43
  7. package/core/src/datamodels/cad/CadModelFactory.d.ts +7 -7
  8. package/core/src/datamodels/cad/CadModelSectorLoadStatistics.d.ts +38 -38
  9. package/core/src/datamodels/cad/createCadManager.d.ts +9 -10
  10. package/core/src/datamodels/cad/picking.d.ts +28 -28
  11. package/core/src/datamodels/cad/rendering/RenderAlreadyLoadedGeometryProvider.d.ts +10 -9
  12. package/core/src/datamodels/cad/sector/CadModelClipper.d.ts +10 -10
  13. package/core/src/datamodels/cad/styling/AssetNodeCollection.d.ts +39 -39
  14. package/core/src/datamodels/cad/styling/InvertedNodeCollection.d.ts +24 -24
  15. package/core/src/datamodels/cad/styling/NodeCollectionDeserializer.d.ts +26 -26
  16. package/core/src/datamodels/cad/styling/PopulateIndexSetFromPagedResponseHelper.d.ts +24 -24
  17. package/core/src/datamodels/cad/styling/PropertyFilterNodeCollection.d.ts +61 -61
  18. package/core/src/datamodels/cad/styling/SinglePropertyFilterNodeCollection.d.ts +60 -60
  19. package/core/src/datamodels/cad/styling/index.d.ts +8 -8
  20. package/core/src/datamodels/pointcloud/PointCloudFactory.d.ts +9 -9
  21. package/core/src/datamodels/pointcloud/PointCloudManager.d.ts +26 -25
  22. package/core/src/datamodels/pointcloud/PointCloudMetadata.d.ts +11 -11
  23. package/core/src/datamodels/pointcloud/PointCloudMetadataRepository.d.ts +13 -13
  24. package/core/src/datamodels/pointcloud/PointCloudNode.d.ts +62 -62
  25. package/core/src/datamodels/pointcloud/PotreeGroupWrapper.d.ts +39 -39
  26. package/core/src/datamodels/pointcloud/PotreeNodeWrapper.d.ts +38 -38
  27. package/core/src/datamodels/pointcloud/createPointCloudManager.d.ts +6 -8
  28. package/core/src/datamodels/pointcloud/index.d.ts +5 -0
  29. package/core/src/datamodels/pointcloud/picking.d.ts +29 -29
  30. package/core/src/datamodels/pointcloud/types.d.ts +114 -114
  31. package/core/src/index.d.ts +19 -19
  32. package/core/src/internals.d.ts +15 -0
  33. package/core/src/migration.d.ts +8 -8
  34. package/core/src/public/RevealManager.d.ts +64 -61
  35. package/core/src/public/createRevealManager.d.ts +23 -24
  36. package/core/src/public/migration/Cognite3DModel.d.ts +339 -323
  37. package/core/src/public/migration/Cognite3DViewer.d.ts +555 -545
  38. package/core/src/public/migration/CogniteModelBase.d.ts +17 -17
  39. package/core/src/public/migration/CognitePointCloudModel.d.ts +121 -121
  40. package/core/src/public/migration/NodeIdAndTreeIndexMaps.d.ts +4 -4
  41. package/core/src/public/migration/NotSupportedInMigrationWrapperError.d.ts +11 -11
  42. package/core/src/public/migration/RenderController.d.ts +4 -4
  43. package/core/src/public/migration/types.d.ts +266 -240
  44. package/core/src/public/types.d.ts +46 -45
  45. package/core/src/{public/migration → storage}/RevealManagerHelper.d.ts +58 -58
  46. package/core/src/utilities/BoundingBoxClipper.d.ts +23 -23
  47. package/core/src/utilities/Spinner.d.ts +27 -28
  48. package/core/src/utilities/ViewStateHelper.d.ts +33 -33
  49. package/core/src/utilities/callActionWithIndicesAsync.d.ts +4 -4
  50. package/core/src/utilities/index.d.ts +8 -8
  51. package/core/src/utilities/reflection.d.ts +7 -7
  52. package/core/src/utilities/worldToViewport.d.ts +30 -31
  53. package/core/utilities.d.ts +4 -4
  54. package/extensions/datasource.d.ts +9 -0
  55. package/extensions/datasource.js +33 -0
  56. package/extensions/datasource.map +1 -0
  57. package/index.d.ts +8 -8
  58. package/index.js +142 -130
  59. package/index.map +1 -1
  60. package/package.json +1 -1
  61. package/packages/cad-geometry-loaders/index.d.ts +14 -20
  62. package/packages/cad-geometry-loaders/src/CadLoadingHints.d.ts +11 -11
  63. package/packages/cad-geometry-loaders/src/CadModelSectorBudget.d.ts +26 -26
  64. package/packages/cad-geometry-loaders/src/CadModelUpdateHandler.d.ts +44 -44
  65. package/packages/cad-geometry-loaders/src/sector/CachedRepository.d.ts +25 -25
  66. package/packages/cad-geometry-loaders/src/sector/ModelStateHandler.d.ts +12 -12
  67. package/packages/cad-geometry-loaders/src/sector/Repository.d.ts +9 -9
  68. package/packages/cad-geometry-loaders/src/sector/SectorLoader.d.ts +28 -28
  69. package/packages/cad-geometry-loaders/src/sector/SimpleAndDetailedToSector3D.d.ts +20 -20
  70. package/packages/cad-geometry-loaders/src/sector/culling/ByVisibilityGpuSectorCuller.d.ts +53 -53
  71. package/packages/cad-geometry-loaders/src/sector/culling/OccludingGeometryProvider.d.ts +6 -6
  72. package/packages/cad-geometry-loaders/src/sector/culling/OrderSectorsByVisibilityCoverage.d.ts +107 -107
  73. package/packages/cad-geometry-loaders/src/sector/culling/SectorCuller.d.ts +33 -33
  74. package/packages/cad-geometry-loaders/src/sector/culling/TakenSectorTree.d.ts +24 -24
  75. package/packages/cad-geometry-loaders/src/sector/culling/types.d.ts +71 -71
  76. package/packages/cad-geometry-loaders/src/sector/rxSectorUtilities.d.ts +12 -12
  77. package/packages/cad-geometry-loaders/src/sector/sectorUtilities.d.ts +20 -19
  78. package/packages/cad-geometry-loaders/src/utilities/PromiseUtils.d.ts +18 -18
  79. package/packages/cad-geometry-loaders/src/utilities/arrays.d.ts +5 -5
  80. package/packages/cad-geometry-loaders/src/utilities/groupMeshesByNumber.d.ts +8 -8
  81. package/packages/cad-geometry-loaders/src/utilities/rxOperations.d.ts +5 -5
  82. package/packages/cad-geometry-loaders/src/utilities/types.d.ts +25 -48
  83. package/packages/cad-parsers/index.d.ts +21 -20
  84. package/packages/cad-parsers/src/cad/CadSectorParser.d.ts +15 -15
  85. package/packages/cad-parsers/src/cad/LevelOfDetail.d.ts +8 -8
  86. package/packages/{cad-geometry-loaders/src/material-manager/rendering → cad-parsers/src/cad}/filterInstanceMesh.d.ts +6 -6
  87. package/packages/cad-parsers/src/cad/filterPrimitives.d.ts +9 -9
  88. package/packages/cad-parsers/src/cad/primitiveGeometries.d.ts +31 -31
  89. package/packages/{cad-geometry-loaders/src/material-manager/rendering → cad-parsers/src/cad}/triangleMeshes.d.ts +6 -6
  90. package/packages/cad-parsers/src/cad/types.d.ts +56 -56
  91. package/packages/cad-parsers/src/metadata/CadMetadataParser.d.ts +7 -7
  92. package/packages/cad-parsers/src/metadata/CadModelMetadata.d.ts +44 -44
  93. package/packages/cad-parsers/src/metadata/CadModelMetadataRepository.d.ts +16 -16
  94. package/packages/cad-parsers/src/metadata/MetadataRepository.d.ts +7 -6
  95. package/packages/cad-parsers/src/metadata/parsers/CadMetadataParserV8.d.ts +51 -51
  96. package/packages/cad-parsers/src/metadata/types.d.ts +41 -41
  97. package/packages/{cad-geometry-loaders → cad-parsers}/src/sector/RootSectorNode.d.ts +12 -12
  98. package/packages/{cad-geometry-loaders → cad-parsers}/src/sector/SectorNode.d.ts +21 -21
  99. package/packages/cad-parsers/src/utilities/SectorScene.d.ts +21 -21
  100. package/packages/cad-parsers/src/utilities/SectorSceneFactory.d.ts +12 -12
  101. package/packages/cad-parsers/src/{cad → utilities}/computeBoundingBoxFromAttributes.d.ts +9 -9
  102. package/packages/{cad-geometry-loaders → cad-parsers}/src/utilities/float32BufferToMatrix.d.ts +12 -12
  103. package/packages/cad-parsers/src/utilities/types.d.ts +48 -48
  104. package/packages/cad-styling/index.d.ts +9 -9
  105. package/packages/cad-styling/src/CombineNodeCollectionBase.d.ts +31 -31
  106. package/packages/cad-styling/src/IntersectionNodeCollection.d.ts +15 -15
  107. package/packages/cad-styling/src/NodeAppearance.d.ts +62 -62
  108. package/packages/cad-styling/src/NodeAppearanceProvider.d.ts +29 -29
  109. package/packages/cad-styling/src/NodeCollectionBase.d.ts +47 -47
  110. package/packages/cad-styling/src/TreeIndexNodeCollection.d.ts +23 -23
  111. package/packages/cad-styling/src/UnionNodeCollection.d.ts +15 -15
  112. package/packages/camera-manager/index.d.ts +4 -4
  113. package/packages/camera-manager/src/ComboControls.d.ts +84 -83
  114. package/packages/camera-manager/src/Keyboard.d.ts +14 -14
  115. package/packages/data-source/index.d.ts +6 -0
  116. package/packages/data-source/src/CdfDataSource.d.ts +19 -0
  117. package/packages/data-source/src/DataSource.d.ts +26 -0
  118. package/packages/data-source/src/LocalDataSource.d.ts +15 -0
  119. package/packages/logger/index.d.ts +5 -5
  120. package/packages/logger/src/Log.d.ts +5 -5
  121. package/packages/metrics/index.d.ts +5 -0
  122. package/packages/metrics/src/MetricsLogger.d.ts +21 -0
  123. package/packages/metrics/src/types.d.ts +7 -0
  124. package/packages/modeldata-api/index.d.ts +13 -8
  125. package/packages/modeldata-api/src/{CdfModelDataClient.d.ts → CdfModelDataProvider.d.ts} +15 -17
  126. package/packages/modeldata-api/src/CdfModelIdentifier.d.ts +17 -0
  127. package/packages/modeldata-api/src/CdfModelMetadataProvider.d.ts +19 -36
  128. package/packages/modeldata-api/src/CdfModelOutputsProvider.d.ts +15 -0
  129. package/packages/modeldata-api/src/{LocalModelDataClient.d.ts → LocalModelDataProvider.d.ts} +9 -10
  130. package/packages/modeldata-api/src/LocalModelIdentifier.d.ts +14 -0
  131. package/packages/modeldata-api/src/LocalModelMetadataProvider.d.ts +14 -19
  132. package/packages/modeldata-api/src/Model3DOutputList.d.ts +17 -17
  133. package/packages/modeldata-api/src/ModelIdentifier.d.ts +12 -0
  134. package/packages/modeldata-api/src/ModelMetadataProvider.d.ts +17 -0
  135. package/packages/modeldata-api/src/applyDefaultModelTransformation.d.ts +6 -6
  136. package/packages/modeldata-api/src/types.d.ts +41 -55
  137. package/packages/modeldata-api/src/utilities.d.ts +7 -7
  138. package/packages/nodes-api/index.d.ts +6 -7
  139. package/packages/nodes-api/src/NodesApiClient.d.ts +52 -43
  140. package/packages/nodes-api/src/NodesCdfClient.d.ts +24 -19
  141. package/packages/nodes-api/src/NodesLocalClient.d.ts +30 -25
  142. package/packages/nodes-api/src/types.d.ts +10 -14
  143. package/packages/rendering/index.d.ts +17 -0
  144. package/packages/{cad-geometry-loaders/src/material-manager → rendering/src}/CadMaterialManager.d.ts +37 -37
  145. package/packages/{cad-geometry-loaders → rendering}/src/InstancedMeshManager.d.ts +20 -20
  146. package/packages/{cad-geometry-loaders → rendering}/src/cameraconfig.d.ts +12 -12
  147. package/packages/{cad-geometry-loaders/src/material-manager → rendering/src}/rendering/EffectRenderManager.d.ts +99 -83
  148. package/packages/{cad-geometry-loaders/src/material-manager/styling → rendering/src/rendering}/NodeAppearanceTextureBuilder.d.ts +51 -50
  149. package/packages/{cad-parsers/src/cad → rendering/src/rendering}/RenderMode.d.ts +15 -15
  150. package/packages/{cad-geometry-loaders/src/material-manager → rendering/src}/rendering/createSimpleGeometryMesh.d.ts +6 -6
  151. package/packages/{cad-parsers/src/cad → rendering/src/rendering}/matCapTextureData.d.ts +5 -5
  152. package/packages/{cad-parsers/src/cad → rendering/src/rendering}/materials.d.ts +23 -23
  153. package/packages/{cad-parsers/src/cad → rendering/src/rendering}/primitives.d.ts +12 -12
  154. package/packages/{cad-parsers/src/cad → rendering/src/rendering}/shaders.d.ts +101 -101
  155. package/packages/{cad-geometry-loaders/src/material-manager → rendering/src}/rendering/types.d.ts +76 -76
  156. package/packages/{cad-geometry-loaders/src → rendering/src/sector}/CadNode.d.ts +54 -54
  157. package/packages/{cad-geometry-loaders/src/material-manager/styling → rendering/src/transform}/NodeTransformProvider.d.ts +13 -13
  158. package/packages/{cad-geometry-loaders/src/material-manager/styling → rendering/src/transform}/NodeTransformTextureBuilder.d.ts +23 -23
  159. package/packages/{cad-geometry-loaders/src/material-manager/styling → rendering/src/transform}/TransformOverrideBuffer.d.ts +21 -21
  160. package/packages/rendering/src/utilities/types.d.ts +26 -0
  161. package/packages/tools/index.d.ts +15 -12
  162. package/packages/tools/src/AxisView/AxisViewTool.d.ts +32 -32
  163. package/packages/tools/src/AxisView/types.d.ts +98 -98
  164. package/packages/tools/src/Cognite3DViewerToolBase.d.ts +25 -25
  165. package/packages/tools/src/DebugCameraTool.d.ts +20 -20
  166. package/packages/tools/src/DebugLoadedSectorsTool.d.ts +23 -23
  167. package/packages/tools/src/ExplodedViewTool.d.ts +12 -12
  168. package/packages/tools/src/Geomap/Geomap.d.ts +14 -14
  169. package/packages/tools/src/Geomap/GeomapTool.d.ts +21 -21
  170. package/packages/tools/src/Geomap/MapConfig.d.ts +195 -195
  171. package/packages/tools/src/HtmlOverlay/BucketGrid2D.d.ts +28 -0
  172. package/packages/tools/src/HtmlOverlay/HtmlOverlayTool.d.ts +159 -0
  173. package/packages/tools/src/Timeline/Keyframe.d.ts +38 -0
  174. package/packages/tools/src/Timeline/TimelineTool.d.ts +79 -0
  175. package/packages/tools/src/Timeline/types.d.ts +13 -0
  176. package/packages/tools/src/types.d.ts +4 -4
  177. package/packages/utilities/index.d.ts +24 -24
  178. package/packages/utilities/src/CameraConfiguration.d.ts +10 -10
  179. package/packages/utilities/src/IndexSet.d.ts +1 -1
  180. package/packages/utilities/src/NumericRange.d.ts +21 -21
  181. package/packages/utilities/src/RandomColors.d.ts +34 -0
  182. package/packages/utilities/src/WebGLRendererStateHelper.d.ts +15 -15
  183. package/packages/utilities/src/assertNever.d.ts +7 -7
  184. package/packages/utilities/src/cache/MemoryRequestCache.d.ts +22 -22
  185. package/packages/utilities/src/cache/MostFrequentlyUsedCache.d.ts +19 -19
  186. package/packages/utilities/src/cache/RequestCache.d.ts +13 -13
  187. package/packages/utilities/src/datastructures/DynamicDefragmentedBuffer.d.ts +22 -22
  188. package/packages/utilities/src/determinePowerOfTwoDimensions.d.ts +11 -11
  189. package/packages/utilities/src/disposeAttributeArrayOnUpload.d.ts +17 -17
  190. package/packages/utilities/src/events/EventTrigger.d.ts +13 -13
  191. package/packages/utilities/src/events/clickOrTouchEventOffset.d.ts +13 -13
  192. package/packages/utilities/src/events/index.d.ts +5 -5
  193. package/packages/utilities/src/indexset/IndexSet.d.ts +26 -26
  194. package/packages/utilities/src/indexset/IntermediateIndexNode.d.ts +26 -26
  195. package/packages/utilities/src/indexset/LeafIndexNode.d.ts +16 -16
  196. package/packages/utilities/src/isMobileOrTablet.d.ts +4 -4
  197. package/packages/utilities/src/networking/isTheSameDomain.d.ts +11 -11
  198. package/packages/utilities/src/objectTraversal.d.ts +8 -8
  199. package/packages/utilities/src/packFloat.d.ts +6 -6
  200. package/packages/utilities/src/revealEnv.d.ts +10 -10
  201. package/packages/utilities/src/three/AutoDisposeGroup.d.ts +17 -17
  202. package/packages/utilities/src/three/BoundingBoxLOD.d.ts +27 -27
  203. package/packages/utilities/src/three/getBox3CornerPoints.d.ts +5 -5
  204. package/packages/utilities/src/transformCameraConfiguration.d.ts +6 -6
  205. package/packages/utilities/src/types.d.ts +10 -10
  206. package/packages/utilities/src/workers/WorkerPool.d.ts +14 -14
  207. package/tools.d.ts +7 -7
  208. package/tools.js +70 -123
  209. package/tools.map +1 -1
  210. package/packages/tools/src/HtmlOverlayTool.d.ts +0 -88
  211. package/packages/utilities/src/metrics.d.ts +0 -15
package/tools.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap","webpack:///external \"three\"","webpack:///./packages/utilities/src/objectTraversal.ts","webpack:///./packages/utilities/src/transformCameraConfiguration.ts","webpack:///./packages/utilities/src/events/clickOrTouchEventOffset.ts","webpack:///./packages/utilities/src/events/EventTrigger.ts","webpack:///./packages/utilities/src/assertNever.ts","webpack:///./packages/utilities/src/NumericRange.ts","webpack:///./packages/utilities/src/determinePowerOfTwoDimensions.ts","webpack:///./packages/utilities/src/indexset/IntermediateIndexNode.ts","webpack:///./packages/utilities/src/indexset/LeafIndexNode.ts","webpack:///./packages/utilities/src/indexset/IndexSet.ts","webpack:///./packages/utilities/src/packFloat.ts","webpack:///./packages/utilities/src/datastructures/DynamicDefragmentedBuffer.ts","webpack:///./packages/utilities/src/three/AutoDisposeGroup.ts","webpack:///./packages/utilities/src/three/BoundingBoxLOD.ts","webpack:///./packages/utilities/src/three/getBox3CornerPoints.ts","webpack:///./packages/utilities/src/isMobileOrTablet.ts","webpack:///./packages/utilities/src/WebGLRendererStateHelper.ts","webpack:///./packages/utilities/src/revealEnv.ts","webpack:///./packages/utilities/src/workers/WorkerPool.ts","webpack:///./packages/utilities/src/networking/isTheSameDomain.ts","webpack:///./packages/utilities/src/cache/MemoryRequestCache.ts","webpack:///./packages/utilities/src/cache/MostFrequentlyUsedCache.ts","webpack:///./packages/utilities/src/metrics.ts","webpack:///./packages/utilities/src/disposeAttributeArrayOnUpload.ts","webpack:///external \"rxjs/operators\"","webpack:///external \"glslify\"","webpack:///external \"rxjs\"","webpack:///./packages/cad-styling/src/NodeAppearance.ts","webpack:///./packages/cad-styling/src/NodeCollectionBase.ts","webpack:///./packages/cad-styling/src/CombineNodeCollectionBase.ts","webpack:///./packages/cad-styling/src/UnionNodeCollection.ts","webpack:///./packages/cad-styling/src/IntersectionNodeCollection.ts","webpack:///./packages/cad-styling/src/TreeIndexNodeCollection.ts","webpack:///./packages/cad-styling/src/NodeAppearanceProvider.ts","webpack:///external \"assert\"","webpack:///./packages/cad-geometry-loaders/src/sector/SectorNode.ts","webpack:///./packages/cad-geometry-loaders/src/sector/RootSectorNode.ts","webpack:///./packages/cad-geometry-loaders/src/InstancedMeshManager.ts","webpack:///./packages/cad-geometry-loaders/src/CadNode.ts","webpack:///./packages/cad-geometry-loaders/src/cameraconfig.ts","webpack:///./packages/cad-parsers/src/cad/primitiveGeometries.ts","webpack:///./packages/cad-parsers/src/cad/computeBoundingBoxFromAttributes.ts","webpack:///./packages/cad-parsers/src/cad/filterPrimitives.ts","webpack:///./packages/cad-parsers/src/cad/primitives.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/rendering/triangleMeshes.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/rendering/createSimpleGeometryMesh.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/rendering/filterInstanceMesh.ts","webpack:///./packages/cad-geometry-loaders/src/sector/sectorUtilities.ts","webpack:///./packages/cad-geometry-loaders/src/utilities/float32BufferToMatrix.ts","webpack:///./packages/cad-geometry-loaders/src/sector/SimpleAndDetailedToSector3D.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/styling/NodeTransformProvider.ts","webpack:///./packages/cad-geometry-loaders/src/utilities/groupMeshesByNumber.ts","webpack:///./packages/cad-geometry-loaders/src/utilities/arrays.ts","webpack:///./packages/cad-geometry-loaders/src/sector/CachedRepository.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/rendering/types.ts","webpack:///./packages/cad-geometry-loaders/src/utilities/types.ts","webpack:///./packages/cad-parsers/src/cad/shaders.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/rendering/EffectRenderManager.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/styling/NodeAppearanceTextureBuilder.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/styling/TransformOverrideBuffer.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/styling/NodeTransformTextureBuilder.ts","webpack:///./packages/cad-parsers/src/cad/matCapTextureData.ts","webpack:///./packages/cad-parsers/src/cad/materials.ts","webpack:///./packages/cad-geometry-loaders/src/material-manager/CadMaterialManager.ts","webpack:///./packages/cad-geometry-loaders/src/utilities/rxOperations.ts","webpack:///./packages/cad-geometry-loaders/src/sector/rxSectorUtilities.ts","webpack:///./packages/cad-geometry-loaders/src/utilities/PromiseUtils.ts","webpack:///./packages/cad-geometry-loaders/src/sector/SectorLoader.ts","webpack:///./packages/cad-geometry-loaders/src/CadModelSectorBudget.ts","webpack:///./packages/cad-geometry-loaders/src/sector/ModelStateHandler.ts","webpack:///./packages/cad-geometry-loaders/src/CadModelUpdateHandler.ts","webpack:///./packages/cad-geometry-loaders/src/sector/culling/OrderSectorsByVisibilityCoverage.ts","webpack:///./packages/cad-geometry-loaders/src/sector/culling/types.ts","webpack:///./packages/cad-geometry-loaders/src/sector/culling/TakenSectorTree.ts","webpack:///./packages/cad-geometry-loaders/src/sector/culling/ByVisibilityGpuSectorCuller.ts","webpack:///./packages/logger/src/Log.ts","webpack:///./packages/logger/index.ts","webpack:///external \"mixpanel-browser\"","webpack:///external \"@tweenjs/tween.js\"","webpack:///./core/src/utilities/worldToViewport.ts","webpack:///external \"lodash/cloneDeep\"","webpack:///external \"geo-three\"","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/instanced.frag","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/instanced.vert","webpack:///./core/src/utilities/BoundingBoxClipper.ts","webpack:///./packages/cad-parsers/src/glsl/post-processing/passthrough.vert","webpack:///./core/src/utilities/index.ts","webpack:///external \"comlink\"","webpack:///external \"loglevel\"","webpack:///external \"lodash/throttle\"","webpack:///external \"lodash/chunk\"","webpack:///./packages/cad-parsers/src/glsl/sector/simple.frag","webpack:///./packages/cad-parsers/src/glsl/sector/simple.vert","webpack:///./packages/cad-parsers/src/glsl/sector/mesh.frag","webpack:///./packages/cad-parsers/src/glsl/sector/mesh.vert","webpack:///./packages/cad-parsers/src/glsl/sector/instancedMesh.frag","webpack:///./packages/cad-parsers/src/glsl/sector/instancedMesh.vert","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/circle.frag","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/circle.vert","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/cone.frag","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/cone.vert","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/eccentricCone.frag","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/eccentricCone.vert","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/ellipsoidSegment.frag","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/ellipsoidSegment.vert","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/generalCylinder.frag","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/generalCylinder.vert","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/generalring.frag","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/generalring.vert","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/torusSegment.frag","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/torusSegment.vert","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/trapezium.frag","webpack:///./packages/cad-parsers/src/glsl/sector/primitives/trapezium.vert","webpack:///./packages/cad-parsers/src/glsl/post-processing/outline-detect-combine.frag","webpack:///./packages/cad-parsers/src/glsl/post-processing/outline-detection.vert","webpack:///./packages/cad-parsers/src/glsl/post-processing/fxaa.frag","webpack:///./packages/cad-parsers/src/glsl/post-processing/fxaa.vert","webpack:///./packages/cad-parsers/src/glsl/post-processing/pure-depth-ssao.frag","webpack:///./packages/cad-parsers/src/glsl/post-processing/ssao-blur-combine.frag","webpack:///./packages/cad-parsers/src/glsl/sector/sectorCoverage.frag","webpack:///./packages/cad-parsers/src/glsl/sector/sectorCoverage.vert","webpack:///external \"lodash/merge\"","webpack:///./packages/cad-parsers/src/cad/LevelOfDetail.ts","webpack:///./packages/cad-parsers/src/cad/RenderMode.ts","webpack:///./packages/tools/src/Cognite3DViewerToolBase.ts","webpack:///./packages/tools/src/HtmlOverlayTool.ts","webpack:///./packages/tools/src/ExplodedViewTool.ts","webpack:///./packages/tools/src/DebugCameraTool.ts","webpack:///./packages/tools/src/AxisView/types.ts","webpack:///./packages/tools/src/AxisView/AxisViewTool.ts","webpack:///./packages/tools/src/Geomap/MapConfig.ts","webpack:///./packages/tools/src/Geomap/Geomap.ts","webpack:///./packages/tools/src/Geomap/GeomapTool.ts","webpack:///./packages/tools/src/DebugLoadedSectorsTool.ts"],"names":["root","factory","exports","module","define","amd","a","i","self","this","installedModules","__webpack_require__","moduleId","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","require","traverseDepthFirst","visitor","children","length","transformCameraConfiguration","cameraConfiguration","modelMatrix","undefined","position","target","applyMatrix4","clickOrTouchEventOffset","ev","rect","getBoundingClientRect","MouseEvent","offsetX","clientX","left","offsetY","clientY","top","changedTouches","touch","EventTrigger","_listeners","listener","push","index","indexOf","splice","args","forEach","assertNever","x","message","Error","NumericRange","from","count","toInclusive","Array","values","other","range","intersects","createFromInterval","Math","max","min","action","determinePowerOfTwoDimensions","elementCount","width","ceilToPowerOfTwo","sqrt","height","log2","log","v","pow","ceil","right","maxSubtreeDepth","r0","r1","balance","traverse","contains","intersectsOrCoinciding","newNode","addRange","fromIndexNodesAndBalance","canUnionLeft","canUnionRight","newLeft","leftRange","soak","newRight","rightRange","unioned","union","newThis","soakedRange","nodeToReturn","leftSubTreeSize","rightSubTreeSize","rotateSmallerRight","rotateRight","rotateSmallerLeft","rotateLeft","clone","node","isInside","hasIntersectionWith","leftRes","rightRes","unionRange","nextRoot","begin","endInclusive","rootNode","add","removeRange","ranges","forEachRange","result","num","arr","toIndexArray","Set","originalRanges","toRangeArray","newRanges","otherSet","leftBoundRange","rightBoundRange","invertedRanges","st","packFloatInto","f","targetBuffer","offset","F","abs","Sign","step","Exponent","floor","Mantissa","exp2","mod","edge","y","DynamicDefragmentedBuffer","initialSize","type","_numFilled","_batchIdCounter","_batchMap","Map","_type","minimalPowerOfTwo","_buffer","array","isReallocated","newSize","allocateNewBuffer","set","batchId","createBatch","bufferIsReallocated","batch","copyWithin","buffer","_currentTail","prev","next","currentBatch","delete","newBuffer","emptyGeometry","_isDisposed","_referenceCount","ensureNotDisposed","dispose","meshes","filter","map","mesh","geometry","updateVars","camPos","bounds","boundingBox","super","_activeLevel","_levels","isLOD","autoUpdate","_boundingBox","copy","distance","sort","b","visible","camera","updateCurrentLevel","levels","matrixWorld","cameraZoom","zoom","setFromMatrixPosition","distanceToCamera","distanceToPoint","findIndex","getBox3CornerPoints","box","z","isMobileOrTablet","check","navigator","userAgent","vendor","window","opera","test","substr","renderer","_originalState","_renderer","color","alpha","clearColor","getClearColor","clearAlpha","getClearAlpha","setClearColor","size","getSize","setSize","enabled","localClippingEnabled","autoClear","renderTarget","getRenderTarget","setRenderTarget","revealEnv","publicPath","workerList","numberOfWorkers","determineNumberOfWorkers","newWorker","worker","createWorker","activeJobCount","messageIdCounter","async","actualWorkerVersion","getVersion","e","minWorkerVersion","majorMin","minorMin","patchMin","split","parseInt","majorWorker","minorWorker","patchWorker","errorMessage","checkWorkerVersion","catch","error","workerObjUrl","URL","revokeObjectURL","_defaultPool","workerUrl","options","url1","url2","location","origin","isRelative","url","match","constructedURLs","startsWith","host","console","isTheSameDomain","Worker","blob","Blob","JSON","stringify","createObjectURL","work","targetWorker","reduce","bestWorker","candidate","hardwareConcurrency","TimestampedContainer","_value","_lastAccessTime","Date","now","MemoryRequestCache","maxElementsInCache","removeCallback","defaultCleanupCount","_data","_maxElementsInCache","_defaultCleanupCount","_removeCallback","id","has","data","isFull","cleanCache","insert","allResults","entries","lastAccessTime","entry","pop","remove","clear","MostFrequentlyUsedCache","capacity","disposeCallback","_cache","_retrieves","_capacity","_disposeCallback","retrieveCount","ensureWithinCapacity","keysForRemoval","keys","retrivalCount","slice","VERSION","MIXPANEL_TOKEN","globalLogMetrics","globalProps","project","application","sessionId","replace","random","toString","initMetrics","logMetrics","applicationId","eventProps","init","disable_cookie","disable_persistence","ip","property_blacklist","reset","identify","trackEvent","eventName","combined","track","trackLoadModel","modelIdentifier","trackError","stack","trackCameraNavigation","disposeAttributeArrayOnUpload","NodeOutlineColor","classToken","_changedEvent","_classToken","event","subscribe","unsubscribe","fire","nodeCollections","_cachedCombinedIndexSet","_nodeCollections","_changedUnderlyingNodeCollectionHandler","makeDirty","nodeCollection","on","off","collection","notifyChanged","createCombinedIndexSet","some","isLoading","token","state","subCollections","serialize","getIndexSet","unionWith","intersectWith","_treeIndices","treeIndices","OutlinedAppearance","outlineColor","White","InFrontAppearance","renderInFront","DefaultNodeAppearance","Default","renderGhosted","NoOutline","Outlined","Hidden","InFront","Ghosted","Highlighted","_styledCollections","_events","changed","loadingStateChanged","appearance","existingCollection","find","handleNodeCollectionChanged","styledCollection","handleNodeCollectionChangedListener","applyCb","styledSet","_lastFiredLoadingState","_styledSet","notifyLoadingStateChanged","sectorId","sectorPath","_lod","LevelOfDetail","Discarded","_updatedTimestamp","depth","path","determineSectorDepth","_group","geomtryGroup","levelOfDetail","resetGeometry","reference","updateMatrixWorld","dereference","modelMetadata","modelBounds","scene","sectorNodeMap","buildScene","sector","parent","sectorGroup","matrixAutoUpdate","child","setModelTransformation","matrix","out","instancedMeshGroup","materialManager","_materialManager","_instancedGeometryMap","_instancedAttributeMap","_processedSectorMap","_instancedMeshGroup","meshFile","fileId","vertices","indices","geometryAttributes","material","getModelMaterials","instancedMesh","instance","instances","instanceIdentifier","triangleOffset","currentAttributes","treeAdd","treeIndexBuffer","colorAdd","colorBuffer","colors","matrixAdd","instanceMatrixBuffer","instanceMatrices","updateAttributes","addBatchDescriptor","recreateBufferGeometry","createInstance","sectorBatchDescriptors","sectorBatchDescriptor","attributeBuffers","treeIndicesbatchId","colorsBatchId","instanceMatricesBatchId","instanceGeometry","setIndex","setAttribute","treeIndexAttribute","colorAttribute","instanceMatrixInterleavedBuffer","column","attribute","needsUpdate","bufferGeometry","updateAttributesCallback","createInstancedBufferGeometry","setDrawRange","triangleCount","dynamicTreeIndicesBuffer","Float32Array","treeIndicesAdd","dynamicColorsBuffer","Uint8Array","colorsAdd","dynamicinstanceMatricesBuffer","instanceMatricesAdd","instanceMesh","frustumCulled","treeIndicesBatchId","batchDescriptor","descriptorList","model","_previousCameraMatrix","_instancedMeshManager","rootSector","_cadModelMetadata","_sectorScene","elements","Infinity","_rootSector","getModelNodeTransformProvider","getModelNodeAppearanceProvider","getModelDefaultNodeAppearance","setModelDefaultNodeAppearance","clippingPlanes","planes","setRenderMode","getRenderMode","getModelTransformation","near","far","averageMin","averageMax","divideScalar","getCenter","extent","addVectors","distanceTo","suggestCameraConfig","threePos","threeTarget","instanceMeshFiles","instanceMeshFile","addInstanceMeshes","removeSectorInstancedMeshes","boxGeometry","boxGeometryBoundingBox","getIndex","getAttribute","normal","computeBoundingBox","quadGeometry","quadGeometryBoundingBox","trapeziumGeometry","trapeziumGeometryBoundingBox","Uint16Array","setFromArray","coneGeometry","coneGeometryBoundingBox","positions","torusLodGeometries","torusGeometryBoundingBox","transformFunc","u","PI","tubularSegments","radialSegments","segmentsX","segmentsY","segmentsXInv","segmentsYInv","j","generatePlane3D","nutGeometry","nutGeometryBoundingBox","makeRotationX","computeBoundingBoxFromCenterAndRadiusAttributesVars","centerA","centerB","sphere","computeBoundingBoxFromVertexAttributesVars","vertex1","vertex2","vertex3","vertex4","computeBoundingBoxFromInstanceMatrixAttributesVars","instanceMatrix","computeBoundingBoxFromEllipseAttributesVars","center","filterPrimitivesOutsideClipBox","attributesByteValues","attributes","clipBox","getBoundsOfElementsCallback","elementSize","attributeFloatValues","instanceBbox","filteredByteValues","filteredCount","intersectsBox","elementValues","subarray","filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix","baseBox","geometryClipBox","instanceMatrixAttribute","outBox","elementIndex","baseBoundingBox","BYTES_PER_ELEMENT","computeBoundingBoxFromInstanceMatrixAttributes","filterPrimitivesOutsideClipBoxByCenterAndRadius","radiusAattributeName","radiusBattributeName","centerAattribute","centerBattribute","radiusAattribute","radiusBattribute","readAttribute","idx","radiusA","radiusB","getBoundingBox","expandByPoint","computeBoundingBoxFromCenterAndRadiusAttributes","filterPrimitivesOutsideClipBoxByVertices","vertex1attribute","vertex2attribute","vertex3attribute","vertex4attribute","vertex1Attribute","vertex2Attribute","vertex3Attribute","vertex4Attribute","setFromPoints","computeBoundingBoxFromVertexAttributes","filterPrimitivesOutsideClipBoxByEllipse","radius1AttributeName","radius2AttributeName","centerAttribute","horizontalRadiusAttribute","verticalRadiusAttribute","heightAttribute","radius1Attribute","radius2Attribute","radius1","radius2","setFromCenterAndSize","computeBoundingBoxFromEllipseAttributes","createPrimitives","materials","sectorBounds","primitives","hasAny","boxCollection","boxAttributes","filteredCollection","setAttributes","setBoundsFromInstanceMatrices","onBeforeRender","updateMaterialInverseModelMatrix","createBoxes","circleCollection","circleAttributes","createCircles","circle","coneCollection","coneAttributes","setBoundsFromBox","createCones","cone","eccentricConeCollection","eccentericConeCollection","eccentericConeAttributes","createEccentricCones","eccentricConeAttributes","eccentricCone","ellipsoidSegmentCollection","ellipsoidSegmentAttributes","createEllipsoidSegments","ellipsoidSegment","generalCylinderCollection","cylinders","generalCylinderAttributes","createGeneralCylinders","generalCylinder","generalRingCollection","generalRingAttributes","createGeneralRings","generalRing","quadCollection","quadAttributes","createQuads","quad","sphericalSegmentCollection","sphericalSegmentAttributes","createSphericalSegments","sphericalSegment","torusSegmentCollection","torusSegmentAttributes","biggestTorus","collectionStride","sum","element","numberOfTorusSegments","biggest","collectionView","DataView","sizeAttributeOffset","getFloat32","getBiggestTorusSize","lod","boundingSphere","level","torus","determineBoundsFromInstanceMatrices","setBoundingBox","addLevel","calcLODDistance","createTorusSegments","torusSegment","trapeziumCollection","trapeziumAttributes","bbox","setBoundsFromVertexAttributesVars","makeEmpty","getX","getY","getZ","getBoundingSphere","setBoundsFromVertexAttributes","createTrapeziums","trapezium","nutCollection","nutAttributes","createNuts","nut","attributesByteSize","matrixAttribute","columnAttribute","splitMatrix","interleavedBuffer8","interleavedBuffer32","is8BitAttribute","interleavedBuffer","onAfterRender","instanceCount","treeIndexAttributeOffset","userData","setTreeIndeciesToUserData","lodLevel","uniforms","inverseModelMatrix","invert","setBoundingSphereFromVerticesVars","instanceBoundingBox","positionAttribute","matCol0Attribute","matCol1Attribute","matCol2Attribute","matCol3Attribute","getW","createTriangleMeshes","triangleMeshes","filteredTriangleMeshes","isTriangleMeshWithinArgs","isTriangleMeshWithin","onUpload","obj","quadVertexData","quadVertexBufferAttribute","primitiveAttributes","filterInstanceMeshVars","baseBounds","instanceBounds","consumeSectorSimple","group","byteLength","sectorMeshes","instancedMeshes","attributeValues","filteredAttributeValues","treeIndex","matrix0","matrix1","matrix2","matrix3","simple","setTreeIndicesToUserData","createSimpleGeometryMesh","consumeSectorDetailed","metadata","containsBox","primitiveRoot","triangleMesh","instanceMeshes","filteredMeshes","v0","v1","v2","filteredOffset","filteredInstanceMatrices","filteredTreeIndices","filteredColors","indexOffset","elementInstanceMatrix","elementColor","elementTreeIndex","filterInstanceMesh","Promise","resolve","identityTransform","identity","transform","groupMeshesByNumber","groupedByFileId","last","lastIndexOf","meshIndices","sortedArray","firstSearchIndex","elementValueOf","low","high","res","mid","elementValue","createOffsetsArray","offsets","_","modelSectorProvider","modelDataParser","modelDataTransformer","_modelSectorProvider","_modelDataParser","_modelDataTransformer","_consumedSectorCache","consumedSector","_ctmFileCache","cacheKey","wantedSectorCacheKey","Detailed","consumed","loadDetailedSectorFromNetwork","forceInsert","Simple","loadSimpleSectorFromNetwork","methodName","moduleName","wantedSector","getBinaryFile","modelBaseUrl","facesFile","fileName","parseF3D","transformed","transformSimpleSector","filename","parseI3D","ctmFilenames","ctms","all","loadCtmFileFromNetwork","indexFile","i3dPromise","loadI3DFromNetwork","ctmsPromise","loadCtmsFromNetwork","peripheralFiles","i3d","finalizeDetailed","transformDetailedSector","ctmFileCacheKey","cached","ctmPromise","then","parseCTM","i3dFile","ctmFiles","finalTriangleMeshes","fileIds","triangleCounts","finalMeshes","fileTriangleCounts","normals","sharedColors","sharedTreeIndices","meshIdx","triOffset","triCount","g","triIdx","vIdx","finalInstanceMeshes","triangleOffsets","ctm","fileTriangleOffsets","Float64Array","fileMeshIndices","treeIndicesBuffer","treeIndexToNodeIdMap","nodeIdToTreeIndexMap","AntiAliasingMode","SsaoSampleQuality","defaultRenderOptions","antiAliasing","FXAA","multiSampleCountHint","ssaoRenderParameters","sampleSize","sampleRadius","depthCheckBias","edgeDetectionParameters","CogniteColors","Black","Cyan","Blue","Purple","Pink","Orange","Yellow","VeryLightGray","LightGray","RevealColors","Red","Green","shaderDefines","defines","COGNITE_COLOR_BY_TREE_INDEX","sectorShaders","simpleMesh","fragment","default","vertex","detailedMesh","boxPrimitive","circlePrimitive","conePrimitive","eccentricConePrimitive","ellipsoidSegmentPrimitive","generalCylinderPrimitive","generalRingPrimitive","nutPrimitive","quadPrimitive","torusSegmentPrimitive","trapeziumPrimitive","outlineDetectionShaders","fxaaShaders","ssaoShaders","ssaoBlurCombineShaders","coverageShaders","_lastFrameSceneState","hasBackElements","hasInFrontElements","hasGhostElements","hasCustomObjects","_rootSectorNodeBuffer","_outlineTexelSize","_autoSetTargetSize","_uiObjects","_renderOptions","_orthographicCamera","_renderTarget","_originalScene","_cadScene","_normalScene","_inFrontScene","_compositionScene","_fxaaScene","_ssaoScene","_ssaoBlurScene","_emptyScene","isWebGL2","capabilities","outlineColorTexture","createOutlineColorTexture","_inFrontRenderedCadModelTarget","createRenderTarget","stencilBuffer","depthTexture","format","_normalRenderedCadModelTarget","_ghostObjectRenderTarget","_customObjectRenderTarget","_compositionTarget","_ssaoTarget","_ssaoBlurTarget","_combineOutlineDetectionMaterial","vertexShader","fragmentShader","tFront","texture","tFrontDepth","tBack","tBackDepth","tCustom","tCustomDepth","tGhost","tGhostDepth","tOutlineColors","resolution","texelSize","cameraNear","cameraFar","edgeStrengthMultiplier","edgeGrayScaleIntensity","extensions","fragDepth","EDGES","noiseTexture","createNoiseTexture","ssaoParameters","numberOfSamples","sampleKernel","createKernel","_ssaoMaterial","tDepth","tNoise","kernel","bias","projMatrix","inverseProjectionMatrix","MAX_KERNEL_SIZE","_ssaoBlurMaterial","tDiffuse","tAmbientOcclusion","diffuseTexture","supportsSsao","_fxaaMaterial","inverseResolution","setupCompositionScene","setupSsaoScene","setupSsaoBlurCombineScene","setupFxaaScene","_normalSceneBuilder","TemporarySceneBuilder","_inFrontSceneBuilder","inputSsaoOptions","setSsaoParameters","screenPos","filteredObject","renderOptions","None","original","renderMode","renderStateHelper","RenderMode","DepthBufferOnly","setVisibilityOfSectors","traverseForRootSectorNode","extractCadNodes","clearTarget","splitToScenes","renderNormalCadModelsFromBaseScene","renderNormalCadModels","restoreOriginalScene","renderInFrontCadModels","resetState","restoreCadNodes","info","autoReset","updateRenderSize","setClearAlpha","lastFrameSceneState","renderGhostedCadModelsFromBaseScene","renderCustomObjects","explicitFlushRender","antiAliasingMode","renderComposition","renderSsao","renderPostProcessStep","NoAA","autoSize","render","rootSectorNodeData","cadNode","backSet","getModelBackTreeIndices","cadModelMetadata","infrontSet","getModelInFrontTreeIndices","ghostSet","getModelGhostedTreeIndices","backRoot","infrontRoot","objectStack","objectTreeIndices","addElement","populateTemporaryScene","Effects","Ghost","renderSize","params","defaultSsaoParameters","canvasSize","domElement","clientWidth","clientHeight","downSampleFactor","uiObject","renderScene","viewportRenderPos","multiply","viewportRenderWidth","viewportRenderHeight","setViewport","clearDepth","projectionMatrixInverse","projectionMatrix","outlineColorBuffer","setOutlineColor","image","createRenderTriangle","stride","wrapS","wrapT","kernelSize","sample","normalize","scale","lerp","multiplyScalar","value1","value2","amount","uvs","rt","samples","outlineTextureData","colorIndex","temporaryScene","temporaryModelRootElement","sceneParent","treeIndexCount","styleProvider","_defaultAppearance","_handleStylesChangedListener","handleStylesChanged","_needsUpdate","_allTreeIndices","_styleProvider","textures","textureElementCount","overrideColorPerTreeIndexTexture","Uint8ClampedArray","transformOverrideIndexBuffer","transformOverrideIndexTexture","allocateTextures","_overrideColorPerTreeIndexTexture","_overrideColorDefaultAppearanceRgba","_regularNodesTreeIndices","_ghostedNodesTreeIndices","_infrontNodesTreeIndices","setDefaultAppearance","rgbaBuffer","style","appearanceToColorOverride","fillRGBA","rgba","populateTexture","populateNodeSets","applyStyles","fullStyle","applyStyleToNodes","rangeStart","inFront","ghosted","commitRange","toExclusive","treeIndexRange","updateRgbBitmask","keepRgbBitmask","updateR","updateG","updateB","updateAlphaBitmask","keepAlphaBitmask","updateAlpha","combineRGBA","Number","onGenerateNewDataTexture","_textureBuffer","MIN_NUMBER_OF_TREE_INDICES","NUMBER_OF_ELEMENTS_PER_MATRIX","BYTES_PER_FLOAT","_dataTexture","_onGenerateNewDataTextureCallback","_unusedIndices","_treeIndexToOverrideIndex","transformBuffer","toArray","matrixIndex","recomputeDataTexture","byteIndex","matrixElement","currentTextureBufferLength","newTextureBuffer","textureDims","newDataTexture","numberOfNewTreeIndices","transformProvider","_handleTransformChangedBound","handleTransformChanged","_transformOverrideIndexTexture","_transformOverrideBuffer","handleNewTransformTexture","_transformProvider","dataTexture","transformIndex","addOverrideTransform","setOverrideIndex","removeOverrideTransform","change","setNodeTransform","resetNodeTransform","Image","src","updateDefinesAndUniforms","overrideColorPerTreeIndex","transformOverrideTexture","matCapTexture","treeIndexTextureSize","transformOverrideTextureSize","oldUniforms","setValues","colorDataTexture","uniformsNeedUpdate","materialsChanged","_renderMode","Color","materialsMap","_clippingPlanes","updateClippingPlanesForModel","triggerMaterialsChanged","maxTreeIndex","nodeAppearanceProvider","nodeAppearanceTextureBuilder","build","nodeTransformProvider","nodeTransformTextureBuilder","updateMaterialsCallback","updateMaterials","leading","trailing","updateTransformsCallback","updateTransforms","transformOverrideLookupTexture","boxMaterial","clipping","side","transparent","circleMaterial","nutMaterial","quadMaterial","generalRingMaterial","coneMaterial","eccentricConeMaterial","ellipsoidSegmentMaterial","generalCylinderMaterial","trapeziumMaterial","torusSegmentMaterial","derivatives","sphericalSegmentMaterial","triangleMeshMaterial","allMaterials","createMaterials","overrideTransformIndexTexture","transformLookupTexture","perModelClippingPlanes","getModelMaterialsWrapper","getDefaultAppearance","materialWrapper","addModelMaterials","applyToModelMaterials","clipIntersection","defaultAppearance","regularNodeTreeIndices","infrontNodeTreeIndices","ghostedNodeTreeIndices","colorWrite","applyToAllMaterials","wrapper","transformsLookupTexture","transformsLookupTextureSize","callback","delayedSwitch","millis","pipe","loadingEnabled","cadModelsMetadata","loadingHints","suspendLoading","PromiseUtils","promises","remaining","completed","race","sectorRepository","sectorCuller","modelStateHandler","collectStatisticsCallback","progressCallback","_sectorRepository","_sectorCuller","_modelStateHandler","_collectStatisticsCallback","_progressCallback","input","cameraInMotion","prioritizedResult","determineSectors","spentBudget","hasSectorChanged","hasStateChanged","changedSectors","wantedSectors","progressHelper","ProgressReportHelper","start","filtered","filterSectors","consumedPromises","startLoadingBatch","raceUntilAllCompleted","updateState","filteredSectors","filterSectorsToLoad","reportNewSectorsCulled","loadSector","makeErrorSector","reportNewSectorsLoaded","reportCb","_sectorsScheduled","_sectorsLoaded","_sectorsCulled","sectorsScheduled","triggerCallback","loadedCountChange","culledCountChange","defaultCadModelSectorBudget","highDetailProximityThreshold","geometryDownloadSizeBytes","maximumNumberOfDrawCalls","maximumRenderCost","_sceneModelState","modelState","sectorLevelOfDetail","notLoadingState","itemsLoaded","itemsRequested","itemsCulled","_cameraSubject","_clippingPlaneSubject","_loadingHintsSubject","_modelSubject","_budgetSubject","_progressSubject","_budget","_lastSpent","downloadSize","drawCalls","renderCost","loadedSectorCount","simpleSectorCount","detailedSectorCount","forcedDetailedSectorCount","totalSectorCount","accumulatedPriority","combinator","makeSettingsInput","makeCameraInput","makeClippingInput","loadingModelObservable","determineSectorsHandler","spendage","loaded","requested","culled","_updateObservable","createDetermineSectorsInput","loadSectors","addModel","operation","removeModel","cadLoadingHints","budget","settings","models","identityRotation","sectorIdOffset","containers","buffers","rtBuffer","sectorVisibilityBuffer","coverageMaterial","_ensureBuffersCorrectSizeVars","_alreadyLoadedProvider","occludingGeometryProvider","generateMipmaps","_debugImageElement","document","createElement","keepModelIdentifiers","container","updateModel","allIdentifiers","discardIdentifiers","sectors","setAllSectorsVisible","setSectorsVisibility","ordered","orderSectorsByVisibility","toBeFiltered","isCameraInsideSector","point","isCameraInsideSectorVars","containsPoint","isWithinSectorBounds","renderSectors","toDataURL","ensureBuffersCorrectSize","readRenderTargetPixels","sectorVisibility","unpackSectorVisibility","totalWeight","weight","findSectorContainer","sectorIdWithOffset","priority","equals","rtWidth","CoverageRenderTargetScalingFactor","rtHeight","stateHelper","renderOccludingGeometry","visibilityValue","sectorIndexById","attributesValues","attributesBuffer","deleteSectorsFromBuffers","lastSectorIdWithOffset","renderable","firstSectorId","lastSectorId","getAllSectors","createSectorTreeGeometry","maxSectorId","renderTargetWidth","renderTargetHeight","renderTargetBuffer","exp","resetVisibilityInformation","halfHeight","halfWidth","ry","rx","translation","sectorCount","instanceValues","coverageFactors","sectorIndex","xy","xz","yz","coverage","compose","setMatrixAt","addSector","addSectorCost","cost","sectorRoot","determineSectorCost","_totalCost","parentIndex","sectorContainer","childrenIndexes","childIndex","setSectorLod","setSectorPriority","replaceSimpleWithDetailed","markAllDiscardedChildrenAsSimple","assert","getSectorLod","condition","_takenSectorTrees","totalCost","sectorTree","determineWantedSectorCount","join","markSectorDetailed","allWanted","toWantedSectors","computeSectorCost","logCallback","coverageUtil","takenSectors","update","wanted","collectWantedSectors","nonDiscarded","takenSectorCount","takenSimpleCount","isFinite","takenDetailedPercent","toPrecision","takenPercent","cullOccludedSectors","initializeScene","setModels","setClipping","prioritized","addHighDetailsForNearSectors","debugAccumulatedPriority","prioritizedLength","isWithinBudget","getWantedSectorCount","shortRangeCamera","updateProjectionMatrix","cameraMatrixWorldInverse","matrixWorldInverse","cameraProjectionMatrix","transformedCameraMatrixWorldInverse","multiplyMatrices","intersectingSectors","getSectorsIntersectingFrustum","testForClippingOcclusion","markSectorsAsDetailed","passingSectors","boundPoints","outvec","shouldKeep","k","planeAccepts","optionalParameters","estimatedDrawCallCount","estimatedRenderCost","createDefaultSectorCuller","worldToViewportVars","worldToNormalizedViewportCoordinates","position3D","canvas","canvasWidth","canvasHeight","scaleX","scaleY","worldToViewportCoordinates","pixelRatio","getPixelRatio","round","BoundingBoxClipper","_box","updatePlanes","setFromNormalAndCoplanarPoint","minX","maxX","minY","maxY","minZ","maxZ","_disposedEvent","_disposed","handler","unsubscribeAll","viewer","_htmlOverlays","_preallocatedVariables","camNormal","nearPlane","farPlane","position2D","_onSceneRenderedHandler","onSceneRendered","_onViewerDisposedHandler","onViewerDisposed","_viewer","getCamera","htmlElement","viewerDomElement","appendChild","getComputedStyle","removeChild","forceUpdate","overlays","viewerCamera","viewerRenderer","getWorldPosition","getWorldDirection","addScaledVector","positionUpdatedCallback","insideCameraPlanes","visibility","offsetTop","offsetLeft","cadModel","_cadModel","_rootTreeIndex","preloadBoundingBoxData","_treeBoundingBoxdata","expandRadius","expandData","direction","resetNodeTransformByTreeIndex","setPosition","setNodeTransformByTreeIndex","rootTreeIndexBoundingBox","getBoundingBoxByTreeIndex","rootBoundingBox","subTreeBoundingBoxes","getSubtreeTreeIndices","subTreeIndices","subTreeIndex","subTreeIndexBoundingBoxCenter","rootCenter","subTreeCenters","subVectors","payloads","payload","hideCameraHelper","_cameraHelper","addObject3D","removeObject3D","Corner","defaultAxisBoxCompassConfig","ringLabel","labelDelta","fontSize","fontColor","tickColor","defaultFaceConfig","label","outlineSize","faceColor","defaultAxisBoxConfig","corner","BottomRight","padding","animationSpeed","faces","xPositiveFace","xNegativeFace","yPositiveFace","yNegativeFace","zPositiveFace","zNegativeFace","compass","config","_dynamicUpdatePosition","_updateClickDiv","_screenPosition","_boxFaceGeometry","_raycastCamera","_raycaster","_layoutConfig","_axisGroup","_interactiveObjects","createAxisCross","_disposeClickDiv","createClickDiv","addAxisBoxToViewer","removeUiObject","querySelector","divElement","zIndex","xMouse","yMouse","addEventListener","mouseDownEvent","button","dispatchEvent","mouseMoveEvent","preventDefault","mouseUpEvent","handleClick","bottom","axisGroup","xAbsolute","yAbsolute","isAbsolute","TopRight","TopLeft","BottomLeft","addUiObject","xScreenPos","yScreenPos","boundingRect","xNdc","yNdc","setFromCamera","rayOrigin","rayDirection","intersectObjects","targetPosition","targetUp","upVector","moveCameraTo","cameraControls","interactiveObjects","createBoxFaces","createCompass","setupTransformOnRender","quaternion","facesConfig","createBoxFace","compassPlaneGeometry","createCompassTexture","sin","cos","up","lookAt","compassLayout","textureSize","context","getContext","halfSize","radius","tickWidth","tickSpace","strokeStyle","getStyle","lineWidth","setLineDash","beginPath","arc","stroke","font","textAlign","fillStyle","fillText","faceConfig","fillRect","fill","face","getFaceTexture","parameters","targetAxis","targetUpAxis","currentCameraPosition","cameraTarget","getState","targetRelativeStartPosition","sub","normalizedFrom","omega","acos","dot","animation","Tween","forward","fromRotation","toRotation","setFromRotationMatrix","makeBasis","cross","angleTo","tmpPosition","tmpRotation","cachedCameraControlsEnabled","to","onUpdate","slerpQuaternions","setRotationFromQuaternion","onStart","onComplete","setState","MapProviders","MapboxMode","MapboxStyle","MapboxId","MapboxImageFormat","BingMapType","BingMapImageFormat","HereMapType","HereMapScheme","HereMapImageFormat","mapConfig","_intervalId","_onCameraChange","handleCameraChange","mapProvider","getMapProvider","_map","PLANAR","coords","datumsToSpherical","latlong","latitude","longitude","bound","getModelBoundingBox","requestRedraw","timeOut","setInterval","setTimeout","clearInterval","provider","BingMap","APIKey","HereMap","appCode","scheme","imageFormat","MapboxMap","tileFormat","OpenStreetMap","latLong","_maps","latLongToWorldCoordinates","_boundingBoxes","_options","setOptions","showDetailedSectors","showDiscardedSectors","showSimpleSectors","colorBy","leafsOnly","sectorPathFilterRegex","_model","updateBoundingBoxes","shouldShowLod","selectedSectorNodes","isSectorNode","sectorNode","isSectorAcceptedByCurrentFilter","isLeaf","bboxNode","createBboxNodeFor","RegExp","allSelectedNodes","Colors","green","lerpHSL","red","yellow","nodesByTimestamp","updatedTimestamp","indexOfNode","setHSL","determineColor"],"mappings":"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","file":"tools.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})((typeof self !== 'undefined' ? self : this), function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"https://apps-cdn.cogniteapp.com/@cognite/reveal-parser-worker/1.2.0/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 65);\n","module.exports = require(\"three\");","/*!\n * Copyright 2021 Cognite AS\n */\n\ninterface WithChildren<T> {\n readonly children: T[];\n}\n\nexport function traverseDepthFirst<T extends WithChildren<T>>(root: T, visitor: (element: T) => boolean): void {\n if (!visitor(root)) {\n return;\n }\n\n for (let i = 0; i < root.children.length; i++) {\n traverseDepthFirst(root.children[i], visitor);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nimport { CameraConfiguration } from './CameraConfiguration';\n\nexport function transformCameraConfiguration(\n cameraConfiguration: CameraConfiguration | undefined,\n modelMatrix: THREE.Matrix4\n): CameraConfiguration | undefined {\n if (cameraConfiguration === undefined) {\n return undefined;\n }\n\n const { position, target } = cameraConfiguration;\n position.applyMatrix4(modelMatrix);\n target.applyMatrix4(modelMatrix);\n return {\n position,\n target\n };\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Determines clicked or touched coordinate as offset\n * @param ev An MouseEvent or TouchEvent.\n * @param target HTML element to find coordinates relative to.\n * @returns A struct containing coordinates relative to the HTML element provided.\n */\nexport function clickOrTouchEventOffset(ev: MouseEvent | TouchEvent, target: HTMLElement) {\n const rect = target.getBoundingClientRect();\n\n if (ev instanceof MouseEvent) {\n return {\n offsetX: ev.clientX - rect.left,\n offsetY: ev.clientY - rect.top\n };\n } else if (ev.changedTouches.length > 0) {\n const touch = ev.changedTouches[0];\n return {\n offsetX: touch.clientX - rect.left,\n offsetY: touch.clientY - rect.top\n };\n }\n\n // Invalid event\n return {\n offsetX: -1,\n offsetY: -1\n };\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Subscribable event source.\n */\nexport class EventTrigger<TListener extends (...args: any[]) => void> {\n private readonly _listeners: TListener[] = [];\n\n subscribe(listener: TListener): void {\n this._listeners.push(listener);\n }\n\n unsubscribe(listener: TListener): void {\n const index = this._listeners.indexOf(listener);\n if (index !== -1) {\n this._listeners.splice(index, 1);\n }\n }\n\n unsubscribeAll(): void {\n this._listeners.splice(0);\n }\n\n fire(...args: Parameters<TListener>): void {\n this._listeners.forEach(listener => listener(...args));\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * See https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#union-exhaustiveness-checking\n */\nexport function assertNever(x: never, message?: string): never {\n throw new Error(message || 'Unexpected object: ' + x);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport class NumericRange {\n readonly from: number;\n readonly count: number;\n readonly toInclusive: number;\n\n constructor(from: number, count: number) {\n if (count < 0) {\n throw new Error('Range cannot have negative number of elements');\n }\n\n this.from = from;\n this.count = count;\n this.toInclusive = from + count - 1;\n }\n\n static createFromInterval(from: number, toInclusive: number): NumericRange {\n return new NumericRange(from, toInclusive - from + 1);\n }\n\n *values(): Generator<number> {\n for (let i = this.from; i <= this.toInclusive; ++i) {\n yield i;\n }\n }\n\n toArray(): number[] {\n return Array.from(this.values());\n }\n\n equal(other: NumericRange): boolean {\n return this.from === other.from && this.count === other.count;\n }\n\n contains(value: number): boolean {\n return value >= this.from && value <= this.toInclusive;\n }\n\n intersects(range: NumericRange): boolean {\n return this.from <= range.toInclusive && this.toInclusive >= range.from;\n }\n\n intersectsOrCoinciding(range: NumericRange): boolean {\n return this.from <= range.toInclusive + 1 && this.toInclusive + 1 >= range.from;\n }\n\n intersectionWith(range: NumericRange): NumericRange | undefined {\n if (!this.intersects(range)) {\n return undefined;\n } else {\n return NumericRange.createFromInterval(\n Math.max(this.from, range.from),\n Math.min(this.toInclusive, range.toInclusive)\n );\n }\n }\n\n isInside(range: NumericRange): boolean {\n return this.from >= range.from && this.toInclusive <= range.toInclusive;\n }\n\n union(range: NumericRange): NumericRange {\n return NumericRange.createFromInterval(\n Math.min(this.from, range.from),\n Math.max(this.toInclusive, range.toInclusive)\n );\n }\n\n forEach(action: (value: number) => void): void {\n for (let i = this.from; i <= this.toInclusive; ++i) {\n action(i);\n }\n }\n\n str() {\n return '(' + this.from + ', ' + this.toInclusive + ')';\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Computes minimal power-of-two width and height that holds at least the number of elements provided.\n * This is useful to compute texture sizes.\n */\nexport function determinePowerOfTwoDimensions(elementCount: number): { width: number; height: number } {\n const width = Math.max(1, ceilToPowerOfTwo(Math.sqrt(elementCount)));\n const height = Math.max(1, ceilToPowerOfTwo(elementCount / width));\n return { width, height };\n}\n\nconst log2 = Math.log(2);\nfunction ceilToPowerOfTwo(v: number): number {\n return Math.pow(2, Math.ceil(Math.log(v) / log2));\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { IndexNode } from './IndexSet';\nimport { LeafIndexNode } from './LeafIndexNode';\nimport { NumericRange } from '../NumericRange';\nimport assert from 'assert';\n\nexport class IntermediateIndexNode {\n readonly range: NumericRange;\n readonly maxSubtreeDepth: number;\n readonly left: IndexNode;\n readonly right: IndexNode;\n readonly count: number;\n\n constructor(left: IndexNode, right: IndexNode) {\n this.left = left;\n this.right = right;\n\n this.maxSubtreeDepth = Math.max(this.left.maxSubtreeDepth, this.right.maxSubtreeDepth) + 1;\n this.range = NumericRange.createFromInterval(this.left.range.from, this.right.range.toInclusive);\n this.count = this.left.count + this.right.count;\n }\n\n static fromIndexNodesAndBalance(r0: IndexNode, r1: IndexNode) {\n if (r0.range.from > r1.range.toInclusive + 1) {\n return new IntermediateIndexNode(r1, r0).balance();\n } else if (r0.range.toInclusive + 1 < r1.range.from) {\n return new IntermediateIndexNode(r0, r1).balance();\n } else {\n // Help, overlapping nodes! There is an error somewhere!\n assert(false, 'Internal error in IndexSet: Overlapping nodes');\n }\n }\n\n traverse(visitor: (range: NumericRange) => void) {\n // Note! The actual ranges are kept in leafs, so we do not visit \"this\"\n this.left.traverse(visitor);\n this.right.traverse(visitor);\n }\n\n contains(index: number): boolean {\n if (!this.range.contains(index)) {\n return false;\n }\n\n return this.left.contains(index) || this.right.contains(index);\n }\n\n addRange(range: NumericRange): IndexNode {\n const canUnionThis = range.intersectsOrCoinciding(this.range);\n\n if (!canUnionThis) {\n // The range is either entirely above or below the range of this node\n if (range.from < this.range.from) {\n const newNode = this.left.addRange(range);\n return IntermediateIndexNode.fromIndexNodesAndBalance(newNode, this.right);\n } else {\n const newNode = this.right.addRange(range);\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left, newNode);\n }\n }\n\n const canUnionLeft = range.intersectsOrCoinciding(this.left.range);\n const canUnionRight = range.intersectsOrCoinciding(this.right.range);\n\n if (canUnionLeft && canUnionRight) {\n // Range intersects both subtrees...\n const [newLeft, leftRange] = this.left.soak(range);\n const [newRight, rightRange] = this.right.soak(range);\n\n const unioned = leftRange.union(rightRange);\n\n if (newLeft === undefined && newRight === undefined) {\n return new LeafIndexNode(unioned);\n } else if (newLeft === undefined && newRight !== undefined) {\n // Last term is added to please compiler\n return newRight.addRange(unioned);\n } else if (newRight === undefined && newLeft !== undefined) {\n // ---\"---\n return newLeft.addRange(unioned);\n }\n\n // We have guaranteed that newLeft and newRight is defined\n const newNode = IntermediateIndexNode.fromIndexNodesAndBalance(newLeft!, newRight!);\n\n return newNode.addRange(unioned);\n } else if (canUnionLeft) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left.addRange(range), this.right);\n } else if (canUnionRight) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left, this.right.addRange(range));\n } else {\n // Range lies between ranges of left and right subtree,\n // add to smallest\n if (this.left.maxSubtreeDepth < this.right.maxSubtreeDepth) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left.addRange(range), this.right);\n } else {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left, this.right.addRange(range));\n }\n }\n }\n\n removeRange(range: NumericRange): IndexNode | undefined {\n // If input range does not intersect with this range, return\n if (!range.intersects(this.range)) {\n return this;\n }\n\n const [newThis, soakedRange] = this.soak(range);\n\n let leftRange: NumericRange | undefined = undefined;\n let rightRange: NumericRange | undefined = undefined;\n\n // If soakedRange extends to either the left or right to the\n // numeric range, we take the ranges extending out and insert anew.\n if (soakedRange.from < range.from) {\n leftRange = NumericRange.createFromInterval(soakedRange.from, range.from - 1);\n }\n\n if (soakedRange.toInclusive > range.toInclusive) {\n rightRange = NumericRange.createFromInterval(range.toInclusive + 1, soakedRange.toInclusive);\n }\n\n if (newThis === undefined) {\n // If all ranges in this was soaked up, create new node with\n // non-empty left and right ranges\n if (leftRange !== undefined && rightRange !== undefined) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(\n new LeafIndexNode(leftRange),\n new LeafIndexNode(rightRange)\n );\n } else if (leftRange != undefined) {\n return new LeafIndexNode(leftRange);\n } else if (rightRange != undefined) {\n return new LeafIndexNode(rightRange);\n } else {\n return undefined;\n }\n } else {\n // Add non-empty left- and right ranges\n let nodeToReturn = newThis;\n\n if (leftRange !== undefined) {\n nodeToReturn = nodeToReturn.addRange(leftRange);\n }\n\n if (rightRange !== undefined) {\n nodeToReturn = nodeToReturn.addRange(rightRange);\n }\n\n return nodeToReturn;\n }\n }\n\n balance(): IntermediateIndexNode {\n const leftSubTreeSize = this.left.maxSubtreeDepth;\n const rightSubTreeSize = this.right.maxSubtreeDepth;\n\n if (rightSubTreeSize + 2 <= leftSubTreeSize) {\n // Left side too deep\n const newLeft = (this.left as IntermediateIndexNode).rotateSmallerRight();\n const newNode = new IntermediateIndexNode(newLeft, this.right).rotateRight().balance();\n return newNode;\n } else if (leftSubTreeSize + 2 <= rightSubTreeSize) {\n // Right side too deep\n const newRight = (this.right as IntermediateIndexNode).rotateSmallerLeft();\n const newNode = new IntermediateIndexNode(this.left, newRight).rotateLeft().balance();\n return newNode;\n }\n\n return this;\n }\n\n clone(): IntermediateIndexNode {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left.clone(), this.right.clone());\n }\n\n hasIntersectionWith(node: IndexNode): boolean {\n if (!node.range.intersects(this.range)) {\n return false;\n }\n\n // Make sure containing range is the \"this\"\n if (this.range.isInside(node.range)) {\n return node.hasIntersectionWith(this);\n }\n\n // Here, we know this range is not contained within node range\n if (this.left.range.intersects(node.range) && this.left.hasIntersectionWith(node)) {\n return true;\n }\n\n if (this.right.range.intersects(node.range) && this.right.hasIntersectionWith(node)) {\n return true;\n }\n\n return false;\n }\n\n /*\n * Utilities\n */\n // Soak up/ delete numeric range touching the input range,\n // returning union of soaked ranges and input range\n // This operation is used as a substep when adding a range - the range\n // is first used to \"soak\" up all touching ranges in the tree, since these must be part of a\n // common union range at the end of the insertion. In the end, the range, unioned with\n // all its soaked ranges in the tree, is inserted normally.\n soak(range: NumericRange): [IndexNode | undefined, NumericRange] {\n let [leftRes, leftRange]: [IndexNode | undefined, NumericRange] = [this.left, range];\n let [rightRes, rightRange]: [IndexNode | undefined, NumericRange] = [this.right, range];\n\n // Both subtrees are inside range, soak up everything\n if (this.right.range.isInside(range) && this.left.range.isInside(range)) {\n return [undefined, range];\n }\n\n // Compute what's left on the left, and the soaked-up range\n if (this.left.range.intersectsOrCoinciding(range)) {\n [leftRes, leftRange] = this.left.soak(range);\n }\n\n // Compute what's left on the right, and the soaked-up range\n if (this.right.range.intersectsOrCoinciding(range)) {\n [rightRes, rightRange] = this.right.soak(range);\n }\n\n // The two soaked-up ranges must touch (they both contain the argument range)\n const unionRange = leftRange.union(rightRange);\n\n if (rightRes == undefined) {\n return [leftRes, unionRange];\n } else if (leftRes == undefined) {\n return [rightRes, unionRange];\n } else {\n const newNode = IntermediateIndexNode.fromIndexNodesAndBalance(leftRes, rightRes);\n return [newNode, unionRange];\n }\n }\n\n /*\n * Rotations\n */\n rotateRight(): IntermediateIndexNode {\n if (!('right' in this.left)) {\n // Left node is leaf node. Abort rotation\n return this;\n }\n\n return new IntermediateIndexNode(\n (this.left as IntermediateIndexNode).left,\n new IntermediateIndexNode((this.left as IntermediateIndexNode).right, this.right)\n );\n }\n\n rotateLeft(): IntermediateIndexNode {\n if (!('left' in this.right)) {\n // Left node is leaf node. Abort rotation\n return this;\n }\n\n return new IntermediateIndexNode(\n new IntermediateIndexNode(this.left, (this.right as IntermediateIndexNode).left),\n (this.right as IntermediateIndexNode).right\n );\n }\n\n // Rotate so that smaller subtree is on left\n rotateSmallerLeft(): IntermediateIndexNode {\n if (this.left.maxSubtreeDepth > this.right.maxSubtreeDepth) {\n // If left subtree depth is larger, it must be of type IntermediateIndexNode\n let nextRoot = this.rotateRight() as IntermediateIndexNode;\n nextRoot = nextRoot.rotateSmallerLeft();\n return nextRoot;\n }\n\n return this;\n }\n\n // Rotate so that smaller subtree is on right\n rotateSmallerRight(): IntermediateIndexNode {\n if (this.right.maxSubtreeDepth > this.left.maxSubtreeDepth) {\n // If left subtree depth is larger, it must be of type IntermediateIndexNode\n let nextRoot = this.rotateLeft() as IntermediateIndexNode;\n nextRoot = nextRoot.rotateSmallerRight();\n return nextRoot;\n }\n\n return this;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS../NumericRange\n */\nimport { IntermediateIndexNode } from './IntermediateIndexNode';\nimport { IndexNode } from './IndexSet';\nimport { NumericRange } from '../NumericRange';\n\nexport class LeafIndexNode {\n readonly range: NumericRange;\n readonly count: number;\n readonly maxSubtreeDepth: number;\n\n static fromInterval(begin: number, endInclusive: number) {\n return new LeafIndexNode(NumericRange.createFromInterval(begin, endInclusive));\n }\n\n constructor(range: NumericRange) {\n this.range = range;\n this.maxSubtreeDepth = 0;\n this.count = range.count;\n }\n\n traverse(visitor: (range: NumericRange) => void) {\n visitor(this.range);\n }\n\n contains(index: number): boolean {\n return this.range.contains(index);\n }\n\n addRange(range: NumericRange): IndexNode {\n if (this.range.intersectsOrCoinciding(range)) {\n // Create union range\n return new LeafIndexNode(this.range.union(range));\n }\n\n return IntermediateIndexNode.fromIndexNodesAndBalance(this, new LeafIndexNode(range));\n }\n\n removeRange(range: NumericRange): IndexNode | undefined {\n if (!range.intersects(this.range)) {\n return this;\n }\n\n if (this.range.isInside(range)) {\n return undefined;\n }\n\n let leftRange: NumericRange | undefined = undefined;\n let rightRange: NumericRange | undefined = undefined;\n\n if (this.range.from < range.from) {\n leftRange = NumericRange.createFromInterval(this.range.from, range.from - 1);\n }\n\n if (this.range.toInclusive > range.toInclusive) {\n rightRange = NumericRange.createFromInterval(range.toInclusive + 1, this.range.toInclusive);\n }\n\n if (leftRange != undefined && rightRange != undefined) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(\n new LeafIndexNode(leftRange),\n new LeafIndexNode(rightRange)\n );\n } else if (leftRange != undefined) {\n return new LeafIndexNode(leftRange);\n } else if (rightRange != undefined) {\n return new LeafIndexNode(rightRange);\n } else {\n return undefined;\n }\n }\n\n hasIntersectionWith(node: IndexNode): boolean {\n return node.range.intersects(this.range);\n }\n\n soak(range: NumericRange): [IndexNode | undefined, NumericRange] {\n if (this.range.intersectsOrCoinciding(range)) {\n return [undefined, this.range.union(range)];\n } else {\n return [this, range];\n }\n }\n\n clone(): LeafIndexNode {\n return new LeafIndexNode(this.range);\n }\n}\n","/*\n * Copyright 2021 Cognite AS\n */\nimport { IntermediateIndexNode } from './IntermediateIndexNode';\nimport { LeafIndexNode } from './LeafIndexNode';\nimport { NumericRange } from '../NumericRange';\n\nexport type IndexNode = IntermediateIndexNode | LeafIndexNode;\n\nexport class IndexSet {\n rootNode?: IndexNode;\n\n constructor(values?: Iterable<number>);\n constructor(values?: NumericRange);\n constructor(values?: Iterable<number> | NumericRange) {\n if (values == undefined) {\n this.rootNode = undefined;\n } else if (values instanceof NumericRange) {\n this.addRange(values);\n } else {\n for (const index of values) {\n this.add(index);\n }\n }\n }\n\n forEachRange(visitor: (range: NumericRange) => void) {\n if (this.rootNode) {\n this.rootNode.traverse(visitor);\n }\n }\n\n add(index: number) {\n const range = new NumericRange(index, 1);\n\n this.addRange(range);\n }\n\n addRange(range: NumericRange) {\n if (this.rootNode) {\n this.rootNode = this.rootNode.addRange(range);\n } else {\n this.rootNode = new LeafIndexNode(range);\n }\n }\n\n remove(index: number) {\n const range = new NumericRange(index, 1);\n this.removeRange(range);\n }\n\n removeRange(range: NumericRange) {\n if (this.rootNode) {\n this.rootNode = this.rootNode.removeRange(range);\n }\n\n // Do nothing if root is empty\n }\n\n contains(index: number): boolean {\n if (this.rootNode) {\n return this.rootNode.contains(index);\n }\n\n return false;\n }\n\n get count(): number {\n if (this.rootNode) {\n return this.rootNode.count;\n }\n\n return 0;\n }\n\n toRangeArray(): NumericRange[] {\n const ranges: NumericRange[] = [];\n this.forEachRange(range => {\n ranges.push(range);\n });\n return ranges;\n }\n\n toIndexArray(): number[] {\n const result: number[] = [];\n\n if (this.rootNode) {\n this.forEachRange(range => {\n range.forEach(num => {\n result.push(num);\n });\n });\n }\n\n return result;\n }\n\n toPlainSet(): Set<number> {\n const arr: number[] = this.toIndexArray();\n const st = new Set(arr);\n return st;\n }\n\n // NB: Assumes that this.ranges() are in order from left to right\n invertedRanges(): NumericRange[] {\n const originalRanges = this.toRangeArray();\n\n const newRanges: NumericRange[] = [];\n\n for (let i = 0; i < originalRanges.length - 1; i++) {\n if (originalRanges[i].toInclusive + 1 >= originalRanges[i + 1].from) {\n // Should not happen, but let's be safe\n continue;\n }\n newRanges.push(NumericRange.createFromInterval(originalRanges[i].toInclusive + 1, originalRanges[i + 1].from));\n }\n\n return newRanges;\n }\n\n unionWith(otherSet: IndexSet): IndexSet {\n if (this.rootNode) {\n otherSet.forEachRange(range => {\n this.rootNode = this.rootNode!.addRange(range);\n });\n } else {\n this.rootNode = otherSet.rootNode;\n }\n\n return this;\n }\n\n differenceWith(otherSet: IndexSet): IndexSet {\n if (this.rootNode) {\n otherSet.forEachRange(range => {\n this.rootNode = this.rootNode?.removeRange(range);\n });\n }\n\n return this;\n }\n\n hasIntersectionWith(otherSet: IndexSet | Set<number>): boolean {\n if (otherSet instanceof IndexSet) {\n if (this.rootNode === undefined || otherSet.rootNode === undefined) {\n return false;\n }\n\n return this.rootNode.hasIntersectionWith(otherSet.rootNode);\n } else {\n for (const index of otherSet) {\n if (this.contains(index)) {\n return true;\n }\n }\n\n return false;\n }\n }\n\n intersectWith(otherSet: IndexSet): IndexSet {\n if (this.rootNode && otherSet.rootNode) {\n // Tackle endpoints\n // Remove left bounds outside input set\n if (this.rootNode.range.from < otherSet.rootNode.range.from) {\n const leftBoundRange = NumericRange.createFromInterval(\n this.rootNode.range.from,\n otherSet.rootNode.range.from - 1\n );\n this.rootNode = this.rootNode.removeRange(leftBoundRange);\n\n if (!this.rootNode) {\n return this;\n }\n }\n\n // Remove right bounds outside input set\n if (this.rootNode.range.toInclusive > otherSet.rootNode.range.toInclusive) {\n const rightBoundRange = NumericRange.createFromInterval(\n otherSet.rootNode.range.toInclusive + 1,\n this.rootNode.range.toInclusive\n );\n this.rootNode = this.rootNode.removeRange(rightBoundRange);\n }\n\n // Invert otherSet ranges and remove them\n const invRanges = otherSet.invertedRanges();\n\n invRanges.forEach(range => {\n if (this.rootNode) {\n this.rootNode = this.rootNode.removeRange(range);\n }\n });\n } else if (this.rootNode) {\n // Otherset is empty, set this to empty as well\n this.rootNode = undefined;\n }\n return this;\n }\n\n clear(): void {\n this.rootNode = undefined;\n }\n\n clone(): IndexSet {\n const st: IndexSet = new IndexSet();\n\n if (this.rootNode) {\n st.rootNode = this.rootNode.clone();\n }\n\n return st;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\n\nexport function packFloat(f: number): [number, number, number, number] {\n const F = abs(f);\n if (F == 0) {\n return [0, 0, 0, 0];\n }\n const Sign = step(0.0, -f);\n let Exponent = floor(log2(F));\n\n const Mantissa = F / exp2(Exponent);\n\n if (Mantissa < 1) Exponent -= 1;\n\n Exponent += 127;\n\n const rgba: [number, number, number, number] = [\n 128.0 * Sign + floor(Exponent * exp2(-1.0)),\n 128.0 * mod(Exponent, 2.0) + mod(floor(Mantissa * 128.0), 128.0),\n floor(mod(floor(Mantissa * exp2(23.0 - 8.0)), exp2(8.0))),\n floor(exp2(23.0) * mod(Mantissa, exp2(-15.0)))\n ];\n return rgba;\n}\n\nexport function packFloatInto(f: number, targetBuffer: Uint8ClampedArray, offset: number) {\n const F = abs(f);\n if (F == 0) {\n return;\n }\n const Sign = step(0.0, -f);\n let Exponent = floor(log2(F));\n\n const Mantissa = F / exp2(Exponent);\n\n if (Mantissa < 1) Exponent -= 1;\n\n Exponent += 127;\n\n targetBuffer[offset] = 128.0 * Sign + floor(Exponent * exp2(-1.0));\n targetBuffer[offset + 1] = 128.0 * mod(Exponent, 2.0) + mod(floor(Mantissa * 128.0), 128.0);\n targetBuffer[offset + 2] = floor(mod(floor(Mantissa * exp2(23.0 - 8.0)), exp2(8.0)));\n targetBuffer[offset + 3] = floor(exp2(23.0) * mod(Mantissa, exp2(-15.0)));\n}\n\nexport function unpackFloat4(packedFloat: [number, number, number, number]) {\n const [r, g, b, a] = packedFloat;\n const sign = 1.0 - step(128.0, r) * 2.0;\n const exponent = 2.0 * mod(r, 128.0) + step(128.0, g) - 127.0;\n if (exponent == -127) return 0;\n const mantissa = mod(g, 128.0) * 65536.0 + b * 256.0 + a + 8388608.0;\n return sign * exp2(exponent - 23.0) * mantissa;\n}\n\nfunction step(edge: number, x: number): number {\n return x < edge ? 0.0 : 1.0;\n}\n\nfunction exp2(x: number) {\n return Math.pow(2, x);\n}\n\nfunction mod(x: number, y: number) {\n return x - y * floor(x / y);\n}\n\nfunction floor(x: number) {\n return Math.floor(x);\n}\n\nfunction log2(x: number) {\n return Math.log(x) / Math.log(2);\n}\n\nfunction abs(x: number) {\n return Math.abs(x);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { TypedArray } from '../types';\n\ntype Batch = {\n from: number;\n count: number;\n prev: Batch | undefined;\n next: Batch | undefined;\n};\n\nexport class DynamicDefragmentedBuffer<T extends TypedArray> {\n public get length(): number {\n return this._numFilled;\n }\n\n public get buffer(): T {\n return this._buffer;\n }\n\n private _buffer: T;\n private _numFilled: number;\n private _type: new (length: number) => T;\n\n private _batchMap: Map<number, Batch>;\n private _currentTail: Batch | undefined;\n\n private _batchIdCounter: number;\n\n constructor(initialSize: number, type: new (length: number) => T) {\n this._numFilled = 0;\n this._batchIdCounter = 0;\n this._batchMap = new Map<number, Batch>();\n\n this._type = type;\n\n const minimalPowerOfTwo = Math.pow(2, Math.ceil(Math.log2(initialSize)));\n this._buffer = new type(minimalPowerOfTwo);\n }\n\n public add(array: T): { batchId: number; bufferIsReallocated: boolean } {\n let isReallocated = false;\n if (this._numFilled + array.length > this._buffer.length) {\n const newSize = Math.pow(2, Math.ceil(Math.log2(this._numFilled + array.length)));\n this.allocateNewBuffer(newSize);\n isReallocated = true;\n }\n\n this._buffer.set(array, this._numFilled);\n\n const batchId = this.createBatch(array);\n\n this._numFilled += array.length;\n\n return { batchId: batchId, bufferIsReallocated: isReallocated };\n }\n\n public remove(batchId: number) {\n const batch = this._batchMap.get(batchId);\n\n if (!batch) {\n throw new Error('batch does not exist in buffer');\n }\n\n this._buffer.copyWithin(batch.from, batch.from + batch.count, this.buffer.length);\n\n this._numFilled -= batch.count;\n\n if (this._currentTail === batch) {\n this._currentTail = batch.prev;\n }\n\n const prev = batch.prev;\n const next = batch.next;\n\n if (prev) {\n prev.next = next;\n }\n\n if (next) {\n next.prev = prev;\n }\n\n let currentBatch = next;\n\n while (currentBatch) {\n currentBatch.from -= batch.count;\n currentBatch = currentBatch.next;\n }\n\n this._batchMap.delete(batchId);\n }\n\n private createBatch(array: T) {\n const batch: Batch = {\n from: this._numFilled,\n count: array.length,\n prev: this._currentTail,\n next: undefined\n };\n\n if (this._currentTail) {\n this._currentTail.next = batch;\n }\n\n this._currentTail = batch;\n\n const batchId = this._batchIdCounter;\n this._batchIdCounter++;\n\n this._batchMap.set(batchId, batch);\n return batchId;\n }\n\n private allocateNewBuffer(newSize: number): void {\n const newBuffer = new this._type(newSize);\n newBuffer.set(this._buffer);\n\n this._buffer = newBuffer;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nconst emptyGeometry = new THREE.BufferGeometry();\n\n/**\n * Referenced count implementation of THREE.Group that\n * automatically disposes all geometries contained in meshes that\n * are direct children of the group.\n */\nexport class AutoDisposeGroup extends THREE.Group {\n private _isDisposed = false;\n private _referenceCount = 0;\n\n reference(): void {\n this.ensureNotDisposed();\n this._referenceCount++;\n }\n\n dereference(): void {\n this.ensureNotDisposed();\n if (this._referenceCount === 0) {\n throw new Error('No references');\n }\n if (--this._referenceCount === 0) {\n this.dispose();\n }\n }\n\n private dispose(): void {\n this.ensureNotDisposed();\n this._isDisposed = true;\n const meshes: THREE.Mesh[] = this.children.filter(x => x instanceof THREE.Mesh).map(x => x as THREE.Mesh);\n for (const mesh of meshes) {\n if (mesh.geometry !== undefined) {\n mesh.geometry.dispose();\n // // NOTE: Forcefully creating a new reference here to make sure\n // // there are no lingering references to the large geometry buffer\n mesh.geometry = emptyGeometry;\n }\n }\n }\n\n private ensureNotDisposed() {\n if (this._isDisposed) {\n throw new Error('Already disposed/dereferenced');\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\n// For BoundingBoxLOD.update()\nconst updateVars = {\n camPos: new THREE.Vector3(),\n bounds: new THREE.Box3()\n};\n\n/**\n * Class similar to THREE.LOD except that it doesn't use `matrixWorld` to determine distance to camera, but a\n * bounding box.\n */\nexport class BoundingBoxLOD extends THREE.Object3D {\n private readonly _boundingBox: THREE.Box3;\n private _activeLevel = 0;\n private readonly _levels: { distance: number; object: THREE.Object3D }[] = [];\n\n // Note! isLOD and autoUpdate is used by WebGLRenderer to perform automatic update of LOD\n // level before rendering\n public readonly isLOD = true;\n public readonly autoUpdate = true;\n\n constructor(boundingBox: THREE.Box3) {\n super();\n this._boundingBox = boundingBox.clone();\n this.type = 'BoundingBoxLOD';\n }\n\n setBoundingBox(boundingBox: THREE.Box3) {\n this._boundingBox.copy(boundingBox);\n }\n\n addLevel(object: THREE.Object3D, distance: number = 0) {\n this._levels.push({ object, distance: Math.abs(distance) });\n this._levels.sort((a, b) => b.distance - a.distance);\n object.visible = false;\n this.add(object);\n }\n\n /**\n * Returns the index of the current active LOD. 0 means highest detail.\n */\n getCurrentLevel() {\n return this._levels.length > 0 ? this._levels.length - this._activeLevel - 1 : 0;\n }\n\n /**\n * Update selected LOD level based on distance to camera.\n */\n update(camera: THREE.Camera) {\n this.updateCurrentLevel(camera);\n }\n\n private updateCurrentLevel(camera: THREE.Camera) {\n const levels = this._levels;\n const { camPos, bounds } = updateVars;\n bounds.copy(this._boundingBox).applyMatrix4(this.matrixWorld);\n const cameraZoom = camera instanceof THREE.PerspectiveCamera ? camera.zoom : 1.0;\n\n if (levels.length > 0) {\n camPos.setFromMatrixPosition(camera.matrixWorld);\n const distanceToCamera = bounds.distanceToPoint(camPos) / cameraZoom;\n\n levels[this._activeLevel].object.visible = false;\n this._activeLevel = levels.findIndex(p => distanceToCamera >= p.distance);\n this._activeLevel = this._activeLevel >= 0 ? this._activeLevel : levels.length - 1;\n levels[this._activeLevel].object.visible = true;\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nexport function getBox3CornerPoints(box: THREE.Box3): THREE.Vector3[] {\n return [\n new THREE.Vector3(box.min.x, box.min.y, box.min.z), // 000\n new THREE.Vector3(box.min.x, box.min.y, box.max.z), // 001\n new THREE.Vector3(box.min.x, box.max.y, box.min.z), // 010\n new THREE.Vector3(box.min.x, box.max.y, box.max.z), // 011\n new THREE.Vector3(box.max.x, box.min.y, box.min.z), // 100\n new THREE.Vector3(box.max.x, box.min.y, box.max.z), // 101\n new THREE.Vector3(box.max.x, box.max.y, box.min.z), // 110\n new THREE.Vector3(box.max.x, box.max.y, box.max.z) // 111\n ];\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport function isMobileOrTablet() {\n // https://stackoverflow.com/a/11381730/167251\n let check = false;\n (a => {\n if (\n /(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(\n a\n ) ||\n /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i.test(\n a.substr(0, 4)\n )\n ) {\n check = true;\n }\n })(navigator.userAgent || navigator.vendor || (window as any).opera);\n return check;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\ntype WebGLRendererState = {\n autoClear?: boolean;\n clearColor?: THREE.Color | string | number;\n clearAlpha?: number;\n size?: THREE.Vector2;\n localClippingEnabled?: boolean;\n renderTarget?: THREE.RenderTarget | null;\n};\n\nexport class WebGLRendererStateHelper {\n private _originalState: WebGLRendererState = {};\n private readonly _renderer: THREE.WebGLRenderer;\n\n constructor(renderer: THREE.WebGLRenderer) {\n this._renderer = renderer;\n this._originalState = {};\n }\n\n setClearColor(color: THREE.Color | number | string, alpha?: number) {\n this._originalState = {\n clearColor: this._renderer.getClearColor(new THREE.Color()),\n clearAlpha: this._renderer.getClearAlpha(),\n ...this._originalState\n };\n this._renderer.setClearColor(color, alpha);\n }\n\n setSize(width: number, height: number) {\n this._originalState = { size: this._renderer.getSize(new THREE.Vector2()), ...this._originalState };\n this._renderer.setSize(width, height);\n }\n\n set localClippingEnabled(enabled: boolean) {\n this._originalState = { localClippingEnabled: this._renderer.localClippingEnabled, ...this._originalState };\n this._renderer.localClippingEnabled = enabled;\n }\n\n set autoClear(enabled: boolean) {\n this._originalState = { autoClear: this._renderer.autoClear, ...this._originalState };\n this._renderer.autoClear = enabled;\n }\n\n setRenderTarget(renderTarget: THREE.RenderTarget | null) {\n this._originalState = { renderTarget: this._renderer.getRenderTarget(), ...this._originalState };\n this._renderer.setRenderTarget(renderTarget);\n }\n\n resetState() {\n if (this._originalState.autoClear !== undefined) {\n this._renderer.autoClear = this._originalState.autoClear;\n }\n if (this._originalState.clearColor !== undefined) {\n this._renderer.setClearColor(this._originalState.clearColor, this._originalState.clearAlpha);\n }\n if (this._originalState.localClippingEnabled !== undefined) {\n this._renderer.localClippingEnabled = this._originalState.localClippingEnabled;\n }\n if (this._originalState.size !== undefined) {\n this._renderer.setSize(this._originalState.size.width, this._originalState.size.height);\n }\n if (this._originalState.renderTarget !== undefined) {\n this._renderer.setRenderTarget(this._originalState.renderTarget);\n }\n\n this._originalState = {};\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Used to specify custom url for worker/wasm files\n * in cases when you need the latest local files or CDN is blocked by CSP.\n */\nexport const revealEnv = {\n publicPath: ''\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { wrap } from 'comlink';\nimport { RevealParserWorker } from '@cognite/reveal-parser-worker';\nimport { revealEnv } from '../revealEnv';\nimport { isTheSameDomain } from '../networking/isTheSameDomain';\n\nimport log from '@reveal/logger';\n\ntype WorkDelegate<T> = (worker: RevealParserWorker) => Promise<T>;\n\ninterface PooledWorker {\n // The worker returned by Comlink.wrap is not strictly speaking a RevealParserWorker,\n // but it should expose the same functions\n worker: RevealParserWorker;\n activeJobCount: number;\n messageIdCounter: number;\n}\n\nexport class WorkerPool {\n static get defaultPool(): WorkerPool {\n WorkerPool._defaultPool = WorkerPool._defaultPool || new WorkerPool();\n return WorkerPool._defaultPool;\n }\n\n private static _defaultPool: WorkerPool | undefined;\n\n private readonly workerList: PooledWorker[] = [];\n\n private workerObjUrl?: string;\n\n constructor() {\n const numberOfWorkers = this.determineNumberOfWorkers();\n\n for (let i = 0; i < numberOfWorkers; i++) {\n const newWorker = {\n // NOTE: As of Comlink 4.2.0 we need to go through unknown before RevealParserWorker\n // Please feel free to remove `as unknown` if possible.\n worker: wrap(this.createWorker()) as unknown as RevealParserWorker,\n activeJobCount: 0,\n messageIdCounter: 0\n };\n this.workerList.push(newWorker);\n }\n\n if (process.env.NODE_ENV !== 'test') {\n checkWorkerVersion(this.workerList[0].worker).catch(x => log.error(x));\n }\n\n if (this.workerObjUrl) {\n URL.revokeObjectURL(this.workerObjUrl);\n }\n }\n\n // Used to construct workers with or without importScripts usage to overcome CORS.\n // When publicPath is not set we need to fetch worker from CDN (perform cross-origin request)\n // and that's possible only with importScripts.\n // If publicPath is set and points on the same domain, we use it normally.\n private createWorker() {\n const workerUrl = (revealEnv.publicPath || __webpack_public_path__) + 'reveal.parser.worker.js';\n const options = { name: `reveal.parser #${this.workerList.length}` };\n\n if (isTheSameDomain(workerUrl)) {\n return new Worker(workerUrl, options);\n }\n\n if (!this.workerObjUrl) {\n const blob = new Blob([`importScripts(${JSON.stringify(workerUrl)});`], {\n type: 'text/javascript'\n });\n this.workerObjUrl = URL.createObjectURL(blob);\n }\n\n return new Worker(this.workerObjUrl, options);\n }\n\n async postWorkToAvailable<T>(work: WorkDelegate<T>): Promise<T> {\n const targetWorker = this.workerList.reduce((bestWorker, candidate) => {\n if (bestWorker.activeJobCount > candidate.activeJobCount) {\n return candidate;\n }\n return bestWorker;\n }, this.workerList[0]);\n\n targetWorker.activeJobCount += 1;\n const result = await (async () => {\n try {\n return await work(targetWorker.worker);\n } finally {\n targetWorker.activeJobCount -= 1;\n }\n })();\n\n return result;\n }\n\n // TODO j-bjorne 16-04-2020: Send in constructor instead\n private determineNumberOfWorkers() {\n // Use between 2-4 workers, depending on hardware\n return Math.max(2, Math.min(4, window.navigator.hardwareConcurrency || 2));\n }\n}\n\nexport async function checkWorkerVersion(worker: RevealParserWorker) {\n let actualWorkerVersion: string;\n try {\n actualWorkerVersion = await worker.getVersion();\n } catch (e) {\n // versions below 1.1.1 do not have getVersion method\n // notice also you cannot use 'in' operator on worker object\n // because it's merely a proxy-wrapper over postmessage('methodname')\n // so `'getVersion' in worker` - will be always false\n actualWorkerVersion = '1.1.0';\n }\n const minWorkerVersion = process.env.WORKER_VERSION;\n\n const [majorMin, minorMin, patchMin] = minWorkerVersion.split('.').map(i => parseInt(i, 10));\n const [majorWorker, minorWorker, patchWorker] = actualWorkerVersion.split('.').map(i => parseInt(i, 10));\n\n const errorMessage = `Update your local copy of @cognite/reveal-parser-worker. Required version is ${minWorkerVersion}. Received ${actualWorkerVersion}.`;\n\n if (majorMin !== majorWorker) {\n throw new Error(errorMessage);\n }\n if (minorWorker < minorMin) {\n throw new Error(errorMessage);\n }\n if (minorWorker === minorMin && patchWorker < patchMin) {\n throw new Error(errorMessage);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Use to determine if the strings that represent urls\n * are pointing on different domains.\n * @param url1\n * @param url2 Optional. Default is `location.origin`. If provided then it must be\n * absolute url to avoid comparison between two relative urls.\n */\nexport function isTheSameDomain(url1: string, url2: string = location.origin) {\n const isRelative = (url: string) => {\n if (url.match(/^.*\\/\\//)) {\n return false; // starts with protocol - means absolute url, e.g. https://foo.bar/baz\n }\n return true;\n };\n\n if (isRelative(url2)) {\n throw new Error(`isTheSameDomain: the second argument must be an absolute url or omitted. Received ${url2}`);\n }\n\n if (isRelative(url1)) {\n return true;\n }\n\n try {\n // url that starts with '//' considered invalid for URL constructor\n // but browsers usually work just fine with them when it comes to links\n // and we just need to compare origins here anyway\n const urls = [url1, url2].map(url => (url.startsWith('//') ? 'https:' + url : url));\n\n const constructedURLs = urls.map(url => new URL(url));\n return constructedURLs[0].host === constructedURLs[1].host;\n } catch (e) {\n console.error(`can not create URLs for ${url1} and ${url2}`, e);\n return false;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { RequestCache } from './RequestCache';\n\nclass TimestampedContainer<T> {\n private _lastAccessTime: number;\n private readonly _value: T;\n\n constructor(value: T) {\n this._value = value;\n this._lastAccessTime = Date.now();\n }\n\n get value() {\n this.touch();\n return this._value;\n }\n\n get lastAccessTime() {\n return this._lastAccessTime;\n }\n\n private touch() {\n this._lastAccessTime = Date.now();\n }\n}\n\nexport interface MemoryRequestCacheOptions {\n maxElementsInCache?: number;\n}\n\nexport class MemoryRequestCache<Key, Data> implements RequestCache<Key, Data> {\n private readonly _maxElementsInCache: number;\n private readonly _data: Map<Key, TimestampedContainer<Data>>;\n private readonly _defaultCleanupCount: number;\n private readonly _removeCallback: ((value: Data) => void) | undefined;\n\n constructor(\n maxElementsInCache: number = 50,\n removeCallback?: (value: Data) => void,\n defaultCleanupCount: number = 10\n ) {\n this._data = new Map();\n this._maxElementsInCache = maxElementsInCache;\n this._defaultCleanupCount = defaultCleanupCount;\n this._removeCallback = removeCallback;\n }\n\n has(id: Key) {\n return this._data.has(id);\n }\n\n forceInsert(id: Key, data: Data) {\n if (this.isFull()) {\n this.cleanCache(this._defaultCleanupCount);\n }\n this.insert(id, data);\n }\n\n insert(id: Key, data: Data) {\n if (this._data.size < this._maxElementsInCache) {\n this._data.set(id, new TimestampedContainer(data));\n } else {\n throw new Error('Cache full, please clean Cache and retry adding data');\n }\n }\n\n remove(id: Key) {\n if (this._removeCallback !== undefined) {\n const value = this._data.get(id);\n if (value !== undefined) {\n this._removeCallback(value.value);\n }\n }\n this._data.delete(id);\n }\n\n get(id: Key): Data {\n const data = this._data.get(id);\n if (data !== undefined) {\n // Don't really like the touch for lastTime being hidden within a get function. Should we maybe make a\n // TimeConstrainedCache interface where the geter is called something like getAndUpdateTimestamp for clarity?\n return data.value;\n }\n throw new Error(`Cache element ${id} does not exist`);\n }\n\n isFull(): boolean {\n return !(this._data.size < this._maxElementsInCache);\n }\n\n cleanCache(count: number) {\n const allResults = Array.from(this._data.entries());\n allResults.sort((left, right) => {\n return right[1].lastAccessTime - left[1].lastAccessTime;\n });\n for (let i = 0; i < count; i++) {\n const entry = allResults.pop();\n if (entry !== undefined) {\n this.remove(entry[0]);\n } else {\n return;\n }\n }\n }\n\n clear() {\n if (this._removeCallback !== undefined) {\n for (const value of this._data.values()) {\n this._removeCallback(value.value);\n }\n }\n this._data.clear();\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n/**\n * A cache that keeps values that is most frequently used (MFU) rather than a more common\n * least recently used (LRU) approach.\n */\nexport class MostFrequentlyUsedCache<TKey, TValue> {\n private readonly _capacity: number;\n private readonly _cache = new Map<TKey, TValue>();\n private readonly _retrieves = new Map<TKey, number>();\n private readonly _disposeCallback: ((value: TValue) => void) | undefined;\n\n constructor(capacity: number, disposeCallback?: (value: TValue) => void) {\n this._capacity = capacity;\n this._disposeCallback = disposeCallback;\n }\n\n get(key: TKey): TValue | undefined {\n const retrieveCount = this._retrieves.get(key) || 0;\n this._retrieves.set(key, retrieveCount + 1);\n return this._cache.get(key);\n }\n\n set(key: TKey, value: TValue): boolean {\n if (this._cache.has(key) || this._capacity < this._cache.size) {\n this._cache.set(key, value);\n return true;\n } else {\n // TODO 2020-12-05 larsmoa: Very inefficient way to set value.\n // We often set a value and discard it a moment later because its not\n // imporant. Fix this.\n this._cache.set(key, value);\n this.ensureWithinCapacity();\n return this._cache.has(key);\n }\n }\n\n remove(key: TKey): boolean {\n this._retrieves.delete(key);\n const value = this._cache.get(key);\n if (value !== undefined) {\n if (this._disposeCallback !== undefined) {\n this._disposeCallback(value);\n }\n this._cache.delete(key);\n return true;\n }\n return false;\n }\n\n clear() {\n if (this._disposeCallback !== undefined) {\n for (const value of this._cache.values()) {\n this._disposeCallback(value);\n }\n }\n this._retrieves.clear();\n this._cache.clear();\n }\n\n private ensureWithinCapacity(): void {\n if (this._capacity >= this._cache.size) return;\n const keys = Array.from(this._cache.keys());\n // Figure out what to remove\n const keysForRemoval = keys\n .map(x => ({ key: x, retrivalCount: this._retrieves.get(x) || 0 }))\n .sort((a, b) => a.retrivalCount - b.retrivalCount)\n .slice(0, this._cache.size - this._capacity)\n .map(x => x.key);\n\n for (const key of keysForRemoval) {\n this.remove(key);\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport mixpanel from 'mixpanel-browser';\n\nimport log from '@reveal/logger';\n\ntype TrackedEvents = 'init' | 'construct3dViewer' | 'loadModel' | 'error' | 'cameraNavigated';\ntype EventProps = {\n [key: string]: any;\n // names mentioned instead of just `string` type for typo protection,\n // better than nothing, easier than anything else\n moduleName:\n | 'RevealManager'\n | 'createRevealManager'\n | 'Cognite3DViewer'\n | 'CadManager'\n | 'CachedRepository'\n | 'Cognite3DModel'\n | 'sectorUtilities';\n methodName: string;\n};\n\nconst { VERSION, MIXPANEL_TOKEN } = process.env;\n\nlet globalLogMetrics = true;\nconst globalProps = {\n VERSION,\n project: 'unknown',\n application: 'unknown',\n // Use a random identifier because we want to don't track users over multiple sessions to not\n // violate GDPR.\n sessionId: generateUuidv4()\n};\n// Don't identify users in MixPanel to avoid GDPR problems\nconst mixpanelDistinctId = 'reveal-single-user';\n\n/**\n * Source: https://stackoverflow.com/a/2117523/167251\n */\nfunction generateUuidv4(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0,\n v = c == 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function initMetrics(logMetrics: boolean, project: string, applicationId: string, eventProps: EventProps) {\n // Even though mixpanel has an opt out property, the mixpanel object\n // used by Metrics is not available here, so we have our own way of opting out.\n globalLogMetrics = logMetrics;\n if (!globalLogMetrics) {\n return;\n }\n\n mixpanel.init(MIXPANEL_TOKEN, {\n disable_cookie: true,\n disable_persistence: true,\n // Don't send IP which disables geolocation\n ip: false,\n // Avoid sending a bunch of properties that might help identifying a user\n property_blacklist: [\n // https://help.mixpanel.com/hc/en-us/articles/115004613766-Default-Properties-Collected-by-Mixpanel#profile-properties-javascript\n '$city',\n '$region',\n 'mp_country_code',\n '$geo_source',\n '$timezone',\n 'mp_lib',\n '$lib_version',\n '$device_id',\n '$user_id',\n '$current_url',\n '$screen_width',\n '$screen_height',\n '$referrer',\n '$referring_domain',\n '$initial_referrer',\n '$initial_referring_domain'\n ]\n });\n // Reset device ID (even if we don't send it)\n mixpanel.reset();\n\n mixpanel.identify(mixpanelDistinctId);\n\n if (project) {\n globalProps.project = project;\n }\n if (applicationId) {\n globalProps.application = applicationId;\n }\n trackEvent('init', eventProps);\n}\n\nexport function trackEvent(eventName: TrackedEvents, eventProps: EventProps) {\n if (!globalLogMetrics) {\n return;\n }\n const combined = { ...globalProps, ...eventProps };\n mixpanel.track(eventName, combined);\n}\n\nexport function trackLoadModel(eventProps: EventProps, modelIdentifier: any) {\n trackEvent('loadModel', { ...eventProps, modelIdentifier });\n}\n\nexport function trackError(error: Error, eventProps: EventProps) {\n log.error(error);\n\n trackEvent('error', {\n message: error.message,\n name: error.name,\n stack: error.stack,\n ...eventProps\n });\n}\n\nexport function trackCameraNavigation(eventProps: EventProps) {\n trackEvent('cameraNavigated', eventProps);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Handler for THREE.BufferAttribute.onUpload() that frees the underlying JS side array\n * of values after they have been uploaded to the GPU.\n *\n * @example\n * const geometry = new THREE.BufferGeometry();\n * const indices = new THREE.Uint32BufferAttribute(mesh.indices.buffer, 1).onUpload(disposeAttributeArrayOnUpload);\n * const vertices = new THREE.Float32BufferAttribute(mesh.vertices.buffer, 3).onUpload(disposeAttributeArrayOnUpload);\n * const colors = new THREE.Float32BufferAttribute(mesh.colors.buffer, 3).onUpload(disposeAttributeArrayOnUpload);\n * const treeIndices = new THREE.Float32BufferAttribute(mesh.treeIndices.buffer, 1).onUpload(disposeAttributeArrayOnUpload);\n */\nexport function disposeAttributeArrayOnUpload(this: { array: ArrayLike<number> }) {\n (this.array as ArrayLike<number> | null) = null;\n}\n","module.exports = require(\"rxjs/operators\");","module.exports = require(\"glslify\");","module.exports = require(\"rxjs\");","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport enum NodeOutlineColor {\n NoOutline = 0,\n White,\n Black,\n Cyan,\n Blue,\n Green,\n Red,\n Orange\n}\n\n/**\n * Type for defining node appearance profiles to style a 3D CAD model.\n * @see {@link DefaultNodeAppearance}\n */\nexport type NodeAppearance = {\n /**\n * Overrides the default color of the node in RGB. Each component\n * is in range [0, 255]. `[0, 0, 0]` means no override.\n */\n readonly color?: [number, number, number];\n /**\n * Overrides the visibility of the node.\n */\n readonly visible?: boolean;\n /**\n * When set to true, the node is rendered in front\n * of all other nodes even if it's occluded.\n * Note that this take precedence over {@link renderGhosted}.\n */\n readonly renderInFront?: boolean;\n /**\n * When set to true, the node is rendered ghosted, i.e.\n * transparent with a fixed color. This has no effect if {@link renderInFront}\n * is `true`.\n */\n readonly renderGhosted?: boolean;\n /**\n * When set, an outline is drawn around the\n * node to make it stand out.\n */\n readonly outlineColor?: NodeOutlineColor;\n};\n\nconst OutlinedAppearance: NodeAppearance = {\n visible: true,\n outlineColor: NodeOutlineColor.White\n};\n\nconst HiddenAppearance: NodeAppearance = {\n visible: false\n};\n\nconst InFrontAppearance: NodeAppearance = {\n visible: true,\n renderInFront: true\n};\n\nconst HighlightedColorAppearance: NodeAppearance = {\n visible: true,\n color: [100, 100, 255]\n};\n\nconst GhostedAppearance: NodeAppearance = {\n visible: true,\n renderGhosted: true\n};\n\nconst DefaultAppearance: NodeAppearance = {\n visible: true,\n renderGhosted: false,\n renderInFront: false,\n outlineColor: NodeOutlineColor.NoOutline,\n color: [0, 0, 0] as [number, number, number]\n};\n\n/**\n * A set of default node appearances used in Reveal.\n */\nexport const DefaultNodeAppearance = {\n Default: DefaultAppearance,\n Outlined: OutlinedAppearance,\n Hidden: HiddenAppearance,\n InFront: InFrontAppearance,\n Ghosted: GhostedAppearance,\n Highlighted: { ...InFrontAppearance, ...HighlightedColorAppearance, ...OutlinedAppearance }\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport assert from 'assert';\nimport { EventTrigger, IndexSet } from '@reveal/utilities';\n\nexport type SerializedNodeCollection = {\n token: string;\n state: any;\n options?: any;\n};\n\n/**\n * Abstract class for implementing a set of nodes to be styled.\n */\nexport abstract class NodeCollectionBase {\n private readonly _changedEvent = new EventTrigger<() => void>();\n private readonly _classToken: string;\n\n protected constructor(classToken: string) {\n this._classToken = classToken;\n }\n\n public get classToken(): string {\n return this._classToken;\n }\n\n /**\n * Subscribe a listener to events about the set changing, i.e.\n * when nodes are added or removed to the set.\n */\n on(event: 'changed', listener: () => void): void {\n assert(event === 'changed');\n this._changedEvent.subscribe(listener);\n }\n\n /**\n * Unsubscribe a listener to events about the set changing, i.e.\n * when nodes are added or removed to the set.\n */\n off(event: 'changed', listener: () => void): void {\n assert(event === 'changed');\n this._changedEvent.unsubscribe(listener);\n }\n\n /**\n * Returns true when the set currently is running an operation\n * for loading the full set of nodes contained by the set.\n */\n abstract get isLoading(): boolean;\n /**\n * Returns the {@link IndexSet} that holds the tree indices\n * of the nodes contained by the set.\n */\n abstract getIndexSet(): IndexSet;\n\n /**\n * Clears the set, making it empty.\n */\n abstract clear(): void;\n\n /**\n * Triggers the changed-event.\n */\n protected notifyChanged() {\n this._changedEvent.fire();\n }\n\n abstract serialize(): SerializedNodeCollection;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { IndexSet } from '@reveal/utilities';\nimport { NodeCollectionBase, SerializedNodeCollection } from './NodeCollectionBase';\n\n/**\n * Node collection that combines the result from multiple underlying node collections.\n */\nexport abstract class CombineNodeCollectionBase extends NodeCollectionBase {\n private _changedUnderlyingNodeCollectionHandler: () => void;\n private _cachedCombinedIndexSet: IndexSet | undefined = undefined;\n protected _nodeCollections: NodeCollectionBase[] = [];\n\n constructor(classToken: string, nodeCollections?: NodeCollectionBase[]) {\n super(classToken);\n\n this._changedUnderlyingNodeCollectionHandler = this.makeDirty.bind(this);\n if (nodeCollections) {\n nodeCollections.forEach(x => this.add(x));\n }\n }\n\n add(nodeCollection: NodeCollectionBase) {\n nodeCollection.on('changed', this._changedUnderlyingNodeCollectionHandler);\n this._nodeCollections.push(nodeCollection);\n this.makeDirty();\n }\n\n remove(nodeCollection: NodeCollectionBase) {\n const index = this._nodeCollections.indexOf(nodeCollection);\n if (index < 0) {\n throw new Error('Could not find set');\n }\n\n nodeCollection.off('changed', this._changedUnderlyingNodeCollectionHandler);\n this._nodeCollections.splice(index, 1);\n this.makeDirty();\n }\n\n /**\n * Clears all underlying node collections.\n */\n clear() {\n this._nodeCollections.forEach(collection => collection.clear());\n }\n\n private makeDirty(): void {\n if (this._cachedCombinedIndexSet === undefined) return;\n this._cachedCombinedIndexSet = undefined;\n this.notifyChanged();\n }\n\n /**\n * @override\n */\n getIndexSet(): IndexSet {\n this._cachedCombinedIndexSet = this._cachedCombinedIndexSet ?? this.createCombinedIndexSet();\n return this._cachedCombinedIndexSet;\n }\n\n /**\n * @override\n */\n get isLoading(): boolean {\n return this._nodeCollections.some(x => x.isLoading);\n }\n\n public abstract serialize(): SerializedNodeCollection;\n\n protected abstract createCombinedIndexSet(): IndexSet;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { NodeCollectionBase, SerializedNodeCollection } from './NodeCollectionBase';\nimport { CombineNodeCollectionBase } from './CombineNodeCollectionBase';\n\nimport { IndexSet } from '@reveal/utilities';\n\n/**\n * Node collection that takes the set union of multiple node collections.\n */\n\nexport class UnionNodeCollection extends CombineNodeCollectionBase {\n public static readonly classToken = 'UnionNodeCollection';\n\n constructor(nodeCollections?: NodeCollectionBase[]) {\n super(UnionNodeCollection.classToken, nodeCollections);\n }\n\n serialize(): SerializedNodeCollection {\n return {\n token: this.classToken,\n state: {\n subCollections: this._nodeCollections.map(set => set.serialize())\n }\n };\n }\n\n protected createCombinedIndexSet() {\n if (this._nodeCollections.length === 0) {\n return new IndexSet();\n }\n const set = this._nodeCollections[0].getIndexSet().clone();\n for (let i = 1; i < this._nodeCollections.length; ++i) {\n set.unionWith(this._nodeCollections[i].getIndexSet());\n }\n return set;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { NodeCollectionBase, SerializedNodeCollection } from './NodeCollectionBase';\nimport { UnionNodeCollection } from './UnionNodeCollection';\nimport { CombineNodeCollectionBase } from './CombineNodeCollectionBase';\n\nimport { IndexSet } from '@reveal/utilities';\n\n/**\n * Node collection that is the intersection between a set of underlying node collections.\n */\nexport class IntersectionNodeCollection extends CombineNodeCollectionBase {\n public static readonly classToken = 'IntersectionNodeCollection';\n\n constructor(nodeCollections?: NodeCollectionBase[]) {\n super(UnionNodeCollection.classToken, nodeCollections);\n }\n\n serialize(): SerializedNodeCollection {\n return {\n token: this.classToken,\n state: {\n subCollections: this._nodeCollections.map(set => set.serialize())\n }\n };\n }\n\n protected createCombinedIndexSet() {\n if (this._nodeCollections.length === 0) {\n return new IndexSet();\n }\n const set = this._nodeCollections[0].getIndexSet().clone();\n for (let i = 1; i < this._nodeCollections.length; ++i) {\n set.intersectWith(this._nodeCollections[i].getIndexSet());\n }\n return set;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { NumericRange, IndexSet } from '@reveal/utilities';\nimport { NodeCollectionBase, SerializedNodeCollection } from './NodeCollectionBase';\n\n/**\n * Node collection that holds a set of nodes defined by a set of tree indices.\n */\nexport class TreeIndexNodeCollection extends NodeCollectionBase {\n public static readonly classToken = 'TreeIndexNodeCollection';\n\n private _treeIndices: IndexSet;\n\n constructor(treeIndexSet?: IndexSet);\n constructor(treeIndices?: Iterable<number>);\n constructor(treeIndexRange?: NumericRange);\n constructor(values?: IndexSet | Iterable<number> | NumericRange) {\n super(TreeIndexNodeCollection.classToken);\n if (values instanceof IndexSet) {\n this._treeIndices = values;\n } else if (values instanceof NumericRange) {\n this._treeIndices = new IndexSet(values);\n } else {\n this._treeIndices = new IndexSet(values);\n }\n }\n\n updateSet(treeIndices: IndexSet) {\n this._treeIndices = treeIndices;\n this.notifyChanged();\n }\n\n /**\n * Sets this set to hold an empty set.\n */\n clear() {\n this._treeIndices = new IndexSet();\n this.notifyChanged();\n }\n\n getIndexSet(): IndexSet {\n return this._treeIndices;\n }\n\n get isLoading(): boolean {\n return false;\n }\n\n serialize(): SerializedNodeCollection {\n return {\n token: this.classToken,\n state: this._treeIndices.toRangeArray()\n };\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { NodeAppearance } from './NodeAppearance';\nimport { NodeCollectionBase } from './NodeCollectionBase';\n\nimport { IndexSet, assertNever, EventTrigger } from '@reveal/utilities';\n\n/**\n * Delegate for applying styles in {@see NodeStyleProvider}.\n * @param treeIndices Set of tree indices that the style is applied to.\n * @param appearance Style to be applied to the nodes.\n */\nexport type ApplyStyleDelegate = (treeIndices: IndexSet, appearance: NodeAppearance) => void;\n\ntype StyledNodeCollection = {\n nodeCollection: NodeCollectionBase;\n appearance: NodeAppearance;\n handleNodeCollectionChangedListener: () => void;\n};\n\nexport class NodeAppearanceProvider {\n private readonly _styledCollections = new Array<StyledNodeCollection>();\n private _lastFiredLoadingState?: boolean;\n\n private readonly _events = {\n changed: new EventTrigger<() => void>(),\n loadingStateChanged: new EventTrigger<(isLoading: boolean) => void>()\n };\n\n on(event: 'changed', listener: () => void): void;\n on(event: 'loadingStateChanged', listener: (isLoading: boolean) => void): void;\n on(event: 'changed' | 'loadingStateChanged', listener: (() => void) | ((isLoading: boolean) => void)): void {\n switch (event) {\n case 'changed':\n this._events.changed.subscribe(listener as () => void);\n break;\n case 'loadingStateChanged':\n this._events.loadingStateChanged.subscribe(listener as (isLoading: boolean) => void);\n break;\n\n default:\n assertNever(event, `Unsupported event: '${event}'`);\n }\n }\n\n off(event: 'changed', listener: () => void): void;\n off(event: 'loadingStateChanged', listener: (isLoading: boolean) => void): void;\n off(event: 'changed' | 'loadingStateChanged', listener: (() => void) | ((isLoading: boolean) => void)): void {\n switch (event) {\n case 'changed':\n this._events.changed.unsubscribe(listener as () => void);\n break;\n case 'loadingStateChanged':\n this._events.loadingStateChanged.unsubscribe(listener as (isLoading: boolean) => void);\n break;\n\n default:\n assertNever(event, `Unsupported event: '${event}'`);\n }\n }\n\n assignStyledNodeCollection(nodeCollection: NodeCollectionBase, appearance: NodeAppearance) {\n const existingCollection = this._styledCollections.find(x => x.nodeCollection === nodeCollection);\n if (existingCollection !== undefined) {\n existingCollection.appearance = appearance;\n this.handleNodeCollectionChanged(existingCollection);\n } else {\n const styledCollection: StyledNodeCollection = {\n nodeCollection: nodeCollection,\n appearance,\n handleNodeCollectionChangedListener: () => {\n this.handleNodeCollectionChanged(styledCollection);\n }\n };\n\n this._styledCollections.push(styledCollection);\n nodeCollection.on('changed', styledCollection.handleNodeCollectionChangedListener);\n this.notifyChanged();\n }\n }\n\n unassignStyledNodeCollection(nodeCollection: NodeCollectionBase) {\n const index = this._styledCollections.findIndex(x => x.nodeCollection === nodeCollection);\n if (index === -1) {\n throw new Error('NodeCollection not added');\n }\n const styledCollection = this._styledCollections[index];\n\n this._styledCollections.splice(index, 1);\n nodeCollection.off('changed', styledCollection.handleNodeCollectionChangedListener);\n this.notifyChanged();\n }\n\n applyStyles(applyCb: ApplyStyleDelegate) {\n this._styledCollections.forEach(styledSet => {\n const set = styledSet.nodeCollection.getIndexSet();\n applyCb(set, styledSet.appearance);\n });\n }\n\n clear() {\n for (const styledSet of this._styledCollections) {\n const nodeCollection = styledSet.nodeCollection;\n nodeCollection.off('changed', styledSet.handleNodeCollectionChangedListener);\n }\n this._styledCollections.splice(0);\n this.notifyChanged();\n }\n\n get isLoading(): boolean {\n return this._styledCollections.some(x => x.nodeCollection.isLoading);\n }\n\n private notifyChanged() {\n this._events.changed.fire();\n }\n\n private notifyLoadingStateChanged() {\n if (this._lastFiredLoadingState === this.isLoading) return;\n this._lastFiredLoadingState = this.isLoading;\n this._events.loadingStateChanged.fire(this.isLoading);\n }\n\n private handleNodeCollectionChanged(_styledSet: StyledNodeCollection) {\n this.notifyChanged();\n this.notifyLoadingStateChanged();\n }\n}\n","module.exports = require(\"assert\");","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { AutoDisposeGroup } from '@reveal/utilities';\nimport { LevelOfDetail } from '@reveal/cad-parsers';\n\nexport class SectorNode extends THREE.Group {\n public readonly sectorPath: string;\n public readonly sectorId: number;\n public readonly bounds: THREE.Box3;\n public readonly depth: number;\n\n private _group?: AutoDisposeGroup;\n private _lod = LevelOfDetail.Discarded;\n private _updatedTimestamp: number = Date.now();\n\n constructor(sectorId: number, sectorPath: string, bounds: THREE.Box3) {\n super();\n this.name = `Sector ${sectorPath} [id=${sectorId}]`;\n this.sectorId = sectorId;\n this.sectorPath = sectorPath;\n this.bounds = bounds;\n this.depth = determineSectorDepth(sectorPath);\n }\n\n get levelOfDetail(): LevelOfDetail {\n return this._lod;\n }\n\n get group(): THREE.Group | undefined {\n return this._group;\n }\n\n get updatedTimestamp(): number {\n return this._updatedTimestamp;\n }\n\n updateGeometry(geomtryGroup: AutoDisposeGroup | undefined, levelOfDetail: LevelOfDetail) {\n this.resetGeometry();\n this._group = geomtryGroup;\n if (this._group !== undefined) {\n this._group.reference();\n }\n this._lod = levelOfDetail;\n this._updatedTimestamp = Date.now();\n this.visible = this._lod !== LevelOfDetail.Discarded;\n this.updateMatrixWorld(true);\n }\n\n resetGeometry() {\n if (this._group !== undefined) {\n this._group.dereference();\n this.remove(this._group);\n }\n\n this._group = undefined;\n this._lod = LevelOfDetail.Discarded;\n this._updatedTimestamp = Date.now();\n }\n}\n\nfunction determineSectorDepth(path: string): number {\n let depth = 0;\n for (let i = 0; i < path.length; ++i) {\n depth += path[i] === '/' ? 1 : 0;\n }\n return depth - 1;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { SectorNode } from './SectorNode';\nimport { CadModelMetadata, SectorMetadata } from '@reveal/cad-parsers';\n\nexport class RootSectorNode extends SectorNode {\n public readonly sectorNodeMap: Map<number, SectorNode>;\n\n constructor(modelMetadata: CadModelMetadata) {\n const modelBounds = modelMetadata.scene.root.bounds.clone();\n modelBounds.applyMatrix4(modelMetadata.modelMatrix);\n super(0, '/', modelBounds);\n\n const { scene, modelMatrix } = modelMetadata;\n this.sectorNodeMap = new Map();\n buildScene(scene.root, this, this.sectorNodeMap, modelMatrix);\n\n // Disable automatic update of matrices of the subtree as it\n // is quite time consuming. We trust that our owner keeps\n // our matrices updated.\n this.matrixAutoUpdate = false;\n this.setModelTransformation(modelMatrix);\n }\n\n setModelTransformation(matrix: THREE.Matrix4): void {\n this.matrix.copy(matrix);\n this.updateMatrixWorld(true);\n }\n\n getModelTransformation(out = new THREE.Matrix4()): THREE.Matrix4 {\n return out.copy(this.matrix);\n }\n}\n\nfunction buildScene(\n sector: SectorMetadata,\n parent: SectorNode,\n sectorNodeMap: Map<number, SectorNode>,\n modelMatrix: THREE.Matrix4\n) {\n const bounds = sector.bounds.clone();\n bounds.applyMatrix4(modelMatrix);\n const sectorGroup = new SectorNode(sector.id, sector.path, bounds);\n sectorGroup.name = `Sector ${sector.id}`;\n parent.add(sectorGroup);\n sectorGroup.matrixAutoUpdate = false;\n sectorGroup.updateMatrixWorld(true);\n\n sectorNodeMap.set(sector.id, sectorGroup);\n for (const child of sector.children) {\n buildScene(child, sectorGroup, sectorNodeMap, modelMatrix);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { DynamicDefragmentedBuffer } from '@reveal/utilities';\nimport { CadMaterialManager } from './material-manager/CadMaterialManager';\nimport { InstancedMesh, InstancedMeshFile } from '@reveal/cad-parsers';\n\nexport class InstancedMeshManager {\n private readonly _instancedGeometryMap: Map<\n number,\n { vertices: THREE.Float32BufferAttribute; indices: THREE.Uint32BufferAttribute }\n >;\n\n private readonly _instancedAttributeMap: Map<\n string,\n {\n mesh: THREE.InstancedMesh;\n treeIndexBuffer: DynamicDefragmentedBuffer<Float32Array>;\n colorBuffer: DynamicDefragmentedBuffer<Uint8Array>;\n instanceMatrixBuffer: DynamicDefragmentedBuffer<Float32Array>;\n updateAttributes: () => void;\n }\n >;\n\n private readonly _processedSectorMap: Map<\n number,\n { instanceIdentifier: string; treeIndicesbatchId: number; colorsBatchId: number; instanceMatricesBatchId: number }[]\n >;\n\n private readonly _instancedMeshGroup: THREE.Group;\n private readonly _materialManager: CadMaterialManager;\n\n constructor(instancedMeshGroup: THREE.Group, materialManager: CadMaterialManager) {\n this._materialManager = materialManager;\n\n this._instancedGeometryMap = new Map();\n this._instancedAttributeMap = new Map();\n\n this._processedSectorMap = new Map();\n\n this._instancedMeshGroup = instancedMeshGroup;\n }\n\n public addInstanceMeshes(meshFile: InstancedMeshFile, modelIdentifier: string, sectorId: number) {\n if (this._processedSectorMap.has(sectorId)) {\n return;\n }\n\n if (!this._instancedGeometryMap.has(meshFile.fileId)) {\n this._instancedGeometryMap.set(meshFile.fileId, {\n vertices: new THREE.Float32BufferAttribute(meshFile.vertices.buffer, 3),\n indices: new THREE.Uint32BufferAttribute(meshFile.indices.buffer, 1)\n });\n }\n\n const geometryAttributes = this._instancedGeometryMap.get(meshFile.fileId)!;\n const material = this._materialManager.getModelMaterials(modelIdentifier).instancedMesh;\n\n for (const instance of meshFile.instances) {\n const instanceIdentifier = JSON.stringify([meshFile.fileId, instance.triangleOffset]);\n\n if (!this._instancedAttributeMap.has(instanceIdentifier)) {\n this.createInstance(instance, geometryAttributes, material, instanceIdentifier, sectorId);\n } else {\n const currentAttributes = this._instancedAttributeMap.get(instanceIdentifier)!;\n\n const treeAdd = currentAttributes.treeIndexBuffer.add(instance.treeIndices);\n const colorAdd = currentAttributes.colorBuffer.add(instance.colors);\n const matrixAdd = currentAttributes.instanceMatrixBuffer.add(instance.instanceMatrices);\n currentAttributes.updateAttributes();\n\n this.addBatchDescriptor(instanceIdentifier, treeAdd.batchId, colorAdd.batchId, matrixAdd.batchId, sectorId);\n\n currentAttributes.mesh.count = currentAttributes.treeIndexBuffer.length;\n\n if (treeAdd.bufferIsReallocated || colorAdd.bufferIsReallocated || matrixAdd.bufferIsReallocated) {\n this.recreateBufferGeometry(geometryAttributes, currentAttributes, instance, instanceIdentifier);\n }\n }\n }\n }\n\n public removeSectorInstancedMeshes(sectorId: number) {\n const sectorBatchDescriptors = this._processedSectorMap.get(sectorId);\n\n if (!sectorBatchDescriptors) {\n return;\n }\n\n for (const sectorBatchDescriptor of sectorBatchDescriptors) {\n const attributeBuffers = this._instancedAttributeMap.get(sectorBatchDescriptor.instanceIdentifier);\n\n if (attributeBuffers === undefined) {\n throw new Error(`Cannot resolve instance identifier for sector ${sectorId}`);\n }\n\n attributeBuffers.treeIndexBuffer.remove(sectorBatchDescriptor.treeIndicesbatchId);\n attributeBuffers.colorBuffer.remove(sectorBatchDescriptor.colorsBatchId);\n attributeBuffers.instanceMatrixBuffer.remove(sectorBatchDescriptor.instanceMatricesBatchId);\n\n attributeBuffers.updateAttributes();\n attributeBuffers.mesh.count = attributeBuffers.treeIndexBuffer.length;\n }\n\n this._processedSectorMap.delete(sectorId);\n }\n\n private createInstancedBufferGeometry(\n vertices: THREE.Float32BufferAttribute,\n indices: THREE.Uint32BufferAttribute,\n treeIndexBuffer: DynamicDefragmentedBuffer<Float32Array>,\n colorBuffer: DynamicDefragmentedBuffer<Uint8Array>,\n instanceMatrixBuffer: DynamicDefragmentedBuffer<Float32Array>\n ): [THREE.InstancedBufferGeometry, () => void] {\n const instanceGeometry = new THREE.InstancedBufferGeometry();\n\n instanceGeometry.setIndex(indices);\n instanceGeometry.setAttribute('position', vertices);\n\n const treeIndexAttribute = new THREE.InstancedBufferAttribute(treeIndexBuffer.buffer, 1);\n instanceGeometry.setAttribute('a_treeIndex', treeIndexAttribute);\n\n const colorAttribute = new THREE.InstancedBufferAttribute(colorBuffer.buffer, 4, true);\n instanceGeometry.setAttribute('a_color', colorAttribute);\n\n const instanceMatrixInterleavedBuffer = new THREE.InstancedInterleavedBuffer(instanceMatrixBuffer.buffer, 16);\n for (let column = 0; column < 4; column++) {\n const attribute = new THREE.InterleavedBufferAttribute(instanceMatrixInterleavedBuffer, 4, column * 4);\n instanceGeometry.setAttribute(`a_instanceMatrix_column_${column}`, attribute);\n }\n\n const updateAttributes = () => {\n treeIndexAttribute.needsUpdate = true;\n colorAttribute.needsUpdate = true;\n instanceMatrixInterleavedBuffer.needsUpdate = true;\n };\n\n return [instanceGeometry, updateAttributes];\n }\n\n private recreateBufferGeometry(\n geometryAttributes: { vertices: THREE.Float32BufferAttribute; indices: THREE.Uint32BufferAttribute },\n currentAttributes: {\n mesh: THREE.InstancedMesh;\n treeIndexBuffer: DynamicDefragmentedBuffer<Float32Array>;\n colorBuffer: DynamicDefragmentedBuffer<Uint8Array>;\n instanceMatrixBuffer: DynamicDefragmentedBuffer<Float32Array>;\n updateAttributes: () => void;\n },\n instance: InstancedMesh,\n instanceIdentifier: string\n ) {\n const [bufferGeometry, updateAttributesCallback] = this.createInstancedBufferGeometry(\n geometryAttributes.vertices,\n geometryAttributes.indices,\n currentAttributes.treeIndexBuffer,\n currentAttributes.colorBuffer,\n currentAttributes.instanceMatrixBuffer\n );\n\n bufferGeometry.setDrawRange(instance.triangleOffset * 3, instance.triangleCount * 3);\n\n currentAttributes.mesh.geometry.dispose();\n\n currentAttributes.mesh.geometry = bufferGeometry;\n\n currentAttributes.mesh.count = currentAttributes.treeIndexBuffer.length;\n\n this._instancedAttributeMap.set(instanceIdentifier, {\n mesh: currentAttributes.mesh,\n treeIndexBuffer: currentAttributes.treeIndexBuffer,\n colorBuffer: currentAttributes.colorBuffer,\n instanceMatrixBuffer: currentAttributes.instanceMatrixBuffer,\n updateAttributes: updateAttributesCallback\n });\n }\n\n private createInstance(\n instance: InstancedMesh,\n geometryAttributes: { vertices: THREE.Float32BufferAttribute; indices: THREE.Uint32BufferAttribute },\n material: THREE.ShaderMaterial,\n instanceIdentifier: string,\n sectorId: number\n ) {\n const dynamicTreeIndicesBuffer = new DynamicDefragmentedBuffer<Float32Array>(\n instance.treeIndices.length,\n Float32Array\n );\n const treeIndicesAdd = dynamicTreeIndicesBuffer.add(instance.treeIndices);\n\n const dynamicColorsBuffer = new DynamicDefragmentedBuffer<Uint8Array>(instance.colors.length, Uint8Array);\n const colorsAdd = dynamicColorsBuffer.add(instance.colors);\n\n const dynamicinstanceMatricesBuffer = new DynamicDefragmentedBuffer<Float32Array>(\n instance.instanceMatrices.length,\n Float32Array\n );\n const instanceMatricesAdd = dynamicinstanceMatricesBuffer.add(instance.instanceMatrices);\n\n this.addBatchDescriptor(\n instanceIdentifier,\n treeIndicesAdd.batchId,\n colorsAdd.batchId,\n instanceMatricesAdd.batchId,\n sectorId\n );\n\n const [instanceGeometry, updateAttributesCallback] = this.createInstancedBufferGeometry(\n geometryAttributes.vertices,\n geometryAttributes.indices,\n dynamicTreeIndicesBuffer,\n dynamicColorsBuffer,\n dynamicinstanceMatricesBuffer\n );\n\n instanceGeometry.setDrawRange(instance.triangleOffset * 3, instance.triangleCount * 3);\n\n const instanceMesh = new THREE.InstancedMesh(instanceGeometry, material, dynamicTreeIndicesBuffer.length);\n\n instanceMesh.frustumCulled = false;\n\n this._instancedAttributeMap.set(instanceIdentifier, {\n mesh: instanceMesh,\n treeIndexBuffer: dynamicTreeIndicesBuffer,\n colorBuffer: dynamicColorsBuffer,\n instanceMatrixBuffer: dynamicinstanceMatricesBuffer,\n updateAttributes: updateAttributesCallback\n });\n\n this._instancedMeshGroup.add(instanceMesh);\n\n instanceMesh.updateMatrixWorld(true);\n }\n\n private addBatchDescriptor(\n instanceIdentifier: string,\n treeIndicesBatchId: number,\n colorsBatchId: number,\n instanceMatricesBatchId: number,\n sectorId: number\n ) {\n const batchDescriptor: {\n instanceIdentifier: string;\n treeIndicesbatchId: number;\n colorsBatchId: number;\n instanceMatricesBatchId: number;\n } = {\n instanceIdentifier: instanceIdentifier,\n treeIndicesbatchId: treeIndicesBatchId,\n colorsBatchId: colorsBatchId,\n instanceMatricesBatchId: instanceMatricesBatchId\n };\n\n const descriptorList = this._processedSectorMap.get(sectorId);\n\n if (!descriptorList) {\n this._processedSectorMap.set(sectorId, [batchDescriptor]);\n } else {\n descriptorList.push(batchDescriptor);\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { SectorQuads } from './material-manager/rendering/types';\nimport { RootSectorNode } from './sector/RootSectorNode';\nimport { CadMaterialManager } from './material-manager/CadMaterialManager';\nimport { suggestCameraConfig } from './cameraconfig';\nimport { NodeTransformProvider } from './material-manager/styling/NodeTransformProvider';\nimport { InstancedMeshManager } from './InstancedMeshManager';\n\nimport { SectorScene, CadModelMetadata, RenderMode, SectorGeometry, InstancedMeshFile } from '@reveal/cad-parsers';\nimport { NodeAppearanceProvider, NodeAppearance } from '@reveal/cad-styling';\n\nexport type ParseCallbackDelegate = (parsed: { lod: string; data: SectorGeometry | SectorQuads }) => void;\n\nexport interface SuggestedCameraConfig {\n position: THREE.Vector3;\n target: THREE.Vector3;\n near: number;\n far: number;\n}\n\nexport class CadNode extends THREE.Object3D {\n private readonly _rootSector: RootSectorNode;\n private readonly _cadModelMetadata: CadModelMetadata;\n private readonly _materialManager: CadMaterialManager;\n private readonly _sectorScene: SectorScene;\n private readonly _previousCameraMatrix = new THREE.Matrix4();\n private readonly _instancedMeshManager: InstancedMeshManager;\n\n constructor(model: CadModelMetadata, materialManager: CadMaterialManager) {\n super();\n this.type = 'CadNode';\n this.name = 'Sector model';\n this._materialManager = materialManager;\n\n const instancedMeshGroup = new THREE.Group();\n instancedMeshGroup.name = 'InstancedMeshes';\n\n this._instancedMeshManager = new InstancedMeshManager(instancedMeshGroup, materialManager);\n\n const rootSector = new RootSectorNode(model);\n\n rootSector.add(instancedMeshGroup);\n\n this._cadModelMetadata = model;\n const { scene } = model;\n\n this._sectorScene = scene;\n // Ensure camera matrix is unequal on first frame\n this._previousCameraMatrix.elements[0] = Infinity;\n\n // Prepare renderables\n this._rootSector = rootSector;\n this.add(rootSector);\n\n this.matrixAutoUpdate = false;\n this.updateMatrixWorld();\n this.setModelTransformation(model.modelMatrix);\n }\n\n get nodeTransformProvider(): NodeTransformProvider {\n return this._materialManager.getModelNodeTransformProvider(this._cadModelMetadata.modelIdentifier);\n }\n\n get nodeAppearanceProvider(): NodeAppearanceProvider {\n return this._materialManager.getModelNodeAppearanceProvider(this._cadModelMetadata.modelIdentifier);\n }\n\n get defaultNodeAppearance(): NodeAppearance {\n return this._materialManager.getModelDefaultNodeAppearance(this._cadModelMetadata.modelIdentifier);\n }\n\n set defaultNodeAppearance(appearance: NodeAppearance) {\n this._materialManager.setModelDefaultNodeAppearance(this._cadModelMetadata.modelIdentifier, appearance);\n }\n\n get clippingPlanes(): THREE.Plane[] {\n return this._materialManager.clippingPlanes;\n }\n\n set clippingPlanes(planes: THREE.Plane[]) {\n this._materialManager.clippingPlanes = planes;\n }\n\n get cadModelMetadata() {\n return this._cadModelMetadata;\n }\n\n get sectorScene(): SectorScene {\n return this._sectorScene;\n }\n\n get rootSector() {\n return this._rootSector;\n }\n\n get materialManager() {\n return this._materialManager;\n }\n\n set renderMode(mode: RenderMode) {\n this._materialManager.setRenderMode(mode);\n }\n\n get renderMode() {\n return this._materialManager.getRenderMode();\n }\n\n /**\n * Sets transformation matrix of the model. This overrides the current transformation.\n * @param matrix Transformation matrix.\n */\n setModelTransformation(matrix: THREE.Matrix4): void {\n this._rootSector.setModelTransformation(matrix);\n this._cadModelMetadata.modelMatrix.copy(matrix);\n }\n\n /**\n * Gets transformation matrix of the model\n * @param out Preallocated `THREE.Matrix4` (optional).\n */\n getModelTransformation(out?: THREE.Matrix4): THREE.Matrix4 {\n return this._rootSector.getModelTransformation(out);\n }\n\n public suggestCameraConfig(): SuggestedCameraConfig {\n const { position, target, near, far } = suggestCameraConfig(this._sectorScene.root);\n\n const modelMatrix = this.getModelTransformation();\n const threePos = position.clone();\n const threeTarget = target.clone();\n threePos.applyMatrix4(modelMatrix);\n threeTarget.applyMatrix4(modelMatrix);\n\n return {\n position: threePos,\n target: threeTarget,\n near,\n far\n };\n }\n\n public updateInstancedMeshes(instanceMeshFiles: InstancedMeshFile[], modelIdentifier: string, sectorId: number) {\n for (const instanceMeshFile of instanceMeshFiles) {\n this._instancedMeshManager.addInstanceMeshes(instanceMeshFile, modelIdentifier, sectorId);\n }\n }\n\n public discardInstancedMeshes(sectorId: number) {\n this._instancedMeshManager.removeSectorInstancedMeshes(sectorId);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nimport { SectorMetadata } from '@reveal/cad-parsers';\nimport { traverseDepthFirst } from '@reveal/utilities';\n\nexport interface SuggestedCameraConfig {\n position: THREE.Vector3;\n target: THREE.Vector3;\n near: number;\n far: number;\n}\n\nexport function suggestCameraConfig(rootSector: SectorMetadata): SuggestedCameraConfig {\n const averageMin = new THREE.Vector3();\n const averageMax = new THREE.Vector3();\n let count = 0;\n\n traverseDepthFirst(rootSector, node => {\n averageMin.add(node.bounds.min);\n averageMax.add(node.bounds.max);\n count += 1;\n return true;\n });\n\n averageMin.divideScalar(count);\n averageMax.divideScalar(count);\n\n const bounds = new THREE.Box3(averageMin, averageMax);\n const target = bounds.getCenter(new THREE.Vector3());\n const extent = bounds.getSize(new THREE.Vector3());\n extent.x *= -2.0;\n extent.y *= -2.0;\n extent.z *= 2.0;\n\n const position = new THREE.Vector3().addVectors(target, extent);\n\n return {\n position,\n target,\n near: 0.1,\n far: position.distanceTo(target) * 12\n };\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\n/**\n * Generate a three-dimensional plane geometry,\n * with an optional applied tranformation function (u, v) => [ x, y, z ]\n */\nfunction generatePlane3D(\n segmentsX: number,\n segmentsY: number,\n transformFunc: (u: number, v: number) => number[] = (u, v) => [u, v, 0]\n) {\n const vertices = [];\n const indices = [];\n\n const segmentsXInv = 1 / segmentsX;\n const segmentsYInv = 1 / segmentsY;\n for (let j = 0; j <= segmentsY; j++) {\n for (let i = 0; i <= segmentsX; i++) {\n // vertices\n const [x, y, z] = transformFunc(i * segmentsXInv, j * segmentsYInv);\n vertices.push(x || 0, y || 0, z || 0);\n }\n }\n\n for (let j = 1; j <= segmentsY; j++) {\n for (let i = 1; i <= segmentsX; i++) {\n // indices\n const a = (segmentsX + 1) * j + i - 1;\n const b = (segmentsX + 1) * (j - 1) + i - 1;\n const c = (segmentsX + 1) * (j - 1) + i;\n const d = (segmentsX + 1) * j + i;\n\n // faces\n indices.push(a, b, d);\n indices.push(b, c, d);\n }\n }\n\n return {\n index: new THREE.Uint16BufferAttribute(indices, 1),\n position: new THREE.Float32BufferAttribute(vertices, 3)\n };\n}\n\nexport const { boxGeometry, boxGeometryBoundingBox } = (() => {\n const geometry = new THREE.BoxBufferGeometry(1, 1, 1, 1, 1, 1);\n try {\n const result = {\n index: geometry.getIndex(),\n position: geometry.getAttribute('position'),\n normal: geometry.getAttribute('normal')\n };\n geometry.computeBoundingBox();\n return { boxGeometry: result, boxGeometryBoundingBox: geometry.boundingBox! };\n } finally {\n geometry.dispose();\n }\n})();\n\nexport const { quadGeometry, quadGeometryBoundingBox } = (() => {\n const geometry = new THREE.PlaneBufferGeometry(1, 1, 1, 1);\n try {\n const result = {\n index: geometry.getIndex(),\n position: geometry.getAttribute('position'),\n normal: geometry.getAttribute('normal')\n };\n geometry.computeBoundingBox();\n return { quadGeometry: result, quadGeometryBoundingBox: geometry.boundingBox! };\n } finally {\n geometry.dispose();\n }\n})();\n\nexport const { trapeziumGeometry, trapeziumGeometryBoundingBox } = (() => {\n const index = [0, 1, 3, 0, 3, 2];\n const position = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3];\n return {\n trapeziumGeometry: {\n index: new THREE.BufferAttribute(new Uint16Array(index), 1),\n position: new THREE.BufferAttribute(new Float32Array(position), 3)\n },\n trapeziumGeometryBoundingBox: new THREE.Box3().setFromArray(position)\n };\n})();\n\n// cone\nexport const { coneGeometry, coneGeometryBoundingBox } = (() => {\n const positions = [];\n positions.push(-1, 1, -1);\n positions.push(-1, -1, -1);\n positions.push(1, 1, -1);\n positions.push(1, -1, -1);\n positions.push(1, 1, 1);\n positions.push(1, -1, 1);\n\n const indices = new Uint16Array([1, 2, 0, 1, 3, 2, 3, 4, 2, 3, 5, 4]);\n return {\n coneGeometry: {\n index: new THREE.BufferAttribute(indices, 1),\n position: new THREE.BufferAttribute(new Float32Array(positions), 3)\n },\n coneGeometryBoundingBox: new THREE.Box3().setFromArray(positions)\n };\n})();\n\nexport const { torusLodGeometries, torusGeometryBoundingBox } = (() => {\n const lods = [\n { tubularSegments: 9, radialSegments: 18 },\n { tubularSegments: 5, radialSegments: 12 },\n { tubularSegments: 4, radialSegments: 5 }\n ];\n const transformFunc = (u: number, v: number) => [u, v * 2.0 * Math.PI];\n const torusLodGeometries = lods.map(({ tubularSegments, radialSegments }) => {\n return generatePlane3D(radialSegments, tubularSegments, transformFunc);\n });\n\n return {\n torusLodGeometries,\n torusGeometryBoundingBox: new THREE.Box3().setFromArray(\n torusLodGeometries[torusLodGeometries.length - 1].position.array\n )\n };\n})();\n\nexport const { nutGeometry, nutGeometryBoundingBox } = (() => {\n const geometry = new THREE.CylinderBufferGeometry(0.5, 0.5, 1, 6);\n try {\n geometry.applyMatrix4(new THREE.Matrix4().makeRotationX(-Math.PI / 2));\n const result = {\n index: geometry.getIndex(),\n position: geometry.getAttribute('position'),\n normal: geometry.getAttribute('normal')\n };\n return { nutGeometry: result, nutGeometryBoundingBox: new THREE.Box3().setFromArray(result.position.array) };\n } finally {\n geometry.dispose();\n }\n})();\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\nimport { ParsePrimitiveAttribute } from '@cognite/reveal-parser-worker';\n\nconst computeBoundingBoxFromCenterAndRadiusAttributesVars = {\n centerA: new THREE.Vector3(),\n centerB: new THREE.Vector3(),\n sphere: new THREE.Sphere(),\n box: new THREE.Box3()\n};\n\nexport function computeBoundingBoxFromCenterAndRadiusAttributes(\n centerAattribute: ParsePrimitiveAttribute,\n centerBattribute: ParsePrimitiveAttribute,\n radiusAattribute: ParsePrimitiveAttribute,\n radiusBattribute: ParsePrimitiveAttribute,\n attributeFloatValues: Float32Array,\n elementSize: number,\n elementIndex: number,\n out: THREE.Box3\n): THREE.Box3 {\n const { centerA, centerB, sphere, box } = computeBoundingBoxFromCenterAndRadiusAttributesVars;\n\n function readAttribute(attribute: ParsePrimitiveAttribute, idx: number = 0): number {\n const offset = (elementIndex * elementSize + attribute.offset) / attributeFloatValues.BYTES_PER_ELEMENT;\n return attributeFloatValues[offset + idx];\n }\n\n centerA.set(\n readAttribute(centerAattribute, 0),\n readAttribute(centerAattribute, 1),\n readAttribute(centerAattribute, 2)\n );\n centerB.set(\n readAttribute(centerBattribute, 0),\n readAttribute(centerBattribute, 1),\n readAttribute(centerBattribute, 2)\n );\n const radiusA = readAttribute(radiusAattribute);\n const radiusB = readAttribute(radiusBattribute);\n\n // Note! Not the tighest fit we could make, works ok for now but could be improved by\n // using normal of each cap to determine exact end points of the top/bottom\n sphere.set(centerA, radiusA);\n sphere.getBoundingBox(out);\n sphere.set(centerB, radiusB);\n sphere.getBoundingBox(box);\n out.expandByPoint(box.min);\n out.expandByPoint(box.max);\n return out;\n}\n\nconst computeBoundingBoxFromVertexAttributesVars = {\n vertex1: new THREE.Vector3(),\n vertex2: new THREE.Vector3(),\n vertex3: new THREE.Vector3(),\n vertex4: new THREE.Vector3()\n};\n\nexport function computeBoundingBoxFromVertexAttributes(\n vertex1Attribute: ParsePrimitiveAttribute,\n vertex2Attribute: ParsePrimitiveAttribute,\n vertex3Attribute: ParsePrimitiveAttribute,\n vertex4Attribute: ParsePrimitiveAttribute,\n attributeFloatValues: Float32Array,\n elementSize: number,\n elementIndex: number,\n out: THREE.Box3\n): THREE.Box3 {\n const { vertex1, vertex2, vertex3, vertex4 } = computeBoundingBoxFromVertexAttributesVars;\n\n function readAttribute(attribute: ParsePrimitiveAttribute, idx: number = 0): number {\n const offset = (elementIndex * elementSize + attribute.offset) / attributeFloatValues.BYTES_PER_ELEMENT;\n return attributeFloatValues[offset + idx];\n }\n\n vertex1.set(\n readAttribute(vertex1Attribute, 0),\n readAttribute(vertex1Attribute, 1),\n readAttribute(vertex1Attribute, 2)\n );\n vertex2.set(\n readAttribute(vertex2Attribute, 0),\n readAttribute(vertex2Attribute, 1),\n readAttribute(vertex2Attribute, 2)\n );\n vertex3.set(\n readAttribute(vertex3Attribute, 0),\n readAttribute(vertex3Attribute, 1),\n readAttribute(vertex3Attribute, 2)\n );\n vertex4.set(\n readAttribute(vertex4Attribute, 0),\n readAttribute(vertex4Attribute, 1),\n readAttribute(vertex4Attribute, 2)\n );\n\n out.setFromPoints([vertex1, vertex2, vertex3, vertex4]);\n return out;\n}\n\nconst computeBoundingBoxFromInstanceMatrixAttributesVars = {\n instanceMatrix: new THREE.Matrix4()\n};\n\nexport function computeBoundingBoxFromInstanceMatrixAttributes(\n instanceMatrixAttribute: ParsePrimitiveAttribute,\n attributeFloatValues: Float32Array,\n elementSize: number,\n elementIndex: number,\n baseBoundingBox: THREE.Box3,\n out: THREE.Box3\n): THREE.Box3 {\n const { instanceMatrix } = computeBoundingBoxFromInstanceMatrixAttributesVars;\n\n const offset = (elementIndex * elementSize + instanceMatrixAttribute.offset) / attributeFloatValues.BYTES_PER_ELEMENT;\n // Note! set() accepts row-major, stored column-major\n instanceMatrix.set(\n attributeFloatValues[offset + 0],\n attributeFloatValues[offset + 4],\n attributeFloatValues[offset + 8],\n attributeFloatValues[offset + 12],\n\n attributeFloatValues[offset + 1],\n attributeFloatValues[offset + 5],\n attributeFloatValues[offset + 9],\n attributeFloatValues[offset + 13],\n\n attributeFloatValues[offset + 2],\n attributeFloatValues[offset + 6],\n attributeFloatValues[offset + 10],\n attributeFloatValues[offset + 14],\n\n attributeFloatValues[offset + 3],\n attributeFloatValues[offset + 7],\n attributeFloatValues[offset + 11],\n attributeFloatValues[offset + 15]\n );\n out.copy(baseBoundingBox).applyMatrix4(instanceMatrix);\n return out;\n}\n\nconst computeBoundingBoxFromEllipseAttributesVars = {\n center: new THREE.Vector3(),\n size: new THREE.Vector3()\n};\n\nexport function computeBoundingBoxFromEllipseAttributes(\n centerAttribute: ParsePrimitiveAttribute,\n radius1Attribute: ParsePrimitiveAttribute,\n radius2Attribute: ParsePrimitiveAttribute,\n heightAttribute: ParsePrimitiveAttribute,\n attributeFloatValues: Float32Array,\n elementSize: number,\n elementIndex: number,\n out: THREE.Box3\n): THREE.Box3 {\n const { center, size } = computeBoundingBoxFromEllipseAttributesVars;\n\n function readAttribute(attribute: ParsePrimitiveAttribute, idx: number = 0): number {\n const offset = (elementIndex * elementSize + attribute.offset) / attributeFloatValues.BYTES_PER_ELEMENT;\n return attributeFloatValues[offset + idx];\n }\n\n center.set(readAttribute(centerAttribute, 0), readAttribute(centerAttribute, 1), readAttribute(centerAttribute, 2));\n const radius1 = readAttribute(radius1Attribute);\n const radius2 = readAttribute(radius2Attribute);\n const height = readAttribute(heightAttribute);\n const extent = 2.0 * Math.max(radius1, radius2, height);\n size.set(extent, extent, extent);\n out.setFromCenterAndSize(center, size);\n return out;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { ParsePrimitiveAttribute } from '@cognite/reveal-parser-worker';\nimport assert from 'assert';\nimport {\n computeBoundingBoxFromCenterAndRadiusAttributes,\n computeBoundingBoxFromEllipseAttributes,\n computeBoundingBoxFromInstanceMatrixAttributes,\n computeBoundingBoxFromVertexAttributes\n} from './computeBoundingBoxFromAttributes';\n\nfunction filterPrimitivesOutsideClipBox(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n clipBox: THREE.Box3,\n getBoundsOfElementsCallback: (\n index: number,\n elementSize: number,\n attributeFloatValues: Float32Array,\n outBox: THREE.Box3\n ) => void\n): Uint8Array {\n const elementSize = Array.from(attributes.values()).reduce((a, b) => Math.max(a, b.offset + b.size), 0);\n const elementCount = attributesByteValues.length / elementSize;\n const attributeFloatValues = new Float32Array(attributesByteValues.buffer);\n\n const instanceBbox = new THREE.Box3();\n\n const filteredByteValues = new Uint8Array(attributesByteValues.length);\n let filteredCount = 0;\n for (let i = 0; i < elementCount; ++i) {\n getBoundsOfElementsCallback(i, elementSize, attributeFloatValues, instanceBbox);\n\n if (clipBox.intersectsBox(instanceBbox)) {\n const elementValues = attributesByteValues.subarray(i * elementSize, (i + 1) * elementSize);\n filteredByteValues.set(elementValues, filteredCount * elementSize);\n filteredCount++;\n }\n }\n return filteredByteValues.slice(0, filteredCount * elementSize);\n}\n\nexport function filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n baseBox: THREE.Box3,\n geometryClipBox: THREE.Box3 | null\n): Uint8Array {\n if (geometryClipBox === null) {\n return attributesByteValues;\n }\n const instanceMatrixAttribute = attributes.get('instanceMatrix');\n assert(instanceMatrixAttribute !== undefined);\n return filterPrimitivesOutsideClipBox(\n attributesByteValues,\n attributes,\n geometryClipBox,\n (index, elementSize, attributeFloatValues, outBox) => {\n computeBoundingBoxFromInstanceMatrixAttributes(\n instanceMatrixAttribute,\n attributeFloatValues,\n elementSize,\n index,\n baseBox,\n outBox\n );\n }\n );\n}\n\nexport function filterPrimitivesOutsideClipBoxByCenterAndRadius(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n geometryClipBox: THREE.Box3 | null,\n radiusAattributeName: string = 'radiusA',\n radiusBattributeName: string = 'radiusB'\n): Uint8Array {\n if (geometryClipBox === null) {\n return attributesByteValues;\n }\n\n const centerAattribute = attributes.get('centerA');\n const centerBattribute = attributes.get('centerB');\n const radiusAattribute = attributes.get(radiusAattributeName);\n const radiusBattribute = attributes.get(radiusBattributeName);\n assert(\n centerAattribute !== undefined &&\n centerBattribute !== undefined &&\n radiusAattribute !== undefined &&\n radiusBattribute !== undefined\n );\n return filterPrimitivesOutsideClipBox(\n attributesByteValues,\n attributes,\n geometryClipBox,\n (index, elementSize, attributeFloatValues, outBox) => {\n computeBoundingBoxFromCenterAndRadiusAttributes(\n centerAattribute,\n centerBattribute,\n radiusAattribute,\n radiusBattribute,\n attributeFloatValues,\n elementSize,\n index,\n outBox\n );\n }\n );\n}\n\nexport function filterPrimitivesOutsideClipBoxByVertices(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n geometryClipBox: THREE.Box3 | null\n): Uint8Array {\n if (geometryClipBox === null) {\n return attributesByteValues;\n }\n\n const vertex1attribute = attributes.get('vertex1');\n const vertex2attribute = attributes.get('vertex2');\n const vertex3attribute = attributes.get('vertex3');\n const vertex4attribute = attributes.get('vertex4');\n assert(\n vertex1attribute !== undefined &&\n vertex2attribute !== undefined &&\n vertex3attribute !== undefined &&\n vertex4attribute !== undefined\n );\n return filterPrimitivesOutsideClipBox(\n attributesByteValues,\n attributes,\n geometryClipBox,\n (index, elementSize, attributeFloatValues, outBox) => {\n computeBoundingBoxFromVertexAttributes(\n vertex1attribute,\n vertex2attribute,\n vertex3attribute,\n vertex4attribute,\n attributeFloatValues,\n elementSize,\n index,\n outBox\n );\n }\n );\n}\n\nexport function filterPrimitivesOutsideClipBoxByEllipse(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n geometryClipBox: THREE.Box3 | null,\n radius1AttributeName: string = 'horizontalRadius',\n radius2AttributeName: string = 'verticalRadius'\n): Uint8Array {\n if (geometryClipBox === null) {\n return attributesByteValues;\n }\n const centerAttribute = attributes.get('center');\n const horizontalRadiusAttribute = attributes.get(radius1AttributeName);\n const verticalRadiusAttribute = attributes.get(radius2AttributeName);\n const heightAttribute = attributes.get('height');\n assert(\n centerAttribute !== undefined &&\n horizontalRadiusAttribute !== undefined &&\n verticalRadiusAttribute !== undefined &&\n heightAttribute !== undefined\n );\n return filterPrimitivesOutsideClipBox(\n attributesByteValues,\n attributes,\n geometryClipBox,\n (index, elementSize, attributeFloatValues, outBox) => {\n computeBoundingBoxFromEllipseAttributes(\n centerAttribute,\n horizontalRadiusAttribute,\n verticalRadiusAttribute,\n heightAttribute,\n attributeFloatValues,\n elementSize,\n index,\n outBox\n );\n }\n );\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { ParsePrimitiveAttribute } from '@cognite/reveal-parser-worker';\nimport {\n boxGeometry,\n quadGeometry,\n coneGeometry,\n trapeziumGeometry,\n nutGeometry,\n torusLodGeometries,\n boxGeometryBoundingBox,\n quadGeometryBoundingBox,\n torusGeometryBoundingBox,\n nutGeometryBoundingBox\n} from './primitiveGeometries';\n\nimport { Materials } from './materials';\nimport { SectorGeometry } from './types';\nimport { disposeAttributeArrayOnUpload } from '@reveal/utilities';\nimport assert from 'assert';\nimport {\n filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix,\n filterPrimitivesOutsideClipBoxByCenterAndRadius,\n filterPrimitivesOutsideClipBoxByEllipse,\n filterPrimitivesOutsideClipBoxByVertices\n} from './filterPrimitives';\nimport { BoundingBoxLOD } from '@reveal/utilities';\n\nexport function* createPrimitives(\n sector: SectorGeometry,\n materials: Materials,\n sectorBounds: THREE.Box3,\n geometryClipBox: THREE.Box3 | null = null\n) {\n const primitives = sector.primitives;\n if (hasAny(primitives.boxCollection)) {\n yield createBoxes(primitives.boxCollection, primitives.boxAttributes, materials.box, geometryClipBox);\n }\n if (hasAny(primitives.circleCollection)) {\n yield createCircles(primitives.circleCollection, primitives.circleAttributes, materials.circle, geometryClipBox);\n }\n if (hasAny(primitives.coneCollection)) {\n yield createCones(\n primitives.coneCollection,\n primitives.coneAttributes,\n materials.cone,\n sectorBounds,\n geometryClipBox\n );\n }\n if (hasAny(primitives.eccentricConeCollection)) {\n yield createEccentricCones(\n primitives.eccentricConeCollection,\n primitives.eccentricConeAttributes,\n materials.eccentricCone,\n sectorBounds,\n geometryClipBox\n );\n }\n if (hasAny(primitives.ellipsoidSegmentCollection)) {\n yield createEllipsoidSegments(\n primitives.ellipsoidSegmentCollection,\n primitives.ellipsoidSegmentAttributes,\n materials.ellipsoidSegment,\n sectorBounds,\n geometryClipBox\n );\n }\n if (hasAny(primitives.generalCylinderCollection)) {\n const cylinders = createGeneralCylinders(\n primitives.generalCylinderCollection,\n primitives.generalCylinderAttributes,\n materials.generalCylinder,\n sectorBounds,\n geometryClipBox\n );\n if (cylinders) yield cylinders;\n }\n if (hasAny(primitives.generalRingCollection)) {\n yield createGeneralRings(\n primitives.generalRingCollection,\n primitives.generalRingAttributes,\n materials.generalRing,\n geometryClipBox\n );\n }\n if (hasAny(primitives.quadCollection)) {\n yield createQuads(primitives.quadCollection, primitives.quadAttributes, materials.quad, geometryClipBox);\n }\n if (hasAny(primitives.sphericalSegmentCollection)) {\n yield createSphericalSegments(\n primitives.sphericalSegmentCollection,\n primitives.sphericalSegmentAttributes,\n materials.sphericalSegment,\n sectorBounds,\n geometryClipBox\n );\n }\n\n if (hasAny(primitives.torusSegmentCollection)) {\n yield createTorusSegments(\n primitives.torusSegmentCollection,\n primitives.torusSegmentAttributes,\n materials.torusSegment,\n geometryClipBox\n );\n }\n if (hasAny(primitives.trapeziumCollection)) {\n yield createTrapeziums(\n primitives.trapeziumCollection,\n primitives.trapeziumAttributes,\n materials.trapezium,\n geometryClipBox\n );\n }\n if (hasAny(primitives.nutCollection)) {\n yield createNuts(primitives.nutCollection, primitives.nutAttributes, materials.nut, geometryClipBox);\n }\n}\n\nfunction hasAny(collection: Uint8Array) {\n return collection.length > 0;\n}\n\nfunction splitMatrix(attributes: Map<string, ParsePrimitiveAttribute>) {\n const matrixColumns = 4;\n\n const matrixAttribute = attributes.get('instanceMatrix');\n\n if (!matrixAttribute) {\n return;\n }\n\n const size = matrixAttribute.size / matrixColumns;\n for (let i = 0; i < matrixColumns; i++) {\n const columnAttribute: ParsePrimitiveAttribute = {\n size,\n offset: matrixAttribute.offset + size * i\n };\n attributes.set('instanceMatrix_column_' + i, columnAttribute);\n }\n\n attributes.delete('instanceMatrix');\n}\n\nfunction setAttributes(\n geometry: THREE.InstancedBufferGeometry,\n collection: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n mesh: THREE.Mesh\n) {\n const attributesByteSize = Array.from(attributes.values()).reduce((a, b) => a + b.size, 0);\n\n splitMatrix(attributes);\n\n const interleavedBuffer8 = new THREE.InstancedInterleavedBuffer(collection, attributesByteSize);\n const interleavedBuffer32 = new THREE.InstancedInterleavedBuffer(\n new Float32Array(collection.buffer),\n attributesByteSize / 4\n );\n\n for (const [name, attribute] of attributes) {\n const is8BitAttribute = name === 'color';\n const interleavedBuffer = is8BitAttribute ? interleavedBuffer8 : interleavedBuffer32;\n const size = is8BitAttribute ? attribute.size : attribute.size / 4;\n const offset = is8BitAttribute ? attribute.offset : attribute.offset / 4;\n\n geometry.setAttribute(\n `a_${name}`,\n new THREE.InterleavedBufferAttribute(interleavedBuffer, size, offset, is8BitAttribute)\n );\n }\n\n mesh.onAfterRender = () => {\n disposeAttributeArrayOnUpload.bind(interleavedBuffer32)();\n disposeAttributeArrayOnUpload.bind(interleavedBuffer8)();\n mesh.onAfterRender = () => {};\n };\n\n geometry.instanceCount = collection.length / attributesByteSize;\n\n setTreeIndeciesToUserData();\n\n function setTreeIndeciesToUserData() {\n const collectionView = new DataView(collection.buffer);\n const treeIndexAttribute = attributes.get('treeIndex')!;\n const treeIndexAttributeOffset = treeIndexAttribute.offset;\n\n const treeIndices = new Set();\n\n for (let i = 0; i < geometry.instanceCount; i++) {\n treeIndices.add(collectionView.getFloat32(i * attributesByteSize + treeIndexAttributeOffset, true));\n }\n mesh.userData.treeIndices = treeIndices;\n }\n}\n\nfunction createBoxes(\n boxCollection: Uint8Array,\n boxAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix(\n boxCollection,\n boxAttributes,\n boxGeometryBoundingBox,\n geometryClipBox\n );\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(boxGeometry.index);\n geometry.setAttribute('position', boxGeometry.position);\n geometry.setAttribute('normal', boxGeometry.normal);\n setAttributes(geometry, filteredCollection, boxAttributes, mesh);\n setBoundsFromInstanceMatrices(geometry);\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n\n mesh.name = `Primitives (Boxes)`;\n\n return mesh;\n}\n\nfunction createCircles(\n circleCollection: Uint8Array,\n circleAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix(\n circleCollection,\n circleAttributes,\n quadGeometryBoundingBox,\n geometryClipBox\n );\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(quadGeometry.index);\n geometry.setAttribute('position', quadGeometry.position);\n geometry.setAttribute('normal', quadGeometry.position);\n setAttributes(geometry, filteredCollection, circleAttributes, mesh);\n setBoundsFromInstanceMatrices(geometry);\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n\n mesh.name = `Primitives (Circles)`;\n return mesh;\n}\n\nfunction createCones(\n coneCollection: Uint8Array,\n coneAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n bounds: THREE.Box3,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByCenterAndRadius(\n coneCollection,\n coneAttributes,\n geometryClipBox\n );\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(coneGeometry.index);\n geometry.setAttribute('position', coneGeometry.position);\n setAttributes(geometry, filteredCollection, coneAttributes, mesh);\n setBoundsFromBox(geometry, bounds);\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n mesh.name = `Primitives (Cones)`;\n return mesh;\n}\n\nfunction createEccentricCones(\n eccentericConeCollection: Uint8Array,\n eccentericConeAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n bounds: THREE.Box3,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByCenterAndRadius(\n eccentericConeCollection,\n eccentericConeAttributes,\n geometryClipBox\n );\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(coneGeometry.index);\n geometry.setAttribute('position', coneGeometry.position);\n setAttributes(geometry, filteredCollection, eccentericConeAttributes, mesh);\n setBoundsFromBox(geometry, bounds);\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n mesh.name = `Primitives (EccentricCones)`;\n return mesh;\n}\n\nfunction createEllipsoidSegments(\n ellipsoidSegmentCollection: Uint8Array,\n ellipsoidSegmentAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n bounds: THREE.Box3,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByEllipse(\n ellipsoidSegmentCollection,\n ellipsoidSegmentAttributes,\n geometryClipBox\n );\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(coneGeometry.index);\n geometry.setAttribute('position', coneGeometry.position);\n setAttributes(geometry, filteredCollection, ellipsoidSegmentAttributes, mesh);\n setBoundsFromBox(geometry, bounds);\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n mesh.name = `Primitives (EllipsoidSegments)`;\n return mesh;\n}\n\nfunction createGeneralCylinders(\n generalCylinderCollection: Uint8Array,\n generalCylinderAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n bounds: THREE.Box3,\n geometryClipBox: THREE.Box3 | null\n): THREE.Mesh | null {\n const filteredCollection = filterPrimitivesOutsideClipBoxByCenterAndRadius(\n generalCylinderCollection,\n generalCylinderAttributes,\n geometryClipBox,\n 'radius',\n 'radius'\n );\n if (filteredCollection.length === 0) {\n return null;\n }\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(coneGeometry.index);\n geometry.setAttribute('position', coneGeometry.position);\n setAttributes(geometry, filteredCollection, generalCylinderAttributes, mesh);\n setBoundsFromBox(geometry, bounds);\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n mesh.name = `Primitives (GeneralCylinders)`;\n return mesh;\n}\n\nfunction createGeneralRings(\n generalRingCollection: Uint8Array,\n generalRingAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix(\n generalRingCollection,\n generalRingAttributes,\n quadGeometryBoundingBox,\n geometryClipBox\n );\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(quadGeometry.index);\n geometry.setAttribute('position', quadGeometry.position);\n setAttributes(geometry, filteredCollection, generalRingAttributes, mesh);\n setBoundsFromInstanceMatrices(geometry);\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n mesh.name = `Primitives (GeneralRings)`;\n return mesh;\n}\n\nfunction createSphericalSegments(\n sphericalSegmentCollection: Uint8Array,\n sphericalSegmentAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n bounds: THREE.Box3,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByEllipse(\n sphericalSegmentCollection,\n sphericalSegmentAttributes,\n geometryClipBox,\n 'radius',\n 'radius'\n );\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(coneGeometry.index);\n geometry.setAttribute('position', coneGeometry.position);\n setAttributes(geometry, filteredCollection, sphericalSegmentAttributes, mesh);\n setBoundsFromBox(geometry, bounds);\n\n // TODO We need to set the radius manually here because\n // we are reusing the ellipsoid shader. We should\n // consider making this cleaner - either by duplicating\n // this data from Rust or by creating a separate shader for\n // spherical segments\n\n geometry.setAttribute(`a_horizontalRadius`, geometry.getAttribute('a_radius'));\n geometry.setAttribute(`a_verticalRadius`, geometry.getAttribute('a_radius'));\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n mesh.name = `Primitives (EllipsoidSegments)`;\n return mesh;\n}\n\nfunction createQuads(\n quadCollection: Uint8Array,\n quadAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix(\n quadCollection,\n quadAttributes,\n quadGeometryBoundingBox,\n geometryClipBox\n );\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(quadGeometry.index);\n geometry.setAttribute('position', quadGeometry.position);\n geometry.setAttribute('normal', quadGeometry.normal);\n setAttributes(geometry, filteredCollection, quadAttributes, mesh);\n setBoundsFromInstanceMatrices(geometry);\n\n mesh.name = `Primitives (Quads)`;\n return mesh;\n}\n\nfunction createTrapeziums(\n trapeziumCollection: Uint8Array,\n trapeziumAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByVertices(\n trapeziumCollection,\n trapeziumAttributes,\n geometryClipBox\n );\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(trapeziumGeometry.index);\n geometry.setAttribute('position', trapeziumGeometry.position);\n setAttributes(geometry, filteredCollection, trapeziumAttributes, mesh);\n setBoundsFromVertexAttributes(geometry);\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n mesh.name = `Primitives (Trapeziums)`;\n return mesh;\n}\n\nfunction getBiggestTorusSize(\n torusSegmentCollection: Uint8Array,\n torusSegmentAttributes: Map<string, ParsePrimitiveAttribute>\n) {\n const collectionStride = Array.from(torusSegmentAttributes.values()).reduce((sum, element) => sum + element.size, 0);\n\n const numberOfTorusSegments = torusSegmentCollection.length / collectionStride;\n\n let biggest = 0.0;\n\n const collectionView = new DataView(torusSegmentCollection.buffer);\n const sizeAttribute = torusSegmentAttributes.get('size')!;\n const sizeAttributeOffset = sizeAttribute.offset;\n\n for (let i = 0; i < numberOfTorusSegments; i++) {\n biggest = Math.max(biggest, collectionView.getFloat32(i * collectionStride + sizeAttributeOffset!, true));\n }\n\n return biggest;\n}\n\nfunction calcLODDistance(size: number, lodLevel: number): number {\n if (lodLevel === 0) {\n return 0;\n }\n const scaleFactor = 5.0;\n const distance = size * scaleFactor ** lodLevel;\n return distance;\n}\n\nfunction createTorusSegments(\n torusSegmentCollection: Uint8Array,\n torusSegmentAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix(\n torusSegmentCollection,\n torusSegmentAttributes,\n torusGeometryBoundingBox,\n geometryClipBox\n );\n\n const biggestTorus = getBiggestTorusSize(filteredCollection, torusSegmentAttributes);\n\n const lod = new BoundingBoxLOD(new THREE.Box3());\n lod.name = 'Primitives (TorusSegments)';\n\n let boundingBox: THREE.Box3 | null = null;\n let boundingSphere: THREE.Sphere | null = null;\n for (const [level, torus] of torusLodGeometries.entries()) {\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(torus.index);\n geometry.setAttribute('position', torus.position);\n setAttributes(geometry, torusSegmentCollection, torusSegmentAttributes, mesh);\n\n if (boundingBox === null) {\n const bounds = determineBoundsFromInstanceMatrices(geometry);\n boundingBox = bounds.boundingBox;\n boundingSphere = bounds.boundingSphere;\n lod.setBoundingBox(boundingBox);\n }\n geometry.boundingBox = boundingBox;\n geometry.boundingSphere = boundingSphere;\n\n mesh.name = `Primitives (TorusSegments) - LOD ${level}`;\n lod.addLevel(mesh, calcLODDistance(biggestTorus, level));\n\n mesh.onBeforeRender = () => updateMaterialInverseModelMatrix(material, mesh.matrixWorld);\n }\n\n return lod;\n}\n\nfunction createNuts(\n nutCollection: Uint8Array,\n nutAttributes: Map<string, ParsePrimitiveAttribute>,\n material: THREE.ShaderMaterial,\n geometryClipBox: THREE.Box3 | null\n) {\n const filteredCollection = filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix(\n nutCollection,\n nutAttributes,\n nutGeometryBoundingBox,\n geometryClipBox\n );\n\n const geometry = new THREE.InstancedBufferGeometry();\n const mesh = new THREE.Mesh(geometry, material);\n\n geometry.setIndex(nutGeometry.index);\n geometry.setAttribute('position', nutGeometry.position);\n geometry.setAttribute('normal', nutGeometry.normal);\n setAttributes(geometry, filteredCollection, nutAttributes, mesh);\n setBoundsFromInstanceMatrices(geometry);\n\n mesh.name = `Primitives (Nuts)`;\n return mesh;\n}\n\nfunction updateMaterialInverseModelMatrix(\n material: THREE.ShaderMaterial | THREE.RawShaderMaterial,\n matrixWorld: THREE.Matrix4\n) {\n const inverseModelMatrix: THREE.Matrix4 = material.uniforms.inverseModelMatrix.value;\n inverseModelMatrix.copy(matrixWorld).invert();\n}\n\nfunction setBoundsFromBox(geometry: THREE.InstancedBufferGeometry, bounds: THREE.Box3) {\n geometry.boundingSphere = geometry.boundingSphere || new THREE.Sphere();\n bounds.getBoundingSphere(geometry.boundingSphere);\n}\n\nconst setBoundingSphereFromVerticesVars = {\n baseBoundingBox: new THREE.Box3(),\n instanceBoundingBox: new THREE.Box3(),\n instanceMatrix: new THREE.Matrix4(),\n p: new THREE.Vector3()\n};\n\nexport function determineBoundsFromInstanceMatrices(geometry: THREE.InstancedBufferGeometry): {\n boundingBox: THREE.Box3;\n boundingSphere: THREE.Sphere;\n} {\n const { baseBoundingBox, instanceBoundingBox, instanceMatrix, p } = setBoundingSphereFromVerticesVars;\n baseBoundingBox.makeEmpty();\n const bbox = new THREE.Box3();\n\n // Determine base bounding box\n const positionAttribute = geometry.getAttribute('position');\n for (let i = 0; i < positionAttribute.count; ++i) {\n p.set(positionAttribute.getX(i), positionAttribute.getY(i), positionAttribute.getZ(i));\n baseBoundingBox.expandByPoint(p);\n }\n\n // Apply instance matrix to bounds to compute real bounds\n const matCol0Attribute = geometry.getAttribute('a_instanceMatrix_column_0');\n const matCol1Attribute = geometry.getAttribute('a_instanceMatrix_column_1');\n const matCol2Attribute = geometry.getAttribute('a_instanceMatrix_column_2');\n const matCol3Attribute = geometry.getAttribute('a_instanceMatrix_column_3');\n assert(\n matCol0Attribute !== undefined &&\n matCol1Attribute !== undefined &&\n matCol2Attribute !== undefined &&\n matCol3Attribute !== undefined\n );\n\n for (let i = 0; i < matCol0Attribute.count; ++i) {\n /* eslint-disable */\n instanceMatrix.set(\n matCol0Attribute.getX(i), matCol1Attribute.getX(i), matCol2Attribute.getX(i), matCol3Attribute.getX(i),\n matCol0Attribute.getY(i), matCol1Attribute.getY(i), matCol2Attribute.getY(i), matCol3Attribute.getY(i),\n matCol0Attribute.getZ(i), matCol1Attribute.getZ(i), matCol2Attribute.getZ(i), matCol3Attribute.getZ(i),\n matCol0Attribute.getW(i), matCol1Attribute.getW(i), matCol2Attribute.getW(i), matCol3Attribute.getW(i),\n );\n /* eslint-enable */\n instanceBoundingBox.copy(baseBoundingBox).applyMatrix4(instanceMatrix);\n bbox.expandByPoint(instanceBoundingBox.min);\n bbox.expandByPoint(instanceBoundingBox.max);\n }\n\n return { boundingBox: bbox, boundingSphere: bbox.getBoundingSphere(new THREE.Sphere()) };\n}\n\nfunction setBoundsFromInstanceMatrices(geometry: THREE.InstancedBufferGeometry) {\n const { boundingBox, boundingSphere } = determineBoundsFromInstanceMatrices(geometry);\n geometry.boundingBox = boundingBox;\n geometry.boundingSphere = boundingSphere;\n}\n\nconst setBoundsFromVertexAttributesVars = {\n bbox: new THREE.Box3(),\n p: new THREE.Vector3()\n};\n\nfunction setBoundsFromVertexAttributes(geometry: THREE.InstancedBufferGeometry) {\n const { bbox, p } = setBoundsFromVertexAttributesVars;\n bbox.makeEmpty();\n\n const vertex1Attribute = geometry.getAttribute('a_vertex1');\n const vertex2Attribute = geometry.getAttribute('a_vertex2');\n const vertex3Attribute = geometry.getAttribute('a_vertex3');\n const vertex4Attribute = geometry.getAttribute('a_vertex4');\n assert(\n vertex1Attribute !== undefined &&\n vertex2Attribute !== undefined &&\n vertex3Attribute !== undefined &&\n vertex4Attribute !== undefined\n );\n\n for (let i = 0; i < vertex1Attribute.count; ++i) {\n p.set(vertex1Attribute.getX(i), vertex1Attribute.getY(i), vertex1Attribute.getZ(i));\n bbox.expandByPoint(p);\n p.set(vertex2Attribute.getX(i), vertex2Attribute.getY(i), vertex2Attribute.getZ(i));\n bbox.expandByPoint(p);\n p.set(vertex3Attribute.getX(i), vertex3Attribute.getY(i), vertex3Attribute.getZ(i));\n bbox.expandByPoint(p);\n p.set(vertex4Attribute.getX(i), vertex4Attribute.getY(i), vertex4Attribute.getZ(i));\n bbox.expandByPoint(p);\n }\n\n geometry.boundingBox = bbox;\n // TODO 20210804 larsmoa: Compute better bounding spheres for primitives\n geometry.boundingSphere = geometry.boundingSphere || new THREE.Sphere();\n geometry.boundingBox.getBoundingSphere(geometry.boundingSphere);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { disposeAttributeArrayOnUpload } from '@reveal/utilities';\nimport { TriangleMesh } from '@reveal/cad-parsers';\n\nexport function createTriangleMeshes(\n triangleMeshes: TriangleMesh[],\n bounds: THREE.Box3,\n material: THREE.ShaderMaterial,\n geometryClipBox: THREE.Box3 | null\n): THREE.Mesh[] {\n const result: THREE.Mesh[] = [];\n\n const filteredTriangleMeshes = triangleMeshes.filter(mesh => {\n return geometryClipBox === null || isTriangleMeshWithin(mesh, geometryClipBox);\n });\n for (const mesh of filteredTriangleMeshes) {\n const geometry = new THREE.BufferGeometry();\n const indices = new THREE.Uint32BufferAttribute(mesh.indices.buffer, 1).onUpload(disposeAttributeArrayOnUpload);\n const vertices = new THREE.Float32BufferAttribute(mesh.vertices.buffer, 3).onUpload(disposeAttributeArrayOnUpload);\n const colors = new THREE.Uint8BufferAttribute(mesh.colors.buffer, 3).onUpload(disposeAttributeArrayOnUpload);\n\n const treeIndices = new THREE.Float32BufferAttribute(mesh.treeIndices.buffer, 1).onUpload(\n disposeAttributeArrayOnUpload\n );\n geometry.setIndex(indices);\n geometry.setAttribute('color', colors);\n geometry.setAttribute('position', vertices);\n geometry.setAttribute('treeIndex', treeIndices);\n geometry.boundingBox = bounds.clone();\n geometry.boundingSphere = new THREE.Sphere();\n bounds.getBoundingSphere(geometry.boundingSphere);\n\n const obj = new THREE.Mesh(geometry, material);\n obj.name = `Triangle mesh ${mesh.fileId}`;\n\n obj.userData.treeIndices = new Set(mesh.treeIndices);\n\n result.push(obj);\n }\n return result;\n}\n\nconst isTriangleMeshWithinArgs = {\n p: new THREE.Vector3(),\n box: new THREE.Box3()\n};\n\nfunction isTriangleMeshWithin(mesh: TriangleMesh, bounds: THREE.Box3): boolean {\n const { p, box } = isTriangleMeshWithinArgs;\n box.makeEmpty();\n for (let i = 0; i < mesh.vertices.length; i += 3) {\n p.set(mesh.vertices[i + 0], mesh.vertices[i + 1], mesh.vertices[i + 2]);\n box.expandByPoint(p);\n }\n return bounds.intersectsBox(box);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nimport { ParsePrimitiveAttribute } from '@cognite/reveal-parser-worker';\n\nimport { disposeAttributeArrayOnUpload } from '@reveal/utilities';\nimport { Materials, filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix } from '@reveal/cad-parsers';\n\nconst quadVertexData = new Float32Array([\n /* eslint-disable prettier/prettier */\n -0.5, -0.5, 0.0,\n 0.5, -0.5, 0.0,\n 0.5, 0.5, 0.0,\n\n 0.5, 0.5, 0.0,\n -0.5, 0.5, 0.0,\n -0.5, -0.5, 0.0,\n /* eslint-enable prettier/prettier */\n]);\n\nconst quadVertexBufferAttribute = new THREE.Float32BufferAttribute(quadVertexData.buffer, 3);\nconst baseBoundingBox = new THREE.Box3().setFromArray(quadVertexData);\nconst primitiveAttributes: Map<string, ParsePrimitiveAttribute> = new Map([\n ['color', { offset: 0, size: 4 * 3 }],\n ['treeIndex', { offset: 12, size: 4 }],\n ['normal', { offset: 16, size: 4 * 3 }],\n ['instanceMatrix', { offset: 7 * 4, size: 16 * 4 }]\n]);\n\nexport function createSimpleGeometryMesh(\n attributeValues: Float32Array,\n materials: Materials,\n sectorBounds: THREE.Box3,\n geometryClipBox: THREE.Box3 | null\n): THREE.Mesh | undefined {\n const attributeByteValues = new Uint8Array(attributeValues.buffer);\n const filteredByteValues = filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix(\n attributeByteValues,\n primitiveAttributes,\n baseBoundingBox,\n geometryClipBox\n );\n if (filteredByteValues.byteLength === 0) {\n // No data, just skip\n return undefined;\n }\n\n const filteredAttributeValues = new Float32Array(filteredByteValues.buffer);\n const stride = 3 + 1 + 3 + 16;\n if (filteredByteValues.byteLength % stride !== 0) {\n throw new Error(`Expected buffer size to be multiple of ${stride}, but got ${filteredAttributeValues.byteLength}`);\n }\n\n const geometry = new THREE.InstancedBufferGeometry();\n\n const interleavedBuffer32 = new THREE.InstancedInterleavedBuffer(filteredAttributeValues, stride);\n const color = new THREE.InterleavedBufferAttribute(interleavedBuffer32, 3, 0, true);\n const treeIndex = new THREE.InterleavedBufferAttribute(interleavedBuffer32, 1, 3, false);\n const normal = new THREE.InterleavedBufferAttribute(interleavedBuffer32, 3, 4, true);\n const matrix0 = new THREE.InterleavedBufferAttribute(interleavedBuffer32, 4, 7, false);\n const matrix1 = new THREE.InterleavedBufferAttribute(interleavedBuffer32, 4, 11, false);\n const matrix2 = new THREE.InterleavedBufferAttribute(interleavedBuffer32, 4, 15, false);\n const matrix3 = new THREE.InterleavedBufferAttribute(interleavedBuffer32, 4, 19, false);\n\n geometry.setAttribute('position', quadVertexBufferAttribute);\n geometry.setAttribute('color', color);\n geometry.setAttribute('treeIndex', treeIndex);\n geometry.setAttribute('normal', normal);\n geometry.setAttribute('matrix0', matrix0);\n geometry.setAttribute('matrix1', matrix1);\n geometry.setAttribute('matrix2', matrix2);\n geometry.setAttribute('matrix3', matrix3);\n\n const obj = new THREE.Mesh(geometry, materials.simple);\n obj.name = 'Low detail geometry';\n obj.onAfterRender = () => {\n disposeAttributeArrayOnUpload.bind(interleavedBuffer32)();\n obj.onAfterRender = () => {};\n };\n\n obj.onBeforeRender = () => {\n const inverseModelMatrix: THREE.Matrix4 = materials.simple.uniforms.inverseModelMatrix.value;\n inverseModelMatrix.copy(obj.matrixWorld).invert();\n };\n\n setTreeIndicesToUserData();\n\n obj.geometry.boundingSphere = new THREE.Sphere();\n sectorBounds.getBoundingSphere(obj.geometry.boundingSphere);\n return obj;\n\n function setTreeIndicesToUserData() {\n const treeIndexAttributeOffset = 3;\n\n const treeIndices = new Set();\n\n for (let i = 0; i < attributeValues.length / stride; i++) {\n treeIndices.add(attributeValues[i * stride + treeIndexAttributeOffset]);\n }\n obj.userData.treeIndices = treeIndices;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\nimport { InstancedMesh } from '@reveal/cad-parsers';\n\nimport { float32BufferToMatrix } from '../../utilities/float32BufferToMatrix';\n\nconst filterInstanceMeshVars = {\n p: new THREE.Vector3(),\n instanceMatrix: new THREE.Matrix4(),\n baseBounds: new THREE.Box3(),\n instanceBounds: new THREE.Box3()\n};\n\nexport function filterInstanceMesh(\n vertices: Float32Array,\n indices: Uint32Array,\n instanceMesh: InstancedMesh,\n geometryClipBox: THREE.Box3 | null\n): InstancedMesh {\n if (geometryClipBox === null) {\n return instanceMesh;\n }\n const { p, instanceMatrix, baseBounds, instanceBounds } = filterInstanceMeshVars;\n\n // Determine base bounds\n baseBounds.makeEmpty();\n for (let j = instanceMesh.triangleOffset; j < instanceMesh.triangleOffset + instanceMesh.triangleCount; ++j) {\n const v0 = indices[3 * j + 0];\n const v1 = indices[3 * j + 1];\n const v2 = indices[3 * j + 2];\n p.set(vertices[v0 + 0], vertices[v0 + 1], vertices[v0 + 2]);\n baseBounds.expandByPoint(p);\n p.set(vertices[v1 + 0], vertices[v1 + 1], vertices[v1 + 2]);\n baseBounds.expandByPoint(p);\n p.set(vertices[v2 + 0], vertices[v2 + 1], vertices[v2 + 2]);\n baseBounds.expandByPoint(p);\n }\n\n let filteredOffset = 0;\n const instanceCount = instanceMesh.treeIndices.length;\n const filteredInstanceMatrices = new Float32Array(instanceMesh.instanceMatrices.length);\n const filteredTreeIndices = new Float32Array(instanceCount);\n const filteredColors = new Uint8Array(4 * instanceCount);\n for (let i = 0; i < instanceCount; ++i) {\n float32BufferToMatrix(instanceMesh.instanceMatrices, i, instanceMatrix);\n\n instanceBounds.copy(baseBounds).applyMatrix4(instanceMatrix);\n if (geometryClipBox.intersectsBox(instanceBounds)) {\n const elementInstanceMatrix = instanceMesh.instanceMatrices.subarray(16 * i, 16 * (i + 1));\n const elementColor = instanceMesh.colors.subarray(4 * i, 4 * (i + 1));\n const elementTreeIndex = instanceMesh.treeIndices[i];\n\n filteredInstanceMatrices.set(elementInstanceMatrix, 16 * filteredOffset);\n filteredColors.set(elementColor, 4 * filteredOffset);\n filteredTreeIndices[filteredOffset] = elementTreeIndex;\n\n filteredOffset++;\n }\n }\n\n if (instanceCount === filteredOffset) {\n return instanceMesh; // Unchanged\n }\n\n const filteredMesh: InstancedMesh = {\n triangleCount: instanceMesh.triangleCount,\n triangleOffset: instanceMesh.triangleOffset,\n instanceMatrices: filteredInstanceMatrices.slice(0, 16 * filteredOffset),\n colors: filteredColors.slice(0, 4 * filteredOffset),\n treeIndices: filteredTreeIndices.slice(0, filteredOffset)\n };\n return filteredMesh;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { SectorQuads } from '@cognite/reveal-parser-worker';\nimport { traverseDepthFirst, AutoDisposeGroup } from '@reveal/utilities';\nimport {\n SectorMetadata,\n SectorGeometry,\n WantedSector,\n ConsumedSector,\n InstancedMeshFile,\n Materials,\n createPrimitives\n} from '@reveal/cad-parsers';\n\nimport { pipe, GroupedObservable, Observable, OperatorFunction } from 'rxjs';\nimport { groupBy, distinctUntilKeyChanged, withLatestFrom, mergeMap, filter, map } from 'rxjs/operators';\n\nimport { createTriangleMeshes } from '../material-manager/rendering/triangleMeshes';\nimport { createSimpleGeometryMesh } from '../material-manager/rendering/createSimpleGeometryMesh';\nimport { filterInstanceMesh } from '../material-manager/rendering/filterInstanceMesh';\n\nexport function consumeSectorSimple(\n sector: SectorQuads,\n sectorBounds: THREE.Box3,\n materials: Materials,\n geometryClipBox: THREE.Box3 | null\n): { sectorMeshes: AutoDisposeGroup; instancedMeshes: InstancedMeshFile[] } {\n const group = new AutoDisposeGroup();\n group.name = 'Quads';\n if (sector.buffer.byteLength === 0) {\n // No data, just skip\n return { sectorMeshes: new AutoDisposeGroup(), instancedMeshes: [] };\n }\n\n const mesh = createSimpleGeometryMesh(sector.buffer, materials, sectorBounds, geometryClipBox);\n if (mesh !== undefined) {\n group.add(mesh);\n }\n return { sectorMeshes: group, instancedMeshes: [] };\n}\n\nexport function consumeSectorDetailed(\n sector: SectorGeometry,\n metadata: SectorMetadata,\n materials: Materials,\n geometryClipBox: THREE.Box3 | null\n): { sectorMeshes: AutoDisposeGroup; instancedMeshes: InstancedMeshFile[] } {\n const bounds = metadata.bounds;\n\n if (geometryClipBox !== null && geometryClipBox.containsBox(bounds)) {\n // If sector bounds is fully inside clip Box, nothing will be clipped so don't go the extra mile\n // to check\n geometryClipBox = null;\n }\n\n const group = new AutoDisposeGroup();\n for (const primitiveRoot of createPrimitives(sector, materials, bounds, geometryClipBox)) {\n group.add(primitiveRoot);\n }\n\n const triangleMeshes = createTriangleMeshes(sector.triangleMeshes, bounds, materials.triangleMesh, geometryClipBox);\n for (const triangleMesh of triangleMeshes) {\n group.add(triangleMesh);\n }\n const instanceMeshes = sector.instanceMeshes\n .map(instanceMeshFile => {\n const filteredMeshes = instanceMeshFile.instances\n .map(mesh => filterInstanceMesh(instanceMeshFile.vertices, instanceMeshFile.indices, mesh, geometryClipBox))\n .filter(x => x.treeIndices.length > 0);\n const filteredInstanceMeshFile: InstancedMeshFile = {\n fileId: instanceMeshFile.fileId,\n vertices: instanceMeshFile.vertices,\n indices: instanceMeshFile.indices,\n instances: filteredMeshes\n };\n return filteredInstanceMeshFile;\n })\n .filter(x => x.instances.length > 0);\n return { sectorMeshes: group, instancedMeshes: instanceMeshes };\n}\n\nexport function distinctUntilLevelOfDetailChanged() {\n return pipe(\n groupBy((sector: ConsumedSector) => sector.modelIdentifier),\n mergeMap((modelGroup: GroupedObservable<string, ConsumedSector>) => {\n return modelGroup.pipe(\n groupBy((sector: ConsumedSector) => sector.metadata.id),\n mergeMap((group: GroupedObservable<number, ConsumedSector>) =>\n group.pipe(distinctUntilKeyChanged('levelOfDetail'))\n )\n );\n })\n );\n}\n\nexport function filterCurrentWantedSectors(\n wantedObservable: Observable<WantedSector[]>\n): OperatorFunction<ConsumedSector, ConsumedSector> {\n return pipe(\n withLatestFrom(wantedObservable),\n filter(([loaded, wanted]) => {\n for (const wantedSector of wanted) {\n if (\n loaded.modelIdentifier === wantedSector.modelIdentifier &&\n loaded.metadata.id === wantedSector.metadata.id &&\n loaded.levelOfDetail === wantedSector.levelOfDetail\n ) {\n return true;\n }\n }\n return false;\n }),\n map(([loaded, _wanted]) => loaded)\n );\n}\n\nexport function findSectorMetadata(root: SectorMetadata, sectorId: number): SectorMetadata {\n let foundSector: SectorMetadata | null = null;\n traverseDepthFirst(root, sector => {\n if (sector.id === sectorId) {\n foundSector = sector;\n }\n return !foundSector;\n });\n if (!foundSector) {\n throw new Error(`Could not find metadata for sector ${sectorId} - invalid id?`);\n }\n return foundSector;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\n/**\n * Sets the elements of a matrix from a row-major\n * matrix stored in a Float32Array.\n * @param buffer\n * @param indexOffset\n * @param outMatrix\n */\nexport function float32BufferToMatrix(\n buffer: Float32Array,\n indexOffset: number,\n outMatrix: THREE.Matrix4\n): THREE.Matrix4 {\n outMatrix.set(\n buffer[indexOffset + 0],\n buffer[indexOffset + 4],\n buffer[indexOffset + 8],\n buffer[indexOffset + 12],\n\n buffer[indexOffset + 1],\n buffer[indexOffset + 5],\n buffer[indexOffset + 9],\n buffer[indexOffset + 13],\n\n buffer[indexOffset + 2],\n buffer[indexOffset + 6],\n buffer[indexOffset + 10],\n buffer[indexOffset + 14],\n\n buffer[indexOffset + 3],\n buffer[indexOffset + 7],\n buffer[indexOffset + 11],\n buffer[indexOffset + 15]\n );\n return outMatrix;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { SectorQuads } from '@cognite/reveal-parser-worker';\n\nimport { SectorMetadata, InstancedMeshFile, SectorGeometry } from '@reveal/cad-parsers';\nimport { AutoDisposeGroup } from '@reveal/utilities';\n\nimport { CadMaterialManager } from '../material-manager/CadMaterialManager';\n\nimport { consumeSectorDetailed, consumeSectorSimple } from './sectorUtilities';\nimport assert from 'assert';\n\nexport class SimpleAndDetailedToSector3D {\n private readonly materialManager: CadMaterialManager;\n\n constructor(materialManager: CadMaterialManager) {\n this.materialManager = materialManager;\n }\n\n transformSimpleSector(\n modelIdentifier: string,\n sector: SectorMetadata,\n geometry: SectorQuads,\n geometryClipBox: THREE.Box3 | null\n ): Promise<{ sectorMeshes: AutoDisposeGroup; instancedMeshes: InstancedMeshFile[] }> {\n const materials = this.materialManager.getModelMaterials(modelIdentifier);\n assert(materials !== undefined, `Could not find materials for model '${modelIdentifier}`);\n return Promise.resolve(consumeSectorSimple(geometry, sector.bounds, materials!, geometryClipBox));\n }\n\n transformDetailedSector(\n modelIdentifier: string,\n sector: SectorMetadata,\n geometry: SectorGeometry,\n geometryClipBox: THREE.Box3 | null\n ): Promise<{ sectorMeshes: AutoDisposeGroup; instancedMeshes: InstancedMeshFile[] }> {\n const materials = this.materialManager.getModelMaterials(modelIdentifier);\n assert(materials !== undefined, `Could not find materials for model '${modelIdentifier}`);\n return Promise.resolve(consumeSectorDetailed(geometry, sector, materials!, geometryClipBox));\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { assertNever, EventTrigger, NumericRange } from '@reveal/utilities';\n\nconst identityTransform = new THREE.Matrix4().identity();\n\nexport type NodeTransformChangeEventDelegate = (\n change: 'set' | 'reset',\n treeIndices: NumericRange,\n transform: THREE.Matrix4\n) => void;\n\nexport class NodeTransformProvider {\n private readonly _events = {\n changed: new EventTrigger<NodeTransformChangeEventDelegate>()\n };\n\n on(event: 'changed', listener: NodeTransformChangeEventDelegate): void {\n switch (event) {\n case 'changed':\n this._events.changed.subscribe(listener as NodeTransformChangeEventDelegate);\n break;\n default:\n assertNever(event, `Unsupported event: '${event}'`);\n }\n }\n\n off(event: 'changed', listener: NodeTransformChangeEventDelegate): void {\n switch (event) {\n case 'changed':\n this._events.changed.unsubscribe(listener as NodeTransformChangeEventDelegate);\n break;\n default:\n assertNever(event, `Unsupported event: '${event}'`);\n }\n }\n\n setNodeTransform(treeIndices: NumericRange, transform: THREE.Matrix4) {\n this._events.changed.fire('set', treeIndices, transform);\n }\n\n resetNodeTransform(treeIndices: NumericRange) {\n this._events.changed.fire('reset', treeIndices, identityTransform);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nexport function* groupMeshesByNumber(id: Float64Array): Generator<{ id: number; meshIndices: number[] }> {\n const groupedByFileId = new Array<{ fileId: number; index: number }>(id.length);\n for (let i = 0; i < id.length; ++i) {\n groupedByFileId[i] = { fileId: id[i], index: i };\n }\n groupedByFileId.sort((a, b) => a.fileId - b.fileId);\n\n let i = 0;\n while (i < groupedByFileId.length) {\n const fileId = groupedByFileId[i].fileId;\n // Determine sequence of occurences with same fileId\n const last = lastIndexOf(groupedByFileId, fileId, i, x => x.fileId);\n const meshIndices = new Array<number>(last + 1 - i);\n for (let j = i; j < last + 1; j++) {\n meshIndices[j - i] = groupedByFileId[j].index;\n }\n yield { id: fileId, meshIndices };\n // Skip to next group\n i = last + 1;\n }\n}\n\nexport function lastIndexOf<T>(\n sortedArray: T[],\n value: number,\n firstSearchIndex: number,\n elementValueOf: (element: T) => number\n) {\n let low = firstSearchIndex;\n let high = sortedArray.length - 1;\n let res = sortedArray.length;\n // Binary search to find last matching element\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const elementValue = elementValueOf(sortedArray[mid]);\n\n if (elementValue > value) {\n high = mid - 1;\n } else if (elementValue < value) {\n low = mid + 1;\n }\n // If arr[mid] is same as x, we\n // update res and move to the right\n // half.\n else {\n res = mid;\n low = mid + 1;\n }\n }\n return res;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport function createOffsets(array: Float64Array): Float64Array {\n const offsets = new Float64Array(array.length);\n array.forEach((_, idx) => {\n offsets[idx] = idx > 0 ? offsets[idx - 1] + array[idx - 1] : 0;\n });\n return offsets;\n}\n\nexport function createOffsetsArray(array: number[]): number[] {\n const offsets = new Array<number>(array.length);\n array.forEach((_, idx) => {\n offsets[idx] = idx > 0 ? offsets[idx - 1] + array[idx - 1] : 0;\n });\n return offsets;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { assertNever, trackError, MostFrequentlyUsedCache, MemoryRequestCache } from '@reveal/utilities';\nimport {\n CadSectorParser,\n LevelOfDetail,\n WantedSector,\n SectorGeometry,\n ConsumedSector,\n TriangleMesh,\n InstancedMeshFile,\n InstancedMesh\n} from '@reveal/cad-parsers';\n\nimport { SimpleAndDetailedToSector3D } from './SimpleAndDetailedToSector3D';\nimport { Repository } from './Repository';\n\nimport { groupMeshesByNumber } from '../utilities/groupMeshesByNumber';\nimport { createOffsetsArray } from '../utilities/arrays';\n\nimport { BinaryFileProvider } from '@reveal/modeldata-api';\nimport { ParseCtmResult, ParseSectorResult } from '@cognite/reveal-parser-worker';\n\n// TODO: j-bjorne 16-04-2020: REFACTOR FINALIZE INTO SOME OTHER FILE PLEZ!\nexport class CachedRepository implements Repository {\n private readonly _consumedSectorCache: MemoryRequestCache<string, ConsumedSector>;\n private readonly _ctmFileCache: MostFrequentlyUsedCache<string, Promise<ParseCtmResult>>;\n\n private readonly _modelSectorProvider: BinaryFileProvider;\n private readonly _modelDataParser: CadSectorParser;\n private readonly _modelDataTransformer: SimpleAndDetailedToSector3D;\n\n constructor(\n modelSectorProvider: BinaryFileProvider,\n modelDataParser: CadSectorParser,\n modelDataTransformer: SimpleAndDetailedToSector3D\n ) {\n this._modelSectorProvider = modelSectorProvider;\n this._modelDataParser = modelDataParser;\n this._modelDataTransformer = modelDataTransformer;\n\n this._consumedSectorCache = new MemoryRequestCache(50, consumedSector => {\n if (consumedSector.group !== undefined) {\n // Dereference so GPU resources can be cleaned up if geomety isn't used anymore\n consumedSector.group.dereference();\n }\n });\n this._ctmFileCache = new MostFrequentlyUsedCache(10);\n }\n\n clear() {\n this._consumedSectorCache.clear();\n this._ctmFileCache.clear();\n }\n\n // TODO j-bjorne 16-04-2020: Should look into ways of not sending in discarded sectors,\n // unless we want them to eventually set their priority to lower in the cache.\n\n async loadSector(sector: WantedSector): Promise<ConsumedSector> {\n const cacheKey = this.wantedSectorCacheKey(sector);\n try {\n if (this._consumedSectorCache.has(cacheKey)) {\n return this._consumedSectorCache.get(cacheKey);\n }\n\n switch (sector.levelOfDetail) {\n case LevelOfDetail.Detailed: {\n const consumed = await this.loadDetailedSectorFromNetwork(sector);\n this._consumedSectorCache.forceInsert(cacheKey, consumed);\n // Increase reference count to avoid geometry from being disposed\n consumed?.group?.reference();\n return consumed;\n }\n\n case LevelOfDetail.Simple: {\n const consumed = await this.loadSimpleSectorFromNetwork(sector);\n this._consumedSectorCache.forceInsert(cacheKey, consumed);\n // Increase reference count to avoid geometry from being disposed\n consumed?.group?.reference();\n return consumed;\n }\n\n case LevelOfDetail.Discarded:\n return {\n modelIdentifier: sector.modelIdentifier,\n metadata: sector.metadata,\n levelOfDetail: sector.levelOfDetail,\n instancedMeshes: [],\n group: undefined\n };\n\n default:\n assertNever(sector.levelOfDetail);\n }\n } catch (error) {\n this._consumedSectorCache.remove(cacheKey);\n trackError(error, { methodName: 'loadSector', moduleName: 'CachedRepository' });\n throw error;\n }\n }\n\n private async loadSimpleSectorFromNetwork(wantedSector: WantedSector): Promise<ConsumedSector> {\n // TODO 2021-05-05 larsmoa: Retry\n const buffer = await this._modelSectorProvider.getBinaryFile(\n wantedSector.modelBaseUrl,\n wantedSector.metadata.facesFile.fileName!\n );\n const geometry = await this._modelDataParser.parseF3D(new Uint8Array(buffer));\n const transformed = await this._modelDataTransformer.transformSimpleSector(\n wantedSector.modelIdentifier,\n wantedSector.metadata,\n geometry,\n wantedSector.geometryClipBox\n );\n const consumedSector: ConsumedSector = {\n ...wantedSector,\n group: transformed.sectorMeshes,\n instancedMeshes: transformed.instancedMeshes\n };\n return consumedSector;\n }\n\n private async loadI3DFromNetwork(modelBaseUrl: string, filename: string): Promise<ParseSectorResult> {\n const buffer = await this._modelSectorProvider.getBinaryFile(modelBaseUrl, filename);\n return this._modelDataParser.parseI3D(new Uint8Array(buffer));\n }\n\n private async loadCtmsFromNetwork(\n modelBaseUrl: string,\n ctmFilenames: string[]\n ): Promise<Map<string, ParseCtmResult>> {\n const ctms = await Promise.all(ctmFilenames.map(x => this.loadCtmFileFromNetwork(modelBaseUrl, x)));\n return ctmFilenames.reduce(\n (map, filename, index) => map.set(filename, ctms[index]),\n new Map<string, ParseCtmResult>()\n );\n }\n\n private async loadDetailedSectorFromNetwork(wantedSector: WantedSector): Promise<ConsumedSector> {\n const indexFile = wantedSector.metadata.indexFile;\n\n const i3dPromise = this.loadI3DFromNetwork(wantedSector.modelBaseUrl, indexFile.fileName);\n const ctmsPromise = this.loadCtmsFromNetwork(wantedSector.modelBaseUrl, indexFile.peripheralFiles);\n\n const i3d = await i3dPromise;\n const ctms = await ctmsPromise;\n const geometry = this.finalizeDetailed(i3d, ctms);\n\n const transformed = await this._modelDataTransformer.transformDetailedSector(\n wantedSector.modelIdentifier,\n wantedSector.metadata,\n geometry,\n wantedSector.geometryClipBox\n );\n\n const consumedSector: ConsumedSector = {\n ...wantedSector,\n group: transformed.sectorMeshes,\n instancedMeshes: transformed.instancedMeshes\n };\n return consumedSector;\n }\n\n private async loadCtmFileFromNetwork(modelBaseUrl: string, filename: string): Promise<ParseCtmResult> {\n const cacheKey = this.ctmFileCacheKey(modelBaseUrl, filename);\n const cached = this._ctmFileCache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n const ctmPromise = this._modelSectorProvider\n .getBinaryFile(modelBaseUrl, filename)\n .then(buffer => this._modelDataParser.parseCTM(new Uint8Array(buffer)));\n this._ctmFileCache.set(cacheKey, ctmPromise);\n return ctmPromise;\n }\n\n private finalizeDetailed(i3dFile: ParseSectorResult, ctmFiles: Map<string, ParseCtmResult>): SectorGeometry {\n const { instanceMeshes, triangleMeshes } = i3dFile;\n\n const finalTriangleMeshes = (() => {\n const { fileIds, colors, triangleCounts, treeIndices } = triangleMeshes;\n\n const finalMeshes = [];\n\n for (const { id: fileId, meshIndices } of groupMeshesByNumber(fileIds)) {\n const fileTriangleCounts = meshIndices.map(i => triangleCounts[i]);\n const offsets = createOffsetsArray(fileTriangleCounts);\n // Load CTM (geometry)\n const fileName = `mesh_${fileId}.ctm`;\n const { indices, vertices, normals } = ctmFiles.get(fileName)!; // TODO: j-bjorne 16-04-2020: try catch error???\n\n const sharedColors = new Uint8Array(3 * indices.length);\n const sharedTreeIndices = new Float32Array(indices.length);\n\n for (let i = 0; i < meshIndices.length; i++) {\n const meshIdx = meshIndices[i];\n const treeIndex = treeIndices[meshIdx];\n const triOffset = offsets[i];\n const triCount = fileTriangleCounts[i];\n const [r, g, b] = [colors[4 * meshIdx + 0], colors[4 * meshIdx + 1], colors[4 * meshIdx + 2]];\n for (let triIdx = triOffset; triIdx < triOffset + triCount; triIdx++) {\n for (let j = 0; j < 3; j++) {\n const vIdx = indices[3 * triIdx + j];\n\n sharedTreeIndices[vIdx] = treeIndex;\n\n sharedColors[3 * vIdx] = r;\n sharedColors[3 * vIdx + 1] = g;\n sharedColors[3 * vIdx + 2] = b;\n }\n }\n }\n\n const mesh: TriangleMesh = {\n colors: sharedColors,\n fileId,\n treeIndices: sharedTreeIndices,\n indices,\n vertices,\n normals\n };\n finalMeshes.push(mesh);\n }\n return finalMeshes;\n })();\n\n const finalInstanceMeshes = (() => {\n const { fileIds, colors, treeIndices, triangleCounts, triangleOffsets, instanceMatrices } = instanceMeshes;\n\n const finalMeshes: InstancedMeshFile[] = [];\n // Merge meshes by file\n // TODO do this in Rust instead\n // TODO de-duplicate this with the merged meshes above\n for (const { id: fileId, meshIndices } of groupMeshesByNumber(fileIds)) {\n const fileName = `mesh_${fileId}.ctm`;\n const ctm = ctmFiles.get(fileName)!;\n\n const indices = ctm.indices;\n const vertices = ctm.vertices;\n const instancedMeshes: InstancedMesh[] = [];\n\n const fileTriangleOffsets = new Float64Array(meshIndices.map(i => triangleOffsets[i]));\n const fileTriangleCounts = new Float64Array(meshIndices.map(i => triangleCounts[i]));\n\n for (const { id: triangleOffset, meshIndices: fileMeshIndices } of groupMeshesByNumber(fileTriangleOffsets)) {\n // NOTE the triangle counts should be the same for all meshes with the same offset,\n const triangleCount = fileTriangleCounts[fileMeshIndices[0]];\n const instanceMatrixBuffer = new Float32Array(16 * fileMeshIndices.length);\n const treeIndicesBuffer = new Float32Array(fileMeshIndices.length);\n const colorBuffer = new Uint8Array(4 * fileMeshIndices.length);\n for (let i = 0; i < fileMeshIndices.length; i++) {\n const meshIdx = meshIndices[fileMeshIndices[i]];\n const treeIndex = treeIndices[meshIdx];\n const instanceMatrix = instanceMatrices.subarray(meshIdx * 16, meshIdx * 16 + 16);\n instanceMatrixBuffer.set(instanceMatrix, i * 16);\n treeIndicesBuffer[i] = treeIndex;\n const color = colors.subarray(meshIdx * 4, meshIdx * 4 + 4);\n colorBuffer.set(color, i * 4);\n }\n instancedMeshes.push({\n triangleCount,\n triangleOffset,\n instanceMatrices: instanceMatrixBuffer,\n colors: colorBuffer,\n treeIndices: treeIndicesBuffer\n });\n }\n\n const mesh: InstancedMeshFile = {\n fileId,\n indices,\n vertices,\n instances: instancedMeshes\n };\n finalMeshes.push(mesh);\n }\n\n return finalMeshes;\n })();\n\n const sector: SectorGeometry = {\n treeIndexToNodeIdMap: i3dFile.treeIndexToNodeIdMap,\n nodeIdToTreeIndexMap: i3dFile.nodeIdToTreeIndexMap,\n primitives: i3dFile.primitives,\n instanceMeshes: finalInstanceMeshes,\n triangleMeshes: finalTriangleMeshes\n };\n\n return sector;\n }\n\n private wantedSectorCacheKey(wantedSector: WantedSector) {\n return wantedSector.modelIdentifier + '.' + wantedSector.metadata.id + '.' + wantedSector.levelOfDetail;\n }\n\n private ctmFileCacheKey(modelBaseUrl: string, fileName: string) {\n return modelBaseUrl + '.' + fileName;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport { SectorQuads } from '@cognite/reveal-parser-worker';\n\n/**\n * Anti-aliasing modes supported by Reveal.\n */\nexport enum AntiAliasingMode {\n /**\n * No anti-aliasing (0).\n */\n NoAA = 0,\n /**\n * Fast-approximate anti-aliasing (FXAA) (1).\n */\n FXAA = 1\n}\n\n/**\n * Options and hints for how the Reveal viewer applies rendering effects.\n */\nexport type RenderOptions = {\n /**\n * Anti-aliasing mode used to avoid aliasing effects in the rendered view.\n */\n antiAliasing?: AntiAliasingMode;\n /**\n * When provided, Reveal will use multi-sampling to reduce aliasing effects when WebGL 2 is\n * available. Ignored if using WebGL 1.\n */\n multiSampleCountHint?: number;\n /**\n * Determines the parameters used for ambient occlusion heuristic shading.\n */\n ssaoRenderParameters?: SsaoParameters;\n /**\n * Determines the parameters used for visualizing edges of the geometry.\n */\n edgeDetectionParameters?: EdgeDetectionParameters;\n};\n\n/**\n * SSAO rendering quality modes supported by Reveal.\n */\nexport enum SsaoSampleQuality {\n Medium = 32,\n High = 64,\n VeryHigh = 128,\n None = 1,\n Default = Medium\n}\n\n/**\n * Defaults for {@ref RevealRenderOptions}.\n */\nexport const defaultRenderOptions: Required<RenderOptions> = {\n antiAliasing: AntiAliasingMode.FXAA,\n multiSampleCountHint: 1,\n ssaoRenderParameters: { sampleSize: SsaoSampleQuality.Default, sampleRadius: 1.0, depthCheckBias: 0.0125 },\n edgeDetectionParameters: { enabled: true }\n};\n\n/**\n * Edge detection parameters supported by Reveal.\n */\nexport type EdgeDetectionParameters = {\n enabled: boolean;\n};\n\n/**\n * Screen-space ambient occlusion parameters supported by Reveal.\n */\nexport type SsaoParameters = {\n /**\n * Quality (Number of samples) to estimate occlusion factor.\n */\n sampleSize: SsaoSampleQuality;\n /**\n * Maximum length of sample vector.\n */\n sampleRadius: number;\n /**\n * Applied bias when depth testing to reduce output noise.\n */\n depthCheckBias: number;\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\n/**\n * Colors from the Cognite theme.\n */\nexport class CogniteColors {\n public static readonly Black = new THREE.Color('rgb(0, 0, 0)');\n public static readonly White = new THREE.Color('rgb(255, 255, 255)');\n public static readonly Cyan = new THREE.Color('rgb(102, 213, 234)');\n public static readonly Blue = new THREE.Color('rgb(77, 106, 242)');\n public static readonly Purple = new THREE.Color('rgb(186, 82, 212)');\n public static readonly Pink = new THREE.Color('rgb(232, 64, 117)');\n public static readonly Orange = new THREE.Color('rgb(238, 113, 53)');\n public static readonly Yellow = new THREE.Color('rgb(246, 189, 65)');\n public static readonly VeryLightGray = new THREE.Color('rgb(247, 246, 245)');\n public static readonly LightGray = new THREE.Color('rgb(242, 241, 240)');\n}\n\n/**\n * Some additional colors to supplement {@link CogniteColors}.\n */\nexport class RevealColors {\n public static readonly Red = new THREE.Color('rgb(235,0,4)');\n public static readonly Green = new THREE.Color('rgb(46,164,79)');\n}\n\n/**\n * State holding information about data being loaded.\n */\nexport type LoadingState = {\n /**\n * Indicates if we are currently loading more data.\n */\n isLoading: boolean;\n /**\n * Items loaded so far in this batch.\n */\n itemsLoaded: number;\n /**\n * Totals number of items to load in this batch.\n */\n itemsRequested: number;\n /**\n * Number of items that has been 'culled' (i.e. deemed not necessary\n * to load) so far in this batch.\n */\n itemsCulled: number;\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport glsl from 'glslify';\n\n/**\n * Defines used to enable debugging features in shaders.\n */\nexport const shaderDefines = {\n defines: {\n // Color geometry by tree index instead of model colors.\n COGNITE_COLOR_BY_TREE_INDEX: false\n }\n};\n\nexport const sectorShaders = {\n // ----------------\n // \"Regular\" meshes\n // ----------------\n simpleMesh: {\n fragment: glsl(require('../glsl/sector/simple.frag').default),\n vertex: glsl(require('../glsl/sector/simple.vert').default)\n },\n detailedMesh: {\n fragment: glsl(require('../glsl/sector/mesh.frag').default),\n vertex: glsl(require('../glsl/sector/mesh.vert').default)\n },\n instancedMesh: {\n fragment: glsl(require('../glsl/sector/instancedMesh.frag').default),\n vertex: glsl(require('../glsl/sector/instancedMesh.vert').default)\n },\n\n // ----------------\n // Primitives\n // ----------------\n boxPrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/instanced.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/instanced.vert').default)\n },\n circlePrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/circle.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/circle.vert').default)\n },\n conePrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/cone.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/cone.vert').default)\n },\n eccentricConePrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/eccentricCone.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/eccentricCone.vert').default)\n },\n ellipsoidSegmentPrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/ellipsoidSegment.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/ellipsoidSegment.vert').default)\n },\n generalCylinderPrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/generalCylinder.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/generalCylinder.vert').default)\n },\n generalRingPrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/generalring.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/generalring.vert').default)\n },\n nutPrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/instanced.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/instanced.vert').default)\n },\n quadPrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/instanced.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/instanced.vert').default)\n },\n torusSegmentPrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/torusSegment.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/torusSegment.vert').default)\n },\n trapeziumPrimitive: {\n fragment: glsl(require('../glsl/sector/primitives/trapezium.frag').default),\n vertex: glsl(require('../glsl/sector/primitives/trapezium.vert').default)\n }\n};\n\nexport const outlineDetectionShaders = {\n fragment: glsl(require('../glsl/post-processing/outline-detect-combine.frag').default),\n vertex: glsl(require('../glsl/post-processing/outline-detection.vert').default)\n};\n\n/**\n * FXAA anti-aliasing shader\n */\nexport const fxaaShaders = {\n fragment: glsl(require('../glsl/post-processing/fxaa.frag').default),\n vertex: glsl(require('../glsl/post-processing/fxaa.vert').default)\n};\n\n/**\n * Screen space ambient occlusion shader\n */\nexport const ssaoShaders = {\n fragment: glsl(require('../glsl/post-processing/pure-depth-ssao.frag').default),\n vertex: glsl(require('../glsl/post-processing/passthrough.vert').default)\n};\n\n/**\n * Shader to blur ambient occlusion texture and combine with diffuse\n */\nexport const ssaoBlurCombineShaders = {\n fragment: glsl(require('../glsl/post-processing/ssao-blur-combine.frag').default),\n vertex: glsl(require('../glsl/post-processing/passthrough.vert').default)\n};\n\n/**\n * Shaders use to estimate how many pixels a sector covers on screen.\n */\nexport const coverageShaders = {\n fragment: glsl(require('../glsl/sector/sectorCoverage.frag').default),\n vertex: glsl(require('../glsl/sector/sectorCoverage.vert').default)\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { RootSectorNode } from '../../sector/RootSectorNode';\nimport { SectorNode } from '../../sector/SectorNode';\n\nimport { CadMaterialManager } from '../CadMaterialManager';\nimport { CogniteColors, RevealColors } from '../../utilities/types';\nimport { CadNode } from '../../CadNode';\nimport { AntiAliasingMode, defaultRenderOptions, RenderOptions, SsaoParameters, SsaoSampleQuality } from './types';\n\nimport { NodeOutlineColor } from '@reveal/cad-styling';\nimport {\n outlineDetectionShaders,\n fxaaShaders,\n ssaoShaders,\n ssaoBlurCombineShaders,\n LevelOfDetail,\n RenderMode\n} from '@reveal/cad-parsers';\nimport { isMobileOrTablet, WebGLRendererStateHelper } from '@reveal/utilities';\n\nexport class EffectRenderManager {\n private readonly _materialManager: CadMaterialManager;\n private readonly _orthographicCamera: THREE.OrthographicCamera;\n\n // Original input scene containing all geometry\n private readonly _originalScene: THREE.Scene;\n\n // Simple scene with a single triangle with UVs [0,1] in both directions\n // used for combining outputs into a single output\n private readonly _compositionScene: THREE.Scene;\n\n // Simple scene with a single triangle with UVs [0,1] in both directions\n // used for applying FXAA to the final result\n private readonly _fxaaScene: THREE.Scene;\n\n // Simple scene with a single triangle with UVs [0,1] in both directions\n // used for generating ambient occlusion map (screen space)\n private readonly _ssaoScene: THREE.Scene;\n\n // Simple scene with a single triangle with UVs [0,1] in both directions\n // used for bluring and applying the ambient occlusion map (screen space)\n private readonly _ssaoBlurScene: THREE.Scene;\n\n // Holds all CAD models\n private readonly _cadScene: THREE.Scene;\n\n // \"Working scene\" used to hold \"normal\" objects, i.e.\n // objects that are depth tested and not \"ghosted\". Populated\n // during render()\n private readonly _normalScene: THREE.Scene;\n // \"Working scene\" used to hold objects that are rendered in front\n // of other objects. Populated during render().\n private readonly _inFrontScene: THREE.Scene;\n\n // Special scene needed to properly clear WebGL2 render targets\n private readonly _emptyScene: THREE.Scene;\n\n // Used to build _normalScene during render()\n private readonly _normalSceneBuilder: TemporarySceneBuilder;\n // Used to build _infrontScene during render()\n private readonly _inFrontSceneBuilder: TemporarySceneBuilder;\n\n private _renderOptions: RenderOptions;\n\n private _combineOutlineDetectionMaterial: THREE.ShaderMaterial;\n private _fxaaMaterial: THREE.ShaderMaterial;\n private _ssaoMaterial: THREE.ShaderMaterial;\n private _ssaoBlurMaterial: THREE.ShaderMaterial;\n\n private _customObjectRenderTarget: THREE.WebGLRenderTarget;\n private _ghostObjectRenderTarget: THREE.WebGLRenderTarget;\n private _normalRenderedCadModelTarget: THREE.WebGLRenderTarget;\n private _inFrontRenderedCadModelTarget: THREE.WebGLRenderTarget;\n private _compositionTarget: THREE.WebGLRenderTarget;\n private _ssaoTarget: THREE.WebGLRenderTarget;\n private _ssaoBlurTarget: THREE.WebGLRenderTarget;\n\n /**\n * Holds state of how the last frame was rendered by `render()`. This is used to explicit clear\n * WebGL2 render targets which might cause geometry to \"get stuck\" after e.g. removing models.\n */\n private _lastFrameSceneState = {\n hasBackElements: true,\n hasInFrontElements: true,\n hasGhostElements: true,\n hasCustomObjects: true\n };\n\n private readonly _rootSectorNodeBuffer: Set<[RootSectorNode, CadNode]> = new Set();\n private readonly _outlineTexelSize = 2;\n\n private readonly _renderer: THREE.WebGLRenderer;\n private _renderTarget: THREE.WebGLRenderTarget | null;\n private _autoSetTargetSize: boolean = false;\n\n private _uiObjects: { object: THREE.Object3D; screenPos: THREE.Vector2; width: number; height: number }[] = [];\n\n public set renderOptions(options: RenderOptions) {\n const ssaoParameters = this.ssaoParameters(options);\n const inputSsaoOptions = { ...ssaoParameters };\n this.setSsaoParameters(inputSsaoOptions);\n this._renderOptions = { ...options, ssaoRenderParameters: { ...ssaoParameters } };\n }\n\n public addUiObject(object: THREE.Object3D, screenPos: THREE.Vector2, size: THREE.Vector2) {\n this._uiObjects.push({ object: object, screenPos, width: size.x, height: size.y });\n }\n\n public removeUiObject(object: THREE.Object3D) {\n this._uiObjects = this._uiObjects.filter(p => {\n const filteredObject = p.object;\n return object !== filteredObject;\n });\n }\n\n private ssaoParameters(renderOptions: RenderOptions): SsaoParameters {\n return renderOptions?.ssaoRenderParameters ?? { ...defaultRenderOptions.ssaoRenderParameters };\n }\n\n private get antiAliasingMode(): AntiAliasingMode {\n const { antiAliasing = defaultRenderOptions.antiAliasing } = this._renderOptions;\n return antiAliasing;\n }\n\n private get multiSampleCountHint(): number {\n const { multiSampleCountHint = defaultRenderOptions.multiSampleCountHint } = this._renderOptions;\n return multiSampleCountHint;\n }\n\n constructor(\n renderer: THREE.WebGLRenderer,\n scene: THREE.Scene,\n materialManager: CadMaterialManager,\n options: RenderOptions\n ) {\n this._renderer = renderer;\n this._renderOptions = options;\n this._materialManager = materialManager;\n this._orthographicCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, -1, 1);\n\n this._renderTarget = null;\n\n this._originalScene = scene;\n this._cadScene = new THREE.Scene();\n this._cadScene.autoUpdate = false;\n this._normalScene = new THREE.Scene();\n this._normalScene.autoUpdate = false;\n this._inFrontScene = new THREE.Scene();\n this._inFrontScene.autoUpdate = false;\n this._compositionScene = new THREE.Scene();\n this._compositionScene.autoUpdate = false;\n this._fxaaScene = new THREE.Scene();\n this._fxaaScene.autoUpdate = false;\n this._ssaoScene = new THREE.Scene();\n this._ssaoScene.autoUpdate = false;\n this._ssaoBlurScene = new THREE.Scene();\n this._ssaoBlurScene.autoUpdate = false;\n this._emptyScene = new THREE.Scene();\n this._emptyScene.autoUpdate = false;\n\n const isWebGL2 = renderer.capabilities.isWebGL2;\n const outlineColorTexture = this.createOutlineColorTexture();\n\n this._inFrontRenderedCadModelTarget = createRenderTarget(isWebGL2, this.multiSampleCountHint, {\n stencilBuffer: false\n });\n this._inFrontRenderedCadModelTarget.depthTexture = new THREE.DepthTexture(0, 0);\n this._inFrontRenderedCadModelTarget.depthTexture.format = THREE.DepthFormat;\n this._inFrontRenderedCadModelTarget.depthTexture.type = THREE.UnsignedIntType;\n\n this._normalRenderedCadModelTarget = createRenderTarget(isWebGL2, this.multiSampleCountHint, {\n stencilBuffer: false\n });\n this._normalRenderedCadModelTarget.depthTexture = new THREE.DepthTexture(0, 0);\n this._normalRenderedCadModelTarget.depthTexture.format = THREE.DepthFormat;\n this._normalRenderedCadModelTarget.depthTexture.type = THREE.UnsignedIntType;\n\n this._ghostObjectRenderTarget = createRenderTarget(isWebGL2, this.multiSampleCountHint, { stencilBuffer: false });\n this._ghostObjectRenderTarget.depthTexture = new THREE.DepthTexture(0, 0);\n this._ghostObjectRenderTarget.depthTexture.format = THREE.DepthFormat;\n this._ghostObjectRenderTarget.depthTexture.type = THREE.UnsignedIntType;\n\n this._customObjectRenderTarget = createRenderTarget(isWebGL2, this.multiSampleCountHint, { stencilBuffer: false });\n this._customObjectRenderTarget.depthTexture = new THREE.DepthTexture(0, 0);\n this._customObjectRenderTarget.depthTexture.format = THREE.DepthFormat;\n this._customObjectRenderTarget.depthTexture.type = THREE.UnsignedIntType;\n\n this._compositionTarget = new THREE.WebGLRenderTarget(0, 0, { stencilBuffer: false });\n this._compositionTarget.depthTexture = new THREE.DepthTexture(0, 0);\n this._compositionTarget.depthTexture.format = THREE.DepthFormat;\n this._compositionTarget.depthTexture.type = THREE.UnsignedIntType;\n\n this._ssaoTarget = new THREE.WebGLRenderTarget(0, 0, { stencilBuffer: false });\n this._ssaoTarget.depthTexture = new THREE.DepthTexture(0, 0);\n this._ssaoTarget.depthTexture.format = THREE.DepthFormat;\n this._ssaoTarget.depthTexture.type = THREE.UnsignedIntType;\n\n this._ssaoBlurTarget = new THREE.WebGLRenderTarget(0, 0, { stencilBuffer: false });\n this._ssaoBlurTarget.depthTexture = new THREE.DepthTexture(0, 0);\n this._ssaoBlurTarget.depthTexture.format = THREE.DepthFormat;\n this._ssaoBlurTarget.depthTexture.type = THREE.UnsignedIntType;\n\n this._combineOutlineDetectionMaterial = new THREE.ShaderMaterial({\n vertexShader: outlineDetectionShaders.vertex,\n fragmentShader: outlineDetectionShaders.fragment,\n uniforms: {\n tFront: { value: this._inFrontRenderedCadModelTarget.texture },\n tFrontDepth: { value: this._inFrontRenderedCadModelTarget.depthTexture },\n tBack: { value: this._normalRenderedCadModelTarget.texture },\n tBackDepth: { value: this._normalRenderedCadModelTarget.depthTexture },\n tCustom: { value: this._customObjectRenderTarget.texture },\n tCustomDepth: { value: this._customObjectRenderTarget.depthTexture },\n tGhost: { value: this._ghostObjectRenderTarget.texture },\n tGhostDepth: { value: this._ghostObjectRenderTarget.depthTexture },\n tOutlineColors: { value: outlineColorTexture },\n resolution: { value: new THREE.Vector2(0, 0) },\n texelSize: { value: new THREE.Vector2(0, 0) },\n cameraNear: { value: 0.1 },\n cameraFar: { value: 10000 },\n edgeStrengthMultiplier: { value: 2.5 },\n edgeGrayScaleIntensity: { value: 0.1 }\n },\n extensions: { fragDepth: true },\n defines: {\n EDGES:\n this._renderOptions.edgeDetectionParameters?.enabled ?? defaultRenderOptions.edgeDetectionParameters.enabled\n }\n });\n\n const noiseTexture = this.createNoiseTexture();\n\n const ssaoParameters = this.ssaoParameters(this._renderOptions);\n\n const numberOfSamples = ssaoParameters.sampleSize;\n const sampleKernel = this.createKernel(numberOfSamples);\n\n const sampleRadius = ssaoParameters.sampleRadius;\n const depthCheckBias = ssaoParameters.depthCheckBias;\n\n this._ssaoMaterial = new THREE.ShaderMaterial({\n uniforms: {\n tDepth: { value: this._compositionTarget.depthTexture },\n tNoise: { value: noiseTexture },\n kernel: { value: sampleKernel },\n sampleRadius: { value: sampleRadius },\n bias: { value: depthCheckBias },\n projMatrix: { value: new THREE.Matrix4() },\n inverseProjectionMatrix: { value: new THREE.Matrix4() },\n resolution: { value: new THREE.Vector2() }\n },\n defines: {\n MAX_KERNEL_SIZE: numberOfSamples\n },\n vertexShader: ssaoShaders.vertex,\n fragmentShader: ssaoShaders.fragment\n });\n\n this._ssaoBlurMaterial = new THREE.ShaderMaterial({\n uniforms: {\n tDiffuse: { value: this._compositionTarget.texture },\n tAmbientOcclusion: { value: this._ssaoTarget.texture },\n resolution: { value: new THREE.Vector2() }\n },\n vertexShader: ssaoBlurCombineShaders.vertex,\n fragmentShader: ssaoBlurCombineShaders.fragment\n });\n\n const diffuseTexture = this.supportsSsao(ssaoParameters)\n ? this._ssaoBlurTarget.texture\n : this._compositionTarget.texture;\n\n this._fxaaMaterial = new THREE.ShaderMaterial({\n uniforms: {\n tDiffuse: { value: diffuseTexture },\n tDepth: { value: this._compositionTarget.depthTexture },\n resolution: { value: new THREE.Vector2() },\n inverseResolution: { value: new THREE.Vector2() }\n },\n vertexShader: fxaaShaders.vertex,\n fragmentShader: fxaaShaders.fragment,\n extensions: { fragDepth: true }\n });\n\n this.setupCompositionScene();\n this.setupSsaoScene();\n this.setupSsaoBlurCombineScene();\n this.setupFxaaScene();\n\n this._normalSceneBuilder = new TemporarySceneBuilder(this._normalScene);\n this._inFrontSceneBuilder = new TemporarySceneBuilder(this._inFrontScene);\n }\n\n private supportsSsao(ssaoParameters: SsaoParameters) {\n return (\n !isMobileOrTablet() &&\n (this._renderer.capabilities.isWebGL2 || this._renderer.extensions.has('EXT_frag_depth')) &&\n ssaoParameters.sampleSize !== SsaoSampleQuality.None\n );\n }\n\n public renderDetailedToDepthOnly(camera: THREE.PerspectiveCamera) {\n const original = {\n renderMode: this._materialManager.getRenderMode()\n };\n const renderStateHelper = new WebGLRendererStateHelper(this._renderer);\n this._materialManager.setRenderMode(RenderMode.DepthBufferOnly);\n\n try {\n renderStateHelper.setRenderTarget(this._renderTarget);\n this.setVisibilityOfSectors(LevelOfDetail.Simple, false);\n this.traverseForRootSectorNode(this._originalScene);\n this.extractCadNodes(this._originalScene);\n\n this.clearTarget(this._renderTarget);\n const { hasBackElements, hasInFrontElements, hasGhostElements } = this.splitToScenes();\n\n if (hasBackElements && !hasGhostElements) {\n this.renderNormalCadModelsFromBaseScene(camera, this._renderTarget);\n } else if (hasBackElements && hasGhostElements) {\n this.renderNormalCadModels(camera, this._renderTarget);\n this._normalSceneBuilder.restoreOriginalScene();\n }\n if (hasInFrontElements) {\n this.renderInFrontCadModels(camera);\n this._inFrontSceneBuilder.restoreOriginalScene();\n }\n } finally {\n this._materialManager.setRenderMode(original.renderMode);\n renderStateHelper.resetState();\n this.restoreCadNodes();\n this.setVisibilityOfSectors(LevelOfDetail.Simple, true);\n }\n }\n\n public render(camera: THREE.PerspectiveCamera) {\n const renderer = this._renderer;\n const scene = this._originalScene;\n\n const renderStateHelper = new WebGLRendererStateHelper(renderer);\n const original = {\n autoClear: renderer.autoClear,\n clearAlpha: renderer.getClearAlpha(),\n renderMode: this._materialManager.getRenderMode()\n };\n\n renderer.info.autoReset = false;\n renderer.info.reset();\n renderStateHelper.autoClear = false;\n\n try {\n renderStateHelper.setRenderTarget(this._renderTarget);\n this.updateRenderSize(renderer);\n\n renderer.info.autoReset = false;\n renderer.info.reset();\n renderStateHelper.autoClear = false;\n\n this.traverseForRootSectorNode(scene);\n this.extractCadNodes(scene);\n\n // Clear targets\n this.clearTarget(this._ghostObjectRenderTarget);\n this.clearTarget(this._compositionTarget);\n this.clearTarget(this._customObjectRenderTarget);\n // We use alpha to store special state for the next targets\n renderer.setClearAlpha(0.0);\n this.clearTarget(this._normalRenderedCadModelTarget);\n this.clearTarget(this._inFrontRenderedCadModelTarget);\n renderer.setClearAlpha(original.clearAlpha);\n\n const lastFrameSceneState = { ...this._lastFrameSceneState };\n const { hasBackElements, hasInFrontElements, hasGhostElements } = this.splitToScenes();\n const hasCustomObjects = scene.children.length > 0;\n this._lastFrameSceneState = { hasBackElements, hasInFrontElements, hasGhostElements, hasCustomObjects };\n\n if (hasBackElements && !hasGhostElements) {\n this.renderNormalCadModelsFromBaseScene(camera);\n } else if (hasBackElements && hasGhostElements) {\n this.renderNormalCadModels(camera);\n this._normalSceneBuilder.restoreOriginalScene();\n this.renderGhostedCadModelsFromBaseScene(camera);\n } else if (!hasBackElements && hasGhostElements) {\n this.renderGhostedCadModelsFromBaseScene(camera);\n }\n\n if (hasInFrontElements) {\n this.renderInFrontCadModels(camera);\n this._inFrontSceneBuilder.restoreOriginalScene();\n }\n if (hasCustomObjects) {\n this.renderCustomObjects(scene, camera);\n }\n\n if (renderer.capabilities.isWebGL2) {\n // Due to how WebGL2 works and how ThreeJS applies changes from 'clear', we need to\n // render something for the clear to have effect\n if (!hasBackElements && lastFrameSceneState.hasBackElements) {\n this.explicitFlushRender(camera, this._normalRenderedCadModelTarget);\n }\n if (!hasGhostElements && lastFrameSceneState.hasGhostElements) {\n this.explicitFlushRender(camera, this._ghostObjectRenderTarget);\n }\n if (!hasInFrontElements && lastFrameSceneState.hasInFrontElements) {\n this.explicitFlushRender(camera, this._inFrontRenderedCadModelTarget);\n }\n if (!hasCustomObjects && lastFrameSceneState.hasInFrontElements) {\n this.explicitFlushRender(camera, this._customObjectRenderTarget);\n }\n }\n\n const supportsSsao = this.supportsSsao(this.ssaoParameters(this._renderOptions));\n\n switch (this.antiAliasingMode) {\n case AntiAliasingMode.FXAA:\n // Composite view\n this.renderComposition(renderer, camera, this._compositionTarget);\n\n // Anti-aliased version to screen\n renderStateHelper.autoClear = original.autoClear;\n\n if (supportsSsao) {\n this.renderSsao(renderer, this._ssaoTarget, camera);\n this.renderPostProcessStep(renderer, this._ssaoBlurTarget, this._ssaoBlurScene);\n }\n\n this.renderPostProcessStep(renderer, this._renderTarget, this._fxaaScene);\n break;\n\n case AntiAliasingMode.NoAA:\n renderer.autoClear = original.autoClear;\n\n if (supportsSsao) {\n this.renderComposition(renderer, camera, this._compositionTarget);\n this.renderSsao(renderer, this._ssaoTarget, camera);\n this.renderPostProcessStep(renderer, this._renderTarget, this._ssaoBlurScene);\n } else {\n this.renderComposition(renderer, camera, this._renderTarget);\n }\n break;\n\n default:\n throw new Error(`Unsupported anti-aliasing mode: ${this.antiAliasingMode}`);\n }\n } finally {\n // Restore state\n renderStateHelper.resetState();\n // renderer.setRenderTarget(original.renderTarget);\n this._materialManager.setRenderMode(original.renderMode);\n this.restoreCadNodes();\n }\n }\n\n private restoreCadNodes() {\n this._rootSectorNodeBuffer.forEach(p => {\n p[1].add(p[0]);\n });\n this._rootSectorNodeBuffer.clear();\n }\n\n private extractCadNodes(scene: THREE.Scene) {\n this._rootSectorNodeBuffer.forEach(p => {\n if (p[1].parent !== scene && p[1].parent !== null && p[1].parent.parent !== scene) {\n throw new Error('CadNode must be put at scene root');\n }\n this._cadScene.add(p[0]);\n });\n }\n\n public setRenderTarget(target: THREE.WebGLRenderTarget | null) {\n this._renderTarget = target;\n }\n\n public getRenderTarget(): THREE.WebGLRenderTarget | null {\n return this._renderTarget;\n }\n\n public setRenderTargetAutoSize(autoSize: boolean) {\n this._autoSetTargetSize = autoSize;\n }\n\n public getRenderTargetAutoSize(): boolean {\n return this._autoSetTargetSize;\n }\n\n private clearTarget(target: THREE.WebGLRenderTarget | null) {\n this._renderer.setRenderTarget(target);\n this._renderer.clear();\n }\n\n private explicitFlushRender(camera: THREE.Camera, target: THREE.WebGLRenderTarget | null) {\n this._renderer.setRenderTarget(target);\n this._renderer.render(this._emptyScene, camera);\n }\n\n private splitToScenes(): { hasBackElements: boolean; hasInFrontElements: boolean; hasGhostElements: boolean } {\n const result = { hasBackElements: false, hasInFrontElements: false, hasGhostElements: false };\n\n // Determine what rendering stages will be active\n this._rootSectorNodeBuffer.forEach(rootSectorNodeData => {\n const cadNode: CadNode = rootSectorNodeData[1];\n\n const backSet = this._materialManager.getModelBackTreeIndices(cadNode.cadModelMetadata.modelIdentifier);\n const infrontSet = this._materialManager.getModelInFrontTreeIndices(cadNode.cadModelMetadata.modelIdentifier);\n const ghostSet = this._materialManager.getModelGhostedTreeIndices(cadNode.cadModelMetadata.modelIdentifier);\n const hasBackElements = backSet.count > 0;\n const hasInFrontElements = infrontSet.count > 0;\n const hasGhostElements = ghostSet.count > 0;\n result.hasBackElements = result.hasBackElements || hasBackElements;\n result.hasInFrontElements = result.hasInFrontElements || hasInFrontElements;\n result.hasGhostElements = result.hasGhostElements || hasGhostElements;\n });\n\n // Split scenes based on what render stages we need\n const { hasBackElements, hasInFrontElements, hasGhostElements } = result;\n this._rootSectorNodeBuffer.forEach(rootSectorNodeData => {\n const root: RootSectorNode = rootSectorNodeData[0];\n const cadNode: CadNode = rootSectorNodeData[1];\n\n const backSet = this._materialManager.getModelBackTreeIndices(cadNode.cadModelMetadata.modelIdentifier);\n const infrontSet = this._materialManager.getModelInFrontTreeIndices(cadNode.cadModelMetadata.modelIdentifier);\n\n const backRoot = new THREE.Object3D();\n backRoot.applyMatrix4(root.matrix);\n if (hasBackElements && hasGhostElements) {\n this._normalScene.add(backRoot);\n }\n\n const infrontRoot = new THREE.Object3D();\n infrontRoot.applyMatrix4(root.matrix);\n if (hasInFrontElements) {\n this._inFrontScene.add(infrontRoot);\n }\n\n const objectStack: THREE.Object3D[] = [rootSectorNodeData[0]];\n while (objectStack.length > 0) {\n const element = objectStack.pop()!;\n const objectTreeIndices = element.userData.treeIndices as Set<number> | undefined;\n\n if (objectTreeIndices) {\n if (hasInFrontElements && infrontSet.hasIntersectionWith(objectTreeIndices)) {\n this._inFrontSceneBuilder.addElement(element, infrontRoot);\n }\n // Note! When we don't have any ghost, we use _cadScene to hold back objects, so no action required\n if (hasBackElements && !hasGhostElements) {\n } else if (hasGhostElements && backSet.hasIntersectionWith(objectTreeIndices)) {\n this._normalSceneBuilder.addElement(element, backRoot);\n // Use _cadScene to hold ghost objects (we assume we have more ghost objects than back objects)\n }\n\n // TODO 2020-09-18 larsmoa: A potential optimization to rendering is to avoid rendering the full\n // set of objects if most are hidden.\n } else {\n // Not a leaf, traverse children\n objectStack.push(...element.children);\n }\n }\n });\n\n return result;\n }\n\n private renderNormalCadModels(\n camera: THREE.PerspectiveCamera,\n target: THREE.WebGLRenderTarget | null = this._normalRenderedCadModelTarget\n ) {\n this._normalSceneBuilder.populateTemporaryScene();\n this._renderer.setRenderTarget(target);\n this._renderer.render(this._normalScene, camera);\n }\n\n private renderNormalCadModelsFromBaseScene(\n camera: THREE.PerspectiveCamera,\n target: THREE.WebGLRenderTarget | null = this._normalRenderedCadModelTarget\n ) {\n this._renderer.setRenderTarget(target);\n this._renderer.render(this._cadScene, camera);\n }\n\n private renderInFrontCadModels(\n camera: THREE.PerspectiveCamera,\n target: THREE.WebGLRenderTarget | null = this._inFrontRenderedCadModelTarget\n ) {\n this._inFrontSceneBuilder.populateTemporaryScene();\n this._renderer.setRenderTarget(target);\n this._materialManager.setRenderMode(RenderMode.Effects);\n this._renderer.render(this._inFrontScene, camera);\n }\n\n private renderGhostedCadModelsFromBaseScene(camera: THREE.PerspectiveCamera) {\n this._renderer.setRenderTarget(this._ghostObjectRenderTarget);\n this._materialManager.setRenderMode(RenderMode.Ghost);\n this._renderer.render(this._cadScene, camera);\n }\n\n private renderCustomObjects(scene: THREE.Scene, camera: THREE.PerspectiveCamera) {\n this._renderer.setRenderTarget(this._customObjectRenderTarget);\n this._renderer.render(scene, camera);\n }\n\n private updateRenderSize(renderer: THREE.WebGLRenderer) {\n const renderSize = new THREE.Vector2();\n renderer.getSize(renderSize);\n\n if (\n this._renderTarget &&\n this._autoSetTargetSize &&\n renderSize.x !== this._renderTarget.width &&\n renderSize.y !== this._renderTarget.height\n ) {\n this._renderTarget.setSize(renderSize.x, renderSize.y);\n }\n\n if (\n renderSize.x !== this._normalRenderedCadModelTarget.width ||\n renderSize.y !== this._normalRenderedCadModelTarget.height\n ) {\n this._normalRenderedCadModelTarget.setSize(renderSize.x, renderSize.y);\n this._inFrontRenderedCadModelTarget.setSize(renderSize.x, renderSize.y);\n this._customObjectRenderTarget.setSize(renderSize.x, renderSize.y);\n this._ghostObjectRenderTarget.setSize(renderSize.x, renderSize.y);\n this._compositionTarget.setSize(renderSize.x, renderSize.y);\n this._ssaoTarget.setSize(renderSize.x, renderSize.y);\n this._ssaoBlurTarget.setSize(renderSize.x, renderSize.y);\n\n this._combineOutlineDetectionMaterial.uniforms.texelSize.value = new THREE.Vector2(\n this._outlineTexelSize / renderSize.x,\n this._outlineTexelSize / renderSize.y\n );\n\n this._combineOutlineDetectionMaterial.uniforms.resolution.value = renderSize;\n\n this._ssaoMaterial.uniforms.resolution.value = renderSize;\n\n this._ssaoBlurMaterial.uniforms.resolution.value = renderSize;\n\n this._fxaaMaterial.uniforms.resolution.value = renderSize;\n this._fxaaMaterial.uniforms.inverseResolution.value = new THREE.Vector2(1.0 / renderSize.x, 1.0 / renderSize.y);\n }\n return renderSize;\n }\n\n private renderComposition(\n renderer: THREE.WebGLRenderer,\n camera: THREE.PerspectiveCamera,\n target: THREE.WebGLRenderTarget | null\n ) {\n this._combineOutlineDetectionMaterial.uniforms.cameraNear.value = camera.near;\n this._combineOutlineDetectionMaterial.uniforms.cameraFar.value = camera.far;\n\n this.renderPostProcessStep(renderer, target, this._compositionScene);\n }\n\n private setSsaoParameters(params: SsaoParameters) {\n const defaultSsaoParameters = defaultRenderOptions.ssaoRenderParameters;\n\n this._ssaoMaterial.uniforms.sampleRadius.value = params.sampleRadius;\n this._ssaoMaterial.uniforms.bias.value = params.depthCheckBias;\n\n if (params.sampleSize !== this.ssaoParameters(this._renderOptions).sampleSize) {\n const sampleSize = params?.sampleSize ?? defaultSsaoParameters.sampleSize!;\n\n const kernel = this.createKernel(sampleSize);\n\n this._fxaaMaterial.uniforms.tDiffuse.value =\n params.sampleSize !== SsaoSampleQuality.None ? this._ssaoBlurTarget.texture : this._compositionTarget.texture;\n\n this._ssaoMaterial.uniforms.kernel.value = kernel;\n\n this._ssaoMaterial.defines = {\n MAX_KERNEL_SIZE: sampleSize\n };\n\n this._ssaoMaterial.needsUpdate = true;\n }\n }\n\n private renderPostProcessStep(\n renderer: THREE.WebGLRenderer,\n target: THREE.WebGLRenderTarget | null,\n scene: THREE.Scene\n ) {\n renderer.setRenderTarget(target);\n\n renderer.render(scene, this._orthographicCamera);\n\n if (target === this._renderTarget) {\n const renderSize = renderer.getSize(new THREE.Vector2());\n const canvasSize = new THREE.Vector2(renderer.domElement.clientWidth, renderer.domElement.clientHeight);\n\n const downSampleFactor = new THREE.Vector2(renderSize.x / canvasSize.x, renderSize.y / canvasSize.y);\n\n renderer.autoClear = false;\n this._uiObjects.forEach(uiObject => {\n const renderScene = new THREE.Scene();\n renderScene.add(uiObject.object);\n\n const viewportRenderPos = uiObject.screenPos.clone().multiply(downSampleFactor);\n const viewportRenderWidth = uiObject.width * downSampleFactor.x;\n const viewportRenderHeight = uiObject.height * downSampleFactor.y;\n\n renderer.setViewport(viewportRenderPos.x, viewportRenderPos.y, viewportRenderWidth, viewportRenderHeight);\n renderer.clearDepth();\n renderer.render(renderScene, this._orthographicCamera);\n });\n\n renderer.setViewport(0, 0, renderSize.x, renderSize.y);\n renderer.autoClear = true;\n }\n }\n\n private renderSsao(renderer: THREE.WebGLRenderer, target: THREE.WebGLRenderTarget | null, camera: THREE.Camera) {\n this._ssaoMaterial.uniforms.inverseProjectionMatrix.value = camera.projectionMatrixInverse;\n this._ssaoMaterial.uniforms.projMatrix.value = camera.projectionMatrix;\n\n this.renderPostProcessStep(renderer, target, this._ssaoScene);\n }\n\n private createOutlineColorTexture(): THREE.DataTexture {\n const outlineColorBuffer = new Uint8Array(8 * 4);\n const outlineColorTexture = new THREE.DataTexture(outlineColorBuffer, 8, 1);\n setOutlineColor(outlineColorTexture.image.data, NodeOutlineColor.White, CogniteColors.White);\n setOutlineColor(outlineColorTexture.image.data, NodeOutlineColor.Black, CogniteColors.Black);\n setOutlineColor(outlineColorTexture.image.data, NodeOutlineColor.Cyan, CogniteColors.Cyan);\n setOutlineColor(outlineColorTexture.image.data, NodeOutlineColor.Blue, CogniteColors.Blue);\n setOutlineColor(outlineColorTexture.image.data, NodeOutlineColor.Green, RevealColors.Green);\n setOutlineColor(outlineColorTexture.image.data, NodeOutlineColor.Red, RevealColors.Red);\n setOutlineColor(outlineColorTexture.image.data, NodeOutlineColor.Orange, CogniteColors.Orange);\n return outlineColorTexture;\n }\n\n private setupCompositionScene() {\n const geometry = this.createRenderTriangle();\n const mesh = new THREE.Mesh(geometry, this._combineOutlineDetectionMaterial);\n this._compositionScene.add(mesh);\n }\n\n private setupFxaaScene() {\n const geometry = this.createRenderTriangle();\n const mesh = new THREE.Mesh(geometry, this._fxaaMaterial);\n this._fxaaScene.add(mesh);\n }\n\n private setupSsaoScene() {\n const geometry = this.createRenderTriangle();\n const mesh = new THREE.Mesh(geometry, this._ssaoMaterial);\n this._ssaoScene.add(mesh);\n }\n\n private setupSsaoBlurCombineScene() {\n const geometry = this.createRenderTriangle();\n const mesh = new THREE.Mesh(geometry, this._ssaoBlurMaterial);\n this._ssaoBlurScene.add(mesh);\n }\n\n private createNoiseTexture() {\n const width = 128;\n const height = 128;\n\n const size = width * height;\n const data = new Float32Array(size * 4);\n\n for (let i = 0; i < size; i++) {\n const stride = i * 4;\n\n const x = Math.random() * 2 - 1;\n const y = Math.random() * 2 - 1;\n const z = Math.random() * 2 - 1;\n\n data[stride] = x;\n data[stride + 1] = y;\n data[stride + 2] = z;\n data[stride + 3] = 1;\n }\n\n const result = new THREE.DataTexture(data, width, height, THREE.RGBAFormat, THREE.FloatType);\n result.wrapS = THREE.RepeatWrapping;\n result.wrapT = THREE.RepeatWrapping;\n return result;\n }\n\n private createKernel(kernelSize: number) {\n const result = [];\n for (let i = 0; i < kernelSize; i++) {\n const sample = new THREE.Vector3();\n while (sample.length() < 0.5) {\n // Ensure some distance in samples\n sample.x = Math.random() * 2 - 1;\n sample.y = Math.random() * 2 - 1;\n sample.z = Math.random();\n }\n sample.normalize();\n let scale = i / kernelSize;\n scale = lerp(0.1, 1, scale * scale);\n sample.multiplyScalar(scale);\n result.push(sample);\n }\n return result;\n\n function lerp(value1: number, value2: number, amount: number) {\n amount = amount < 0 ? 0 : amount;\n amount = amount > 1 ? 1 : amount;\n return value1 + (value2 - value1) * amount;\n }\n }\n\n private createRenderTriangle() {\n const geometry = new THREE.BufferGeometry();\n const vertices = new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]);\n const uvs = new Float32Array([0, 0, 2, 0, 0, 2]);\n\n geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));\n geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));\n\n return geometry;\n }\n\n private traverseForRootSectorNode(root: THREE.Object3D) {\n const objectStack = [root];\n\n while (objectStack.length > 0) {\n const element = objectStack.pop()!;\n if (element instanceof RootSectorNode) {\n const cadNode = element.parent! as CadNode;\n if (cadNode.visible) {\n this._rootSectorNodeBuffer.add([element, cadNode]);\n }\n } else if (!(element instanceof THREE.Group)) {\n objectStack.push(...element.children);\n }\n }\n }\n\n private setVisibilityOfSectors(levelOfDetail: LevelOfDetail, visible: boolean) {\n this._originalScene.traverse(x => {\n if (x instanceof SectorNode && x.levelOfDetail === levelOfDetail) {\n x.visible = visible;\n }\n });\n }\n}\n\nfunction createRenderTarget(\n isWebGL2: boolean,\n multiSampleCountHint: number,\n options?: THREE.WebGLRenderTargetOptions\n): THREE.WebGLRenderTarget {\n if (isWebGL2 && multiSampleCountHint > 1) {\n const rt = new THREE.WebGLMultisampleRenderTarget(0, 0, options);\n rt.samples = multiSampleCountHint;\n return rt;\n }\n return new THREE.WebGLRenderTarget(0, 0, options);\n}\n\nfunction setOutlineColor(outlineTextureData: Uint8ClampedArray, colorIndex: number, color: THREE.Color) {\n outlineTextureData[4 * colorIndex + 0] = Math.floor(255 * color.r);\n outlineTextureData[4 * colorIndex + 1] = Math.floor(255 * color.g);\n outlineTextureData[4 * colorIndex + 2] = Math.floor(255 * color.b);\n outlineTextureData[4 * colorIndex + 3] = 255;\n}\n\n/**\n * Holds parent-child relationship for a ThreeJS element in order to restore\n * the relationship after moving it temporarily.\n */\ntype Object3DStructure = {\n /**\n * Element described.\n */\n object: THREE.Object3D;\n /**\n * The previous parent of the element.\n */\n parent: THREE.Object3D;\n /**\n * The object that temporarily holds the elemnt.\n */\n sceneParent: THREE.Object3D;\n};\n\nclass TemporarySceneBuilder {\n private readonly buffer: Object3DStructure[];\n private readonly temporaryScene: THREE.Scene;\n\n constructor(temporaryScene: THREE.Scene) {\n this.buffer = [];\n this.temporaryScene = temporaryScene;\n }\n\n addElement(element: THREE.Object3D, temporaryModelRootElement: THREE.Object3D): void {\n this.buffer.push({ object: element, parent: element.parent!, sceneParent: temporaryModelRootElement });\n }\n\n populateTemporaryScene(): void {\n this.buffer.forEach(x => x.sceneParent.add(x.object));\n }\n\n restoreOriginalScene(): void {\n this.buffer.forEach(p => {\n p.parent.add(p.object);\n });\n this.buffer.length = 0; // clear\n this.temporaryScene.remove(...this.temporaryScene.children);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { IndexSet, determinePowerOfTwoDimensions, NumericRange } from '@reveal/utilities';\nimport { NodeAppearanceProvider, NodeAppearance, DefaultNodeAppearance } from '@reveal/cad-styling';\n\nexport class NodeAppearanceTextureBuilder {\n private _defaultAppearance: NodeAppearance = {};\n private readonly _styleProvider: NodeAppearanceProvider;\n private readonly _handleStylesChangedListener = this.handleStylesChanged.bind(this);\n\n private _needsUpdate = true;\n private readonly _allTreeIndices: IndexSet;\n private readonly _overrideColorDefaultAppearanceRgba: Uint8ClampedArray;\n private readonly _overrideColorPerTreeIndexTexture: THREE.DataTexture;\n private readonly _regularNodesTreeIndices: IndexSet;\n private readonly _ghostedNodesTreeIndices: IndexSet;\n private readonly _infrontNodesTreeIndices: IndexSet;\n\n constructor(treeIndexCount: number, styleProvider: NodeAppearanceProvider) {\n this._allTreeIndices = new IndexSet();\n this._allTreeIndices.addRange(new NumericRange(0, treeIndexCount));\n this._styleProvider = styleProvider;\n this._styleProvider.on('changed', this._handleStylesChangedListener);\n\n const textures = allocateTextures(treeIndexCount);\n this._overrideColorPerTreeIndexTexture = textures.overrideColorPerTreeIndexTexture;\n this._overrideColorDefaultAppearanceRgba = new Uint8ClampedArray(\n this._overrideColorPerTreeIndexTexture.image.data.length\n );\n this._regularNodesTreeIndices = new IndexSet();\n this._ghostedNodesTreeIndices = new IndexSet();\n this._infrontNodesTreeIndices = new IndexSet();\n\n this.setDefaultAppearance(DefaultNodeAppearance.Default);\n }\n\n getDefaultAppearance(): NodeAppearance {\n return this._defaultAppearance;\n }\n\n /**\n * Sets the default style and invalidates the builder. Note that this causes a full\n * recomputation of values the next time {@link build} is called, so using this might be\n * expensive.\n * @param appearance New style that is applied to all 'unstyled' elements.\n */\n setDefaultAppearance(appearance: NodeAppearance) {\n if (equalNodeAppearances(appearance, this._defaultAppearance)) {\n return;\n }\n\n this._defaultAppearance = appearance;\n // Create a pre-cached buffer of texture content for fast initialization in build()\n fillRGBA(this._overrideColorDefaultAppearanceRgba, appearance);\n this._needsUpdate = true;\n }\n\n get regularNodeTreeIndices(): IndexSet {\n return this._regularNodesTreeIndices;\n }\n\n get ghostedNodeTreeIndices(): IndexSet {\n return this._ghostedNodesTreeIndices;\n }\n\n get infrontNodeTreeIndices(): IndexSet {\n return this._infrontNodesTreeIndices;\n }\n\n get needsUpdate(): boolean {\n return this._needsUpdate;\n }\n\n /**\n * A texture holding at least one element per node with color override\n * and style information. RGB is used to store color, A is used to store\n * style toggles, with the following bit layout:\n * - 0 : visible bit - when set the node is visible\n * - 1 : in front bit - when set the node is rendered in front of other objects\n * - 2 : ghosted bit - when set the node is rendered 'ghosted'\n * - 3-5: outline color - outline toggle and color ({@see OutlineColor}).\n * - 6-7: unused\n * Note that in-front and ghost information also is available from\n * the {@see inFrontTreeIndices} and {@see ghostedTreeIndices} collections.\n */\n get overrideColorPerTreeIndexTexture(): THREE.DataTexture {\n return this._overrideColorPerTreeIndexTexture;\n }\n\n dispose() {\n this._styleProvider.off('changed', this._handleStylesChangedListener);\n this._overrideColorPerTreeIndexTexture.dispose();\n }\n\n build() {\n if (!this._needsUpdate) {\n return;\n }\n\n const rgba = this._overrideColorPerTreeIndexTexture.image.data;\n this.populateTexture(rgba);\n this.populateNodeSets(rgba);\n\n this._needsUpdate = false;\n }\n\n private populateTexture(rgbaBuffer: Uint8ClampedArray) {\n // Fill texture with default style\n rgbaBuffer.set(this._overrideColorDefaultAppearanceRgba); // Note! This is basically memcpy(), i.e. fast\n\n // Apply individual styles\n this._styleProvider.applyStyles((treeIndices, appearance) => {\n // Translate from style to magic values in textures\n const fullStyle = { ...this._defaultAppearance, ...appearance };\n this.applyStyleToNodes(treeIndices, fullStyle);\n });\n\n this._overrideColorPerTreeIndexTexture.needsUpdate = true;\n }\n\n private populateNodeSets(rgbaBuffer: Uint8ClampedArray) {\n this._regularNodesTreeIndices.clear();\n this._infrontNodesTreeIndices.clear();\n this._ghostedNodesTreeIndices.clear();\n\n const range = {\n rangeStart: -1,\n inFront: false,\n ghosted: false\n };\n\n const commitRange = (toExclusive: number) => {\n const treeIndexRange = NumericRange.createFromInterval(range.rangeStart, toExclusive - 1);\n if (range.inFront) {\n this._infrontNodesTreeIndices.addRange(treeIndexRange);\n } else if (range.ghosted) {\n this._ghostedNodesTreeIndices.addRange(treeIndexRange);\n } else {\n this._regularNodesTreeIndices.addRange(treeIndexRange);\n }\n };\n\n // Loop over texture to determine if each node is \"regular\", \"ghosted\" or \"in front\"\n for (let i = 0; i < this._allTreeIndices.count; ++i) {\n const inFront = (rgbaBuffer[4 * i + 3] & 2) !== 0;\n const ghosted = (rgbaBuffer[4 * i + 3] & 4) !== 0;\n if (range.rangeStart === -1) {\n range.rangeStart = i;\n range.inFront = inFront;\n range.ghosted = ghosted;\n } else if (range.inFront !== inFront || range.ghosted !== ghosted) {\n commitRange(i);\n range.rangeStart = i;\n range.inFront = inFront;\n range.ghosted = ghosted;\n }\n }\n // Commit the last range\n if (range.rangeStart !== -1) {\n commitRange(this._allTreeIndices.count);\n }\n }\n\n private applyStyleToNodes(treeIndices: IndexSet, style: NodeAppearance) {\n if (treeIndices.count === 0) {\n return;\n }\n\n combineRGBA(this._overrideColorPerTreeIndexTexture.image.data, treeIndices, style);\n }\n\n private handleStylesChanged() {\n this._needsUpdate = true;\n }\n}\n\nfunction allocateTextures(treeIndexCount: number): {\n overrideColorPerTreeIndexTexture: THREE.DataTexture;\n transformOverrideIndexTexture: THREE.DataTexture;\n} {\n const { width, height } = determinePowerOfTwoDimensions(treeIndexCount);\n const textureElementCount = width * height;\n\n // Color and style override texture\n const overrideColorPerTreeIndexTexture = new THREE.DataTexture(\n new Uint8ClampedArray(4 * textureElementCount),\n width,\n height\n );\n\n // Texture for holding node transforms (translation, scale, rotation)\n const transformOverrideIndexBuffer = new Uint8ClampedArray(3 * textureElementCount);\n const transformOverrideIndexTexture = new THREE.DataTexture(\n transformOverrideIndexBuffer,\n width,\n height,\n THREE.RGBFormat\n );\n\n return { overrideColorPerTreeIndexTexture, transformOverrideIndexTexture };\n}\n\nfunction appearanceToColorOverride(appearance: NodeAppearance): [number, number, number, number] {\n const [r, g, b] = appearance.color || [0, 0, 0];\n const isVisible = appearance.visible !== undefined ? !!appearance.visible : true;\n const inFront = !!appearance.renderInFront;\n const ghosted = !!appearance.renderGhosted;\n const outlineColor = appearance.outlineColor ? Number(appearance.outlineColor) : 0;\n // Byte layout:\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\n const bytePattern = (isVisible ? 1 << 0 : 0) + (inFront ? 1 << 1 : 0) + (ghosted ? 1 << 2 : 0) + (outlineColor << 3);\n return [r, g, b, bytePattern];\n}\n\nfunction fillRGBA(rgbaBuffer: Uint8ClampedArray, style: NodeAppearance) {\n const [r, g, b, a] = appearanceToColorOverride(style);\n for (let i = 0; i < rgbaBuffer.length; ++i) {\n rgbaBuffer[4 * i + 0] = r;\n rgbaBuffer[4 * i + 1] = g;\n rgbaBuffer[4 * i + 2] = b;\n rgbaBuffer[4 * i + 3] = a;\n }\n}\n\nfunction combineRGBA(rgbaBuffer: Uint8ClampedArray, treeIndices: IndexSet, style: NodeAppearance) {\n const [r, g, b, a] = appearanceToColorOverride(style);\n // Create a bit mask for updating color (update if style contains color, don't update if it doesn't)\n const updateRgbBitmask = style.color !== undefined ? 0b11111111 : 0;\n const keepRgbBitmask = ~updateRgbBitmask;\n const updateR = r & updateRgbBitmask;\n const updateG = g & updateRgbBitmask;\n const updateB = b & updateRgbBitmask;\n\n // Create bit masks for updating the correct bits in the alpha channel based on what settings\n // the style overrides\n const updateAlphaBitmask =\n (style.visible !== undefined ? 0b00000001 : 0) |\n (style.renderInFront !== undefined ? 0b00000010 : 0) |\n (style.renderGhosted !== undefined ? 0b00000100 : 0) |\n (style.outlineColor !== undefined ? 0b00111000 : 0);\n const keepAlphaBitmask = ~updateAlphaBitmask;\n const updateAlpha = a & updateAlphaBitmask;\n\n treeIndices.forEachRange(range => {\n for (let i = range.from; i <= range.toInclusive; ++i) {\n // Combine color - this will replace color if the style provided sets color or keep\n // the old color if not\n rgbaBuffer[4 * i + 0] = (r & keepRgbBitmask) | updateR;\n rgbaBuffer[4 * i + 1] = (g & keepRgbBitmask) | updateG;\n rgbaBuffer[4 * i + 2] = (b & keepRgbBitmask) | updateB;\n // Update \"settings\" - this will override any settings provided by the style,\n // but keep any existing setting that is not provided by the style\n rgbaBuffer[4 * i + 3] = (rgbaBuffer[4 * i + 3] & keepAlphaBitmask) | updateAlpha;\n }\n });\n}\n\nfunction equalNodeAppearances(left: NodeAppearance, right: NodeAppearance) {\n // https://stackoverflow.com/a/1144249/167251\n return JSON.stringify(left) === JSON.stringify(right);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { packFloatInto } from '@reveal/utilities';\nimport { determinePowerOfTwoDimensions } from '@reveal/utilities';\n\nexport class TransformOverrideBuffer {\n private static readonly MIN_NUMBER_OF_TREE_INDICES = 16;\n private static readonly NUMBER_OF_ELEMENTS_PER_MATRIX = 16;\n private static readonly BYTES_PER_FLOAT = 4;\n\n private _dataTexture: THREE.DataTexture;\n private _textureBuffer: Uint8Array;\n\n private _unusedIndices: number[];\n\n private _treeIndexToOverrideIndex: Map<number, number>;\n\n private _onGenerateNewDataTextureCallback: (datatexture: THREE.DataTexture) => void;\n\n get dataTexture(): THREE.DataTexture {\n return this._dataTexture;\n }\n\n get overrideIndices() {\n return this._treeIndexToOverrideIndex;\n }\n\n constructor(onGenerateNewDataTexture: (datatexture: THREE.DataTexture) => void) {\n this._textureBuffer = new Uint8Array(\n TransformOverrideBuffer.MIN_NUMBER_OF_TREE_INDICES *\n TransformOverrideBuffer.NUMBER_OF_ELEMENTS_PER_MATRIX *\n TransformOverrideBuffer.BYTES_PER_FLOAT\n );\n\n this._dataTexture = new THREE.DataTexture(\n this._textureBuffer,\n TransformOverrideBuffer.NUMBER_OF_ELEMENTS_PER_MATRIX,\n TransformOverrideBuffer.MIN_NUMBER_OF_TREE_INDICES\n );\n\n this._onGenerateNewDataTextureCallback = onGenerateNewDataTexture;\n\n this._unusedIndices = [...Array(TransformOverrideBuffer.MIN_NUMBER_OF_TREE_INDICES).keys()].map((_, n) => n);\n\n this._treeIndexToOverrideIndex = new Map();\n }\n\n dispose() {\n this._dataTexture.dispose();\n }\n\n public addOverrideTransform(treeIndex: number, transform: THREE.Matrix4): number {\n const transformBuffer = transform.toArray();\n\n let matrixIndex: number | undefined;\n\n if (this._treeIndexToOverrideIndex.has(treeIndex)) {\n matrixIndex = this._treeIndexToOverrideIndex.get(treeIndex)!;\n } else {\n matrixIndex = this._unusedIndices.pop();\n\n if (matrixIndex === undefined) {\n this.recomputeDataTexture();\n matrixIndex = this._unusedIndices.pop()!;\n }\n\n this._treeIndexToOverrideIndex.set(treeIndex, matrixIndex);\n }\n\n for (let i = 0; i < TransformOverrideBuffer.NUMBER_OF_ELEMENTS_PER_MATRIX; i++) {\n const byteIndex =\n (matrixIndex * TransformOverrideBuffer.NUMBER_OF_ELEMENTS_PER_MATRIX + i) *\n TransformOverrideBuffer.BYTES_PER_FLOAT;\n\n const matrixElement = transformBuffer[(i % 4) * 4 + Math.floor(i / 4)];\n\n packFloatInto(matrixElement, this._dataTexture.image.data, byteIndex);\n }\n\n this._dataTexture.needsUpdate = true;\n\n return matrixIndex;\n }\n\n public removeOverrideTransform(treeIndex: number) {\n if (!this._treeIndexToOverrideIndex.has(treeIndex)) return;\n\n const matrixIndex = this._treeIndexToOverrideIndex.get(treeIndex)!;\n\n this._unusedIndices.push(matrixIndex);\n this._treeIndexToOverrideIndex.delete(treeIndex);\n }\n\n private recomputeDataTexture() {\n const currentTextureBufferLength = this._textureBuffer.length;\n\n const newTextureBuffer = new Uint8Array(currentTextureBufferLength * 2);\n\n newTextureBuffer.set(this._textureBuffer);\n\n const textureDims = determinePowerOfTwoDimensions(\n (currentTextureBufferLength * 2) / TransformOverrideBuffer.BYTES_PER_FLOAT\n );\n\n const newDataTexture = new THREE.DataTexture(newTextureBuffer, textureDims.width, textureDims.height);\n\n const numberOfNewTreeIndices =\n currentTextureBufferLength /\n (TransformOverrideBuffer.BYTES_PER_FLOAT * TransformOverrideBuffer.NUMBER_OF_ELEMENTS_PER_MATRIX);\n\n for (let i = numberOfNewTreeIndices; i < numberOfNewTreeIndices * 2; i++) {\n this._unusedIndices.push(i);\n }\n\n this._textureBuffer = newTextureBuffer;\n this._dataTexture = newDataTexture;\n\n this._onGenerateNewDataTextureCallback(newDataTexture);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nimport { TransformOverrideBuffer } from './TransformOverrideBuffer';\n\nimport { determinePowerOfTwoDimensions, assertNever, NumericRange } from '@reveal/utilities';\nimport { NodeTransformProvider } from './NodeTransformProvider';\n\nexport class NodeTransformTextureBuilder {\n private readonly _transformProvider: NodeTransformProvider;\n private readonly _transformOverrideBuffer: TransformOverrideBuffer;\n private readonly _transformOverrideIndexTexture: THREE.DataTexture;\n private _needsUpdate = false;\n private _handleTransformChangedBound = this.handleTransformChanged.bind(this);\n\n constructor(treeIndexCount: number, transformProvider: NodeTransformProvider) {\n const textures = allocateTextures(treeIndexCount);\n this._transformOverrideIndexTexture = textures.transformOverrideIndexTexture;\n this._transformOverrideBuffer = new TransformOverrideBuffer(this.handleNewTransformTexture.bind(this));\n this._transformProvider = transformProvider;\n\n this._transformProvider.on('changed', this._handleTransformChangedBound);\n }\n\n dispose() {\n this._transformOverrideBuffer.dispose();\n this._transformOverrideIndexTexture.dispose();\n this._transformProvider.off('changed', this._handleTransformChangedBound);\n }\n\n get needsUpdate() {\n return this._needsUpdate;\n }\n\n get overrideTransformIndexTexture(): THREE.DataTexture {\n return this._transformOverrideIndexTexture;\n }\n\n get transformLookupTexture(): THREE.DataTexture {\n return this._transformOverrideBuffer.dataTexture;\n }\n\n build() {\n this._needsUpdate = false;\n }\n\n private setNodeTransform(treeIndices: NumericRange, transform: THREE.Matrix4) {\n const transformIndex = this._transformOverrideBuffer.addOverrideTransform(treeIndices.from, transform);\n treeIndices.forEach(treeIndex => this.setOverrideIndex(treeIndex, transformIndex));\n this._needsUpdate = true;\n }\n\n private resetNodeTransform(treeIndices: NumericRange) {\n this._transformOverrideBuffer.removeOverrideTransform(treeIndices.from);\n treeIndices.forEach(treeIndex => this.setOverrideIndex(treeIndex, -1));\n this._needsUpdate = true;\n }\n\n private setOverrideIndex(treeIndex: number, transformIndex: number) {\n const data = this._transformOverrideIndexTexture.image.data;\n data[treeIndex * 3 + 0] = (transformIndex + 1) >> 16;\n data[treeIndex * 3 + 1] = (transformIndex + 1) >> 8;\n data[treeIndex * 3 + 2] = (transformIndex + 1) >> 0;\n this._transformOverrideIndexTexture.needsUpdate = true;\n }\n\n private handleNewTransformTexture() {\n this._needsUpdate = true;\n }\n\n private handleTransformChanged(change: 'set' | 'reset', treeIndices: NumericRange, transform: THREE.Matrix4) {\n switch (change) {\n case 'set':\n this.setNodeTransform(treeIndices, transform);\n break;\n case 'reset':\n this.resetNodeTransform(treeIndices);\n break;\n default:\n assertNever(change, `Unexpected change type '${change}'`);\n }\n }\n}\n\nfunction allocateTextures(treeIndexCount: number): { transformOverrideIndexTexture: THREE.DataTexture } {\n const { width, height } = determinePowerOfTwoDimensions(treeIndexCount);\n const textureElementCount = width * height;\n\n // Texture for holding node transforms (translation, scale, rotation)\n const transformOverrideIndexBuffer = new Uint8ClampedArray(3 * textureElementCount);\n const transformOverrideIndexTexture = new THREE.DataTexture(\n transformOverrideIndexBuffer,\n width,\n height,\n THREE.RGBFormat\n );\n\n return { transformOverrideIndexTexture };\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nconst image = new Image();\n\n// Image source https://github.com/nidorx/matcaps/blob/master/PAGE-26.md\nimage.src =\n 'data:image/png;base64,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';\n\nexport default image;\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { sectorShaders, shaderDefines } from './shaders';\nimport { RenderMode } from './RenderMode';\n\nimport matCapTextureImage from './matCapTextureData';\n\nexport interface Materials {\n // Materials\n box: THREE.ShaderMaterial;\n circle: THREE.ShaderMaterial;\n generalRing: THREE.ShaderMaterial;\n nut: THREE.ShaderMaterial;\n quad: THREE.ShaderMaterial;\n cone: THREE.ShaderMaterial;\n eccentricCone: THREE.ShaderMaterial;\n sphericalSegment: THREE.ShaderMaterial;\n torusSegment: THREE.ShaderMaterial;\n generalCylinder: THREE.ShaderMaterial;\n trapezium: THREE.ShaderMaterial;\n ellipsoidSegment: THREE.ShaderMaterial;\n instancedMesh: THREE.ShaderMaterial;\n triangleMesh: THREE.ShaderMaterial;\n simple: THREE.ShaderMaterial;\n}\n\nexport function createMaterials(\n renderMode: RenderMode,\n clippingPlanes: THREE.Plane[],\n overrideColorPerTreeIndex: THREE.DataTexture,\n transformOverrideIndexTexture: THREE.DataTexture,\n transformOverrideLookupTexture: THREE.DataTexture\n): Materials {\n const transparent = false;\n\n const matCapTexture = new THREE.Texture(matCapTextureImage);\n matCapTexture.needsUpdate = true;\n\n const boxMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Box)',\n clipping: true,\n clippingPlanes,\n extensions: { fragDepth: true },\n vertexShader: sectorShaders.boxPrimitive.vertex,\n fragmentShader: sectorShaders.boxPrimitive.fragment,\n side: THREE.DoubleSide,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n transparent\n });\n\n const circleMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Circle)',\n clipping: true,\n clippingPlanes,\n extensions: { fragDepth: true },\n vertexShader: sectorShaders.circlePrimitive.vertex,\n fragmentShader: sectorShaders.circlePrimitive.fragment,\n // TODO double side is not necessary for all,\n // we should indicate this in the data from Rust\n side: THREE.DoubleSide,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n transparent\n });\n\n const nutMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Nuts)',\n clipping: true,\n clippingPlanes,\n vertexShader: sectorShaders.nutPrimitive.vertex,\n fragmentShader: sectorShaders.nutPrimitive.fragment,\n side: THREE.DoubleSide,\n transparent\n });\n\n const quadMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Quads)',\n clipping: true,\n clippingPlanes,\n vertexShader: sectorShaders.quadPrimitive.vertex,\n fragmentShader: sectorShaders.quadPrimitive.fragment,\n side: THREE.DoubleSide,\n transparent\n });\n\n const generalRingMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (General rings)',\n clipping: true,\n clippingPlanes,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n extensions: { fragDepth: true },\n vertexShader: sectorShaders.generalRingPrimitive.vertex,\n fragmentShader: sectorShaders.generalRingPrimitive.fragment,\n // TODO we can avoid drawing DoubleSide if we flip the ring in Rust and adjust the angle and\n // arc_angle accordingly\n side: THREE.DoubleSide,\n transparent\n });\n\n const coneMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Cone)',\n clipping: true,\n clippingPlanes,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n extensions: { fragDepth: true },\n vertexShader: sectorShaders.conePrimitive.vertex,\n fragmentShader: sectorShaders.conePrimitive.fragment,\n side: THREE.DoubleSide,\n transparent\n });\n\n const eccentricConeMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Eccentric cone)',\n clipping: true,\n clippingPlanes,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n extensions: { fragDepth: true },\n vertexShader: sectorShaders.eccentricConePrimitive.vertex,\n fragmentShader: sectorShaders.eccentricConePrimitive.fragment,\n side: THREE.DoubleSide,\n transparent\n });\n\n const ellipsoidSegmentMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Ellipsoid segments)',\n clipping: true,\n clippingPlanes,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n\n extensions: { fragDepth: true },\n vertexShader: sectorShaders.ellipsoidSegmentPrimitive.vertex,\n fragmentShader: sectorShaders.ellipsoidSegmentPrimitive.fragment,\n side: THREE.DoubleSide,\n transparent\n });\n\n const generalCylinderMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (General cylinder)',\n clipping: true,\n clippingPlanes,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n extensions: { fragDepth: true },\n vertexShader: sectorShaders.generalCylinderPrimitive.vertex,\n fragmentShader: sectorShaders.generalCylinderPrimitive.fragment,\n side: THREE.DoubleSide,\n transparent\n });\n\n const trapeziumMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Trapezium)',\n clipping: true,\n clippingPlanes,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n extensions: { fragDepth: true },\n vertexShader: sectorShaders.trapeziumPrimitive.vertex,\n fragmentShader: sectorShaders.trapeziumPrimitive.fragment,\n side: THREE.DoubleSide,\n transparent\n });\n\n const torusSegmentMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Torus segment)',\n clipping: true,\n clippingPlanes,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n extensions: {\n fragDepth: true,\n derivatives: true\n },\n vertexShader: sectorShaders.torusSegmentPrimitive.vertex,\n fragmentShader: sectorShaders.torusSegmentPrimitive.fragment,\n side: THREE.DoubleSide,\n transparent\n });\n\n const sphericalSegmentMaterial = new THREE.ShaderMaterial({\n name: 'Primitives (Spherical segment)',\n clipping: true,\n clippingPlanes,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n extensions: { fragDepth: true },\n vertexShader: sectorShaders.ellipsoidSegmentPrimitive.vertex,\n fragmentShader: sectorShaders.ellipsoidSegmentPrimitive.fragment,\n side: THREE.DoubleSide,\n transparent\n });\n\n const triangleMeshMaterial = new THREE.ShaderMaterial({\n name: 'Triangle meshes',\n clipping: true,\n clippingPlanes,\n extensions: {\n derivatives: true\n },\n side: THREE.DoubleSide,\n fragmentShader: sectorShaders.detailedMesh.fragment,\n vertexShader: sectorShaders.detailedMesh.vertex,\n transparent\n });\n\n const instancedMeshMaterial = new THREE.ShaderMaterial({\n name: 'Instanced meshes',\n clipping: true,\n clippingPlanes,\n extensions: {\n derivatives: true\n },\n side: THREE.DoubleSide,\n fragmentShader: sectorShaders.instancedMesh.fragment,\n vertexShader: sectorShaders.instancedMesh.vertex,\n transparent\n });\n\n const simpleMaterial = new THREE.ShaderMaterial({\n name: 'Low detail material',\n clipping: true,\n clippingPlanes,\n uniforms: {\n inverseModelMatrix: {\n value: new THREE.Matrix4()\n }\n },\n side: THREE.FrontSide,\n fragmentShader: sectorShaders.simpleMesh.fragment,\n vertexShader: sectorShaders.simpleMesh.vertex,\n transparent\n });\n\n const allMaterials = {\n box: boxMaterial,\n circle: circleMaterial,\n nut: nutMaterial,\n generalRing: generalRingMaterial,\n quad: quadMaterial,\n cone: coneMaterial,\n eccentricCone: eccentricConeMaterial,\n sphericalSegment: sphericalSegmentMaterial,\n torusSegment: torusSegmentMaterial,\n generalCylinder: generalCylinderMaterial,\n trapezium: trapeziumMaterial,\n ellipsoidSegment: ellipsoidSegmentMaterial,\n instancedMesh: instancedMeshMaterial,\n triangleMesh: triangleMeshMaterial,\n simple: simpleMaterial\n };\n\n for (const material of Object.values(allMaterials)) {\n updateDefinesAndUniforms(\n material,\n overrideColorPerTreeIndex,\n transformOverrideIndexTexture,\n transformOverrideLookupTexture,\n matCapTexture,\n renderMode\n );\n }\n\n return {\n ...allMaterials\n };\n}\n\nfunction updateDefinesAndUniforms(\n material: THREE.ShaderMaterial,\n overrideColorPerTreeIndex: THREE.DataTexture,\n transformOverrideIndexTexture: THREE.DataTexture,\n transformOverrideTexture: THREE.DataTexture,\n matCapTexture: THREE.Texture,\n renderMode: RenderMode\n) {\n const treeIndexTextureSize = new THREE.Vector2(\n overrideColorPerTreeIndex.image.width,\n overrideColorPerTreeIndex.image.height\n );\n const transformOverrideTextureSize = new THREE.Vector2(\n transformOverrideTexture.image.width,\n transformOverrideTexture.image.height\n );\n const oldUniforms = material.uniforms;\n material.setValues({\n ...shaderDefines,\n uniforms: {\n ...oldUniforms,\n renderMode: {\n value: renderMode\n },\n treeIndexTextureSize: {\n value: treeIndexTextureSize\n },\n transformOverrideTextureSize: {\n value: transformOverrideTextureSize\n },\n colorDataTexture: {\n value: overrideColorPerTreeIndex\n },\n transformOverrideIndexTexture: {\n value: transformOverrideIndexTexture\n },\n transformOverrideTexture: {\n value: transformOverrideTexture\n },\n matCapTexture: {\n value: matCapTexture\n }\n }\n });\n\n material.uniformsNeedUpdate = true;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { NodeAppearanceTextureBuilder } from './styling/NodeAppearanceTextureBuilder';\nimport { NodeAppearance } from '@reveal/cad-styling';\nimport { NodeTransformTextureBuilder } from './styling/NodeTransformTextureBuilder';\nimport { NodeTransformProvider } from './styling/NodeTransformProvider';\n\nimport { createMaterials, Materials, RenderMode } from '@reveal/cad-parsers';\nimport { NodeAppearanceProvider } from '@reveal/cad-styling';\nimport { IndexSet, EventTrigger, assertNever } from '@reveal/utilities';\n\nimport throttle from 'lodash/throttle';\n\ninterface MaterialsWrapper {\n materials: Materials;\n perModelClippingPlanes: THREE.Plane[];\n nodeAppearanceProvider: NodeAppearanceProvider;\n nodeTransformProvider: NodeTransformProvider;\n nodeAppearanceTextureBuilder: NodeAppearanceTextureBuilder;\n nodeTransformTextureBuilder: NodeTransformTextureBuilder;\n updateMaterialsCallback: () => void;\n updateTransformsCallback: () => void;\n}\n\nexport class CadMaterialManager {\n private readonly _events = {\n materialsChanged: new EventTrigger<() => void>()\n };\n\n get clippingPlanes(): THREE.Plane[] {\n return this._clippingPlanes;\n }\n\n set clippingPlanes(clippingPlanes: THREE.Plane[]) {\n this._clippingPlanes = clippingPlanes;\n for (const modelIdentifier of this.materialsMap.keys()) {\n this.updateClippingPlanesForModel(modelIdentifier);\n }\n this.triggerMaterialsChanged();\n }\n\n private _renderMode: RenderMode = RenderMode.Color;\n private readonly materialsMap: Map<string, MaterialsWrapper> = new Map();\n // TODO: j-bjorne 29-04-2020: Move into separate cliping manager?\n private _clippingPlanes: THREE.Plane[] = [];\n\n public on(event: 'materialsChanged', listener: () => void): void {\n switch (event) {\n case 'materialsChanged':\n this._events.materialsChanged.subscribe(listener);\n break;\n\n default:\n assertNever(event, `Unexpected event '${event}`);\n }\n }\n\n public off(event: 'materialsChanged', listener: () => void): void {\n switch (event) {\n case 'materialsChanged':\n this._events.materialsChanged.unsubscribe(listener);\n break;\n\n default:\n assertNever(event, `Unexpected event '${event}`);\n }\n }\n\n addModelMaterials(modelIdentifier: string, maxTreeIndex: number) {\n const nodeAppearanceProvider = new NodeAppearanceProvider();\n const nodeAppearanceTextureBuilder = new NodeAppearanceTextureBuilder(maxTreeIndex + 1, nodeAppearanceProvider);\n nodeAppearanceTextureBuilder.build();\n\n const nodeTransformProvider = new NodeTransformProvider();\n const nodeTransformTextureBuilder = new NodeTransformTextureBuilder(maxTreeIndex + 1, nodeTransformProvider);\n nodeTransformTextureBuilder.build();\n\n const materialUpdateThrottleDelay = 75;\n const updateMaterialsCallback: () => void = throttle(\n () => this.updateMaterials(modelIdentifier),\n materialUpdateThrottleDelay,\n {\n leading: true,\n trailing: true\n }\n );\n const updateTransformsCallback = () => this.updateTransforms(modelIdentifier);\n\n nodeAppearanceProvider.on('changed', updateMaterialsCallback);\n nodeTransformProvider.on('changed', updateTransformsCallback);\n\n const materials = createMaterials(\n this._renderMode,\n this._clippingPlanes,\n nodeAppearanceTextureBuilder.overrideColorPerTreeIndexTexture,\n nodeTransformTextureBuilder.overrideTransformIndexTexture,\n nodeTransformTextureBuilder.transformLookupTexture\n );\n this.materialsMap.set(modelIdentifier, {\n materials,\n perModelClippingPlanes: [],\n nodeAppearanceProvider,\n nodeTransformProvider,\n nodeAppearanceTextureBuilder,\n nodeTransformTextureBuilder,\n updateMaterialsCallback,\n updateTransformsCallback\n });\n\n this.updateClippingPlanesForModel(modelIdentifier);\n }\n\n getModelMaterials(modelIdentifier: string): Materials {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n return wrapper.materials;\n }\n\n getModelNodeAppearanceProvider(modelIdentifier: string): NodeAppearanceProvider {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n return wrapper.nodeAppearanceProvider;\n }\n\n getModelNodeTransformProvider(modelIdentifier: string): NodeTransformProvider {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n return wrapper.nodeTransformProvider;\n }\n\n getModelDefaultNodeAppearance(modelIdentifier: string): NodeAppearance {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n return wrapper.nodeAppearanceTextureBuilder.getDefaultAppearance();\n }\n\n setModelClippingPlanes(modelIdentifier: string, clippingPlanes: THREE.Plane[]) {\n const materialWrapper = this.materialsMap.get(modelIdentifier);\n if (materialWrapper === undefined) {\n throw new Error(\n `Materials for model ${modelIdentifier} has not been added, call ${this.addModelMaterials.name} first`\n );\n }\n\n materialWrapper.perModelClippingPlanes = clippingPlanes;\n this.updateClippingPlanesForModel(modelIdentifier);\n this.triggerMaterialsChanged();\n }\n\n private updateClippingPlanesForModel(modelIdentifier: string) {\n const materialWrapper = this.materialsMap.get(modelIdentifier);\n if (materialWrapper === undefined) {\n throw new Error(\n `Materials for model ${modelIdentifier} has not been added, call ${this.addModelMaterials.name} first`\n );\n }\n\n const clippingPlanes = [...materialWrapper.perModelClippingPlanes, ...this.clippingPlanes];\n applyToModelMaterials(materialWrapper.materials, m => {\n m.clipping = true;\n m.clipIntersection = false;\n m.clippingPlanes = clippingPlanes;\n });\n }\n\n setModelDefaultNodeAppearance(modelIdentifier: string, defaultAppearance: NodeAppearance) {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n wrapper.nodeAppearanceTextureBuilder.setDefaultAppearance(defaultAppearance);\n this.updateMaterials(modelIdentifier);\n }\n\n getModelBackTreeIndices(modelIdentifier: string): IndexSet {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n return wrapper.nodeAppearanceTextureBuilder.regularNodeTreeIndices;\n }\n\n getModelInFrontTreeIndices(modelIdentifier: string): IndexSet {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n return wrapper.nodeAppearanceTextureBuilder.infrontNodeTreeIndices;\n }\n\n getModelGhostedTreeIndices(modelIdentifier: string): IndexSet {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n return wrapper.nodeAppearanceTextureBuilder.ghostedNodeTreeIndices;\n }\n\n setRenderMode(mode: RenderMode) {\n this._renderMode = mode;\n const transparent = mode === RenderMode.Ghost;\n const colorWrite = mode !== RenderMode.DepthBufferOnly;\n this.applyToAllMaterials(material => {\n material.uniforms.renderMode.value = mode;\n material.colorWrite = colorWrite;\n material.transparent = transparent;\n });\n }\n\n getRenderMode(): RenderMode {\n return this._renderMode;\n }\n\n private updateMaterials(modelIdentifier: string) {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n if (wrapper.nodeAppearanceTextureBuilder.needsUpdate) {\n const { nodeAppearanceTextureBuilder } = wrapper;\n nodeAppearanceTextureBuilder.build();\n }\n this.triggerMaterialsChanged();\n }\n\n private updateTransforms(modelIdentifier: string) {\n const wrapper = this.getModelMaterialsWrapper(modelIdentifier);\n if (wrapper.nodeTransformTextureBuilder.needsUpdate) {\n const { nodeTransformTextureBuilder, materials } = wrapper;\n nodeTransformTextureBuilder.build();\n\n const transformsLookupTexture = nodeTransformTextureBuilder.transformLookupTexture;\n const transformsLookupTextureSize = new THREE.Vector2(\n transformsLookupTexture.image.width,\n transformsLookupTexture.image.height\n );\n applyToModelMaterials(materials, material => {\n material.uniforms.transformOverrideTexture.value = transformsLookupTexture;\n material.uniforms.transformOverrideTextureSize.value = transformsLookupTextureSize;\n });\n }\n this.triggerMaterialsChanged();\n }\n\n private getModelMaterialsWrapper(modelIdentifier: string): MaterialsWrapper {\n const wrapper = this.materialsMap.get(modelIdentifier);\n if (wrapper === undefined) {\n throw new Error(`Model ${modelIdentifier} has not been added to MaterialManager`);\n }\n return wrapper;\n }\n\n private applyToAllMaterials(callback: (material: THREE.ShaderMaterial) => void) {\n for (const materialWrapper of this.materialsMap.values()) {\n const materials = materialWrapper.materials;\n applyToModelMaterials(materials, callback);\n }\n }\n\n private triggerMaterialsChanged() {\n this._events.materialsChanged.fire();\n }\n}\n\nfunction applyToModelMaterials(materials: Materials, callback: (material: THREE.ShaderMaterial) => void) {\n callback(materials.box);\n callback(materials.circle);\n callback(materials.generalRing);\n callback(materials.nut);\n callback(materials.quad);\n callback(materials.cone);\n callback(materials.eccentricCone);\n callback(materials.sphericalSegment);\n callback(materials.torusSegment);\n callback(materials.generalCylinder);\n callback(materials.trapezium);\n callback(materials.ellipsoidSegment);\n callback(materials.instancedMesh);\n callback(materials.triangleMesh);\n callback(materials.simple);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { of, pipe } from 'rxjs';\nimport { delay, startWith, switchMap, distinctUntilChanged } from 'rxjs/operators';\n\nexport const emissionLastMillis = (millis: number) => {\n return pipe(\n switchMap(_ => delayedSwitch(millis)),\n distinctUntilChanged()\n );\n};\n\nexport const delayedSwitch = (millis: number) => {\n return of(false).pipe(delay(millis), startWith(true));\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { LevelOfDetail } from '@reveal/cad-parsers';\n\nimport { DetermineSectorsInput } from './culling/types';\n\nexport function loadingEnabled({ cadModelsMetadata, loadingHints }: DetermineSectorsInput) {\n return cadModelsMetadata.length > 0 && loadingHints.suspendLoading !== true;\n}\n\nexport interface ModelState {\n [id: number]: LevelOfDetail;\n}\nexport interface SceneModelState {\n [modelIdentifier: string]: ModelState;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Extension utilities for Promise.\n */\nexport class PromiseUtils {\n /**\n * Awaits all promises in the list of promises available, returning them in an async iterator\n * as they finish. The function completes when all promises has completed and the results have\n * been yielded, or one of the promises provided rejects. This function is similar to\n * Promise.all(), except that it returns results as they are ready and doesn't wait for all\n * operations to finish.\n *\n * @param promises A list of promises to complete.\n */\n static async *raceUntilAllCompleted<T>(promises: Promise<T>[]): AsyncIterable<T> {\n // Inspired by https://stackoverflow.com/a/42898229\n const remaining = new Map(promises.map(p => [p, p.then(() => [p])]));\n while (remaining.size > 0) {\n const [completed] = await Promise.race(remaining.values());\n remaining.delete(completed);\n yield completed;\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { ConsumedSector, WantedSector, LevelOfDetail } from '@reveal/cad-parsers';\n\nimport { DetermineSectorsInput, SectorLoadingSpent } from './culling/types';\nimport { SectorCuller } from './culling/SectorCuller';\nimport { ModelStateHandler } from './ModelStateHandler';\nimport { Repository } from './Repository';\nimport chunk from 'lodash/chunk';\nimport { PromiseUtils } from '../utilities/PromiseUtils';\n\nimport log from '@reveal/logger';\n\n/**\n * How many sectors to load per batch before doing another filtering pass, i.e. perform culling to determine\n * potential visible sectors.\n */\nconst SectorLoadingBatchSize = 20;\n\n/**\n * Loads sector based on a given camera pose, a set of models and budget.\n * Uses {@link SectorCuller} to determine what to load, {@link Repository} to\n * load sectors and {@link ModelStateHandler} to keep track of what has been\n * loaded to avoid loading data that's already available.\n *\n * The caller is responsible for making the result from the load operation visible\n * on screen.\n */\nexport class SectorLoader {\n private readonly _modelStateHandler: ModelStateHandler;\n private readonly _sectorCuller: SectorCuller;\n private readonly _sectorRepository: Repository;\n private readonly _progressCallback: (sectorsLoaded: number, sectorsScheduled: number, sectorsCulled: number) => void;\n private readonly _collectStatisticsCallback: (spent: SectorLoadingSpent) => void;\n\n constructor(\n sectorRepository: Repository,\n sectorCuller: SectorCuller,\n modelStateHandler: ModelStateHandler,\n collectStatisticsCallback: (spent: SectorLoadingSpent) => void,\n progressCallback: (sectorsLoaded: number, sectorsScheduled: number, sectorsCulled: number) => void\n ) {\n this._sectorRepository = sectorRepository;\n this._sectorCuller = sectorCuller;\n this._modelStateHandler = modelStateHandler;\n this._collectStatisticsCallback = collectStatisticsCallback;\n this._progressCallback = progressCallback;\n }\n\n async *loadSectors(input: DetermineSectorsInput): AsyncIterable<ConsumedSector> {\n if (input.cameraInMotion) {\n return [];\n }\n\n // Initial prioritization\n const prioritizedResult = this._sectorCuller.determineSectors(input);\n this._collectStatisticsCallback(prioritizedResult.spentBudget);\n\n const hasSectorChanged = this._modelStateHandler.hasStateChanged.bind(this._modelStateHandler);\n const changedSectors = prioritizedResult.wantedSectors.filter(hasSectorChanged);\n\n const progressHelper = new ProgressReportHelper(this._progressCallback);\n progressHelper.start(changedSectors.length);\n\n for (const batch of chunk(changedSectors, SectorLoadingBatchSize)) {\n const filtered = await this.filterSectors(input, batch, progressHelper);\n const consumedPromises = this.startLoadingBatch(filtered, progressHelper);\n\n for await (const consumed of PromiseUtils.raceUntilAllCompleted(consumedPromises)) {\n this._modelStateHandler.updateState(consumed);\n yield consumed;\n }\n }\n }\n\n private async filterSectors(\n input: DetermineSectorsInput,\n batch: WantedSector[],\n progressHelper: ProgressReportHelper\n ): Promise<WantedSector[]> {\n // Determine if some of the sectors in the batch is culled by already loaded geometry\n const filteredSectors = await this._sectorCuller.filterSectorsToLoad(input, batch);\n progressHelper.reportNewSectorsCulled(batch.length - filteredSectors.length);\n return filteredSectors;\n }\n\n private startLoadingBatch(batch: WantedSector[], progressHelper: ProgressReportHelper): Promise<ConsumedSector>[] {\n const consumedPromises = batch.map(async wantedSector => {\n try {\n const consumedSector = await this._sectorRepository.loadSector(wantedSector);\n return consumedSector;\n } catch (error) {\n log.error('Failed to load sector', wantedSector, 'error:', error);\n // Ignore error but mark sector as discarded since we didn't load any geometry\n const errorSector = makeErrorSector(wantedSector);\n return errorSector;\n } finally {\n progressHelper.reportNewSectorsLoaded(1);\n }\n });\n return consumedPromises;\n }\n}\n\nfunction makeErrorSector(wantedSector: WantedSector): ConsumedSector {\n return {\n modelIdentifier: wantedSector.modelIdentifier,\n metadata: wantedSector.metadata,\n levelOfDetail: LevelOfDetail.Discarded,\n group: undefined,\n instancedMeshes: undefined\n };\n}\n\nclass ProgressReportHelper {\n private readonly _progressCallback: (sectorsLoaded: number, sectorsScheduled: number, sectorsCulled: number) => void;\n private _sectorsScheduled = 0;\n private _sectorsLoaded = 0;\n private _sectorsCulled = 0;\n\n constructor(reportCb: (sectorsLoaded: number, sectorsScheduled: number, sectorsCulled: number) => void) {\n this._progressCallback = reportCb;\n }\n\n start(sectorsScheduled: number) {\n this._sectorsScheduled = sectorsScheduled;\n this._sectorsLoaded = 0;\n this._sectorsCulled = 0;\n this.triggerCallback();\n }\n\n reportNewSectorsLoaded(loadedCountChange: number) {\n this._sectorsLoaded += loadedCountChange;\n this.triggerCallback();\n }\n\n reportNewSectorsCulled(culledCountChange: number) {\n this._sectorsCulled += culledCountChange;\n this._sectorsLoaded += culledCountChange;\n this.triggerCallback();\n }\n\n private triggerCallback() {\n this._progressCallback(this._sectorsLoaded, this._sectorsScheduled, this._sectorsCulled);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { isMobileOrTablet } from '@reveal/utilities';\n\n/**\n * Represents a measurement of how much geometry can be loaded.\n */\nexport type CadModelSectorBudget = {\n /**\n * Sectors within this distance from the camera will always be loaded in high details.\n */\n readonly highDetailProximityThreshold: number;\n\n /**\n * Number of bytes of the geometry that must be downloaded.\n */\n readonly geometryDownloadSizeBytes: number;\n\n /**\n * Maximum number of estimated draw calls of geometry to load.\n */\n readonly maximumNumberOfDrawCalls: number;\n\n /**\n * Maximum render cost. This number can be thought of as triangle count, although the number\n * doesn't match this directly.\n */\n readonly maximumRenderCost: number;\n};\n\nexport const defaultCadModelSectorBudget: CadModelSectorBudget = isMobileOrTablet()\n ? // Mobile/tablet\n {\n highDetailProximityThreshold: 5,\n geometryDownloadSizeBytes: 20 * 1024 * 1024,\n maximumNumberOfDrawCalls: 700,\n maximumRenderCost: Infinity\n }\n : // Desktop\n {\n highDetailProximityThreshold: 10,\n geometryDownloadSizeBytes: 35 * 1024 * 1024,\n maximumNumberOfDrawCalls: 2000,\n maximumRenderCost: Infinity\n };\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { SceneModelState } from './rxSectorUtilities';\nimport { WantedSector, ConsumedSector, LevelOfDetail } from '@reveal/cad-parsers';\n\nimport assert from 'assert';\n\nexport class ModelStateHandler {\n private readonly _sceneModelState: SceneModelState;\n\n constructor() {\n this._sceneModelState = {} as SceneModelState;\n }\n\n hasStateChanged(wantedSector: WantedSector): boolean {\n const modelState = this._sceneModelState[wantedSector.modelIdentifier];\n assert(modelState !== undefined, `Model ${wantedSector.modelIdentifier} has not been added`);\n const sectorLevelOfDetail = modelState[wantedSector.metadata.id];\n if (sectorLevelOfDetail !== undefined) {\n return sectorLevelOfDetail !== wantedSector.levelOfDetail;\n } else {\n return wantedSector.levelOfDetail !== LevelOfDetail.Discarded;\n }\n }\n\n addModel(modelIdentifier: string) {\n assert(this._sceneModelState[modelIdentifier] === undefined, `Model ${modelIdentifier} is already added`);\n this._sceneModelState[modelIdentifier] = {};\n }\n\n removeModel(modelIdentifier: string) {\n assert(this._sceneModelState[modelIdentifier] !== undefined, `Model ${modelIdentifier} is not added`);\n delete this._sceneModelState[modelIdentifier];\n }\n\n updateState(consumedSector: ConsumedSector) {\n if (this._sceneModelState[consumedSector.modelIdentifier] === undefined) {\n // Received sector from model but the model is not added - happens when\n // sectors from newly removed model are loaded\n return;\n }\n\n const modelState = this._sceneModelState[consumedSector.modelIdentifier];\n if (consumedSector.levelOfDetail === LevelOfDetail.Discarded) {\n delete modelState[consumedSector.metadata.id];\n } else {\n modelState[consumedSector.metadata.id] = consumedSector.levelOfDetail;\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { assertNever } from '@reveal/utilities';\nimport { ConsumedSector } from '@reveal/cad-parsers';\n\nimport { Subject, Observable, combineLatest, asyncScheduler, BehaviorSubject } from 'rxjs';\nimport { CadNode } from './CadNode';\nimport { scan, share, startWith, auditTime, filter, map, finalize, observeOn, mergeMap } from 'rxjs/operators';\nimport { SectorCuller } from './sector/culling/SectorCuller';\nimport { CadLoadingHints } from './CadLoadingHints';\nimport { Repository } from './sector/Repository';\n\nimport { LoadingState } from './utilities/types';\nimport { emissionLastMillis } from './utilities/rxOperations';\nimport { loadingEnabled } from './sector/rxSectorUtilities';\nimport { SectorLoader } from './sector/SectorLoader';\nimport { CadModelSectorBudget, defaultCadModelSectorBudget } from './CadModelSectorBudget';\nimport { DetermineSectorsInput, SectorLoadingSpent } from './sector/culling/types';\nimport { ModelStateHandler } from './sector/ModelStateHandler';\n\nconst notLoadingState: LoadingState = { isLoading: false, itemsLoaded: 0, itemsRequested: 0, itemsCulled: 0 };\n\nexport class CadModelUpdateHandler {\n private readonly _sectorRepository: Repository;\n private readonly _sectorCuller: SectorCuller;\n private readonly _modelStateHandler: ModelStateHandler;\n private _budget: CadModelSectorBudget;\n private _lastSpent: SectorLoadingSpent;\n\n private readonly _cameraSubject: Subject<THREE.PerspectiveCamera> = new Subject();\n private readonly _clippingPlaneSubject: Subject<THREE.Plane[]> = new Subject();\n private readonly _loadingHintsSubject: Subject<CadLoadingHints> = new Subject();\n private readonly _modelSubject: Subject<{ model: CadNode; operation: 'add' | 'remove' }> = new Subject();\n private readonly _budgetSubject: Subject<CadModelSectorBudget> = new Subject();\n private readonly _progressSubject: Subject<LoadingState> = new BehaviorSubject<LoadingState>(notLoadingState);\n\n private readonly _updateObservable: Observable<ConsumedSector>;\n\n constructor(sectorRepository: Repository, sectorCuller: SectorCuller) {\n this._sectorRepository = sectorRepository;\n this._sectorCuller = sectorCuller;\n this._modelStateHandler = new ModelStateHandler();\n this._budget = defaultCadModelSectorBudget;\n this._lastSpent = {\n downloadSize: 0,\n drawCalls: 0,\n renderCost: 0,\n loadedSectorCount: 0,\n simpleSectorCount: 0,\n detailedSectorCount: 0,\n forcedDetailedSectorCount: 0,\n totalSectorCount: 0,\n accumulatedPriority: 0\n };\n\n /* Creates and observable that emits an event when either of the observables emitts an item.\n * ------- new camera ---------\\\n * --- new clipping plane ------\\\n * --- new clip intersection ----\\_______ DetermineSectorsInput\n * --- new global loading hints--/\n * --- new camera motion state -/\n * --- changes in cadmodels ---/\n * ------ sector budget ------/\n */\n const combinator = combineLatest([\n combineLatest([\n this._loadingHintsSubject.pipe(startWith({} as CadLoadingHints)),\n this._budgetSubject.pipe(startWith(this._budget))\n ]).pipe(map(makeSettingsInput)),\n combineLatest([\n this._cameraSubject.pipe(auditTime(500)),\n this._cameraSubject.pipe(auditTime(250), emissionLastMillis(600))\n ]).pipe(map(makeCameraInput)),\n combineLatest([this._clippingPlaneSubject.pipe(startWith([]))]).pipe(map(makeClippingInput)),\n this.loadingModelObservable()\n ]);\n const collectStatisticsCallback = (spendage: SectorLoadingSpent) => {\n this._lastSpent = spendage;\n };\n const reportProgressCallback = (loaded: number, requested: number, culled: number) => {\n const state: LoadingState = {\n isLoading: requested > loaded,\n itemsRequested: requested,\n itemsLoaded: loaded,\n itemsCulled: culled\n };\n this._progressSubject.next(state);\n };\n const determineSectorsHandler = new SectorLoader(\n sectorRepository,\n sectorCuller,\n this._modelStateHandler,\n collectStatisticsCallback,\n reportProgressCallback\n );\n\n async function* loadSectors(input: DetermineSectorsInput) {\n for await (const sector of determineSectorsHandler.loadSectors(input)) {\n yield sector;\n }\n }\n\n this._updateObservable = combinator.pipe(\n observeOn(asyncScheduler), // Schedule tasks on macro task queue (setInterval)\n auditTime(250), // Take the last value every 250ms\n map(createDetermineSectorsInput), // Map from array to interface (enables destructuring)\n filter(loadingEnabled), // should we load?\n mergeMap(async x => loadSectors(x)),\n mergeMap(x => x),\n finalize(() => {\n this._sectorRepository.clear(); // clear the cache once this is unsubscribed from.\n })\n );\n }\n\n dispose() {\n this._sectorCuller.dispose();\n }\n\n updateCamera(camera: THREE.PerspectiveCamera): void {\n this._cameraSubject.next(camera);\n this._progressSubject.next(notLoadingState);\n }\n\n set clippingPlanes(value: THREE.Plane[]) {\n this._clippingPlaneSubject.next(value);\n }\n\n get budget(): CadModelSectorBudget {\n return this._budget;\n }\n\n set budget(b: CadModelSectorBudget) {\n this._budget = b;\n this._budgetSubject.next(b);\n }\n\n get lastBudgetSpendage(): SectorLoadingSpent {\n return this._lastSpent;\n }\n\n addModel(model: CadNode) {\n this._modelStateHandler.addModel(model.cadModelMetadata.modelIdentifier);\n this._modelSubject.next({ model, operation: 'add' });\n }\n\n removeModel(model: CadNode) {\n this._modelStateHandler.removeModel(model.cadModelMetadata.modelIdentifier);\n this._modelSubject.next({ model, operation: 'remove' });\n }\n\n updateLoadingHints(cadLoadingHints: CadLoadingHints): void {\n this._loadingHintsSubject.next(cadLoadingHints);\n }\n\n consumedSectorObservable(): Observable<ConsumedSector> {\n return this._updateObservable.pipe(share());\n }\n\n getLoadingStateObserver(): Observable<LoadingState> {\n return this._progressSubject;\n }\n\n /**\n * When loading hints of a CAD model changes, propagate the event down to the stream and either add or remove\n * the {@link CadModelMetadata} from the array and push the new array down stream\n */\n private loadingModelObservable() {\n return this._modelSubject.pipe(\n scan((array, next) => {\n const { model, operation } = next;\n switch (operation) {\n case 'add':\n array.push(model);\n return array;\n case 'remove':\n return array.filter(x => x.cadModelMetadata.modelIdentifier !== model.cadModelMetadata.modelIdentifier);\n default:\n assertNever(operation);\n }\n }, [] as CadNode[])\n );\n }\n}\n\ntype SettingsInput = {\n loadingHints: CadLoadingHints;\n budget: CadModelSectorBudget;\n};\ntype CameraInput = {\n camera: THREE.PerspectiveCamera;\n cameraInMotion: boolean;\n};\ntype ClippingInput = {\n clippingPlanes: THREE.Plane[] | never[];\n};\n\nfunction makeSettingsInput([loadingHints, budget]: [CadLoadingHints, CadModelSectorBudget]): SettingsInput {\n return { loadingHints, budget };\n}\nfunction makeCameraInput([camera, cameraInMotion]: [THREE.PerspectiveCamera, boolean]): CameraInput {\n return { camera, cameraInMotion };\n}\nfunction makeClippingInput([clippingPlanes]: [THREE.Plane[]]): ClippingInput {\n return { clippingPlanes };\n}\n\nfunction createDetermineSectorsInput([settings, camera, clipping, models]: [\n SettingsInput,\n CameraInput,\n ClippingInput,\n CadNode[]\n]): DetermineSectorsInput {\n return {\n ...camera,\n ...settings,\n ...clipping,\n cadModelsMetadata: models.filter(x => x.visible).map(x => x.cadModelMetadata)\n };\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { WebGLRendererStateHelper } from '@reveal/utilities';\nimport { SectorMetadata, CadModelMetadata, WantedSector, coverageShaders } from '@reveal/cad-parsers';\n\nimport { OccludingGeometryProvider } from './OccludingGeometryProvider';\n\ntype SectorContainer = {\n model: CadModelMetadata;\n sectors: SectorMetadata[];\n // Index is sectorId, value is sectorIndex\n sectorIndexById: number[];\n sectorIdOffset: number;\n lastSectorIdWithOffset: number;\n renderable: THREE.Object3D;\n attributesBuffer: THREE.InstancedInterleavedBuffer;\n attributesValues: Float32Array;\n mesh: THREE.Mesh;\n};\n\ntype SectorVisibility = {\n sectorIdWithOffset: number;\n weight: number;\n distance: number;\n};\n\nfunction nullSectorVisibility(): SectorVisibility {\n return {\n sectorIdWithOffset: -1,\n weight: -1,\n distance: Infinity\n };\n}\n\nconst identityRotation = new THREE.Quaternion();\n\n/**\n * Options for OrderSectorsByVisibleCoverage.\n */\nexport interface OrderSectorsByVisibleCoverageOptions {\n /**\n * Renderer used to render coverage.\n */\n renderer: THREE.WebGLRenderer;\n\n /**\n * Initializes a render target with already loaded geometry for pre-load\n * occlusion.\n */\n occludingGeometryProvider: OccludingGeometryProvider;\n}\n\nexport type PrioritizedSectorIdentifier = {\n /**\n * The CAD model that holds the sector.\n */\n model: CadModelMetadata;\n /**\n * Sector ID contained in the model provided.\n */\n sectorId: number;\n /**\n * A number between 0 and 1 indicating how 'important' the sector is.\n */\n priority: number;\n};\n\n/**\n * Interface for classes that estimates how visible a sector will be on screen.\n */\nexport interface OrderSectorsByVisibilityCoverage {\n /**\n * Dispose any resources that cannot be garbage collected.\n */\n dispose(): void;\n\n /**\n * Specifies what CAD models to estimate sector visibility for.\n * @param models Models to estimate sector visibility for.\n */\n setModels(models: CadModelMetadata[]): void;\n\n /**\n * Specify clipping planes.\n * @param planes A list of clip planes or null to disable clipping.\n */\n setClipping(planes: THREE.Plane[] | null): void;\n\n /**\n * Cull a set of sectors potentially being loaded towards already loaded geometry to determine if\n * the sector is visible or occluded.\n */\n cullOccludedSectors(camera: THREE.PerspectiveCamera, sectors: WantedSector[]): WantedSector[];\n\n /**\n * Estimates how visible the different sectors for the models added are and returns\n * a prioritized list.\n * @param camera The current viewpoint.\n */\n orderSectorsByVisibility(camera: THREE.Camera): PrioritizedSectorIdentifier[];\n}\n\n/**\n * Estimates sector visibility by rendering their bounds with a pattern confirming to how\n * much of the geometry covers of the bounding box.\n */\nexport class GpuOrderSectorsByVisibilityCoverage implements OrderSectorsByVisibilityCoverage {\n /**\n * Factor of how big render target we use for determining visibility of sectors\n * compared to the full render size.\n */\n private static readonly CoverageRenderTargetScalingFactor = 1.0 / 2.0;\n\n private sectorIdOffset = 0;\n private readonly scene = new THREE.Scene();\n private readonly _renderer: THREE.WebGLRenderer;\n private readonly _alreadyLoadedProvider: OccludingGeometryProvider;\n // private debugRenderer?: THREE.WebGLRenderer;\n private _debugImageElement?: HTMLImageElement;\n private readonly renderTarget: THREE.WebGLRenderTarget;\n private readonly containers: Map<string, SectorContainer> = new Map();\n private readonly buffers = {\n size: new THREE.Vector2(),\n rtBuffer: new Uint8Array(),\n sectorVisibilityBuffer: [] as SectorVisibility[]\n };\n\n private readonly coverageMaterial = new THREE.ShaderMaterial({\n vertexShader: coverageShaders.vertex,\n fragmentShader: coverageShaders.fragment,\n clipping: true,\n side: THREE.DoubleSide\n });\n\n constructor(options: OrderSectorsByVisibleCoverageOptions) {\n this._renderer = options.renderer;\n this._alreadyLoadedProvider = options.occludingGeometryProvider;\n\n // Note! Rener target will be resize before actual use\n this.renderTarget = new THREE.WebGLRenderTarget(1, 1, {\n generateMipmaps: false,\n type: THREE.UnsignedByteType,\n format: THREE.RGBAFormat,\n stencilBuffer: false\n });\n }\n\n dispose() {\n this._renderer.dispose();\n }\n\n get renderer(): THREE.WebGLRenderer {\n return this._renderer;\n }\n\n createDebugCanvas(options?: { width: number; height: number }): HTMLElement {\n if (this._debugImageElement) {\n throw new Error('createDebugCanvas() can only be called once');\n }\n const width = options ? options.width : this.renderTarget.width;\n const height = options ? options.height : this.renderTarget.height;\n this._debugImageElement = document.createElement('img');\n this._debugImageElement.style.width = `${width}px`;\n this._debugImageElement.style.height = `${height}px`;\n return this._debugImageElement;\n }\n\n setModels(models: CadModelMetadata[]) {\n const keepModelIdentifiers = new Set<string>();\n for (const model of models) {\n const modelIdentifier = model.modelIdentifier;\n keepModelIdentifiers.add(modelIdentifier);\n const container = this.containers.get(modelIdentifier);\n if (container) {\n this.updateModel(container, model);\n } else {\n this.addModel(model);\n }\n }\n\n const allIdentifiers = new Set<string>(this.containers.keys());\n const discardIdentifiers = new Set([...allIdentifiers].filter(x => !keepModelIdentifiers.has(x)));\n for (const modelIdentifier of discardIdentifiers) {\n this.removeModel(modelIdentifier);\n }\n }\n\n setClipping(planes: THREE.Plane[] | null) {\n this.coverageMaterial.clippingPlanes = planes;\n }\n\n cullOccludedSectors(camera: THREE.PerspectiveCamera, sectors: WantedSector[]): WantedSector[] {\n try {\n // Only render sectors we are interested in\n this.setAllSectorsVisible(false);\n this.setSectorsVisibility(sectors, true);\n\n const ordered = this.orderSectorsByVisibility(camera);\n const filtered = sectors.filter(toBeFiltered => {\n const container = this.containers.get(toBeFiltered.modelIdentifier);\n if (container === undefined) {\n throw new Error(`Model ${toBeFiltered.modelIdentifier} is not registered`);\n }\n const isCameraInsideSector = isWithinSectorBounds(container.model, toBeFiltered.metadata, camera.position);\n // Note! O(N), but N is number of input sectors (i.e. low)\n const found = ordered.some(\n x => x.model.modelIdentifier === toBeFiltered.modelIdentifier && x.sectorId === toBeFiltered.metadata.id\n );\n return found || isCameraInsideSector;\n });\n return filtered;\n } finally {\n this.setAllSectorsVisible(true);\n }\n }\n\n orderSectorsByVisibility(camera: THREE.PerspectiveCamera): PrioritizedSectorIdentifier[] {\n if (this._debugImageElement) {\n this.renderSectors(null, camera);\n this._debugImageElement.src = this._renderer.domElement.toDataURL();\n }\n\n this.ensureBuffersCorrectSize();\n this.renderSectors(this.renderTarget, camera);\n\n // Read back result from GPU\n this._renderer.readRenderTargetPixels(\n this.renderTarget,\n 0,\n 0,\n this.renderTarget.width,\n this.renderTarget.height,\n this.buffers.rtBuffer\n );\n\n // Unpack GPU result to sector IDs with visibility score\n const sectorVisibility = this.unpackSectorVisibility(\n this.renderTarget.width,\n this.renderTarget.height,\n this.buffers.rtBuffer\n );\n\n // Map to IDs that the world understands\n const totalWeight = sectorVisibility.reduce((weight, x) => x.weight + weight, 0);\n const result = sectorVisibility\n .filter(x => x.weight > 0)\n // Sort by \"hit\" to put most visible sectors first\n .sort((left, right) => {\n if (left && right) {\n return right.weight - left.weight;\n } else if (left) {\n return -1;\n } else if (right) {\n return 1;\n }\n return 0;\n })\n .map(x => {\n const container = this.findSectorContainer(x.sectorIdWithOffset);\n const sectorId = x.sectorIdWithOffset - container.sectorIdOffset;\n return {\n model: container.model,\n sectorId,\n priority: x.weight / totalWeight,\n depth: x.distance\n };\n });\n return result;\n }\n\n private readonly _ensureBuffersCorrectSizeVars = {\n size: new THREE.Vector2()\n };\n\n private ensureBuffersCorrectSize() {\n const { size } = this._ensureBuffersCorrectSizeVars;\n this._renderer.getSize(size);\n\n if (!this.buffers.size.equals(size)) {\n const rtWidth = Math.max(\n Math.floor(size.width * GpuOrderSectorsByVisibilityCoverage.CoverageRenderTargetScalingFactor),\n 64\n );\n const rtHeight = Math.max(\n Math.floor(size.height * GpuOrderSectorsByVisibilityCoverage.CoverageRenderTargetScalingFactor),\n 64\n );\n this.renderTarget.setSize(rtWidth, rtHeight);\n\n // Ensure buffer can hold all pixels from render target\n if (this.buffers.rtBuffer.length < 4 * rtWidth * rtHeight) {\n this.buffers.rtBuffer = new Uint8Array(4 * rtWidth * rtHeight);\n }\n\n this.buffers.size.copy(size);\n }\n }\n\n private renderSectors(renderTarget: THREE.WebGLRenderTarget | null, camera: THREE.PerspectiveCamera): void {\n const stateHelper = new WebGLRendererStateHelper(this._renderer);\n try {\n stateHelper.localClippingEnabled = true;\n stateHelper.setRenderTarget(renderTarget);\n stateHelper.setClearColor('#FFFFFF', 1.0);\n stateHelper.autoClear = false;\n stateHelper.setSize(this.buffers.size.width, this.buffers.size.height);\n\n // 1. Clear render target (depth + color)\n this._renderer.clear(true, true);\n\n // 2. Render already loaded geometry to offscreen buffer\n this._alreadyLoadedProvider.renderOccludingGeometry(renderTarget, camera);\n\n // 3. Render to offscreen buffer\n this._renderer.render(this.scene, camera);\n } finally {\n stateHelper.resetState();\n }\n }\n\n private setAllSectorsVisible(visible: boolean) {\n const visibilityValue = visible ? 1.0 : 0.0;\n this.containers.forEach(container => {\n for (let i = 0; i < container.sectors.length; ++i) {\n const id = container.sectors[i].id;\n const index = container.sectorIndexById[id];\n container.attributesValues[5 * index + 4] = visibilityValue;\n }\n container.attributesBuffer.needsUpdate = true;\n });\n }\n\n private setSectorsVisibility(sectors: WantedSector[], visible: boolean) {\n const visibilityValue = visible ? 1.0 : 0.0;\n sectors.forEach(s => {\n const id = s.metadata.id;\n const container = this.containers.get(s.modelIdentifier);\n if (container === undefined) {\n throw new Error(`Sector ${s} is from a model not added`);\n }\n const index = container.sectorIndexById[id];\n container.attributesValues[5 * index + 4] = visibilityValue;\n container.attributesBuffer.needsUpdate = true;\n });\n }\n\n private removeModel(modelIdentifier: string) {\n const container = this.containers.get(modelIdentifier);\n if (!container) {\n throw new Error(`Could not find model '${modelIdentifier}'`);\n }\n container.mesh.geometry.dispose();\n this.deleteSectorsFromBuffers(container.sectorIdOffset, container.lastSectorIdWithOffset);\n this.scene.remove(container.renderable);\n this.containers.delete(modelIdentifier);\n }\n\n private deleteSectorsFromBuffers(firstSectorId: number, lastSectorId: number) {\n const sectorVisibility = this.buffers.sectorVisibilityBuffer;\n for (let i = firstSectorId; i <= lastSectorId; ++i) {\n sectorVisibility[i] = nullSectorVisibility();\n }\n }\n\n private addModel(model: CadModelMetadata) {\n const sectors = model.scene.getAllSectors();\n const [mesh, attributesBuffer, attributesValues] = this.createSectorTreeGeometry(this.sectorIdOffset, sectors);\n\n const group = new THREE.Group();\n group.matrixAutoUpdate = false;\n group.applyMatrix4(model.modelMatrix);\n group.updateMatrixWorld();\n group.add(mesh);\n\n const maxSectorId = sectors.reduce((max, sector) => Math.max(sector.id, max), 0);\n const sectorIndexById = new Array<number>(maxSectorId);\n sectors.forEach((x, index) => (sectorIndexById[x.id] = index));\n this.containers.set(model.modelIdentifier, {\n model,\n sectors,\n sectorIndexById,\n sectorIdOffset: this.sectorIdOffset,\n lastSectorIdWithOffset: this.sectorIdOffset + maxSectorId,\n renderable: group,\n mesh,\n attributesBuffer,\n attributesValues\n });\n this.sectorIdOffset += maxSectorId + 1;\n this.scene.add(group);\n }\n\n private updateModel(container: SectorContainer, model: CadModelMetadata) {\n container.renderable.matrix.copy(model.modelMatrix);\n container.renderable.updateMatrixWorld(true);\n }\n\n private findSectorContainer(sectorIdWithOffset: number): SectorContainer {\n for (const container of this.containers.values()) {\n if (sectorIdWithOffset >= container.sectorIdOffset && sectorIdWithOffset <= container.lastSectorIdWithOffset) {\n return container;\n }\n }\n throw new Error(`Sector ID ${sectorIdWithOffset} is out of range`);\n }\n\n private unpackSectorVisibility(\n renderTargetWidth: number,\n renderTargetHeight: number,\n renderTargetBuffer: Uint8Array\n ): SectorVisibility[] {\n // Weight function that prioritizes pixels in the middle of the screen.\n // See https://www.wolframalpha.com/input/?i=plot+%282.5+-+%28x%5E2+%2B+y%5E2%29+%2B+2*e%5E%28-sqrt%28x%5E2+%2B+y%5E2%29%29%29%2F2%2C+x+in+%5B-1%2C+1%5D+y+in+%5B-1%2C+1%5D\n function weight(x: number, y: number): number {\n const s = x * x + y * y;\n return 0.5 * (2.5 - s) + Math.exp(-Math.sqrt(s));\n }\n\n const sectorVisibility = this.buffers.sectorVisibilityBuffer;\n resetVisibilityInformation(sectorVisibility);\n const halfHeight = renderTargetHeight / 2;\n const halfWidth = renderTargetWidth / 2;\n for (let y = 0; y < renderTargetHeight; y++) {\n const ry = (y - renderTargetHeight / 2) / halfHeight;\n for (let x = 0; x < renderTargetWidth; x++) {\n const i = x + renderTargetWidth * y;\n const r = renderTargetBuffer[4 * i + 0];\n const g = renderTargetBuffer[4 * i + 1];\n const b = renderTargetBuffer[4 * i + 2];\n const distance = renderTargetBuffer[4 * i + 3]; // Distance stored in alpha\n if (r !== 255 || g !== 255 || b !== 255) {\n const rx = (y - halfWidth) / halfWidth;\n\n const sectorIdWithOffset = b + g * 255 + r * 255 * 255;\n const value = sectorVisibility[sectorIdWithOffset] || { sectorIdWithOffset, weight: 0, distance };\n value.weight += weight(rx, ry);\n value.distance = Math.min(value.distance, distance);\n sectorVisibility[sectorIdWithOffset] = value;\n }\n }\n }\n return sectorVisibility;\n }\n\n private createSectorTreeGeometry(\n sectorIdOffset: number,\n sectors: SectorMetadata[]\n ): [THREE.Mesh, THREE.InstancedInterleavedBuffer, Float32Array] {\n const translation = new THREE.Vector3();\n const scale = new THREE.Vector3();\n\n const sectorCount = sectors.length;\n const instanceValues = new Float32Array(5 * sectorCount); // sectorId, coverageFactor[3], visibility\n const boxGeometry = new THREE.BoxBufferGeometry();\n const mesh = new THREE.InstancedMesh(boxGeometry, this.coverageMaterial, sectorCount);\n\n const addSector = (sectorBounds: THREE.Box3, sectorIndex: number, sectorId: number, coverage: THREE.Vector3) => {\n sectorBounds.getCenter(translation);\n sectorBounds.getSize(scale);\n\n const instanceMatrix = new THREE.Matrix4().compose(translation, identityRotation, scale);\n mesh.setMatrixAt(sectorIndex, instanceMatrix);\n instanceValues[5 * sectorIndex + 0] = sectorIdOffset + sectorId;\n instanceValues[5 * sectorIndex + 1] = coverage.x;\n instanceValues[5 * sectorIndex + 2] = coverage.y;\n instanceValues[5 * sectorIndex + 3] = coverage.z;\n instanceValues[5 * sectorIndex + 4] = 1.0; // visible\n };\n\n const coverageFactors = new THREE.Vector3(); // Allocate once only\n sectors.forEach((sector, sectorIndex) => {\n // Note! We always use the 'high detail' coverage factors, not recursiveCoverageFactors because we\n // don't know what detail level a sector will be loaded in. A better approach might be to choose this\n // runtime (either before rendering or in shader), but not sure how to solve this. -lars 2020-04-22\n const { xy, xz, yz } = sector.facesFile.coverageFactors;\n coverageFactors.set(yz, xz, xy);\n addSector(sector.bounds, sectorIndex, sector.id, coverageFactors);\n });\n\n const buffer = new THREE.InstancedInterleavedBuffer(instanceValues, 5);\n boxGeometry.setAttribute('a_sectorId', new THREE.InterleavedBufferAttribute(buffer, 1, 0));\n boxGeometry.setAttribute('a_coverageFactor', new THREE.InterleavedBufferAttribute(buffer, 3, 1));\n boxGeometry.setAttribute('a_visible', new THREE.InterleavedBufferAttribute(buffer, 1, 4));\n\n return [mesh, buffer, instanceValues];\n }\n}\n\nconst isCameraInsideSectorVars = {\n sectorBounds: new THREE.Box3()\n};\n\nfunction isWithinSectorBounds(model: CadModelMetadata, metadata: SectorMetadata, point: THREE.Vector3) {\n const { sectorBounds } = isCameraInsideSectorVars;\n sectorBounds.copy(metadata.bounds);\n sectorBounds.applyMatrix4(model.modelMatrix);\n return sectorBounds.containsPoint(point);\n}\n\nfunction resetVisibilityInformation(sectorVisibility: SectorVisibility[]) {\n // Blank visibility information\n for (let i = 0; i < sectorVisibility.length; i++) {\n const entry = sectorVisibility[i];\n if (entry) {\n entry.weight = 0;\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\nimport { SectorMetadata, CadModelMetadata, LevelOfDetail, WantedSector } from '@reveal/cad-parsers';\n\nimport { CadLoadingHints } from '../../CadLoadingHints';\nimport { CadModelSectorBudget } from '../../CadModelSectorBudget';\n\nexport interface DetermineSectorsInput {\n camera: THREE.PerspectiveCamera;\n clippingPlanes: THREE.Plane[];\n cadModelsMetadata: CadModelMetadata[];\n loadingHints: CadLoadingHints;\n cameraInMotion: boolean;\n budget: CadModelSectorBudget;\n}\n\n/**\n * Statistics for how much data is required to load set of sectors.\n */\nexport type SectorLoadingSpent = {\n /**\n * Estimated number of bytes to download sectors.\n */\n readonly downloadSize: number;\n /**\n * Estimated number of draw calls required to draw the sectors.\n */\n readonly drawCalls: number;\n /**\n * Estimated \"render cost\" which can be compared to triangle count (but\n * due to how Reveal renders primitives doesn't map directly to triangles).\n */\n readonly renderCost: number;\n\n /**\n * Total number of sectors to load.\n */\n readonly loadedSectorCount: number;\n /**\n * Number of 'simple' sectors to load.\n */\n readonly simpleSectorCount: number;\n /**\n * Number of 'detailed' sectors to load.\n */\n readonly detailedSectorCount: number;\n /**\n * How many sectors that was \"forced prioritized\".\n */\n readonly forcedDetailedSectorCount: number;\n /**\n * The total number of sectors in models we are loading.\n */\n readonly totalSectorCount: number;\n /**\n * How much of the prioritized nodes that are loaded (between 0 and 1).\n */\n readonly accumulatedPriority: number;\n};\n\nexport type SectorCost = {\n downloadSize: number;\n drawCalls: number;\n renderCost: number;\n};\n\nexport function addSectorCost(sum: SectorCost, cost: SectorCost) {\n sum.downloadSize += cost.downloadSize;\n sum.drawCalls += cost.drawCalls;\n sum.renderCost += cost.renderCost;\n}\n\nexport function reduceSectorCost(sum: SectorCost, cost: SectorCost) {\n sum.downloadSize -= cost.downloadSize;\n sum.drawCalls -= cost.drawCalls;\n sum.renderCost -= cost.renderCost;\n}\n\nexport type PrioritizedWantedSector = WantedSector & { priority: number };\n\n/**\n * Delegates that computes 'cost' of loading/visualizing a given sector.\n */\nexport type DetermineSectorCostDelegate = (sector: SectorMetadata, levelOfDetail: LevelOfDetail) => SectorCost;\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { SectorMetadata, LevelOfDetail } from '@reveal/cad-parsers';\nimport {\n PrioritizedWantedSector,\n DetermineSectorCostDelegate,\n SectorCost,\n reduceSectorCost,\n addSectorCost\n} from './types';\n\nimport { traverseDepthFirst } from '@reveal/utilities';\n\nimport log from '@reveal/logger';\n\nexport class TakenSectorTree {\n get totalCost(): SectorCost {\n return this._totalCost;\n }\n private readonly sectors: {\n sector: SectorMetadata;\n parentIndex: number;\n priority: number;\n cost: SectorCost;\n lod: LevelOfDetail;\n }[] = [];\n private readonly determineSectorCost: DetermineSectorCostDelegate;\n\n private _totalCost: SectorCost = { downloadSize: 0, drawCalls: 0, renderCost: 0 };\n\n constructor(sectorRoot: SectorMetadata, determineSectorCost: DetermineSectorCostDelegate) {\n this.determineSectorCost = determineSectorCost;\n // Allocate space for all sectors\n traverseDepthFirst(sectorRoot, x => {\n this.sectors.length = Math.max(this.sectors.length, x.id);\n this.sectors[x.id] = {\n sector: x,\n parentIndex: -1,\n priority: -1,\n cost: { downloadSize: 0, drawCalls: 0, renderCost: 0 },\n lod: LevelOfDetail.Discarded\n };\n return true;\n });\n // Assign parents\n for (let i = 0; i < this.sectors.length; ++i) {\n const sectorContainer = this.sectors[i];\n if (sectorContainer !== undefined) {\n const childrenIndexes = sectorContainer.sector.children.map(x => x.id);\n for (const childIndex of childrenIndexes) {\n this.sectors[childIndex].parentIndex = i;\n }\n }\n }\n\n // Default to load root\n if (sectorRoot.facesFile.fileName) {\n this.setSectorLod(sectorRoot.id, LevelOfDetail.Simple);\n }\n }\n\n determineWantedSectorCount(): number {\n return this.sectors.reduce((count, x) => {\n count = x.lod !== LevelOfDetail.Discarded ? count + 1 : count;\n return count;\n }, 0);\n }\n\n toWantedSectors(\n modelIdentifier: string,\n modelBaseUrl: string,\n geometryClipBox: THREE.Box3 | null\n ): PrioritizedWantedSector[] {\n return this.sectors\n .filter(x => x !== undefined)\n .map(sector => {\n const wanted: PrioritizedWantedSector = {\n modelIdentifier,\n modelBaseUrl,\n levelOfDetail: sector.lod,\n metadata: sector.sector,\n priority: sector.priority,\n geometryClipBox\n };\n return wanted;\n })\n .sort((l, r) => r.priority - l.priority);\n }\n\n markSectorDetailed(sectorId: number, priority: number) {\n this.setSectorPriority(sectorId, priority);\n if (this.sectors[sectorId].lod === LevelOfDetail.Detailed) {\n return;\n }\n let sectorContainer = this.sectors[sectorId];\n while (true) {\n switch (sectorContainer.lod) {\n case LevelOfDetail.Simple:\n this.replaceSimpleWithDetailed(sectorContainer.sector.id);\n break;\n case LevelOfDetail.Discarded:\n this.setSectorLod(sectorContainer.sector.id, LevelOfDetail.Detailed);\n break;\n default:\n // Already detailed\n }\n\n // More parents?\n if (sectorContainer.parentIndex === -1) break;\n sectorContainer = this.sectors[sectorContainer.parentIndex];\n }\n\n this.markAllDiscardedChildrenAsSimple(sectorId);\n }\n\n /**\n * Replaces a Simple sector by marking all its non-detailed children as Simple and\n * marking the sector itself Detailed.\n */\n private replaceSimpleWithDetailed(sectorId: number) {\n assert(\n this.sectors[sectorId].lod === LevelOfDetail.Simple,\n `Sector ${sectorId} must be a Simple-sector, but got ${this.sectors[sectorId].lod}`\n );\n this.setSectorLod(sectorId, LevelOfDetail.Detailed);\n this.markAllDiscardedChildrenAsSimple(sectorId);\n }\n\n private markAllDiscardedChildrenAsSimple(sectorId: number) {\n for (const child of this.sectors[sectorId].sector.children) {\n if (this.getSectorLod(child.id) === LevelOfDetail.Discarded) {\n // Note! When fileName is null the sector is so sparse that there is\n // no geometry in the F3D - we therefore skip such sectors.\n if (child.facesFile.fileName !== null) {\n this.setSectorLod(child.id, LevelOfDetail.Simple);\n }\n }\n }\n }\n\n private setSectorLod(sectorId: number, lod: LevelOfDetail) {\n assert(lod !== LevelOfDetail.Simple || this.sectors[sectorId].sector.facesFile.fileName !== null);\n this.sectors[sectorId].lod = lod;\n reduceSectorCost(this._totalCost, this.sectors[sectorId].cost);\n this.sectors[sectorId].cost = this.determineSectorCost(this.sectors[sectorId].sector, lod);\n addSectorCost(this._totalCost, this.sectors[sectorId].cost);\n }\n\n private setSectorPriority(sectorId: number, priority: number) {\n this.sectors[sectorId].priority = priority;\n }\n\n private getSectorLod(sectorId: number): LevelOfDetail {\n return this.sectors[sectorId].lod;\n }\n}\n\nfunction assert(condition: boolean, message: string = 'assertion hit') {\n if (!condition) {\n log.error('[ASSERT]', message);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n// Note! We introduce ThreeJS as a dependency here, but it's not exposed.\n// If we add other rendering engines, we should consider to implement this in 'pure'\n// WebGL.\nimport * as THREE from 'three';\n\nimport { SectorMetadata, CadModelMetadata, WantedSector, LevelOfDetail } from '@reveal/cad-parsers';\nimport { getBox3CornerPoints } from '@reveal/utilities';\n\nimport {\n GpuOrderSectorsByVisibilityCoverage,\n OrderSectorsByVisibilityCoverage\n} from './OrderSectorsByVisibilityCoverage';\nimport { SectorCuller } from './SectorCuller';\nimport { TakenSectorTree } from './TakenSectorTree';\nimport {\n PrioritizedWantedSector,\n DetermineSectorCostDelegate,\n DetermineSectorsInput,\n SectorCost,\n addSectorCost,\n SectorLoadingSpent\n} from './types';\n\nimport { CadModelSectorBudget } from '../../CadModelSectorBudget';\nimport { OccludingGeometryProvider } from './OccludingGeometryProvider';\n\n/**\n * Options for creating GpuBasedSectorCuller.\n */\nexport type ByVisibilityGpuSectorCullerOptions = {\n /**\n * Renderer used to determine what sector to load.\n */\n renderer: THREE.WebGLRenderer;\n\n /**\n * Optional callback for determining the cost of a sector. The default unit of the cost\n * function is bytes downloaded.\n */\n determineSectorCost?: DetermineSectorCostDelegate;\n\n /**\n * Use a custom coverage utility to determine how \"visible\" each sector is.\n */\n coverageUtil: OrderSectorsByVisibilityCoverage;\n\n /**\n * Logging function for debugging.\n */\n logCallback?: (message?: any, ...optionalParameters: any[]) => void;\n};\n\nfunction assert(condition: boolean, message: string = 'assertion hit') {\n console.assert(condition, message);\n}\n\nclass TakenSectorMap {\n private readonly _takenSectorTrees: Map<string, { sectorTree: TakenSectorTree; modelMetadata: CadModelMetadata }> =\n new Map();\n private readonly determineSectorCost: DetermineSectorCostDelegate;\n\n get totalCost(): SectorCost {\n const totalCost: SectorCost = { downloadSize: 0, drawCalls: 0, renderCost: 0 };\n this._takenSectorTrees.forEach(({ sectorTree }) => {\n addSectorCost(totalCost, sectorTree.totalCost);\n });\n return totalCost;\n }\n\n // TODO 2020-04-21 larsmoa: Unit test TakenSectorMap\n constructor(determineSectorCost: DetermineSectorCostDelegate) {\n this.determineSectorCost = determineSectorCost;\n }\n\n initializeScene(modelMetadata: CadModelMetadata) {\n this._takenSectorTrees.set(modelMetadata.modelIdentifier, {\n sectorTree: new TakenSectorTree(modelMetadata.scene.root, this.determineSectorCost),\n modelMetadata\n });\n }\n\n getWantedSectorCount(): number {\n let count = 0;\n this._takenSectorTrees.forEach(({ sectorTree }) => {\n count += sectorTree.determineWantedSectorCount();\n });\n return count;\n }\n\n markSectorDetailed(model: CadModelMetadata, sectorId: number, priority: number) {\n const entry = this._takenSectorTrees.get(model.modelIdentifier);\n assert(\n !!entry,\n `Could not find sector tree for ${model.modelIdentifier} (have trees ${Array.from(\n this._takenSectorTrees.keys()\n ).join(', ')})`\n );\n const { sectorTree } = entry!;\n sectorTree!.markSectorDetailed(sectorId, priority);\n }\n\n isWithinBudget(budget: CadModelSectorBudget): boolean {\n return (\n this.totalCost.downloadSize < budget.geometryDownloadSizeBytes &&\n this.totalCost.drawCalls < budget.maximumNumberOfDrawCalls &&\n this.totalCost.renderCost < budget.maximumRenderCost\n );\n }\n\n collectWantedSectors(): PrioritizedWantedSector[] {\n const allWanted = new Array<PrioritizedWantedSector>();\n\n // Collect sectors\n for (const [modelIdentifier, { sectorTree, modelMetadata }] of this._takenSectorTrees) {\n allWanted.push(\n ...sectorTree.toWantedSectors(modelIdentifier, modelMetadata.modelBaseUrl, modelMetadata.geometryClipBox)\n );\n }\n\n // Sort by priority\n allWanted.sort((l, r) => r.priority - l.priority);\n return allWanted;\n }\n\n clear() {\n this._takenSectorTrees.clear();\n }\n}\n\n/**\n * SectorCuller that uses the GPU to determine an approximation\n * of how \"visible\" each sector is to get a priority for each sector\n * and loads sectors based on priority within a budget.\n */\nexport class ByVisibilityGpuSectorCuller implements SectorCuller {\n private readonly options: Required<ByVisibilityGpuSectorCullerOptions>;\n private readonly takenSectors: TakenSectorMap;\n\n constructor(options: ByVisibilityGpuSectorCullerOptions) {\n this.options = {\n renderer: options.renderer,\n determineSectorCost: options && options.determineSectorCost ? options.determineSectorCost : computeSectorCost,\n logCallback:\n options && options.logCallback\n ? options.logCallback\n : // No logging\n () => {},\n coverageUtil: options.coverageUtil\n };\n this.takenSectors = new TakenSectorMap(this.options.determineSectorCost);\n }\n\n dispose() {\n this.options.coverageUtil.dispose();\n }\n\n determineSectors(input: DetermineSectorsInput): { wantedSectors: WantedSector[]; spentBudget: SectorLoadingSpent } {\n const takenSectors = this.update(input.camera, input.cadModelsMetadata, input.clippingPlanes, input.budget);\n const wanted = takenSectors.collectWantedSectors();\n const nonDiscarded = wanted.filter(x => x.levelOfDetail !== LevelOfDetail.Discarded);\n\n const totalSectorCount = input.cadModelsMetadata.reduce((sum, x) => sum + x.scene.sectorCount, 0);\n const takenSectorCount = nonDiscarded.length;\n const takenSimpleCount = nonDiscarded.filter(x => x.levelOfDetail === LevelOfDetail.Simple).length;\n const forcedDetailedSectorCount = nonDiscarded.filter(x => !Number.isFinite(x.priority)).length;\n const accumulatedPriority = nonDiscarded\n .filter(x => Number.isFinite(x.priority) && x.priority > 0)\n .reduce((sum, x) => sum + x.priority, 0);\n const takenDetailedPercent = ((100.0 * (takenSectorCount - takenSimpleCount)) / totalSectorCount).toPrecision(3);\n const takenPercent = ((100.0 * takenSectorCount) / totalSectorCount).toPrecision(3);\n\n this.log(\n `Scene: ${takenSectorCount} (${forcedDetailedSectorCount} required, ${totalSectorCount} sectors, ${takenPercent}% of all sectors - ${takenDetailedPercent}% detailed)`\n );\n const spentBudget: SectorLoadingSpent = {\n drawCalls: takenSectors.totalCost.drawCalls,\n downloadSize: takenSectors.totalCost.downloadSize,\n renderCost: takenSectors.totalCost.renderCost,\n totalSectorCount,\n forcedDetailedSectorCount,\n loadedSectorCount: takenSectorCount,\n simpleSectorCount: takenSimpleCount,\n detailedSectorCount: takenSectorCount - takenSimpleCount,\n accumulatedPriority\n };\n return { spentBudget, wantedSectors: wanted };\n }\n\n filterSectorsToLoad(input: DetermineSectorsInput, wantedSectors: WantedSector[]): Promise<WantedSector[]> {\n const filtered = this.options.coverageUtil.cullOccludedSectors(input.camera, wantedSectors);\n return Promise.resolve(filtered);\n }\n\n private update(\n camera: THREE.PerspectiveCamera,\n models: CadModelMetadata[],\n clippingPlanes: THREE.Plane[] | null,\n budget: CadModelSectorBudget\n ): TakenSectorMap {\n const { coverageUtil } = this.options;\n const takenSectors = this.takenSectors;\n takenSectors.clear();\n models.forEach(x => takenSectors.initializeScene(x));\n\n // Update wanted sectors\n coverageUtil.setModels(models);\n coverageUtil.setClipping(clippingPlanes);\n const prioritized = coverageUtil.orderSectorsByVisibility(camera);\n\n // Add high details for all sectors the camera is inside or near\n this.addHighDetailsForNearSectors(camera, models, budget, takenSectors, clippingPlanes);\n\n let debugAccumulatedPriority = 0.0;\n const prioritizedLength = prioritized.length;\n\n let i = 0;\n for (i = 0; i < prioritizedLength && takenSectors.isWithinBudget(budget); i++) {\n const x = prioritized[i];\n takenSectors.markSectorDetailed(x.model, x.sectorId, x.priority);\n debugAccumulatedPriority += x.priority;\n }\n\n this.log(`Retrieving ${i} of ${prioritizedLength} (last: ${prioritized.length > 0 ? prioritized[i - 1] : null})`);\n this.log(\n `Total scheduled: ${takenSectors.getWantedSectorCount()} of ${prioritizedLength} (cost: ${\n takenSectors.totalCost.downloadSize / 1024 / 1024\n }/${budget.geometryDownloadSizeBytes / 1024 / 1024}, drawCalls: ${takenSectors.totalCost.drawCalls}/${\n budget.maximumNumberOfDrawCalls\n }, priority: ${debugAccumulatedPriority})`\n );\n\n return takenSectors;\n }\n\n private addHighDetailsForNearSectors(\n camera: THREE.PerspectiveCamera,\n models: CadModelMetadata[],\n budget: CadModelSectorBudget,\n takenSectors: TakenSectorMap,\n clippingPlanes: THREE.Plane[] | null\n ) {\n const shortRangeCamera = camera.clone(true) as THREE.PerspectiveCamera;\n shortRangeCamera.far = budget.highDetailProximityThreshold;\n shortRangeCamera.updateProjectionMatrix();\n const cameraMatrixWorldInverse = shortRangeCamera.matrixWorldInverse;\n const cameraProjectionMatrix = shortRangeCamera.projectionMatrix;\n\n const transformedCameraMatrixWorldInverse = new THREE.Matrix4();\n models.forEach(model => {\n // Apply model transformation to camera matrix\n transformedCameraMatrixWorldInverse.multiplyMatrices(cameraMatrixWorldInverse, model.modelMatrix);\n\n let intersectingSectors = model.scene.getSectorsIntersectingFrustum(\n cameraProjectionMatrix,\n transformedCameraMatrixWorldInverse\n );\n\n if (clippingPlanes != null && clippingPlanes.length > 0) {\n intersectingSectors = this.testForClippingOcclusion(intersectingSectors, clippingPlanes, model.modelMatrix);\n }\n\n this.markSectorsAsDetailed(intersectingSectors, takenSectors, model);\n });\n }\n\n private testForClippingOcclusion(\n intersectingSectors: SectorMetadata[],\n clippingPlanes: THREE.Plane[],\n modelMatrix: THREE.Matrix4\n ): SectorMetadata[] {\n const passingSectors = [];\n\n for (let i = 0; i < intersectingSectors.length; i++) {\n const boundPoints = getBox3CornerPoints(intersectingSectors[i].bounds).map(p => {\n const outvec = p.clone();\n outvec.applyMatrix4(modelMatrix);\n return outvec;\n });\n\n let shouldKeep = true;\n for (let k = 0; k < clippingPlanes.length; k++) {\n let planeAccepts = false;\n\n for (let j = 0; j < boundPoints.length; j++) {\n planeAccepts = clippingPlanes[k].distanceToPoint(boundPoints[j]) >= 0 || planeAccepts;\n }\n\n shouldKeep = shouldKeep && planeAccepts;\n }\n\n if (shouldKeep) {\n passingSectors.push(intersectingSectors[i]);\n }\n }\n return passingSectors;\n }\n\n private markSectorsAsDetailed(\n intersectingSectors: SectorMetadata[],\n takenSectors: TakenSectorMap,\n model: CadModelMetadata\n ) {\n for (let i = 0; i < intersectingSectors.length; i++) {\n takenSectors.markSectorDetailed(model, intersectingSectors[i].id, Infinity);\n }\n }\n\n private log(message?: any, ...optionalParameters: any[]) {\n this.options.logCallback(message, ...optionalParameters);\n }\n}\n\nfunction computeSectorCost(metadata: SectorMetadata, lod: LevelOfDetail): SectorCost {\n switch (lod) {\n case LevelOfDetail.Detailed:\n return {\n downloadSize: metadata.indexFile.downloadSize,\n drawCalls: metadata.estimatedDrawCallCount,\n renderCost: metadata.estimatedRenderCost\n };\n case LevelOfDetail.Simple:\n return {\n downloadSize: metadata.facesFile.downloadSize,\n drawCalls: 1,\n // TODO 2021-09-23 larsmoa: Estimate for simple sector render cost is very arbitrary\n renderCost: Math.ceil(metadata.facesFile.downloadSize / 100)\n };\n default:\n throw new Error(`Can't compute cost for lod ${lod}`);\n }\n}\n\nexport function createDefaultSectorCuller(\n renderer: THREE.WebGLRenderer,\n occludingGeometryProvider: OccludingGeometryProvider\n): SectorCuller {\n const coverageUtil = new GpuOrderSectorsByVisibilityCoverage({ renderer, occludingGeometryProvider });\n return new ByVisibilityGpuSectorCuller({ renderer, coverageUtil });\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n// This file is in place for future-proofing. We can change the implementation here if\n// we want to use something else than loglevel.\n\nimport * as log from 'loglevel';\nexport default log;\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport log from './src/Log';\nexport default log;\n","module.exports = require(\"mixpanel-browser\");","module.exports = require(\"@tweenjs/tween.js\");","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nconst worldToViewportVars = {\n renderSize: new THREE.Vector2(),\n position: new THREE.Vector3()\n};\n\n/**\n * Maps from 3D world coordinates to normalized screen coordinates\n * relative to the canvas being rendered to. X and Y will\n * be in range [0, 1]. Z is in range [-1, 1] if the coordinate\n * is inside the camera near and far planes.\n * @param renderer Renderer used to render the \"world\"\n * @param camera Camera used to project point from 3D to NDC coordinates\n * @param position3D World position in 3D\n * @param out Optionally pre-allocated THREE.Vector3\n * @returns Relative screen coordinates in X, Y and Z in range [-1, 1] if point\n * is within near/far of camera.\n */\nexport function worldToNormalizedViewportCoordinates(\n renderer: THREE.WebGLRenderer,\n camera: THREE.PerspectiveCamera,\n position3D: THREE.Vector3,\n out: THREE.Vector3 = new THREE.Vector3()\n): THREE.Vector3 {\n const { renderSize, position } = worldToViewportVars;\n const canvas = renderer.domElement;\n const pixelRatio = 1; // renderer.getPixelRatio();\n renderer.getSize(renderSize);\n\n // map to normalized device coordinate (NDC) space\n position.copy(position3D);\n position.project(camera);\n\n // Compute 'virtual' canvas size\n const { width: canvasWidth, height: canvasHeight } = canvas.getBoundingClientRect();\n const scaleX = renderSize.width / canvasWidth;\n const scaleY = renderSize.height / canvasHeight;\n\n // map to 2D screen space\n const x = (position.x + 1) / (scaleX * pixelRatio * 2);\n const y = (-position.y + 1) / (scaleY * pixelRatio * 2);\n\n return out.set(x, y, position.z);\n}\n\n/**\n * Maps from 3D world coordinates to screen coordinates\n * relative to the canvas. X and Y will be in absolute\n * coordinates (0,0 being the top left of the canvas). Z is\n * in range [-1, 1] if the coordinate\n * is inside the camera near and far planes.\n * @param renderer Renderer used to render the \"world\"\n * @param camera Camera used to project point from 3D to NDC coordinates\n * @param position3D World position in 3D\n * @param out Optionally pre-allocated THREE.Vector3\n * @returns Relative screen coordinates in X, Y and Z in range [-1, 1] if point\n * is within near/far of camera.\n */\nexport function worldToViewportCoordinates(\n renderer: THREE.WebGLRenderer,\n camera: THREE.PerspectiveCamera,\n position3D: THREE.Vector3,\n out: THREE.Vector3 = new THREE.Vector3()\n): THREE.Vector3 {\n worldToNormalizedViewportCoordinates(renderer, camera, position3D, out);\n\n const { renderSize } = worldToViewportVars;\n renderer.getSize(renderSize);\n const pixelRatio = renderer.getPixelRatio();\n\n out.x = Math.round((out.x * renderSize.width) / pixelRatio);\n out.y = Math.round((out.y * renderSize.height) / pixelRatio);\n return out;\n}\n","module.exports = require(\"lodash/cloneDeep\");","module.exports = require(\"geo-three\");","export default \"#define GLSLIFY 1\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_0 || renderMode == RenderTypeEffects_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_0) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_0) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_0) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_0) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_1) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_1) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_1));\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_normal;\\nvarying vec3 v_color;\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform int renderMode;\\n\\nvarying vec3 vViewPosition;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n if (isSliced(vViewPosition)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n vec3 normal = normalize(v_normal);\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, gl_FragCoord.z, matCapTexture, GeometryType.Primitive);\\n}\\n\";","export default \"#define GLSLIFY 1\\n// Not using the w-component to support using vec3 and vec4 as input\\nmat4 constructMatrix(vec4 column_0, vec4 column_1, vec4 column_2, vec4 column_3) {\\n return mat4(\\n vec4(column_0.xyz, 0.0),\\n vec4(column_1.xyz, 0.0),\\n vec4(column_2.xyz, 0.0),\\n vec4(column_3.xyz, 1.0)\\n );\\n}\\n\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\n\\nattribute vec4 a_instanceMatrix_column_0;\\nattribute vec4 a_instanceMatrix_column_1;\\nattribute vec4 a_instanceMatrix_column_2;\\nattribute vec4 a_instanceMatrix_column_3;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_color;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_normal;\\nvarying vec3 v_color;\\n\\nvarying vec3 vViewPosition;\\n\\nuniform vec2 treeIndexTextureSize;\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize;\\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main()\\n{\\n mat4 instanceMatrix = constructMatrix(\\n a_instanceMatrix_column_0,\\n a_instanceMatrix_column_1,\\n a_instanceMatrix_column_2,\\n a_instanceMatrix_column_3\\n );\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n v_treeIndex = a_treeIndex;\\n v_color = a_color;\\n v_normal = normalMatrix * normalize(inverseModelMatrix * treeIndexWorldTransform * modelMatrix * instanceMatrix * vec4(normalize(normal), 0.0)).xyz;\\n //v_normal = normal;\\n\\n vec3 transformed = (instanceMatrix * vec4(position, 1.0)).xyz;\\n vec4 modelViewPosition = viewMatrix * treeIndexWorldTransform * modelMatrix * vec4(transformed, 1.0);\\n vViewPosition = modelViewPosition.xyz;\\n gl_Position = projectionMatrix * modelViewPosition;\\n}\";","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nexport class BoundingBoxClipper {\n private readonly _box: THREE.Box3;\n private readonly _clippingPlanes: THREE.Plane[] = [\n new THREE.Plane(),\n new THREE.Plane(),\n new THREE.Plane(),\n new THREE.Plane(),\n new THREE.Plane(),\n new THREE.Plane()\n ];\n\n constructor(box?: THREE.Box3) {\n this._box = box || new THREE.Box3();\n this.updatePlanes();\n }\n\n set minX(x: number) {\n this._box.min.x = x;\n this.updatePlanes();\n }\n\n get minX() {\n return this._box.min.x;\n }\n\n set minY(y: number) {\n this._box.min.y = y;\n this.updatePlanes();\n }\n\n get minY() {\n return this._box.min.y;\n }\n\n set minZ(z: number) {\n this._box.min.z = z;\n this.updatePlanes();\n }\n\n get minZ() {\n return this._box.min.z;\n }\n\n set maxX(x: number) {\n this._box.max.x = x;\n this.updatePlanes();\n }\n\n get maxX() {\n return this._box.max.x;\n }\n\n set maxY(y: number) {\n this._box.max.y = y;\n this.updatePlanes();\n }\n\n get maxY() {\n return this._box.max.y;\n }\n\n set maxZ(z: number) {\n this._box.max.z = z;\n this.updatePlanes();\n }\n\n get maxZ() {\n return this._box.max.z;\n }\n\n private updatePlanes() {\n this._clippingPlanes[0].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(1, 0, 0),\n new THREE.Vector3(this.minX, 0, 0)\n );\n this._clippingPlanes[1].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(-1, 0, 0),\n new THREE.Vector3(this.maxX, 0, 0)\n );\n this._clippingPlanes[2].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(0, 1, 0),\n new THREE.Vector3(0, this.minY, 0)\n );\n this._clippingPlanes[3].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(0, -1, 0),\n new THREE.Vector3(0, this.maxY, 0)\n );\n this._clippingPlanes[4].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(0, 0, 1),\n new THREE.Vector3(0, 0, this.minZ)\n );\n this._clippingPlanes[5].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(0, 0, -1),\n new THREE.Vector3(0, 0, this.maxZ)\n );\n }\n\n get clippingPlanes() {\n return this._clippingPlanes;\n }\n}\n","export default \"#define GLSLIFY 1\\nvarying vec2 vUv;\\n\\nvoid main() {\\n vUv = uv;\\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\\n}\\n\";","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport { worldToViewportCoordinates, worldToNormalizedViewportCoordinates } from './worldToViewport';\nexport { BoundingBoxClipper } from './BoundingBoxClipper';\n\nexport { assertNever, EventTrigger } from '@reveal/utilities';\n\nexport { LoadingState } from '@reveal/cad-geometry-loaders';\n\nexport { LocalModelIdentifier, CdfModelIdentifier } from '@reveal/modeldata-api';\n","module.exports = require(\"comlink\");","module.exports = require(\"loglevel\");","module.exports = require(\"lodash/throttle\");","module.exports = require(\"lodash/chunk\");","export default \"#define GLSLIFY 1\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_1 || renderMode == RenderTypeEffects_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_1) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_1) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_1) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_1) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_0) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_0) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_0));\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform int renderMode;\\n\\nvarying vec3 vViewPosition;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n if (isSliced(vViewPosition)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n updateFragmentColor(renderMode, color, v_treeIndex, v_normal, gl_FragCoord.z, matCapTexture, GeometryType.Quad);\\n}\\n\";","export default \"#define GLSLIFY 1\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\n\\nattribute vec3 color;\\nattribute float treeIndex;\\nattribute vec4 matrix0;\\nattribute vec4 matrix1;\\nattribute vec4 matrix2;\\nattribute vec4 matrix3;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nvarying vec3 vViewPosition;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n \\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n v_treeIndex = treeIndex;\\n v_color = color;\\n v_normal = normalize(normalMatrix * (inverseModelMatrix * treeIndexWorldTransform * modelMatrix * vec4(normalize(normal), 0.0)).xyz);\\n mat4 instanceMatrix = mat4(matrix0, matrix1, matrix2, matrix3);\\n vec3 transformed = (instanceMatrix * vec4(position, 1.0)).xyz;\\n vec4 mvPosition = viewMatrix * treeIndexWorldTransform * modelMatrix * vec4( transformed, 1.0 );\\n vViewPosition = mvPosition.xyz;\\n gl_Position = projectionMatrix * mvPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 derivateNormal(vec3 v_viewPosition) {\\n vec3 fdx = vec3(dFdx(v_viewPosition.x), dFdx(v_viewPosition.y), dFdx(v_viewPosition.z));\\n vec3 fdy = vec3(dFdy(v_viewPosition.x), dFdy(v_viewPosition.y), dFdy(v_viewPosition.z));\\n vec3 normal = normalize(cross(fdx, fdy));\\n return normal;\\n}\\n\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_1 || renderMode == RenderTypeEffects_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_1) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_1) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_1) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_1) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_0) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_0) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_0));\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_viewPosition;\\n\\nuniform int renderMode;\\n\\nvoid main()\\n{\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n if (isSliced(v_viewPosition)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n vec3 normal = derivateNormal(v_viewPosition);\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, gl_FragCoord.z, matCapTexture, GeometryType.TriangleMesh);\\n}\\n\";","export default \"#define GLSLIFY 1\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nattribute vec3 color;\\nattribute float treeIndex; \\n\\nvarying vec3 v_color;\\nvarying float v_treeIndex;\\nvarying vec3 v_viewPosition;\\n\\nuniform vec2 treeIndexTextureSize;\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize;\\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n v_color = color;\\n v_treeIndex = treeIndex;\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n vec4 modelViewPosition = viewMatrix * treeIndexWorldTransform * modelMatrix * vec4(position, 1.0);\\n v_viewPosition = modelViewPosition.xyz;\\n gl_Position = projectionMatrix * modelViewPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 derivateNormal(vec3 v_viewPosition) {\\n vec3 fdx = vec3(dFdx(v_viewPosition.x), dFdx(v_viewPosition.y), dFdx(v_viewPosition.z));\\n vec3 fdy = vec3(dFdy(v_viewPosition.x), dFdy(v_viewPosition.y), dFdy(v_viewPosition.z));\\n vec3 normal = normalize(cross(fdx, fdy));\\n return normal;\\n}\\n\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_1 || renderMode == RenderTypeEffects_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_1) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_1) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_1) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_1) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_0) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_0) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_0));\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_viewPosition;\\n\\nuniform int renderMode;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n if (isSliced(v_viewPosition)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n vec3 normal = derivateNormal(v_viewPosition);\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, gl_FragCoord.z, matCapTexture, GeometryType.InstancedMesh);\\n}\\n\";","export default \"#define GLSLIFY 1\\n// Not using the w-component to support using vec3 and vec4 as input\\nmat4 constructMatrix(vec4 column_0, vec4 column_1, vec4 column_2, vec4 column_3) {\\n return mat4(\\n vec4(column_0.xyz, 0.0),\\n vec4(column_1.xyz, 0.0),\\n vec4(column_2.xyz, 0.0),\\n vec4(column_3.xyz, 1.0)\\n );\\n}\\n\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nattribute vec4 a_instanceMatrix_column_0;\\nattribute vec4 a_instanceMatrix_column_1;\\nattribute vec4 a_instanceMatrix_column_2;\\nattribute vec4 a_instanceMatrix_column_3;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_color;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_viewPosition;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main()\\n{\\n mat4 instanceMatrix = constructMatrix(\\n a_instanceMatrix_column_0,\\n a_instanceMatrix_column_1,\\n a_instanceMatrix_column_2,\\n a_instanceMatrix_column_3\\n );\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n v_color = a_color;\\n\\n vec3 transformed = (instanceMatrix * vec4(position, 1.0)).xyz;\\n vec4 modelViewPosition = viewMatrix * modelMatrix * vec4(transformed, 1.0);\\n v_viewPosition = modelViewPosition.xyz;\\n v_treeIndex = a_treeIndex;\\n gl_Position = projectionMatrix * modelViewPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_1 || renderMode == RenderTypeEffects_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_1) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_1) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_1) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_1) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_0) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_0) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_0));\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nvarying float v_treeIndex;\\nvarying vec2 v_xy;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform int renderMode;\\n\\nvarying vec3 vViewPosition;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n if (isSliced(vViewPosition)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n float dist = dot(v_xy, v_xy);\\n vec3 normal = normalize( v_normal );\\n if (dist > 0.25)\\n discard;\\n\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, gl_FragCoord.z, matCapTexture, GeometryType.Primitive);\\n}\\n\";","export default \"#define GLSLIFY 1\\n// Not using the w-component to support using vec3 and vec4 as input\\nmat4 constructMatrix(vec4 column_0, vec4 column_1, vec4 column_2, vec4 column_3) {\\n return mat4(\\n vec4(column_0.xyz, 0.0),\\n vec4(column_1.xyz, 0.0),\\n vec4(column_2.xyz, 0.0),\\n vec4(column_3.xyz, 1.0)\\n );\\n}\\n\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\n\\nattribute vec4 a_instanceMatrix_column_0;\\nattribute vec4 a_instanceMatrix_column_1;\\nattribute vec4 a_instanceMatrix_column_2;\\nattribute vec4 a_instanceMatrix_column_3;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_color;\\nattribute vec3 a_normal;\\n\\nvarying vec2 v_xy;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\nvarying float v_treeIndex;\\n\\nvarying vec3 vViewPosition;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n v_xy = vec2(position.x, position.y);\\n v_treeIndex = a_treeIndex;\\n\\n mat4 instanceMatrix = constructMatrix(\\n a_instanceMatrix_column_0,\\n a_instanceMatrix_column_1,\\n a_instanceMatrix_column_2,\\n a_instanceMatrix_column_3\\n );\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n vec3 transformed = (instanceMatrix * vec4(position, 1.0)).xyz;\\n vec4 mvPosition = viewMatrix * treeIndexWorldTransform * modelMatrix * vec4( transformed, 1.0 );\\n v_color = a_color;\\n\\n v_normal = normalMatrix * normalize(inverseModelMatrix * treeIndexWorldTransform * modelMatrix * vec4(normalize(a_normal), 0.0)).xyz;\\n vViewPosition = mvPosition.xyz;\\n gl_Position = projectionMatrix * mvPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 mul3(mat4 M, vec3 v) {\\n vec4 u = M * vec4(v, 1.0);\\n return u.xyz / u.w;\\n}\\n\\nfloat displaceScalar(vec3 point, float scalar, \\n float treeIndex, vec3 cameraPosition, mat4 inverseModelMatrix) {\\n\\n // Displaces a scalar based on distance to camera to avoid z-fighting\\n vec3 cameraPositionModelSpace = (inverseModelMatrix * vec4(cameraPosition, 1.0)).xyz;\\n vec3 pointToCamera = cameraPositionModelSpace - point;\\n\\n // \\\"Random\\\" number in the range [0, 1], based on treeIndex\\n float rnd = mod(treeIndex, 64.) / 64.;\\n // Compute distance to camera, but cap it\\n float maxDistanceToCamera = 50.;\\n float distanceToCamera = min(length(pointToCamera), maxDistanceToCamera);\\n\\n float maxDisplacement = 0.01;\\n float scaleFactor = 0.01;\\n float displacement = min(maxDisplacement, scaleFactor * rnd * distanceToCamera / maxDistanceToCamera);\\n return scalar + displacement;\\n}\\n\\nfloat computeFragmentDepth(vec3 p, mat4 projectionMatrix) {\\n // Anders Hafreager comments:\\n // Depth value can be calculated by transforming the z-component of the intersection point to projection space.\\n // The w-component is also needed to scale projection space into clip space.\\n // However, the 4th column of the projection matrix is (0, 0, const, 0), so we can exploit this when computing w-value.\\n float projected_intersection_z=projectionMatrix[0][2]*p.x+projectionMatrix[1][2]*p.y+projectionMatrix[2][2]*p.z+projectionMatrix[3][2];\\n\\n // If we want to use orthographic camera, the full w-component is found as\\n float projected_intersection_w=projectionMatrix[0][3]*p.x+projectionMatrix[1][3]*p.y+projectionMatrix[2][3]*p.z+projectionMatrix[3][3];\\n // float projected_intersection_w = projectionMatrix[2][3]*newPoint.z; // Optimized for perspective camera\\n return ((gl_DepthRange.diff * (projected_intersection_z / projected_intersection_w)) + gl_DepthRange.near + gl_DepthRange.far) * .5;\\n}\\n\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth) \\n\\nfloat updateFragmentDepth(vec3 p,mat4 projectionMatrix) {\\n gl_FragDepthEXT = computeFragmentDepth(p, projectionMatrix);\\n return gl_FragDepthEXT;\\n}\\n\\n#else\\n\\nfloat updateFragmentDepth(vec3 p, mat4 projectionMatrix){\\n // Extension not available - not much we can do.\\n return computeFragmentDepth(p, projectionMatrix);\\n}\\n\\n#endif\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_1) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_1) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_1));\\n}\\n\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_0 || renderMode == RenderTypeEffects_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_0) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_0) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_0) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_0) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\n#define PI 3.14159265359\\n#define PI2 6.28318530718\\n#define PI_HALF 1.5707963267949\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform mat4 projectionMatrix;\\n\\nvarying vec4 v_centerB;\\n\\nvarying vec4 v_W;\\nvarying vec4 v_U;\\n\\nvarying float v_angle;\\nvarying float v_arcAngle;\\n\\nvarying vec4 v_centerA;\\nvarying vec4 v_V;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform int renderMode;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n vec3 normal = normalize( v_normal );\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n\\n float R1 = v_centerB.w;\\n vec4 U = v_U;\\n vec4 W = v_W;\\n vec4 V = v_V;\\n float height = length(v_centerA.xyz - v_centerB.xyz);\\n float R2 = v_centerA.w;\\n float dR = R2 - R1;\\n\\n mat3 basis = mat3(U.xyz, V.xyz, W.xyz);\\n vec3 surfacePoint = vec3(U.w, V.w, W.w);\\n vec3 rayTarget = surfacePoint;\\n\\n #if defined(COGNITE_ORTHOGRAPHIC_CAMERA)\\n vec3 rayDirection = vec3(0.0, 0.0, -1.0);\\n #else\\n vec3 rayDirection = normalize(rayTarget); // rayOrigin is (0,0,0) in camera space\\n #endif\\n\\n vec3 diff = rayTarget - v_centerB.xyz;\\n vec3 E = diff * basis;\\n vec3 D = rayDirection * basis;\\n\\n float a = dot(D.xy, D.xy);\\n float b = dot(E.xy, D.xy);\\n float c = dot(E.xy, E.xy) - R1*R1;\\n\\n if (R1 != R2) {\\n // Additional terms if radii are different\\n float dRLInv = dR / height;\\n float dRdRL2Inv = dRLInv * dRLInv;\\n a -= D.z * D.z * dRdRL2Inv;\\n b -= dRLInv * (E.z * D.z * dRLInv + R1 * D.z);\\n c -= dRLInv * (E.z * E.z * dRLInv + 2.0 * R1 * E.z);\\n }\\n\\n // Calculate a dicriminant of the above quadratic equation\\n float d = b*b - a*c;\\n\\n // d < 0.0 means the ray hits outside an infinitely long cone\\n if (d < 0.0) {\\n discard;\\n }\\n\\n float sqrtd = sqrt(d);\\n float dist1 = (-b - sqrtd)/a;\\n float dist2 = (-b + sqrtd)/a;\\n\\n // Make sure dist1 is the smaller one\\n if (dist2 < dist1) {\\n float tmp = dist1;\\n dist1 = dist2;\\n dist2 = tmp;\\n }\\n\\n float dist = dist1;\\n vec3 intersectionPoint = E + dist * D;\\n float theta = atan(intersectionPoint.y, intersectionPoint.x);\\n if (theta < v_angle) theta += 2.0 * PI;\\n\\n // Intersection point in camera space\\n vec3 p = rayTarget + dist*rayDirection;\\n\\n bool isInner = false;\\n\\n if (intersectionPoint.z <= 0.0 ||\\n intersectionPoint.z > height ||\\n theta > v_angle + v_arcAngle ||\\n isSliced(p)\\n ) {\\n // Missed the first point, check the other point\\n isInner = true;\\n dist = dist2;\\n intersectionPoint = E + dist * D;\\n theta = atan(intersectionPoint.y, intersectionPoint.x);\\n p = rayTarget + dist*rayDirection;\\n if (theta < v_angle) theta += 2.0 * PI;\\n if (intersectionPoint.z <= 0.0 ||\\n intersectionPoint.z > height ||\\n theta > v_angle + v_arcAngle ||\\n isSliced(p)\\n ) {\\n // Missed the other point too\\n discard;\\n }\\n }\\n\\n #if !defined(COGNITE_RENDER_COLOR_ID) && !defined(COGNITE_RENDER_DEPTH)\\n if (R1 != R2)\\n {\\n // Find normal vector\\n vec3 n = -normalize(W.xyz);\\n vec3 P1 = v_centerB.xyz;\\n vec3 P2 = v_centerA.xyz;\\n vec3 A = cross(P1 - p, P2 - p);\\n\\n vec3 t = normalize(cross(n, A));\\n vec3 o1 = P1 + R1 * t;\\n vec3 o2 = P2 + R2 * t;\\n vec3 B = o2-o1;\\n normal = normalize(cross(A, B));\\n }\\n else\\n {\\n // Regular cylinder has simpler normal vector in camera space\\n vec3 p_local = p - v_centerB.xyz;\\n normal = normalize(p_local - W.xyz * dot(p_local, W.xyz));\\n }\\n #endif\\n\\n float fragDepth = updateFragmentDepth(p, projectionMatrix);\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, fragDepth, matCapTexture, GeometryType.Primitive);\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 mul3(mat4 M, vec3 v) {\\n vec4 u = M * vec4(v, 1.0);\\n return u.xyz / u.w;\\n}\\n\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_centerA;\\nattribute vec3 a_centerB;\\nattribute float a_radiusA;\\nattribute float a_radiusB;\\nattribute vec3 a_color;\\n// segment attributes\\nattribute vec3 a_localXAxis;\\nattribute float a_angle;\\nattribute float a_arcAngle;\\n\\nvarying float v_treeIndex;\\n// We pack the radii into w-components\\nvarying vec4 v_centerB;\\n\\n// U, V, axis represent the 3x3 cone basis.\\n// They are vec4 to pack extra data into the w-component\\n// since Safari on iOS only supports 8 varying vec4 registers.\\nvarying vec4 v_U;\\nvarying vec4 v_W;\\n\\nvarying vec4 v_centerA;\\nvarying vec4 v_V;\\n\\nvarying float v_angle;\\nvarying float v_arcAngle;\\n\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n mat4 modelTransformOffset = inverseModelMatrix * treeIndexWorldTransform * modelMatrix;\\n\\n vec3 centerA = mul3(modelTransformOffset, a_centerA);\\n vec3 centerB = mul3(modelTransformOffset, a_centerB);\\n\\n vec3 center = 0.5 * (centerA + centerB);\\n float halfHeight = 0.5 * length(centerA - centerB);\\n vec3 dir = normalize(centerA - centerB);\\n vec3 newPosition = position;\\n\\n vec3 rayOrigin = (inverseModelMatrix * vec4(cameraPosition, 1.0)).xyz;\\n vec3 objectToCameraModelSpace = rayOrigin - center;\\n\\n float maxRadius = max(a_radiusA, a_radiusB);\\n float leftUpScale = maxRadius;\\n\\n vec3 lDir = dir;\\n if (dot(objectToCameraModelSpace, dir) < 0.0) { // direction vector looks away, flip it\\n lDir = -lDir;\\n }\\n\\n vec3 left = normalize(cross(objectToCameraModelSpace, lDir));\\n vec3 up = normalize(cross(left, lDir));\\n\\n#ifndef GL_EXT_frag_depth\\n // make sure the billboard will not overlap with cap geometry (flickering effect), not important if we write to depth buffer\\n newPosition.x *= 1.0 - (maxRadius * (position.x + 1.0) * 0.0025 / halfHeight);\\n#endif\\n\\n vec3 surfacePoint = center + mat3(halfHeight*lDir, leftUpScale*left, leftUpScale*up) * newPosition;\\n vec3 transformed = surfacePoint;\\n surfacePoint = mul3(modelViewMatrix, surfacePoint);\\n\\n // varying data\\n v_treeIndex = a_treeIndex;\\n v_angle = a_angle;\\n v_arcAngle = a_arcAngle;\\n\\n // compute basis for cone\\n v_W.xyz = dir;\\n v_U.xyz = (modelTransformOffset * vec4(a_localXAxis, 0.0)).xyz;\\n v_W.xyz = normalize(normalMatrix * v_W.xyz);\\n v_U.xyz = normalize(normalMatrix * v_U.xyz);\\n // We pack surfacePoint as w-components of U and W\\n v_W.w = surfacePoint.z;\\n v_U.w = surfacePoint.x;\\n\\n mat4 modelToTransformOffset = modelMatrix * modelTransformOffset;\\n\\n float radiusB = length((modelToTransformOffset * vec4(a_localXAxis * a_radiusB, 0.0)).xyz);\\n float radiusA = length((modelToTransformOffset * vec4(a_localXAxis * a_radiusA, 0.0)).xyz);\\n\\n // We pack radii as w-components of v_centerB\\n v_centerB.xyz = mul3(modelViewMatrix, centerB);\\n v_centerB.w = radiusB;\\n\\n v_V.xyz = -cross(v_U.xyz, v_W.xyz);\\n v_V.w = surfacePoint.y;\\n\\n v_centerA.xyz = mul3(modelViewMatrix, centerA);\\n v_centerA.w = radiusA;\\n\\n v_color = a_color;\\n v_normal = normalMatrix * normal;\\n\\n vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\\n\\n gl_Position = projectionMatrix * mvPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nfloat displaceScalar(vec3 point, float scalar, \\n float treeIndex, vec3 cameraPosition, mat4 inverseModelMatrix) {\\n\\n // Displaces a scalar based on distance to camera to avoid z-fighting\\n vec3 cameraPositionModelSpace = (inverseModelMatrix * vec4(cameraPosition, 1.0)).xyz;\\n vec3 pointToCamera = cameraPositionModelSpace - point;\\n\\n // \\\"Random\\\" number in the range [0, 1], based on treeIndex\\n float rnd = mod(treeIndex, 64.) / 64.;\\n // Compute distance to camera, but cap it\\n float maxDistanceToCamera = 50.;\\n float distanceToCamera = min(length(pointToCamera), maxDistanceToCamera);\\n\\n float maxDisplacement = 0.01;\\n float scaleFactor = 0.01;\\n float displacement = min(maxDisplacement, scaleFactor * rnd * distanceToCamera / maxDistanceToCamera);\\n return scalar + displacement;\\n}\\n\\nfloat computeFragmentDepth(vec3 p, mat4 projectionMatrix) {\\n // Anders Hafreager comments:\\n // Depth value can be calculated by transforming the z-component of the intersection point to projection space.\\n // The w-component is also needed to scale projection space into clip space.\\n // However, the 4th column of the projection matrix is (0, 0, const, 0), so we can exploit this when computing w-value.\\n float projected_intersection_z=projectionMatrix[0][2]*p.x+projectionMatrix[1][2]*p.y+projectionMatrix[2][2]*p.z+projectionMatrix[3][2];\\n\\n // If we want to use orthographic camera, the full w-component is found as\\n float projected_intersection_w=projectionMatrix[0][3]*p.x+projectionMatrix[1][3]*p.y+projectionMatrix[2][3]*p.z+projectionMatrix[3][3];\\n // float projected_intersection_w = projectionMatrix[2][3]*newPoint.z; // Optimized for perspective camera\\n return ((gl_DepthRange.diff * (projected_intersection_z / projected_intersection_w)) + gl_DepthRange.near + gl_DepthRange.far) * .5;\\n}\\n\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth) \\n\\nfloat updateFragmentDepth(vec3 p,mat4 projectionMatrix) {\\n gl_FragDepthEXT = computeFragmentDepth(p, projectionMatrix);\\n return gl_FragDepthEXT;\\n}\\n\\n#else\\n\\nfloat updateFragmentDepth(vec3 p, mat4 projectionMatrix){\\n // Extension not available - not much we can do.\\n return computeFragmentDepth(p, projectionMatrix);\\n}\\n\\n#endif\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_1) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_1) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_1));\\n}\\n\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_0 || renderMode == RenderTypeEffects_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_0) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_0) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_0) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_0) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\n#define PI 3.14159265359\\n#define PI2 6.28318530718\\n#define PI_HALF 1.5707963267949\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform mat4 projectionMatrix;\\n\\nvarying vec4 U;\\nvarying vec4 V;\\nvarying vec4 axis;\\n\\nvarying vec4 v_centerA;\\nvarying vec4 v_centerB;\\nvarying float height;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform int renderMode;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n vec3 normal = normalize( v_normal );\\n mat3 basis = mat3(U.xyz, V.xyz, axis.xyz);\\n vec3 surfacePoint = vec3(U.w, V.w, axis.w);\\n vec3 rayTarget = surfacePoint;\\n\\n#if defined(COGNITE_ORTHOGRAPHIC_CAMERA)\\n vec3 rayDirection = vec3(0.0, 0.0, -1.0);\\n#else\\n vec3 rayDirection = normalize(rayTarget); // rayOrigin is (0,0,0) in camera space\\n#endif\\n\\n vec3 diff = rayTarget - v_centerA.xyz;\\n vec3 E = diff * basis;\\n float L = height;\\n vec3 D = rayDirection * basis;\\n\\n float R1 = v_centerA.w;\\n float R2 = v_centerB.w;\\n float dR = R2 - R1;\\n\\n float a = dot(D.xy, D.xy);\\n float b = dot(E.xy, D.xy);\\n float c = dot(E.xy, E.xy)-R1*R1;\\n float L2Inv = 1.0/(L*L);\\n\\n if (R1 != R2) {\\n // Additional terms if radii are different\\n float dRLInv = dR/L;\\n float dRdRL2Inv = dRLInv*dRLInv;\\n a -= D.z*D.z*dRdRL2Inv;\\n b -= dRLInv*(E.z*D.z*dRLInv + R1*D.z);\\n c -= dRLInv*(E.z*E.z*dRLInv + 2.0*R1*E.z);\\n }\\n\\n // Additional terms when one of the center points is displaced orthogonal to normal vector\\n vec2 displacement = ((v_centerB.xyz-v_centerA.xyz)*basis).xy; // In the basis where displacement is in XY only\\n float displacementLengthSquared = dot(displacement, displacement);\\n a += D.z*(D.z*displacementLengthSquared - 2.0*L*dot(D.xy, displacement))*L2Inv;\\n b += (D.z*E.z*displacementLengthSquared - L*(D.x*E.z*displacement.x + D.y*E.z*displacement.y + D.z*E.x*displacement.x + D.z*E.y*displacement.y))*L2Inv;\\n c += E.z*(E.z*displacementLengthSquared - 2.*L*dot(E.xy, displacement))*L2Inv;\\n\\n // Calculate a dicriminant of the above quadratic equation (factor 2 removed from all b-terms above)\\n float d = b*b - a*c;\\n\\n // d < 0.0 means the ray hits outside an infinitely long eccentric cone\\n if (d < 0.0) {\\n discard;\\n }\\n float sqrtd = sqrt(d);\\n float dist1 = (-b - sqrtd)/a;\\n float dist2 = (-b + sqrtd)/a;\\n\\n // Make sure dist1 is the smaller one\\n if (dist2 < dist1) {\\n float tmp = dist1;\\n dist1 = dist2;\\n dist2 = tmp;\\n }\\n\\n // Check the smallest root, it is closest camera. Only test if the z-component is outside the truncated eccentric cone\\n float dist = dist1;\\n float intersectionPointZ = E.z + dist*D.z;\\n // Intersection point in camera space\\n vec3 p = rayTarget + dist*rayDirection;\\n bool isInner = false;\\n\\n if (intersectionPointZ <= 0.0 ||\\n intersectionPointZ >= L ||\\n isSliced(p)\\n ) {\\n // Either intersection point is behind starting point (happens inside the cone),\\n // or the intersection point is outside the end caps. This is not a valid solution.\\n isInner = true;\\n dist = dist2;\\n intersectionPointZ = E.z + dist*D.z;\\n p = rayTarget + dist*rayDirection;\\n\\n if (intersectionPointZ <= 0.0 ||\\n intersectionPointZ >= L ||\\n isSliced(p)\\n ) {\\n // Missed the other point too\\n discard;\\n }\\n }\\n\\n#if !defined(COGNITE_RENDER_COLOR_ID) && !defined(COGNITE_RENDER_DEPTH)\\n // Find normal vector\\n vec3 n = normalize(-axis.xyz);\\n vec3 v_centerA = v_centerA.xyz;\\n vec3 v_centerB = v_centerB.xyz;\\n vec3 A = cross(v_centerA - p, v_centerB - p);\\n\\n vec3 t = normalize(cross(n, A));\\n vec3 o1 = v_centerA + R1 * t;\\n vec3 o2 = v_centerB + R2 * t;\\n vec3 B = o2-o1;\\n normal = normalize(cross(A, B));\\n#endif\\n\\n float fragDepth = updateFragmentDepth(p, projectionMatrix);\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, fragDepth, matCapTexture, GeometryType.Primitive);\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 mul3(mat4 M, vec3 v) {\\n vec4 u = M * vec4(v, 1.0);\\n return u.xyz / u.w;\\n}\\n\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_centerA;\\nattribute vec3 a_centerB;\\nattribute float a_radiusA;\\nattribute float a_radiusB;\\nattribute vec3 a_normal;\\nattribute vec3 a_color;\\n\\nvarying float v_treeIndex;\\n// We pack the radii into w-components\\nvarying vec4 v_centerA;\\nvarying vec4 v_centerB;\\n\\n// U, V, axis represent the 3x3 cone basis.\\n// They are vec4 to pack extra data into the w-component\\n// since Safari on iOS only supports 8 varying vec4 registers.\\nvarying vec4 U;\\nvarying vec4 V;\\nvarying vec4 axis;\\nvarying float height;\\n\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n mat4 modelTransformOffset = inverseModelMatrix * treeIndexWorldTransform * modelMatrix;\\n mat4 modelToTransformOffset = modelMatrix * modelTransformOffset;\\n\\n vec3 centerA = mul3(modelTransformOffset, a_centerA);\\n vec3 centerB = mul3(modelTransformOffset, a_centerB);\\n\\n vec3 normalWithOffset = normalize((modelTransformOffset * vec4(a_normal, 0)).xyz);\\n\\n float uniformScaleFactor = length(mul3(modelMatrix, normalize(vec3(1.0))));\\n\\n height = dot(centerA - centerB, normalWithOffset) * uniformScaleFactor;\\n\\n vec3 lDir;\\n vec3 center = 0.5 * (centerA + centerB);\\n vec3 newPosition = position;\\n\\n vec3 rayOrigin = (inverseModelMatrix * vec4(cameraPosition, 1.0)).xyz;\\n vec3 objectToCameraModelSpace = rayOrigin - center;\\n\\n // Find the coordinates of centerA and centerB projected down to the end cap plane\\n vec3 maxCenterProjected = centerA - dot(centerA, normalWithOffset) * normalWithOffset;\\n vec3 minCenterProjected = centerB - dot(centerB, normalWithOffset) * normalWithOffset;\\n float distanceBetweenProjectedCenters = length(maxCenterProjected - minCenterProjected);\\n\\n lDir = normalWithOffset;\\n float dirSign = 1.0;\\n if (dot(objectToCameraModelSpace, lDir) < 0.0) { // direction vector looks away, flip it\\n dirSign = -1.0;\\n lDir *= -1.;\\n }\\n\\n vec3 left = normalize(cross(objectToCameraModelSpace, lDir));\\n vec3 up = normalize(cross(left, lDir));\\n\\n // compute basis for cone\\n axis.xyz = -normalWithOffset;\\n U.xyz = cross(objectToCameraModelSpace, axis.xyz);\\n V.xyz = cross(U.xyz, axis.xyz);\\n // Transform to camera space\\n axis.xyz = normalize(normalMatrix * axis.xyz);\\n U.xyz = normalize(normalMatrix * U.xyz);\\n V.xyz = normalize(normalMatrix * V.xyz);\\n\\n#ifndef GL_EXT_frag_depth\\n // make sure the billboard will not overlap with cap geometry (flickering effect), not important if we write to depth buffer\\n newPosition.x *= 1.0 - (a_radiusA * (position.x + 1.0) * 0.0025 / height);\\n#endif\\n\\n v_centerA.xyz = mul3(viewMatrix, mul3(modelMatrix, centerA));\\n v_centerB.xyz = mul3(viewMatrix, mul3(modelMatrix, centerB));\\n\\n float radiusA = length((modelToTransformOffset * vec4(normalize(vec3(1.0)) * a_radiusA, 0.0)).xyz);\\n float radiusB = length((modelToTransformOffset * vec4(normalize(vec3(1.0)) * a_radiusB, 0.0)).xyz);\\n\\n // Pack radii as w components of v_centerA and v_centerB\\n v_centerA.w = radiusA;\\n v_centerB.w = radiusB;\\n\\n float radiusIncludedDisplacement = 0.5*(2.0*max(a_radiusA, a_radiusB) + distanceBetweenProjectedCenters);\\n vec3 surfacePoint = center + mat3(0.5 * height * lDir * (1.0 / uniformScaleFactor), radiusIncludedDisplacement*left, radiusIncludedDisplacement*up) * newPosition;\\n vec3 transformed = surfacePoint;\\n\\n surfacePoint = mul3(modelViewMatrix, surfacePoint);\\n\\n // We pack surfacePoint as w-components of U, V and axis\\n U.w = surfacePoint.x;\\n V.w = surfacePoint.y;\\n axis.w = surfacePoint.z;\\n\\n v_treeIndex = a_treeIndex;\\n v_color = a_color;\\n v_normal = normalMatrix * normal;\\n\\n vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\\n gl_Position = projectionMatrix * mvPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nfloat computeFragmentDepth(vec3 p, mat4 projectionMatrix) {\\n // Anders Hafreager comments:\\n // Depth value can be calculated by transforming the z-component of the intersection point to projection space.\\n // The w-component is also needed to scale projection space into clip space.\\n // However, the 4th column of the projection matrix is (0, 0, const, 0), so we can exploit this when computing w-value.\\n float projected_intersection_z=projectionMatrix[0][2]*p.x+projectionMatrix[1][2]*p.y+projectionMatrix[2][2]*p.z+projectionMatrix[3][2];\\n\\n // If we want to use orthographic camera, the full w-component is found as\\n float projected_intersection_w=projectionMatrix[0][3]*p.x+projectionMatrix[1][3]*p.y+projectionMatrix[2][3]*p.z+projectionMatrix[3][3];\\n // float projected_intersection_w = projectionMatrix[2][3]*newPoint.z; // Optimized for perspective camera\\n return ((gl_DepthRange.diff * (projected_intersection_z / projected_intersection_w)) + gl_DepthRange.near + gl_DepthRange.far) * .5;\\n}\\n\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth) \\n\\nfloat updateFragmentDepth(vec3 p,mat4 projectionMatrix) {\\n gl_FragDepthEXT = computeFragmentDepth(p, projectionMatrix);\\n return gl_FragDepthEXT;\\n}\\n\\n#else\\n\\nfloat updateFragmentDepth(vec3 p, mat4 projectionMatrix){\\n // Extension not available - not much we can do.\\n return computeFragmentDepth(p, projectionMatrix);\\n}\\n\\n#endif\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_1) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_1) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_1));\\n}\\n\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_0 || renderMode == RenderTypeEffects_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_0) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_0) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_0) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_0) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform mat4 projectionMatrix;\\nvarying vec4 center;\\nvarying float hRadius;\\nvarying float height;\\n\\nvarying vec4 U;\\nvarying vec4 V;\\nvarying vec4 sphereNormal;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform int renderMode;\\n\\nvoid main() {\\n\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n vec3 normal = normalize(sphereNormal.xyz);\\n\\n float vRadius = center.w;\\n float ratio = vRadius / hRadius;\\n mat3 basis = mat3(U.xyz, V.xyz, sphereNormal.xyz);\\n mat3 scaledBasis = mat3(ratio * U.xyz, ratio * V.xyz, sphereNormal.xyz);\\n vec3 surfacePoint = vec3(U.w, V.w, sphereNormal.w);\\n vec3 rayTarget = surfacePoint;\\n\\n#if defined(COGNITE_ORTHOGRAPHIC_CAMERA)\\n vec3 rayDirection = vec3(0.0, 0.0, -1.0);\\n#else\\n vec3 rayDirection = normalize(rayTarget); // rayOrigin is (0,0,0) in camera space\\n#endif\\n\\n vec3 diff = rayTarget - center.xyz;\\n vec3 E = diff * scaledBasis;\\n vec3 D = rayDirection * scaledBasis;\\n\\n float a = dot(D, D);\\n float b = dot(E, D);\\n float c = dot(E, E) - vRadius*vRadius;\\n\\n // discriminant of sphere equation (factor 2 removed from b above)\\n float d = b*b - a*c;\\n if(d < 0.0)\\n discard;\\n\\n float sqrtd = sqrt(d);\\n float dist1 = (-b - sqrtd)/a;\\n float dist2 = (-b + sqrtd)/a;\\n\\n // Make sure dist1 is the smaller one\\n if (dist2 < dist1) {\\n float tmp = dist1;\\n dist1 = dist2;\\n dist2 = tmp;\\n }\\n\\n float dist = dist1;\\n float intersectionPointZ = E.z + dist*D.z;\\n // Intersection point in camera space\\n vec3 p = rayTarget + dist*rayDirection;\\n\\n if (intersectionPointZ <= vRadius - height ||\\n intersectionPointZ > vRadius ||\\n isSliced(p)\\n ) {\\n // Missed the first point, check the other point\\n\\n dist = dist2;\\n intersectionPointZ = E.z + dist*D.z;\\n p = rayTarget + dist*rayDirection;\\n if (intersectionPointZ <= vRadius - height ||\\n intersectionPointZ > vRadius ||\\n isSliced(p)\\n ) {\\n // Missed the other point too\\n discard;\\n }\\n }\\n\\n#if !defined(COGNITE_RENDER_COLOR_ID) && !defined(COGNITE_RENDER_DEPTH)\\n // Find normal vector in local space\\n normal = vec3(p - center.xyz) * basis;\\n normal.z = normal.z * (hRadius / vRadius) * (hRadius / vRadius);\\n // Transform into camera space\\n normal = normalize(basis * normal);\\n if (dot(normal, rayDirection) > 0.) {\\n normal = -normal;\\n }\\n#endif\\n\\n float fragDepth = updateFragmentDepth(p, projectionMatrix);\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, fragDepth, matCapTexture, GeometryType.Primitive);\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 mul3(mat4 M, vec3 v) {\\n vec4 u = M * vec4(v, 1.0);\\n return u.xyz / u.w;\\n}\\n\\nfloat displaceScalar(vec3 point, float scalar, \\n float treeIndex, vec3 cameraPosition, mat4 inverseModelMatrix) {\\n\\n // Displaces a scalar based on distance to camera to avoid z-fighting\\n vec3 cameraPositionModelSpace = (inverseModelMatrix * vec4(cameraPosition, 1.0)).xyz;\\n vec3 pointToCamera = cameraPositionModelSpace - point;\\n\\n // \\\"Random\\\" number in the range [0, 1], based on treeIndex\\n float rnd = mod(treeIndex, 64.) / 64.;\\n // Compute distance to camera, but cap it\\n float maxDistanceToCamera = 50.;\\n float distanceToCamera = min(length(pointToCamera), maxDistanceToCamera);\\n\\n float maxDisplacement = 0.01;\\n float scaleFactor = 0.01;\\n float displacement = min(maxDisplacement, scaleFactor * rnd * distanceToCamera / maxDistanceToCamera);\\n return scalar + displacement;\\n}\\n\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\nuniform mat4 inverseNormalMatrix;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_color;\\nattribute vec3 a_center;\\nattribute vec3 a_normal;\\nattribute float a_horizontalRadius;\\nattribute float a_verticalRadius;\\nattribute float a_height;\\n\\nvarying float v_treeIndex;\\n// We pack vRadius as w-component of center\\nvarying vec4 center;\\nvarying float hRadius;\\nvarying float height;\\n\\n// U, V, axis represent the 3x3 sphere basis.\\n// They are vec4 to pack extra data into the w-component\\n// since Safari on iOS only supports 8 varying vec4 registers.\\nvarying vec4 U;\\nvarying vec4 V;\\nvarying vec4 sphereNormal;\\n\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n mat4 modelTransformOffset = inverseModelMatrix * treeIndexWorldTransform * modelMatrix;\\n\\n vec3 centerWithOffset = mul3(modelTransformOffset, a_center).xyz;\\n\\n vec3 normalWithOffset = (modelTransformOffset * vec4(a_normal, 0)).xyz;\\n\\n vec3 lDir;\\n float distanceToCenterOfSegment = a_verticalRadius - a_height * 0.5;\\n vec3 centerOfSegment = centerWithOffset + normalWithOffset * distanceToCenterOfSegment;\\n\\n#if defined(COGNITE_ORTHOGRAPHIC_CAMERA)\\n vec3 objectToCameraModelSpace = inverseNormalMatrix * vec3(0.0, 0.0, 1.0);\\n#else\\n vec3 rayOrigin = (inverseModelMatrix * vec4(cameraPosition, 1.0)).xyz;\\n vec3 objectToCameraModelSpace = rayOrigin - centerOfSegment;\\n#endif\\n\\n vec3 newPosition = position;\\n\\n float bb = dot(objectToCameraModelSpace, normalWithOffset);\\n if (bb < 0.0) { // direction vector looks away, flip it\\n lDir = -normalWithOffset;\\n } else { // direction vector already looks in my direction\\n lDir = normalWithOffset;\\n }\\n\\n vec3 left = normalize(cross(objectToCameraModelSpace, lDir));\\n vec3 up = normalize(cross(left, lDir));\\n\\n#ifndef GL_EXT_frag_depth\\n // make sure the billboard will not overlap with cap geometry (flickering effect), not important if we write to depth buffer\\n newPosition.x *= 1.0 - (a_verticalRadius * (position.x + 1.0) * 0.0025 / a_height);\\n#endif\\n\\n // Negative angle means height larger than radius,\\n // so we should have full size so we can render the largest part of the ellipsoid segment\\n float ratio = max(0.0, 1.0 - a_height / a_verticalRadius);\\n // maxRadiusOfSegment is the radius of the circle (projected ellipsoid) when ellipsoid segment is seen from above\\n float maxRadiusOfSegment = a_horizontalRadius * sqrt(1.0 - ratio * ratio);\\n\\n vec3 displacement = vec3(newPosition.x*a_height*0.5, maxRadiusOfSegment*newPosition.y, maxRadiusOfSegment*newPosition.z);\\n vec3 surfacePoint = centerOfSegment + mat3(lDir, left, up) * displacement;\\n vec3 transformed = surfacePoint;\\n\\n v_treeIndex = a_treeIndex;\\n surfacePoint = mul3(modelViewMatrix, surfacePoint);\\n center.xyz = mul3(modelViewMatrix, centerWithOffset);\\n center.w = a_verticalRadius; // Pack radius into w-component\\n hRadius = a_horizontalRadius;\\n height = a_height;\\n v_color = a_color;\\n\\n // compute basis\\n sphereNormal.xyz = normalMatrix * normalWithOffset;\\n U.xyz = normalMatrix * up;\\n V.xyz = normalMatrix * left;\\n\\n // We pack surfacePoint as w-components of U, V and axis\\n U.w = surfacePoint.x;\\n V.w = surfacePoint.y;\\n sphereNormal.w = surfacePoint.z;\\n\\n // TODO should perhaps be a different normal?\\n vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\\n gl_Position = projectionMatrix * mvPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 mul3(mat4 M, vec3 v) {\\n vec4 u = M * vec4(v, 1.0);\\n return u.xyz / u.w;\\n}\\n\\nfloat displaceScalar(vec3 point, float scalar, \\n float treeIndex, vec3 cameraPosition, mat4 inverseModelMatrix) {\\n\\n // Displaces a scalar based on distance to camera to avoid z-fighting\\n vec3 cameraPositionModelSpace = (inverseModelMatrix * vec4(cameraPosition, 1.0)).xyz;\\n vec3 pointToCamera = cameraPositionModelSpace - point;\\n\\n // \\\"Random\\\" number in the range [0, 1], based on treeIndex\\n float rnd = mod(treeIndex, 64.) / 64.;\\n // Compute distance to camera, but cap it\\n float maxDistanceToCamera = 50.;\\n float distanceToCamera = min(length(pointToCamera), maxDistanceToCamera);\\n\\n float maxDisplacement = 0.01;\\n float scaleFactor = 0.01;\\n float displacement = min(maxDisplacement, scaleFactor * rnd * distanceToCamera / maxDistanceToCamera);\\n return scalar + displacement;\\n}\\n\\nfloat computeFragmentDepth(vec3 p, mat4 projectionMatrix) {\\n // Anders Hafreager comments:\\n // Depth value can be calculated by transforming the z-component of the intersection point to projection space.\\n // The w-component is also needed to scale projection space into clip space.\\n // However, the 4th column of the projection matrix is (0, 0, const, 0), so we can exploit this when computing w-value.\\n float projected_intersection_z=projectionMatrix[0][2]*p.x+projectionMatrix[1][2]*p.y+projectionMatrix[2][2]*p.z+projectionMatrix[3][2];\\n\\n // If we want to use orthographic camera, the full w-component is found as\\n float projected_intersection_w=projectionMatrix[0][3]*p.x+projectionMatrix[1][3]*p.y+projectionMatrix[2][3]*p.z+projectionMatrix[3][3];\\n // float projected_intersection_w = projectionMatrix[2][3]*newPoint.z; // Optimized for perspective camera\\n return ((gl_DepthRange.diff * (projected_intersection_z / projected_intersection_w)) + gl_DepthRange.near + gl_DepthRange.far) * .5;\\n}\\n\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth) \\n\\nfloat updateFragmentDepth(vec3 p,mat4 projectionMatrix) {\\n gl_FragDepthEXT = computeFragmentDepth(p, projectionMatrix);\\n return gl_FragDepthEXT;\\n}\\n\\n#else\\n\\nfloat updateFragmentDepth(vec3 p, mat4 projectionMatrix){\\n // Extension not available - not much we can do.\\n return computeFragmentDepth(p, projectionMatrix);\\n}\\n\\n#endif\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_0) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_0) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_0));\\n}\\n\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_1 || renderMode == RenderTypeEffects_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_1) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_1) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_1) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_1) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\n#define PI 3.14159265359\\n#define PI2 6.28318530718\\n#define PI_HALF 1.5707963267949\\n\\n// TODO general cylinder and cone are very similar and used\\n// the same shader in the old code. Consider de-duplicating\\n// parts of this code\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform float dataTextureWidth;\\nuniform float dataTextureHeight;\\nuniform mat4 projectionMatrix;\\n\\nvarying vec4 v_centerB;\\n\\nvarying vec4 v_W;\\nvarying vec4 v_U;\\n\\nvarying float v_angle;\\nvarying float v_arcAngle;\\n\\nvarying float v_surfacePointY;\\n\\nvarying vec4 v_planeA;\\nvarying vec4 v_planeB;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform int renderMode;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n vec3 normal = normalize( v_normal );\\n\\n float R1 = v_centerB.w;\\n vec4 U = v_U;\\n vec4 W = v_W;\\n vec4 V = vec4(normalize(cross(W.xyz, U.xyz)), v_surfacePointY);\\n\\n mat3 basis = mat3(U.xyz, V.xyz, W.xyz);\\n vec3 surfacePoint = vec3(U.w, V.w, W.w);\\n vec3 rayTarget = surfacePoint;\\n\\n#if defined(COGNITE_ORTHOGRAPHIC_CAMERA)\\n vec3 rayDirection = vec3(0.0, 0.0, -1.0);\\n#else\\n vec3 rayDirection = normalize(rayTarget); // rayOrigin is (0,0,0) in camera space\\n#endif\\n\\n vec3 diff = rayTarget - v_centerB.xyz;\\n vec3 E = diff * basis;\\n vec3 D = rayDirection * basis;\\n\\n float a = dot(D.xy, D.xy);\\n float b = dot(E.xy, D.xy);\\n float c = dot(E.xy, E.xy) - R1*R1;\\n\\n // Calculate a dicriminant of the above quadratic equation\\n float d = b*b - a*c;\\n\\n // d < 0.0 means the ray hits outside an infinitely long cone\\n if (d < 0.0)\\n discard;\\n\\n float sqrtd = sqrt(d);\\n float dist1 = (-b - sqrtd)/a;\\n float dist2 = (-b + sqrtd)/a;\\n\\n // Make sure dist1 is the smaller one\\n if (dist2 < dist1) {\\n float tmp = dist1;\\n dist1 = dist2;\\n dist2 = tmp;\\n }\\n\\n float dist = dist1;\\n vec3 intersectionPoint = E + dist * D;\\n float theta = atan(intersectionPoint.y, intersectionPoint.x);\\n if (theta < v_angle) theta += 2.0 * PI;\\n\\n // Intersection point in camera space\\n vec3 p = rayTarget + dist*rayDirection;\\n\\n vec3 planeACenter = vec3(0.0, 0.0, v_planeA.w);\\n vec3 planeANormal = v_planeA.xyz;\\n vec3 planeBCenter = vec3(0.0, 0.0, v_planeB.w);\\n vec3 planeBNormal = v_planeB.xyz;\\n bool isInner = false;\\n\\n if (dot(intersectionPoint - planeACenter, planeANormal) > 0.0 ||\\n dot(intersectionPoint - planeBCenter, planeBNormal) > 0.0 ||\\n theta > v_arcAngle + v_angle ||\\n isSliced(p)\\n ) {\\n // Missed the first point, check the other point\\n isInner = true;\\n dist = dist2;\\n intersectionPoint = E + dist * D;\\n theta = atan(intersectionPoint.y, intersectionPoint.x);\\n p = rayTarget + dist*rayDirection;\\n if (theta < v_angle) theta += 2.0 * PI;\\n if (dot(intersectionPoint - planeACenter, planeANormal) > 0.0 ||\\n dot(intersectionPoint - planeBCenter, planeBNormal) > 0.0 ||\\n theta > v_arcAngle + v_angle || isSliced(p)\\n ) {\\n // Missed the other point too\\n discard;\\n }\\n }\\n\\n#if !defined(COGNITE_RENDER_COLOR_ID) && !defined(COGNITE_RENDER_DEPTH)\\n // Regular cylinder has simpler normal vector in camera space\\n vec3 p_local = p - v_centerB.xyz;\\n normal = normalize(p_local - W.xyz * dot(p_local, W.xyz));\\n#endif\\n\\n float fragDepth = updateFragmentDepth(p, projectionMatrix);\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, fragDepth, matCapTexture, GeometryType.Primitive);\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 mul3(mat4 M, vec3 v) {\\n vec4 u = M * vec4(v, 1.0);\\n return u.xyz / u.w;\\n}\\n\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_centerA;\\nattribute vec3 a_centerB;\\nattribute float a_radius;\\nattribute vec3 a_color;\\n// slicing plane attributes\\nattribute vec4 a_planeA;\\nattribute vec4 a_planeB;\\n// segment attributes\\nattribute vec3 a_localXAxis;\\nattribute float a_angle;\\nattribute float a_arcAngle;\\n\\nvarying float v_treeIndex;\\n// We pack the radii into w-components\\nvarying vec4 v_centerB;\\n\\n// U, V, axis represent the 3x3 cone basis.\\n// They are vec4 to pack extra data into the w-component\\n// since Safari on iOS only supports 8 varying vec4 registers.\\nvarying vec4 v_U;\\nvarying vec4 v_W;\\n\\nvarying vec4 v_planeA;\\nvarying vec4 v_planeB;\\n\\nvarying float v_surfacePointY;\\n\\nvarying float v_angle;\\nvarying float v_arcAngle;\\n\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n \\n mat4 modelTransformOffset = inverseModelMatrix * treeIndexWorldTransform * modelMatrix;\\n\\n vec3 centerA = mul3(modelTransformOffset, a_centerA);\\n vec3 centerB = mul3(modelTransformOffset, a_centerB);\\n\\n vec3 center = 0.5 * (centerA + centerB);\\n float halfHeight = 0.5 * length(centerA - centerB);\\n vec3 dir = normalize(centerA - centerB);\\n vec3 newPosition = position;\\n\\n vec3 rayOrigin = (inverseModelMatrix * vec4(cameraPosition, 1.0)).xyz;\\n vec3 objectToCameraModelSpace = rayOrigin - center;\\n\\n float leftUpScale = a_radius;\\n\\n vec3 lDir = dir;\\n if (dot(objectToCameraModelSpace, dir) < 0.0) { // direction vector looks away, flip it\\n lDir = -lDir;\\n }\\n\\n vec3 left = normalize(cross(objectToCameraModelSpace, lDir));\\n vec3 up = normalize(cross(left, lDir));\\n\\n#ifndef GL_EXT_frag_depth\\n // make sure the billboard will not overlap with cap geometry (flickering effect), not important if we write to depth buffer\\n newPosition.x *= 1.0 - (a_radius * (position.x + 1.0) * 0.0025 / halfHeight);\\n#endif\\n\\n vec3 surfacePoint = center + mat3(halfHeight*lDir, leftUpScale*left, leftUpScale*up) * newPosition;\\n vec3 transformed = surfacePoint;\\n surfacePoint = mul3(modelViewMatrix, surfacePoint);\\n\\n // varying data\\n v_treeIndex = a_treeIndex;\\n v_angle = a_angle;\\n v_arcAngle = a_arcAngle;\\n\\n // compute basis for cone\\n v_W.xyz = dir;\\n v_U.xyz = (modelTransformOffset * vec4(a_localXAxis, 0)).xyz;\\n v_W.xyz = normalize(normalMatrix * v_W.xyz);\\n v_U.xyz = normalize(normalMatrix * v_U.xyz);\\n // We pack surfacePoint as w-components of U and W\\n v_W.w = surfacePoint.z;\\n v_U.w = surfacePoint.x;\\n\\n // We pack radii as w-components of v_centerB\\n mat4 modelToTransformOffset = modelMatrix * modelTransformOffset;\\n float radius = length((modelToTransformOffset * vec4(a_localXAxis * a_radius, 0.0)).xyz);\\n\\n centerB = centerB - dir;\\n v_centerB.xyz = mul3(modelViewMatrix, centerB);\\n v_centerB.w = radius;\\n\\n vec4 planeA = a_planeA;\\n planeA.w = length((modelToTransformOffset * vec4(planeA.xyz * planeA.w, 0.0)).xyz);\\n\\n vec4 planeB = a_planeB;\\n planeB.w = length((modelToTransformOffset * vec4(planeB.xyz * planeB.w, 0.0)).xyz);\\n\\n v_planeA = planeA;\\n v_planeB = planeB;\\n v_surfacePointY = surfacePoint.y;\\n v_centerB.w = radius;\\n\\n v_color = a_color;\\n v_normal = normalMatrix * normal;\\n\\n vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\\n gl_Position = projectionMatrix * mvPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nfloat computeFragmentDepth(vec3 p, mat4 projectionMatrix) {\\n // Anders Hafreager comments:\\n // Depth value can be calculated by transforming the z-component of the intersection point to projection space.\\n // The w-component is also needed to scale projection space into clip space.\\n // However, the 4th column of the projection matrix is (0, 0, const, 0), so we can exploit this when computing w-value.\\n float projected_intersection_z=projectionMatrix[0][2]*p.x+projectionMatrix[1][2]*p.y+projectionMatrix[2][2]*p.z+projectionMatrix[3][2];\\n\\n // If we want to use orthographic camera, the full w-component is found as\\n float projected_intersection_w=projectionMatrix[0][3]*p.x+projectionMatrix[1][3]*p.y+projectionMatrix[2][3]*p.z+projectionMatrix[3][3];\\n // float projected_intersection_w = projectionMatrix[2][3]*newPoint.z; // Optimized for perspective camera\\n return ((gl_DepthRange.diff * (projected_intersection_z / projected_intersection_w)) + gl_DepthRange.near + gl_DepthRange.far) * .5;\\n}\\n\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth) \\n\\nfloat updateFragmentDepth(vec3 p,mat4 projectionMatrix) {\\n gl_FragDepthEXT = computeFragmentDepth(p, projectionMatrix);\\n return gl_FragDepthEXT;\\n}\\n\\n#else\\n\\nfloat updateFragmentDepth(vec3 p, mat4 projectionMatrix){\\n // Extension not available - not much we can do.\\n return computeFragmentDepth(p, projectionMatrix);\\n}\\n\\n#endif\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_1) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_1) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_1));\\n}\\n\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_0 || renderMode == RenderTypeEffects_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_0) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_0) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_0) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_0) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\n#define PI 3.14159265359\\n#define PI2 6.28318530718\\n#define PI_HALF 1.5707963267949\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\nvarying float v_oneMinusThicknessSqr;\\nvarying vec2 v_xy;\\nvarying float v_angle;\\nvarying float v_arcAngle;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform int renderMode;\\n\\nvarying vec3 vViewPosition;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n if (isSliced(vViewPosition)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n float dist = dot(v_xy, v_xy);\\n float theta = atan(v_xy.y, v_xy.x);\\n vec3 normal = normalize( v_normal );\\n if (theta < v_angle) {\\n theta += 2.0 * PI;\\n }\\n if (dist > 0.25 || dist < 0.25 * v_oneMinusThicknessSqr || theta >= v_angle + v_arcAngle) {\\n discard;\\n }\\n\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, gl_FragCoord.z, matCapTexture, GeometryType.Primitive);\\n}\\n\";","export default \"#define GLSLIFY 1\\n// Not using the w-component to support using vec3 and vec4 as input\\nmat4 constructMatrix(vec4 column_0, vec4 column_1, vec4 column_2, vec4 column_3) {\\n return mat4(\\n vec4(column_0.xyz, 0.0),\\n vec4(column_1.xyz, 0.0),\\n vec4(column_2.xyz, 0.0),\\n vec4(column_3.xyz, 1.0)\\n );\\n}\\n\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\n\\nattribute vec4 a_instanceMatrix_column_0;\\nattribute vec4 a_instanceMatrix_column_1;\\nattribute vec4 a_instanceMatrix_column_2;\\nattribute vec4 a_instanceMatrix_column_3;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_color;\\nattribute float a_angle;\\nattribute float a_arcAngle;\\nattribute float a_thickness;\\nattribute vec3 a_normal;\\n\\nvarying float v_treeIndex;\\nvarying float v_oneMinusThicknessSqr;\\nvarying vec2 v_xy;\\nvarying float v_angle;\\nvarying float v_arcAngle;\\n\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nvarying vec3 vViewPosition;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n mat4 instanceMatrix = constructMatrix(\\n a_instanceMatrix_column_0,\\n a_instanceMatrix_column_1,\\n a_instanceMatrix_column_2,\\n a_instanceMatrix_column_3\\n );\\n\\n v_treeIndex = a_treeIndex;\\n v_oneMinusThicknessSqr = (1.0 - a_thickness) * (1.0 - a_thickness);\\n v_xy = vec2(position.x, position.y);\\n v_angle = a_angle;\\n v_arcAngle = a_arcAngle;\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n vec3 transformed = (instanceMatrix * vec4(position, 1.0)).xyz;\\n vec4 mvPosition = viewMatrix * treeIndexWorldTransform * modelMatrix * vec4( transformed, 1.0 );\\n v_color = a_color;\\n\\n v_normal = normalMatrix * normalize(inverseModelMatrix * treeIndexWorldTransform * modelMatrix * vec4(normalize(a_normal), 0.0)).xyz;\\n vViewPosition = mvPosition.xyz;\\n gl_Position = projectionMatrix * mvPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_1 || renderMode == RenderTypeEffects_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_1) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_1) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_1) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_1) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_1) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_0) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_0) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_0));\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform int renderMode;\\n\\nvarying vec3 vViewPosition;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n if (isSliced(vViewPosition)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n vec3 normal = normalize(v_normal);\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, gl_FragCoord.z, matCapTexture, GeometryType.Primitive);\\n}\\n\";","export default \"#define GLSLIFY 1\\n// Not using the w-component to support using vec3 and vec4 as input\\nmat4 constructMatrix(vec4 column_0, vec4 column_1, vec4 column_2, vec4 column_3) {\\n return mat4(\\n vec4(column_0.xyz, 0.0),\\n vec4(column_1.xyz, 0.0),\\n vec4(column_2.xyz, 0.0),\\n vec4(column_3.xyz, 1.0)\\n );\\n}\\n\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\n\\nattribute vec4 a_instanceMatrix_column_0;\\nattribute vec4 a_instanceMatrix_column_1;\\nattribute vec4 a_instanceMatrix_column_2;\\nattribute vec4 a_instanceMatrix_column_3;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_color;\\nattribute float a_arcAngle;\\nattribute float a_radius;\\nattribute float a_tubeRadius;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nvarying vec3 vViewPosition;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n mat4 instanceMatrix = constructMatrix(\\n a_instanceMatrix_column_0,\\n a_instanceMatrix_column_1,\\n a_instanceMatrix_column_2,\\n a_instanceMatrix_column_3\\n );\\n // normalized theta and phi are packed into positions\\n float theta = position.x * a_arcAngle;\\n float phi = position.y;\\n float cosTheta = cos(theta);\\n float sinTheta = sin(theta);\\n vec3 pos3 = vec3(0);\\n\\n pos3.x = (a_radius + a_tubeRadius*cos(phi)) * cosTheta;\\n pos3.y = (a_radius + a_tubeRadius*cos(phi)) * sinTheta;\\n pos3.z = a_tubeRadius*sin(phi);\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n \\n vec3 transformed = (instanceMatrix * vec4(pos3, 1.0)).xyz;\\n\\n // Calculate normal vectors if we're not picking\\n vec3 center = (instanceMatrix * vec4(a_radius * cosTheta, a_radius * sinTheta, 0.0, 1.0)).xyz;\\n vec3 objectNormal = normalize(transformed.xyz - center);\\n\\n v_treeIndex = a_treeIndex;\\n v_color = a_color;\\n v_normal = normalMatrix * normalize(inverseModelMatrix * treeIndexWorldTransform * modelMatrix * vec4(objectNormal, 0.0)).xyz;\\n\\n vec4 modelViewPosition = viewMatrix * treeIndexWorldTransform * modelMatrix * vec4(transformed, 1.0);\\n\\n vViewPosition = modelViewPosition.xyz;\\n\\n gl_Position = projectionMatrix * modelViewPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nvec3 rgb2hsv(vec3 c)\\n{\\n vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\\n vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\\n\\n float d = q.x - min(q.w, q.y);\\n float e = 1.0e-10;\\n return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\\n}\\n\\nvec3 hsv2rgb(vec3 c)\\n{\\n vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\\n}\\n\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nstruct GeometryTypeEnum {\\n int Quad;\\n int Primitive;\\n int TriangleMesh;\\n int InstancedMesh;\\n};\\n\\nconst GeometryTypeEnum GeometryType = GeometryTypeEnum(1,2,3,4);\\n\\nconst int RenderTypeColor_0 = 1;\\nconst int RenderTypeNormal_0 = 2;\\nconst int RenderTypeTreeIndex_0 = 3;\\nconst int RenderTypePackColorAndNormal_0 = 4;\\nconst int RenderTypeDepth_0 = 5;\\nconst int RenderTypeEffects_0 = 6;\\nconst int RenderTypeGhost_0 = 7;\\nconst int RenderTypeLOD = 8;\\nconst int RenderTypeDepthBufferOnly = 9;\\nconst int RenderTypeGeometryType = 10;\\n\\n#include <packing>\\n\\nvec3 packNormalToRgb( const in vec3 normal ) {\\n return normalize( normal ) * 0.5 + 0.5;\\n}\\n\\nvoid updateFragmentColor(\\n int renderMode, vec4 color, float treeIndex, \\n vec3 normal, float depth, sampler2D matCapTexture, \\n int geometryType) {\\n if (renderMode == RenderTypeColor_0 || renderMode == RenderTypeEffects_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n hsv.z = min(0.5 * hsv.z + 0.5, 1.0);\\n vec3 colorRGB = hsv2rgb(hsv);\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec4 albedo = vec4(colorRGB * (0.4 + 0.6 * amplitude), 1.0);\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec4 mc = vec4(texture2D(matCapTexture, cap).rgb, 1.0);\\n \\n gl_FragColor = vec4(albedo.rgb * mc.rgb * 1.7, color.a);\\n } else if (renderMode == RenderTypeGhost_0) {\\n float amplitude = max(0.0, dot(normal, vec3(0.0, 0.0, 1.0)));\\n vec3 albedo = min(vec3(0.8) * (0.4 + 0.6 * amplitude), 1.0);\\n gl_FragColor = vec4(albedo, 0.2);\\n } else if (renderMode == RenderTypeDepthBufferOnly) {\\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n } else if (renderMode == RenderTypePackColorAndNormal_0) {\\n vec3 hsv = rgb2hsv(color.rgb);\\n float a = 0.0;\\n if (hsv.y > 0.01) {\\n if (hsv.z > 0.5) {\\n // light color\\n a = (0.55 + hsv.x * 0.45);\\n } else {\\n // dark color\\n a = (0.1 + hsv.x * 0.45);\\n }\\n } else {\\n // no saturation - grayscale\\n a = hsv.z * 0.09;\\n }\\n gl_FragColor = vec4(packNormalToRgb(normal.rgb), a);\\n } else if (renderMode == RenderTypeNormal_0) {\\n gl_FragColor = vec4(packNormalToRgb(normal), 1.0);\\n } else if (renderMode == RenderTypeTreeIndex_0) {\\n gl_FragColor = vec4(packIntToColor(treeIndex), 1.0);\\n } else if (renderMode == RenderTypeDepth_0) {\\n gl_FragColor = packDepthToRGBA(depth);\\n } else if (renderMode == RenderTypeLOD) {\\n bool isHighDetail = geometryType != GeometryType.Quad;\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n gl_FragColor = isHighDetail ? vec4(vec3(0.0, 1.0, 0.0) * mc, color.a) : vec4(vec3(1.0, 1.0, 0.0) * mc, color.a);\\n } else if (renderMode == RenderTypeGeometryType) {\\n vec2 cap = normal.xy * 0.5 + 0.5;\\n vec3 mc = texture2D(matCapTexture, cap).rgb * 1.5;\\n vec3 geometryColor = \\n float(geometryType == 1) * vec3(1.0, 0.0, 0.0) + // Quads\\n float(geometryType == 2) * vec3(0.0, 1.0, 0.0) + // Primitives\\n float(geometryType == 3) * vec3(0.0, 0.0, 1.0) + // Triangle meshes\\n float(geometryType == 4) * vec3(1.0, 1.0, 0.0); // Instance meshes\\n gl_FragColor = vec4(geometryColor * mc, color.a);\\n } else {\\n // Unknown render mode - should not happen. \\n gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\\n }\\n}\\n\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\n\\nconst int RenderTypeColor_1 = 1;\\nconst int RenderTypeNormal_1 = 2;\\nconst int RenderTypeTreeIndex_1 = 3;\\nconst int RenderTypePackColorAndNormal_1 = 4;\\nconst int RenderTypeDepth_1 = 5;\\nconst int RenderTypeEffects_1 = 6;\\nconst int RenderTypeGhost_1 = 7;\\n\\nbool determineVisibility(sampler2D visibilityTexture, vec2 textureSize, float treeIndex, int renderMode) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 visible = texture2D(visibilityTexture, treeIndexUv);\\n\\n // Byte layout: \\n // [isVisible, renderInFront, renderGhosted, outlineColor0, outlineColor1, outlineColor2, unused, unused]\\n float byteUnwrapped = floor((visible.a * 255.0) + 0.5);\\n \\n bool isVisible = floatBitsSubset(byteUnwrapped, 0, 1) == 1.0;\\n bool renderInFront = floatBitsSubset(byteUnwrapped, 1, 2) == 1.0;\\n bool renderGhosted = floatBitsSubset(byteUnwrapped, 2, 3) == 1.0;\\n\\n return \\n // In ghost mode\\n ((renderMode == RenderTypeGhost_1) && isVisible && renderGhosted) ||\\n // Not ghost mode\\n ((renderMode != RenderTypeGhost_1) && \\n !renderGhosted && isVisible && (renderInFront || renderMode != RenderTypeEffects_1));\\n}\\n\\nvec4 determineColor(vec3 originalColor, sampler2D colorDataTexture, vec2 textureSize, float treeIndex) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n\\n float dataTextureWidth = textureSize.x;\\n float dataTextureHeight = textureSize.y;\\n\\n float u = mod(treeIndex, dataTextureWidth);\\n float v = floor(treeIndex / dataTextureWidth);\\n float uCoord = (u + 0.5) / dataTextureWidth;\\n float vCoord = (v + 0.5) / dataTextureHeight; // invert Y axis\\n vec2 treeIndexUv = vec2(uCoord, vCoord);\\n vec4 overrideColor = texture2D(colorDataTexture, treeIndexUv);\\n\\n if (any(greaterThan(overrideColor.rgb, vec3(0.0)))) {\\n return overrideColor;\\n }\\n\\n return vec4(originalColor.rgb, overrideColor.a);\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nuniform sampler2D colorDataTexture;\\nuniform sampler2D overrideVisibilityPerTreeIndex;\\nuniform sampler2D matCapTexture;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform int renderMode;\\n\\nvarying vec3 vViewPosition;\\n\\nvoid main() {\\n if (!determineVisibility(colorDataTexture, treeIndexTextureSize, v_treeIndex, renderMode)) {\\n discard;\\n }\\n\\n if (isSliced(vViewPosition)) {\\n discard;\\n }\\n\\n vec4 color = determineColor(v_color, colorDataTexture, treeIndexTextureSize, v_treeIndex);\\n vec3 normal = normalize(v_normal);\\n updateFragmentColor(renderMode, color, v_treeIndex, normal, gl_FragCoord.z, matCapTexture, GeometryType.Primitive);\\n}\\n\";","export default \"#define GLSLIFY 1\\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\\nfloat unpackVec4ToFloat( vec4 packedFloat)\\n{\\n vec4 rgba = packedFloat;\\n float sign = 1.0 - step(128.0, rgba.x) * 2.0;\\n float exponent = 2.0 * mod(rgba.x, 128.0) + step(128.0, rgba.y) - 127.0;\\n if (exponent == -127.0) return 0.0;\\n float mantissa = mod(rgba.y, 128.0) * 65536.0 + rgba.z * 256.0 + rgba.w + 8388608.0;\\n return sign * exp2(exponent - 23.0) * mantissa; \\n}\\n\\nfloat unpackFloatFromRGBATexel(vec4 texel){\\n float byteValueR = floor((texel.r * 255.0) + 0.5);\\n float byteValueG = floor((texel.g * 255.0) + 0.5);\\n float byteValueB = floor((texel.b * 255.0) + 0.5);\\n float byteValueA = floor((texel.a * 255.0) + 0.5);\\n\\n return unpackVec4ToFloat(vec4(byteValueR, byteValueG, byteValueB, byteValueA));\\n}\\n\\nmat4 determineMatrixOverride(\\n float treeIndex, \\n vec2 treeIndexTextureSize, \\n sampler2D transformOverrideIndexTexture, \\n vec2 transformOverrideTextureSize, \\n sampler2D transformOverrideTexture\\n) {\\n\\n treeIndex = floor(treeIndex + 0.5);\\n float dataTextureWidth = treeIndexTextureSize.x;\\n float dataTextureHeight = treeIndexTextureSize.y;\\n\\n float xTreeIndexTextureCoord = mod(treeIndex, dataTextureWidth);\\n float yTreeIndexTextureCoord = floor(treeIndex / dataTextureWidth);\\n\\n vec2 indexUV = vec2((xTreeIndexTextureCoord + 0.5) / dataTextureWidth, (yTreeIndexTextureCoord + 0.5) / dataTextureHeight);\\n\\n vec3 indexTexel = texture2D(transformOverrideIndexTexture, indexUV).rgb;\\n\\n float index = floor(indexTexel.r * 256.0) * 65536.0 + floor(indexTexel.g * 256.0) * 256.0 + floor(indexTexel.b * 256.0);\\n \\n \\n if(index == 0.0){\\n return mat4(\\n 1.0, 0.0, 0.0, 0.0,\\n 0.0, 1.0, 0.0, 0.0,\\n 0.0, 0.0, 1.0, 0.0,\\n 0.0, 0.0, 0.0, 1.0\\n );\\n }\\n\\n index = index - 1.0;\\n float overridesPerRow = transformOverrideTextureSize.x / 16.0;\\n\\n float xOverrideTextureCoord = mod(index, overridesPerRow);\\n float yOverrideTextureCoord = floor(index / overridesPerRow);\\n\\n float cellWidth = 1.0 / transformOverrideTextureSize.x;\\n float cellHeight = 1.0 / transformOverrideTextureSize.y;\\n\\n float overrideU = (xOverrideTextureCoord / overridesPerRow) + cellWidth / 2.0;\\n float overrideV = (yOverrideTextureCoord / transformOverrideTextureSize.y) + cellHeight / 2.0;\\n\\n vec2 overrideUV = vec2(overrideU, overrideV); \\n\\n float matrixElements[12];\\n\\n for(int i = 0; i < 12; i++){\\n matrixElements[i] = unpackFloatFromRGBATexel(texture2D(transformOverrideTexture, overrideUV + vec2(float(i) * cellWidth, 0.0)));\\n }\\n \\n return mat4(\\n matrixElements[0], matrixElements[4], matrixElements[8], 0,\\n matrixElements[1], matrixElements[5], matrixElements[9], 0,\\n matrixElements[2], matrixElements[6], matrixElements[10], 0,\\n matrixElements[3], matrixElements[7], matrixElements[11], 1\\n );\\n}\\n\\nuniform mat4 inverseModelMatrix;\\n\\nattribute float a_treeIndex;\\nattribute vec3 a_color;\\nattribute vec3 a_vertex1;\\nattribute vec3 a_vertex2;\\nattribute vec3 a_vertex3;\\nattribute vec3 a_vertex4;\\n\\nvarying float v_treeIndex;\\nvarying vec3 v_color;\\nvarying vec3 v_normal;\\n\\nvarying vec3 vViewPosition;\\n\\nuniform vec2 treeIndexTextureSize;\\n\\nuniform sampler2D transformOverrideIndexTexture;\\n\\nuniform vec2 transformOverrideTextureSize; \\nuniform sampler2D transformOverrideTexture;\\n\\nvoid main() {\\n vec3 transformed;\\n // reduce the avarage branchings\\n if (position.x < 1.5) {\\n transformed = position.x == 0.0 ? a_vertex1 : a_vertex2;\\n } else {\\n transformed = position.x == 2.0 ? a_vertex3 : a_vertex4;\\n }\\n\\n mat4 treeIndexWorldTransform = determineMatrixOverride(\\n a_treeIndex, \\n treeIndexTextureSize, \\n transformOverrideIndexTexture, \\n transformOverrideTextureSize, \\n transformOverrideTexture\\n );\\n\\n vec3 objectNormal = cross(a_vertex1 - a_vertex2, a_vertex1 - a_vertex3);\\n\\n v_treeIndex = a_treeIndex;\\n v_color = a_color;\\n v_normal = normalMatrix * normalize(inverseModelMatrix * treeIndexWorldTransform * modelMatrix * vec4(objectNormal, 0.0)).xyz;\\n\\n vec4 mvPosition = viewMatrix * treeIndexWorldTransform * modelMatrix * vec4( transformed, 1.0 );\\n vViewPosition = mvPosition.xyz;\\n gl_Position = projectionMatrix * mvPosition;\\n}\\n\";","export default \"#define GLSLIFY 1\\nfloat floatBitsSubset(float inNumber, int fromLeastSignificantBitIndex, int toMostSignificantBitIndex) {\\n float r = float(fromLeastSignificantBitIndex);\\n float l = float(toMostSignificantBitIndex);\\n\\n float bitShift = pow(2.0, r);\\n return mod(((inNumber - mod(inNumber, bitShift)) / bitShift), pow(2.0, l - r));\\n}\\n\\n/*\\n\\nExample:\\n\\nGet the value from bit 2 to 4 (not inclusive)\\n\\ninput:\\ninNumber = 173 = 1010_1101 , from=2, to=4\\n\\nexpected output = 1010_|11|01 = 3\\n\\n1) subtract any bits in the least significant bit-subset\\n\\n mod(inNumber=173, pow(2.0, from=2)) = mod(inNumber, 4) = 1\\n \\n inNumber - 1 = 172\\n\\n2) bitshift such that we remove the least significant bit-subset\\n this is guaranteed to be devisible since we subtracted the remainder\\n\\n (inNumber=172) / pow(2.0, from=2) = 172 / 4 = 43 = 0010_1011\\n\\n3) lastly, remove the most significant bit-subset\\n\\n mod((inNumber=43), pow(2.0, to=4 - from=2) = mod(43, 4)\\n\\n mod(43, 4) = 3\\n\\n or in binary notation: 0000_0011 which is the expected result.\\n\\n*/ \\nmat3 G[9];\\n// hard coded matrix values!!!! as suggested in https://github.com/neilmendoza/ofxPostProcessing/blob/master/src/EdgePass.cpp#L45\\nconst mat3 g0 = mat3( 0.3535533845424652, 0, -0.3535533845424652, 0.5, 0, -0.5, 0.3535533845424652, 0, -0.3535533845424652 );\\nconst mat3 g1 = mat3( 0.3535533845424652, 0.5, 0.3535533845424652, 0, 0, 0, -0.3535533845424652, -0.5, -0.3535533845424652 );\\nconst mat3 g2 = mat3( 0, 0.3535533845424652, -0.5, -0.3535533845424652, 0, 0.3535533845424652, 0.5, -0.3535533845424652, 0 );\\nconst mat3 g3 = mat3( 0.5, -0.3535533845424652, 0, -0.3535533845424652, 0, 0.3535533845424652, 0, 0.3535533845424652, -0.5 );\\nconst mat3 g4 = mat3( 0, -0.5, 0, 0.5, 0, 0.5, 0, -0.5, 0 );\\nconst mat3 g5 = mat3( -0.5, 0, 0.5, 0, 0, 0, 0.5, 0, -0.5 );\\nconst mat3 g6 = mat3( 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.6666666865348816, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204 );\\nconst mat3 g7 = mat3( -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, 0.6666666865348816, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408 );\\nconst mat3 g8 = mat3( 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408 );\\n\\nfloat edgeDetectionFilter(sampler2D baseTexture, vec2 uv, vec2 resolution) {\\n\\n vec2 texel = vec2(1.0 / resolution.x, 1.0 / resolution.y);\\n\\n\\tG[0] = g0,\\n\\tG[1] = g1,\\n\\tG[2] = g2,\\n\\tG[3] = g3,\\n\\tG[4] = g4,\\n\\tG[5] = g5,\\n\\tG[6] = g6,\\n\\tG[7] = g7,\\n\\tG[8] = g8;\\n\\n\\tmat3 I;\\n\\tfloat cnv[9];\\n\\tvec3 neighbour;\\n\\n\\t/* fetch the 3x3 neighbourhood and use the RGB vector's length as intensity value */\\n\\tfor (int i=0; i<3; i++) {\\n\\t\\tfor (int j=0; j<3; j++) {\\n\\t\\t\\tneighbour = texture2D(baseTexture, uv + texel * vec2(float(i)-1.0,float(j)-1.0) ).rgb;\\n\\t\\t\\tI[i][j] = length(neighbour);\\n\\t\\t}\\n\\t}\\n\\n\\t/* calculate the convolution values for all the masks */\\n\\tfor (int i=0; i<9; i++) {\\n\\t\\tfloat dp3 = dot(G[i][0], I[0]) + dot(G[i][1], I[1]) + dot(G[i][2], I[2]);\\n\\t\\tcnv[i] = dp3 * dp3;\\n\\t}\\n\\n\\tfloat M = (cnv[0] + cnv[1]) + (cnv[2] + cnv[3]);\\n\\tfloat S = (cnv[4] + cnv[5]) + (cnv[6] + cnv[7]) + (cnv[8] + M);\\n\\n float edgeStrength = sqrt(M/S);\\n\\n return edgeStrength;\\n}\\n\\n#include <packing>\\n\\nvarying vec2 vUv;\\n\\nvarying vec2 vUv0;\\nvarying vec2 vUv1;\\nvarying vec2 vUv2;\\nvarying vec2 vUv3;\\n\\nuniform sampler2D tFront;\\nuniform sampler2D tFrontDepth;\\n\\nuniform sampler2D tBack;\\nuniform sampler2D tBackDepth;\\n\\nuniform sampler2D tCustom;\\nuniform sampler2D tCustomDepth;\\n\\nuniform sampler2D tGhost;\\nuniform sampler2D tGhostDepth;\\n\\nuniform sampler2D tOutlineColors;\\n\\nuniform float cameraNear;\\nuniform float cameraFar;\\n\\nuniform vec2 resolution;\\n\\nuniform float edgeStrengthMultiplier;\\nuniform float edgeGrayScaleIntensity;\\n\\nconst float infinity = 1e20;\\n\\nfloat computeFloatEncodedOutlineIndex(float bitEncodedFloat){\\n return floatBitsSubset(floor((bitEncodedFloat * 255.0) + 0.5), 3, 6);\\n}\\n\\nvec4 computeNeighborOutlineIndices(sampler2D colorTexture){\\n float outlineIndex0 = computeFloatEncodedOutlineIndex(texture2D(colorTexture, vUv0).a);\\n float outlineIndex1 = computeFloatEncodedOutlineIndex(texture2D(colorTexture, vUv1).a);\\n float outlineIndex2 = computeFloatEncodedOutlineIndex(texture2D(colorTexture, vUv2).a);\\n float outlineIndex3 = computeFloatEncodedOutlineIndex(texture2D(colorTexture, vUv3).a);\\n\\n return vec4(outlineIndex0, outlineIndex1, outlineIndex2, outlineIndex3);\\n}\\n\\nfloat toViewZ(float depth, float near, float far){\\n float normalizedDepth = depth * 2.0 - 1.0;\\n return 2.0 * near * far / (far + near - normalizedDepth * (far - near)); \\n}\\n\\nvec4 computeNeighborAlphas(sampler2D colorTexture){\\n float alpha0 = texture2D(colorTexture, vUv0).a;\\n float alpha1 = texture2D(colorTexture, vUv1).a;\\n float alpha2 = texture2D(colorTexture, vUv2).a;\\n float alpha3 = texture2D(colorTexture, vUv3).a;\\n\\n return vec4(alpha0, alpha1, alpha2, alpha3);\\n}\\n\\nvoid main() {\\n vec4 frontAlbedo = texture2D(tFront, vUv);\\n vec4 backAlbedo = texture2D(tBack, vUv);\\n vec4 customAlbedo = texture2D(tCustom, vUv);\\n vec4 ghostAlbedo = texture2D(tGhost, vUv);\\n\\n float frontDepth = texture2D(tFrontDepth, vUv).r;\\n float backDepth = texture2D(tBackDepth, vUv).r; \\n float customDepth = texture2D(tCustomDepth, vUv).r;\\n float ghostDepth = texture2D(tGhostDepth, vUv).r;\\n\\n // This is a hack to make sure that all textures are initialized\\n // If a texture is unused, it will have a clear value of 0.0.\\n // Without this we've seen issues with MSAA where resizing render targets\\n // causes depth to cleared to either 1 or 0 depending on the device/browser\\n customDepth = customDepth > 0.0 ? customDepth : 1.0; \\n backDepth = backDepth > 0.0 ? backDepth : 1.0;\\n ghostDepth = ghostDepth > 0.0 ? ghostDepth : 1.0;\\n frontDepth = frontDepth > 0.0 ? frontDepth : 1.0; \\n\\n if(all(greaterThanEqual(vec4(backDepth, customDepth, ghostDepth, frontDepth), vec4(1.0)))){\\n discard;\\n }\\n \\n // Decompose and clamp \\\"ghost\\\" color\\n vec4 clampedGhostAlbedo = vec4(max(ghostAlbedo.rgb, 0.5), min(ghostAlbedo.a, 0.8));\\n\\n float frontOutlineIndex = computeFloatEncodedOutlineIndex(frontAlbedo.a);\\n vec4 frontNeighborIndices = computeNeighborOutlineIndices(tFront);\\n\\n // There exsists fragments of rendered objects within the edge width that should have border\\n if(any(equal(frontNeighborIndices, vec4(0.0))) && frontOutlineIndex > 0.0) \\n { \\n float borderColorIndex = max(max(frontNeighborIndices.x, frontNeighborIndices.y), max(frontNeighborIndices.z, frontNeighborIndices.w));\\n gl_FragColor = texture2D(tOutlineColors, vec2(0.125 * borderColorIndex + (0.125 / 2.0), 0.5));\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth) \\n gl_FragDepthEXT = frontDepth;\\n#endif\\n return;\\n }\\n\\n // texture has drawn fragment\\n if(frontDepth < 1.0){\\n float customDepthTest = step(customDepth, backDepth); // zero if back is in front\\n\\n float a = customDepthTest > 0.0 ? ceil(customAlbedo.a) * 0.5 : ceil(backAlbedo.a) * 0.5;\\n\\n gl_FragColor = vec4(frontAlbedo.rgb, 1.0) * (1.0 - a) + (vec4(backAlbedo.rgb, 1.0) * (1.0 - customDepthTest) + vec4(customAlbedo.rgb, 1.0) * customDepthTest) * a;\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth) \\n gl_FragDepthEXT = texture2D(tFrontDepth, vUv).r;\\n#endif\\n return;\\n }\\n\\n if (customDepth >= backDepth) {\\n float backOutlineIndex = computeFloatEncodedOutlineIndex(backAlbedo.a);\\n vec4 backNeighborIndices = computeNeighborOutlineIndices(tBack);\\n\\n if( any(equal(backNeighborIndices, vec4(0.0))) && backOutlineIndex > 0.0) \\n { \\n float borderColorIndex = max(max(backNeighborIndices.x, backNeighborIndices.y), max(backNeighborIndices.z, backNeighborIndices.w));\\n gl_FragColor = texture2D(tOutlineColors, vec2(0.125 * borderColorIndex + (0.125 / 2.0), 0.5));\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth)\\n gl_FragDepthEXT = texture2D(tBackDepth, vUv).r;\\n#endif\\n return;\\n }\\n }\\n \\n float edgeStrength = 0.0;\\n#if defined(EDGES)\\n if (!any(equal(computeNeighborAlphas(tBack), vec4(0.0)))) {\\n float depthEdge = toViewZ(backDepth, cameraNear, cameraFar);\\n edgeStrength = (1.0 - smoothstep(10.0, 40.0, depthEdge)) * edgeDetectionFilter(tBack, vUv, resolution) * edgeStrengthMultiplier;\\n }\\n#endif\\n\\n // Combine color from ghost, back and custom object\\n vec4 color = backAlbedo;\\n float depth = backDepth;\\n if (customDepth < backDepth && ghostDepth == 1.0) {\\n color = vec4(customAlbedo.rgb * customAlbedo.a + (1.0 - customAlbedo.a) * backAlbedo.rgb, 1.0);\\n depth = customDepth;\\n edgeStrength = 0.0;\\n } else if (customDepth < backDepth && ghostDepth < 1.0) {\\n float s = (1.0 - step(backDepth, ghostDepth)) * clampedGhostAlbedo.a;\\n vec3 modelAlbedo = mix(backAlbedo.rgb, clampedGhostAlbedo.rgb, s);\\n color = vec4(customAlbedo.rgb * customAlbedo.a + (1.0 - customAlbedo.a) * modelAlbedo.rgb, 1.0);\\n depth = customDepth;\\n edgeStrength = 0.0;\\n } else {\\n float s = (1.0 - step(backDepth, ghostDepth)) * clampedGhostAlbedo.a;\\n color = vec4(mix(backAlbedo.rgb, clampedGhostAlbedo.rgb, s), backAlbedo.a);\\n depth = mix(backDepth, ghostDepth, s);\\n }\\n \\n gl_FragColor = color * (1.0 - edgeStrength) + vec4(vec3(edgeGrayScaleIntensity) * edgeStrength, 1.0);\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth) \\n gl_FragDepthEXT = depth;\\n#endif\\n}\\n\";","export default \"#define GLSLIFY 1\\nvarying vec2 vUv;\\n\\n// selection outline\\nuniform vec2 texelSize;\\nvarying vec2 vUv0;\\nvarying vec2 vUv1;\\nvarying vec2 vUv2;\\nvarying vec2 vUv3;\\n\\nvoid main() {\\n vUv = uv;\\n\\n // selection outline\\n vUv0 = vec2(uv.x + texelSize.x, uv.y);\\n vUv1 = vec2(uv.x - texelSize.x, uv.y);\\n vUv2 = vec2(uv.x, uv.y + texelSize.y);\\n vUv3 = vec2(uv.x, uv.y - texelSize.y);\\n\\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\\n}\";","export default \"#define GLSLIFY 1\\n/*!\\n *\\n * Adapted from:\\n * https://github.com/mattdesl/three-shader-fxaa\\n * MIT License (MIT) Copyright (c) 2014 Matt DesLauriers\\n *\\n */\\n\\nvarying vec2 v_uv;\\nvarying vec2 v_fragCoord;\\nvarying vec2 v_rgbNW;\\nvarying vec2 v_rgbNE;\\nvarying vec2 v_rgbSW;\\nvarying vec2 v_rgbSE;\\nvarying vec2 v_rgbM;\\n\\nuniform vec2 inverseResolution;\\nuniform vec2 resolution;\\nuniform sampler2D tDiffuse;\\nuniform sampler2D tDepth;\\n\\n#ifndef FXAA_REDUCE_MIN\\n #define FXAA_REDUCE_MIN (1.0/ 128.0)\\n#endif\\n#ifndef FXAA_REDUCE_MUL\\n #define FXAA_REDUCE_MUL (1.0 / 8.0)\\n#endif\\n#ifndef FXAA_SPAN_MAX\\n #define FXAA_SPAN_MAX 8.0\\n#endif\\n\\nvec4 fxaa(sampler2D tex, vec2 fragCoord,\\n vec2 resolution, vec2 inverseResolution,\\n vec2 v_rgbNW, vec2 v_rgbNE,\\n vec2 v_rgbSW, vec2 v_rgbSE,\\n vec2 v_rgbM) {\\n vec4 color;\\n\\n vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;\\n vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;\\n vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;\\n vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;\\n vec4 texColor = texture2D(tex, v_rgbM);\\n vec3 rgbM = texColor.xyz;\\n\\n vec3 luma = vec3(0.299, 0.587, 0.114);\\n float lumaNW = dot(rgbNW, luma);\\n float lumaNE = dot(rgbNE, luma);\\n float lumaSW = dot(rgbSW, luma);\\n float lumaSE = dot(rgbSE, luma);\\n float lumaM = dot(rgbM, luma);\\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\\n\\n mediump vec2 dir;\\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\\n\\n float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *\\n (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\\n\\n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\\n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\\n dir * rcpDirMin));\\n\\n vec4 rgbA = 0.5 * (\\n texture2D(tex, inverseResolution * (v_fragCoord + dir * (1.0 / 3.0 - 0.5))) +\\n texture2D(tex, inverseResolution * (v_fragCoord + dir * (2.0 / 3.0 - 0.5))));\\n vec4 rgbB = rgbA * 0.5 + 0.25 * (\\n texture2D(tex, inverseResolution * (v_fragCoord + dir * -0.5)) +\\n texture2D(tex, inverseResolution * (v_fragCoord + dir * 0.5)));\\n\\n float lumaB = dot(rgbB.rgb, luma);\\n if ((lumaB < lumaMin) || (lumaB > lumaMax)) {\\n color = rgbA;\\n } else {\\n color = rgbB;\\n }\\n return color;\\n}\\n\\nvoid main() {\\n gl_FragColor = fxaa(tDiffuse, v_fragCoord, \\n resolution, inverseResolution, \\n v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\\n#if defined(gl_FragDepthEXT) || defined(GL_EXT_frag_depth)\\n gl_FragDepthEXT = texture2D(tDepth, v_uv).r;\\n#endif\\n}\\n\";","export default \"#define GLSLIFY 1\\n/*!\\n *\\n * Adapted from:\\n * https://github.com/mattdesl/three-shader-fxaa\\n * MIT License (MIT) Copyright (c) 2014 Matt DesLauriers\\n *\\n */\\n\\nuniform vec2 resolution;\\nuniform vec2 inverseResolution;\\n\\nvarying vec2 v_uv;\\nvarying vec2 v_fragCoord;\\nvarying vec2 v_rgbNW;\\nvarying vec2 v_rgbNE;\\nvarying vec2 v_rgbSW;\\nvarying vec2 v_rgbSE;\\nvarying vec2 v_rgbM;\\n\\nvoid main() {\\n v_fragCoord = uv * resolution;\\n v_rgbNW = (v_fragCoord + vec2(-1.0, -1.0)) * inverseResolution;\\n v_rgbNE = (v_fragCoord + vec2(1.0, -1.0)) * inverseResolution;\\n v_rgbSW = (v_fragCoord + vec2(-1.0, 1.0)) * inverseResolution;\\n v_rgbSE = (v_fragCoord + vec2(1.0, 1.0)) * inverseResolution;\\n v_rgbM = vec2(v_fragCoord * inverseResolution);\\n v_uv = uv;\\n\\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\\n}\\n\";","export default \"#define GLSLIFY 1\\nvarying vec2 vUv;\\n\\nuniform mat4 projMatrix;\\nuniform mat4 inverseProjectionMatrix;\\n\\nuniform vec3 kernel[MAX_KERNEL_SIZE];\\n\\nuniform sampler2D tDepth;\\nuniform sampler2D tNoise;\\n\\nuniform vec2 resolution;\\n\\nuniform float sampleRadius;\\nuniform float bias;\\n\\nvec3 viewPosFromDepth(float depth, vec2 uv) {\\n // Depth to clip space: [0, 1] -> [-1, 1]\\n float z = depth * 2.0 - 1.0;\\n\\n // Fragment in clip space\\n vec4 clipSpacePosition = vec4(uv * 2.0 - 1.0, z, 1.0);\\n vec4 viewSpacePosition = inverseProjectionMatrix * clipSpacePosition;\\n\\n // Perspective division\\n viewSpacePosition /= viewSpacePosition.w;\\n\\n return viewSpacePosition.xyz;\\n}\\n\\nvec3 computeWorldNormalFromDepth(sampler2D depthTexture, vec2 resolution, vec2 uv, float sampleDepth){\\n float dx = 1.0 / resolution.x;\\n float dy = 1.0 / resolution.y;\\n\\n vec2 uv1 = uv + vec2(dx, 0.0); // right\\n float d1 = texture2D(depthTexture, uv1).r; \\n\\n vec2 uv2 = uv + vec2(0.0, dy); // up\\n float d2 = texture2D(depthTexture, uv2).r;\\n\\n vec2 uv3 = uv + vec2(-dx, 0.0); // left\\n float d3 = texture2D(depthTexture, uv3).r;\\n\\n vec2 uv4 = uv + vec2(0.0, -dy); // down\\n float d4 = texture2D(depthTexture, uv4).r;\\n\\n bool horizontalSampleCondition = abs(d1 - sampleDepth) < abs(d3 - sampleDepth);\\n\\n float horizontalSampleDepth = horizontalSampleCondition ? d1 : d3;\\n vec2 horizontalSampleUv = horizontalSampleCondition ? uv1 : uv3;\\n\\n bool verticalSampleCondition = abs(d2 - sampleDepth) < abs(d4 - sampleDepth);\\n\\n float verticalSampleDepth = verticalSampleCondition ? d2 : d4;\\n vec2 verticalSampleUv = verticalSampleCondition ? uv2 : uv4;\\n\\n vec3 viewPos = viewPosFromDepth(sampleDepth, vUv);\\n \\n vec3 viewPos1 = (horizontalSampleCondition == verticalSampleCondition) ? viewPosFromDepth(horizontalSampleDepth, horizontalSampleUv) : viewPosFromDepth(verticalSampleDepth, verticalSampleUv);\\n vec3 viewPos2 = (horizontalSampleCondition == verticalSampleCondition) ? viewPosFromDepth(verticalSampleDepth, verticalSampleUv) : viewPosFromDepth(horizontalSampleDepth, horizontalSampleUv);\\n\\n return normalize(cross(viewPos1 - viewPos, viewPos2 - viewPos));\\n}\\n\\nvoid main(){\\n float d = texture2D(tDepth, vUv).r;\\n\\n vec3 viewNormal = computeWorldNormalFromDepth(tDepth, resolution, vUv, d);\\n\\n vec3 viewPosition = viewPosFromDepth(d, vUv);\\n\\n vec2 noiseScale = vec2( resolution.x / 128.0, resolution.y / 128.0 );\\n vec3 randomVec = normalize(texture2D(tNoise, vUv * noiseScale).xyz);\\n\\n vec3 tangent = normalize(randomVec - viewNormal * dot(randomVec, viewNormal));\\n\\n vec3 bitangent = cross(viewNormal, tangent);\\n\\n mat3 TBN = mat3(tangent, bitangent, viewNormal);\\n\\n float occlusion = 0.0;\\n\\n for (int i = 0; i < MAX_KERNEL_SIZE; i++){\\n \\n vec3 sampleVector = TBN * kernel[i];\\n sampleVector = viewPosition + sampleVector * sampleRadius;\\n\\n vec4 offset = projMatrix * vec4(sampleVector, 1.0);\\n offset.xyz /= offset.w;\\n offset.xyz = offset.xyz * 0.5 + 0.5;\\n\\n float realDepth = texture2D(tDepth, offset.xy).r;\\n vec3 realPos = viewPosFromDepth(realDepth, offset.xy);\\n\\n float rangeCheck = smoothstep(0.0, 1.0, sampleRadius / length(viewPosition - realPos));\\n\\n occlusion += (realPos.z >= sampleVector.z + bias ? 1.0 : 0.0) * rangeCheck;\\n }\\n\\n float occlusionFactor = 1.0 - clamp(occlusion / float(MAX_KERNEL_SIZE), 0.0, 1.0);\\n\\n gl_FragColor = vec4(vec3(occlusionFactor), 1.0);\\n}\";","export default \"#define GLSLIFY 1\\n// Copyright Cognite (C) 2019 Cognite\\n//\\n// Efficient Gaussian blur based on technique described by Daniel Rákos in\\n// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/\\n//\\n\\nvarying vec2 vUv;\\n\\nuniform sampler2D tDiffuse;\\nuniform sampler2D tAmbientOcclusion;\\n\\nuniform vec2 resolution;\\n\\nvoid main() {\\n float blurredAO = 0.5 * (\\n 2.0 * texture2D(tAmbientOcclusion, vUv).r * 0.2270270270 +\\n texture2D(tAmbientOcclusion, vUv + vec2(1.3746153846, 0.0) / resolution.x).r * 0.3162162162 +\\n texture2D(tAmbientOcclusion, vUv + vec2(3.2307692308, 0.0) / resolution.x).r * 0.0702702703 +\\n texture2D(tAmbientOcclusion, vUv - vec2(1.3746153846, 0.0) / resolution.x).r * 0.3162162162 +\\n texture2D(tAmbientOcclusion, vUv - vec2(3.2307692308, 0.0) / resolution.x).r * 0.0702702703 +\\n texture2D(tAmbientOcclusion, vUv + vec2(0.0, 1.3746153846) / resolution.y).r * 0.3162162162 +\\n texture2D(tAmbientOcclusion, vUv + vec2(0.0, 3.2307692308) / resolution.y).r * 0.0702702703 +\\n texture2D(tAmbientOcclusion, vUv - vec2(0.0, 1.3746153846) / resolution.y).r * 0.3162162162 +\\n texture2D(tAmbientOcclusion, vUv - vec2(0.0, 3.2307692308) / resolution.y).r * 0.0702702703\\n );\\n\\n gl_FragColor = vec4(texture2D(tDiffuse, vUv).rgb * blurredAO, 1.0);\\n}\\n\\n\";","export default \"#define GLSLIFY 1\\n// From http://www.science-and-fiction.org/rendering/noise.html\\nfloat rand2d(in vec2 co){\\n return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);\\n}\\n\\n#if NUM_CLIPPING_PLANES > 0\\nuniform vec4 clippingPlanes[NUM_CLIPPING_PLANES];\\n#endif\\n\\nbool isSliced(vec3 point) {\\n#if NUM_CLIPPING_PLANES > 0\\n vec3 pointFlipped = -point;\\n vec4 plane;\\n\\n for (int i = 0; i < UNION_CLIPPING_PLANES; i++) {\\n plane = clippingPlanes[i];\\n if (dot(pointFlipped, plane.xyz) > plane.w) return true;\\n }\\n#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n bool clipped = true;\\n for ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n plane = clippingPlanes[ i ];\\n clipped = (dot(pointFlipped, plane.xyz) > plane.w) && clipped;\\n }\\n if ( clipped ) return true;\\n#endif\\n#endif\\n return false;\\n}\\n\\nvarying mediump vec3 v_color;\\nvarying lowp float v_coverageFactor;\\nvarying lowp float v_visible;\\nvarying lowp vec2 v_seed;\\n\\nvarying vec3 v_viewPosition;\\n\\nvoid main() {\\n \\n if(v_visible != 1.0 || isSliced(v_viewPosition)){\\n discard;\\n }\\n\\n float v = rand2d(gl_FragCoord.xy + v_seed);\\n if (v >= v_coverageFactor) {\\n discard;\\n }\\n\\n gl_FragColor = vec4(v_color, 1.0);\\n}\\n\";","export default \"#define GLSLIFY 1\\n/**\\n * Packs the integer part of the number given to a RGB color.\\n */\\nvec3 packIntToColor(float number) {\\n float r = floor(number / (255.0 * 255.0)) / 255.0;\\n float g = mod(floor(number / 255.0), 255.0) / 255.0;\\n float b = mod(number, 255.0) / 255.0;\\n return vec3(r, g, b);\\n}\\n\\nattribute mediump float a_sectorId;\\nattribute lowp vec3 a_coverageFactor;\\nattribute lowp float a_visible;\\n\\nvarying mediump vec3 v_color;\\nvarying lowp float v_coverageFactor;\\nvarying lowp vec2 v_seed;\\nvarying lowp float v_visible;\\n\\nvarying vec3 v_viewPosition;\\n\\nvoid main()\\n{\\n v_visible = a_visible;\\n v_color = packIntToColor(a_sectorId);\\n v_coverageFactor = abs(dot(a_coverageFactor, normal));\\n // A seed to ensure that two overlapping sectors A and B \\n // doesn't produce the same noise pattern\\n v_seed = vec2(a_sectorId / 255.0, a_sectorId / 65025.0);\\n\\n vec4 mvPosition = modelViewMatrix * instanceMatrix * vec4( position, 1.0 );\\n\\n v_viewPosition = mvPosition.xyz;\\n\\n gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position, 1.0);\\n}\\n\";","module.exports = require(\"lodash/merge\");","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport enum LevelOfDetail {\n Discarded,\n Simple,\n Detailed\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport enum RenderMode {\n Color = 1,\n Normal,\n TreeIndex,\n PackColorAndNormal,\n Depth,\n Effects,\n Ghost,\n LOD,\n DepthBufferOnly,\n GeometryType\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { assertNever, EventTrigger } from '@reveal/core/utilities';\n\n/**\n * Base class for tools attaching to a {@see Cognite3DViewer}.\n */\nexport abstract class Cognite3DViewerToolBase {\n private readonly _disposedEvent = new EventTrigger<() => void>();\n private _disposed = false;\n\n /**\n * Registers an event handler that is triggered when {@see Cognite3DViewerToolBase.dispose} is\n * called.\n * @param event\n * @param handler\n * @internal\n */\n on(event: 'disposed', handler: () => void) {\n switch (event) {\n case 'disposed':\n this._disposedEvent.subscribe(handler);\n break;\n\n default:\n assertNever(event);\n }\n }\n\n /**\n * Unregisters an event handler for the 'disposed'-event.\n * @param event\n * @param handler\n */\n off(event: 'disposed', handler: () => void) {\n switch (event) {\n case 'disposed':\n this._disposedEvent.unsubscribe(handler);\n break;\n\n default:\n assertNever(event);\n }\n }\n\n /**\n * Disposes the element and triggeres the 'disposed' event before clearing the list\n * of dipose-listeners.\n */\n dispose(): void {\n if (this._disposed) {\n throw new Error('Already disposed');\n }\n this._disposed = true;\n this._disposedEvent.fire();\n this._disposedEvent.unsubscribeAll();\n }\n\n /**\n * Throws an error if the instance has been disposed.\n */\n protected ensureNotDisposed(): void {\n if (this._disposed) {\n throw new Error('The tool has been disposed');\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { Cognite3DViewer, DisposedDelegate, SceneRenderedDelegate } from '@reveal/core';\nimport { worldToViewportCoordinates } from '@reveal/core/utilities';\nimport { Cognite3DViewerToolBase } from './Cognite3DViewerToolBase';\n\nexport type HtmlOverlayPositionUpdatedDelegate = (\n element: HTMLElement,\n position2D: THREE.Vector2,\n position3D: THREE.Vector3,\n distanceToCamera: number\n) => void;\n\nexport type HtmlOverlayOptions = {\n positionUpdatedCallback?: HtmlOverlayPositionUpdatedDelegate;\n};\n\ntype HtmlOverlayElement = {\n position3D: THREE.Vector3;\n options: HtmlOverlayOptions;\n};\n\n/**\n * Manages HTMLoverlays for {@see Cognite3DViewer}. Attaches HTML elements to a \n * 3D position and updates it's position/visibility as user moves the camera. This is \n * useful to create HTML overlays to highlight information about key positions in the 3D model.\n *\n * Attached elements *must* have CSS style 'position: absolute'. It's also recommended\n * in most cases to have styles 'pointerEvents: none' and 'touchAction: none' to avoid\n * interfering with 3D navigation. Consider also applying 'transform: translate(-50%, -50%)'\n * to anchor the center of the element rather than the top-left corner. In some cases the\n * `zIndex`-attribute is necessary for the element to appear on top of the viewer.\n *\n * @example\n * ```js\n * const el = document.createElement('div');\n * el.style.position = 'absolute'; // Required!\n * // Anchor to center of element\n * el.style.transform = 'translate(-50%, -50%)';\n * // Avoid being target for events\n * el.style.pointerEvents = 'none;\n * el.style.touchAction = 'none';\n * // Render in front of other elements\n * el.style.zIndex = 10;\n *\n * el.style.color = 'red';\n * el.innerHtml = '<h1>Overlay</h1>';\n *\n * const overlayTool = new HtmlOverlayTool(viewer);\n * overlayTool.add(el, new THREE.Vector3(10, 10, 10));\n * // ...\n * overlayTool.remove(el);\n * // or, to remove all attached elements\n * overlayTool.clear();\n \n * // detach the tool from the viewer\n * overlayTool.dispose();\n * ```\n */\nexport class HtmlOverlayTool extends Cognite3DViewerToolBase {\n private readonly _viewer: Cognite3DViewer;\n private readonly _htmlOverlays: Map<HTMLElement, HtmlOverlayElement> = new Map();\n\n private readonly _onSceneRenderedHandler: SceneRenderedDelegate;\n private readonly _onViewerDisposedHandler: DisposedDelegate;\n // Allocate variables needed for processing once to avoid allocations\n private readonly _preallocatedVariables = {\n camPos: new THREE.Vector3(),\n camNormal: new THREE.Vector3(),\n point: new THREE.Vector3(),\n nearPlane: new THREE.Plane(),\n farPlane: new THREE.Plane(),\n position2D: new THREE.Vector2()\n };\n\n private get viewerDomElement(): HTMLElement {\n return this._viewer.domElement;\n }\n\n private get viewerCamera(): THREE.PerspectiveCamera {\n return this._viewer.getCamera();\n }\n\n private get viewerRenderer(): THREE.WebGLRenderer {\n return this._viewer.renderer;\n }\n\n constructor(viewer: Cognite3DViewer) {\n super();\n\n this._onSceneRenderedHandler = this.onSceneRendered.bind(this);\n this._onViewerDisposedHandler = this.onViewerDisposed.bind(this);\n this._viewer = viewer;\n this._viewer.on('sceneRendered', this._onSceneRenderedHandler);\n this._viewer.on('disposed', this._onViewerDisposedHandler);\n }\n\n /**\n * Removes all elements and detaches from the viewer.\n * @override\n */\n dispose(): void {\n this._viewer.off('sceneRendered', this._onSceneRenderedHandler);\n this._viewer.off('disposed', this._onViewerDisposedHandler);\n this.clear();\n super.dispose();\n }\n\n /**\n * Registers a HTML overlay that will be updated on rendering.\n *\n * @param htmlElement\n * @param position3D\n * @param options\n */\n add(htmlElement: HTMLElement, position3D: THREE.Vector3, options: HtmlOverlayOptions = {}) {\n this.ensureNotDisposed();\n\n if (this.viewerDomElement.contains(htmlElement)) {\n throw new Error(`Element is already attached to viewer`);\n }\n\n // Note! Must be part of DOM tree before we do getComputedStyle(), so add before check\n this.viewerDomElement.appendChild(htmlElement);\n const style = getComputedStyle(htmlElement);\n if (style.position !== 'absolute') {\n this.viewerDomElement.removeChild(htmlElement);\n throw new Error(`htmlElement style must have a position of absolute. but was '${style.position}'`);\n }\n\n const element: HtmlOverlayElement = { position3D, options };\n this._htmlOverlays.set(htmlElement, element);\n\n this.forceUpdate();\n }\n\n /**\n * Removes a overlay and removes it from the DOM.\n * @param htmlElement\n */\n remove(htmlElement: HTMLElement) {\n this.ensureNotDisposed();\n if (!this.viewerDomElement.contains(htmlElement) || !this._htmlOverlays.has(htmlElement)) {\n throw new Error(`Element is not attached to viewer`);\n }\n this.viewerDomElement.removeChild(htmlElement);\n this._htmlOverlays.delete(htmlElement);\n }\n\n /**\n * Removes all attached HTML overlay elements.\n */\n clear() {\n const overlays = Array.from(this._htmlOverlays.keys());\n for (const element of overlays) {\n this.remove(element);\n }\n }\n\n /**\n * Updates positions of all overlays. This is automatically managed and there\n * shouldn't be any reason to trigger this unless the attached elements are\n * modified externally.\n */\n forceUpdate(): void {\n this.ensureNotDisposed();\n if (this._htmlOverlays.size === 0) {\n return;\n }\n\n const camera = this.viewerCamera;\n const renderer = this.viewerRenderer;\n const { camPos, camNormal, point, nearPlane, farPlane, position2D } = this._preallocatedVariables;\n\n // Determine near/far plane to cull based on distance. Note! We don't cull outside the \"walls\"\n // of the frustum to allow HTML elements that are partially outside the edges. The HTML clipping\n // will fix this anyways\n camera.getWorldPosition(camPos);\n camera.getWorldDirection(camNormal);\n point.copy(camPos).addScaledVector(camNormal, camera.near);\n nearPlane.setFromNormalAndCoplanarPoint(camNormal, point);\n point.copy(camPos).addScaledVector(camNormal, camera.far);\n farPlane.setFromNormalAndCoplanarPoint(camNormal, point);\n\n this._htmlOverlays.forEach((element, htmlElement) => {\n const {\n position3D,\n options: { positionUpdatedCallback }\n } = element;\n const canvas = renderer.domElement;\n\n const insideCameraPlanes =\n nearPlane.distanceToPoint(position3D) >= 0.0 && farPlane.distanceToPoint(position3D) <= 0.0;\n const { x, y } = worldToViewportCoordinates(renderer, camera, position3D);\n\n if (insideCameraPlanes) {\n htmlElement.style.visibility = 'visible';\n htmlElement.style.top = `${y + canvas.offsetTop}px`;\n htmlElement.style.left = `${x + canvas.offsetLeft}px`;\n } else {\n // Outside frustum - hide point\n htmlElement.style.visibility = 'hidden';\n }\n\n if (positionUpdatedCallback) {\n position2D.set(x, y);\n const distanceToCamera = camPos.distanceTo(position3D);\n positionUpdatedCallback(htmlElement, position2D, position3D, distanceToCamera);\n }\n });\n }\n\n private onSceneRendered(): void {\n this.forceUpdate();\n }\n\n private onViewerDisposed(): void {\n this.dispose();\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\nimport { Cognite3DModel } from '@reveal/core';\nimport { Cognite3DViewerToolBase } from './Cognite3DViewerToolBase';\n\nexport class ExplodedViewTool extends Cognite3DViewerToolBase {\n private readonly _cadModel: Cognite3DModel;\n private _treeBoundingBoxdata!: Promise<{ treeIndex: number; direction: THREE.Vector3; transform: THREE.Matrix4 }[]>;\n private readonly _rootTreeIndex: number;\n\n public get readyPromise(): Promise<void> {\n return this._treeBoundingBoxdata.then();\n }\n\n constructor(treeIndex: number, cadModel: Cognite3DModel) {\n super();\n\n this._cadModel = cadModel;\n this._rootTreeIndex = treeIndex;\n\n this.preloadBoundingBoxData(cadModel, treeIndex);\n }\n\n public async expand(expandRadius: number): Promise<void> {\n const expandData = await this._treeBoundingBoxdata;\n\n await Promise.all(\n expandData.map(({ treeIndex, direction, transform }) => {\n if (expandRadius === 0) {\n this._cadModel.resetNodeTransformByTreeIndex(treeIndex);\n return Promise.resolve(0);\n }\n\n transform.setPosition(direction.x * expandRadius, direction.y * expandRadius, direction.z * expandRadius);\n\n return this._cadModel.setNodeTransformByTreeIndex(treeIndex, transform);\n })\n );\n }\n\n public reset(): void {\n this._cadModel.resetNodeTransformByTreeIndex(this._rootTreeIndex, true);\n }\n\n private preloadBoundingBoxData(cadModel: Cognite3DModel, treeIndex: number) {\n const rootTreeIndexBoundingBox = cadModel\n .getBoundingBoxByTreeIndex(treeIndex)\n .then(rootBoundingBox => rootBoundingBox.getCenter(new THREE.Vector3()));\n\n const subTreeBoundingBoxes = cadModel\n .getSubtreeTreeIndices(treeIndex)\n .then(subTreeIndices => {\n if (subTreeIndices.count > 1000) {\n throw new Error(`Subtree size of ${subTreeIndices.count} is too large (max size = 1000)`);\n }\n\n return subTreeIndices;\n })\n .then(subTreeIndices => {\n return Promise.all(\n subTreeIndices.toArray().map(async subTreeIndex => {\n // TODO 2021-06-09 larsmoa: We could make this a lot more efficient by\n // batching bounding box lookups together to one/a few API calls rather than\n // one per node\n const subTreeBox = await cadModel.getBoundingBoxByTreeIndex(subTreeIndex);\n return {\n subTreeIndex: subTreeIndex,\n subTreeIndexBoundingBoxCenter: subTreeBox.getCenter(new THREE.Vector3())\n };\n })\n );\n });\n\n this._treeBoundingBoxdata = Promise.all([rootTreeIndexBoundingBox, subTreeBoundingBoxes])\n .then(data => {\n const [rootCenter, subTreeCenters] = data;\n return subTreeCenters.map(({ subTreeIndex, subTreeIndexBoundingBoxCenter }) => {\n return {\n treeIndex: subTreeIndex,\n direction: new THREE.Vector3().subVectors(subTreeIndexBoundingBoxCenter, rootCenter),\n transform: new THREE.Matrix4()\n };\n });\n })\n .then(async payloads => {\n await Promise.all(\n payloads.map(payload => {\n return cadModel.setNodeTransformByTreeIndex(payload.treeIndex, payload.transform);\n })\n );\n return payloads;\n });\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { Cognite3DViewer } from '@reveal/core';\nimport { DisposedDelegate } from './types';\n\nimport { Cognite3DViewerToolBase } from './Cognite3DViewerToolBase';\n\nexport class DebugCameraTool extends Cognite3DViewerToolBase {\n private readonly _viewer: Cognite3DViewer;\n private readonly _onViewerDisposedHandler: DisposedDelegate;\n private _cameraHelper?: THREE.CameraHelper;\n\n private get viewerCamera(): THREE.PerspectiveCamera {\n return this._viewer.getCamera();\n }\n\n constructor(viewer: Cognite3DViewer) {\n super();\n\n this._onViewerDisposedHandler = this.onViewerDisposed.bind(this);\n this._viewer = viewer;\n this._viewer.on('disposed', this._onViewerDisposedHandler);\n }\n\n /**\n * Removes all elements and detaches from the viewer.\n * @override\n */\n dispose(): void {\n this._viewer.off('disposed', this._onViewerDisposedHandler);\n super.dispose();\n }\n\n showCameraHelper() {\n this.hideCameraHelper();\n this._cameraHelper = new THREE.CameraHelper(this.viewerCamera.clone() as THREE.PerspectiveCamera);\n this._viewer.addObject3D(this._cameraHelper);\n }\n\n hideCameraHelper() {\n if (this._cameraHelper !== undefined) {\n this._viewer.removeObject3D(this._cameraHelper);\n this._cameraHelper = undefined;\n }\n }\n\n private onViewerDisposed(): void {\n this.dispose();\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\n/**\n * Configuration of {@link AxisViewTool}.\n */\nexport type AxisBoxConfig = {\n /**\n * Size in pixels of the axis tool.\n */\n size?: number;\n /**\n * Position, either absolute or relative.\n */\n position?: AbsolutePosition | RelativePosition;\n /**\n * How long the camera animation lasts when\n * clicking a face of the orientation box.\n */\n animationSpeed?: number;\n /**\n * Configuration for each of the faces of the orientation box.\n * Note that Reveal uses a right-handed Y up coordinate system,\n * which might differ from the original model space. To account\n * for this, you might want to reassign labels of the faces.\n */\n faces?: {\n xPositiveFace?: AxisBoxFaceConfig;\n xNegativeFace?: AxisBoxFaceConfig;\n yPositiveFace?: AxisBoxFaceConfig;\n yNegativeFace?: AxisBoxFaceConfig;\n zPositiveFace?: AxisBoxFaceConfig;\n zNegativeFace?: AxisBoxFaceConfig;\n };\n /**\n * Configuration of the compass \"base\" of the tool.\n */\n compass?: AxisBoxCompassConfig;\n};\n\n/**\n * Absolute position in pixels.\n */\nexport type AbsolutePosition = {\n xAbsolute: number;\n yAbsolute: number;\n};\n\n/**\n * Relative position from a corner of the viewer\n * and a given padding.\n */\nexport type RelativePosition = {\n corner: Corner;\n padding: THREE.Vector2;\n};\n\n/**\n * Configuration of each face of the orientation box.\n */\nexport type AxisBoxFaceConfig = {\n /**\n * Label of the respective face, e.g. 'X' or 'Right'.\n */\n label?: string;\n fontSize?: number;\n fontColor?: THREE.Color;\n outlineSize?: number;\n outlineColor?: THREE.Color;\n faceColor?: THREE.Color;\n};\n\n/**\n * Configuration of the compass.\n */\nexport type AxisBoxCompassConfig = {\n /**\n * Label of the orientation indicator. Defaults\n * to 'N' for north.\n */\n ringLabel?: string;\n /**\n * Offset in radians of the orientation indicator.\n */\n labelDelta?: number;\n fontSize?: number;\n fontColor?: THREE.Color;\n tickColor?: THREE.Color;\n};\n\n/**\n * A corner of the viewer.\n */\nexport enum Corner {\n TopRight,\n TopLeft,\n BottomLeft,\n BottomRight\n}\n\nexport const defaultAxisBoxCompassConfig: AxisBoxCompassConfig = {\n ringLabel: 'N',\n labelDelta: Math.PI,\n fontSize: undefined,\n fontColor: new THREE.Color(0xff0000),\n tickColor: new THREE.Color(0x949494)\n};\n\nexport const defaultFaceConfig: AxisBoxFaceConfig = {\n label: '',\n fontSize: undefined,\n fontColor: new THREE.Color(0x333333),\n outlineSize: undefined,\n outlineColor: new THREE.Color(0x333333),\n faceColor: new THREE.Color(0x949494)\n};\n\nexport const defaultAxisBoxConfig: Required<AxisBoxConfig> = {\n size: 128,\n position: {\n corner: Corner.BottomRight,\n padding: new THREE.Vector2()\n },\n animationSpeed: 200,\n faces: {\n xPositiveFace: {\n ...defaultFaceConfig,\n label: 'Right'\n },\n xNegativeFace: {\n ...defaultFaceConfig,\n label: 'Left'\n },\n yPositiveFace: {\n ...defaultFaceConfig,\n label: 'Up'\n },\n yNegativeFace: {\n ...defaultFaceConfig,\n label: 'Down'\n },\n zPositiveFace: {\n ...defaultFaceConfig,\n label: 'Front'\n },\n zNegativeFace: {\n ...defaultFaceConfig,\n label: 'Back'\n }\n },\n compass: defaultAxisBoxCompassConfig\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport TWEEN from '@tweenjs/tween.js';\n\nimport { Cognite3DViewer } from '@reveal/core';\nimport { Cognite3DViewerToolBase } from '../Cognite3DViewerToolBase';\nimport {\n AxisBoxConfig,\n defaultAxisBoxConfig,\n AxisBoxFaceConfig,\n Corner,\n AbsolutePosition,\n RelativePosition\n} from './types';\nimport ComboControls from '@reveal/camera-manager';\nimport cloneDeep from 'lodash/cloneDeep';\nimport merge from 'lodash/merge';\n\nexport class AxisViewTool extends Cognite3DViewerToolBase {\n private readonly _layoutConfig: Required<AxisBoxConfig>;\n\n private readonly _boxFaceGeometry: THREE.PlaneGeometry;\n\n private readonly _viewer: Cognite3DViewer;\n\n private readonly _axisGroup: THREE.Group;\n\n private readonly _interactiveObjects: THREE.Mesh[];\n private readonly _raycastCamera: THREE.OrthographicCamera;\n private readonly _raycaster: THREE.Raycaster;\n\n private readonly _screenPosition: THREE.Vector2;\n\n private readonly _disposeClickDiv: () => void;\n\n private _dynamicUpdatePosition = () => {};\n private _updateClickDiv = () => {};\n\n constructor(viewer: Cognite3DViewer, config?: AxisBoxConfig) {\n super();\n\n this._screenPosition = new THREE.Vector2();\n this._boxFaceGeometry = new THREE.PlaneGeometry(0.85, 0.85, 1, 1);\n\n this._raycastCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, -1, 1);\n this._raycaster = new THREE.Raycaster();\n\n this._viewer = viewer;\n\n this._layoutConfig = merge(cloneDeep(defaultAxisBoxConfig), config);\n\n this._axisGroup = new THREE.Group();\n this._interactiveObjects = this.createAxisCross(this._axisGroup);\n\n [this._updateClickDiv, this._disposeClickDiv] = this.createClickDiv(viewer);\n this.addAxisBoxToViewer(this._axisGroup, this._layoutConfig.position!);\n }\n\n public dispose(): void {\n super.dispose();\n this._viewer.removeUiObject(this._axisGroup);\n this._disposeClickDiv();\n }\n\n private createClickDiv(viewer: Cognite3DViewer) {\n const canvasElement = viewer.domElement.querySelector('canvas');\n if (canvasElement === null) {\n throw new Error('Could not find canvas');\n }\n const divElement = document.createElement('div');\n divElement.style.position = 'absolute';\n divElement.style.height = `${this._layoutConfig.size}px`;\n divElement.style.width = `${this._layoutConfig.size}px`;\n divElement.style.zIndex = '1';\n\n let xMouse = 0;\n let yMouse = 0;\n\n divElement.addEventListener('mousedown', event => {\n const mouseDownEvent = new MouseEvent('mousedown', {\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button\n });\n xMouse = event.clientX;\n yMouse = event.clientY;\n viewer.renderer.domElement.dispatchEvent(mouseDownEvent);\n });\n\n divElement.addEventListener('mousemove', event => {\n const mouseMoveEvent = new MouseEvent('mousemove', {\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button\n });\n viewer.renderer.domElement.dispatchEvent(mouseMoveEvent);\n });\n\n divElement.addEventListener('contextmenu', event => event.preventDefault());\n\n divElement.addEventListener('mouseup', event => {\n const mouseUpEvent = new MouseEvent('mouseup', {\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button\n });\n\n const rect = viewer.domElement.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n if (Math.abs(xMouse - event.clientX) + Math.abs(yMouse - event.clientY) <= 10 && !this.handleClick(x, y, rect)) {\n viewer.renderer.domElement.dispatchEvent(mouseUpEvent);\n }\n });\n\n viewer.domElement.appendChild(divElement);\n\n return [\n () => {\n divElement.style.left = `${this._screenPosition.x}px`;\n divElement.style.bottom = `${this._screenPosition.y}px`;\n },\n () => {\n viewer.domElement.removeChild(divElement);\n }\n ];\n }\n\n private addAxisBoxToViewer(axisGroup: THREE.Group, position: AbsolutePosition | RelativePosition) {\n const size = this._layoutConfig.size;\n\n if (isAbsolute(position)) {\n this._screenPosition.x = position.xAbsolute;\n this._screenPosition.y = position.yAbsolute;\n } else {\n switch (position.corner) {\n case Corner.BottomRight:\n this._screenPosition.y = position.padding.y;\n\n this._dynamicUpdatePosition = () => {\n this._screenPosition.x = this._viewer.renderer.domElement.clientWidth - position.padding.x - size;\n };\n break;\n\n case Corner.TopRight:\n this._dynamicUpdatePosition = () => {\n this._screenPosition.x = this._viewer.renderer.domElement.clientWidth - position.padding.x - size;\n this._screenPosition.y = this._viewer.renderer.domElement.clientHeight - position.padding.y - size;\n };\n break;\n\n case Corner.TopLeft:\n this._screenPosition.x = position.padding.x;\n this._dynamicUpdatePosition = () => {\n this._screenPosition.y = this._viewer.renderer.domElement.clientHeight - position.padding.y - size;\n };\n break;\n\n case Corner.BottomLeft:\n this._screenPosition.x = position.padding.x;\n this._screenPosition.y = position.padding.y;\n break;\n default:\n throw new Error(`Unknown corner position for Axis Cross: Corner = ${position.corner}`);\n }\n this._dynamicUpdatePosition();\n }\n\n this._viewer.addUiObject(axisGroup, this._screenPosition, new THREE.Vector2(size, size));\n\n function isAbsolute(position: AbsolutePosition | RelativePosition): position is AbsolutePosition {\n return (\n (position as AbsolutePosition).xAbsolute !== undefined && (position as AbsolutePosition).yAbsolute !== undefined\n );\n }\n }\n\n private handleClick(xScreenPos: number, yScreenPos: number, boundingRect: DOMRect): boolean {\n const xNdc = (2 * (xScreenPos - this._screenPosition.x)) / this._layoutConfig.size - 1;\n const yNdc = (2 * (boundingRect.height - yScreenPos - this._screenPosition.y)) / this._layoutConfig.size - 1;\n this._raycaster.setFromCamera({ x: xNdc, y: yNdc }, this._raycastCamera);\n const rayOrigin = new THREE.Vector3(xNdc, yNdc, 1);\n const rayDirection = new THREE.Vector3(0, 0, -1).normalize();\n this._raycaster.set(rayOrigin, rayDirection);\n\n const intersects = this._raycaster.intersectObjects(this._interactiveObjects);\n\n if (!(intersects.length > 0)) return false;\n\n const targetPosition = intersects[0].object.position.clone().normalize();\n const targetUp = (intersects[0].object.userData.upVector as THREE.Vector3).clone();\n\n this.moveCameraTo(this._viewer.getCamera(), this._viewer.cameraControls, targetPosition, targetUp);\n\n return true;\n }\n\n private createAxisCross(axisGroup: THREE.Group) {\n const interactiveObjects = this.createBoxFaces();\n axisGroup.add(...interactiveObjects);\n\n const compass = this.createCompass();\n axisGroup.add(compass);\n\n this.setupTransformOnRender(axisGroup);\n\n return interactiveObjects;\n }\n\n private setupTransformOnRender(axisGroup: THREE.Group) {\n axisGroup.children[0].onBeforeRender = () => {\n this._dynamicUpdatePosition();\n axisGroup.quaternion.copy(this._viewer.getCamera().quaternion).invert();\n axisGroup.updateMatrixWorld();\n this._updateClickDiv();\n };\n }\n\n private createBoxFaces() {\n const facesConfig = this._layoutConfig.faces;\n\n const posXFace = this.createBoxFace(new THREE.Vector3(1, 0, 0), facesConfig.xPositiveFace!);\n const negXFace = this.createBoxFace(new THREE.Vector3(-1, 0, 0), facesConfig.xNegativeFace!);\n\n const posYFace = this.createBoxFace(\n new THREE.Vector3(0, 1, 0),\n facesConfig.yPositiveFace!,\n new THREE.Vector3(0, 0, -1)\n );\n const negYFace = this.createBoxFace(\n new THREE.Vector3(0, -1, 0),\n facesConfig.yNegativeFace!,\n new THREE.Vector3(0, 0, 1)\n );\n\n const posZFace = this.createBoxFace(new THREE.Vector3(0, 0, 1), facesConfig.zPositiveFace!);\n const negZFace = this.createBoxFace(new THREE.Vector3(0, 0, -1), facesConfig.zNegativeFace!);\n\n return [posXFace, negXFace, posYFace, negYFace, posZFace, negZFace];\n }\n\n private createCompass() {\n const compassPlaneGeometry = new THREE.PlaneGeometry(2.1, 2.1, 1, 1);\n const compass = new THREE.Mesh(\n compassPlaneGeometry,\n new THREE.MeshBasicMaterial({\n map: this.createCompassTexture(),\n side: THREE.DoubleSide,\n transparent: true\n })\n );\n\n const x = Math.sin(this._layoutConfig.compass.labelDelta!);\n const z = Math.cos(this._layoutConfig.compass.labelDelta!);\n\n compass.position.y = -0.5;\n compass.up.copy(new THREE.Vector3(x, 0, z));\n compass.lookAt(0, 0, 0);\n\n return compass;\n }\n\n private createCompassTexture() {\n const compassLayout = this._layoutConfig.compass;\n const textureSize = this._layoutConfig.size;\n\n const canvas = document.createElement('canvas');\n canvas.width = textureSize;\n canvas.height = textureSize;\n const context = canvas.getContext('2d')!;\n\n const halfSize = textureSize / 2;\n const radius = halfSize - halfSize / 4;\n\n const tickWidth = textureSize / 32;\n const tickSpace = textureSize / 8;\n\n context.strokeStyle = compassLayout.tickColor!.getStyle();\n context.lineWidth = textureSize / 16;\n context.setLineDash([tickWidth, tickSpace]);\n context.beginPath();\n context.arc(halfSize, halfSize, radius, 0, 2 * Math.PI);\n context.stroke();\n\n if (compassLayout.ringLabel && compassLayout.ringLabel.length > 0) {\n const fontSize = compassLayout.fontSize ?? textureSize / 5;\n context.font = `bold ${fontSize}px Arial`;\n context.textAlign = 'center';\n context.fillStyle = compassLayout.fontColor!.getStyle();\n context.fillText(compassLayout.ringLabel, halfSize, halfSize * (1 / 4) + fontSize / 3);\n }\n\n return new THREE.CanvasTexture(canvas);\n }\n\n private getFaceTexture(faceConfig: AxisBoxFaceConfig, size: number) {\n const textureSize = size / 2;\n\n const canvas = document.createElement('canvas');\n canvas.width = textureSize;\n canvas.height = textureSize;\n\n const context = canvas.getContext('2d')!;\n context.fillStyle = faceConfig.outlineColor!.getStyle();\n context.fillRect(0, 0, textureSize, textureSize);\n context.fillStyle = faceConfig.faceColor!.getStyle();\n\n const outlineSize = faceConfig.outlineSize ?? textureSize / 32;\n context.fillRect(outlineSize, outlineSize, textureSize - outlineSize * 2, textureSize - outlineSize * 2);\n context.fill();\n\n if (faceConfig.label !== '') {\n const fontSize = faceConfig.fontSize ?? textureSize / 3;\n context.font = `bold ${fontSize}px Arial`;\n context.textAlign = 'center';\n context.fillStyle = faceConfig.fontColor!.getStyle();\n context.fillText(faceConfig.label!, textureSize / 2, textureSize / 2 + fontSize / 3);\n }\n\n return new THREE.CanvasTexture(canvas);\n }\n\n private createBoxFace(position: THREE.Vector3, faceConfig: AxisBoxFaceConfig, upVector = new THREE.Vector3(0, 1, 0)) {\n const face = new THREE.Mesh(\n this._boxFaceGeometry,\n new THREE.MeshBasicMaterial({ map: this.getFaceTexture(faceConfig, this._layoutConfig.size) })\n );\n\n face.position.copy(position.multiplyScalar(0.5 * this._boxFaceGeometry.parameters.width));\n face.lookAt(position.multiplyScalar(2));\n\n face.userData.upVector = upVector;\n\n return face;\n }\n\n private moveCameraTo(\n camera: THREE.PerspectiveCamera,\n cameraControls: ComboControls,\n targetAxis: THREE.Vector3,\n targetUpAxis: THREE.Vector3\n ) {\n const currentCameraPosition = camera.position.clone();\n const cameraTarget = cameraControls.getState().target;\n\n const targetRelativeStartPosition = currentCameraPosition.clone().sub(cameraTarget);\n const radius = targetRelativeStartPosition.length();\n\n const normalizedFrom = targetRelativeStartPosition.clone().normalize();\n\n const omega = Math.acos(normalizedFrom.dot(targetAxis));\n\n const from = { t: 0 };\n const to = { t: 1 };\n\n const animation = new TWEEN.Tween(from);\n\n const forward = targetAxis.clone();\n\n const fromRotation = camera.quaternion.clone();\n const toRotation = new THREE.Quaternion().setFromRotationMatrix(\n new THREE.Matrix4().makeBasis(targetUpAxis.clone().cross(forward), targetUpAxis, forward)\n );\n\n const epsilon = 1e-6;\n\n if (fromRotation.angleTo(toRotation) < epsilon) {\n return;\n }\n\n const tmpPosition = new THREE.Vector3();\n const tmpRotation = new THREE.Quaternion();\n let cachedCameraControlsEnabled: boolean;\n const tween = animation\n .to(to, this._layoutConfig.animationSpeed)\n .onUpdate(() => {\n tmpPosition\n .copy(normalizedFrom)\n .multiplyScalar(Math.sin((1 - from.t) * omega) / Math.sin(omega))\n .add(targetAxis.clone().multiplyScalar(Math.sin(from.t * omega) / Math.sin(omega)));\n\n tmpPosition.multiplyScalar(radius);\n tmpPosition.add(cameraTarget);\n\n tmpRotation.slerpQuaternions(fromRotation, toRotation, from.t);\n\n camera.position.copy(tmpPosition);\n camera.setRotationFromQuaternion(tmpRotation);\n })\n .start(TWEEN.now())\n .onStart(() => {\n cachedCameraControlsEnabled = cameraControls.enabled;\n cameraControls.enabled = false;\n })\n .onComplete(() => {\n cameraControls.setState(camera.position, cameraTarget);\n cameraControls.enabled = cachedCameraControlsEnabled;\n });\n tween.update(TWEEN.now());\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Supported map Providers Bing, Here & Mapbox\n */\nexport enum MapProviders {\n BingMap = 'BingMap',\n HereMap = 'HereMap',\n MapboxMap = 'MapboxMap',\n OpenStreetMap = 'OpenStreetMap'\n}\n\n/**\n * Map data for Mapbox\n */\nexport enum MapboxMode {\n /**\n * Access the map data using a map style. For details see https://docs.mapbox.com/api/maps/styles/\n */\n Style = 100,\n /**\n * Access the map data using a map id or Tileset id. For details see https://docs.mapbox.com/help/glossary/tileset-id/\n */\n Map_Id = 101\n}\n\n/**\n * Mapbox Map Style, these are pre-defined styles using map/tileset id, created in Mapbox Studio style editor.\n * This is used when MapboxMode.Style is used for mode.\n */\nexport enum MapboxStyle {\n Streets = 'mapbox/streets-v10',\n Outdoor = 'mapbox/outdoors-v10',\n Light = 'mapbox/light-v9',\n Dark = 'mapbox/dark-v9',\n Satellite = 'mapbox/satellite-v9',\n Satellite_Streets = 'mapbox/satellite-streets-v10',\n Navigation_Day = 'mapbox/navigation-preview-day-v4',\n Navigation_Night = 'mapbox/navigation-preview-night-v4',\n Navigation_Guide_Day = 'mapbox/navigation-guidance-day-v4',\n Navigation_Guide_Night = 'mapbox/navigation-guidance-night-v4'\n}\n\n/**\n * A map/tileset ID is a unique identifier given to every tileset, used when MapboxMode.Map_Id is choosen for mode.\n */\nexport enum MapboxId {\n Streets = 'mapbox.mapbox-streets-v7',\n Satellite = 'mapbox.satellite',\n Terrain = 'mapbox.mapbox-terrain-v2',\n Traffic = 'mapbox.mapbox-traffic-v1',\n TerrainRGB = 'mapbox.terrain-rgb'\n}\n\n/**\n * Mapbox Map image tile format\n */\nexport enum MapboxImageFormat {\n PNG = 'png',\n PNG32 = 'png32',\n PNG64 = 'png64',\n PNG128 = 'png128',\n PNG256 = 'png256',\n JPG70 = 'jpg70',\n JPG80 = 'jpg80',\n JPG90 = 'jpg90',\n PNGRAW = 'pngraw'\n}\n\n/**\n * Bing Map View (aerial, road, bird's eye view of the map)\n */\nexport enum BingMapType {\n Aerial = 'a',\n Road = 'r',\n Aerial_Labels = 'h',\n Oblique = 'o',\n Oblique_Labels = 'b'\n}\n\n/**\n * Bing Map Tile Image formats\n */\nexport enum BingMapImageFormat {\n GIF = 'gif',\n JPEG = 'jpeg',\n PNG = 'png'\n}\n\n/**\n * Here Map types\n */\nexport enum HereMapType {\n Aerial = 'aerial',\n Base = 'base',\n Pano = 'pano',\n Traffic = 'traffic'\n}\n\n/**\n * Here Map View Scheme like day, night, satellite, terrain\n */\nexport enum HereMapScheme {\n Day = 'normal.day',\n Night = 'normal.night',\n Terrain = 'terrain.day',\n Satellite = 'satellite.day'\n}\n\n/**\n * Here Map Tiles Image Format\n */\nexport enum HereMapImageFormat {\n PNG = 'png',\n PNG8 = 'png8',\n JPG = 'jpg'\n}\n\nexport type BingMapConfig = {\n provider: MapProviders.BingMap;\n /**\n * Bing Map API Key\n */\n APIKey: string;\n /**\n * The type of the map used.\n */\n type?: BingMapType;\n};\n\nexport type HereMapConfig = {\n provider: MapProviders.HereMap;\n /**\n * Here map API Key\n */\n APIKey: string;\n /**\n * Service application code token.\n */\n appCode?: string;\n /**\n * The type of maps to be used.\n */\n style?: HereMapType;\n /**\n * Specifies the view scheme\n */\n scheme?: string;\n /**\n * Map image tile format\n */\n imageFormat?: HereMapImageFormat;\n /**\n Returned tile map image size.\n The following sizes are supported:\n - 256\n - 512\n - 128 (deprecated, although usage is still accepted)\n */\n size?: number;\n};\n\nexport type OpenStreetMapConfig = {\n provider: MapProviders.OpenStreetMap;\n};\n\nexport type MapboxConfig = {\n provider: MapProviders.MapboxMap;\n /**\n * Mapbox API Key\n */\n APIKey: string;\n /**\n * Map style or map ID if the mode is set to MAP_ID\n */\n id: string;\n /**\n Map tile access mode\n - MapboxMode.STYLE\n - MapboxMode.MAP_ID\n */\n mode?: MapboxMode;\n /**\n * Map image tile format\n */\n tileFormat?: MapboxImageFormat;\n /**\n * Flag to indicate if should use high resolution tiles\n */\n useHDPI?: boolean;\n};\n\n/**\n * Maps Configuration of {@link GeomapTool}.\n */\nexport type MapConfig = {\n /**\n * Latitude, Longitude position\n */\n latlong: LatLongPosition;\n} & (BingMapConfig | HereMapConfig | MapboxConfig | OpenStreetMapConfig);\n\n/**\n * Latitude, Longitude position.\n */\nexport type LatLongPosition = {\n latitude: number;\n longitude: number;\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\n// To overcome \"implicitly has an 'any' type\" and \"unused variable reference\" error in the geo-three library\n// @ts-ignore\nimport * as GEOTHREE from 'geo-three';\nimport { Cognite3DViewer } from '@reveal/core';\nimport { LatLongPosition, MapConfig, MapProviders } from './MapConfig';\n\nexport class Geomap {\n private readonly _viewer: Cognite3DViewer;\n private _map: GEOTHREE.MapView;\n private _intervalId: any = 0;\n private readonly _onCameraChange = this.handleCameraChange.bind(this);\n\n constructor(viewer: Cognite3DViewer, mapConfig: MapConfig) {\n this._viewer = viewer;\n const mapProvider = this.getMapProvider(mapConfig);\n this._map = new GEOTHREE.MapView(GEOTHREE.MapView.PLANAR, mapProvider, mapProvider);\n this._viewer.addObject3D(this._map);\n\n const coords = GEOTHREE.UnitsUtils.datumsToSpherical(mapConfig.latlong.latitude, mapConfig.latlong.longitude);\n const bound = this._viewer.models[0].getModelBoundingBox();\n this._map.position.set(-coords.x, bound.min.y, coords.y);\n this._map.updateMatrixWorld(true);\n this.requestRedraw(10000);\n this._viewer.on('cameraChange', this._onCameraChange);\n }\n\n private requestRedraw(timeOut: number) {\n if (this._intervalId == 0) {\n this._intervalId = setInterval(() => {\n this._viewer.requestRedraw();\n }, 100);\n\n setTimeout(() => {\n clearInterval(this._intervalId);\n this._intervalId = 0;\n }, timeOut);\n }\n }\n\n private getMapProvider(mapConfig: MapConfig) {\n let mapProvider: GEOTHREE.MapProvider;\n switch (mapConfig.provider) {\n case MapProviders.BingMap:\n mapProvider = new GEOTHREE.BingMapsProvider(mapConfig.APIKey, mapConfig.type);\n break;\n case MapProviders.HereMap:\n mapProvider = new GEOTHREE.HereMapsProvider(\n mapConfig.APIKey,\n mapConfig.appCode,\n mapConfig.style,\n mapConfig.scheme,\n mapConfig.imageFormat,\n mapConfig.size\n );\n break;\n case MapProviders.MapboxMap:\n mapProvider = new GEOTHREE.MapBoxProvider(mapConfig.APIKey, mapConfig.id, mapConfig.mode, mapConfig.tileFormat);\n break;\n case MapProviders.OpenStreetMap:\n mapProvider = new GEOTHREE.OpenStreetMapsProvider();\n break;\n\n default:\n throw new Error('Unsupported map provider');\n }\n\n return mapProvider;\n }\n\n public latLongToWorldCoordinates(latLong: LatLongPosition) {\n return GEOTHREE.UnitsUtils.datumsToSpherical(latLong.latitude, latLong.longitude);\n }\n\n private handleCameraChange() {\n this.requestRedraw(1000);\n }\n\n public dispose(): void {\n this._viewer.removeObject3D(this._map);\n this._viewer.off('cameraChange', this._onCameraChange);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { Cognite3DViewer } from '@reveal/core';\nimport { Cognite3DViewerToolBase } from '../Cognite3DViewerToolBase';\nimport { LatLongPosition, MapConfig } from './MapConfig';\nimport { Geomap } from './Geomap';\n\n/**\n * The `GeomapTool` is a geolocation for the models and allow the user to place them on the maps.\n * @version New since 2.1.\n */\nexport class GeomapTool extends Cognite3DViewerToolBase {\n private readonly _viewer: Cognite3DViewer;\n private readonly _maps: Geomap;\n\n constructor(viewer: Cognite3DViewer, config: MapConfig) {\n super();\n\n this._viewer = viewer;\n this._maps = new Geomap(this._viewer, config);\n }\n\n /**\n * Converts Latitude & Longitude into Vector2 World coordinates on the Map\n * @param latLong Latitude & Longitude\n */\n public latLongToWorldCoordinates(latLong: LatLongPosition) {\n this._maps.latLongToWorldCoordinates(latLong);\n }\n\n public dispose(): void {\n super.dispose();\n this._maps.dispose();\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nimport { Cognite3DViewer, Cognite3DModel } from '@reveal/core';\nimport { LevelOfDetail, SectorNode } from '@reveal/core/cad';\nimport { assertNever } from '@reveal/core/utilities';\n\nimport { Cognite3DViewerToolBase } from './Cognite3DViewerToolBase';\n\nexport type DebugLoadedSectorsToolOptions = {\n showSimpleSectors?: boolean;\n showDetailedSectors?: boolean;\n showDiscardedSectors?: boolean;\n colorBy?: 'depth' | 'lod' | 'loadedTimestamp' | 'random';\n leafsOnly?: boolean;\n sectorPathFilterRegex?: string;\n};\n\nexport class DebugLoadedSectorsTool extends Cognite3DViewerToolBase {\n private readonly _boundingBoxes = new THREE.Group();\n private readonly _viewer: Cognite3DViewer;\n private _options: Required<DebugLoadedSectorsToolOptions>;\n private _model?: Cognite3DModel;\n\n constructor(viewer: Cognite3DViewer, options: DebugLoadedSectorsToolOptions = {}) {\n super();\n this._viewer = viewer;\n this._viewer.addObject3D(this._boundingBoxes);\n this._options = {} as any; // Force - it's set in setOptions\n this.setOptions(options);\n }\n\n setOptions(options: DebugLoadedSectorsToolOptions) {\n this._options = {\n showDetailedSectors: true,\n showDiscardedSectors: false,\n showSimpleSectors: true,\n colorBy: 'lod',\n leafsOnly: false,\n sectorPathFilterRegex: '.*',\n ...options\n };\n }\n\n dispose() {\n this._viewer.removeObject3D(this._boundingBoxes);\n }\n\n showSectorBoundingBoxes(model: Cognite3DModel) {\n this._model = model;\n this.updateBoundingBoxes();\n }\n\n private updateBoundingBoxes() {\n this._boundingBoxes.clear();\n if (this._model === undefined) {\n return;\n }\n this._model.getModelTransformation(this._boundingBoxes.matrix);\n const shouldShowLod: boolean[] = [];\n shouldShowLod[LevelOfDetail.Discarded] = this._options.showDiscardedSectors;\n shouldShowLod[LevelOfDetail.Simple] = this._options.showSimpleSectors;\n shouldShowLod[LevelOfDetail.Detailed] = this._options.showDetailedSectors;\n\n const selectedSectorNodes: SectorNode[] = [];\n this._model.cadNode.traverse(node => {\n if (isSectorNode(node)) {\n const sectorNode = node as SectorNode;\n\n if (\n this.isSectorAcceptedByCurrentFilter(sectorNode) &&\n shouldShowLod[sectorNode.levelOfDetail] &&\n (!this._options.leafsOnly || isLeaf(sectorNode))\n ) {\n selectedSectorNodes.push(sectorNode);\n }\n }\n });\n\n selectedSectorNodes.forEach(sectorNode => {\n const bboxNode = this.createBboxNodeFor(sectorNode, selectedSectorNodes);\n this._boundingBoxes.add(bboxNode);\n });\n this._boundingBoxes.updateMatrixWorld(true);\n\n this._viewer.requestRedraw();\n }\n\n private isSectorAcceptedByCurrentFilter(node: SectorNode): boolean {\n const accepted = new RegExp(this._options.sectorPathFilterRegex).test(node.sectorPath);\n return accepted;\n }\n\n private createBboxNodeFor(node: SectorNode, allSelectedNodes: SectorNode[]) {\n const options = this._options;\n function determineColor() {\n switch (options.colorBy) {\n case 'depth': {\n const s = Math.min(1.0, node.depth / 8);\n return new THREE.Color(Colors.green).lerpHSL(Colors.red, s);\n }\n case 'lod': {\n switch (node.levelOfDetail) {\n case LevelOfDetail.Simple:\n return Colors.yellow;\n case LevelOfDetail.Detailed:\n return Colors.green;\n case LevelOfDetail.Discarded:\n return Colors.red;\n default:\n assertNever(node.levelOfDetail);\n }\n }\n case 'loadedTimestamp': {\n // Note! Horribly slow since we do this for every sector, but since this is a debug tool\n // we consider it OK\n const nodesByTimestamp = [...allSelectedNodes].sort((a, b) => a.updatedTimestamp - b.updatedTimestamp);\n const indexOfNode = nodesByTimestamp.findIndex(x => x === node);\n const s = (nodesByTimestamp.length - 1 - indexOfNode) / Math.max(nodesByTimestamp.length - 1, 1);\n return new THREE.Color(Colors.green).lerpHSL(Colors.red, s);\n }\n\n case 'random':\n return new THREE.Color().setHSL(Math.random(), 1.0, 0.5);\n\n default:\n assertNever(options.colorBy);\n }\n }\n const color = determineColor();\n return new THREE.Box3Helper(node.bounds, color);\n }\n}\n\nconst Colors = {\n green: new THREE.Color('#00ff00'),\n yellow: new THREE.Color('yellow'),\n red: new THREE.Color('red')\n};\n\nfunction isSectorNode(node: THREE.Object3D) {\n return node.name.match(/^Sector \\d+$/);\n}\n\nfunction isLeaf(node: SectorNode) {\n return !node.children.some(x => isSectorNode(x));\n}\n"],"sourceRoot":""}
1
+ {"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap","webpack:///external \"three\"","webpack:///./packages/utilities/src/objectTraversal.ts","webpack:///./packages/utilities/src/transformCameraConfiguration.ts","webpack:///./packages/utilities/src/RandomColors.ts","webpack:///./packages/utilities/src/events/clickOrTouchEventOffset.ts","webpack:///./packages/utilities/src/events/EventTrigger.ts","webpack:///./packages/utilities/src/assertNever.ts","webpack:///./packages/utilities/src/NumericRange.ts","webpack:///./packages/utilities/src/determinePowerOfTwoDimensions.ts","webpack:///./packages/utilities/src/indexset/IntermediateIndexNode.ts","webpack:///./packages/utilities/src/indexset/LeafIndexNode.ts","webpack:///./packages/utilities/src/indexset/IndexSet.ts","webpack:///./packages/utilities/src/packFloat.ts","webpack:///./packages/utilities/src/datastructures/DynamicDefragmentedBuffer.ts","webpack:///./packages/utilities/src/three/AutoDisposeGroup.ts","webpack:///./packages/utilities/src/three/BoundingBoxLOD.ts","webpack:///./packages/utilities/src/three/getBox3CornerPoints.ts","webpack:///./packages/utilities/src/isMobileOrTablet.ts","webpack:///./packages/utilities/src/WebGLRendererStateHelper.ts","webpack:///./packages/utilities/src/revealEnv.ts","webpack:///./packages/utilities/src/workers/WorkerPool.ts","webpack:///./packages/utilities/src/networking/isTheSameDomain.ts","webpack:///./packages/utilities/src/cache/MemoryRequestCache.ts","webpack:///./packages/utilities/src/cache/MostFrequentlyUsedCache.ts","webpack:///./packages/utilities/src/disposeAttributeArrayOnUpload.ts","webpack:///./packages/cad-parsers/src/utilities/SectorScene.ts","webpack:///./packages/cad-parsers/src/metadata/parsers/CadMetadataParserV8.ts","webpack:///./packages/cad-parsers/src/metadata/CadMetadataParser.ts","webpack:///./packages/cad-parsers/src/utilities/types.ts","webpack:///./packages/cad-parsers/src/metadata/CadModelMetadataRepository.ts","webpack:///./packages/cad-parsers/src/cad/LevelOfDetail.ts","webpack:///./packages/cad-parsers/src/utilities/SectorSceneFactory.ts","webpack:///./packages/cad-parsers/src/sector/SectorNode.ts","webpack:///./packages/cad-parsers/src/sector/RootSectorNode.ts","webpack:///./packages/cad-parsers/src/cad/CadSectorParser.ts","webpack:///./packages/cad-parsers/src/utilities/computeBoundingBoxFromAttributes.ts","webpack:///./packages/cad-parsers/src/cad/filterPrimitives.ts","webpack:///./packages/cad-parsers/src/cad/filterInstanceMesh.ts","webpack:///./packages/cad-parsers/src/utilities/float32BufferToMatrix.ts","webpack:///./packages/cad-parsers/src/cad/primitiveGeometries.ts","webpack:///./packages/cad-parsers/src/cad/triangleMeshes.ts","webpack:///./packages/modeldata-api/src/CdfModelDataProvider.ts","webpack:///./packages/modeldata-api/src/CdfModelIdentifier.ts","webpack:///./packages/modeldata-api/src/types.ts","webpack:///./packages/modeldata-api/src/applyDefaultModelTransformation.ts","webpack:///./packages/modeldata-api/src/Model3DOutputList.ts","webpack:///./packages/modeldata-api/src/CdfModelMetadataProvider.ts","webpack:///./packages/modeldata-api/src/CdfModelOutputsProvider.ts","webpack:///./packages/modeldata-api/src/utilities.ts","webpack:///./packages/modeldata-api/src/LocalModelDataProvider.ts","webpack:///./packages/modeldata-api/src/LocalModelIdentifier.ts","webpack:///./packages/modeldata-api/src/LocalModelMetadataProvider.ts","webpack:///external \"assert\"","webpack:///./packages/metrics/src/MetricsLogger.ts","webpack:///./packages/logger/src/Log.ts","webpack:///./packages/logger/index.ts","webpack:///external \"@tweenjs/tween.js\"","webpack:///external \"mixpanel-browser\"","webpack:///./core/src/utilities/worldToViewport.ts","webpack:///external \"lodash/cloneDeep\"","webpack:///external \"geo-three\"","webpack:///external \"@cognite/sdk-core\"","webpack:///./core/src/utilities/index.ts","webpack:///./core/src/utilities/BoundingBoxClipper.ts","webpack:///external \"lodash/range\"","webpack:///external \"comlink\"","webpack:///external \"loglevel\"","webpack:///external \"lodash/debounce\"","webpack:///external \"skmeans\"","webpack:///external \"lodash/merge\"","webpack:///./packages/tools/src/Cognite3DViewerToolBase.ts","webpack:///./packages/tools/src/HtmlOverlay/BucketGrid2D.ts","webpack:///./packages/tools/src/HtmlOverlay/HtmlOverlayTool.ts","webpack:///./packages/tools/src/ExplodedViewTool.ts","webpack:///./packages/tools/src/DebugCameraTool.ts","webpack:///./packages/tools/src/AxisView/types.ts","webpack:///./packages/tools/src/AxisView/AxisViewTool.ts","webpack:///./packages/tools/src/Geomap/MapConfig.ts","webpack:///./packages/tools/src/Geomap/Geomap.ts","webpack:///./packages/tools/src/Geomap/GeomapTool.ts","webpack:///./packages/tools/src/Timeline/Keyframe.ts","webpack:///./packages/tools/src/Timeline/TimelineTool.ts","webpack:///./packages/tools/src/DebugLoadedSectorsTool.ts"],"names":["root","factory","exports","module","define","amd","a","i","self","this","installedModules","__webpack_require__","moduleId","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","require","traverseDepthFirst","visitor","children","length","transformCameraConfiguration","cameraConfiguration","modelMatrix","undefined","position","target","applyMatrix4","colorIndex","color","_colors","newColor","generateRandomColor","set","Math","floor","g","b","colorRGB","hue","random","saturation","lightness","setHSL","clickOrTouchEventOffset","ev","rect","getBoundingClientRect","MouseEvent","offsetX","clientX","left","offsetY","clientY","top","changedTouches","touch","Map","EventTrigger","_listeners","listener","push","index","indexOf","splice","args","forEach","assertNever","x","message","Error","NumericRange","from","count","toInclusive","Array","values","other","range","intersects","createFromInterval","max","min","action","determinePowerOfTwoDimensions","elementCount","width","ceilToPowerOfTwo","sqrt","height","log2","log","v","pow","ceil","right","maxSubtreeDepth","r0","r1","balance","traverse","contains","intersectsOrCoinciding","newNode","addRange","fromIndexNodesAndBalance","canUnionLeft","canUnionRight","newLeft","leftRange","soak","newRight","rightRange","unioned","union","newThis","soakedRange","nodeToReturn","leftSubTreeSize","rightSubTreeSize","rotateSmallerRight","rotateRight","rotateSmallerLeft","rotateLeft","clone","node","isInside","hasIntersectionWith","leftRes","rightRes","unionRange","nextRoot","begin","endInclusive","rootNode","add","removeRange","ranges","forEachRange","result","num","arr","toIndexArray","Set","originalRanges","toRangeArray","newRanges","otherSet","leftBoundRange","rightBoundRange","invertedRanges","st","packFloatInto","f","targetBuffer","offset","F","abs","Sign","step","Exponent","Mantissa","exp2","mod","edge","y","DynamicDefragmentedBuffer","initialSize","type","_numFilled","_batchIdCounter","_batchMap","_type","minimalPowerOfTwo","_buffer","array","isReallocated","newSize","allocateNewBuffer","batchId","createBatch","bufferIsReallocated","batch","copyWithin","buffer","_currentTail","prev","next","currentBatch","delete","newBuffer","emptyGeometry","_isDisposed","_referenceCount","ensureNotDisposed","dispose","meshes","filter","map","mesh","geometry","updateVars","camPos","bounds","boundingBox","super","_activeLevel","_levels","isLOD","autoUpdate","_boundingBox","copy","distance","sort","visible","camera","updateCurrentLevel","levels","matrixWorld","cameraZoom","zoom","setFromMatrixPosition","distanceToCamera","distanceToPoint","findIndex","getBox3CornerPoints","box","z","isMobileOrTablet","check","navigator","userAgent","vendor","window","opera","test","substr","renderer","_originalState","_renderer","alpha","clearColor","getClearColor","clearAlpha","getClearAlpha","setClearColor","size","getSize","setSize","enabled","localClippingEnabled","autoClear","renderTarget","getRenderTarget","setRenderTarget","revealEnv","publicPath","workerList","numberOfWorkers","determineNumberOfWorkers","newWorker","worker","createWorker","activeJobCount","messageIdCounter","async","actualWorkerVersion","getVersion","e","minWorkerVersion","majorMin","minorMin","patchMin","split","parseInt","majorWorker","minorWorker","patchWorker","errorMessage","checkWorkerVersion","catch","error","workerObjUrl","URL","revokeObjectURL","_defaultPool","workerUrl","options","url1","url2","location","origin","isRelative","url","match","constructedURLs","startsWith","host","console","isTheSameDomain","Worker","blob","Blob","JSON","stringify","createObjectURL","work","targetWorker","reduce","bestWorker","candidate","hardwareConcurrency","TimestampedContainer","_value","_lastAccessTime","Date","now","MemoryRequestCache","maxElementsInCache","removeCallback","defaultCleanupCount","_data","_maxElementsInCache","_defaultCleanupCount","_removeCallback","id","has","data","isFull","cleanCache","insert","allResults","entries","lastAccessTime","entry","pop","remove","clear","MostFrequentlyUsedCache","capacity","disposeCallback","_cache","_retrieves","_capacity","_disposeCallback","retrieveCount","ensureWithinCapacity","keysForRemoval","keys","retrivalCount","slice","disposeAttributeArrayOnUpload","version","maxTreeIndex","unit","sectorsById","sectors","sectorId","accepted","containsPoint","intersectsBox","allBounds","corners","toArray","numClusters","clusters","clusterCounts","idxs","fill","clusterBounds","_","biggestCluster","idx","cluster","expandByPoint","intersectingBounds","merged","projectionMatrix","inverseCameraModelMatrix","frustumMatrix","multiplyMatrices","frustum","setFromProjectionMatrix","parseCadMetadataV8","metadata","parentIds","sector","facesFile","quadSize","coverageFactors","xy","yz","xz","recursiveCoverageFactors","fileName","downloadSize","indexFile","determineFacesFile","bb","min_x","min_y","min_z","max_x","max_y","max_z","path","depth","estimatedDrawCallCount","estimatedRenderCost","estimatedTriangleCount","createSectorMetadata","parentId","rootSector","populateCoverageFactorsFromAnchestors","validFacesFileSection","hasDummyFacesFileSection","child","parsedJson","WellKnownDistanceToMeterConversionFactors","modelMetadataProvider","modelDataProvider","cadMetadataParser","blobFileName","_currentModelIdentifier","_modelMetadataProvider","_modelDataProvider","_cadSceneParser","_blobFileName","modelIdentifier","blobBaseUrlPromise","getModelUri","modelMatrixPromise","getModelMatrix","modelCameraPromise","getModelCamera","blobBaseUrl","json","getJsonFile","scene","parse","conversionFactor","makeScale","multiply","createScaleToMetersModelMatrix","inverseModelMatrix","invert","modelBaseUrl","geometryClipBox","LevelOfDetail","sectorPath","_lod","Discarded","_updatedTimestamp","determineSectorDepth","_group","geomtryGroup","levelOfDetail","resetGeometry","reference","updateMatrixWorld","dereference","modelMetadata","modelBounds","sectorNodeMap","buildScene","parent","sectorGroup","matrixAutoUpdate","setModelTransformation","matrix","out","workerPool","defaultPool","parseDetailed","parseSimple","parseCtm","quadsArrayBuffer","postWorkToAvailable","parseQuads","sectorArrayBuffer","parseSector","ctmArrayBuffer","computeBoundingBoxFromCenterAndRadiusAttributesVars","centerA","centerB","sphere","computeBoundingBoxFromVertexAttributesVars","vertex1","vertex2","vertex3","vertex4","computeBoundingBoxFromInstanceMatrixAttributesVars","instanceMatrix","computeBoundingBoxFromEllipseAttributesVars","center","filterPrimitivesOutsideClipBox","attributesByteValues","attributes","clipBox","getBoundsOfElementsCallback","elementSize","attributeFloatValues","Float32Array","instanceBbox","filteredByteValues","Uint8Array","filteredCount","elementValues","subarray","filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix","baseBox","instanceMatrixAttribute","outBox","elementIndex","baseBoundingBox","BYTES_PER_ELEMENT","computeBoundingBoxFromInstanceMatrixAttributes","filterPrimitivesOutsideClipBoxByCenterAndRadius","radiusAattributeName","radiusBattributeName","centerAattribute","centerBattribute","radiusAattribute","radiusBattribute","readAttribute","attribute","radiusA","radiusB","getBoundingBox","computeBoundingBoxFromCenterAndRadiusAttributes","filterPrimitivesOutsideClipBoxByVertices","vertex1attribute","vertex2attribute","vertex3attribute","vertex4attribute","vertex1Attribute","vertex2Attribute","vertex3Attribute","vertex4Attribute","setFromPoints","computeBoundingBoxFromVertexAttributes","filterPrimitivesOutsideClipBoxByEllipse","radius1AttributeName","radius2AttributeName","centerAttribute","horizontalRadiusAttribute","verticalRadiusAttribute","heightAttribute","radius1Attribute","radius2Attribute","radius1","radius2","extent","setFromCenterAndSize","computeBoundingBoxFromEllipseAttributes","filterInstanceMeshVars","baseBounds","instanceBounds","filterInstanceMesh","vertices","indices","instanceMesh","makeEmpty","j","triangleOffset","triangleCount","v0","v1","v2","filteredOffset","instanceCount","treeIndices","filteredInstanceMatrices","instanceMatrices","filteredTreeIndices","filteredColors","indexOffset","elementInstanceMatrix","elementColor","colors","elementTreeIndex","boxGeometry","boxGeometryBoundingBox","getIndex","getAttribute","normal","computeBoundingBox","quadGeometry","quadGeometryBoundingBox","trapeziumGeometry","trapeziumGeometryBoundingBox","Uint16Array","setFromArray","coneGeometry","coneGeometryBoundingBox","positions","torusLodGeometries","torusGeometryBoundingBox","transformFunc","u","PI","tubularSegments","radialSegments","segmentsX","segmentsY","segmentsXInv","segmentsYInv","generatePlane3D","nutGeometry","nutGeometryBoundingBox","makeRotationX","createTriangleMeshes","triangleMeshes","material","filteredTriangleMeshes","isTriangleMeshWithinArgs","isTriangleMeshWithin","onUpload","setIndex","setAttribute","boundingSphere","getBoundingSphere","obj","fileId","userData","CdfModelDataProvider","client","getDefaultRequestHeaders","baseUrl","headers","Accept","input","retries","fetch","err","fetchWithRetry","method","arrayBuffer","CdfModelIdentifier","modelId","revisionId","modelFormat","revealInternalId","String","File3dFormat","cadFromCdfToThreeMatrix","applyDefaultModelTransformation","format","RevealCadModel","premultiply","EptPointCloud","Model3DOutputList","outputs","outputFormat","supportedVersions","candidates","_client","toString","model","revisions3D","retrieve","rotation","makeRotationFromEuler","mostRecentOutput","getOutputs","findMostRecentOutput","directoryId","blobId","getBaseUrl","getRequestPath","project","params","response","status","items","fetchWithStatusCheck","ok","body","LocalModelIdentifier","localPath","Promise","resolve","VERSION","MIXPANEL_TOKEN","applicationId","eventProps","init","disable_cookie","disable_persistence","ip","property_blacklist","reset","identify","_sessionProps","application","sessionId","replace","innerTrackEvent","logMetrics","globalThis","revealMetricsLogger","metricsLogger","eventName","combined","track","toolName","trackEvent","nodeCollectionClassToken","appearance","style","stack","worldToViewportVars","renderSize","worldToNormalizedViewportCoordinates","position3D","worldToViewportCoordinates","canvas","domElement","canvasWidth","canvasHeight","round","BoundingBoxClipper","_clippingPlanes","_box","updatePlanes","setFromNormalAndCoplanarPoint","minX","maxX","minY","maxY","minZ","maxZ","_disposedEvent","_disposed","event","handler","subscribe","unsubscribe","fire","unsubscribeAll","dimensions","_removedElements","_dimensions","_cells","_bounds","element","cell","cellsIntersecting","visitedElements","candidateElement","dimX","dimY","relativeBoundsMinX","relativeBoundsMaxX","relativeBoundsMinY","relativeBoundsMaxY","clamp","minI","maxI","minJ","maxJ","viewer","_htmlOverlays","_compositeOverlays","_preallocatedVariables","camNormal","point","nearPlane","farPlane","position2D","_onSceneRenderedHandler","onSceneRendered","_onViewerDisposedHandler","onViewerDisposed","_options","_viewer","on","scheduleUpdate","forceUpdate","trackCreateTool","getCamera","info","off","htmlElement","viewerDomElement","visibility","appendChild","getComputedStyle","removeChild","state","overlays","cleanupClusterElements","updateNewElementSizes","viewerCamera","viewerRenderer","getWorldPosition","getWorldDirection","addScaledVector","near","far","positionUpdatedCallback","insideCameraPlanes","distanceTo","clusterElements","commitDOMChanges","clientRect","offsetLeft","offsetTop","opacity","transition","fadeIn","fadeOut","clusteringOptions","clusterByOverlapInScreenSpace","createClusterElementCallback","canvasBounds","bottom","canvasSize","grid","elementBounds","createElementBounds","clusterMidpoint","removeOverlappingElements","midpoint","divideScalar","compositeElement","addComposite","treeIndex","cadModel","_cadModel","_rootTreeIndex","preloadBoundingBoxData","_treeBoundingBoxdata","then","expandRadius","expandData","all","direction","transform","resetNodeTransformByTreeIndex","setPosition","setNodeTransformByTreeIndex","rootTreeIndexBoundingBox","getBoundingBoxByTreeIndex","rootBoundingBox","getCenter","subTreeBoundingBoxes","getSubtreeTreeIndices","subTreeIndices","subTreeIndex","subTreeIndexBoundingBoxCenter","rootCenter","subTreeCenters","subVectors","payloads","payload","hideCameraHelper","_cameraHelper","addObject3D","removeObject3D","Corner","defaultAxisBoxCompassConfig","ringLabel","labelDelta","fontSize","fontColor","tickColor","defaultFaceConfig","label","outlineSize","outlineColor","faceColor","defaultAxisBoxConfig","corner","BottomRight","padding","animationSpeed","faces","xPositiveFace","xNegativeFace","yPositiveFace","yNegativeFace","zPositiveFace","zNegativeFace","compass","config","_dynamicUpdatePosition","_updateClickDiv","_screenPosition","_boxFaceGeometry","_raycastCamera","_raycaster","_layoutConfig","_axisGroup","_interactiveObjects","createAxisCross","_disposeClickDiv","createClickDiv","addAxisBoxToViewer","removeUiObject","querySelector","divElement","document","createElement","zIndex","xMouse","yMouse","addEventListener","mouseDownEvent","button","dispatchEvent","mouseMoveEvent","preventDefault","mouseUpEvent","handleClick","axisGroup","xAbsolute","yAbsolute","isAbsolute","clientWidth","TopRight","clientHeight","TopLeft","BottomLeft","addUiObject","xScreenPos","yScreenPos","boundingRect","xNdc","yNdc","setFromCamera","rayOrigin","rayDirection","normalize","intersectObjects","targetPosition","targetUp","upVector","moveCameraTo","cameraControls","interactiveObjects","createBoxFaces","createCompass","setupTransformOnRender","onBeforeRender","quaternion","facesConfig","createBoxFace","compassPlaneGeometry","createCompassTexture","side","transparent","sin","cos","up","lookAt","compassLayout","textureSize","context","getContext","halfSize","radius","tickWidth","tickSpace","strokeStyle","getStyle","lineWidth","setLineDash","beginPath","arc","stroke","font","textAlign","fillStyle","fillText","faceConfig","fillRect","face","getFaceTexture","multiplyScalar","parameters","targetAxis","targetUpAxis","currentCameraPosition","cameraTarget","getState","targetRelativeStartPosition","sub","normalizedFrom","omega","acos","dot","animation","Tween","forward","fromRotation","toRotation","setFromRotationMatrix","makeBasis","cross","angleTo","tmpPosition","tmpRotation","cachedCameraControlsEnabled","to","onUpdate","slerpQuaternions","setRotationFromQuaternion","start","onStart","onComplete","setState","update","MapProviders","MapboxMode","MapboxStyle","MapboxId","MapboxImageFormat","BingMapType","BingMapImageFormat","HereMapType","HereMapScheme","HereMapImageFormat","mapConfig","_intervalId","_onCameraChange","handleCameraChange","mapProvider","getMapProvider","_map","PLANAR","coords","datumsToSpherical","latlong","latitude","longitude","bound","models","getModelBoundingBox","requestRedraw","timeOut","setInterval","setTimeout","clearInterval","provider","BingMap","APIKey","HereMap","appCode","scheme","imageFormat","MapboxMap","tileFormat","OpenStreetMap","latLong","_maps","latLongToWorldCoordinates","date","_nodeCollectionAndAppearance","_model","_date","_index","assignStyledNodeCollection","nodes","nodeAppearance","unassignStyledNodeCollection","nodeCollection","trackCadModelStyled","classToken","_playback","_events","dateChanged","_keyframes","keyframe","sortKeyframesByDates","find","getKeyframeDate","startDate","endDate","totalDurationInMilliSeconds","stop","playState","dateInMs","getTime","tween","currentKeyframeIndex","prevIndex","deactivate","activate","activeKeyframe","isPlaying","pause","isPaused","resume","_boundingBoxes","setOptions","showDetailedSectors","showDiscardedSectors","showSimpleSectors","colorBy","leafsOnly","sectorPathFilterRegex","updateBoundingBoxes","getModelTransformation","shouldShowLod","Simple","Detailed","selectedSectorNodes","cadNode","isSectorNode","sectorNode","isSectorAcceptedByCurrentFilter","some","isLeaf","bboxNode","createBboxNodeFor","RegExp","allSelectedNodes","Colors","green","lerpHSL","red","yellow","nodesByTimestamp","updatedTimestamp","indexOfNode","determineColor"],"mappings":"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","file":"tools.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})((typeof self !== 'undefined' ? self : this), function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"https://apps-cdn.cogniteapp.com/@cognite/reveal-parser-worker/1.2.0/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 65);\n","module.exports = require(\"three\");","/*!\n * Copyright 2021 Cognite AS\n */\n\ninterface WithChildren<T> {\n readonly children: T[];\n}\n\nexport function traverseDepthFirst<T extends WithChildren<T>>(root: T, visitor: (element: T) => boolean): void {\n if (!visitor(root)) {\n return;\n }\n\n for (let i = 0; i < root.children.length; i++) {\n traverseDepthFirst(root.children[i], visitor);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nimport { CameraConfiguration } from './CameraConfiguration';\n\nexport function transformCameraConfiguration(\n cameraConfiguration: CameraConfiguration | undefined,\n modelMatrix: THREE.Matrix4\n): CameraConfiguration | undefined {\n if (cameraConfiguration === undefined) {\n return undefined;\n }\n\n const { position, target } = cameraConfiguration;\n position.applyMatrix4(modelMatrix);\n target.applyMatrix4(modelMatrix);\n return {\n position,\n target\n };\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\n/**\n * Utility class for creating reasonable visible colors. Mainly meant for use\n * in debugging.\n */\nexport class RandomColors {\n private static readonly _colors: Map<number, THREE.Color> = new Map();\n\n /**\n * Returns a color as a THREE.Color.\n * @param colorIndex\n * @returns\n */\n static color(colorIndex: number): THREE.Color {\n const color = RandomColors._colors.get(colorIndex);\n if (color !== undefined) {\n return color;\n }\n\n const newColor = RandomColors.generateRandomColor();\n RandomColors._colors.set(colorIndex, newColor);\n return newColor;\n }\n\n /**\n * Returns color as RGB components between 0 and 255.\n * @param colorIndex Return\n * @returns\n */\n static colorRGB(colorIndex: number): [number, number, number] {\n const c = RandomColors.color(colorIndex);\n return [Math.floor(c.r * 255), Math.floor(c.g * 255), Math.floor(c.b * 255)];\n }\n\n /**\n * Returns a color string suitable for usage in CSS styles.\n * @param colorIndex\n * @returns\n */\n static colorCSS(colorIndex: number): string {\n const [r, g, b] = RandomColors.colorRGB(colorIndex);\n return `rgb(${r}, ${g}, ${b})`;\n }\n\n /**\n * Returns a random color with reasonable lightness and saturation\n * to make the color easily distinguishable from other colors.\n */\n static generateRandomColor(): THREE.Color {\n const hue = Math.random();\n const saturation = 0.4 + Math.random() * 0.6;\n const lightness = 0.3 + 0.4 * Math.random();\n return new THREE.Color().setHSL(hue, saturation, lightness);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Determines clicked or touched coordinate as offset\n * @param ev An MouseEvent or TouchEvent.\n * @param target HTML element to find coordinates relative to.\n * @returns A struct containing coordinates relative to the HTML element provided.\n */\nexport function clickOrTouchEventOffset(ev: MouseEvent | TouchEvent, target: HTMLElement) {\n const rect = target.getBoundingClientRect();\n\n if (ev instanceof MouseEvent) {\n return {\n offsetX: ev.clientX - rect.left,\n offsetY: ev.clientY - rect.top\n };\n } else if (ev.changedTouches.length > 0) {\n const touch = ev.changedTouches[0];\n return {\n offsetX: touch.clientX - rect.left,\n offsetY: touch.clientY - rect.top\n };\n }\n\n // Invalid event\n return {\n offsetX: -1,\n offsetY: -1\n };\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Subscribable event source.\n */\nexport class EventTrigger<TListener extends (...args: any[]) => void> {\n private readonly _listeners: TListener[] = [];\n\n subscribe(listener: TListener): void {\n this._listeners.push(listener);\n }\n\n unsubscribe(listener: TListener): void {\n const index = this._listeners.indexOf(listener);\n if (index !== -1) {\n this._listeners.splice(index, 1);\n }\n }\n\n unsubscribeAll(): void {\n this._listeners.splice(0);\n }\n\n fire(...args: Parameters<TListener>): void {\n this._listeners.forEach(listener => listener(...args));\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * See https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#union-exhaustiveness-checking\n */\nexport function assertNever(x: never, message?: string): never {\n throw new Error(message || 'Unexpected object: ' + x);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport class NumericRange {\n readonly from: number;\n readonly count: number;\n readonly toInclusive: number;\n\n constructor(from: number, count: number) {\n if (count < 0) {\n throw new Error('Range cannot have negative number of elements');\n }\n\n this.from = from;\n this.count = count;\n this.toInclusive = from + count - 1;\n }\n\n static createFromInterval(from: number, toInclusive: number): NumericRange {\n return new NumericRange(from, toInclusive - from + 1);\n }\n\n *values(): Generator<number> {\n for (let i = this.from; i <= this.toInclusive; ++i) {\n yield i;\n }\n }\n\n toArray(): number[] {\n return Array.from(this.values());\n }\n\n equal(other: NumericRange): boolean {\n return this.from === other.from && this.count === other.count;\n }\n\n contains(value: number): boolean {\n return value >= this.from && value <= this.toInclusive;\n }\n\n intersects(range: NumericRange): boolean {\n return this.from <= range.toInclusive && this.toInclusive >= range.from;\n }\n\n intersectsOrCoinciding(range: NumericRange): boolean {\n return this.from <= range.toInclusive + 1 && this.toInclusive + 1 >= range.from;\n }\n\n intersectionWith(range: NumericRange): NumericRange | undefined {\n if (!this.intersects(range)) {\n return undefined;\n } else {\n return NumericRange.createFromInterval(\n Math.max(this.from, range.from),\n Math.min(this.toInclusive, range.toInclusive)\n );\n }\n }\n\n isInside(range: NumericRange): boolean {\n return this.from >= range.from && this.toInclusive <= range.toInclusive;\n }\n\n union(range: NumericRange): NumericRange {\n return NumericRange.createFromInterval(\n Math.min(this.from, range.from),\n Math.max(this.toInclusive, range.toInclusive)\n );\n }\n\n forEach(action: (value: number) => void): void {\n for (let i = this.from; i <= this.toInclusive; ++i) {\n action(i);\n }\n }\n\n str() {\n return '(' + this.from + ', ' + this.toInclusive + ')';\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Computes minimal power-of-two width and height that holds at least the number of elements provided.\n * This is useful to compute texture sizes.\n */\nexport function determinePowerOfTwoDimensions(elementCount: number): { width: number; height: number } {\n const width = Math.max(1, ceilToPowerOfTwo(Math.sqrt(elementCount)));\n const height = Math.max(1, ceilToPowerOfTwo(elementCount / width));\n return { width, height };\n}\n\nconst log2 = Math.log(2);\nfunction ceilToPowerOfTwo(v: number): number {\n return Math.pow(2, Math.ceil(Math.log(v) / log2));\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { IndexNode } from './IndexSet';\nimport { LeafIndexNode } from './LeafIndexNode';\nimport { NumericRange } from '../NumericRange';\nimport assert from 'assert';\n\nexport class IntermediateIndexNode {\n readonly range: NumericRange;\n readonly maxSubtreeDepth: number;\n readonly left: IndexNode;\n readonly right: IndexNode;\n readonly count: number;\n\n constructor(left: IndexNode, right: IndexNode) {\n this.left = left;\n this.right = right;\n\n this.maxSubtreeDepth = Math.max(this.left.maxSubtreeDepth, this.right.maxSubtreeDepth) + 1;\n this.range = NumericRange.createFromInterval(this.left.range.from, this.right.range.toInclusive);\n this.count = this.left.count + this.right.count;\n }\n\n static fromIndexNodesAndBalance(r0: IndexNode, r1: IndexNode) {\n if (r0.range.from > r1.range.toInclusive + 1) {\n return new IntermediateIndexNode(r1, r0).balance();\n } else if (r0.range.toInclusive + 1 < r1.range.from) {\n return new IntermediateIndexNode(r0, r1).balance();\n } else {\n // Help, overlapping nodes! There is an error somewhere!\n assert(false, 'Internal error in IndexSet: Overlapping nodes');\n }\n }\n\n traverse(visitor: (range: NumericRange) => void) {\n // Note! The actual ranges are kept in leafs, so we do not visit \"this\"\n this.left.traverse(visitor);\n this.right.traverse(visitor);\n }\n\n contains(index: number): boolean {\n if (!this.range.contains(index)) {\n return false;\n }\n\n return this.left.contains(index) || this.right.contains(index);\n }\n\n addRange(range: NumericRange): IndexNode {\n const canUnionThis = range.intersectsOrCoinciding(this.range);\n\n if (!canUnionThis) {\n // The range is either entirely above or below the range of this node\n if (range.from < this.range.from) {\n const newNode = this.left.addRange(range);\n return IntermediateIndexNode.fromIndexNodesAndBalance(newNode, this.right);\n } else {\n const newNode = this.right.addRange(range);\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left, newNode);\n }\n }\n\n const canUnionLeft = range.intersectsOrCoinciding(this.left.range);\n const canUnionRight = range.intersectsOrCoinciding(this.right.range);\n\n if (canUnionLeft && canUnionRight) {\n // Range intersects both subtrees...\n const [newLeft, leftRange] = this.left.soak(range);\n const [newRight, rightRange] = this.right.soak(range);\n\n const unioned = leftRange.union(rightRange);\n\n if (newLeft === undefined && newRight === undefined) {\n return new LeafIndexNode(unioned);\n } else if (newLeft === undefined && newRight !== undefined) {\n // Last term is added to please compiler\n return newRight.addRange(unioned);\n } else if (newRight === undefined && newLeft !== undefined) {\n // ---\"---\n return newLeft.addRange(unioned);\n }\n\n // We have guaranteed that newLeft and newRight is defined\n const newNode = IntermediateIndexNode.fromIndexNodesAndBalance(newLeft!, newRight!);\n\n return newNode.addRange(unioned);\n } else if (canUnionLeft) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left.addRange(range), this.right);\n } else if (canUnionRight) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left, this.right.addRange(range));\n } else {\n // Range lies between ranges of left and right subtree,\n // add to smallest\n if (this.left.maxSubtreeDepth < this.right.maxSubtreeDepth) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left.addRange(range), this.right);\n } else {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left, this.right.addRange(range));\n }\n }\n }\n\n removeRange(range: NumericRange): IndexNode | undefined {\n // If input range does not intersect with this range, return\n if (!range.intersects(this.range)) {\n return this;\n }\n\n const [newThis, soakedRange] = this.soak(range);\n\n let leftRange: NumericRange | undefined = undefined;\n let rightRange: NumericRange | undefined = undefined;\n\n // If soakedRange extends to either the left or right to the\n // numeric range, we take the ranges extending out and insert anew.\n if (soakedRange.from < range.from) {\n leftRange = NumericRange.createFromInterval(soakedRange.from, range.from - 1);\n }\n\n if (soakedRange.toInclusive > range.toInclusive) {\n rightRange = NumericRange.createFromInterval(range.toInclusive + 1, soakedRange.toInclusive);\n }\n\n if (newThis === undefined) {\n // If all ranges in this was soaked up, create new node with\n // non-empty left and right ranges\n if (leftRange !== undefined && rightRange !== undefined) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(\n new LeafIndexNode(leftRange),\n new LeafIndexNode(rightRange)\n );\n } else if (leftRange != undefined) {\n return new LeafIndexNode(leftRange);\n } else if (rightRange != undefined) {\n return new LeafIndexNode(rightRange);\n } else {\n return undefined;\n }\n } else {\n // Add non-empty left- and right ranges\n let nodeToReturn = newThis;\n\n if (leftRange !== undefined) {\n nodeToReturn = nodeToReturn.addRange(leftRange);\n }\n\n if (rightRange !== undefined) {\n nodeToReturn = nodeToReturn.addRange(rightRange);\n }\n\n return nodeToReturn;\n }\n }\n\n balance(): IntermediateIndexNode {\n const leftSubTreeSize = this.left.maxSubtreeDepth;\n const rightSubTreeSize = this.right.maxSubtreeDepth;\n\n if (rightSubTreeSize + 2 <= leftSubTreeSize) {\n // Left side too deep\n const newLeft = (this.left as IntermediateIndexNode).rotateSmallerRight();\n const newNode = new IntermediateIndexNode(newLeft, this.right).rotateRight().balance();\n return newNode;\n } else if (leftSubTreeSize + 2 <= rightSubTreeSize) {\n // Right side too deep\n const newRight = (this.right as IntermediateIndexNode).rotateSmallerLeft();\n const newNode = new IntermediateIndexNode(this.left, newRight).rotateLeft().balance();\n return newNode;\n }\n\n return this;\n }\n\n clone(): IntermediateIndexNode {\n return IntermediateIndexNode.fromIndexNodesAndBalance(this.left.clone(), this.right.clone());\n }\n\n hasIntersectionWith(node: IndexNode): boolean {\n if (!node.range.intersects(this.range)) {\n return false;\n }\n\n // Make sure containing range is the \"this\"\n if (this.range.isInside(node.range)) {\n return node.hasIntersectionWith(this);\n }\n\n // Here, we know this range is not contained within node range\n if (this.left.range.intersects(node.range) && this.left.hasIntersectionWith(node)) {\n return true;\n }\n\n if (this.right.range.intersects(node.range) && this.right.hasIntersectionWith(node)) {\n return true;\n }\n\n return false;\n }\n\n /*\n * Utilities\n */\n // Soak up/ delete numeric range touching the input range,\n // returning union of soaked ranges and input range\n // This operation is used as a substep when adding a range - the range\n // is first used to \"soak\" up all touching ranges in the tree, since these must be part of a\n // common union range at the end of the insertion. In the end, the range, unioned with\n // all its soaked ranges in the tree, is inserted normally.\n soak(range: NumericRange): [IndexNode | undefined, NumericRange] {\n let [leftRes, leftRange]: [IndexNode | undefined, NumericRange] = [this.left, range];\n let [rightRes, rightRange]: [IndexNode | undefined, NumericRange] = [this.right, range];\n\n // Both subtrees are inside range, soak up everything\n if (this.right.range.isInside(range) && this.left.range.isInside(range)) {\n return [undefined, range];\n }\n\n // Compute what's left on the left, and the soaked-up range\n if (this.left.range.intersectsOrCoinciding(range)) {\n [leftRes, leftRange] = this.left.soak(range);\n }\n\n // Compute what's left on the right, and the soaked-up range\n if (this.right.range.intersectsOrCoinciding(range)) {\n [rightRes, rightRange] = this.right.soak(range);\n }\n\n // The two soaked-up ranges must touch (they both contain the argument range)\n const unionRange = leftRange.union(rightRange);\n\n if (rightRes == undefined) {\n return [leftRes, unionRange];\n } else if (leftRes == undefined) {\n return [rightRes, unionRange];\n } else {\n const newNode = IntermediateIndexNode.fromIndexNodesAndBalance(leftRes, rightRes);\n return [newNode, unionRange];\n }\n }\n\n /*\n * Rotations\n */\n rotateRight(): IntermediateIndexNode {\n if (!('right' in this.left)) {\n // Left node is leaf node. Abort rotation\n return this;\n }\n\n return new IntermediateIndexNode(\n (this.left as IntermediateIndexNode).left,\n new IntermediateIndexNode((this.left as IntermediateIndexNode).right, this.right)\n );\n }\n\n rotateLeft(): IntermediateIndexNode {\n if (!('left' in this.right)) {\n // Left node is leaf node. Abort rotation\n return this;\n }\n\n return new IntermediateIndexNode(\n new IntermediateIndexNode(this.left, (this.right as IntermediateIndexNode).left),\n (this.right as IntermediateIndexNode).right\n );\n }\n\n // Rotate so that smaller subtree is on left\n rotateSmallerLeft(): IntermediateIndexNode {\n if (this.left.maxSubtreeDepth > this.right.maxSubtreeDepth) {\n // If left subtree depth is larger, it must be of type IntermediateIndexNode\n let nextRoot = this.rotateRight() as IntermediateIndexNode;\n nextRoot = nextRoot.rotateSmallerLeft();\n return nextRoot;\n }\n\n return this;\n }\n\n // Rotate so that smaller subtree is on right\n rotateSmallerRight(): IntermediateIndexNode {\n if (this.right.maxSubtreeDepth > this.left.maxSubtreeDepth) {\n // If left subtree depth is larger, it must be of type IntermediateIndexNode\n let nextRoot = this.rotateLeft() as IntermediateIndexNode;\n nextRoot = nextRoot.rotateSmallerRight();\n return nextRoot;\n }\n\n return this;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS../NumericRange\n */\nimport { IntermediateIndexNode } from './IntermediateIndexNode';\nimport { IndexNode } from './IndexSet';\nimport { NumericRange } from '../NumericRange';\n\nexport class LeafIndexNode {\n readonly range: NumericRange;\n readonly count: number;\n readonly maxSubtreeDepth: number;\n\n static fromInterval(begin: number, endInclusive: number) {\n return new LeafIndexNode(NumericRange.createFromInterval(begin, endInclusive));\n }\n\n constructor(range: NumericRange) {\n this.range = range;\n this.maxSubtreeDepth = 0;\n this.count = range.count;\n }\n\n traverse(visitor: (range: NumericRange) => void) {\n visitor(this.range);\n }\n\n contains(index: number): boolean {\n return this.range.contains(index);\n }\n\n addRange(range: NumericRange): IndexNode {\n if (this.range.intersectsOrCoinciding(range)) {\n // Create union range\n return new LeafIndexNode(this.range.union(range));\n }\n\n return IntermediateIndexNode.fromIndexNodesAndBalance(this, new LeafIndexNode(range));\n }\n\n removeRange(range: NumericRange): IndexNode | undefined {\n if (!range.intersects(this.range)) {\n return this;\n }\n\n if (this.range.isInside(range)) {\n return undefined;\n }\n\n let leftRange: NumericRange | undefined = undefined;\n let rightRange: NumericRange | undefined = undefined;\n\n if (this.range.from < range.from) {\n leftRange = NumericRange.createFromInterval(this.range.from, range.from - 1);\n }\n\n if (this.range.toInclusive > range.toInclusive) {\n rightRange = NumericRange.createFromInterval(range.toInclusive + 1, this.range.toInclusive);\n }\n\n if (leftRange != undefined && rightRange != undefined) {\n return IntermediateIndexNode.fromIndexNodesAndBalance(\n new LeafIndexNode(leftRange),\n new LeafIndexNode(rightRange)\n );\n } else if (leftRange != undefined) {\n return new LeafIndexNode(leftRange);\n } else if (rightRange != undefined) {\n return new LeafIndexNode(rightRange);\n } else {\n return undefined;\n }\n }\n\n hasIntersectionWith(node: IndexNode): boolean {\n return node.range.intersects(this.range);\n }\n\n soak(range: NumericRange): [IndexNode | undefined, NumericRange] {\n if (this.range.intersectsOrCoinciding(range)) {\n return [undefined, this.range.union(range)];\n } else {\n return [this, range];\n }\n }\n\n clone(): LeafIndexNode {\n return new LeafIndexNode(this.range);\n }\n}\n","/*\n * Copyright 2021 Cognite AS\n */\nimport { IntermediateIndexNode } from './IntermediateIndexNode';\nimport { LeafIndexNode } from './LeafIndexNode';\nimport { NumericRange } from '../NumericRange';\n\nexport type IndexNode = IntermediateIndexNode | LeafIndexNode;\n\nexport class IndexSet {\n rootNode?: IndexNode;\n\n constructor(values?: Iterable<number>);\n constructor(values?: NumericRange);\n constructor(values?: Iterable<number> | NumericRange) {\n if (values == undefined) {\n this.rootNode = undefined;\n } else if (values instanceof NumericRange) {\n this.addRange(values);\n } else {\n for (const index of values) {\n this.add(index);\n }\n }\n }\n\n forEachRange(visitor: (range: NumericRange) => void) {\n if (this.rootNode) {\n this.rootNode.traverse(visitor);\n }\n }\n\n add(index: number) {\n const range = new NumericRange(index, 1);\n\n this.addRange(range);\n }\n\n addRange(range: NumericRange) {\n if (this.rootNode) {\n this.rootNode = this.rootNode.addRange(range);\n } else {\n this.rootNode = new LeafIndexNode(range);\n }\n }\n\n remove(index: number) {\n const range = new NumericRange(index, 1);\n this.removeRange(range);\n }\n\n removeRange(range: NumericRange) {\n if (this.rootNode) {\n this.rootNode = this.rootNode.removeRange(range);\n }\n\n // Do nothing if root is empty\n }\n\n contains(index: number): boolean {\n if (this.rootNode) {\n return this.rootNode.contains(index);\n }\n\n return false;\n }\n\n get count(): number {\n if (this.rootNode) {\n return this.rootNode.count;\n }\n\n return 0;\n }\n\n toRangeArray(): NumericRange[] {\n const ranges: NumericRange[] = [];\n this.forEachRange(range => {\n ranges.push(range);\n });\n return ranges;\n }\n\n toIndexArray(): number[] {\n const result: number[] = [];\n\n if (this.rootNode) {\n this.forEachRange(range => {\n range.forEach(num => {\n result.push(num);\n });\n });\n }\n\n return result;\n }\n\n toPlainSet(): Set<number> {\n const arr: number[] = this.toIndexArray();\n const st = new Set(arr);\n return st;\n }\n\n // NB: Assumes that this.ranges() are in order from left to right\n invertedRanges(): NumericRange[] {\n const originalRanges = this.toRangeArray();\n\n const newRanges: NumericRange[] = [];\n\n for (let i = 0; i < originalRanges.length - 1; i++) {\n if (originalRanges[i].toInclusive + 1 >= originalRanges[i + 1].from) {\n // Should not happen, but let's be safe\n continue;\n }\n newRanges.push(\n NumericRange.createFromInterval(originalRanges[i].toInclusive + 1, originalRanges[i + 1].from - 1)\n );\n }\n\n return newRanges;\n }\n\n unionWith(otherSet: IndexSet): IndexSet {\n if (this.rootNode) {\n otherSet.forEachRange(range => {\n this.rootNode = this.rootNode!.addRange(range);\n });\n } else {\n this.rootNode = otherSet.rootNode;\n }\n\n return this;\n }\n\n differenceWith(otherSet: IndexSet): IndexSet {\n if (this.rootNode) {\n otherSet.forEachRange(range => {\n this.rootNode = this.rootNode?.removeRange(range);\n });\n }\n\n return this;\n }\n\n hasIntersectionWith(otherSet: IndexSet | Set<number>): boolean {\n if (otherSet instanceof IndexSet) {\n if (this.rootNode === undefined || otherSet.rootNode === undefined) {\n return false;\n }\n\n return this.rootNode.hasIntersectionWith(otherSet.rootNode);\n } else {\n for (const index of otherSet) {\n if (this.contains(index)) {\n return true;\n }\n }\n\n return false;\n }\n }\n\n intersectWith(otherSet: IndexSet): IndexSet {\n if (this.rootNode && otherSet.rootNode) {\n // Tackle endpoints\n // Remove left bounds outside input set\n if (this.rootNode.range.from < otherSet.rootNode.range.from) {\n const leftBoundRange = NumericRange.createFromInterval(\n this.rootNode.range.from,\n otherSet.rootNode.range.from - 1\n );\n this.rootNode = this.rootNode.removeRange(leftBoundRange);\n\n if (!this.rootNode) {\n return this;\n }\n }\n\n // Remove right bounds outside input set\n if (this.rootNode.range.toInclusive > otherSet.rootNode.range.toInclusive) {\n const rightBoundRange = NumericRange.createFromInterval(\n otherSet.rootNode.range.toInclusive + 1,\n this.rootNode.range.toInclusive\n );\n this.rootNode = this.rootNode.removeRange(rightBoundRange);\n }\n\n // Invert otherSet ranges and remove them\n const invRanges = otherSet.invertedRanges();\n\n invRanges.forEach(range => {\n if (this.rootNode) {\n this.rootNode = this.rootNode.removeRange(range);\n }\n });\n } else if (this.rootNode) {\n // Otherset is empty, set this to empty as well\n this.rootNode = undefined;\n }\n return this;\n }\n\n clear(): void {\n this.rootNode = undefined;\n }\n\n clone(): IndexSet {\n const st: IndexSet = new IndexSet();\n\n if (this.rootNode) {\n st.rootNode = this.rootNode.clone();\n }\n\n return st;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n// https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float @ Arjan\n\nexport function packFloat(f: number): [number, number, number, number] {\n const F = abs(f);\n if (F == 0) {\n return [0, 0, 0, 0];\n }\n const Sign = step(0.0, -f);\n let Exponent = floor(log2(F));\n\n const Mantissa = F / exp2(Exponent);\n\n if (Mantissa < 1) Exponent -= 1;\n\n Exponent += 127;\n\n const rgba: [number, number, number, number] = [\n 128.0 * Sign + floor(Exponent * exp2(-1.0)),\n 128.0 * mod(Exponent, 2.0) + mod(floor(Mantissa * 128.0), 128.0),\n floor(mod(floor(Mantissa * exp2(23.0 - 8.0)), exp2(8.0))),\n floor(exp2(23.0) * mod(Mantissa, exp2(-15.0)))\n ];\n return rgba;\n}\n\nexport function packFloatInto(f: number, targetBuffer: Uint8ClampedArray, offset: number) {\n const F = abs(f);\n if (F == 0) {\n return;\n }\n const Sign = step(0.0, -f);\n let Exponent = floor(log2(F));\n\n const Mantissa = F / exp2(Exponent);\n\n if (Mantissa < 1) Exponent -= 1;\n\n Exponent += 127;\n\n targetBuffer[offset] = 128.0 * Sign + floor(Exponent * exp2(-1.0));\n targetBuffer[offset + 1] = 128.0 * mod(Exponent, 2.0) + mod(floor(Mantissa * 128.0), 128.0);\n targetBuffer[offset + 2] = floor(mod(floor(Mantissa * exp2(23.0 - 8.0)), exp2(8.0)));\n targetBuffer[offset + 3] = floor(exp2(23.0) * mod(Mantissa, exp2(-15.0)));\n}\n\nexport function unpackFloat4(packedFloat: [number, number, number, number]) {\n const [r, g, b, a] = packedFloat;\n const sign = 1.0 - step(128.0, r) * 2.0;\n const exponent = 2.0 * mod(r, 128.0) + step(128.0, g) - 127.0;\n if (exponent == -127) return 0;\n const mantissa = mod(g, 128.0) * 65536.0 + b * 256.0 + a + 8388608.0;\n return sign * exp2(exponent - 23.0) * mantissa;\n}\n\nfunction step(edge: number, x: number): number {\n return x < edge ? 0.0 : 1.0;\n}\n\nfunction exp2(x: number) {\n return Math.pow(2, x);\n}\n\nfunction mod(x: number, y: number) {\n return x - y * floor(x / y);\n}\n\nfunction floor(x: number) {\n return Math.floor(x);\n}\n\nfunction log2(x: number) {\n return Math.log(x) / Math.log(2);\n}\n\nfunction abs(x: number) {\n return Math.abs(x);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { TypedArray } from '../types';\n\ntype Batch = {\n from: number;\n count: number;\n prev: Batch | undefined;\n next: Batch | undefined;\n};\n\nexport class DynamicDefragmentedBuffer<T extends TypedArray> {\n public get length(): number {\n return this._numFilled;\n }\n\n public get buffer(): T {\n return this._buffer;\n }\n\n private _buffer: T;\n private _numFilled: number;\n private readonly _type: new (length: number) => T;\n\n private readonly _batchMap: Map<number, Batch>;\n private _currentTail: Batch | undefined;\n\n private _batchIdCounter: number;\n\n constructor(initialSize: number, type: new (length: number) => T) {\n this._numFilled = 0;\n this._batchIdCounter = 0;\n this._batchMap = new Map<number, Batch>();\n\n this._type = type;\n\n const minimalPowerOfTwo = Math.pow(2, Math.ceil(Math.log2(initialSize)));\n this._buffer = new type(minimalPowerOfTwo);\n }\n\n public add(array: T): { batchId: number; bufferIsReallocated: boolean } {\n let isReallocated = false;\n if (this._numFilled + array.length > this._buffer.length) {\n const newSize = Math.pow(2, Math.ceil(Math.log2(this._numFilled + array.length)));\n this.allocateNewBuffer(newSize);\n isReallocated = true;\n }\n\n this._buffer.set(array, this._numFilled);\n\n const batchId = this.createBatch(array);\n\n this._numFilled += array.length;\n\n return { batchId: batchId, bufferIsReallocated: isReallocated };\n }\n\n public remove(batchId: number) {\n const batch = this._batchMap.get(batchId);\n\n if (!batch) {\n throw new Error('batch does not exist in buffer');\n }\n\n this._buffer.copyWithin(batch.from, batch.from + batch.count, this.buffer.length);\n\n this._numFilled -= batch.count;\n\n if (this._currentTail === batch) {\n this._currentTail = batch.prev;\n }\n\n const prev = batch.prev;\n const next = batch.next;\n\n if (prev) {\n prev.next = next;\n }\n\n if (next) {\n next.prev = prev;\n }\n\n let currentBatch = next;\n\n while (currentBatch) {\n currentBatch.from -= batch.count;\n currentBatch = currentBatch.next;\n }\n\n this._batchMap.delete(batchId);\n }\n\n private createBatch(array: T) {\n const batch: Batch = {\n from: this._numFilled,\n count: array.length,\n prev: this._currentTail,\n next: undefined\n };\n\n if (this._currentTail) {\n this._currentTail.next = batch;\n }\n\n this._currentTail = batch;\n\n const batchId = this._batchIdCounter;\n this._batchIdCounter++;\n\n this._batchMap.set(batchId, batch);\n return batchId;\n }\n\n private allocateNewBuffer(newSize: number): void {\n const newBuffer = new this._type(newSize);\n newBuffer.set(this._buffer);\n\n this._buffer = newBuffer;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nconst emptyGeometry = new THREE.BufferGeometry();\n\n/**\n * Referenced count implementation of THREE.Group that\n * automatically disposes all geometries contained in meshes that\n * are direct children of the group.\n */\nexport class AutoDisposeGroup extends THREE.Group {\n private _isDisposed = false;\n private _referenceCount = 0;\n\n reference(): void {\n this.ensureNotDisposed();\n this._referenceCount++;\n }\n\n dereference(): void {\n this.ensureNotDisposed();\n if (this._referenceCount === 0) {\n throw new Error('No references');\n }\n if (--this._referenceCount === 0) {\n this.dispose();\n }\n }\n\n private dispose(): void {\n this.ensureNotDisposed();\n this._isDisposed = true;\n const meshes: THREE.Mesh[] = this.children.filter(x => x instanceof THREE.Mesh).map(x => x as THREE.Mesh);\n for (const mesh of meshes) {\n if (mesh.geometry !== undefined) {\n mesh.geometry.dispose();\n // // NOTE: Forcefully creating a new reference here to make sure\n // // there are no lingering references to the large geometry buffer\n mesh.geometry = emptyGeometry;\n }\n }\n }\n\n private ensureNotDisposed() {\n if (this._isDisposed) {\n throw new Error('Already disposed/dereferenced');\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\n// For BoundingBoxLOD.update()\nconst updateVars = {\n camPos: new THREE.Vector3(),\n bounds: new THREE.Box3()\n};\n\n/**\n * Class similar to THREE.LOD except that it doesn't use `matrixWorld` to determine distance to camera, but a\n * bounding box.\n */\nexport class BoundingBoxLOD extends THREE.Object3D {\n private readonly _boundingBox: THREE.Box3;\n private _activeLevel = 0;\n private readonly _levels: { distance: number; object: THREE.Object3D }[] = [];\n\n // Note! isLOD and autoUpdate is used by WebGLRenderer to perform automatic update of LOD\n // level before rendering\n public readonly isLOD = true;\n public readonly autoUpdate = true;\n\n constructor(boundingBox: THREE.Box3) {\n super();\n this._boundingBox = boundingBox.clone();\n this.type = 'BoundingBoxLOD';\n }\n\n setBoundingBox(boundingBox: THREE.Box3) {\n this._boundingBox.copy(boundingBox);\n }\n\n addLevel(object: THREE.Object3D, distance: number = 0) {\n this._levels.push({ object, distance: Math.abs(distance) });\n this._levels.sort((a, b) => b.distance - a.distance);\n object.visible = false;\n this.add(object);\n }\n\n /**\n * Returns the index of the current active LOD. 0 means highest detail.\n */\n getCurrentLevel() {\n return this._levels.length > 0 ? this._levels.length - this._activeLevel - 1 : 0;\n }\n\n /**\n * Update selected LOD level based on distance to camera.\n */\n update(camera: THREE.Camera) {\n this.updateCurrentLevel(camera);\n }\n\n private updateCurrentLevel(camera: THREE.Camera) {\n const levels = this._levels;\n const { camPos, bounds } = updateVars;\n bounds.copy(this._boundingBox).applyMatrix4(this.matrixWorld);\n const cameraZoom = camera instanceof THREE.PerspectiveCamera ? camera.zoom : 1.0;\n\n if (levels.length > 0) {\n camPos.setFromMatrixPosition(camera.matrixWorld);\n const distanceToCamera = bounds.distanceToPoint(camPos) / cameraZoom;\n\n levels[this._activeLevel].object.visible = false;\n this._activeLevel = levels.findIndex(p => distanceToCamera >= p.distance);\n this._activeLevel = this._activeLevel >= 0 ? this._activeLevel : levels.length - 1;\n levels[this._activeLevel].object.visible = true;\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nexport function getBox3CornerPoints(box: THREE.Box3): THREE.Vector3[] {\n return [\n new THREE.Vector3(box.min.x, box.min.y, box.min.z), // 000\n new THREE.Vector3(box.min.x, box.min.y, box.max.z), // 001\n new THREE.Vector3(box.min.x, box.max.y, box.min.z), // 010\n new THREE.Vector3(box.min.x, box.max.y, box.max.z), // 011\n new THREE.Vector3(box.max.x, box.min.y, box.min.z), // 100\n new THREE.Vector3(box.max.x, box.min.y, box.max.z), // 101\n new THREE.Vector3(box.max.x, box.max.y, box.min.z), // 110\n new THREE.Vector3(box.max.x, box.max.y, box.max.z) // 111\n ];\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport function isMobileOrTablet() {\n // https://stackoverflow.com/a/11381730/167251\n let check = false;\n (a => {\n if (\n /(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(\n a\n ) ||\n /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i.test(\n a.substr(0, 4)\n )\n ) {\n check = true;\n }\n })(navigator.userAgent || navigator.vendor || (window as any).opera);\n return check;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\ntype WebGLRendererState = {\n autoClear?: boolean;\n clearColor?: THREE.Color | string | number;\n clearAlpha?: number;\n size?: THREE.Vector2;\n localClippingEnabled?: boolean;\n renderTarget?: THREE.RenderTarget | null;\n};\n\nexport class WebGLRendererStateHelper {\n private _originalState: WebGLRendererState = {};\n private readonly _renderer: THREE.WebGLRenderer;\n\n constructor(renderer: THREE.WebGLRenderer) {\n this._renderer = renderer;\n this._originalState = {};\n }\n\n setClearColor(color: THREE.Color | number | string, alpha?: number) {\n this._originalState = {\n clearColor: this._renderer.getClearColor(new THREE.Color()),\n clearAlpha: this._renderer.getClearAlpha(),\n ...this._originalState\n };\n this._renderer.setClearColor(color, alpha);\n }\n\n setSize(width: number, height: number) {\n this._originalState = { size: this._renderer.getSize(new THREE.Vector2()), ...this._originalState };\n this._renderer.setSize(width, height);\n }\n\n set localClippingEnabled(enabled: boolean) {\n this._originalState = { localClippingEnabled: this._renderer.localClippingEnabled, ...this._originalState };\n this._renderer.localClippingEnabled = enabled;\n }\n\n set autoClear(enabled: boolean) {\n this._originalState = { autoClear: this._renderer.autoClear, ...this._originalState };\n this._renderer.autoClear = enabled;\n }\n\n setRenderTarget(renderTarget: THREE.RenderTarget | null) {\n this._originalState = { renderTarget: this._renderer.getRenderTarget(), ...this._originalState };\n this._renderer.setRenderTarget(renderTarget);\n }\n\n resetState() {\n if (this._originalState.autoClear !== undefined) {\n this._renderer.autoClear = this._originalState.autoClear;\n }\n if (this._originalState.clearColor !== undefined) {\n this._renderer.setClearColor(this._originalState.clearColor, this._originalState.clearAlpha);\n }\n if (this._originalState.localClippingEnabled !== undefined) {\n this._renderer.localClippingEnabled = this._originalState.localClippingEnabled;\n }\n if (this._originalState.size !== undefined) {\n this._renderer.setSize(this._originalState.size.width, this._originalState.size.height);\n }\n if (this._originalState.renderTarget !== undefined) {\n this._renderer.setRenderTarget(this._originalState.renderTarget);\n }\n\n this._originalState = {};\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Used to specify custom url for worker/wasm files\n * in cases when you need the latest local files or CDN is blocked by CSP.\n */\nexport const revealEnv = {\n publicPath: ''\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { wrap } from 'comlink';\nimport { RevealParserWorker } from '@cognite/reveal-parser-worker';\nimport { revealEnv } from '../revealEnv';\nimport { isTheSameDomain } from '../networking/isTheSameDomain';\n\nimport log from '@reveal/logger';\n\ntype WorkDelegate<T> = (worker: RevealParserWorker) => Promise<T>;\n\ninterface PooledWorker {\n // The worker returned by Comlink.wrap is not strictly speaking a RevealParserWorker,\n // but it should expose the same functions\n worker: RevealParserWorker;\n activeJobCount: number;\n messageIdCounter: number;\n}\n\nexport class WorkerPool {\n static get defaultPool(): WorkerPool {\n WorkerPool._defaultPool = WorkerPool._defaultPool || new WorkerPool();\n return WorkerPool._defaultPool;\n }\n\n private static _defaultPool: WorkerPool | undefined;\n\n private readonly workerList: PooledWorker[] = [];\n\n private workerObjUrl?: string;\n\n constructor() {\n const numberOfWorkers = this.determineNumberOfWorkers();\n\n for (let i = 0; i < numberOfWorkers; i++) {\n const newWorker = {\n // NOTE: As of Comlink 4.2.0 we need to go through unknown before RevealParserWorker\n // Please feel free to remove `as unknown` if possible.\n worker: wrap(this.createWorker()) as unknown as RevealParserWorker,\n activeJobCount: 0,\n messageIdCounter: 0\n };\n this.workerList.push(newWorker);\n }\n\n if (process.env.NODE_ENV !== 'test') {\n checkWorkerVersion(this.workerList[0].worker).catch(x => log.error(x));\n }\n\n if (this.workerObjUrl) {\n URL.revokeObjectURL(this.workerObjUrl);\n }\n }\n\n // Used to construct workers with or without importScripts usage to overcome CORS.\n // When publicPath is not set we need to fetch worker from CDN (perform cross-origin request)\n // and that's possible only with importScripts.\n // If publicPath is set and points on the same domain, we use it normally.\n private createWorker() {\n const workerUrl = (revealEnv.publicPath || __webpack_public_path__) + 'reveal.parser.worker.js';\n const options = { name: `reveal.parser #${this.workerList.length}` };\n\n if (isTheSameDomain(workerUrl)) {\n return new Worker(workerUrl, options);\n }\n\n if (!this.workerObjUrl) {\n const blob = new Blob([`importScripts(${JSON.stringify(workerUrl)});`], {\n type: 'text/javascript'\n });\n this.workerObjUrl = URL.createObjectURL(blob);\n }\n\n return new Worker(this.workerObjUrl, options);\n }\n\n async postWorkToAvailable<T>(work: WorkDelegate<T>): Promise<T> {\n const targetWorker = this.workerList.reduce((bestWorker, candidate) => {\n if (bestWorker.activeJobCount > candidate.activeJobCount) {\n return candidate;\n }\n return bestWorker;\n }, this.workerList[0]);\n\n targetWorker.activeJobCount += 1;\n const result = await (async () => {\n try {\n return await work(targetWorker.worker);\n } finally {\n targetWorker.activeJobCount -= 1;\n }\n })();\n\n return result;\n }\n\n // TODO j-bjorne 16-04-2020: Send in constructor instead\n private determineNumberOfWorkers() {\n // Use between 2-4 workers, depending on hardware\n return Math.max(2, Math.min(4, window.navigator.hardwareConcurrency || 2));\n }\n}\n\nexport async function checkWorkerVersion(worker: RevealParserWorker) {\n let actualWorkerVersion: string;\n try {\n actualWorkerVersion = await worker.getVersion();\n } catch (e) {\n // versions below 1.1.1 do not have getVersion method\n // notice also you cannot use 'in' operator on worker object\n // because it's merely a proxy-wrapper over postmessage('methodname')\n // so `'getVersion' in worker` - will be always false\n actualWorkerVersion = '1.1.0';\n }\n const minWorkerVersion = process.env.WORKER_VERSION;\n\n const [majorMin, minorMin, patchMin] = minWorkerVersion.split('.').map(i => parseInt(i, 10));\n const [majorWorker, minorWorker, patchWorker] = actualWorkerVersion.split('.').map(i => parseInt(i, 10));\n\n const errorMessage = `Update your local copy of @cognite/reveal-parser-worker. Required version is ${minWorkerVersion}. Received ${actualWorkerVersion}.`;\n\n if (majorMin !== majorWorker) {\n throw new Error(errorMessage);\n }\n if (minorWorker < minorMin) {\n throw new Error(errorMessage);\n }\n if (minorWorker === minorMin && patchWorker < patchMin) {\n throw new Error(errorMessage);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Use to determine if the strings that represent urls\n * are pointing on different domains.\n * @param url1\n * @param url2 Optional. Default is `location.origin`. If provided then it must be\n * absolute url to avoid comparison between two relative urls.\n */\nexport function isTheSameDomain(url1: string, url2: string = location.origin) {\n const isRelative = (url: string) => {\n if (url.match(/^.*\\/\\//)) {\n return false; // starts with protocol - means absolute url, e.g. https://foo.bar/baz\n }\n return true;\n };\n\n if (isRelative(url2)) {\n throw new Error(`isTheSameDomain: the second argument must be an absolute url or omitted. Received ${url2}`);\n }\n\n if (isRelative(url1)) {\n return true;\n }\n\n try {\n // url that starts with '//' considered invalid for URL constructor\n // but browsers usually work just fine with them when it comes to links\n // and we just need to compare origins here anyway\n const urls = [url1, url2].map(url => (url.startsWith('//') ? 'https:' + url : url));\n\n const constructedURLs = urls.map(url => new URL(url));\n return constructedURLs[0].host === constructedURLs[1].host;\n } catch (e) {\n console.error(`can not create URLs for ${url1} and ${url2}`, e);\n return false;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { RequestCache } from './RequestCache';\n\nclass TimestampedContainer<T> {\n private _lastAccessTime: number;\n private readonly _value: T;\n\n constructor(value: T) {\n this._value = value;\n this._lastAccessTime = Date.now();\n }\n\n get value() {\n this.touch();\n return this._value;\n }\n\n get lastAccessTime() {\n return this._lastAccessTime;\n }\n\n private touch() {\n this._lastAccessTime = Date.now();\n }\n}\n\nexport interface MemoryRequestCacheOptions {\n maxElementsInCache?: number;\n}\n\nexport class MemoryRequestCache<Key, Data> implements RequestCache<Key, Data> {\n private readonly _maxElementsInCache: number;\n private readonly _data: Map<Key, TimestampedContainer<Data>>;\n private readonly _defaultCleanupCount: number;\n private readonly _removeCallback: ((value: Data) => void) | undefined;\n\n constructor(\n maxElementsInCache: number = 50,\n removeCallback?: (value: Data) => void,\n defaultCleanupCount: number = 10\n ) {\n this._data = new Map();\n this._maxElementsInCache = maxElementsInCache;\n this._defaultCleanupCount = defaultCleanupCount;\n this._removeCallback = removeCallback;\n }\n\n has(id: Key) {\n return this._data.has(id);\n }\n\n forceInsert(id: Key, data: Data) {\n if (this.isFull()) {\n this.cleanCache(this._defaultCleanupCount);\n }\n this.insert(id, data);\n }\n\n insert(id: Key, data: Data) {\n if (this._data.size < this._maxElementsInCache) {\n this._data.set(id, new TimestampedContainer(data));\n } else {\n throw new Error('Cache full, please clean Cache and retry adding data');\n }\n }\n\n remove(id: Key) {\n if (this._removeCallback !== undefined) {\n const value = this._data.get(id);\n if (value !== undefined) {\n this._removeCallback(value.value);\n }\n }\n this._data.delete(id);\n }\n\n get(id: Key): Data {\n const data = this._data.get(id);\n if (data !== undefined) {\n // Don't really like the touch for lastTime being hidden within a get function. Should we maybe make a\n // TimeConstrainedCache interface where the geter is called something like getAndUpdateTimestamp for clarity?\n return data.value;\n }\n throw new Error(`Cache element ${id} does not exist`);\n }\n\n isFull(): boolean {\n return !(this._data.size < this._maxElementsInCache);\n }\n\n cleanCache(count: number) {\n const allResults = Array.from(this._data.entries());\n allResults.sort((left, right) => {\n return right[1].lastAccessTime - left[1].lastAccessTime;\n });\n for (let i = 0; i < count; i++) {\n const entry = allResults.pop();\n if (entry !== undefined) {\n this.remove(entry[0]);\n } else {\n return;\n }\n }\n }\n\n clear() {\n if (this._removeCallback !== undefined) {\n for (const value of this._data.values()) {\n this._removeCallback(value.value);\n }\n }\n this._data.clear();\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n/**\n * A cache that keeps values that is most frequently used (MFU) rather than a more common\n * least recently used (LRU) approach.\n */\nexport class MostFrequentlyUsedCache<TKey, TValue> {\n private readonly _capacity: number;\n private readonly _cache = new Map<TKey, TValue>();\n private readonly _retrieves = new Map<TKey, number>();\n private readonly _disposeCallback: ((value: TValue) => void) | undefined;\n\n constructor(capacity: number, disposeCallback?: (value: TValue) => void) {\n this._capacity = capacity;\n this._disposeCallback = disposeCallback;\n }\n\n get(key: TKey): TValue | undefined {\n const retrieveCount = this._retrieves.get(key) || 0;\n this._retrieves.set(key, retrieveCount + 1);\n return this._cache.get(key);\n }\n\n set(key: TKey, value: TValue): boolean {\n if (this._cache.has(key) || this._capacity < this._cache.size) {\n this._cache.set(key, value);\n return true;\n } else {\n // TODO 2020-12-05 larsmoa: Very inefficient way to set value.\n // We often set a value and discard it a moment later because its not\n // imporant. Fix this.\n this._cache.set(key, value);\n this.ensureWithinCapacity();\n return this._cache.has(key);\n }\n }\n\n remove(key: TKey): boolean {\n this._retrieves.delete(key);\n const value = this._cache.get(key);\n if (value !== undefined) {\n if (this._disposeCallback !== undefined) {\n this._disposeCallback(value);\n }\n this._cache.delete(key);\n return true;\n }\n return false;\n }\n\n clear() {\n if (this._disposeCallback !== undefined) {\n for (const value of this._cache.values()) {\n this._disposeCallback(value);\n }\n }\n this._retrieves.clear();\n this._cache.clear();\n }\n\n private ensureWithinCapacity(): void {\n if (this._capacity >= this._cache.size) return;\n const keys = Array.from(this._cache.keys());\n // Figure out what to remove\n const keysForRemoval = keys\n .map(x => ({ key: x, retrivalCount: this._retrieves.get(x) || 0 }))\n .sort((a, b) => a.retrivalCount - b.retrivalCount)\n .slice(0, this._cache.size - this._capacity)\n .map(x => x.key);\n\n for (const key of keysForRemoval) {\n this.remove(key);\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Handler for THREE.BufferAttribute.onUpload() that frees the underlying JS side array\n * of values after they have been uploaded to the GPU.\n *\n * @example\n * const geometry = new THREE.BufferGeometry();\n * const indices = new THREE.Uint32BufferAttribute(mesh.indices.buffer, 1).onUpload(disposeAttributeArrayOnUpload);\n * const vertices = new THREE.Float32BufferAttribute(mesh.vertices.buffer, 3).onUpload(disposeAttributeArrayOnUpload);\n * const colors = new THREE.Float32BufferAttribute(mesh.colors.buffer, 3).onUpload(disposeAttributeArrayOnUpload);\n * const treeIndices = new THREE.Float32BufferAttribute(mesh.treeIndices.buffer, 1).onUpload(disposeAttributeArrayOnUpload);\n */\nexport function disposeAttributeArrayOnUpload(this: { array: ArrayLike<number> }) {\n (this.array as ArrayLike<number> | null) = null;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { traverseDepthFirst } from '@reveal/utilities';\nimport { SectorScene } from './types';\nimport { SectorMetadata } from '../metadata/types';\nimport skmeans from 'skmeans';\n\nexport class SectorSceneImpl implements SectorScene {\n readonly version: number;\n readonly maxTreeIndex: number;\n readonly root: SectorMetadata;\n readonly unit: string;\n private readonly sectors: Map<number, SectorMetadata>;\n\n constructor(\n version: number,\n maxTreeIndex: number,\n unit: string,\n root: SectorMetadata,\n sectorsById: Map<number, SectorMetadata>\n ) {\n this.version = version;\n this.maxTreeIndex = maxTreeIndex;\n this.root = root;\n this.sectors = sectorsById;\n this.unit = unit;\n }\n\n get sectorCount(): number {\n return this.sectors.size;\n }\n\n getSectorById(sectorId: number): SectorMetadata | undefined {\n return this.sectors.get(sectorId);\n }\n\n getAllSectors(): SectorMetadata[] {\n return [...this.sectors.values()];\n }\n\n getSectorsContainingPoint(p: THREE.Vector3): SectorMetadata[] {\n const accepted: SectorMetadata[] = [];\n traverseDepthFirst(this.root, x => {\n if (x.bounds.containsPoint(p)) {\n accepted.push(x);\n return true;\n }\n return false;\n });\n return accepted;\n }\n\n getSectorsIntersectingBox(b: THREE.Box3): SectorMetadata[] {\n const accepted: SectorMetadata[] = [];\n traverseDepthFirst(this.root, x => {\n if (x.bounds.intersectsBox(b)) {\n accepted.push(x);\n return true;\n }\n return false;\n });\n return accepted;\n }\n\n getBoundsOfMostGeometry(): THREE.Box3 {\n if (this.root.children.length === 0) {\n return this.root.bounds;\n }\n\n // Determine all corners of the bboxes\n const allBounds: THREE.Box3[] = [];\n const corners: number[][] = [];\n traverseDepthFirst(this.root, x => {\n if (x.children.length === 0) {\n corners.push(x.bounds.min.toArray(), x.bounds.max.toArray());\n allBounds.push(x.bounds, x.bounds);\n }\n return true;\n });\n // Cluster the corners into four groups and determine bounds of each cluster\n const numClusters = Math.min(corners.length, 4);\n const clusters = skmeans(corners, numClusters, 'kmpp', 10);\n const clusterCounts = new Array<number>(clusters.idxs.length).fill(0);\n const clusterBounds = clusterCounts.map(_ => new THREE.Box3());\n clusters.idxs.map(x => clusterCounts[x]++);\n const biggestCluster = clusterCounts.reduce(\n (max, count, idx) => {\n if (count > max.count) {\n max.count = count;\n max.idx = idx;\n }\n return max;\n },\n { count: 0, idx: -1 }\n ).idx;\n clusters.idxs.forEach((cluster, idx) => {\n clusterCounts[cluster]++;\n clusterBounds[cluster].expandByPoint(allBounds[idx].min);\n clusterBounds[cluster].expandByPoint(allBounds[idx].max);\n });\n\n const intersectingBounds = clusterBounds.filter((x, idx) => {\n if (idx !== biggestCluster && x.intersectsBox(clusterBounds[biggestCluster])) {\n return true;\n }\n return false;\n });\n if (intersectingBounds.length > 0) {\n // Overlapping clusters - assume it's because the model doesn't contain junk geometry\n const merged = clusterBounds[biggestCluster].clone();\n intersectingBounds.forEach(x => {\n merged.expandByPoint(x.min);\n merged.expandByPoint(x.max);\n });\n return merged;\n } else {\n // Create bounds of the biggest cluster - assume the smallest one is junk geometry\n return clusterBounds[biggestCluster];\n }\n }\n\n getSectorsIntersectingFrustum(\n projectionMatrix: THREE.Matrix4,\n inverseCameraModelMatrix: THREE.Matrix4\n ): SectorMetadata[] {\n const frustumMatrix = new THREE.Matrix4().multiplyMatrices(projectionMatrix, inverseCameraModelMatrix);\n const frustum = new THREE.Frustum().setFromProjectionMatrix(frustumMatrix);\n const accepted: SectorMetadata[] = [];\n traverseDepthFirst(this.root, x => {\n if (frustum.intersectsBox(x.bounds)) {\n accepted.push(x);\n return true;\n }\n return false;\n });\n return accepted;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { SectorMetadata, SectorMetadataFacesFileSection } from '../types';\nimport { SectorScene } from '../../utilities/types';\nimport { SectorSceneImpl } from '../../utilities/SectorScene';\n\nexport interface CadSectorMetadataV8 {\n readonly id: number;\n readonly parentId: number;\n readonly path: string;\n readonly depth: number;\n readonly estimatedDrawCallCount: number;\n readonly estimatedTriangleCount: number;\n\n readonly boundingBox: {\n readonly min: {\n x: number;\n y: number;\n z: number;\n };\n readonly max: {\n x: number;\n y: number;\n z: number;\n };\n };\n readonly indexFile: {\n readonly fileName: string;\n readonly peripheralFiles: string[];\n readonly downloadSize: number;\n };\n readonly facesFile: {\n readonly quadSize: number;\n readonly coverageFactors: {\n xy: number;\n yz: number;\n xz: number;\n };\n readonly recursiveCoverageFactors:\n | {\n xy: number;\n yz: number;\n xz: number;\n }\n | undefined;\n readonly fileName: string | null;\n readonly downloadSize: number;\n } | null;\n}\n\nexport interface CadMetadataV8 {\n readonly version: 8;\n readonly maxTreeIndex: number;\n readonly sectors: CadSectorMetadataV8[];\n readonly unit: string | null;\n\n // Available, but unused:\n // readonly projectId: number;\n // readonly modelId: number;\n // readonly revisionId: number;\n // readonly subRevisionId: number;\n}\n\nexport function parseCadMetadataV8(metadata: CadMetadataV8): SectorScene {\n // Create list of sectors and a map of child -> parent\n const sectorsById = new Map<number, SectorMetadata>();\n const parentIds: number[] = [];\n metadata.sectors.forEach(s => {\n const sector = createSectorMetadata(s);\n sectorsById.set(s.id, sector);\n parentIds[s.id] = s.parentId;\n });\n\n // Establish relationships between sectors\n for (const sector of sectorsById.values()) {\n const parentId = parentIds[sector.id];\n if (parentId === -1) {\n continue;\n }\n const parent = sectorsById.get(parentId)!;\n parent.children.push(sector);\n }\n\n const rootSector = sectorsById.get(0);\n if (!rootSector) {\n throw new Error('Root sector not found, must have ID 0');\n }\n // Check for missing facesFile-sections and provide coverage factors from parents when necessary\n populateCoverageFactorsFromAnchestors(rootSector, rootSector.facesFile);\n\n const unit = metadata.unit !== null ? metadata.unit : 'Meters';\n\n return new SectorSceneImpl(metadata.version, metadata.maxTreeIndex, unit, rootSector, sectorsById);\n}\n\nfunction createSectorMetadata(metadata: CadSectorMetadataV8): SectorMetadata {\n const facesFile = determineFacesFile(metadata);\n\n const bb = metadata.boundingBox;\n const min_x = bb.min.x;\n const min_y = bb.min.y;\n const min_z = bb.min.z;\n const max_x = bb.max.x;\n const max_y = bb.max.y;\n const max_z = bb.max.z;\n return {\n id: metadata.id,\n path: metadata.path,\n depth: metadata.depth,\n bounds: new THREE.Box3(new THREE.Vector3(min_x, min_y, min_z), new THREE.Vector3(max_x, max_y, max_z)),\n estimatedDrawCallCount: metadata.estimatedDrawCallCount,\n estimatedRenderCost: metadata.estimatedTriangleCount || 0,\n\n // I3D\n indexFile: { ...metadata.indexFile },\n // F3D\n facesFile,\n\n // Populated later\n children: []\n };\n}\n\nfunction determineFacesFile(metadata: CadSectorMetadataV8): SectorMetadataFacesFileSection {\n if (!metadata.facesFile) {\n return {\n quadSize: -1.0,\n coverageFactors: {\n xy: -1.0,\n yz: -1.0,\n xz: -1.0\n },\n recursiveCoverageFactors: {\n xy: -1.0,\n yz: -1.0,\n xz: -1.0\n },\n fileName: null,\n downloadSize: metadata.indexFile.downloadSize\n };\n }\n const facesFile = {\n ...metadata.facesFile,\n recursiveCoverageFactors: metadata.facesFile.recursiveCoverageFactors || metadata.facesFile.coverageFactors\n };\n return facesFile;\n}\n\nfunction hasDummyFacesFileSection(metadata: SectorMetadata): boolean {\n return metadata.facesFile.coverageFactors.xy === -1.0;\n}\n\nfunction populateCoverageFactorsFromAnchestors(\n sector: SectorMetadata,\n validFacesFileSection: SectorMetadataFacesFileSection\n) {\n if (hasDummyFacesFileSection(sector)) {\n sector.facesFile.coverageFactors.xy = validFacesFileSection.recursiveCoverageFactors.xy;\n sector.facesFile.coverageFactors.yz = validFacesFileSection.recursiveCoverageFactors.yz;\n sector.facesFile.coverageFactors.xz = validFacesFileSection.recursiveCoverageFactors.xz;\n sector.facesFile.recursiveCoverageFactors.xy = validFacesFileSection.recursiveCoverageFactors.xy;\n sector.facesFile.recursiveCoverageFactors.yz = validFacesFileSection.recursiveCoverageFactors.yz;\n sector.facesFile.recursiveCoverageFactors.xz = validFacesFileSection.recursiveCoverageFactors.xz;\n sector.children.forEach(child => populateCoverageFactorsFromAnchestors(child, validFacesFileSection));\n } else {\n sector.children.forEach(child => populateCoverageFactorsFromAnchestors(child, sector.facesFile));\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { parseCadMetadataV8 } from './parsers/CadMetadataParserV8';\nimport { SectorScene } from '../utilities/types';\n\ninterface VersionHeader {\n readonly version: number;\n}\n\nexport class CadMetadataParser {\n public parse(parsedJson: any): SectorScene {\n const version = (parsedJson as VersionHeader).version;\n switch (version) {\n case 8:\n return parseCadMetadataV8(parsedJson);\n\n case undefined:\n throw new Error('Metadata must contain a \"version\"-field');\n\n default:\n throw new Error(`Version ${version} is not supported`);\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { SectorMetadata } from '../metadata/types';\n/**\n * Conversion factors from a given unit to meters.\n */\nexport const WellKnownDistanceToMeterConversionFactors = new Map<string, number>([\n ['Meters', 1.0],\n ['Centimeters', 0.01],\n ['Millimeters', 0.001],\n ['Micrometers', 1e-6],\n ['Kilometers', 1000],\n ['Feet', 0.3048],\n ['Inches', 0.0254],\n ['Yards', 0.9144],\n ['Miles', 1609.34],\n ['Mils', 0.0254 * 1e-3],\n ['Microinches', 0.0254 * 1e-6]\n]);\n\nexport interface SectorScene {\n readonly version: number;\n readonly maxTreeIndex: number;\n readonly root: SectorMetadata;\n readonly unit: string;\n\n readonly sectorCount: number;\n getSectorById(sectorId: number): SectorMetadata | undefined;\n getSectorsContainingPoint(p: THREE.Vector3): SectorMetadata[];\n getSectorsIntersectingBox(b: THREE.Box3): SectorMetadata[];\n\n /**\n * Returns bounds that contains \"most geometry\". This bounds is an\n * attempt to remove junk geometry from the bounds to allow e.g. setting\n * a good camera position.\n */\n getBoundsOfMostGeometry(): THREE.Box3;\n\n /**\n * Gets the sectors intersecting the frustum provided from the projection and inverse\n * camera matrix. Note that this function expects matrices in the the coordinate system\n * of the metadata. See below how to convert ThreeJS camera matrices to the correct format.\n *\n * @example Converting a ThreeJS camera to a frustum\n * ```\n * const cameraMatrixWorldInverse = camera.matrixWorldInverse;\n * const cameraProjectionMatrix = camera.projectionMatrix;\n *\n * const transformedCameraMatrixWorldInverse =\n * new THREE.Matrix4().multiplyMatrices(cameraMatrixWorldInverse, model.modelMatrix)\n *\n * const intersectingSectors = model.scene.getSectorsIntersectingFrustum(\n * cameraProjectionMatrix,\n * transformedCameraMatrixWorldInverse\n * );\n * ```\n * @param projectionMatrix\n * @param inverseCameraModelMatrix\n */\n getSectorsIntersectingFrustum(\n projectionMatrix: THREE.Matrix4,\n inverseCameraModelMatrix: THREE.Matrix4\n ): SectorMetadata[];\n getAllSectors(): SectorMetadata[];\n\n // Available, but not supported:\n // readonly projectId: number;\n // readonly modelId: number;\n // readonly revisionId: number;\n // readonly subRevisionId: number;\n // readonly unit: string | null;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { CadMetadataParser } from './CadMetadataParser';\n\nimport { SectorScene, WellKnownDistanceToMeterConversionFactors } from '../utilities/types';\nimport { CadModelMetadata } from './CadModelMetadata';\nimport { MetadataRepository } from './MetadataRepository';\nimport { transformCameraConfiguration } from '@reveal/utilities';\n\nimport { ModelDataProvider, ModelMetadataProvider, ModelIdentifier } from '@reveal/modeldata-api';\n\nexport class CadModelMetadataRepository implements MetadataRepository<Promise<CadModelMetadata>> {\n private readonly _modelMetadataProvider: ModelMetadataProvider;\n private readonly _modelDataProvider: ModelDataProvider;\n private readonly _cadSceneParser: CadMetadataParser;\n private readonly _blobFileName: string;\n private _currentModelIdentifier = 0;\n\n constructor(\n modelMetadataProvider: ModelMetadataProvider,\n modelDataProvider: ModelDataProvider,\n cadMetadataParser: CadMetadataParser,\n blobFileName: string = 'scene.json'\n ) {\n this._modelMetadataProvider = modelMetadataProvider;\n this._modelDataProvider = modelDataProvider;\n this._cadSceneParser = cadMetadataParser;\n this._blobFileName = blobFileName;\n }\n\n async loadData(modelIdentifier: ModelIdentifier): Promise<CadModelMetadata> {\n const blobBaseUrlPromise = this._modelMetadataProvider.getModelUri(modelIdentifier);\n const modelMatrixPromise = this._modelMetadataProvider.getModelMatrix(modelIdentifier);\n const modelCameraPromise = this._modelMetadataProvider.getModelCamera(modelIdentifier);\n\n const blobBaseUrl = await blobBaseUrlPromise;\n const json = await this._modelDataProvider.getJsonFile(blobBaseUrl, this._blobFileName);\n const scene: SectorScene = this._cadSceneParser.parse(json);\n const modelMatrix = createScaleToMetersModelMatrix(scene.unit, await modelMatrixPromise);\n const inverseModelMatrix = new THREE.Matrix4().copy(modelMatrix).invert();\n const cameraConfiguration = await modelCameraPromise;\n\n return {\n modelIdentifier: `${this._currentModelIdentifier++}`, // TODO 2021-10-03 larsmoa: Change to ModelIdentifier\n modelBaseUrl: blobBaseUrl,\n // Clip box is not loaded, it must be set elsewhere\n geometryClipBox: null,\n modelMatrix,\n inverseModelMatrix,\n cameraConfiguration: transformCameraConfiguration(cameraConfiguration, modelMatrix),\n scene\n };\n }\n}\n\nfunction createScaleToMetersModelMatrix(unit: string, modelMatrix: THREE.Matrix4): THREE.Matrix4 {\n const conversionFactor = WellKnownDistanceToMeterConversionFactors.get(unit);\n if (conversionFactor === undefined) {\n throw new Error(`Unknown model unit '${unit}'`);\n }\n\n const scaledModelMatrix = new THREE.Matrix4().makeScale(conversionFactor, conversionFactor, conversionFactor);\n return scaledModelMatrix.multiply(modelMatrix);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport enum LevelOfDetail {\n Discarded,\n Simple,\n Detailed\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { SectorSceneImpl } from './SectorScene';\nimport { SectorMetadata } from '../metadata/types';\n\nimport { traverseDepthFirst } from '@reveal/utilities';\n\nimport assert from 'assert';\n\n/**\n * Factory for creating instance of {@link SectorScene} based on\n * the version of the format provided.\n */\nexport class SectorSceneFactory {\n createSectorScene(version: number, maxTreeIndex: number, unit: string, root: SectorMetadata) {\n assert(version === 8, 'Only version 8 is currently supported');\n\n const sectorsById: Map<number, SectorMetadata> = new Map();\n traverseDepthFirst(root, x => {\n sectorsById.set(x.id, x);\n return true;\n });\n return new SectorSceneImpl(version, maxTreeIndex, unit, root, sectorsById);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { AutoDisposeGroup } from '@reveal/utilities';\nimport { LevelOfDetail } from '../cad/LevelOfDetail';\n\nexport class SectorNode extends THREE.Group {\n public readonly sectorPath: string;\n public readonly sectorId: number;\n public readonly bounds: THREE.Box3;\n public readonly depth: number;\n\n private _group?: AutoDisposeGroup;\n private _lod = LevelOfDetail.Discarded;\n private _updatedTimestamp: number = Date.now();\n\n constructor(sectorId: number, sectorPath: string, bounds: THREE.Box3) {\n super();\n this.name = `Sector ${sectorPath} [id=${sectorId}]`;\n this.sectorId = sectorId;\n this.sectorPath = sectorPath;\n this.bounds = bounds;\n this.depth = determineSectorDepth(sectorPath);\n }\n\n get levelOfDetail(): LevelOfDetail {\n return this._lod;\n }\n\n get group(): THREE.Group | undefined {\n return this._group;\n }\n\n get updatedTimestamp(): number {\n return this._updatedTimestamp;\n }\n\n updateGeometry(geomtryGroup: AutoDisposeGroup | undefined, levelOfDetail: LevelOfDetail) {\n this.resetGeometry();\n this._group = geomtryGroup;\n if (this._group !== undefined) {\n this._group.reference();\n }\n this._lod = levelOfDetail;\n this._updatedTimestamp = Date.now();\n this.visible = this._lod !== LevelOfDetail.Discarded;\n this.updateMatrixWorld(true);\n }\n\n resetGeometry() {\n if (this._group !== undefined) {\n this._group.dereference();\n this.remove(this._group);\n }\n\n this._group = undefined;\n this._lod = LevelOfDetail.Discarded;\n this._updatedTimestamp = Date.now();\n }\n}\n\nfunction determineSectorDepth(path: string): number {\n let depth = 0;\n for (let i = 0; i < path.length; ++i) {\n depth += path[i] === '/' ? 1 : 0;\n }\n return depth - 1;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { SectorNode } from './SectorNode';\nimport { SectorMetadata } from '../metadata/types';\nimport { CadModelMetadata } from '../metadata/CadModelMetadata';\n\nexport class RootSectorNode extends SectorNode {\n public readonly sectorNodeMap: Map<number, SectorNode>;\n\n constructor(modelMetadata: CadModelMetadata) {\n const modelBounds = modelMetadata.scene.root.bounds.clone();\n modelBounds.applyMatrix4(modelMetadata.modelMatrix);\n super(0, '/', modelBounds);\n\n const { scene, modelMatrix } = modelMetadata;\n this.sectorNodeMap = new Map();\n buildScene(scene.root, this, this.sectorNodeMap, modelMatrix);\n\n // Disable automatic update of matrices of the subtree as it\n // is quite time consuming. We trust that our owner keeps\n // our matrices updated.\n this.matrixAutoUpdate = false;\n this.setModelTransformation(modelMatrix);\n }\n\n setModelTransformation(matrix: THREE.Matrix4): void {\n this.matrix.copy(matrix);\n this.updateMatrixWorld(true);\n }\n\n getModelTransformation(out = new THREE.Matrix4()): THREE.Matrix4 {\n return out.copy(this.matrix);\n }\n}\n\nfunction buildScene(\n sector: SectorMetadata,\n parent: SectorNode,\n sectorNodeMap: Map<number, SectorNode>,\n modelMatrix: THREE.Matrix4\n) {\n const bounds = sector.bounds.clone();\n bounds.applyMatrix4(modelMatrix);\n const sectorGroup = new SectorNode(sector.id, sector.path, bounds);\n sectorGroup.name = `Sector ${sector.id}`;\n parent.add(sectorGroup);\n sectorGroup.matrixAutoUpdate = false;\n sectorGroup.updateMatrixWorld(true);\n\n sectorNodeMap.set(sector.id, sectorGroup);\n for (const child of sector.children) {\n buildScene(child, sectorGroup, sectorNodeMap, modelMatrix);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { WorkerPool } from '@reveal/utilities';\n\nimport { ParseSectorResult, ParseCtmResult, RevealParserWorker, SectorQuads } from '@cognite/reveal-parser-worker';\n\nexport class CadSectorParser {\n private readonly workerPool: WorkerPool;\n constructor(workerPool: WorkerPool = WorkerPool.defaultPool) {\n this.workerPool = workerPool;\n }\n\n parseI3D(data: Uint8Array): Promise<ParseSectorResult> {\n return this.parseDetailed(data);\n }\n\n parseF3D(data: Uint8Array): Promise<SectorQuads> {\n return this.parseSimple(data);\n }\n\n parseCTM(data: Uint8Array): Promise<ParseCtmResult> {\n return this.parseCtm(data);\n }\n\n private async parseSimple(quadsArrayBuffer: Uint8Array): Promise<SectorQuads> {\n return this.workerPool.postWorkToAvailable<SectorQuads>(async (worker: RevealParserWorker) =>\n worker.parseQuads(quadsArrayBuffer)\n );\n }\n\n private async parseDetailed(sectorArrayBuffer: Uint8Array): Promise<ParseSectorResult> {\n return this.workerPool.postWorkToAvailable(async (worker: RevealParserWorker) =>\n worker.parseSector(sectorArrayBuffer)\n );\n }\n\n private async parseCtm(ctmArrayBuffer: Uint8Array): Promise<ParseCtmResult> {\n return this.workerPool.postWorkToAvailable(async (worker: RevealParserWorker) => worker.parseCtm(ctmArrayBuffer));\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\nimport { ParsePrimitiveAttribute } from '@cognite/reveal-parser-worker';\n\nconst computeBoundingBoxFromCenterAndRadiusAttributesVars = {\n centerA: new THREE.Vector3(),\n centerB: new THREE.Vector3(),\n sphere: new THREE.Sphere(),\n box: new THREE.Box3()\n};\n\nexport function computeBoundingBoxFromCenterAndRadiusAttributes(\n centerAattribute: ParsePrimitiveAttribute,\n centerBattribute: ParsePrimitiveAttribute,\n radiusAattribute: ParsePrimitiveAttribute,\n radiusBattribute: ParsePrimitiveAttribute,\n attributeFloatValues: Float32Array,\n elementSize: number,\n elementIndex: number,\n out: THREE.Box3\n): THREE.Box3 {\n const { centerA, centerB, sphere, box } = computeBoundingBoxFromCenterAndRadiusAttributesVars;\n\n function readAttribute(attribute: ParsePrimitiveAttribute, idx: number = 0): number {\n const offset = (elementIndex * elementSize + attribute.offset) / attributeFloatValues.BYTES_PER_ELEMENT;\n return attributeFloatValues[offset + idx];\n }\n\n centerA.set(\n readAttribute(centerAattribute, 0),\n readAttribute(centerAattribute, 1),\n readAttribute(centerAattribute, 2)\n );\n centerB.set(\n readAttribute(centerBattribute, 0),\n readAttribute(centerBattribute, 1),\n readAttribute(centerBattribute, 2)\n );\n const radiusA = readAttribute(radiusAattribute);\n const radiusB = readAttribute(radiusBattribute);\n\n // Note! Not the tighest fit we could make, works ok for now but could be improved by\n // using normal of each cap to determine exact end points of the top/bottom\n sphere.set(centerA, radiusA);\n sphere.getBoundingBox(out);\n sphere.set(centerB, radiusB);\n sphere.getBoundingBox(box);\n out.expandByPoint(box.min);\n out.expandByPoint(box.max);\n return out;\n}\n\nconst computeBoundingBoxFromVertexAttributesVars = {\n vertex1: new THREE.Vector3(),\n vertex2: new THREE.Vector3(),\n vertex3: new THREE.Vector3(),\n vertex4: new THREE.Vector3()\n};\n\nexport function computeBoundingBoxFromVertexAttributes(\n vertex1Attribute: ParsePrimitiveAttribute,\n vertex2Attribute: ParsePrimitiveAttribute,\n vertex3Attribute: ParsePrimitiveAttribute,\n vertex4Attribute: ParsePrimitiveAttribute,\n attributeFloatValues: Float32Array,\n elementSize: number,\n elementIndex: number,\n out: THREE.Box3\n): THREE.Box3 {\n const { vertex1, vertex2, vertex3, vertex4 } = computeBoundingBoxFromVertexAttributesVars;\n\n function readAttribute(attribute: ParsePrimitiveAttribute, idx: number = 0): number {\n const offset = (elementIndex * elementSize + attribute.offset) / attributeFloatValues.BYTES_PER_ELEMENT;\n return attributeFloatValues[offset + idx];\n }\n\n vertex1.set(\n readAttribute(vertex1Attribute, 0),\n readAttribute(vertex1Attribute, 1),\n readAttribute(vertex1Attribute, 2)\n );\n vertex2.set(\n readAttribute(vertex2Attribute, 0),\n readAttribute(vertex2Attribute, 1),\n readAttribute(vertex2Attribute, 2)\n );\n vertex3.set(\n readAttribute(vertex3Attribute, 0),\n readAttribute(vertex3Attribute, 1),\n readAttribute(vertex3Attribute, 2)\n );\n vertex4.set(\n readAttribute(vertex4Attribute, 0),\n readAttribute(vertex4Attribute, 1),\n readAttribute(vertex4Attribute, 2)\n );\n\n out.setFromPoints([vertex1, vertex2, vertex3, vertex4]);\n return out;\n}\n\nconst computeBoundingBoxFromInstanceMatrixAttributesVars = {\n instanceMatrix: new THREE.Matrix4()\n};\n\nexport function computeBoundingBoxFromInstanceMatrixAttributes(\n instanceMatrixAttribute: ParsePrimitiveAttribute,\n attributeFloatValues: Float32Array,\n elementSize: number,\n elementIndex: number,\n baseBoundingBox: THREE.Box3,\n out: THREE.Box3\n): THREE.Box3 {\n const { instanceMatrix } = computeBoundingBoxFromInstanceMatrixAttributesVars;\n\n const offset = (elementIndex * elementSize + instanceMatrixAttribute.offset) / attributeFloatValues.BYTES_PER_ELEMENT;\n // Note! set() accepts row-major, stored column-major\n instanceMatrix.set(\n attributeFloatValues[offset + 0],\n attributeFloatValues[offset + 4],\n attributeFloatValues[offset + 8],\n attributeFloatValues[offset + 12],\n\n attributeFloatValues[offset + 1],\n attributeFloatValues[offset + 5],\n attributeFloatValues[offset + 9],\n attributeFloatValues[offset + 13],\n\n attributeFloatValues[offset + 2],\n attributeFloatValues[offset + 6],\n attributeFloatValues[offset + 10],\n attributeFloatValues[offset + 14],\n\n attributeFloatValues[offset + 3],\n attributeFloatValues[offset + 7],\n attributeFloatValues[offset + 11],\n attributeFloatValues[offset + 15]\n );\n out.copy(baseBoundingBox).applyMatrix4(instanceMatrix);\n return out;\n}\n\nconst computeBoundingBoxFromEllipseAttributesVars = {\n center: new THREE.Vector3(),\n size: new THREE.Vector3()\n};\n\nexport function computeBoundingBoxFromEllipseAttributes(\n centerAttribute: ParsePrimitiveAttribute,\n radius1Attribute: ParsePrimitiveAttribute,\n radius2Attribute: ParsePrimitiveAttribute,\n heightAttribute: ParsePrimitiveAttribute,\n attributeFloatValues: Float32Array,\n elementSize: number,\n elementIndex: number,\n out: THREE.Box3\n): THREE.Box3 {\n const { center, size } = computeBoundingBoxFromEllipseAttributesVars;\n\n function readAttribute(attribute: ParsePrimitiveAttribute, idx: number = 0): number {\n const offset = (elementIndex * elementSize + attribute.offset) / attributeFloatValues.BYTES_PER_ELEMENT;\n return attributeFloatValues[offset + idx];\n }\n\n center.set(readAttribute(centerAttribute, 0), readAttribute(centerAttribute, 1), readAttribute(centerAttribute, 2));\n const radius1 = readAttribute(radius1Attribute);\n const radius2 = readAttribute(radius2Attribute);\n const height = readAttribute(heightAttribute);\n const extent = 2.0 * Math.max(radius1, radius2, height);\n size.set(extent, extent, extent);\n out.setFromCenterAndSize(center, size);\n return out;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { ParsePrimitiveAttribute } from '@cognite/reveal-parser-worker';\nimport assert from 'assert';\nimport {\n computeBoundingBoxFromCenterAndRadiusAttributes,\n computeBoundingBoxFromEllipseAttributes,\n computeBoundingBoxFromInstanceMatrixAttributes,\n computeBoundingBoxFromVertexAttributes\n} from '../utilities/computeBoundingBoxFromAttributes';\n\nfunction filterPrimitivesOutsideClipBox(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n clipBox: THREE.Box3,\n getBoundsOfElementsCallback: (\n index: number,\n elementSize: number,\n attributeFloatValues: Float32Array,\n outBox: THREE.Box3\n ) => void\n): Uint8Array {\n const elementSize = Array.from(attributes.values()).reduce((a, b) => Math.max(a, b.offset + b.size), 0);\n const elementCount = attributesByteValues.length / elementSize;\n const attributeFloatValues = new Float32Array(attributesByteValues.buffer);\n\n const instanceBbox = new THREE.Box3();\n\n const filteredByteValues = new Uint8Array(attributesByteValues.length);\n let filteredCount = 0;\n for (let i = 0; i < elementCount; ++i) {\n getBoundsOfElementsCallback(i, elementSize, attributeFloatValues, instanceBbox);\n\n if (clipBox.intersectsBox(instanceBbox)) {\n const elementValues = attributesByteValues.subarray(i * elementSize, (i + 1) * elementSize);\n filteredByteValues.set(elementValues, filteredCount * elementSize);\n filteredCount++;\n }\n }\n return filteredByteValues.slice(0, filteredCount * elementSize);\n}\n\nexport function filterPrimitivesOutsideClipBoxByBaseBoundsAndInstanceMatrix(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n baseBox: THREE.Box3,\n geometryClipBox: THREE.Box3 | null\n): Uint8Array {\n if (geometryClipBox === null) {\n return attributesByteValues;\n }\n const instanceMatrixAttribute = attributes.get('instanceMatrix');\n assert(instanceMatrixAttribute !== undefined);\n return filterPrimitivesOutsideClipBox(\n attributesByteValues,\n attributes,\n geometryClipBox,\n (index, elementSize, attributeFloatValues, outBox) => {\n computeBoundingBoxFromInstanceMatrixAttributes(\n instanceMatrixAttribute,\n attributeFloatValues,\n elementSize,\n index,\n baseBox,\n outBox\n );\n }\n );\n}\n\nexport function filterPrimitivesOutsideClipBoxByCenterAndRadius(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n geometryClipBox: THREE.Box3 | null,\n radiusAattributeName: string = 'radiusA',\n radiusBattributeName: string = 'radiusB'\n): Uint8Array {\n if (geometryClipBox === null) {\n return attributesByteValues;\n }\n\n const centerAattribute = attributes.get('centerA');\n const centerBattribute = attributes.get('centerB');\n const radiusAattribute = attributes.get(radiusAattributeName);\n const radiusBattribute = attributes.get(radiusBattributeName);\n assert(\n centerAattribute !== undefined &&\n centerBattribute !== undefined &&\n radiusAattribute !== undefined &&\n radiusBattribute !== undefined\n );\n return filterPrimitivesOutsideClipBox(\n attributesByteValues,\n attributes,\n geometryClipBox,\n (index, elementSize, attributeFloatValues, outBox) => {\n computeBoundingBoxFromCenterAndRadiusAttributes(\n centerAattribute,\n centerBattribute,\n radiusAattribute,\n radiusBattribute,\n attributeFloatValues,\n elementSize,\n index,\n outBox\n );\n }\n );\n}\n\nexport function filterPrimitivesOutsideClipBoxByVertices(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n geometryClipBox: THREE.Box3 | null\n): Uint8Array {\n if (geometryClipBox === null) {\n return attributesByteValues;\n }\n\n const vertex1attribute = attributes.get('vertex1');\n const vertex2attribute = attributes.get('vertex2');\n const vertex3attribute = attributes.get('vertex3');\n const vertex4attribute = attributes.get('vertex4');\n assert(\n vertex1attribute !== undefined &&\n vertex2attribute !== undefined &&\n vertex3attribute !== undefined &&\n vertex4attribute !== undefined\n );\n return filterPrimitivesOutsideClipBox(\n attributesByteValues,\n attributes,\n geometryClipBox,\n (index, elementSize, attributeFloatValues, outBox) => {\n computeBoundingBoxFromVertexAttributes(\n vertex1attribute,\n vertex2attribute,\n vertex3attribute,\n vertex4attribute,\n attributeFloatValues,\n elementSize,\n index,\n outBox\n );\n }\n );\n}\n\nexport function filterPrimitivesOutsideClipBoxByEllipse(\n attributesByteValues: Uint8Array,\n attributes: Map<string, ParsePrimitiveAttribute>,\n geometryClipBox: THREE.Box3 | null,\n radius1AttributeName: string = 'horizontalRadius',\n radius2AttributeName: string = 'verticalRadius'\n): Uint8Array {\n if (geometryClipBox === null) {\n return attributesByteValues;\n }\n const centerAttribute = attributes.get('center');\n const horizontalRadiusAttribute = attributes.get(radius1AttributeName);\n const verticalRadiusAttribute = attributes.get(radius2AttributeName);\n const heightAttribute = attributes.get('height');\n assert(\n centerAttribute !== undefined &&\n horizontalRadiusAttribute !== undefined &&\n verticalRadiusAttribute !== undefined &&\n heightAttribute !== undefined\n );\n return filterPrimitivesOutsideClipBox(\n attributesByteValues,\n attributes,\n geometryClipBox,\n (index, elementSize, attributeFloatValues, outBox) => {\n computeBoundingBoxFromEllipseAttributes(\n centerAttribute,\n horizontalRadiusAttribute,\n verticalRadiusAttribute,\n heightAttribute,\n attributeFloatValues,\n elementSize,\n index,\n outBox\n );\n }\n );\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\nimport { InstancedMesh } from './types';\n\nimport { float32BufferToMatrix } from '../utilities/float32BufferToMatrix';\n\nconst filterInstanceMeshVars = {\n p: new THREE.Vector3(),\n instanceMatrix: new THREE.Matrix4(),\n baseBounds: new THREE.Box3(),\n instanceBounds: new THREE.Box3()\n};\n\nexport function filterInstanceMesh(\n vertices: Float32Array,\n indices: Uint32Array,\n instanceMesh: InstancedMesh,\n geometryClipBox: THREE.Box3 | null\n): InstancedMesh {\n if (geometryClipBox === null) {\n return instanceMesh;\n }\n const { p, instanceMatrix, baseBounds, instanceBounds } = filterInstanceMeshVars;\n\n // Determine base bounds\n baseBounds.makeEmpty();\n for (let j = instanceMesh.triangleOffset; j < instanceMesh.triangleOffset + instanceMesh.triangleCount; ++j) {\n const v0 = indices[3 * j + 0];\n const v1 = indices[3 * j + 1];\n const v2 = indices[3 * j + 2];\n p.set(vertices[v0 + 0], vertices[v0 + 1], vertices[v0 + 2]);\n baseBounds.expandByPoint(p);\n p.set(vertices[v1 + 0], vertices[v1 + 1], vertices[v1 + 2]);\n baseBounds.expandByPoint(p);\n p.set(vertices[v2 + 0], vertices[v2 + 1], vertices[v2 + 2]);\n baseBounds.expandByPoint(p);\n }\n\n let filteredOffset = 0;\n const instanceCount = instanceMesh.treeIndices.length;\n const filteredInstanceMatrices = new Float32Array(instanceMesh.instanceMatrices.length);\n const filteredTreeIndices = new Float32Array(instanceCount);\n const filteredColors = new Uint8Array(4 * instanceCount);\n for (let i = 0; i < instanceCount; ++i) {\n float32BufferToMatrix(instanceMesh.instanceMatrices, i, instanceMatrix);\n\n instanceBounds.copy(baseBounds).applyMatrix4(instanceMatrix);\n if (geometryClipBox.intersectsBox(instanceBounds)) {\n const elementInstanceMatrix = instanceMesh.instanceMatrices.subarray(16 * i, 16 * (i + 1));\n const elementColor = instanceMesh.colors.subarray(4 * i, 4 * (i + 1));\n const elementTreeIndex = instanceMesh.treeIndices[i];\n\n filteredInstanceMatrices.set(elementInstanceMatrix, 16 * filteredOffset);\n filteredColors.set(elementColor, 4 * filteredOffset);\n filteredTreeIndices[filteredOffset] = elementTreeIndex;\n\n filteredOffset++;\n }\n }\n\n if (instanceCount === filteredOffset) {\n return instanceMesh; // Unchanged\n }\n\n const filteredMesh: InstancedMesh = {\n triangleCount: instanceMesh.triangleCount,\n triangleOffset: instanceMesh.triangleOffset,\n instanceMatrices: filteredInstanceMatrices.slice(0, 16 * filteredOffset),\n colors: filteredColors.slice(0, 4 * filteredOffset),\n treeIndices: filteredTreeIndices.slice(0, filteredOffset)\n };\n return filteredMesh;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\n/**\n * Sets the elements of a matrix from a row-major\n * matrix stored in a Float32Array.\n * @param buffer\n * @param indexOffset\n * @param outMatrix\n */\nexport function float32BufferToMatrix(\n buffer: Float32Array,\n indexOffset: number,\n outMatrix: THREE.Matrix4\n): THREE.Matrix4 {\n outMatrix.set(\n buffer[indexOffset + 0],\n buffer[indexOffset + 4],\n buffer[indexOffset + 8],\n buffer[indexOffset + 12],\n\n buffer[indexOffset + 1],\n buffer[indexOffset + 5],\n buffer[indexOffset + 9],\n buffer[indexOffset + 13],\n\n buffer[indexOffset + 2],\n buffer[indexOffset + 6],\n buffer[indexOffset + 10],\n buffer[indexOffset + 14],\n\n buffer[indexOffset + 3],\n buffer[indexOffset + 7],\n buffer[indexOffset + 11],\n buffer[indexOffset + 15]\n );\n return outMatrix;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\n/**\n * Generate a three-dimensional plane geometry,\n * with an optional applied tranformation function (u, v) => [ x, y, z ]\n */\nfunction generatePlane3D(\n segmentsX: number,\n segmentsY: number,\n transformFunc: (u: number, v: number) => number[] = (u, v) => [u, v, 0]\n) {\n const vertices = [];\n const indices = [];\n\n const segmentsXInv = 1 / segmentsX;\n const segmentsYInv = 1 / segmentsY;\n for (let j = 0; j <= segmentsY; j++) {\n for (let i = 0; i <= segmentsX; i++) {\n // vertices\n const [x, y, z] = transformFunc(i * segmentsXInv, j * segmentsYInv);\n vertices.push(x || 0, y || 0, z || 0);\n }\n }\n\n for (let j = 1; j <= segmentsY; j++) {\n for (let i = 1; i <= segmentsX; i++) {\n // indices\n const a = (segmentsX + 1) * j + i - 1;\n const b = (segmentsX + 1) * (j - 1) + i - 1;\n const c = (segmentsX + 1) * (j - 1) + i;\n const d = (segmentsX + 1) * j + i;\n\n // faces\n indices.push(a, b, d);\n indices.push(b, c, d);\n }\n }\n\n return {\n index: new THREE.Uint16BufferAttribute(indices, 1),\n position: new THREE.Float32BufferAttribute(vertices, 3)\n };\n}\n\nexport const { boxGeometry, boxGeometryBoundingBox } = (() => {\n const geometry = new THREE.BoxBufferGeometry(1, 1, 1, 1, 1, 1);\n try {\n const result = {\n index: geometry.getIndex(),\n position: geometry.getAttribute('position'),\n normal: geometry.getAttribute('normal')\n };\n geometry.computeBoundingBox();\n return { boxGeometry: result, boxGeometryBoundingBox: geometry.boundingBox! };\n } finally {\n geometry.dispose();\n }\n})();\n\nexport const { quadGeometry, quadGeometryBoundingBox } = (() => {\n const geometry = new THREE.PlaneBufferGeometry(1, 1, 1, 1);\n try {\n const result = {\n index: geometry.getIndex(),\n position: geometry.getAttribute('position'),\n normal: geometry.getAttribute('normal')\n };\n geometry.computeBoundingBox();\n return { quadGeometry: result, quadGeometryBoundingBox: geometry.boundingBox! };\n } finally {\n geometry.dispose();\n }\n})();\n\nexport const { trapeziumGeometry, trapeziumGeometryBoundingBox } = (() => {\n const index = [0, 1, 3, 0, 3, 2];\n const position = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3];\n return {\n trapeziumGeometry: {\n index: new THREE.BufferAttribute(new Uint16Array(index), 1),\n position: new THREE.BufferAttribute(new Float32Array(position), 3)\n },\n trapeziumGeometryBoundingBox: new THREE.Box3().setFromArray(position)\n };\n})();\n\n// cone\nexport const { coneGeometry, coneGeometryBoundingBox } = (() => {\n const positions = [];\n positions.push(-1, 1, -1);\n positions.push(-1, -1, -1);\n positions.push(1, 1, -1);\n positions.push(1, -1, -1);\n positions.push(1, 1, 1);\n positions.push(1, -1, 1);\n\n const indices = new Uint16Array([1, 2, 0, 1, 3, 2, 3, 4, 2, 3, 5, 4]);\n return {\n coneGeometry: {\n index: new THREE.BufferAttribute(indices, 1),\n position: new THREE.BufferAttribute(new Float32Array(positions), 3)\n },\n coneGeometryBoundingBox: new THREE.Box3().setFromArray(positions)\n };\n})();\n\nexport const { torusLodGeometries, torusGeometryBoundingBox } = (() => {\n const lods = [\n { tubularSegments: 9, radialSegments: 18 },\n { tubularSegments: 5, radialSegments: 12 },\n { tubularSegments: 4, radialSegments: 5 }\n ];\n const transformFunc = (u: number, v: number) => [u, v * 2.0 * Math.PI];\n const torusLodGeometries = lods.map(({ tubularSegments, radialSegments }) => {\n return generatePlane3D(radialSegments, tubularSegments, transformFunc);\n });\n\n return {\n torusLodGeometries,\n torusGeometryBoundingBox: new THREE.Box3().setFromArray(\n torusLodGeometries[torusLodGeometries.length - 1].position.array\n )\n };\n})();\n\nexport const { nutGeometry, nutGeometryBoundingBox } = (() => {\n const geometry = new THREE.CylinderBufferGeometry(0.5, 0.5, 1, 6);\n try {\n geometry.applyMatrix4(new THREE.Matrix4().makeRotationX(-Math.PI / 2));\n const result = {\n index: geometry.getIndex(),\n position: geometry.getAttribute('position'),\n normal: geometry.getAttribute('normal')\n };\n return { nutGeometry: result, nutGeometryBoundingBox: new THREE.Box3().setFromArray(result.position.array) };\n } finally {\n geometry.dispose();\n }\n})();\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { disposeAttributeArrayOnUpload } from '@reveal/utilities';\nimport { TriangleMesh } from '@reveal/cad-parsers';\n\nexport function createTriangleMeshes(\n triangleMeshes: TriangleMesh[],\n bounds: THREE.Box3,\n material: THREE.ShaderMaterial,\n geometryClipBox: THREE.Box3 | null\n): THREE.Mesh[] {\n const result: THREE.Mesh[] = [];\n\n const filteredTriangleMeshes = triangleMeshes.filter(mesh => {\n return geometryClipBox === null || isTriangleMeshWithin(mesh, geometryClipBox);\n });\n for (const mesh of filteredTriangleMeshes) {\n const geometry = new THREE.BufferGeometry();\n const indices = new THREE.Uint32BufferAttribute(mesh.indices.buffer, 1).onUpload(disposeAttributeArrayOnUpload);\n const vertices = new THREE.Float32BufferAttribute(mesh.vertices.buffer, 3).onUpload(disposeAttributeArrayOnUpload);\n const colors = new THREE.Uint8BufferAttribute(mesh.colors.buffer, 3).onUpload(disposeAttributeArrayOnUpload);\n\n const treeIndices = new THREE.Float32BufferAttribute(mesh.treeIndices.buffer, 1).onUpload(\n disposeAttributeArrayOnUpload\n );\n geometry.setIndex(indices);\n geometry.setAttribute('color', colors);\n geometry.setAttribute('position', vertices);\n geometry.setAttribute('treeIndex', treeIndices);\n geometry.boundingBox = bounds.clone();\n geometry.boundingSphere = new THREE.Sphere();\n bounds.getBoundingSphere(geometry.boundingSphere);\n\n const obj = new THREE.Mesh(geometry, material);\n obj.name = `Triangle mesh ${mesh.fileId}`;\n\n obj.userData.treeIndices = new Set(mesh.treeIndices);\n\n result.push(obj);\n }\n return result;\n}\n\nconst isTriangleMeshWithinArgs = {\n p: new THREE.Vector3(),\n box: new THREE.Box3()\n};\n\nfunction isTriangleMeshWithin(mesh: TriangleMesh, bounds: THREE.Box3): boolean {\n const { p, box } = isTriangleMeshWithinArgs;\n box.makeEmpty();\n for (let i = 0; i < mesh.vertices.length; i += 3) {\n p.set(mesh.vertices[i + 0], mesh.vertices[i + 1], mesh.vertices[i + 2]);\n box.expandByPoint(p);\n }\n return bounds.intersectsBox(box);\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { CogniteClient } from '@cognite/sdk';\n\nimport { ModelDataProvider } from './types';\n\n/**\n * Provides 3D V2 specific extensions for the standard CogniteClient used by Reveal.\n */\nexport class CdfModelDataProvider implements ModelDataProvider {\n private readonly client: CogniteClient;\n\n constructor(client: CogniteClient) {\n this.client = client;\n }\n\n get headers() {\n return this.client.getDefaultRequestHeaders();\n }\n\n public async getBinaryFile(baseUrl: string, fileName: string): Promise<ArrayBuffer> {\n const url = `${baseUrl}/${fileName}`;\n const headers = {\n ...this.client.getDefaultRequestHeaders(),\n Accept: '*/*'\n };\n\n const response = await fetchWithRetry(url, { headers, method: 'GET' });\n return response.arrayBuffer();\n }\n\n async getJsonFile(baseUrl: string, fileName: string): Promise<any> {\n const response = await this.client.get(`${baseUrl}/${fileName}`);\n return response.data;\n }\n}\n\nasync function fetchWithRetry(input: RequestInfo, options: RequestInit | undefined, retries: number = 3) {\n let error: Error | undefined;\n for (let i = 0; i < retries; i++) {\n try {\n return await fetch(input, options);\n } catch (err) {\n // Keep first error only\n if (error !== undefined) {\n error = err;\n }\n }\n }\n throw error;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport { ModelIdentifier } from '..';\nimport { File3dFormat } from './types';\n\n/**\n * Identifies a 3D model stored in CDF by the combination of a modelId, a revisionId\n * and a format.\n */\nexport class CdfModelIdentifier implements ModelIdentifier {\n readonly revealInternalId: symbol;\n readonly modelFormat: File3dFormat;\n\n readonly modelId: number;\n readonly revisionId: number;\n\n constructor(modelId: number, revisionId: number, modelFormat: File3dFormat) {\n this.revealInternalId = Symbol(`${modelId}/${revisionId}[${modelFormat}]`);\n this.modelId = modelId;\n this.revisionId = revisionId;\n this.modelFormat = modelFormat;\n }\n\n public toString(): string {\n return `${CdfModelIdentifier.name} (${String(this.revealInternalId)} - ${this.modelFormat})`;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { HttpHeaders } from '@cognite/sdk-core';\nexport interface JsonFileProvider {\n getJsonFile(baseUrl: string, fileName: string): Promise<any>;\n}\n\nexport interface BinaryFileProvider {\n getBinaryFile(baseUrl: string, fileName: string): Promise<ArrayBuffer>;\n}\n\n/**\n * Provides data for 3D models.\n * @version New since 2.2\n */\nexport interface ModelDataProvider extends HttpHeadersProvider, JsonFileProvider, BinaryFileProvider {\n /**\n * Download and parse a JSON file and return the resulting struct.\n * @param baseUrl Base URL of the model.\n * @param fileName Filename of JSON file.\n */\n getJsonFile(baseUrl: string, fileName: string): Promise<any>;\n /**\n * Downloads a binary blob.\n * @param baseUrl Base URL of the model.\n * @param fileName Filename of binary file.\n */\n getBinaryFile(baseUrl: string, fileName: string): Promise<ArrayBuffer>;\n}\n\nexport interface HttpHeadersProvider {\n readonly headers: HttpHeaders;\n}\n\nexport enum File3dFormat {\n EptPointCloud = 'ept-pointcloud',\n RevealCadModel = 'reveal-directory',\n AnyFormat = 'all-outputs'\n}\n\nexport interface BlobOutputMetadata {\n blobId: number;\n format: File3dFormat | string;\n version: number;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { File3dFormat } from './types';\n\n// The below is equal to new THREE.Matrix4().makeRotationFromEuler(new THREE.Euler(-Math.PI / 2, 0, 0));\nconst cadFromCdfToThreeMatrix = new THREE.Matrix4().set(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1);\n\nexport function applyDefaultModelTransformation(matrix: THREE.Matrix4, format: File3dFormat | string): void {\n switch (format) {\n case File3dFormat.RevealCadModel:\n matrix.premultiply(cadFromCdfToThreeMatrix);\n break;\n\n case File3dFormat.EptPointCloud:\n // No action, identity transform\n break;\n\n default:\n throw new Error(`Unknown model format '${format}`);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { BlobOutputMetadata, File3dFormat } from './types';\n\nexport class Model3DOutputList {\n public readonly modelId: number;\n public readonly revisionId: number;\n public readonly outputs: BlobOutputMetadata[];\n\n constructor(modelId: number, revisionId: number, outputs: BlobOutputMetadata[]) {\n this.modelId = modelId;\n this.revisionId = revisionId;\n this.outputs = outputs;\n }\n\n /**\n * Finds an output with a given format of the most recent version.\n *\n * @param outputFormat Format to find output for, either a well known format a custom format.\n * @param supportedVersions Optional list of supported version. If not provided all versions are considered.\n */\n public findMostRecentOutput(\n outputFormat: File3dFormat | string,\n supportedVersions?: number[]\n ): BlobOutputMetadata | undefined {\n const candidates = this.outputs.filter(\n x => x.format === outputFormat && (!supportedVersions || supportedVersions.indexOf(x.version) !== -1)\n );\n return candidates.length > 0\n ? candidates.reduce((left, right) => {\n return right.version > left.version ? right : left;\n })\n : undefined;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\nimport { BlobOutputMetadata } from './types';\nimport { ModelMetadataProvider } from './ModelMetadataProvider';\n\nimport { applyDefaultModelTransformation } from './applyDefaultModelTransformation';\nimport { Model3DOutputList } from './Model3DOutputList';\n\nimport { CogniteClient } from '@cognite/sdk';\nimport { ItemsResponse } from '@cognite/sdk-core';\nimport { ModelIdentifier } from './ModelIdentifier';\nimport { CdfModelIdentifier } from './CdfModelIdentifier';\n\n// TODO 2020-06-25 larsmoa: Extend CogniteClient.files3d.retrieve() to support subpath instead of\n// using URLs directly. Also add support for listing outputs in the SDK.\nexport class CdfModelMetadataProvider implements ModelMetadataProvider {\n private readonly _client: CogniteClient;\n\n constructor(client: CogniteClient) {\n this._client = client;\n }\n\n public async getModelMatrix(modelIdentifier: ModelIdentifier): Promise<THREE.Matrix4> {\n if (!(modelIdentifier instanceof CdfModelIdentifier)) {\n throw new Error(`Model must be a ${CdfModelIdentifier.name}, but got ${modelIdentifier.toString()}`);\n }\n\n const { modelId, revisionId, modelFormat } = modelIdentifier;\n const model = await this._client.revisions3D.retrieve(modelId, revisionId);\n\n const modelMatrix = new THREE.Matrix4();\n if (model.rotation) {\n modelMatrix.makeRotationFromEuler(new THREE.Euler(...model.rotation));\n }\n applyDefaultModelTransformation(modelMatrix, modelFormat);\n return modelMatrix;\n }\n\n public async getModelCamera(\n modelIdentifier: ModelIdentifier\n ): Promise<{ position: THREE.Vector3; target: THREE.Vector3 } | undefined> {\n if (!(modelIdentifier instanceof CdfModelIdentifier)) {\n throw new Error(`Model must be a ${CdfModelIdentifier.name}, but got ${modelIdentifier.toString()}`);\n }\n\n const { modelId, revisionId } = modelIdentifier;\n const model = await this._client.revisions3D.retrieve(modelId, revisionId);\n if (model.camera && model.camera.position && model.camera.target) {\n const { position, target } = model.camera;\n return {\n position: new THREE.Vector3(position[0], position[1], position[2]),\n target: new THREE.Vector3(target[0], target[1], target[2])\n };\n }\n return undefined;\n }\n\n public async getModelUri(modelIdentifier: ModelIdentifier): Promise<string> {\n if (!(modelIdentifier instanceof CdfModelIdentifier)) {\n throw new Error(`Model must be a ${CdfModelIdentifier.name}, but got ${modelIdentifier.toString()}`);\n }\n\n const { modelId, revisionId, modelFormat } = modelIdentifier;\n const outputs = await this.getOutputs(modelIdentifier);\n const mostRecentOutput = outputs.findMostRecentOutput(modelFormat);\n if (!mostRecentOutput) {\n throw new Error(\n `Model '${modelId}/${revisionId}' is not compatible with this version of Reveal, because no outputs for format '(${modelFormat})' was found. If this model works with a previous version of Reveal it must be reprocessed to support this version.`\n );\n }\n const directoryId = mostRecentOutput.blobId;\n return `${this._client.getBaseUrl()}${this.getRequestPath(directoryId)}`;\n }\n\n private async getOutputs(modelIdentifier: CdfModelIdentifier): Promise<Model3DOutputList> {\n const { modelId, revisionId, modelFormat } = modelIdentifier;\n const url = `/api/v1/projects/${this._client.project}/3d/models/${modelId}/revisions/${revisionId}/outputs`;\n const params = modelFormat !== undefined ? { params: { format: modelFormat } } : undefined;\n const response = await this._client.get<ItemsResponse<BlobOutputMetadata>>(url, params);\n if (response.status === 200) {\n return new Model3DOutputList(modelId, revisionId, response.data.items);\n }\n throw new Error(`Unexpected response ${response.status} (payload: '${response.data})`);\n }\n\n private getRequestPath(directoryId: number): string {\n return `/api/v1/projects/${this._client.project}/3d/files/${directoryId}`;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { CdfModelIdentifier } from './CdfModelIdentifier';\nimport { Model3DOutputList } from './Model3DOutputList';\nimport { BlobOutputMetadata } from './types';\n\nimport { CogniteClient } from '@cognite/sdk';\nimport { ItemsResponse } from '@cognite/sdk-core';\n\n/**\n * Helper class for getting the available 'outputs' from the Cognite\n * 3D processing pipeline for a given model.\n */\nexport class CdfModelOutputsProvider {\n private readonly _client: CogniteClient;\n\n constructor(client: CogniteClient) {\n this._client = client;\n }\n\n public async getOutputs(modelIdentifier: CdfModelIdentifier): Promise<Model3DOutputList> {\n const { modelId, revisionId, modelFormat } = modelIdentifier;\n const url = `/api/v1/projects/${this._client.project}/3d/models/${modelId}/revisions/${revisionId}/outputs`;\n const params = modelFormat !== undefined ? { params: { format: modelFormat } } : undefined;\n const response = await this._client.get<ItemsResponse<BlobOutputMetadata>>(url, params);\n if (response.status === 200) {\n return new Model3DOutputList(modelId, revisionId, response.data.items);\n }\n throw new Error(`Unexpected response ${response.status} (payload: '${response.data})`);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { Versioned3DFile } from '@cognite/sdk';\n\n// To avoid direct dependency on @cognite/sdk we use sdk-core here for HttpError.\n// that's why it's avoided https://github.com/cognitedata/cdf-hub/pull/687/files#r489204315\nimport { HttpError } from '@cognite/sdk-core';\n\nexport const supportedVersions = [8];\n\nexport function getNewestVersionedFile(files: Versioned3DFile[]): Versioned3DFile {\n return files\n .filter(file => supportedVersions.includes(file.version))\n .reduce((newestFile, file) => (file.version > newestFile.version ? file : newestFile), {\n fileId: -1,\n version: -1\n });\n}\n\nexport async function fetchWithStatusCheck(url: string): Promise<Response> {\n const response = await fetch(url);\n if (!response.ok) {\n const headers: { [key: string]: string } = {};\n response.headers.forEach((key, value) => {\n headers[key] = value;\n });\n throw new HttpError(response.status, response.body, headers);\n }\n return response;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { ModelDataProvider } from './types';\nimport { fetchWithStatusCheck } from './utilities';\n\nexport class LocalModelDataProvider implements ModelDataProvider {\n get headers() {\n return {};\n }\n\n async getBinaryFile(baseUrl: string, fileName: string): Promise<ArrayBuffer> {\n const response = await fetchWithStatusCheck(`${baseUrl}/${fileName}`);\n return response.arrayBuffer();\n }\n\n async getJsonFile(baseUrl: string, fileName: string): Promise<any> {\n const response = await fetchWithStatusCheck(`${baseUrl}/${fileName}`);\n return response.json();\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { ModelIdentifier } from './ModelIdentifier';\n\n/**\n * Identifies a 3D model by a URL. This implementation is used for testing\n * purposes.\n */\nexport class LocalModelIdentifier implements ModelIdentifier {\n readonly revealInternalId: symbol;\n readonly localPath: string;\n\n constructor(localPath: string) {\n this.revealInternalId = Symbol(localPath);\n this.localPath = localPath;\n }\n\n public toString(): string {\n return `${LocalModelIdentifier.name} (${this.localPath})`;\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nimport { applyDefaultModelTransformation } from './applyDefaultModelTransformation';\nimport { LocalModelIdentifier } from './LocalModelIdentifier';\nimport { ModelIdentifier } from './ModelIdentifier';\nimport { ModelMetadataProvider } from './ModelMetadataProvider';\nimport { File3dFormat } from './types';\n\nexport class LocalModelMetadataProvider implements ModelMetadataProvider {\n getModelUri(modelIdentifier: ModelIdentifier): Promise<string> {\n if (!(modelIdentifier instanceof LocalModelIdentifier)) {\n throw new Error(`Model must be a ${LocalModelIdentifier.name}, but got ${modelIdentifier.toString()}`);\n }\n return Promise.resolve(`${location.origin}/${modelIdentifier.localPath}`);\n }\n\n async getModelMatrix(modelIdentifier: ModelIdentifier): Promise<THREE.Matrix4> {\n if (!(modelIdentifier instanceof LocalModelIdentifier)) {\n throw new Error(`Model must be a ${LocalModelIdentifier.name}, but got ${modelIdentifier.toString()}`);\n }\n\n const matrix = new THREE.Matrix4();\n applyDefaultModelTransformation(matrix, File3dFormat.RevealCadModel);\n return matrix;\n }\n\n getModelCamera(\n modelIdentifier: ModelIdentifier\n ): Promise<{ position: THREE.Vector3; target: THREE.Vector3 } | undefined> {\n if (!(modelIdentifier instanceof LocalModelIdentifier)) {\n throw new Error(`Model must be a ${LocalModelIdentifier.name}, but got ${modelIdentifier.toString()}`);\n }\n\n return Promise.resolve(undefined);\n }\n}\n","module.exports = require(\"assert\");","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport mixpanel from 'mixpanel-browser';\n\nimport log from '@reveal/logger';\n\nimport { TrackedEvents, EventProps } from './types';\n\n/**\n * Source: https://stackoverflow.com/a/2117523/167251\n */\nfunction generateUuidv4(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0,\n v = c == 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nconst { VERSION, MIXPANEL_TOKEN } = process.env;\n\n// Don't identify users in MixPanel to avoid GDPR problems\nconst mixpanelDistinctId = 'reveal-single-user';\n\nexport class MetricsLogger {\n _sessionProps: {\n VERSION: string;\n project: string;\n application: string;\n sessionId: string;\n };\n\n private constructor(project: string, applicationId: string, eventProps: EventProps) {\n // Even though mixpanel has an opt out property, the mixpanel object\n // used by Metrics is not available here, so we have our own way of opting out.\n\n mixpanel.init(MIXPANEL_TOKEN, {\n disable_cookie: true,\n disable_persistence: true,\n // Don't send IP which disables geolocation\n ip: false,\n // Avoid sending a bunch of properties that might help identifying a user\n property_blacklist: [\n // https://help.mixpanel.com/hc/en-us/articles/115004613766-Default-Properties-Collected-by-Mixpanel#profile-properties-javascript\n '$city',\n '$region',\n 'mp_country_code',\n '$geo_source',\n '$timezone',\n 'mp_lib',\n '$lib_version',\n '$device_id',\n '$user_id',\n '$current_url',\n '$screen_width',\n '$screen_height',\n '$referrer',\n '$referring_domain',\n '$initial_referrer',\n '$initial_referring_domain'\n ]\n });\n // Reset device ID (even if we don't send it)\n mixpanel.reset();\n\n mixpanel.identify(mixpanelDistinctId);\n\n this._sessionProps = {\n VERSION,\n project: 'unknown',\n application: 'unknown',\n // Use a random identifier because we want to don't track users over multiple sessions to not\n // violate GDPR.\n sessionId: generateUuidv4()\n };\n\n if (project) {\n this._sessionProps.project = project;\n }\n if (applicationId) {\n this._sessionProps.application = applicationId;\n }\n this.innerTrackEvent('init', eventProps);\n }\n\n static init(logMetrics: boolean, project: string, applicationId: string, eventProps: EventProps) {\n if (globalThis.revealMetricsLogger === undefined && logMetrics) {\n const metricsLogger = new MetricsLogger(project, applicationId, eventProps);\n globalThis.revealMetricsLogger = { metricsLogger };\n }\n }\n\n private innerTrackEvent(eventName: TrackedEvents, eventProps: EventProps) {\n const combined = { ...this._sessionProps, ...eventProps };\n mixpanel.track(eventName, combined);\n }\n\n static trackEvent(eventName: TrackedEvents, eventProps: EventProps) {\n if (globalThis.revealMetricsLogger) {\n globalThis.revealMetricsLogger.metricsLogger.innerTrackEvent(eventName, eventProps);\n }\n }\n\n static trackCreateTool(toolName: string) {\n MetricsLogger.trackEvent('toolCreated', { toolName });\n }\n\n static trackLoadModel(eventProps: EventProps, modelIdentifier: any) {\n MetricsLogger.trackEvent('loadModel', { ...eventProps, modelIdentifier });\n }\n\n static trackCadModelStyled(nodeCollectionClassToken: string, appearance: any) {\n MetricsLogger.trackEvent('cadModelStyleAssigned', { nodeCollectionClassToken, style: appearance });\n }\n\n static trackError(error: Error, eventProps: EventProps) {\n log.error(error);\n\n this.trackEvent('error', {\n message: error.message,\n name: error.name,\n stack: error.stack,\n ...eventProps\n });\n }\n\n static trackCameraNavigation(eventProps: EventProps) {\n MetricsLogger.trackEvent('cameraNavigated', eventProps);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n// This file is in place for future-proofing. We can change the implementation here if\n// we want to use something else than loglevel.\n\nimport * as log from 'loglevel';\nexport default log;\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport log from './src/Log';\nexport default log;\n","module.exports = require(\"@tweenjs/tween.js\");","module.exports = require(\"mixpanel-browser\");","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nconst worldToViewportVars = {\n renderSize: new THREE.Vector2(),\n position: new THREE.Vector3()\n};\n\n/**\n * Maps from 3D world coordinates to normalized screen coordinates\n * relative to the canvas being rendered to. X and Y will\n * be in range [0, 1]. Z is in range [-1, 1] if the coordinate\n * is inside the camera near and far planes.\n * @param camera Camera used to project point from 3D to NDC coordinates\n * @param position3D World position in 3D\n * @param out Optionally pre-allocated THREE.Vector3\n * @returns Relative screen coordinates in X, Y and Z in range [-1, 1] if point\n * is within near/far of camera.\n */\nexport function worldToNormalizedViewportCoordinates(\n camera: THREE.PerspectiveCamera,\n position3D: THREE.Vector3,\n out: THREE.Vector3 = new THREE.Vector3()\n): THREE.Vector3 {\n const { position } = worldToViewportVars;\n\n // map to normalized device coordinate (NDC) space\n position.copy(position3D);\n position.project(camera);\n\n // map to 2D screen space\n const x = (position.x + 1) / 2;\n const y = (-position.y + 1) / 2;\n\n return out.set(x, y, position.z);\n}\n\n/**\n * Maps from 3D world coordinates to screen coordinates\n * relative to the canvas. X and Y will be in absolute\n * coordinates (0,0 being the top left of the canvas). Z is\n * in range [-1, 1] if the coordinate\n * is inside the camera near and far planes.\n * @param renderer Renderer used to render the \"world\"\n * @param camera Camera used to project point from 3D to NDC coordinates\n * @param position3D World position in 3D\n * @param out Optionally pre-allocated THREE.Vector3\n * @returns Relative screen coordinates in X, Y and Z in range [-1, 1] if point\n * is within near/far of camera.\n */\nexport function worldToViewportCoordinates(\n renderer: THREE.WebGLRenderer,\n camera: THREE.PerspectiveCamera,\n position3D: THREE.Vector3,\n out: THREE.Vector3 = new THREE.Vector3()\n): THREE.Vector3 {\n worldToNormalizedViewportCoordinates(camera, position3D, out);\n\n const { renderSize } = worldToViewportVars;\n renderer.getSize(renderSize);\n\n const canvas = renderer.domElement;\n const { width: canvasWidth, height: canvasHeight } = canvas.getBoundingClientRect();\n\n out.x = Math.round(out.x * canvasWidth);\n out.y = Math.round(out.y * canvasHeight);\n return out;\n}\n","module.exports = require(\"lodash/cloneDeep\");","module.exports = require(\"geo-three\");","module.exports = require(\"@cognite/sdk-core\");","/*!\n * Copyright 2021 Cognite AS\n */\n\nexport { worldToViewportCoordinates, worldToNormalizedViewportCoordinates } from './worldToViewport';\nexport { BoundingBoxClipper } from './BoundingBoxClipper';\n\nexport { assertNever, EventTrigger } from '@reveal/utilities';\n\nexport { LoadingState } from '@reveal/cad-geometry-loaders';\n\nexport { LocalModelIdentifier, CdfModelIdentifier } from '@reveal/modeldata-api';\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nexport class BoundingBoxClipper {\n private readonly _box: THREE.Box3;\n private readonly _clippingPlanes: THREE.Plane[] = [\n new THREE.Plane(),\n new THREE.Plane(),\n new THREE.Plane(),\n new THREE.Plane(),\n new THREE.Plane(),\n new THREE.Plane()\n ];\n\n constructor(box?: THREE.Box3) {\n this._box = box || new THREE.Box3();\n this.updatePlanes();\n }\n\n set minX(x: number) {\n this._box.min.x = x;\n this.updatePlanes();\n }\n\n get minX() {\n return this._box.min.x;\n }\n\n set minY(y: number) {\n this._box.min.y = y;\n this.updatePlanes();\n }\n\n get minY() {\n return this._box.min.y;\n }\n\n set minZ(z: number) {\n this._box.min.z = z;\n this.updatePlanes();\n }\n\n get minZ() {\n return this._box.min.z;\n }\n\n set maxX(x: number) {\n this._box.max.x = x;\n this.updatePlanes();\n }\n\n get maxX() {\n return this._box.max.x;\n }\n\n set maxY(y: number) {\n this._box.max.y = y;\n this.updatePlanes();\n }\n\n get maxY() {\n return this._box.max.y;\n }\n\n set maxZ(z: number) {\n this._box.max.z = z;\n this.updatePlanes();\n }\n\n get maxZ() {\n return this._box.max.z;\n }\n\n private updatePlanes() {\n this._clippingPlanes[0].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(1, 0, 0),\n new THREE.Vector3(this.minX, 0, 0)\n );\n this._clippingPlanes[1].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(-1, 0, 0),\n new THREE.Vector3(this.maxX, 0, 0)\n );\n this._clippingPlanes[2].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(0, 1, 0),\n new THREE.Vector3(0, this.minY, 0)\n );\n this._clippingPlanes[3].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(0, -1, 0),\n new THREE.Vector3(0, this.maxY, 0)\n );\n this._clippingPlanes[4].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(0, 0, 1),\n new THREE.Vector3(0, 0, this.minZ)\n );\n this._clippingPlanes[5].setFromNormalAndCoplanarPoint(\n new THREE.Vector3(0, 0, -1),\n new THREE.Vector3(0, 0, this.maxZ)\n );\n }\n\n get clippingPlanes() {\n return this._clippingPlanes;\n }\n}\n","module.exports = require(\"lodash/range\");","module.exports = require(\"comlink\");","module.exports = require(\"loglevel\");","module.exports = require(\"lodash/debounce\");","module.exports = require(\"skmeans\");","module.exports = require(\"lodash/merge\");","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { assertNever, EventTrigger } from '@reveal/core/utilities';\n\n/**\n * Base class for tools attaching to a {@see Cognite3DViewer}.\n */\nexport abstract class Cognite3DViewerToolBase {\n private readonly _disposedEvent = new EventTrigger<() => void>();\n private _disposed = false;\n\n /**\n * Registers an event handler that is triggered when {@see Cognite3DViewerToolBase.dispose} is\n * called.\n * @param event\n * @param handler\n * @internal\n */\n on(event: 'disposed', handler: () => void) {\n switch (event) {\n case 'disposed':\n this._disposedEvent.subscribe(handler);\n break;\n\n default:\n assertNever(event);\n }\n }\n\n /**\n * Unregisters an event handler for the 'disposed'-event.\n * @param event\n * @param handler\n */\n off(event: 'disposed', handler: () => void) {\n switch (event) {\n case 'disposed':\n this._disposedEvent.unsubscribe(handler);\n break;\n\n default:\n assertNever(event);\n }\n }\n\n /**\n * Disposes the element and triggeres the 'disposed' event before clearing the list\n * of dipose-listeners.\n */\n dispose(): void {\n if (this._disposed) {\n throw new Error('Already disposed');\n }\n this._disposed = true;\n this._disposedEvent.fire();\n this._disposedEvent.unsubscribeAll();\n }\n\n /**\n * Throws an error if the instance has been disposed.\n */\n protected ensureNotDisposed(): void {\n if (this._disposed) {\n throw new Error('The tool has been disposed');\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\nimport range from 'lodash/range';\n\ntype SimpleGrid2DElement<T> = {\n bounds: THREE.Box2;\n element: T;\n};\n\n/**\n * Data structure that splits a 2D region into cells where each cell can contain zero to many\n * elements. Elements can be stored in several cells. This data structure make overlap lookups\n * efficient.\n *\n * Note! This class is tailored for usage with {@link HtmlOverlayTool} and has a few restrictions\n * and assumptions associated with the usage. If used elsewhere, take care as to how this affects\n * performance and behaviour.\n */\nexport class BucketGrid2D<T> {\n private readonly _dimensions: [width: number, height: number];\n private readonly _bounds: THREE.Box2;\n private readonly _cells: SimpleGrid2DElement<T>[][];\n /**\n * Holds elements that has been removed from the collection using {@link removeOverlappingElements}.\n * This is used to avoid expensive re-allocations of cells when removing elements.\n */\n private readonly _removedElements = new Set<T>();\n\n constructor(bounds: THREE.Box2, dimensions: [width: number, height: number]) {\n this._dimensions = dimensions;\n this._cells = range(0, dimensions[0] * dimensions[1]).map(() => new Array<SimpleGrid2DElement<T>>());\n this._bounds = bounds;\n }\n\n insert(bounds: THREE.Box2, element: T) {\n if (!this._bounds.intersectsBox(bounds)) {\n throw new Error('Element to be added must be partially inside grid');\n }\n if (this._removedElements.has(element)) {\n throw new Error('Re-adding previously taken elements is currently not supported');\n }\n\n for (const cell of this.cellsIntersecting(bounds)) {\n cell.push({ bounds, element });\n }\n }\n\n *overlappingElements(bounds: THREE.Box2): Generator<T> {\n if (!this._bounds.intersectsBox(bounds)) {\n return;\n }\n\n const visitedElements = new Set<T>();\n for (const cell of this.cellsIntersecting(bounds)) {\n for (const candidateElement of cell) {\n if (\n !visitedElements.has(candidateElement.element) &&\n !this._removedElements.has(candidateElement.element) &&\n bounds.intersectsBox(candidateElement.bounds)\n ) {\n visitedElements.add(candidateElement.element);\n yield candidateElement.element;\n }\n }\n }\n }\n\n *removeOverlappingElements(bounds: THREE.Box2): Generator<T> {\n if (!this._bounds.intersectsBox(bounds)) {\n return;\n }\n\n for (const cell of this.cellsIntersecting(bounds)) {\n for (let i = 0; i < cell.length; i++) {\n const candidateElement = cell[i];\n if (!this._removedElements.has(candidateElement.element) && bounds.intersectsBox(candidateElement.bounds)) {\n this._removedElements.add(candidateElement.element);\n yield candidateElement.element;\n }\n }\n }\n }\n\n private *cellsIntersecting(bounds: THREE.Box2): Generator<SimpleGrid2DElement<T>[]> {\n const { min, max } = this._bounds;\n const dimX = this._dimensions[0];\n const dimY = this._dimensions[1];\n const relativeBoundsMinX = (bounds.min.x - min.x) / (max.x - min.x);\n const relativeBoundsMaxX = (bounds.max.x - min.x) / (max.x - min.x);\n const relativeBoundsMinY = (bounds.min.y - min.y) / (max.y - min.y);\n const relativeBoundsMaxY = (bounds.max.y - min.y) / (max.y - min.y);\n\n const clamp = THREE.MathUtils.clamp;\n const minI = clamp(Math.floor(dimX * relativeBoundsMinX), 0, dimX - 1);\n const maxI = clamp(Math.floor(dimX * relativeBoundsMaxX), 0, dimX - 1);\n const minJ = clamp(Math.floor(dimY * relativeBoundsMinY), 0, dimY - 1);\n const maxJ = clamp(Math.floor(dimY * relativeBoundsMaxY), 0, dimY - 1);\n for (let j = minJ; j <= maxJ; ++j) {\n for (let i = minI; i <= maxI; ++i) {\n yield this._cells[j * dimX + i];\n }\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\nimport { Cognite3DViewerToolBase } from '../Cognite3DViewerToolBase';\nimport { BucketGrid2D } from './BucketGrid2D';\n\nimport { MetricsLogger } from '@reveal/metrics';\nimport { assertNever, worldToViewportCoordinates } from '@reveal/core/utilities';\nimport { Cognite3DViewer, DisposedDelegate, SceneRenderedDelegate } from '@reveal/core';\nimport debounce from 'lodash/debounce';\n\n/**\n * Callback that is triggered whenever the 2D position of an overlay is updated\n * in {@link HtmlOverlayTool}.\n */\nexport type HtmlOverlayPositionUpdatedDelegate = (\n element: HTMLElement,\n position2D: THREE.Vector2,\n position3D: THREE.Vector3,\n distanceToCamera: number,\n userData: any\n) => void;\n\n/**\n * Callback that is triggered when a set of overlays are clustered together in\n * {@link HtmlOverlayTool}.\n */\nexport type HtmlOverlayCreateClusterDelegate = (\n overlayElements: {\n htmlElement: HTMLElement;\n userData: any;\n }[]\n) => HTMLElement;\n\n/**\n * Options for an overlay added using {@link HtmlOverlayTool.add}.\n */\nexport type HtmlOverlayOptions = {\n /**\n * Callback that is triggered whenever the position of the overlay is updated. Optional.\n */\n positionUpdatedCallback?: HtmlOverlayPositionUpdatedDelegate;\n /**\n * Optional user specified data that is provided to the {@link HtmlOverlayCreateClusterDelegate} and\n * {@link HtmlOverlayPositionUpdatedDelegate}.\n */\n userData?: any;\n};\n\n/**\n * Controls how close overlay elements are clustered together.\n */\nexport type HtmlOverlayToolClusteringOptions = {\n /**\n * Currently only 'overlapInScreenSpace' is supported. In this mode,\n * overlays are clustered together into a single element as defined by\n * the {@link createClusterElementCallback} and hidden when they overlap\n * in screen space. The composite element is placed at the midpoint of\n * all clustered elements.\n *\n * Clustered elements are faded in/out using CSS styling `transition`,\n * `opacity` and `visibility`.\n */\n mode: 'overlapInScreenSpace';\n\n /**\n * Callback that is triggered when a set of overlays are clustered together\n * to create a \"composite\" element as a placeholder for the clustered elements.\n * Note that this callback will be triggered every frame for each cluster so it\n * must be performant.\n */\n createClusterElementCallback: HtmlOverlayCreateClusterDelegate;\n};\n\nexport type HtmlOverlayToolOptions = {\n clusteringOptions?: HtmlOverlayToolClusteringOptions;\n};\n\ntype HtmlOverlayElement = {\n position3D: THREE.Vector3;\n options: HtmlOverlayOptions;\n\n state: {\n visible: boolean;\n position2D: THREE.Vector2;\n width: number;\n height: number;\n };\n};\n\n/**\n * Manages HTMLoverlays for {@see Cognite3DViewer}. Attaches HTML elements to a \n * 3D position and updates its position/visibility as user moves the camera. This is \n * useful to create HTML overlays to highlight information about key positions in the 3D model.\n *\n * Attached elements *must* have CSS style 'position: absolute'. It's also recommended\n * in most cases to have styles 'pointer-events: none' and 'touch-action: none' to avoid\n * interfering with 3D navigation. Consider also applying 'transform: translate(-50%, -50%)'\n * to anchor the center of the element rather than the top-left corner. In some cases the\n * `zIndex`-attribute is necessary for the element to appear on top of the viewer.\n *\n * @example\n * ```js\n * const el = document.createElement('div');\n * el.style.position = 'absolute'; // Required!\n * // Anchor to center of element\n * el.style.transform = 'translate(-50%, -50%)';\n * // Avoid being target for events\n * el.style.pointerEvents = 'none;\n * el.style.touchAction = 'none';\n * // Render in front of other elements\n * el.style.zIndex = 10;\n *\n * el.style.color = 'red';\n * el.innerHtml = '<h1>Overlay</h1>';\n *\n * const overlayTool = new HtmlOverlayTool(viewer);\n * overlayTool.add(el, new THREE.Vector3(10, 10, 10));\n * // ...\n * overlayTool.remove(el);\n * // or, to remove all attached elements\n * overlayTool.clear();\n \n * // detach the tool from the viewer\n * overlayTool.dispose();\n * ```\n */\nexport class HtmlOverlayTool extends Cognite3DViewerToolBase {\n private readonly _viewer: Cognite3DViewer;\n private readonly _options: HtmlOverlayToolOptions;\n private readonly _htmlOverlays: Map<HTMLElement, HtmlOverlayElement> = new Map();\n private readonly _compositeOverlays: HTMLElement[] = [];\n\n private readonly _onSceneRenderedHandler: SceneRenderedDelegate;\n private readonly _onViewerDisposedHandler: DisposedDelegate;\n // Allocate variables needed for processing once to avoid allocations\n private readonly _preallocatedVariables = {\n camPos: new THREE.Vector3(),\n camNormal: new THREE.Vector3(),\n point: new THREE.Vector3(),\n nearPlane: new THREE.Plane(),\n farPlane: new THREE.Plane(),\n position2D: new THREE.Vector2()\n };\n\n private readonly scheduleUpdate: () => void;\n\n private get viewerDomElement(): HTMLElement {\n return this._viewer.domElement;\n }\n\n private get viewerCamera(): THREE.PerspectiveCamera {\n return this._viewer.getCamera();\n }\n\n private get viewerRenderer(): THREE.WebGLRenderer {\n return this._viewer.renderer;\n }\n\n constructor(viewer: Cognite3DViewer, options?: HtmlOverlayToolOptions) {\n super();\n\n this._onSceneRenderedHandler = this.onSceneRendered.bind(this);\n this._onViewerDisposedHandler = this.onViewerDisposed.bind(this);\n this._options = options ?? {};\n this._viewer = viewer;\n this._viewer.on('sceneRendered', this._onSceneRenderedHandler);\n this._viewer.on('disposed', this._onViewerDisposedHandler);\n\n this.scheduleUpdate = debounce(() => this.forceUpdate(), 20);\n\n MetricsLogger.trackCreateTool('HtmlOverlayTool');\n }\n\n /**\n * Returns all added HTML elements along with their 3D positions.\n */\n get elements(): { element: HTMLElement; position3D: THREE.Vector3 }[] {\n return Array.from(this._htmlOverlays.entries()).map(([element, info]) => {\n return { element, position3D: info.position3D };\n });\n }\n\n /**\n * Removes all elements and detaches from the viewer.\n * @override\n */\n dispose(): void {\n this._viewer.off('sceneRendered', this._onSceneRenderedHandler);\n this._viewer.off('disposed', this._onViewerDisposedHandler);\n this.clear();\n super.dispose();\n }\n\n /**\n * Registers a HTML overlay that will be updated on rendering.\n *\n * @param htmlElement\n * @param position3D\n * @param options\n */\n add(htmlElement: HTMLElement, position3D: THREE.Vector3, options: HtmlOverlayOptions = {}) {\n this.ensureNotDisposed();\n\n if (this.viewerDomElement.contains(htmlElement)) {\n throw new Error(`Element is already attached to viewer`);\n }\n\n htmlElement.style.visibility = 'hidden';\n\n // Note! Must be part of DOM tree before we do getComputedStyle(), so add before check\n this.viewerDomElement.appendChild(htmlElement);\n const style = getComputedStyle(htmlElement);\n if (style.position !== 'absolute') {\n this.viewerDomElement.removeChild(htmlElement);\n throw new Error(`htmlElement style must have a position of absolute. but was '${style.position}'`);\n }\n\n const element: HtmlOverlayElement = {\n position3D,\n options,\n state: {\n position2D: new THREE.Vector2(),\n width: -1,\n height: -1,\n visible: true\n }\n };\n this._htmlOverlays.set(htmlElement, element);\n\n this.scheduleUpdate();\n }\n\n /**\n * Removes a overlay and removes it from the DOM.\n * @param htmlElement\n */\n remove(htmlElement: HTMLElement) {\n this.ensureNotDisposed();\n if (!this.viewerDomElement.contains(htmlElement) || !this._htmlOverlays.has(htmlElement)) {\n throw new Error(`Element is not attached to viewer`);\n }\n this.viewerDomElement.removeChild(htmlElement);\n this._htmlOverlays.delete(htmlElement);\n }\n\n /**\n * Removes all attached HTML overlay elements.\n */\n clear() {\n const overlays = Array.from(this._htmlOverlays.keys());\n for (const element of overlays) {\n this.remove(element);\n }\n }\n\n /**\n * Updates positions of all overlays. This is automatically managed and there\n * shouldn't be any reason to trigger this unless the attached elements are\n * modified externally.\n *\n * Calling this function often might cause degraded performance.\n */\n forceUpdate(): void {\n this.ensureNotDisposed();\n this.cleanupClusterElements();\n if (this._htmlOverlays.size === 0) {\n return;\n }\n this.updateNewElementSizes();\n\n const camera = this.viewerCamera;\n const renderer = this.viewerRenderer;\n const { camPos, camNormal, point, nearPlane, farPlane, position2D } = this._preallocatedVariables;\n\n // Determine near/far plane to cull based on distance. Note! We don't cull outside the \"walls\"\n // of the frustum to allow HTML elements that are partially outside the edges. The HTML clipping\n // will fix this anyways\n camera.getWorldPosition(camPos);\n camera.getWorldDirection(camNormal);\n point.copy(camPos).addScaledVector(camNormal, camera.near);\n nearPlane.setFromNormalAndCoplanarPoint(camNormal, point);\n point.copy(camPos).addScaledVector(camNormal, camera.far);\n farPlane.setFromNormalAndCoplanarPoint(camNormal, point);\n\n this._htmlOverlays.forEach((element, htmlElement) => {\n const {\n position3D,\n options: { positionUpdatedCallback, userData },\n state\n } = element;\n\n const insideCameraPlanes =\n nearPlane.distanceToPoint(position3D) >= 0.0 && farPlane.distanceToPoint(position3D) <= 0.0;\n // TODO 2021-11-19 larsmoa: Replace worldToViewportCoordinates() with something that doesn't cause\n // canvas.getClientBoundingRect() to be called when PR #1700 is done.\n // https://github.com/cognitedata/reveal/pull/1700\n const { x, y } = worldToViewportCoordinates(renderer, camera, position3D);\n\n if (insideCameraPlanes) {\n state.position2D.set(x, y);\n state.visible = true;\n } else {\n // Outside frustum - hide point\n state.visible = false;\n }\n\n if (positionUpdatedCallback) {\n position2D.set(x, y);\n const distanceToCamera = camPos.distanceTo(position3D);\n positionUpdatedCallback(htmlElement, position2D, position3D, distanceToCamera, userData);\n }\n });\n this.clusterElements();\n this.commitDOMChanges();\n }\n\n /**\n * Update size of new elements. This is only done once as this causes\n * layout to be invalidated which is an expensive operation.\n */\n private updateNewElementSizes() {\n this._htmlOverlays.forEach((element, htmlElement) => {\n if (element.state.width === -1) {\n const clientRect = htmlElement.getBoundingClientRect();\n element.state.width = clientRect.width;\n element.state.height = clientRect.height;\n }\n });\n }\n\n private commitDOMChanges() {\n const canvas = this.viewerRenderer.domElement;\n // Compute once as updating styles below will cause (unnecessary)\n // recomputation which slows down the process\n const offsetLeft = canvas.offsetLeft;\n const offsetTop = canvas.offsetTop;\n\n this._htmlOverlays.forEach((element, htmlElement) => {\n const { state } = element;\n htmlElement.style.left = `${state.position2D.x + offsetLeft}px`;\n htmlElement.style.top = `${state.position2D.y + offsetTop}px`;\n\n if (state.visible && htmlElement.style.visibility !== 'visible') {\n fadeIn(htmlElement);\n } else if (!state.visible && htmlElement.style.visibility !== 'hidden') {\n fadeOut(htmlElement);\n }\n });\n\n this._compositeOverlays.forEach(htmlElement => {\n this.viewerDomElement.appendChild(htmlElement);\n });\n }\n\n private clusterElements() {\n const options = this._options.clusteringOptions;\n if (options === undefined) {\n return;\n }\n\n switch (options.mode) {\n case 'overlapInScreenSpace':\n this.clusterByOverlapInScreenSpace(options.createClusterElementCallback);\n break;\n\n default:\n assertNever(options.mode, `Unsupported clustering mode: '${options.mode}`);\n }\n }\n\n private cleanupClusterElements(): void {\n this._compositeOverlays.forEach(element => {\n this.viewerDomElement.removeChild(element);\n });\n this._compositeOverlays.splice(0);\n }\n\n private clusterByOverlapInScreenSpace(createClusterElementCallback: HtmlOverlayCreateClusterDelegate) {\n type Element = HtmlOverlayElement & { htmlElement: HTMLElement };\n\n const canvas = this.viewerRenderer.domElement;\n const canvasBounds = domRectToBox2(canvas.getBoundingClientRect());\n const canvasSize = canvasBounds.getSize(new THREE.Vector2());\n canvasBounds.set(new THREE.Vector2(0, 0), canvasSize);\n // Compute once as updating styles below will cause (unnecessary)\n // recomputation which slows down the process\n\n const grid = new BucketGrid2D<Element>(canvasBounds, [10, 10]);\n for (const [htmlElement, element] of this._htmlOverlays.entries()) {\n const { state } = element;\n const elementBounds = createElementBounds(element);\n if (!state.visible || !elementBounds.intersectsBox(canvasBounds)) {\n continue;\n }\n grid.insert(elementBounds, { htmlElement, ...element });\n }\n\n const elementBounds = new THREE.Box2();\n const clusterMidpoint = new THREE.Vector2();\n for (const element of this._htmlOverlays.values()) {\n const { state } = element;\n createElementBounds(element, elementBounds);\n if (!state.visible || !elementBounds.intersectsBox(canvasBounds)) {\n continue;\n }\n\n const cluster = Array.from(grid.removeOverlappingElements(elementBounds));\n if (cluster.length > 1) {\n const midpoint = cluster\n .reduce((position, element) => position.add(element.state.position2D), clusterMidpoint.set(0, 0))\n .divideScalar(cluster.length);\n const compositeElement = createClusterElementCallback(\n cluster.map(element => ({ htmlElement: element.htmlElement, userData: element.options.userData }))\n );\n // Hide all elements in cluster\n cluster.forEach(element => (element.state.visible = false));\n // ... and replace with a composite\n this.addComposite(compositeElement, midpoint);\n }\n }\n }\n\n private addComposite(htmlElement: HTMLElement, position: THREE.Vector2) {\n const canvas = this.viewerRenderer.domElement;\n htmlElement.style.visibility = 'visible';\n htmlElement.style.left = `${position.x + canvas.offsetLeft}px`;\n htmlElement.style.top = `${position.y + canvas.offsetTop}px`;\n this._compositeOverlays.push(htmlElement);\n }\n\n private onSceneRendered(): void {\n this.forceUpdate();\n }\n\n private onViewerDisposed(): void {\n this.dispose();\n }\n}\n\n/**\n * Hides an element and applies a CSS transition.\n */\nfunction fadeOut(htmlElement: HTMLElement) {\n // https://stackoverflow.com/a/4861306\n htmlElement.style.visibility = 'hidden';\n htmlElement.style.opacity = '0';\n htmlElement.style.transition = 'visibility 0s 0.2s, opacity 0.2s linear';\n}\n\n/**\n * Shows an element and applies a CSS transition.\n */\nfunction fadeIn(htmlElement: HTMLElement) {\n // https://stackoverflow.com/a/4861306\n htmlElement.style.visibility = 'visible';\n htmlElement.style.opacity = '1';\n htmlElement.style.transition = 'opacity 0.2s linear';\n}\n\nfunction domRectToBox2(rect: DOMRect, out?: THREE.Box2): THREE.Box2 {\n out = out ?? new THREE.Box2();\n out.min.set(rect.left, rect.top);\n out.max.set(rect.right, rect.bottom);\n return out;\n}\n\nfunction createElementBounds(element: HtmlOverlayElement, out?: THREE.Box2) {\n const { state } = element;\n out = out ?? new THREE.Box2();\n out.min.set(state.position2D.x, state.position2D.y);\n out.max.set(state.position2D.x + state.width, state.position2D.y + state.height);\n return out;\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\nimport { Cognite3DModel } from '@reveal/core';\nimport { Cognite3DViewerToolBase } from './Cognite3DViewerToolBase';\nimport { MetricsLogger } from '@reveal/metrics';\n\nexport class ExplodedViewTool extends Cognite3DViewerToolBase {\n private readonly _cadModel: Cognite3DModel;\n private _treeBoundingBoxdata!: Promise<{ treeIndex: number; direction: THREE.Vector3; transform: THREE.Matrix4 }[]>;\n private readonly _rootTreeIndex: number;\n\n public get readyPromise(): Promise<void> {\n return this._treeBoundingBoxdata.then();\n }\n\n constructor(treeIndex: number, cadModel: Cognite3DModel) {\n super();\n\n this._cadModel = cadModel;\n this._rootTreeIndex = treeIndex;\n\n this.preloadBoundingBoxData(cadModel, treeIndex);\n\n MetricsLogger.trackCreateTool('ExplodedViewTool');\n }\n\n public async expand(expandRadius: number): Promise<void> {\n const expandData = await this._treeBoundingBoxdata;\n\n await Promise.all(\n expandData.map(({ treeIndex, direction, transform }) => {\n if (expandRadius === 0) {\n this._cadModel.resetNodeTransformByTreeIndex(treeIndex);\n return Promise.resolve(0);\n }\n\n transform.setPosition(direction.x * expandRadius, direction.y * expandRadius, direction.z * expandRadius);\n\n return this._cadModel.setNodeTransformByTreeIndex(treeIndex, transform);\n })\n );\n }\n\n public reset(): void {\n this._cadModel.resetNodeTransformByTreeIndex(this._rootTreeIndex, true);\n }\n\n private preloadBoundingBoxData(cadModel: Cognite3DModel, treeIndex: number) {\n const rootTreeIndexBoundingBox = cadModel\n .getBoundingBoxByTreeIndex(treeIndex)\n .then(rootBoundingBox => rootBoundingBox.getCenter(new THREE.Vector3()));\n\n const subTreeBoundingBoxes = cadModel\n .getSubtreeTreeIndices(treeIndex)\n .then(subTreeIndices => {\n if (subTreeIndices.count > 1000) {\n throw new Error(`Subtree size of ${subTreeIndices.count} is too large (max size = 1000)`);\n }\n\n return subTreeIndices;\n })\n .then(subTreeIndices => {\n return Promise.all(\n subTreeIndices.toArray().map(async subTreeIndex => {\n // TODO 2021-06-09 larsmoa: We could make this a lot more efficient by\n // batching bounding box lookups together to one/a few API calls rather than\n // one per node\n const subTreeBox = await cadModel.getBoundingBoxByTreeIndex(subTreeIndex);\n return {\n subTreeIndex: subTreeIndex,\n subTreeIndexBoundingBoxCenter: subTreeBox.getCenter(new THREE.Vector3())\n };\n })\n );\n });\n\n this._treeBoundingBoxdata = Promise.all([rootTreeIndexBoundingBox, subTreeBoundingBoxes])\n .then(data => {\n const [rootCenter, subTreeCenters] = data;\n return subTreeCenters.map(({ subTreeIndex, subTreeIndexBoundingBoxCenter }) => {\n return {\n treeIndex: subTreeIndex,\n direction: new THREE.Vector3().subVectors(subTreeIndexBoundingBoxCenter, rootCenter),\n transform: new THREE.Matrix4()\n };\n });\n })\n .then(async payloads => {\n await Promise.all(\n payloads.map(payload => {\n return cadModel.setNodeTransformByTreeIndex(payload.treeIndex, payload.transform);\n })\n );\n return payloads;\n });\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport { Cognite3DViewer } from '@reveal/core';\nimport { DisposedDelegate } from './types';\n\nimport { Cognite3DViewerToolBase } from './Cognite3DViewerToolBase';\n\nexport class DebugCameraTool extends Cognite3DViewerToolBase {\n private readonly _viewer: Cognite3DViewer;\n private readonly _onViewerDisposedHandler: DisposedDelegate;\n private _cameraHelper?: THREE.CameraHelper;\n\n private get viewerCamera(): THREE.PerspectiveCamera {\n return this._viewer.getCamera();\n }\n\n constructor(viewer: Cognite3DViewer) {\n super();\n\n this._onViewerDisposedHandler = this.onViewerDisposed.bind(this);\n this._viewer = viewer;\n this._viewer.on('disposed', this._onViewerDisposedHandler);\n }\n\n /**\n * Removes all elements and detaches from the viewer.\n * @override\n */\n dispose(): void {\n this._viewer.off('disposed', this._onViewerDisposedHandler);\n super.dispose();\n }\n\n showCameraHelper() {\n this.hideCameraHelper();\n this._cameraHelper = new THREE.CameraHelper(this.viewerCamera.clone() as THREE.PerspectiveCamera);\n this._viewer.addObject3D(this._cameraHelper);\n }\n\n hideCameraHelper() {\n if (this._cameraHelper !== undefined) {\n this._viewer.removeObject3D(this._cameraHelper);\n this._cameraHelper = undefined;\n }\n }\n\n private onViewerDisposed(): void {\n this.dispose();\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\n\n/**\n * Configuration of {@link AxisViewTool}.\n */\nexport type AxisBoxConfig = {\n /**\n * Size in pixels of the axis tool.\n */\n size?: number;\n /**\n * Position, either absolute or relative.\n */\n position?: AbsolutePosition | RelativePosition;\n /**\n * How long the camera animation lasts when\n * clicking a face of the orientation box.\n */\n animationSpeed?: number;\n /**\n * Configuration for each of the faces of the orientation box.\n * Note that Reveal uses a right-handed Y up coordinate system,\n * which might differ from the original model space. To account\n * for this, you might want to reassign labels of the faces.\n */\n faces?: {\n xPositiveFace?: AxisBoxFaceConfig;\n xNegativeFace?: AxisBoxFaceConfig;\n yPositiveFace?: AxisBoxFaceConfig;\n yNegativeFace?: AxisBoxFaceConfig;\n zPositiveFace?: AxisBoxFaceConfig;\n zNegativeFace?: AxisBoxFaceConfig;\n };\n /**\n * Configuration of the compass \"base\" of the tool.\n */\n compass?: AxisBoxCompassConfig;\n};\n\n/**\n * Absolute position in pixels.\n */\nexport type AbsolutePosition = {\n xAbsolute: number;\n yAbsolute: number;\n};\n\n/**\n * Relative position from a corner of the viewer\n * and a given padding.\n */\nexport type RelativePosition = {\n corner: Corner;\n padding: THREE.Vector2;\n};\n\n/**\n * Configuration of each face of the orientation box.\n */\nexport type AxisBoxFaceConfig = {\n /**\n * Label of the respective face, e.g. 'X' or 'Right'.\n */\n label?: string;\n fontSize?: number;\n fontColor?: THREE.Color;\n outlineSize?: number;\n outlineColor?: THREE.Color;\n faceColor?: THREE.Color;\n};\n\n/**\n * Configuration of the compass.\n */\nexport type AxisBoxCompassConfig = {\n /**\n * Label of the orientation indicator. Defaults\n * to 'N' for north.\n */\n ringLabel?: string;\n /**\n * Offset in radians of the orientation indicator.\n */\n labelDelta?: number;\n fontSize?: number;\n fontColor?: THREE.Color;\n tickColor?: THREE.Color;\n};\n\n/**\n * A corner of the viewer.\n */\nexport enum Corner {\n TopRight,\n TopLeft,\n BottomLeft,\n BottomRight\n}\n\nexport const defaultAxisBoxCompassConfig: AxisBoxCompassConfig = {\n ringLabel: 'N',\n labelDelta: Math.PI,\n fontSize: undefined,\n fontColor: new THREE.Color(0xff0000),\n tickColor: new THREE.Color(0x949494)\n};\n\nexport const defaultFaceConfig: AxisBoxFaceConfig = {\n label: '',\n fontSize: undefined,\n fontColor: new THREE.Color(0x333333),\n outlineSize: undefined,\n outlineColor: new THREE.Color(0x333333),\n faceColor: new THREE.Color(0x949494)\n};\n\nexport const defaultAxisBoxConfig: Required<AxisBoxConfig> = {\n size: 128,\n position: {\n corner: Corner.BottomRight,\n padding: new THREE.Vector2()\n },\n animationSpeed: 200,\n faces: {\n xPositiveFace: {\n ...defaultFaceConfig,\n label: 'Right'\n },\n xNegativeFace: {\n ...defaultFaceConfig,\n label: 'Left'\n },\n yPositiveFace: {\n ...defaultFaceConfig,\n label: 'Up'\n },\n yNegativeFace: {\n ...defaultFaceConfig,\n label: 'Down'\n },\n zPositiveFace: {\n ...defaultFaceConfig,\n label: 'Front'\n },\n zNegativeFace: {\n ...defaultFaceConfig,\n label: 'Back'\n }\n },\n compass: defaultAxisBoxCompassConfig\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport * as THREE from 'three';\nimport cloneDeep from 'lodash/cloneDeep';\nimport merge from 'lodash/merge';\nimport TWEEN from '@tweenjs/tween.js';\n\nimport { Cognite3DViewerToolBase } from '../Cognite3DViewerToolBase';\nimport {\n AxisBoxConfig,\n defaultAxisBoxConfig,\n AxisBoxFaceConfig,\n Corner,\n AbsolutePosition,\n RelativePosition\n} from './types';\nimport ComboControls from '@reveal/camera-manager';\nimport { Cognite3DViewer } from '@reveal/core';\nimport { MetricsLogger } from '@reveal/metrics';\n\nexport class AxisViewTool extends Cognite3DViewerToolBase {\n private readonly _layoutConfig: Required<AxisBoxConfig>;\n\n private readonly _boxFaceGeometry: THREE.PlaneGeometry;\n\n private readonly _viewer: Cognite3DViewer;\n\n private readonly _axisGroup: THREE.Group;\n\n private readonly _interactiveObjects: THREE.Mesh[];\n private readonly _raycastCamera: THREE.OrthographicCamera;\n private readonly _raycaster: THREE.Raycaster;\n\n private readonly _screenPosition: THREE.Vector2;\n\n private readonly _disposeClickDiv: () => void;\n\n private _dynamicUpdatePosition = () => {};\n private readonly _updateClickDiv = () => {};\n\n constructor(viewer: Cognite3DViewer, config?: AxisBoxConfig) {\n super();\n\n this._screenPosition = new THREE.Vector2();\n this._boxFaceGeometry = new THREE.PlaneGeometry(0.85, 0.85, 1, 1);\n\n this._raycastCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, -1, 1);\n this._raycaster = new THREE.Raycaster();\n\n this._viewer = viewer;\n\n this._layoutConfig = merge(cloneDeep(defaultAxisBoxConfig), config);\n\n this._axisGroup = new THREE.Group();\n this._interactiveObjects = this.createAxisCross(this._axisGroup);\n\n [this._updateClickDiv, this._disposeClickDiv] = this.createClickDiv(viewer);\n this.addAxisBoxToViewer(this._axisGroup, this._layoutConfig.position!);\n\n MetricsLogger.trackCreateTool('AxisViewTool');\n }\n\n public dispose(): void {\n super.dispose();\n this._viewer.removeUiObject(this._axisGroup);\n this._disposeClickDiv();\n }\n\n private createClickDiv(viewer: Cognite3DViewer) {\n const canvasElement = viewer.domElement.querySelector('canvas');\n if (canvasElement === null) {\n throw new Error('Could not find canvas');\n }\n const divElement = document.createElement('div');\n divElement.style.position = 'absolute';\n divElement.style.height = `${this._layoutConfig.size}px`;\n divElement.style.width = `${this._layoutConfig.size}px`;\n divElement.style.zIndex = '1';\n\n let xMouse = 0;\n let yMouse = 0;\n\n divElement.addEventListener('mousedown', event => {\n const mouseDownEvent = new MouseEvent('mousedown', {\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button\n });\n xMouse = event.clientX;\n yMouse = event.clientY;\n viewer.renderer.domElement.dispatchEvent(mouseDownEvent);\n });\n\n divElement.addEventListener('mousemove', event => {\n const mouseMoveEvent = new MouseEvent('mousemove', {\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button\n });\n viewer.renderer.domElement.dispatchEvent(mouseMoveEvent);\n });\n\n divElement.addEventListener('contextmenu', event => event.preventDefault());\n\n divElement.addEventListener('mouseup', event => {\n const mouseUpEvent = new MouseEvent('mouseup', {\n clientX: event.clientX,\n clientY: event.clientY,\n button: event.button\n });\n\n const rect = viewer.domElement.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n if (Math.abs(xMouse - event.clientX) + Math.abs(yMouse - event.clientY) <= 10 && !this.handleClick(x, y, rect)) {\n viewer.renderer.domElement.dispatchEvent(mouseUpEvent);\n }\n });\n\n viewer.domElement.appendChild(divElement);\n\n return [\n () => {\n divElement.style.left = `${this._screenPosition.x}px`;\n divElement.style.bottom = `${this._screenPosition.y}px`;\n },\n () => {\n viewer.domElement.removeChild(divElement);\n }\n ];\n }\n\n private addAxisBoxToViewer(axisGroup: THREE.Group, position: AbsolutePosition | RelativePosition) {\n const size = this._layoutConfig.size;\n\n if (isAbsolute(position)) {\n this._screenPosition.x = position.xAbsolute;\n this._screenPosition.y = position.yAbsolute;\n } else {\n switch (position.corner) {\n case Corner.BottomRight:\n this._screenPosition.y = position.padding.y;\n\n this._dynamicUpdatePosition = () => {\n this._screenPosition.x = this._viewer.renderer.domElement.clientWidth - position.padding.x - size;\n };\n break;\n\n case Corner.TopRight:\n this._dynamicUpdatePosition = () => {\n this._screenPosition.x = this._viewer.renderer.domElement.clientWidth - position.padding.x - size;\n this._screenPosition.y = this._viewer.renderer.domElement.clientHeight - position.padding.y - size;\n };\n break;\n\n case Corner.TopLeft:\n this._screenPosition.x = position.padding.x;\n this._dynamicUpdatePosition = () => {\n this._screenPosition.y = this._viewer.renderer.domElement.clientHeight - position.padding.y - size;\n };\n break;\n\n case Corner.BottomLeft:\n this._screenPosition.x = position.padding.x;\n this._screenPosition.y = position.padding.y;\n break;\n default:\n throw new Error(`Unknown corner position for Axis Cross: Corner = ${position.corner}`);\n }\n this._dynamicUpdatePosition();\n }\n\n this._viewer.addUiObject(axisGroup, this._screenPosition, new THREE.Vector2(size, size));\n\n function isAbsolute(position: AbsolutePosition | RelativePosition): position is AbsolutePosition {\n return (\n (position as AbsolutePosition).xAbsolute !== undefined && (position as AbsolutePosition).yAbsolute !== undefined\n );\n }\n }\n\n private handleClick(xScreenPos: number, yScreenPos: number, boundingRect: DOMRect): boolean {\n const xNdc = (2 * (xScreenPos - this._screenPosition.x)) / this._layoutConfig.size - 1;\n const yNdc = (2 * (boundingRect.height - yScreenPos - this._screenPosition.y)) / this._layoutConfig.size - 1;\n this._raycaster.setFromCamera({ x: xNdc, y: yNdc }, this._raycastCamera);\n const rayOrigin = new THREE.Vector3(xNdc, yNdc, 1);\n const rayDirection = new THREE.Vector3(0, 0, -1).normalize();\n this._raycaster.set(rayOrigin, rayDirection);\n\n const intersects = this._raycaster.intersectObjects(this._interactiveObjects);\n\n if (!(intersects.length > 0)) return false;\n\n const targetPosition = intersects[0].object.position.clone().normalize();\n const targetUp = (intersects[0].object.userData.upVector as THREE.Vector3).clone();\n\n this.moveCameraTo(this._viewer.getCamera(), this._viewer.cameraControls, targetPosition, targetUp);\n\n return true;\n }\n\n private createAxisCross(axisGroup: THREE.Group) {\n const interactiveObjects = this.createBoxFaces();\n axisGroup.add(...interactiveObjects);\n\n const compass = this.createCompass();\n axisGroup.add(compass);\n\n this.setupTransformOnRender(axisGroup);\n\n return interactiveObjects;\n }\n\n private setupTransformOnRender(axisGroup: THREE.Group) {\n axisGroup.children[0].onBeforeRender = () => {\n this._dynamicUpdatePosition();\n axisGroup.quaternion.copy(this._viewer.getCamera().quaternion).invert();\n axisGroup.updateMatrixWorld();\n this._updateClickDiv();\n };\n }\n\n private createBoxFaces() {\n const facesConfig = this._layoutConfig.faces;\n\n const posXFace = this.createBoxFace(new THREE.Vector3(1, 0, 0), facesConfig.xPositiveFace!);\n const negXFace = this.createBoxFace(new THREE.Vector3(-1, 0, 0), facesConfig.xNegativeFace!);\n\n const posYFace = this.createBoxFace(\n new THREE.Vector3(0, 1, 0),\n facesConfig.yPositiveFace!,\n new THREE.Vector3(0, 0, -1)\n );\n const negYFace = this.createBoxFace(\n new THREE.Vector3(0, -1, 0),\n facesConfig.yNegativeFace!,\n new THREE.Vector3(0, 0, 1)\n );\n\n const posZFace = this.createBoxFace(new THREE.Vector3(0, 0, 1), facesConfig.zPositiveFace!);\n const negZFace = this.createBoxFace(new THREE.Vector3(0, 0, -1), facesConfig.zNegativeFace!);\n\n return [posXFace, negXFace, posYFace, negYFace, posZFace, negZFace];\n }\n\n private createCompass() {\n const compassPlaneGeometry = new THREE.PlaneGeometry(2.1, 2.1, 1, 1);\n const compass = new THREE.Mesh(\n compassPlaneGeometry,\n new THREE.MeshBasicMaterial({\n map: this.createCompassTexture(),\n side: THREE.DoubleSide,\n transparent: true\n })\n );\n\n const x = Math.sin(this._layoutConfig.compass.labelDelta!);\n const z = Math.cos(this._layoutConfig.compass.labelDelta!);\n\n compass.position.y = -0.5;\n compass.up.copy(new THREE.Vector3(x, 0, z));\n compass.lookAt(0, 0, 0);\n\n return compass;\n }\n\n private createCompassTexture() {\n const compassLayout = this._layoutConfig.compass;\n const textureSize = this._layoutConfig.size;\n\n const canvas = document.createElement('canvas');\n canvas.width = textureSize;\n canvas.height = textureSize;\n const context = canvas.getContext('2d')!;\n\n const halfSize = textureSize / 2;\n const radius = halfSize - halfSize / 4;\n\n const tickWidth = textureSize / 32;\n const tickSpace = textureSize / 8;\n\n context.strokeStyle = compassLayout.tickColor!.getStyle();\n context.lineWidth = textureSize / 16;\n context.setLineDash([tickWidth, tickSpace]);\n context.beginPath();\n context.arc(halfSize, halfSize, radius, 0, 2 * Math.PI);\n context.stroke();\n\n if (compassLayout.ringLabel && compassLayout.ringLabel.length > 0) {\n const fontSize = compassLayout.fontSize ?? textureSize / 5;\n context.font = `bold ${fontSize}px Arial`;\n context.textAlign = 'center';\n context.fillStyle = compassLayout.fontColor!.getStyle();\n context.fillText(compassLayout.ringLabel, halfSize, halfSize * (1 / 4) + fontSize / 3);\n }\n\n return new THREE.CanvasTexture(canvas);\n }\n\n private getFaceTexture(faceConfig: AxisBoxFaceConfig, size: number) {\n const textureSize = size / 2;\n\n const canvas = document.createElement('canvas');\n canvas.width = textureSize;\n canvas.height = textureSize;\n\n const context = canvas.getContext('2d')!;\n context.fillStyle = faceConfig.outlineColor!.getStyle();\n context.fillRect(0, 0, textureSize, textureSize);\n context.fillStyle = faceConfig.faceColor!.getStyle();\n\n const outlineSize = faceConfig.outlineSize ?? textureSize / 32;\n context.fillRect(outlineSize, outlineSize, textureSize - outlineSize * 2, textureSize - outlineSize * 2);\n context.fill();\n\n if (faceConfig.label !== '') {\n const fontSize = faceConfig.fontSize ?? textureSize / 3;\n context.font = `bold ${fontSize}px Arial`;\n context.textAlign = 'center';\n context.fillStyle = faceConfig.fontColor!.getStyle();\n context.fillText(faceConfig.label!, textureSize / 2, textureSize / 2 + fontSize / 3);\n }\n\n return new THREE.CanvasTexture(canvas);\n }\n\n private createBoxFace(position: THREE.Vector3, faceConfig: AxisBoxFaceConfig, upVector = new THREE.Vector3(0, 1, 0)) {\n const face = new THREE.Mesh(\n this._boxFaceGeometry,\n new THREE.MeshBasicMaterial({ map: this.getFaceTexture(faceConfig, this._layoutConfig.size) })\n );\n\n face.position.copy(position.multiplyScalar(0.5 * this._boxFaceGeometry.parameters.width));\n face.lookAt(position.multiplyScalar(2));\n\n face.userData.upVector = upVector;\n\n return face;\n }\n\n private moveCameraTo(\n camera: THREE.PerspectiveCamera,\n cameraControls: ComboControls,\n targetAxis: THREE.Vector3,\n targetUpAxis: THREE.Vector3\n ) {\n const currentCameraPosition = camera.position.clone();\n const cameraTarget = cameraControls.getState().target;\n\n const targetRelativeStartPosition = currentCameraPosition.clone().sub(cameraTarget);\n const radius = targetRelativeStartPosition.length();\n\n const normalizedFrom = targetRelativeStartPosition.clone().normalize();\n\n const omega = Math.acos(normalizedFrom.dot(targetAxis));\n\n const from = { t: 0 };\n const to = { t: 1 };\n\n const animation = new TWEEN.Tween(from);\n\n const forward = targetAxis.clone();\n\n const fromRotation = camera.quaternion.clone();\n const toRotation = new THREE.Quaternion().setFromRotationMatrix(\n new THREE.Matrix4().makeBasis(targetUpAxis.clone().cross(forward), targetUpAxis, forward)\n );\n\n const epsilon = 1e-6;\n\n if (fromRotation.angleTo(toRotation) < epsilon) {\n return;\n }\n\n const tmpPosition = new THREE.Vector3();\n const tmpRotation = new THREE.Quaternion();\n let cachedCameraControlsEnabled: boolean;\n const tween = animation\n .to(to, this._layoutConfig.animationSpeed)\n .onUpdate(() => {\n tmpPosition\n .copy(normalizedFrom)\n .multiplyScalar(Math.sin((1 - from.t) * omega) / Math.sin(omega))\n .add(targetAxis.clone().multiplyScalar(Math.sin(from.t * omega) / Math.sin(omega)));\n\n tmpPosition.multiplyScalar(radius);\n tmpPosition.add(cameraTarget);\n\n tmpRotation.slerpQuaternions(fromRotation, toRotation, from.t);\n\n camera.position.copy(tmpPosition);\n camera.setRotationFromQuaternion(tmpRotation);\n })\n .start(TWEEN.now())\n .onStart(() => {\n cachedCameraControlsEnabled = cameraControls.enabled;\n cameraControls.enabled = false;\n })\n .onComplete(() => {\n cameraControls.setState(camera.position, cameraTarget);\n cameraControls.enabled = cachedCameraControlsEnabled;\n });\n tween.update(TWEEN.now());\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\n/**\n * Supported map Providers Bing, Here & Mapbox\n */\nexport enum MapProviders {\n BingMap = 'BingMap',\n HereMap = 'HereMap',\n MapboxMap = 'MapboxMap',\n OpenStreetMap = 'OpenStreetMap'\n}\n\n/**\n * Map data for Mapbox\n */\nexport enum MapboxMode {\n /**\n * Access the map data using a map style. For details see https://docs.mapbox.com/api/maps/styles/\n */\n Style = 100,\n /**\n * Access the map data using a map id or Tileset id. For details see https://docs.mapbox.com/help/glossary/tileset-id/\n */\n Map_Id = 101\n}\n\n/**\n * Mapbox Map Style, these are pre-defined styles using map/tileset id, created in Mapbox Studio style editor.\n * This is used when MapboxMode.Style is used for mode.\n */\nexport enum MapboxStyle {\n Streets = 'mapbox/streets-v10',\n Outdoor = 'mapbox/outdoors-v10',\n Light = 'mapbox/light-v9',\n Dark = 'mapbox/dark-v9',\n Satellite = 'mapbox/satellite-v9',\n Satellite_Streets = 'mapbox/satellite-streets-v10',\n Navigation_Day = 'mapbox/navigation-preview-day-v4',\n Navigation_Night = 'mapbox/navigation-preview-night-v4',\n Navigation_Guide_Day = 'mapbox/navigation-guidance-day-v4',\n Navigation_Guide_Night = 'mapbox/navigation-guidance-night-v4'\n}\n\n/**\n * A map/tileset ID is a unique identifier given to every tileset, used when MapboxMode.Map_Id is choosen for mode.\n */\nexport enum MapboxId {\n Streets = 'mapbox.mapbox-streets-v7',\n Satellite = 'mapbox.satellite',\n Terrain = 'mapbox.mapbox-terrain-v2',\n Traffic = 'mapbox.mapbox-traffic-v1',\n TerrainRGB = 'mapbox.terrain-rgb'\n}\n\n/**\n * Mapbox Map image tile format\n */\nexport enum MapboxImageFormat {\n PNG = 'png',\n PNG32 = 'png32',\n PNG64 = 'png64',\n PNG128 = 'png128',\n PNG256 = 'png256',\n JPG70 = 'jpg70',\n JPG80 = 'jpg80',\n JPG90 = 'jpg90',\n PNGRAW = 'pngraw'\n}\n\n/**\n * Bing Map View (aerial, road, bird's eye view of the map)\n */\nexport enum BingMapType {\n Aerial = 'a',\n Road = 'r',\n Aerial_Labels = 'h',\n Oblique = 'o',\n Oblique_Labels = 'b'\n}\n\n/**\n * Bing Map Tile Image formats\n */\nexport enum BingMapImageFormat {\n GIF = 'gif',\n JPEG = 'jpeg',\n PNG = 'png'\n}\n\n/**\n * Here Map types\n */\nexport enum HereMapType {\n Aerial = 'aerial',\n Base = 'base',\n Pano = 'pano',\n Traffic = 'traffic'\n}\n\n/**\n * Here Map View Scheme like day, night, satellite, terrain\n */\nexport enum HereMapScheme {\n Day = 'normal.day',\n Night = 'normal.night',\n Terrain = 'terrain.day',\n Satellite = 'satellite.day'\n}\n\n/**\n * Here Map Tiles Image Format\n */\nexport enum HereMapImageFormat {\n PNG = 'png',\n PNG8 = 'png8',\n JPG = 'jpg'\n}\n\nexport type BingMapConfig = {\n provider: MapProviders.BingMap;\n /**\n * Bing Map API Key\n */\n APIKey: string;\n /**\n * The type of the map used.\n */\n type?: BingMapType;\n};\n\nexport type HereMapConfig = {\n provider: MapProviders.HereMap;\n /**\n * Here map API Key\n */\n APIKey: string;\n /**\n * Service application code token.\n */\n appCode?: string;\n /**\n * The type of maps to be used.\n */\n style?: HereMapType;\n /**\n * Specifies the view scheme\n */\n scheme?: string;\n /**\n * Map image tile format\n */\n imageFormat?: HereMapImageFormat;\n /**\n Returned tile map image size.\n The following sizes are supported:\n - 256\n - 512\n - 128 (deprecated, although usage is still accepted)\n */\n size?: number;\n};\n\nexport type OpenStreetMapConfig = {\n provider: MapProviders.OpenStreetMap;\n};\n\nexport type MapboxConfig = {\n provider: MapProviders.MapboxMap;\n /**\n * Mapbox API Key\n */\n APIKey: string;\n /**\n * Map style or map ID if the mode is set to MAP_ID\n */\n id: string;\n /**\n Map tile access mode\n - MapboxMode.STYLE\n - MapboxMode.MAP_ID\n */\n mode?: MapboxMode;\n /**\n * Map image tile format\n */\n tileFormat?: MapboxImageFormat;\n /**\n * Flag to indicate if should use high resolution tiles\n */\n useHDPI?: boolean;\n};\n\n/**\n * Maps Configuration of {@link GeomapTool}.\n */\nexport type MapConfig = {\n /**\n * Latitude, Longitude position\n */\n latlong: LatLongPosition;\n} & (BingMapConfig | HereMapConfig | MapboxConfig | OpenStreetMapConfig);\n\n/**\n * Latitude, Longitude position.\n */\nexport type LatLongPosition = {\n latitude: number;\n longitude: number;\n};\n","/*!\n * Copyright 2021 Cognite AS\n */\n// To overcome \"implicitly has an 'any' type\" and \"unused variable reference\" error in the geo-three library\n// @ts-ignore\nimport * as GEOTHREE from 'geo-three';\nimport { Cognite3DViewer } from '@reveal/core';\nimport { LatLongPosition, MapConfig, MapProviders } from './MapConfig';\n\nexport class Geomap {\n private readonly _viewer: Cognite3DViewer;\n private readonly _map: GEOTHREE.MapView;\n private _intervalId: any = 0;\n private readonly _onCameraChange = this.handleCameraChange.bind(this);\n\n constructor(viewer: Cognite3DViewer, mapConfig: MapConfig) {\n this._viewer = viewer;\n const mapProvider = this.getMapProvider(mapConfig);\n this._map = new GEOTHREE.MapView(GEOTHREE.MapView.PLANAR, mapProvider, mapProvider);\n this._viewer.addObject3D(this._map);\n\n const coords = GEOTHREE.UnitsUtils.datumsToSpherical(mapConfig.latlong.latitude, mapConfig.latlong.longitude);\n const bound = this._viewer.models[0].getModelBoundingBox();\n this._map.position.set(-coords.x, bound.min.y, coords.y);\n this._map.updateMatrixWorld(true);\n this.requestRedraw(10000);\n this._viewer.on('cameraChange', this._onCameraChange);\n }\n\n private requestRedraw(timeOut: number) {\n if (this._intervalId == 0) {\n this._intervalId = setInterval(() => {\n this._viewer.requestRedraw();\n }, 100);\n\n setTimeout(() => {\n clearInterval(this._intervalId);\n this._intervalId = 0;\n }, timeOut);\n }\n }\n\n private getMapProvider(mapConfig: MapConfig) {\n let mapProvider: GEOTHREE.MapProvider;\n switch (mapConfig.provider) {\n case MapProviders.BingMap:\n mapProvider = new GEOTHREE.BingMapsProvider(mapConfig.APIKey, mapConfig.type);\n break;\n case MapProviders.HereMap:\n mapProvider = new GEOTHREE.HereMapsProvider(\n mapConfig.APIKey,\n mapConfig.appCode,\n mapConfig.style,\n mapConfig.scheme,\n mapConfig.imageFormat,\n mapConfig.size\n );\n break;\n case MapProviders.MapboxMap:\n mapProvider = new GEOTHREE.MapBoxProvider(mapConfig.APIKey, mapConfig.id, mapConfig.mode, mapConfig.tileFormat);\n break;\n case MapProviders.OpenStreetMap:\n mapProvider = new GEOTHREE.OpenStreetMapsProvider();\n break;\n\n default:\n throw new Error('Unsupported map provider');\n }\n\n return mapProvider;\n }\n\n public latLongToWorldCoordinates(latLong: LatLongPosition) {\n return GEOTHREE.UnitsUtils.datumsToSpherical(latLong.latitude, latLong.longitude);\n }\n\n private handleCameraChange() {\n this.requestRedraw(1000);\n }\n\n public dispose(): void {\n this._viewer.removeObject3D(this._map);\n this._viewer.off('cameraChange', this._onCameraChange);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { Cognite3DViewerToolBase } from '../Cognite3DViewerToolBase';\nimport { LatLongPosition, MapConfig } from './MapConfig';\nimport { Geomap } from './Geomap';\n\nimport { Cognite3DViewer } from '@reveal/core';\nimport { MetricsLogger } from '@reveal/metrics';\n\n/**\n * The `GeomapTool` is a geolocation for the models and allow the user to place them on the maps.\n * @version New since 2.1.\n */\nexport class GeomapTool extends Cognite3DViewerToolBase {\n private readonly _viewer: Cognite3DViewer;\n private readonly _maps: Geomap;\n\n constructor(viewer: Cognite3DViewer, config: MapConfig) {\n super();\n\n this._viewer = viewer;\n this._maps = new Geomap(this._viewer, config);\n\n MetricsLogger.trackCreateTool('AxisViewTool');\n }\n\n /**\n * Converts Latitude & Longitude into Vector2 World coordinates on the Map\n * @param latLong Latitude & Longitude\n */\n public latLongToWorldCoordinates(latLong: LatLongPosition) {\n this._maps.latLongToWorldCoordinates(latLong);\n }\n\n public dispose(): void {\n super.dispose();\n this._maps.dispose();\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport { NodeCollectionBase, NodeAppearance } from '@reveal/core/src';\nimport { Cognite3DModel } from '@reveal/core';\nimport { MetricsLogger } from '@reveal/metrics';\n\n/**\n * Timeline Key Frames contains parameters to access Nodes, Styles for the Timeline\n */\nexport class Keyframe {\n private readonly _date: Date;\n private readonly _model: Cognite3DModel;\n private readonly _nodeCollectionAndAppearance: { nodes: NodeCollectionBase; nodeAppearance: NodeAppearance }[] = [];\n\n constructor(model: Cognite3DModel, date: Date) {\n this._model = model;\n this._date = date;\n }\n\n /**\n * Get date of the Keyframe\n * @returns date\n */\n public getKeyframeDate(): Date {\n return this._date;\n }\n\n /**\n * Assigns the styles for the node set for the model for this Keyframe\n */\n public activate() {\n this._nodeCollectionAndAppearance.forEach((node, _index) => {\n this._model.assignStyledNodeCollection(node.nodes, node.nodeAppearance);\n });\n }\n\n /**\n * Removes the style for the model\n */\n public deactivate() {\n this._nodeCollectionAndAppearance.forEach((node, _index) => {\n this._model.unassignStyledNodeCollection(node.nodes);\n });\n }\n\n /**\n * Add node & style to the collection\n * @param nodeCollection Node set to apply the Styles\n * @param nodeAppearance Style to assign to the node collection\n */\n public assignStyledNodeCollection(nodeCollection: NodeCollectionBase, nodeAppearance: NodeAppearance) {\n MetricsLogger.trackCadModelStyled(nodeCollection.classToken, nodeAppearance);\n\n const index = this._nodeCollectionAndAppearance.findIndex(x => x.nodes === nodeCollection);\n if (index !== -1) {\n throw new Error(\n 'Node collection as already been assigned, use updateStyledNodeCollection() to update the appearance'\n );\n }\n\n this._nodeCollectionAndAppearance.push({ nodes: nodeCollection, nodeAppearance });\n }\n\n /**\n * Remove Node & Style for this keyframe's nodeCollection and nodeAppearance\n * @param nodeCollection Nodes to be unassign from node collection\n */\n public unassignStyledNodeCollection(nodeCollection: NodeCollectionBase) {\n const index = this._nodeCollectionAndAppearance.findIndex(x => x.nodes === nodeCollection);\n if (index === -1) {\n throw new Error('Node collection has not been assigned to model');\n }\n this._nodeCollectionAndAppearance.splice(index, 1);\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\n\nimport TWEEN from '@tweenjs/tween.js';\n\nimport { Cognite3DModel } from '@reveal/core';\nimport { Cognite3DViewerToolBase } from '../Cognite3DViewerToolBase';\nimport { Keyframe } from './Keyframe';\nimport { TimelineDateUpdateDelegate } from './types';\nimport { EventTrigger, assertNever } from '@reveal/core/utilities';\n\n/**\n * Tool to applying styles to nodes based on date to play them over in Timeline\n */\nexport class TimelineTool extends Cognite3DViewerToolBase {\n private readonly _model: Cognite3DModel;\n private readonly _keyframes: Keyframe[];\n private _playback: TWEEN.Tween | undefined = undefined;\n private readonly _events = { dateChanged: new EventTrigger<TimelineDateUpdateDelegate>() };\n\n constructor(cadModel: Cognite3DModel) {\n super();\n\n this._model = cadModel;\n this._keyframes = new Array<Keyframe>();\n }\n\n /**\n * Subscribe to the Date changed event\n * @param event `dateChanged` event\n * @param listener Listen to Timeline date Update during Playback\n */\n public subscribe(event: 'dateChanged', listener: TimelineDateUpdateDelegate): void {\n switch (event) {\n case 'dateChanged':\n this._events.dateChanged.subscribe(listener);\n break;\n default:\n assertNever(event, `Unsupported event: '${event}'`);\n }\n }\n\n /**\n * Unsubscribe to the Date changed event\n * @param event `dateChanged` event\n * @param listener Remove Listen to Timeline date Update\n */\n public unsubscribe(event: 'dateChanged', listener: TimelineDateUpdateDelegate): void {\n switch (event) {\n case 'dateChanged':\n this._events.dateChanged.unsubscribe(listener);\n break;\n default:\n assertNever(event, `Unsupported event: '${event}'`);\n }\n }\n\n /**\n * Create Key frame for the Timeline\n * @param date - date value by Date.now() since January 1, 1970\n */\n public createKeyframe(date: Date): Keyframe {\n const keyframe = new Keyframe(this._model, date);\n this._keyframes.push(keyframe);\n this.sortKeyframesByDates();\n\n return keyframe;\n }\n\n /**\n * Returns the keyframe at the date given, or undefined if not found.\n * @param date\n * @returns\n */\n public getKeyframeByDate(date: Date): Keyframe | undefined {\n return this._keyframes.find(candidate => candidate.getKeyframeDate() === date);\n }\n\n /**\n * Removes the Keyframe from the timeline. Does nothing if the keyframe isn't part of the timeline.\n * @param keyframe - Keyframe to be removed from the timeline\n */\n public removeKeyframe(keyframe: Keyframe) {\n const index = this._keyframes.findIndex(obj => obj === keyframe);\n\n if (index > -1) {\n this._keyframes.splice(index, 1);\n }\n }\n\n /**\n * Removes the Keyframe from the Timeline\n * @param date - Date of the Keyframe to be removed from the Timeline\n */\n public removeKeyframeByDate(date: Date) {\n const index = this._keyframes.findIndex(obj => obj.getKeyframeDate() === date);\n\n if (index > -1) {\n this._keyframes.splice(index, 1);\n }\n }\n\n /**\n * Starts playback of Timeline\n * @param startDate - Keyframe date to start the Playback of Keyframes\n * @param endDate - Keyframe date to stop the Playback of Keyframes\n * @param totalDurationInMilliSeconds - Number of milliseconds for all Keyframe within startDate & endDate to be rendered\n */\n public play(startDate: Date, endDate: Date, totalDurationInMilliSeconds: number) {\n this.stop();\n\n const playState = { dateInMs: startDate.getTime() };\n const to = { dateInMs: endDate.getTime() };\n const tween = new TWEEN.Tween(playState).to(to, totalDurationInMilliSeconds);\n let currentKeyframeIndex = -1;\n tween.onUpdate(() => {\n const date = new Date(playState.dateInMs);\n\n // Forward active keyframe to last keyframe that is before current date\n const prevIndex = currentKeyframeIndex;\n while (\n currentKeyframeIndex < this._keyframes.length - 1 &&\n this._keyframes[currentKeyframeIndex + 1].getKeyframeDate().getTime() <= date.getTime()\n ) {\n currentKeyframeIndex++;\n }\n\n if (currentKeyframeIndex !== prevIndex) {\n if (prevIndex !== -1) {\n this._keyframes[prevIndex].deactivate();\n }\n this._keyframes[currentKeyframeIndex].activate();\n }\n\n this._events.dateChanged.fire({\n date: date,\n activeKeyframe: this._keyframes[currentKeyframeIndex],\n startDate: startDate,\n endDate: endDate\n });\n });\n\n this._playback = tween;\n tween.start();\n }\n\n /**\n * Stops any ongoing playback\n */\n public stop() {\n if (this._playback !== undefined) {\n this._playback.stop();\n this._playback = undefined;\n }\n }\n\n /**\n * Pause any ongoing playback\n */\n public pause() {\n if (this._playback !== undefined && this._playback.isPlaying()) {\n this._playback.pause();\n }\n }\n\n /**\n * Resume any paused playback\n */\n public resume() {\n if (this._playback !== undefined && this._playback.isPaused()) {\n this._playback.resume();\n }\n }\n\n /**\n * Provides all Keyframes in the Timeline\n * @returns All Keyframes in Timeline\n */\n public getAllKeyframes(): Keyframe[] {\n return this._keyframes.slice();\n }\n\n public dispose(): void {\n super.dispose();\n this._events.dateChanged.unsubscribeAll();\n }\n\n /**\n * Sort the Timeline Keyframe by their Date\n */\n private sortKeyframesByDates() {\n if (this._keyframes.length > 1) {\n this._keyframes.sort((a: Keyframe, b: Keyframe) => {\n return a.getKeyframeDate().getTime() - b.getKeyframeDate().getTime();\n });\n }\n }\n}\n","/*!\n * Copyright 2021 Cognite AS\n */\nimport * as THREE from 'three';\n\nimport { Cognite3DViewer, Cognite3DModel } from '@reveal/core';\nimport { LevelOfDetail, SectorNode } from '@reveal/core/cad';\nimport { assertNever } from '@reveal/core/utilities';\n\nimport { Cognite3DViewerToolBase } from './Cognite3DViewerToolBase';\n\nexport type DebugLoadedSectorsToolOptions = {\n showSimpleSectors?: boolean;\n showDetailedSectors?: boolean;\n showDiscardedSectors?: boolean;\n colorBy?: 'depth' | 'lod' | 'loadedTimestamp' | 'random';\n leafsOnly?: boolean;\n sectorPathFilterRegex?: string;\n};\n\nexport class DebugLoadedSectorsTool extends Cognite3DViewerToolBase {\n private readonly _boundingBoxes = new THREE.Group();\n private readonly _viewer: Cognite3DViewer;\n private _options: Required<DebugLoadedSectorsToolOptions>;\n private _model?: Cognite3DModel;\n\n constructor(viewer: Cognite3DViewer, options: DebugLoadedSectorsToolOptions = {}) {\n super();\n this._viewer = viewer;\n this._viewer.addObject3D(this._boundingBoxes);\n this._options = {} as any; // Force - it's set in setOptions\n this.setOptions(options);\n }\n\n setOptions(options: DebugLoadedSectorsToolOptions) {\n this._options = {\n showDetailedSectors: true,\n showDiscardedSectors: false,\n showSimpleSectors: true,\n colorBy: 'lod',\n leafsOnly: false,\n sectorPathFilterRegex: '.*',\n ...options\n };\n }\n\n dispose() {\n this._viewer.removeObject3D(this._boundingBoxes);\n }\n\n showSectorBoundingBoxes(model: Cognite3DModel) {\n this._model = model;\n this.updateBoundingBoxes();\n }\n\n private updateBoundingBoxes() {\n this._boundingBoxes.clear();\n if (this._model === undefined) {\n return;\n }\n this._model.getModelTransformation(this._boundingBoxes.matrix);\n const shouldShowLod: boolean[] = [];\n shouldShowLod[LevelOfDetail.Discarded] = this._options.showDiscardedSectors;\n shouldShowLod[LevelOfDetail.Simple] = this._options.showSimpleSectors;\n shouldShowLod[LevelOfDetail.Detailed] = this._options.showDetailedSectors;\n\n const selectedSectorNodes: SectorNode[] = [];\n this._model.cadNode.traverse(node => {\n if (isSectorNode(node)) {\n const sectorNode = node as SectorNode;\n\n if (\n this.isSectorAcceptedByCurrentFilter(sectorNode) &&\n shouldShowLod[sectorNode.levelOfDetail] &&\n (!this._options.leafsOnly || isLeaf(sectorNode))\n ) {\n selectedSectorNodes.push(sectorNode);\n }\n }\n });\n\n selectedSectorNodes.forEach(sectorNode => {\n const bboxNode = this.createBboxNodeFor(sectorNode, selectedSectorNodes);\n this._boundingBoxes.add(bboxNode);\n });\n this._boundingBoxes.updateMatrixWorld(true);\n\n this._viewer.requestRedraw();\n }\n\n private isSectorAcceptedByCurrentFilter(node: SectorNode): boolean {\n const accepted = new RegExp(this._options.sectorPathFilterRegex).test(node.sectorPath);\n return accepted;\n }\n\n private createBboxNodeFor(node: SectorNode, allSelectedNodes: SectorNode[]) {\n const options = this._options;\n function determineColor() {\n switch (options.colorBy) {\n case 'depth': {\n const s = Math.min(1.0, node.depth / 8);\n return new THREE.Color(Colors.green).lerpHSL(Colors.red, s);\n }\n case 'lod': {\n switch (node.levelOfDetail) {\n case LevelOfDetail.Simple:\n return Colors.yellow;\n case LevelOfDetail.Detailed:\n return Colors.green;\n case LevelOfDetail.Discarded:\n return Colors.red;\n default:\n assertNever(node.levelOfDetail);\n }\n }\n case 'loadedTimestamp': {\n // Note! Horribly slow since we do this for every sector, but since this is a debug tool\n // we consider it OK\n const nodesByTimestamp = [...allSelectedNodes].sort((a, b) => a.updatedTimestamp - b.updatedTimestamp);\n const indexOfNode = nodesByTimestamp.findIndex(x => x === node);\n const s = (nodesByTimestamp.length - 1 - indexOfNode) / Math.max(nodesByTimestamp.length - 1, 1);\n return new THREE.Color(Colors.green).lerpHSL(Colors.red, s);\n }\n\n case 'random':\n return new THREE.Color().setHSL(Math.random(), 1.0, 0.5);\n\n default:\n assertNever(options.colorBy);\n }\n }\n const color = determineColor();\n return new THREE.Box3Helper(node.bounds, color);\n }\n}\n\nconst Colors = {\n green: new THREE.Color('#00ff00'),\n yellow: new THREE.Color('yellow'),\n red: new THREE.Color('red')\n};\n\nfunction isSectorNode(node: THREE.Object3D) {\n return node.name.match(/^Sector \\d+$/);\n}\n\nfunction isLeaf(node: SectorNode) {\n return !node.children.some(x => isSectorNode(x));\n}\n"],"sourceRoot":""}