leaflet-city-mapper 0.0.1 → 0.0.3

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 (629) hide show
  1. package/README.md +61 -13
  2. package/cucumber.mjs +4 -0
  3. package/dist/leaflet-city-mapper.js +3 -1
  4. package/dist/leaflet-city-mapper.js.map +4 -4
  5. package/package.json +3 -4
  6. package/src/archives/decodeDirectory.js +32 -0
  7. package/src/archives/decodeHeader.js +19 -0
  8. package/src/archives/decompress.js +5 -0
  9. package/src/archives/getHeader.js +9 -0
  10. package/src/archives/getZxy.js +75 -0
  11. package/src/archives/loadDirectory.js +7 -0
  12. package/src/archives/loadSource.js +17 -0
  13. package/src/archives/read.js +29 -0
  14. package/src/archives/tileId.js +19 -0
  15. package/src/archives/varint.js +15 -0
  16. package/src/camera/angles.js +6 -0
  17. package/src/camera/animationPoint.js +8 -0
  18. package/src/camera/cameraMapReady.js +8 -0
  19. package/src/camera/cancelCameraAnimation.js +11 -0
  20. package/src/camera/cleanupCameraMap.js +11 -0
  21. package/src/camera/constrainCameraToBounds.js +3 -0
  22. package/src/camera/displayPoint.js +3 -0
  23. package/src/camera/fitCameraBounds.js +48 -0
  24. package/src/camera/groundBounds.js +11 -0
  25. package/src/camera/initializeCameraMap.js +25 -0
  26. package/src/camera/mapAnimateCamera.js +17 -0
  27. package/src/camera/mapCamera.js +123 -0
  28. package/src/camera/mapContainerPointToLayerPoint.js +7 -0
  29. package/src/camera/mapGetBearing.js +1 -0
  30. package/src/camera/mapGetBounds.js +14 -0
  31. package/src/camera/mapGetBoundsCenterZoom.js +7 -0
  32. package/src/camera/mapGetBoundsZoom.js +14 -0
  33. package/src/camera/mapGetCenterLayerPoint.js +5 -0
  34. package/src/camera/mapGetPitch.js +1 -0
  35. package/src/camera/mapLayerPointToContainerPoint.js +7 -0
  36. package/src/camera/mapLimitCenter.js +12 -0
  37. package/src/camera/mapLimitOffset.js +10 -0
  38. package/src/camera/mapPanBy.js +9 -0
  39. package/src/camera/mapPanInside.js +14 -0
  40. package/src/camera/mapResetNorth.js +1 -0
  41. package/src/camera/mapResetNorthPitch.js +1 -0
  42. package/src/camera/mapSetBearing.js +1 -0
  43. package/src/camera/mapSetPitch.js +1 -0
  44. package/src/camera/mapSetPitchAndBearing.js +14 -0
  45. package/src/camera/mapSetZoomAround.js +11 -0
  46. package/src/camera/mapStopPitchBearingAnimation.js +6 -0
  47. package/src/camera/mapTryAnimatedPan.js +9 -0
  48. package/src/camera/mapUpdateCameraOverlays.js +7 -0
  49. package/src/camera/pointOf.js +3 -0
  50. package/src/camera/project.js +20 -0
  51. package/src/camera/runCameraAnimations.js +28 -0
  52. package/src/camera/scheduleCameraAnimation.js +8 -0
  53. package/src/camera/updateSky.js +16 -0
  54. package/src/camera/verticalGroundY.js +4 -0
  55. package/src/collision/collectMeshes.js +5 -0
  56. package/src/collision/collider.js +63 -0
  57. package/src/collision/horizontalRay.js +12 -0
  58. package/src/collision/intersectMeshes.js +133 -0
  59. package/src/collision/sortHits.js +23 -0
  60. package/src/constants/CELL.js +4 -0
  61. package/src/constants/Compass.js +7 -0
  62. package/src/constants/ContainerResize.js +7 -0
  63. package/src/constants/HEIGHT.js +1 -0
  64. package/src/constants/PitchDrag.js +7 -0
  65. package/src/constants/ShiftRotate.js +7 -0
  66. package/src/constants/TILE_RADIUS.js +1 -0
  67. package/src/constants/TILE_SIZE.js +1 -0
  68. package/src/constants/TouchMode.js +6 -0
  69. package/src/constants/accessorSizes.js +1 -0
  70. package/src/constants/accessorTypes.js +8 -0
  71. package/src/constants/attachState.js +1 -0
  72. package/src/constants/cameraControlsState.js +1 -0
  73. package/src/constants/cityMapper.js +6 -0
  74. package/src/constants/colliders.js +2 -0
  75. package/src/constants/dark.js +1 -0
  76. package/src/constants/elevationWGSL.js +27 -0
  77. package/src/constants/glass.js +1 -0
  78. package/src/constants/headlight.js +1 -0
  79. package/src/constants/hull.js +1 -0
  80. package/src/constants/indexState.js +1 -0
  81. package/src/constants/limbs.js +9 -0
  82. package/src/constants/mapCameraState.js +1 -0
  83. package/src/constants/moves.js +11 -0
  84. package/src/constants/nativeEventMaps.js +1 -0
  85. package/src/constants/nativeLayerState.js +1 -0
  86. package/src/constants/nativeMethodHandlers.js +31 -0
  87. package/src/constants/onMapChangeState.js +1 -0
  88. package/src/constants/onZoomAnimState.js +1 -0
  89. package/src/constants/paints.js +10 -0
  90. package/src/constants/parts.js +19 -0
  91. package/src/constants/pendingUpdates.js +1 -0
  92. package/src/constants/pumpState.js +1 -0
  93. package/src/constants/renderers.js +2 -0
  94. package/src/constants/ringDirections.js +10 -0
  95. package/src/constants/roundProfile.js +1 -0
  96. package/src/constants/shirt.js +1 -0
  97. package/src/constants/skin.js +2 -0
  98. package/src/constants/speed.js +3 -0
  99. package/src/constants/taillight.js +1 -0
  100. package/src/constants/trafficShader.js +49 -0
  101. package/src/constants/trousers.js +1 -0
  102. package/src/constants/tyre.js +1 -0
  103. package/src/constants/underEntryState.js +1 -0
  104. package/src/constants/vehicles.js +40 -0
  105. package/src/constants/white.js +1 -0
  106. package/src/controls/acceptPitchDrag.js +4 -0
  107. package/src/controls/acceptRotateDrag.js +3 -0
  108. package/src/controls/adjustCameraDrag.js +10 -0
  109. package/src/controls/cameraControls.js +60 -0
  110. package/src/controls/cameraDragClick.js +9 -0
  111. package/src/controls/cameraDragContextMenu.js +8 -0
  112. package/src/controls/cameraDragDown.js +20 -0
  113. package/src/controls/cameraDragEnd.js +6 -0
  114. package/src/controls/cameraDragMove.js +23 -0
  115. package/src/controls/changeCameraTouch.js +14 -0
  116. package/src/controls/cleanupCameraTouch.js +24 -0
  117. package/src/controls/compassAddHooks.js +15 -0
  118. package/src/controls/compassOrientation.js +6 -0
  119. package/src/controls/compassRemoveHooks.js +5 -0
  120. package/src/controls/containerResizeAddHooks.js +8 -0
  121. package/src/controls/containerResizeRemoveHooks.js +5 -0
  122. package/src/controls/dragCamera.js +22 -0
  123. package/src/controls/editable.js +3 -0
  124. package/src/controls/endAllCameraDrags.js +7 -0
  125. package/src/controls/endAllCameraTouches.js +7 -0
  126. package/src/controls/endCameraTouch.js +11 -0
  127. package/src/controls/endCameraTouchEvent.js +5 -0
  128. package/src/controls/finishCameraDrag.js +9 -0
  129. package/src/controls/finishCompassPermission.js +16 -0
  130. package/src/controls/loadCameraControls.js +9 -0
  131. package/src/controls/moveCameraTouch.js +22 -0
  132. package/src/controls/notifyCameraTouchChange.js +1 -0
  133. package/src/controls/pitchDragAddHooks.js +6 -0
  134. package/src/controls/pitchDragRemoveHooks.js +5 -0
  135. package/src/controls/refreshRotateControl.js +7 -0
  136. package/src/controls/refreshRotateFocus.js +5 -0
  137. package/src/controls/removeCameraDrag.js +23 -0
  138. package/src/controls/resizeMap.js +3 -0
  139. package/src/controls/rotateButtonClick.js +7 -0
  140. package/src/controls/rotateButtonKeydown.js +11 -0
  141. package/src/controls/rotateControl.js +3 -0
  142. package/src/controls/rotateOnAdd.js +38 -0
  143. package/src/controls/rotateOnRemove.js +6 -0
  144. package/src/controls/shiftRotateAddHooks.js +8 -0
  145. package/src/controls/shiftRotateRemoveHooks.js +5 -0
  146. package/src/controls/shiftRotateWheel.js +9 -0
  147. package/src/controls/startCameraTouch.js +23 -0
  148. package/src/core/addImageState.js +7 -0
  149. package/src/core/addRasterImage.js +10 -0
  150. package/src/core/adjustCameraMarkerPan.js +22 -0
  151. package/src/core/beforeNativeRender.js +10 -0
  152. package/src/core/boundsQuad.js +11 -0
  153. package/src/core/bringNativeLayerToBack.js +3 -0
  154. package/src/core/bringNativeLayerToFront.js +3 -0
  155. package/src/core/cameraCircleBounds.js +6 -0
  156. package/src/core/cameraMarkerDrag.js +18 -0
  157. package/src/core/cameraMarkerOnDrag.js +8 -0
  158. package/src/core/cancelGridFade.js +10 -0
  159. package/src/core/closestCameraLayerPoint.js +7 -0
  160. package/src/core/compareNativeHits.js +3 -0
  161. package/src/core/current.js +3 -0
  162. package/src/core/disposeNativeLayer.js +35 -0
  163. package/src/core/fireRasterLoad.js +5 -0
  164. package/src/core/forwardNativeError.js +3 -0
  165. package/src/core/gridlayerGetEvents.js +7 -0
  166. package/src/core/gridlayerGetTiledPixelBounds.js +8 -0
  167. package/src/core/handleNativeMapEvent.js +47 -0
  168. package/src/core/hideTargets.js +16 -0
  169. package/src/core/initNativeGPU.js +21 -0
  170. package/src/core/initializeGridContainer.js +6 -0
  171. package/src/core/initializeNativeLayer.js +42 -0
  172. package/src/core/localPixel.js +5 -0
  173. package/src/core/localPixelForGeometry.js +6 -0
  174. package/src/core/localPosition.js +6 -0
  175. package/src/core/markerCameraIconPoint.js +9 -0
  176. package/src/core/markerGetEvents.js +5 -0
  177. package/src/core/markerInitInteraction.js +8 -0
  178. package/src/core/markerQuadCorners.js +31 -0
  179. package/src/core/markerSetIcon.js +9 -0
  180. package/src/core/markerSetPos.js +14 -0
  181. package/src/core/markerSetRotation.js +7 -0
  182. package/src/core/markerUpdateZIndex.js +8 -0
  183. package/src/core/nativeAddLatLng.js +3 -0
  184. package/src/core/nativeBringToBack.js +3 -0
  185. package/src/core/nativeBringToFront.js +3 -0
  186. package/src/core/nativeEvents.js +26 -0
  187. package/src/core/nativeImageError.js +8 -0
  188. package/src/core/nativeImageRefresh.js +7 -0
  189. package/src/core/nativeLayer.js +97 -0
  190. package/src/core/nativeLayerMethod.js +21 -0
  191. package/src/core/nativeRedraw.js +3 -0
  192. package/src/core/nativeSetBounds.js +3 -0
  193. package/src/core/nativeSetIcon.js +3 -0
  194. package/src/core/nativeSetLatLng.js +3 -0
  195. package/src/core/nativeSetLatLngs.js +3 -0
  196. package/src/core/nativeSetOpacity.js +3 -0
  197. package/src/core/nativeSetRadius.js +3 -0
  198. package/src/core/nativeSetStyle.js +3 -0
  199. package/src/core/nativeSetUrl.js +3 -0
  200. package/src/core/nativeSetZIndex.js +3 -0
  201. package/src/core/nativeSetZIndexOffset.js +3 -0
  202. package/src/core/popupAdjustPan.js +23 -0
  203. package/src/core/popupGetEvents.js +5 -0
  204. package/src/core/popupUpdatePosition.js +14 -0
  205. package/src/core/putNativeMesh.js +33 -0
  206. package/src/core/quadNativeMesh.js +15 -0
  207. package/src/core/readyNativeGPU.js +6 -0
  208. package/src/core/refreshNativeEvent.js +5 -0
  209. package/src/core/refreshNativeLayer.js +29 -0
  210. package/src/core/refreshNativeLayerContract.js +3 -0
  211. package/src/core/rejectNativeReady.js +3 -0
  212. package/src/core/removeImageState.js +8 -0
  213. package/src/core/removeNativeEvents.js +16 -0
  214. package/src/core/removeTargets.js +8 -0
  215. package/src/core/reorderNativeLayer.js +6 -0
  216. package/src/core/resolveNativeReady.js +3 -0
  217. package/src/core/restoreNativeEvents.js +6 -0
  218. package/src/core/runGridFades.js +14 -0
  219. package/src/core/runMarkerPanFrame.js +12 -0
  220. package/src/core/scheduleGridFade.js +9 -0
  221. package/src/core/scheduleMarkerPan.js +8 -0
  222. package/src/core/styleNativeMesh.js +10 -0
  223. package/src/core/syncGridLayer.js +22 -0
  224. package/src/core/syncImageOverlay.js +9 -0
  225. package/src/core/syncMarker.js +12 -0
  226. package/src/core/syncVectorLayer.js +26 -0
  227. package/src/core/synchronizeNativeLayer.js +35 -0
  228. package/src/core/textureFor.js +48 -0
  229. package/src/core/tooltipGetEvents.js +5 -0
  230. package/src/core/tooltipSetPosition.js +8 -0
  231. package/src/core/updateGridOpacity.js +23 -0
  232. package/src/core/updateNativeLayerView.js +6 -0
  233. package/src/core/uploadCanvasTexture.js +19 -0
  234. package/src/geometry/addBridges.js +88 -0
  235. package/src/geometry/below.js +3 -0
  236. package/src/geometry/box.js +3 -0
  237. package/src/geometry/bridgeElevation.js +19 -0
  238. package/src/geometry/bridgeLocal.js +4 -0
  239. package/src/geometry/build.js +19 -0
  240. package/src/geometry/circleAt.js +5 -0
  241. package/src/geometry/clipLine.js +23 -0
  242. package/src/geometry/clipSegment.js +19 -0
  243. package/src/geometry/computeBounds.js +33 -0
  244. package/src/geometry/conformModelToTerrain.js +67 -0
  245. package/src/geometry/cross.js +3 -0
  246. package/src/geometry/disk.js +11 -0
  247. package/src/geometry/diskAt.js +4 -0
  248. package/src/geometry/dot.js +6 -0
  249. package/src/geometry/emitter.js +8 -0
  250. package/src/geometry/lampPostGeometry.js +24 -0
  251. package/src/geometry/lampRing.js +11 -0
  252. package/src/geometry/lightGeometry.js +15 -0
  253. package/src/geometry/line.js +54 -0
  254. package/src/geometry/nativeGeometry.js +55 -0
  255. package/src/geometry/nativeTriangle.js +3 -0
  256. package/src/geometry/polygon.js +22 -0
  257. package/src/geometry/push.js +3 -0
  258. package/src/geometry/quad.js +4 -0
  259. package/src/geometry/roofCoverage.js +52 -0
  260. package/src/geometry/samePoint.js +3 -0
  261. package/src/geometry/segment.js +21 -0
  262. package/src/geometry/setVertexColor.js +15 -0
  263. package/src/geometry/sub.js +6 -0
  264. package/src/geometry/surface.js +17 -0
  265. package/src/geometry/treeGeometry.js +31 -0
  266. package/src/geometry/treeRing.js +14 -0
  267. package/src/geometry/triangle.js +12 -0
  268. package/src/geometry/vertexNormals.js +32 -0
  269. package/src/geometry/visit.js +9 -0
  270. package/src/index.js +98 -65
  271. package/src/lighting/cacheLightGrid.js +23 -0
  272. package/src/lighting/collectLightMeshes.js +6 -0
  273. package/src/lighting/lightGrid.js +42 -0
  274. package/src/lighting/updatePointLights.js +34 -0
  275. package/src/lighting/visitCells.js +15 -0
  276. package/src/lighting/worldLights.js +27 -0
  277. package/src/models/decodeModel.js +45 -0
  278. package/src/models/hasUnsupportedPrimitives.js +10 -0
  279. package/src/models/loadBuffer.js +6 -0
  280. package/src/models/loadImage.js +15 -0
  281. package/src/models/loadModel.js +69 -0
  282. package/src/models/materialFor.js +21 -0
  283. package/src/models/modelNode.js +93 -0
  284. package/src/models/nodeMatrix.js +22 -0
  285. package/src/models/readAccessor.js +53 -0
  286. package/src/models/readAccessorValues.js +16 -0
  287. package/src/models/textureFor.js +35 -0
  288. package/src/models/textureSampler.js +10 -0
  289. package/src/picking/collectVisibleMesh.js +4 -0
  290. package/src/picking/findFeature.js +49 -0
  291. package/src/picking/hit.js +23 -0
  292. package/src/picking/hitMesh.js +30 -0
  293. package/src/picking/onClick.js +13 -0
  294. package/src/picking/onPointerLeave.js +11 -0
  295. package/src/picking/onPointerMove.js +15 -0
  296. package/src/picking/pointerClick.js +5 -0
  297. package/src/picking/pointerLeave.js +5 -0
  298. package/src/picking/pointerMove.js +5 -0
  299. package/src/picking/raycast.js +59 -0
  300. package/src/picking/setHighlight.js +13 -0
  301. package/src/picking/shouldSkipOther.js +3 -0
  302. package/src/picking/showFeature.js +34 -0
  303. package/src/raster/addRasterTile.js +114 -0
  304. package/src/raster/comparePendingTiles.js +5 -0
  305. package/src/raster/createGeometry.js +22 -0
  306. package/src/raster/createRasterMesh.js +47 -0
  307. package/src/raster/finishAttachment.js +11 -0
  308. package/src/raster/finishRasterTile.js +47 -0
  309. package/src/raster/getRasterEvents.js +6 -0
  310. package/src/raster/getRasterTileSize.js +5 -0
  311. package/src/raster/initRaster.js +38 -0
  312. package/src/raster/isLoading.js +5 -0
  313. package/src/raster/loadRasterTile.js +10 -0
  314. package/src/raster/onPMTileAdd.js +10 -0
  315. package/src/raster/onPMTileRemove.js +8 -0
  316. package/src/raster/pruneRasterTiles.js +37 -0
  317. package/src/raster/pumpRasterTiles.js +22 -0
  318. package/src/raster/readyRaster.js +13 -0
  319. package/src/raster/registerTerrainTile.js +12 -0
  320. package/src/raster/releaseRasterTile.js +18 -0
  321. package/src/raster/releaseRasterTiles.js +15 -0
  322. package/src/raster/removeRasterTile.js +13 -0
  323. package/src/raster/reportError.js +6 -0
  324. package/src/raster/setPMTileOpacity.js +7 -0
  325. package/src/raster/setPMTileZIndex.js +7 -0
  326. package/src/raster/setRasterOpacity.js +11 -0
  327. package/src/raster/setRasterTerrain.js +21 -0
  328. package/src/raster/setRasterZIndex.js +11 -0
  329. package/src/raster/updateAttachedTiles.js +10 -0
  330. package/src/raster/updateRasterTiles.js +59 -0
  331. package/src/rendering/collectFrameMeshes.js +31 -0
  332. package/src/rendering/collectMeshes.js +36 -0
  333. package/src/rendering/compareMeshes.js +10 -0
  334. package/src/rendering/compareRoofTiles.js +4 -0
  335. package/src/rendering/composeRoofAtlas.js +52 -0
  336. package/src/rendering/createMesh.js +33 -0
  337. package/src/rendering/createProgram.js +92 -0
  338. package/src/rendering/destroyAfterSubmission.js +8 -0
  339. package/src/rendering/destroyTexture.js +6 -0
  340. package/src/rendering/disposeMesh.js +14 -0
  341. package/src/rendering/drawGeometry.js +129 -0
  342. package/src/rendering/drawSceneMeshes.js +51 -0
  343. package/src/rendering/ensureRoofBlit.js +40 -0
  344. package/src/rendering/prepareFrameMeshes.js +42 -0
  345. package/src/rendering/prepareFrameUniforms.js +49 -0
  346. package/src/rendering/rebuildRoofAtlas.js +67 -0
  347. package/src/rendering/render.js +57 -0
  348. package/src/rendering/reportCompilation.js +17 -0
  349. package/src/rendering/resizeRenderer.js +19 -0
  350. package/src/rendering/sortMeshes.js +6 -0
  351. package/src/rendering/synchronizeZoomView.js +34 -0
  352. package/src/rendering/textureBinding.js +7 -0
  353. package/src/rendering/updateMapCamera.js +32 -0
  354. package/src/rendering/updateRoofRaster.js +32 -0
  355. package/src/scene/attach.js +161 -0
  356. package/src/scene/attachLayer.js +10 -0
  357. package/src/scene/cancelUpdate.js +10 -0
  358. package/src/scene/emptyEvents.js +3 -0
  359. package/src/scene/emptyNode.js +11 -0
  360. package/src/scene/endZoom.js +16 -0
  361. package/src/scene/failAttachment.js +9 -0
  362. package/src/scene/get3DEvents.js +13 -0
  363. package/src/scene/init3D.js +30 -0
  364. package/src/scene/initializeLayer.js +16 -0
  365. package/src/scene/initializerFor.js +14 -0
  366. package/src/scene/layerInitialize.js +38 -0
  367. package/src/scene/layerLayerAdd.js +21 -0
  368. package/src/scene/onAdd3DLayer.js +35 -0
  369. package/src/scene/onMapChange.js +16 -0
  370. package/src/scene/onRemove3DLayer.js +69 -0
  371. package/src/scene/onZoomAnim.js +16 -0
  372. package/src/scene/placeEntry.js +11 -0
  373. package/src/scene/placeUnderEntry.js +8 -0
  374. package/src/scene/ready3D.js +25 -0
  375. package/src/scene/releaseRenderer.js +14 -0
  376. package/src/scene/removeEntry.js +6 -0
  377. package/src/scene/renderPendingMapChange.js +11 -0
  378. package/src/scene/renderPendingUpdates.js +19 -0
  379. package/src/scene/renderPendingZoomAnimation.js +7 -0
  380. package/src/scene/rendererDeviceError.js +10 -0
  381. package/src/scene/rendererDeviceLost.js +11 -0
  382. package/src/scene/replaceEntry.js +7 -0
  383. package/src/scene/reportError.js +3 -0
  384. package/src/scene/requestAdapter.js +12 -0
  385. package/src/scene/requestDevice.js +9 -0
  386. package/src/scene/resolveNextInitialization.js +12 -0
  387. package/src/scene/restoreObject.js +71 -0
  388. package/src/scene/runPlacements.js +7 -0
  389. package/src/scene/setParent.js +7 -0
  390. package/src/scene/showWebGPUWarning.js +16 -0
  391. package/src/scene/startZoom.js +5 -0
  392. package/src/scene/traverse.js +7 -0
  393. package/src/scene/underEntry.js +17 -0
  394. package/src/scene/update.js +19 -0
  395. package/src/scene/updateCamera.js +34 -0
  396. package/src/scene/updateWorldMatrix.js +48 -0
  397. package/src/{utils/shaders.js → shaders/materialShaders.js} +246 -237
  398. package/src/shadows/bindSunlight.js +12 -0
  399. package/src/shadows/drawShadowMeshes.js +48 -0
  400. package/src/shadows/ensureShadowPipeline.js +53 -0
  401. package/src/shadows/renderSunlight.js +46 -0
  402. package/src/shadows/resizeSunlight.js +15 -0
  403. package/src/shadows/shadowBounds.js +32 -0
  404. package/src/shadows/shadowCacheMatches.js +23 -0
  405. package/src/shadows/shadowMatrix.js +39 -0
  406. package/src/sources/addGeneratedTriangle.js +6 -0
  407. package/src/sources/addTriangle.js +17 -0
  408. package/src/sources/attachAreaMesh.js +58 -0
  409. package/src/sources/buildArea.js +42 -0
  410. package/src/sources/buildAreaFeature.js +41 -0
  411. package/src/sources/buildAreaPoint.js +25 -0
  412. package/src/sources/buildAreaPolygon.js +29 -0
  413. package/src/sources/compareAreaDistance.js +4 -0
  414. package/src/sources/generateTreeGeometry.js +11 -0
  415. package/src/sources/groundOffset.js +3 -0
  416. package/src/sources/initializeGeoJSON.js +8 -0
  417. package/src/sources/instanceAreaGeometry.js +29 -0
  418. package/src/sources/projectRing.js +20 -0
  419. package/src/sources/projectedTree.js +13 -0
  420. package/src/sources/pump.js +54 -0
  421. package/src/sources/releaseArea.js +22 -0
  422. package/src/sources/setGeoJSONData.js +12 -0
  423. package/src/sources/setGeoJSONLayerData.js +5 -0
  424. package/src/sources/sourceAreaContext.js +9 -0
  425. package/src/sources/updateArea.js +45 -0
  426. package/src/sources/updateStatus.js +12 -0
  427. package/src/sunlight/addTimeLayer.js +3 -0
  428. package/src/sunlight/addTo.js +10 -0
  429. package/src/sunlight/atmosphere.js +28 -0
  430. package/src/sunlight/horizontalPosition.js +16 -0
  431. package/src/sunlight/initSunlight.js +14 -0
  432. package/src/sunlight/initialize.js +11 -0
  433. package/src/sunlight/mix.js +6 -0
  434. package/src/sunlight/moonPosition.js +17 -0
  435. package/src/sunlight/onAdd.js +5 -0
  436. package/src/sunlight/onAddSun.js +66 -0
  437. package/src/sunlight/projectCelestialBody.js +13 -0
  438. package/src/sunlight/remove.js +7 -0
  439. package/src/sunlight/removeSun.js +15 -0
  440. package/src/sunlight/removeTimeLayer.js +3 -0
  441. package/src/sunlight/render.js +7 -0
  442. package/src/sunlight/rgb.js +6 -0
  443. package/src/sunlight/solarPosition.js +17 -0
  444. package/src/sunlight/styleTimeControl.js +7 -0
  445. package/src/sunlight/tickSun.js +5 -0
  446. package/src/sunlight/updateSky.js +20 -0
  447. package/src/sunlight/updateSun.js +34 -0
  448. package/src/sunlight/useLiveTime.js +6 -0
  449. package/src/sunlight/useSelectedTime.js +20 -0
  450. package/src/terrain/clearLayerTerrain.js +5 -0
  451. package/src/terrain/getElevation.js +10 -0
  452. package/src/terrain/initTerrain.js +20 -0
  453. package/src/terrain/loadReadyTerrain.js +5 -0
  454. package/src/terrain/loadTerrain.js +63 -0
  455. package/src/terrain/loadTerrainTiles.js +13 -0
  456. package/src/terrain/onTerrainAdd.js +21 -0
  457. package/src/terrain/onTerrainChange.js +14 -0
  458. package/src/terrain/onTerrainRemove.js +41 -0
  459. package/src/terrain/readBridges.js +4 -0
  460. package/src/terrain/sample.js +7 -0
  461. package/src/terrain/setLayerTerrain.js +5 -0
  462. package/src/terrain/setTerrainHeight.js +10 -0
  463. package/src/terrain/terrainAtlas.js +23 -0
  464. package/src/terrain/terrainElevation.js +20 -0
  465. package/src/terrain/terrainGrid.js +24 -0
  466. package/src/traffic/addTraffic.js +7 -0
  467. package/src/traffic/along.js +14 -0
  468. package/src/traffic/clockMinutes.js +6 -0
  469. package/src/traffic/compareDepartures.js +5 -0
  470. package/src/traffic/createTrafficMesh.js +7 -0
  471. package/src/traffic/destroyTrafficGpu.js +5 -0
  472. package/src/traffic/disposeTrafficObject.js +13 -0
  473. package/src/traffic/drawTrafficRoute.js +6 -0
  474. package/src/traffic/failTraffic.js +6 -0
  475. package/src/traffic/failedTrafficLoad.js +5 -0
  476. package/src/traffic/fetchTrafficLanes.js +10 -0
  477. package/src/traffic/groundTraffic.js +15 -0
  478. package/src/traffic/initTraffic.js +54 -0
  479. package/src/traffic/loadTraffic.js +15 -0
  480. package/src/traffic/loadedTrafficLanes.js +16 -0
  481. package/src/traffic/locateTraffic.js +9 -0
  482. package/src/traffic/moveTraffic.js +15 -0
  483. package/src/traffic/placeTraffic.js +21 -0
  484. package/src/traffic/prepareTraffic.js +25 -0
  485. package/src/traffic/readyTraffic.js +6 -0
  486. package/src/traffic/rebaseTraffic.js +58 -0
  487. package/src/traffic/rebuildTrafficMesh.js +28 -0
  488. package/src/traffic/removeTraffic.js +17 -0
  489. package/src/traffic/routeColor.js +6 -0
  490. package/src/traffic/routeGeometry.js +31 -0
  491. package/src/traffic/scheduledTrips.js +40 -0
  492. package/src/traffic/startTraffic.js +8 -0
  493. package/src/traffic/tickTraffic.js +57 -0
  494. package/src/traffic/toLanes.js +16 -0
  495. package/src/traffic/tooltip.js +11 -0
  496. package/src/traffic/trafficBounds.js +17 -0
  497. package/src/traffic/trafficNow.js +4 -0
  498. package/src/traffic/trafficStorage.js +5 -0
  499. package/src/traffic/tripsAt.js +27 -0
  500. package/src/traffic/updateTraffic.js +8 -0
  501. package/src/traffic/updateTrafficTerrain.js +12 -0
  502. package/src/traffic/vehicleOffsets.js +11 -0
  503. package/src/triangulation/area.js +9 -0
  504. package/src/triangulation/clean.js +18 -0
  505. package/src/triangulation/containsVertex.js +11 -0
  506. package/src/triangulation/cross.js +3 -0
  507. package/src/triangulation/crossesBoundary.js +8 -0
  508. package/src/triangulation/crossesRing.js +9 -0
  509. package/src/triangulation/equal.js +3 -0
  510. package/src/triangulation/inside.js +10 -0
  511. package/src/triangulation/insideHole.js +7 -0
  512. package/src/triangulation/intersects.js +11 -0
  513. package/src/triangulation/isClockWise.js +13 -0
  514. package/src/triangulation/minimumX.js +6 -0
  515. package/src/triangulation/on.js +4 -0
  516. package/src/triangulation/sortHoles.js +26 -0
  517. package/src/triangulation/triangulate.js +86 -0
  518. package/src/utils/channel.js +4 -0
  519. package/src/utils/compareDistance.js +3 -0
  520. package/src/utils/noOperation.js +1 -0
  521. package/src/utils/parseColor.js +42 -0
  522. package/src/utils/toSRGB.js +3 -0
  523. package/src/utils/wrap.js +3 -0
  524. package/src/vehicles/bicycleModel.js +23 -0
  525. package/src/vehicles/boatBenches.js +8 -0
  526. package/src/vehicles/boatModel.js +27 -0
  527. package/src/vehicles/busModel.js +6 -0
  528. package/src/vehicles/carModel.js +22 -0
  529. package/src/vehicles/carriage.js +19 -0
  530. package/src/vehicles/metroModel.js +9 -0
  531. package/src/vehicles/mirror.js +8 -0
  532. package/src/vehicles/pedestrianModel.js +17 -0
  533. package/src/vehicles/tramModel.js +9 -0
  534. package/src/walk/blocked.js +6 -0
  535. package/src/walk/createWalk.js +60 -0
  536. package/src/walk/initWalk.js +18 -0
  537. package/src/walk/initialize.js +6 -0
  538. package/src/walk/local.js +10 -0
  539. package/src/walk/onAdd.js +4 -0
  540. package/src/walk/onBlur.js +3 -0
  541. package/src/walk/onKey.js +12 -0
  542. package/src/walk/onPointer.js +13 -0
  543. package/src/walk/onRemove.js +4 -0
  544. package/src/walk/onTerrain.js +5 -0
  545. package/src/walk/place.js +18 -0
  546. package/src/walk/start.js +37 -0
  547. package/src/walk/step.js +53 -0
  548. package/src/walk/stop.js +27 -0
  549. package/src/walk/toggle.js +6 -0
  550. package/dist/scene/gpu.js +0 -3
  551. package/dist/scene/gpu.js.map +0 -7
  552. package/dist/scene/lighting.js +0 -9
  553. package/dist/scene/lighting.js.map +0 -7
  554. package/dist/scene/model.js +0 -2
  555. package/dist/scene/model.js.map +0 -7
  556. package/dist/scene/picking.js +0 -2
  557. package/dist/scene/picking.js.map +0 -7
  558. package/dist/scene/pmtiles.js +0 -2
  559. package/dist/scene/pmtiles.js.map +0 -7
  560. package/dist/scene/render.js +0 -15
  561. package/dist/scene/render.js.map +0 -7
  562. package/dist/scene/sources.js +0 -2
  563. package/dist/scene/sources.js.map +0 -7
  564. package/dist/types/3d.js +0 -2
  565. package/dist/types/3d.js.map +0 -7
  566. package/dist/types/geojson.js +0 -2
  567. package/dist/types/geojson.js.map +0 -7
  568. package/dist/types/pmtiles.js +0 -2
  569. package/dist/types/pmtiles.js.map +0 -7
  570. package/dist/types/sunlight.js +0 -2
  571. package/dist/types/sunlight.js.map +0 -7
  572. package/dist/types/terrain.js +0 -24
  573. package/dist/types/terrain.js.map +0 -7
  574. package/dist/types/traffic.js +0 -41
  575. package/dist/types/traffic.js.map +0 -7
  576. package/dist/types/walk.js +0 -2
  577. package/dist/types/walk.js.map +0 -7
  578. package/dist/utils/control.js +0 -2
  579. package/dist/utils/control.js.map +0 -7
  580. package/dist/utils/geometry.js +0 -2
  581. package/dist/utils/geometry.js.map +0 -7
  582. package/dist/utils/lighting.js +0 -2
  583. package/dist/utils/lighting.js.map +0 -7
  584. package/dist/utils/model.js +0 -2
  585. package/dist/utils/model.js.map +0 -7
  586. package/dist/utils/picking.js +0 -2
  587. package/dist/utils/picking.js.map +0 -7
  588. package/dist/utils/pmtiles.js +0 -2
  589. package/dist/utils/pmtiles.js.map +0 -7
  590. package/dist/utils/scene.js +0 -2
  591. package/dist/utils/scene.js.map +0 -7
  592. package/dist/utils/shaders.js +0 -203
  593. package/dist/utils/shaders.js.map +0 -7
  594. package/dist/utils/sun.js +0 -2
  595. package/dist/utils/sun.js.map +0 -7
  596. package/dist/utils/terrain.js +0 -2
  597. package/dist/utils/terrain.js.map +0 -7
  598. package/dist/utils/traffic.js +0 -2
  599. package/dist/utils/traffic.js.map +0 -7
  600. package/dist/utils/vehicles.js +0 -2
  601. package/dist/utils/vehicles.js.map +0 -7
  602. package/dist/utils/walk.js +0 -2
  603. package/dist/utils/walk.js.map +0 -7
  604. package/src/scene/gpu.js +0 -438
  605. package/src/scene/lighting.js +0 -193
  606. package/src/scene/model.js +0 -204
  607. package/src/scene/picking.js +0 -150
  608. package/src/scene/pmtiles.js +0 -94
  609. package/src/scene/render.js +0 -467
  610. package/src/scene/sources.js +0 -265
  611. package/src/types/3d.js +0 -337
  612. package/src/types/geojson.js +0 -42
  613. package/src/types/pmtiles.js +0 -143
  614. package/src/types/sunlight.js +0 -142
  615. package/src/types/terrain.js +0 -331
  616. package/src/types/traffic.js +0 -356
  617. package/src/types/walk.js +0 -219
  618. package/src/utils/control.js +0 -18
  619. package/src/utils/geometry.js +0 -256
  620. package/src/utils/lighting.js +0 -51
  621. package/src/utils/model.js +0 -178
  622. package/src/utils/picking.js +0 -119
  623. package/src/utils/pmtiles.js +0 -79
  624. package/src/utils/scene.js +0 -102
  625. package/src/utils/sun.js +0 -71
  626. package/src/utils/terrain.js +0 -78
  627. package/src/utils/traffic.js +0 -90
  628. package/src/utils/vehicles.js +0 -69
  629. package/src/utils/walk.js +0 -72
@@ -0,0 +1,60 @@
1
+ import { init3D } from '../scene/init3D.js';
2
+ import { onBlur } from './onBlur.js';
3
+ import { onKey } from './onKey.js';
4
+ import { onPointer } from './onPointer.js';
5
+ import { onTerrain } from './onTerrain.js';
6
+ import { start } from './start.js';
7
+ import { step } from './step.js';
8
+ import { stop } from './stop.js';
9
+ import { toggle } from './toggle.js';
10
+
11
+ export function createWalk(control, {
12
+ speed,
13
+ distance,
14
+ ...options
15
+ } = {}) {
16
+ const layer = new L.Layer();
17
+ layer._type = 'walk';
18
+ init3D(layer, options);
19
+ const keys = new Set();
20
+ const container = L.DomUtil.create('div', 'leaflet-bar leaflet-control');
21
+ container.style.cssText = 'display:flex;align-items:center;background:#fff;';
22
+ const button = L.DomUtil.create('button', '', container);
23
+ button.type = 'button';
24
+ button.title = 'Walk';
25
+ button.setAttribute('aria-label', 'Walk');
26
+ button.setAttribute('aria-pressed', 'false');
27
+ button.textContent = '🚶';
28
+ button.style.cssText = 'width:30px;height:30px;padding:0;border:0;border-radius:4px;background:#fff;font-size:18px;line-height:30px;cursor:pointer;';
29
+ const hint = L.DomUtil.create('small', '', container);
30
+ hint.style.cssText = 'display:none;padding:0 8px;color:#333;white-space:nowrap;';
31
+ hint.textContent = 'W/S: run · A/D: turn · drag: look around · Esc: exit';
32
+ L.DomEvent.disableClickPropagation(container);
33
+
34
+ const context = {
35
+ layer,
36
+ speed,
37
+ distance,
38
+ keys,
39
+ container,
40
+ button,
41
+ hint,
42
+ meshes: null,
43
+ frame: null,
44
+ last: undefined,
45
+ swing: 0,
46
+ saved: null,
47
+ drag: null,
48
+ state: control.walker = layer.walker = { latlng: null, heading: 0, phase: 0 }
49
+ }
50
+ context.step = step.bind(context);
51
+ context.onKey = onKey.bind(context);
52
+ context.onBlur = onBlur.bind(context);
53
+ context.onPointer = onPointer.bind(context);
54
+ context.onTerrain = onTerrain.bind(context);
55
+ context.start = start.bind(context);
56
+ context.stop = stop.bind(context);
57
+ context.toggle = toggle.bind(context);
58
+ control._walk = context;
59
+ L.DomEvent.on(button, 'click', context.toggle);
60
+ }
@@ -0,0 +1,18 @@
1
+ import { initialize } from './initialize.js';
2
+ import { onAdd } from './onAdd.js';
3
+ import { onRemove } from './onRemove.js';
4
+
5
+ /**
6
+ * Third-person walk mode, toggled by a map button (and Esc): a pedestrian at the map centre runs with W/S (or ↑/↓) and
7
+ * turns with A/D (or ←/→); the camera swings back behind it while it moves. Dragging the map only turns the camera
8
+ * (bearing, pitch); the wheel changes the camera distance.
9
+ * The walker follows the terrain, bridges included, and `control.walker` exposes `{ latlng, heading, phase }`.
10
+ * Options: `speed` (m/s, default 70), `distance` (camera distance in metres, default 20), `position` (button corner, default 'bottomright').
11
+ * Visible meshes of the other 3D layers (buildings, trees, models, streetlights) are solid; terrain and traffic are not.
12
+ */
13
+ L.Control.Walk = L.Control.extend({
14
+ options: { position: 'bottomright', speed: 70, distance: 20 },
15
+ initialize,
16
+ onAdd,
17
+ onRemove,
18
+ });
@@ -0,0 +1,6 @@
1
+ import { createWalk } from './createWalk.js';
2
+
3
+ export function initialize(options) {
4
+ L.Util.setOptions(this, options);
5
+ createWalk(this, this.options);
6
+ }
@@ -0,0 +1,10 @@
1
+ import { getElevation } from '../terrain/getElevation.js';
2
+
3
+ export function local() {
4
+ const { layer, state } = this;
5
+ const map = layer._map, crs = map.options.crs, origin = crs.project(layer.location);
6
+ const metres = Math.cos(layer.location.lat * Math.PI / 180);
7
+ const p = crs.project(state.latlng), terrain = map._terrain3D?._terrainReady && map._terrain3D;
8
+ const ground = (terrain && getElevation(terrain, state.latlng)) || 0;
9
+ return [(p.x - origin.x) * metres, ground - layer.root.position[1], -(p.y - origin.y) * metres];
10
+ }
@@ -0,0 +1,4 @@
1
+ export function onAdd(map) {
2
+ this._walk.layer.addTo(map);
3
+ return this._walk.container;
4
+ }
@@ -0,0 +1,3 @@
1
+ export function onBlur() {
2
+ this.keys.clear();
3
+ }
@@ -0,0 +1,12 @@
1
+ import { moves } from '../constants/moves.js';
2
+ import { stop } from './stop.js';
3
+
4
+ export function onKey(event) {
5
+ // Text fields and sliders keep their keys; buttons and checkboxes don't.
6
+ if (event.target.closest?.('input:not([type=checkbox], [type=radio]), select, textarea, [contenteditable]') ||
7
+ event.ctrlKey || event.altKey || event.metaKey) return;
8
+ if (event.type === 'keydown' && event.code === 'Escape') { this.stop(); return; }
9
+ if (!moves[event.code]) return;
10
+ event.preventDefault();
11
+ if (event.type === 'keydown') this.keys.add(event.code); else this.keys.delete(event.code);
12
+ }
@@ -0,0 +1,13 @@
1
+ export function onPointer(event) {
2
+ // Dragging only turns the camera around the walker: horizontal = bearing, vertical = pitch.
3
+ const map = this.layer._map;
4
+ if (event.type === 'pointerdown') {
5
+ if (event.button !== 0 || event.target.closest('.leaflet-control')) return;
6
+ this.drag = { x: event.clientX, y: event.clientY };
7
+ map.getContainer().setPointerCapture(event.pointerId);
8
+ } else if (this.drag && event.type === 'pointermove') {
9
+ map._setPitchAndBearing(Math.max(20, Math.min(85, map.getPitch() - (event.clientY - this.drag.y) * 0.2)),
10
+ map.getBearing() - (event.clientX - this.drag.x) * 0.25);
11
+ this.drag = { x: event.clientX, y: event.clientY };
12
+ } else this.drag = null;
13
+ }
@@ -0,0 +1,4 @@
1
+ export function onRemove() {
2
+ this._walk.stop();
3
+ this._walk.layer.remove();
4
+ }
@@ -0,0 +1,5 @@
1
+ import { place } from './place.js';
2
+
3
+ export function onTerrain() {
4
+ if (this.meshes) place.call(this);
5
+ }
@@ -0,0 +1,18 @@
1
+ import { update } from '../scene/update.js';
2
+ import { limbs } from '../constants/limbs.js';
3
+ import { local } from './local.js';
4
+
5
+ export function place() {
6
+ const [x, y, z] = local.call(this);
7
+ // Model forward is -z; a yaw of -heading turns it to the compass heading (x east, -z north).
8
+ const yaw = -this.state.heading, cos = Math.cos(yaw), sin = Math.sin(yaw);
9
+ let i, px, py, sign, mesh;
10
+ for (i = 0; i < limbs.length; i++) {
11
+ [, px, py, sign] = limbs[i];
12
+ mesh = this.meshes[i];
13
+ mesh.position[0] = x + px * cos; mesh.position[1] = y + py; mesh.position[2] = z - px * sin;
14
+ mesh.rotation[0] = sign * this.swing * Math.sin(this.state.phase);
15
+ mesh.rotation[1] = yaw;
16
+ }
17
+ update(this.layer);
18
+ }
@@ -0,0 +1,37 @@
1
+ import { step } from './step.js';
2
+ import { onKey } from './onKey.js';
3
+ import { onBlur } from './onBlur.js';
4
+ import { onPointer } from './onPointer.js';
5
+ import { onTerrain } from './onTerrain.js';
6
+
7
+ export function start() {
8
+ const map = this.layer._map;
9
+ if (this.saved || !map) return;
10
+ this.state.latlng = map.getCenter();
11
+ // Zoom whose camera distance (1.5 viewport heights, as in scene/render.js) is about `distance` metres behind the walker.
12
+ const pixelsPerMetre = map.getSize().y * 1.5 / this.distance;
13
+ const zoom = Math.min(map.getMaxZoom(), Math.log2(pixelsPerMetre * 40075016.68557849 * Math.cos(this.state.latlng.lat * Math.PI / 180) / 256));
14
+ const handlers = [];
15
+ let name;
16
+ for (name of ['dragging', 'keyboard', 'doubleClickZoom', 'boxZoom']) {
17
+ if (map[name]?.enabled()) handlers.push(name);
18
+ }
19
+ this.saved = {
20
+ zoom: map.getZoom(), pitch: map.getPitch(), scrollWheelZoom: map.options.scrollWheelZoom, handlers
21
+ };
22
+ for (name of this.saved.handlers) map[name].disable();
23
+ // Wheel zoom moves the camera closer or farther, keeping the walker centred.
24
+ map.options.scrollWheelZoom = this.saved.scrollWheelZoom && 'center';
25
+ this.state.heading = -map.getBearing() * Math.PI / 180;
26
+ map.setView(this.state.latlng, zoom, { animate: false });
27
+ map.setPitch(75);
28
+ L.DomEvent.on(document, 'keydown keyup', this.onKey);
29
+ L.DomEvent.on(window, 'blur', this.onBlur);
30
+ L.DomEvent.on(map.getContainer(), 'pointerdown pointermove pointerup pointercancel', this.onPointer);
31
+ map.on('terrainchange', this.onTerrain);
32
+ this.button.setAttribute('aria-pressed', 'true');
33
+ this.button.style.background = '#e4e4e4';
34
+ this.hint.style.display = '';
35
+ this.last = undefined;
36
+ this.frame = requestAnimationFrame(this.step);
37
+ }
@@ -0,0 +1,53 @@
1
+ import * as createMesh from '../rendering/createMesh.js';
2
+ import { build } from '../geometry/build.js';
3
+ import { limbs } from '../constants/limbs.js';
4
+ import { moves } from '../constants/moves.js';
5
+ import { parts } from '../constants/parts.js';
6
+ import { wrap } from '../utils/wrap.js';
7
+ import { local } from './local.js';
8
+ import { place } from './place.js';
9
+ import { blocked } from './blocked.js';
10
+
11
+ export function step(now) {
12
+ const layer = this.layer, map = layer._map;
13
+ this.frame = requestAnimationFrame(this.step);
14
+ const dt = Math.min(0.1, (now - (this.last ?? now)) / 1000);
15
+ this.last = now;
16
+ if (!layer.renderer) return;
17
+ let changed = false;
18
+ let part, key, i;
19
+ if (!this.meshes) {
20
+ this.meshes = [];
21
+ for ([part] of limbs) this.meshes.push(createMesh.createMesh(layer, build(parts[part])));
22
+ changed = true;
23
+ }
24
+ let forward = 0, turn = 0;
25
+ for (key of this.keys) { forward += moves[key]?.[0] || 0; turn += moves[key]?.[1] || 0; }
26
+ forward = Math.sign(forward); turn = Math.sign(turn);
27
+ if (turn) { this.state.heading = wrap(this.state.heading + turn * 2.5 * dt); changed = true; }
28
+ if (forward) {
29
+ const metres = forward * this.speed * dt, { lat, lng } = this.state.latlng, { position, scale } = layer.root;
30
+ let east = Math.sin(this.state.heading) * metres, north = Math.cos(this.state.heading) * metres;
31
+ const feet = local.call(this);
32
+ for (i = 0; i < feet.length; i++) feet[i] = position[i] + scale[i] * feet[i];
33
+ // World x is east, z south; keep 0.3 m from walls and slide along the one in the way.
34
+ const wall = blocked.call(this, east, north, feet);
35
+ if (wall) {
36
+ const into = east * wall[0] - north * wall[1];
37
+ east -= into * wall[0]; north += into * wall[1];
38
+ if (blocked.call(this, east, north, feet)) east = north = 0;
39
+ }
40
+ this.state.latlng = new L.LatLng(lat + north / 111320, lng + east / (111320 * Math.cos(lat * Math.PI / 180)));
41
+ this.state.phase += Math.hypot(east, north) / 1.6 * Math.PI;
42
+ changed = true;
43
+ }
44
+ if (forward || turn) {
45
+ // The camera (looking along -bearing) swings back behind the walker.
46
+ const bearing = map.getBearing() * Math.PI / 180, behind = wrap(-this.state.heading - bearing);
47
+ if (Math.abs(behind) > 1e-3) map._setPitchAndBearing(map.getPitch(), (bearing + behind * Math.min(1, dt * 4)) * 180 / Math.PI);
48
+ map.setView(this.state.latlng, map.getZoom(), { animate: false });
49
+ }
50
+ const target = forward ? 0.9 : 0;
51
+ if (Math.abs(this.swing - target) > 1e-3) { this.swing += (target - this.swing) * Math.min(1, dt * 10); changed = true; }
52
+ if (changed) place.call(this);
53
+ }
@@ -0,0 +1,27 @@
1
+ import * as disposeMesh from '../rendering/disposeMesh.js';
2
+ import { onKey } from './onKey.js';
3
+ import { onBlur } from './onBlur.js';
4
+ import { onPointer } from './onPointer.js';
5
+ import { onTerrain } from './onTerrain.js';
6
+
7
+ export function stop() {
8
+ const map = this.layer._map;
9
+ cancelAnimationFrame(this.frame);
10
+ this.keys.clear(); this.drag = null;
11
+ L.DomEvent.off(document, 'keydown keyup', this.onKey);
12
+ L.DomEvent.off(window, 'blur', this.onBlur);
13
+ let mesh, name;
14
+ for (mesh of this.meshes || []) disposeMesh.disposeMesh(this.layer, mesh);
15
+ this.meshes = null;
16
+ this.button.setAttribute('aria-pressed', 'false');
17
+ this.button.style.background = '#fff';
18
+ this.hint.style.display = 'none';
19
+ if (!map || !this.saved) return;
20
+ L.DomEvent.off(map.getContainer(), 'pointerdown pointermove pointerup pointercancel', this.onPointer);
21
+ map.off('terrainchange', this.onTerrain);
22
+ map.options.scrollWheelZoom = this.saved.scrollWheelZoom;
23
+ for (name of this.saved.handlers) map[name].enable();
24
+ map.setView(this.state.latlng, this.saved.zoom, { animate: false });
25
+ map.setPitch(this.saved.pitch);
26
+ this.saved = null;
27
+ }
@@ -0,0 +1,6 @@
1
+ import { start } from './start.js';
2
+ import { stop } from './stop.js';
3
+
4
+ export function toggle() {
5
+ if (this.saved) stop.call(this); else start.call(this);
6
+ }
package/dist/scene/gpu.js DELETED
@@ -1,3 +0,0 @@
1
- import{materialShaders as _}from"../utils/shaders.js";import{emptyNode as U,setParent as w,traverse as G}from"../utils/scene.js";async function B(r,e){let t=L.Layer.types["3d"]._renderers.get(e);if(t?._rendererReady&&await t._rendererReady.promise,!t){const o=Promise.withResolvers();t=r,r._rendererReady=o,o.promise.catch(()=>{}),L.Layer.types["3d"]._renderers.set(e,t);const x=l=>{throw o.reject(l),L.Layer.types["3d"]._renderers.delete(e),l},g=document.createElement("canvas");navigator.gpu||x(new Error("Layer3D requires WebGPU"));const f=await navigator.gpu.requestAdapter().catch(x);f||x(new Error("Unable to acquire a WebGPU adapter"));const i=await f.requestDevice().catch(x);i.addEventListener("uncapturederror",l=>{const p=L.Layer.types["3d"]._renderers.get(e);if(p?.renderer?.device===i)for(const v of p?._layers||[])v.fire("error",{error:l.error})}),i.lost.then(l=>{const p=L.Layer.types["3d"]._renderers.get(e);if(!p||p.renderer?.device!==i)return;const v=new Error(`WebGPU device lost: ${l.message||l.reason}`);for(const c of p._layers)c.fire("error",{error:v})});const u=g.getContext("webgpu");u||(i.destroy(),x(new Error("Unable to create a WebGPU canvas context")));const n=navigator.gpu.getPreferredCanvasFormat();u.configure({device:i,format:n,alphaMode:"premultiplied"}),r._shared=r,r._layers=new Set,r._sceneOrigin=r.location,r.scene=U(),r.camera={position:[0,0,0],up:[0,1,0],target:[0,0,0],viewMatrix:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],projectionMatrix:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],projectionViewMatrix:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],fov:45,aspect:1,near:.1,far:1e4},r.renderer={device:i,context:u,format:n,canvas:g,dpr:Math.min(window.devicePixelRatio,2)},r._initSunlight();const s=document.createElement("canvas");s.width=1,s.height=1,r.renderer.roofFallbackTexture={device:i,texture:i.createTexture({size:[1,1],format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),sampler:i.createSampler({addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"}),image:s,format:"rgba8unorm",srgb:!1,uploaded:null},t._size=null,g.className="leaflet-3d",g.style.cssText="position:absolute;top:0;left:0;pointer-events:none",g.setAttribute("role","img"),g.setAttribute("aria-label",r.options.ariaLabel);let a=e.getPane("webgpuPane");a||(a=e.createPane("webgpuPane",e.getContainer()),a.style.zIndex=450),a.append(g),e.on("move zoom rotate pitch resize viewreset layeradd layerremove",t._onMapChange,t),e.on("zoomstart",t._startZoom,t),e.on("zoomanim",t.update,t),e.on("zoomend",t._endZoom,t),o.resolve(),delete t._rendererReady,t._render(),L.Layer.types["3d"]._renderers.set(e,t)}const y=e.options.crs.project(t._sceneOrigin),h=e.options.crs.project(r.location),d=Math.cos(t._sceneOrigin.lat*Math.PI/180);r._terrainBaseY??=r.root.position[1],r.root.position[0]=(h.x-y.x)*d,r.root.position[1]=r._terrainBaseY,r.root.position[2]=-(h.y-y.y)*d,r._setTerrainHeight(),r.root.scale.fill(d/Math.cos(r.location.lat*Math.PI/180)),r._shared=t,r.renderer=t.renderer,r.scene=t.scene,r.camera=t.camera,t._layers.add(r),w(r.root,t.scene),G(r.root,o=>{if(o.geometry&&o.geometry.device!==t.renderer.device){const x=o.geometry,g=o.program._layerMaterial,f={};for(const u of["position","normal","color","uv","index"]){const n=x.attributes[u];if(!n)continue;const{data:s,size:a,count:l,normalized:p}=n;f[u]={data:s.slice(0,l*a),size:a,normalized:p}}const i=t.renderer.device;f.index?.data instanceof Uint8Array&&(f.index.data=Uint16Array.from(f.index.data));for(const[u,n]of Object.entries(f))n.size||=1,n.count=n.data.length/n.size,n.indexFormat=n.data instanceof Uint32Array?"uint32":"uint16",n.buffer=i.createBuffer({size:Math.max(4,n.data.byteLength),usage:u==="index"?GPUBufferUsage.INDEX|GPUBufferUsage.COPY_DST:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST}),i.queue.writeBuffer(n.buffer,0,n.data);o.geometry={device:i,attributes:f,drawRange:{start:0,count:f.index?.count||f.position.count}};for(const u of Object.values(x.attributes))u.buffer.destroy();o.bindGroup=null,o.boundTextures=[];for(const u of["baseTexture","metalTexture","emissiveTexture","occlusionTexture"]){const n=g[u];!n||n.device===i||(g[u]={...n,device:i,texture:i.createTexture({size:[n.image.width,n.image.height],format:n.format,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),sampler:i.createSampler(n.samplerOptions),uploaded:null})}r._removeProgram(o.program),o.program=r._createProgram(g),o.device=i}o.texture&&o.texture.device!==t.renderer.device&&(o.texture={...o.texture,device:t.renderer.device,texture:t.renderer.device.createTexture({size:[o.texture.image.width,o.texture.image.height],format:o.texture.format,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),sampler:t.renderer.device.createSampler(o.texture.samplerOptions),uploaded:null})}),t.update(),(r.header||r._geojson)&&r._updateArea()}function M(r,e){r.renderer.device.queue.onSubmittedWorkDone().then(()=>e.destroy(),t=>{r.fire("error",{error:t}),e.destroy()})}function R(r,e={}){const t=r.renderer.device,y=!!r.options.nightSparkle,h=_(e,y,e.terrain?L.Layer.types.terrain.elevationWGSL:""),{bindings:d,textured:o,hasTerrain:x}=h,g=t.createShaderModule({code:h.vertex}),f=t.createShaderModule({code:h.fragment});Promise.all([g.getCompilationInfo(),f.getCompilationInfo()]).then(a=>{const l=a.flatMap(p=>p.messages).filter(p=>p.type==="error");l.length&&r.fire("error",{error:new Error(`Unable to compile Layer3D WGSL: ${l.map(p=>p.message).join(`
2
- `)}`)})}).catch(a=>r.fire("error",{error:a}));const i=[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]},{arrayStride:12,attributes:[{shaderLocation:1,offset:0,format:"float32x3"}]},e.vertexColors?{arrayStride:12,attributes:[{shaderLocation:2,offset:0,format:"float32x3"}]}:null,o?{arrayStride:8,attributes:[{shaderLocation:3,offset:0,format:"float32x2"}]}:null],u=[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform",hasDynamicOffset:!0}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}];x&&u.push({binding:2,visibility:GPUShaderStage.VERTEX,texture:{sampleType:"unfilterable-float",viewDimension:"2d"}});for(const a of d)u.push({binding:a.texture,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float",viewDimension:"2d"}}),u.push({binding:a.sampler,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}});const n=t.createBindGroupLayout({entries:u}),s=t.createPipelineLayout({bindGroupLayouts:[n,r.renderer.sunlight.layout]});return{device:t,vertex:g,fragment:f,bindings:d,vertexBuffers:i,bindGroupLayout:n,pipelineLayout:s,pipelineCache:new Map,cullMode:e.doubleSided?"none":"back",transparent:e.alphaMode==="BLEND",depthWrite:e.alphaMode!=="BLEND",depthTest:e.depthTest!==!1,terrain:e.terrain,nightLight:!!e.nightLight,nightSparkle:y,uniforms:{baseColor:{value:e.color||[1,1,1]},metallic:{value:e.metallic??0},roughness:{value:e.roughness??.85},opacity:{value:e.opacity??1},alphaCutoff:{value:e.alphaCutoff??.5},occlusionStrength:{value:e.occlusionStrength??1},emissive:{value:e.emissive||[0,0,0]},...e.baseTexture?{baseTexture:{value:e.baseTexture}}:{},...e.metalTexture?{metalTexture:{value:e.metalTexture}}:{},...e.emissiveTexture?{emissiveTexture:{value:e.emissiveTexture}}:{},...e.occlusionTexture?{occlusionTexture:{value:e.occlusionTexture}}:{},...e.roofTexture?{roofTexture:{value:null}}:{}},_layerMaterial:e}}function C(r){r.pipelineCache.clear()}function D(r,e,t={},y=0){const{device:h}=r.renderer,d={};for(const[x,g]of Object.entries(e)){const f=new Float32Array(g),i=h.createBuffer({size:Math.max(4,f.byteLength),usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST|y});h.queue.writeBuffer(i,0,f),d[x]={size:3,data:f,count:f.length/3,buffer:i}}const o={...U(),device:h,geometry:{device:h,attributes:d,drawRange:{start:0,count:d.position.count}},program:r._createProgram({vertexColors:!0,doubleSided:!0,...t}),id:L.Layer.types["3d"]._nextId++,renderOrder:0,extras:{}};return r.add(o),o}function N(r,e){if(e){r.remove(e);for(const t of Object.values(e.geometry.attributes))t.buffer.destroy();r._removeProgram(e.program)}}function z(r,e,t,y,h){const{geometry:d,program:o}=e,x=r.renderer.device,g=`${y}:${h}`;let f=o.pipelineCache.get(g);f||(f=x.createRenderPipeline({layout:o.pipelineLayout,vertex:{module:o.vertex,entryPoint:"vertexMain",buffers:o.vertexBuffers},fragment:{module:o.fragment,entryPoint:"fragmentMain",targets:[{format:r.renderer.format,blend:o.transparent?{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha",operation:"add"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha",operation:"add"}}:void 0,writeMask:GPUColorWrite.ALL}]},primitive:{topology:"triangle-list",cullMode:y,frontFace:h},depthStencil:{format:"depth24plus",depthWriteEnabled:o.depthWrite,depthCompare:o.depthTest===!1?"always":"less-equal"}}),o.pipelineCache.set(g,f));const i=o.uniforms,u=r.renderer,n=u.uniformSlot++*256,s=u.uniformData,a=n/4;s.set(e.worldMatrix,a),s.set(i.baseColor.value,a+16),s[a+19]=1,s[a+20]=i.metallic.value,s[a+21]=i.roughness.value,s[a+22]=i.opacity.value,s[a+23]=i.alphaCutoff.value,s.set(i.emissive.value,a+24),s[a+27]=i.occlusionStrength.value,s[a+28]=e.terrain?.[0]??0,s[a+29]=e.terrain?.[1]??0,s[a+30]=e.terrain?.[2]??0,s[a+31]=e.terrain?.[3]??0,s[a+32]=e.highlight?.[0]??0,s[a+33]=e.highlight?.[1]??0,s[a+34]=o.nightSparkle?s[55]:0,s[a+35]=0;const l=e._textures||=[];l.length=0;for(const c of o.bindings){const m=i[c.name]?.value;if(!m)throw new Error(`Missing Layer3D texture: ${c.name}`);m.uploaded!==m.image&&(x.queue.copyExternalImageToTexture({source:m.image,flipY:!!m.flipY},{texture:m.texture},[m.image.width,m.image.height]),m.uploaded=m.image),l.push(m)}let p=!e.bindGroup||e.boundBuffer!==u.uniformBuffer||l.length!==e.boundTextures.length;for(let c=0;!p&&c<l.length;c++)(l[c].texture!==e.boundTextures[c][0]||l[c].sampler!==e.boundTextures[c][1])&&(p=!0);if(p){const c=[{binding:0,resource:{buffer:u.uniformBuffer,size:144}},{binding:1,resource:{buffer:u.uniformBuffer,size:240}}];o.terrain&&c.push({binding:2,resource:o.terrain.texture.createView()}),e.boundBuffer=u.uniformBuffer;const m=e.boundTextures||=[];m.length=l.length;for(let T=0;T<l.length;T++){const P=o.bindings[T],b=l[T];c.push({binding:P.texture,resource:b.texture.createView()}),c.push({binding:P.sampler,resource:b.sampler}),m[T]||=[],m[T][0]=b.texture,m[T][1]=b.sampler}e.bindGroup=x.createBindGroup({layout:o.bindGroupLayout,entries:c})}t.setPipeline(f),t.setBindGroup(0,e.bindGroup,[n]),t.setVertexBuffer(0,d.attributes.position.buffer),t.setVertexBuffer(1,d.attributes.normal.buffer),d.attributes.color&&t.setVertexBuffer(2,d.attributes.color.buffer),d.attributes.uv&&t.setVertexBuffer(3,d.attributes.uv.buffer);for(const c of Object.values(d.attributes))c.needsUpdate&&(x.queue.writeBuffer(c.buffer,0,c.data),c.needsUpdate=!1,d.bounds=null);const v=d.attributes.index;v?(t.setIndexBuffer(v.buffer,v.indexFormat),t.drawIndexed(d.drawRange.count,1,d.drawRange.start,0,0)):t.draw(d.drawRange.count,1,d.drawRange.start,0)}export{B as attach,D as createMesh,R as createProgram,M as destroyTexture,N as disposeMesh,z as drawGeometry,C as removeProgram};
3
- //# sourceMappingURL=gpu.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/scene/gpu.js"],
4
- "sourcesContent": ["import { materialShaders } from '../utils/shaders.js';\nimport { emptyNode, setParent, traverse } from '../utils/scene.js';\n\n/** WebGPU device attachment, materials/pipelines and draw calls. */\n/**\n * Join/create this map's shared scene and rebuild GPU objects if its context changed.\n * Buffer/program handles belong to one context; typed arrays and decoded images do not.\n * @private\n */\nexport async function attach(backend, map) {\n let shared = L.Layer.types['3d']._renderers.get(map);\n if (shared?._rendererReady) {\n await shared._rendererReady.promise;\n }\n if (!shared) {\n const rendererReady = Promise.withResolvers();\n shared = backend;\n backend._rendererReady = rendererReady;\n rendererReady.promise.catch(() => {});\n L.Layer.types['3d']._renderers.set(map, shared);\n const fail = error => {\n rendererReady.reject(error);\n L.Layer.types['3d']._renderers.delete(map);\n throw error;\n };\n const canvas = document.createElement('canvas');\n if (!navigator.gpu) fail(new Error('Layer3D requires WebGPU'));\n const adapter = await navigator.gpu.requestAdapter().catch(fail);\n if (!adapter) fail(new Error('Unable to acquire a WebGPU adapter'));\n const device = await adapter.requestDevice().catch(fail);\n device.addEventListener('uncapturederror', event => {\n const owner = L.Layer.types['3d']._renderers.get(map);\n if (owner?.renderer?.device !== device) return;\n for (const layer of owner?._layers || []) layer.fire('error', { error: event.error });\n });\n device.lost.then(info => {\n const owner = L.Layer.types['3d']._renderers.get(map);\n if (!owner || owner.renderer?.device !== device) return;\n const error = new Error(`WebGPU device lost: ${info.message || info.reason}`);\n for (const layer of owner._layers) layer.fire('error', { error });\n });\n const context = canvas.getContext('webgpu');\n if (!context) {\n device.destroy();\n fail(new Error('Unable to create a WebGPU canvas context'));\n }\n const format = navigator.gpu.getPreferredCanvasFormat();\n context.configure({ device, format, alphaMode: 'premultiplied' });\n backend._shared = backend;\n backend._layers = new Set();\n backend._sceneOrigin = backend.location;\n backend.scene = emptyNode();\n // Perspective camera state: fov in degrees, near/far in scene metres.\n backend.camera = {\n position: [0, 0, 0],\n up: [0, 1, 0],\n target: [0, 0, 0],\n viewMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],\n projectionMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],\n projectionViewMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],\n fov: 45,\n aspect: 1,\n near: 0.1,\n far: 10000,\n };\n backend.renderer = { device, context, format, canvas, dpr: Math.min(window.devicePixelRatio, 2) };\n backend._initSunlight();\n const emptyImage = document.createElement('canvas');\n emptyImage.width = 1;\n emptyImage.height = 1;\n backend.renderer.roofFallbackTexture = {\n device,\n texture: device.createTexture({\n size: [1, 1],\n format: 'rgba8unorm',\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,\n }),\n sampler: device.createSampler({\n addressModeU: 'clamp-to-edge', addressModeV: 'clamp-to-edge',\n }),\n image: emptyImage, format: 'rgba8unorm', srgb: false, uploaded: null,\n };\n shared._size = null;\n canvas.className = 'leaflet-3d';\n canvas.style.cssText = 'position:absolute;top:0;left:0;pointer-events:none';\n canvas.setAttribute('role', 'img');\n canvas.setAttribute('aria-label', backend.options.ariaLabel);\n let pane = map.getPane('webgpuPane');\n if (!pane) {\n pane = map.createPane('webgpuPane', map.getContainer());\n pane.style.zIndex = 450;\n }\n pane.append(canvas);\n map.on('move zoom rotate pitch resize viewreset layeradd layerremove', shared._onMapChange, shared);\n map.on('zoomstart', shared._startZoom, shared);\n map.on('zoomanim', shared.update, shared);\n map.on('zoomend', shared._endZoom, shared);\n rendererReady.resolve();\n delete shared._rendererReady;\n shared._render();\n L.Layer.types['3d']._renderers.set(map, shared);\n }\n const origin = map.options.crs.project(shared._sceneOrigin);\n const point = map.options.crs.project(backend.location);\n const metres = Math.cos(shared._sceneOrigin.lat * Math.PI / 180);\n backend._terrainBaseY ??= backend.root.position[1];\n backend.root.position[0] = (point.x - origin.x) * metres;\n backend.root.position[1] = backend._terrainBaseY;\n backend.root.position[2] = -(point.y - origin.y) * metres;\n backend._setTerrainHeight();\n // Each group's metres are measured at its own latitude, not the shared camera origin.\n backend.root.scale.fill(metres / Math.cos(backend.location.lat * Math.PI / 180));\n backend._shared = shared;\n backend.renderer = shared.renderer;\n backend.scene = shared.scene;\n backend.camera = shared.camera;\n shared._layers.add(backend);\n setParent(backend.root, shared.scene);\n traverse(backend.root, object => {\n if (object.geometry && object.geometry.device !== shared.renderer.device) {\n const geometry = object.geometry;\n const material = object.program._layerMaterial;\n // Retain packed CPU attributes, never old-context GPU buffer handles.\n const attributes = {};\n for (const name of ['position', 'normal', 'color', 'uv', 'index']) {\n const attribute = geometry.attributes[name];\n if (!attribute) continue;\n const { data, size, count, normalized } = attribute;\n attributes[name] = { data: data.slice(0, count * size), size, normalized };\n }\n const device = shared.renderer.device;\n if (attributes.index?.data instanceof Uint8Array) {\n attributes.index.data = Uint16Array.from(attributes.index.data);\n }\n for (const [name, attribute] of Object.entries(attributes)) {\n attribute.size ||= 1;\n attribute.count = attribute.data.length / attribute.size;\n attribute.indexFormat = attribute.data instanceof Uint32Array ? 'uint32' : 'uint16';\n attribute.buffer = device.createBuffer({\n size: Math.max(4, attribute.data.byteLength),\n usage: name === 'index'\n ? GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST\n : GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n device.queue.writeBuffer(attribute.buffer, 0, attribute.data);\n }\n object.geometry = {\n device,\n attributes,\n drawRange: { start: 0, count: attributes.index?.count || attributes.position.count },\n };\n for (const attribute of Object.values(geometry.attributes)) attribute.buffer.destroy();\n object.bindGroup = null;\n object.boundTextures = [];\n for (const key of ['baseTexture', 'metalTexture', 'emissiveTexture', 'occlusionTexture']) {\n const texture = material[key];\n if (!texture || texture.device === device) continue;\n material[key] = {\n ...texture,\n device,\n texture: device.createTexture({\n size: [texture.image.width, texture.image.height],\n format: texture.format,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,\n }),\n sampler: device.createSampler(texture.samplerOptions),\n uploaded: null,\n };\n }\n backend._removeProgram(object.program);\n object.program = backend._createProgram(material);\n object.device = device;\n }\n if (object.texture && object.texture.device !== shared.renderer.device) {\n object.texture = {\n ...object.texture,\n device: shared.renderer.device,\n texture: shared.renderer.device.createTexture({\n size: [object.texture.image.width, object.texture.image.height],\n format: object.texture.format,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,\n }),\n sampler: shared.renderer.device.createSampler(object.texture.samplerOptions),\n uploaded: null,\n };\n }\n });\n shared.update();\n if (backend.header || backend._geojson) backend._updateArea();\n}\n\nexport function destroyTexture(backend, texture) {\n backend.renderer.device.queue.onSubmittedWorkDone().then(() => texture.destroy(), error => {\n backend.fire('error', { error });\n texture.destroy();\n });\n}\n\nexport function createProgram(backend, material = {}) {\n const device = backend.renderer.device;\n const sparkle = Boolean(backend.options.nightSparkle);\n const shaders = materialShaders(material, sparkle, material.terrain ? L.Layer.types.terrain.elevationWGSL : '');\n const { bindings, textured, hasTerrain } = shaders;\n const vertex = device.createShaderModule({ code: shaders.vertex });\n const fragment = device.createShaderModule({ code: shaders.fragment });\n Promise.all([vertex.getCompilationInfo(), fragment.getCompilationInfo()]).then(infos => {\n const errors = infos.flatMap(info => info.messages).filter(message => message.type === 'error');\n if (errors.length) {\n backend.fire('error', {\n error: new Error(`Unable to compile Layer3D WGSL: ${errors.map(error => error.message).join('\\n')}`),\n });\n }\n }).catch(error => backend.fire('error', { error }));\n const vertexBuffers = [\n { arrayStride: 12, attributes: [{ shaderLocation: 0, offset: 0, format: 'float32x3' }] },\n { arrayStride: 12, attributes: [{ shaderLocation: 1, offset: 0, format: 'float32x3' }] },\n material.vertexColors ? { arrayStride: 12, attributes: [{ shaderLocation: 2, offset: 0, format: 'float32x3' }] } : null,\n textured ? { arrayStride: 8, attributes: [{ shaderLocation: 3, offset: 0, format: 'float32x2' }] } : null,\n ];\n const bindGroupEntries = [{\n binding: 0,\n visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,\n buffer: { type: 'uniform', hasDynamicOffset: true },\n }, {\n binding: 1,\n visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,\n buffer: { type: 'uniform' },\n }];\n if (hasTerrain) {\n bindGroupEntries.push({\n binding: 2,\n visibility: GPUShaderStage.VERTEX,\n texture: { sampleType: 'unfilterable-float', viewDimension: '2d' },\n });\n }\n for (const texture of bindings) {\n bindGroupEntries.push({\n binding: texture.texture,\n visibility: GPUShaderStage.FRAGMENT,\n texture: { sampleType: 'float', viewDimension: '2d' },\n });\n bindGroupEntries.push({\n binding: texture.sampler,\n visibility: GPUShaderStage.FRAGMENT,\n sampler: { type: 'filtering' },\n });\n }\n const bindGroupLayout = device.createBindGroupLayout({ entries: bindGroupEntries });\n const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout, backend.renderer.sunlight.layout] });\n return {\n device,\n vertex,\n fragment,\n bindings,\n vertexBuffers,\n bindGroupLayout,\n pipelineLayout,\n pipelineCache: new Map(),\n cullMode: material.doubleSided ? 'none' : 'back',\n transparent: material.alphaMode === 'BLEND',\n depthWrite: material.alphaMode !== 'BLEND',\n depthTest: material.depthTest !== false,\n terrain: material.terrain,\n nightLight: Boolean(material.nightLight),\n nightSparkle: sparkle,\n uniforms: {\n baseColor: { value: material.color || [1, 1, 1] },\n metallic: { value: material.metallic ?? 0 },\n roughness: { value: material.roughness ?? 0.85 },\n opacity: { value: material.opacity ?? 1 },\n alphaCutoff: { value: material.alphaCutoff ?? 0.5 },\n occlusionStrength: { value: material.occlusionStrength ?? 1 },\n emissive: { value: material.emissive || [0, 0, 0] },\n ...(material.baseTexture ? { baseTexture: { value: material.baseTexture } } : {}),\n ...(material.metalTexture ? { metalTexture: { value: material.metalTexture } } : {}),\n ...(material.emissiveTexture ? { emissiveTexture: { value: material.emissiveTexture } } : {}),\n ...(material.occlusionTexture ? { occlusionTexture: { value: material.occlusionTexture } } : {}),\n ...(material.roofTexture ? { roofTexture: { value: null } } : {}),\n },\n _layerMaterial: material,\n };\n}\n\nexport function removeProgram(program) {\n program.pipelineCache.clear();\n}\n\n/**\n * Add a non-indexed, vertex-coloured mesh from flat vec3 arrays `{ position, normal, color }` in layer-local metres.\n * `usage` adds GPUBufferUsage flags to the vertex buffers (e.g. STORAGE for compute passes).\n */\nexport function createMesh(backend, data, material = {}, usage = 0) {\n const { device } = backend.renderer, attributes = {};\n for (const [name, values] of Object.entries(data)) {\n const array = new Float32Array(values);\n const buffer = device.createBuffer({ size: Math.max(4, array.byteLength), usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST | usage });\n device.queue.writeBuffer(buffer, 0, array);\n attributes[name] = { size: 3, data: array, count: array.length / 3, buffer };\n }\n const mesh = {\n ...emptyNode(),\n device,\n geometry: { device, attributes, drawRange: { start: 0, count: attributes.position.count } },\n program: backend._createProgram({ vertexColors: true, doubleSided: true, ...material }),\n id: L.Layer.types['3d']._nextId++, renderOrder: 0, extras: {},\n };\n backend.add(mesh);\n return mesh;\n}\n\nexport function disposeMesh(backend, mesh) {\n if (!mesh) return;\n backend.remove(mesh);\n for (const attribute of Object.values(mesh.geometry.attributes)) attribute.buffer.destroy();\n backend._removeProgram(mesh.program);\n}\n\n/** Upload retained CPU data and draw one mesh in the active WebGPU render pass. */\nexport function drawGeometry(backend, mesh, pass, cullMode, frontFace) {\n const { geometry, program } = mesh;\n const device = backend.renderer.device;\n const pipelineKey = `${cullMode}:${frontFace}`;\n let pipeline = program.pipelineCache.get(pipelineKey);\n if (!pipeline) {\n pipeline = device.createRenderPipeline({\n layout: program.pipelineLayout,\n vertex: {\n module: program.vertex,\n entryPoint: 'vertexMain',\n buffers: program.vertexBuffers,\n },\n fragment: {\n module: program.fragment,\n entryPoint: 'fragmentMain',\n targets: [{\n format: backend.renderer.format,\n blend: program.transparent ? {\n color: { srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n } : undefined,\n writeMask: GPUColorWrite.ALL,\n }],\n },\n primitive: { topology: 'triangle-list', cullMode, frontFace },\n depthStencil: {\n format: 'depth24plus',\n depthWriteEnabled: program.depthWrite,\n depthCompare: program.depthTest === false ? 'always' : 'less-equal',\n },\n });\n program.pipelineCache.set(pipelineKey, pipeline);\n }\n\n const uniforms = program.uniforms;\n const renderer = backend.renderer;\n const offset = renderer.uniformSlot++ * 256;\n const data = renderer.uniformData, base = offset / 4;\n data.set(mesh.worldMatrix, base);\n data.set(uniforms.baseColor.value, base + 16);\n data[base + 19] = 1;\n data[base + 20] = uniforms.metallic.value;\n data[base + 21] = uniforms.roughness.value;\n data[base + 22] = uniforms.opacity.value;\n data[base + 23] = uniforms.alphaCutoff.value;\n data.set(uniforms.emissive.value, base + 24);\n data[base + 27] = uniforms.occlusionStrength.value;\n data[base + 28] = mesh.terrain?.[0] ?? 0;\n data[base + 29] = mesh.terrain?.[1] ?? 0;\n data[base + 30] = mesh.terrain?.[2] ?? 0;\n data[base + 31] = mesh.terrain?.[3] ?? 0;\n data[base + 32] = mesh.highlight?.[0] ?? 0;\n data[base + 33] = mesh.highlight?.[1] ?? 0;\n data[base + 34] = program.nightSparkle ? data[55] : 0;\n data[base + 35] = 0;\n\n const textures = mesh._textures ||= [];\n textures.length = 0;\n for (const binding of program.bindings) {\n const texture = uniforms[binding.name]?.value;\n if (!texture) throw new Error(`Missing Layer3D texture: ${binding.name}`);\n if (texture.uploaded !== texture.image) {\n device.queue.copyExternalImageToTexture(\n { source: texture.image, flipY: Boolean(texture.flipY) },\n { texture: texture.texture },\n [texture.image.width, texture.image.height],\n );\n texture.uploaded = texture.image;\n }\n textures.push(texture);\n }\n let bindingsChanged = !mesh.bindGroup || mesh.boundBuffer !== renderer.uniformBuffer ||\n textures.length !== mesh.boundTextures.length;\n for (let i = 0; !bindingsChanged && i < textures.length; i++) {\n if (textures[i].texture !== mesh.boundTextures[i][0] ||\n textures[i].sampler !== mesh.boundTextures[i][1]) bindingsChanged = true;\n }\n if (bindingsChanged) {\n const entries = [\n { binding: 0, resource: { buffer: renderer.uniformBuffer, size: 144 } },\n { binding: 1, resource: { buffer: renderer.uniformBuffer, size: 240 } },\n ];\n if (program.terrain) entries.push({ binding: 2, resource: program.terrain.texture.createView() });\n mesh.boundBuffer = renderer.uniformBuffer;\n const boundTextures = mesh.boundTextures ||= [];\n boundTextures.length = textures.length;\n for (let i = 0; i < textures.length; i++) {\n const binding = program.bindings[i], texture = textures[i];\n entries.push({ binding: binding.texture, resource: texture.texture.createView() });\n entries.push({ binding: binding.sampler, resource: texture.sampler });\n boundTextures[i] ||= [];\n boundTextures[i][0] = texture.texture;\n boundTextures[i][1] = texture.sampler;\n }\n mesh.bindGroup = device.createBindGroup({\n layout: program.bindGroupLayout,\n entries,\n });\n }\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, mesh.bindGroup, [offset]);\n pass.setVertexBuffer(0, geometry.attributes.position.buffer);\n pass.setVertexBuffer(1, geometry.attributes.normal.buffer);\n if (geometry.attributes.color) pass.setVertexBuffer(2, geometry.attributes.color.buffer);\n if (geometry.attributes.uv) pass.setVertexBuffer(3, geometry.attributes.uv.buffer);\n for (const attribute of Object.values(geometry.attributes)) {\n if (!attribute.needsUpdate) continue;\n device.queue.writeBuffer(attribute.buffer, 0, attribute.data);\n attribute.needsUpdate = false;\n geometry.bounds = null;\n }\n const index = geometry.attributes.index;\n if (index) {\n pass.setIndexBuffer(index.buffer, index.indexFormat);\n pass.drawIndexed(geometry.drawRange.count, 1, geometry.drawRange.start, 0, 0);\n } else {\n pass.draw(geometry.drawRange.count, 1, geometry.drawRange.start, 0);\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["materialShaders", "emptyNode", "setParent", "traverse", "attach", "backend", "map", "shared", "rendererReady", "fail", "error", "canvas", "adapter", "device", "event", "owner", "layer", "info", "context", "format", "emptyImage", "pane", "origin", "point", "metres", "object", "geometry", "material", "attributes", "name", "attribute", "data", "size", "count", "normalized", "key", "texture", "destroyTexture", "createProgram", "sparkle", "shaders", "bindings", "textured", "hasTerrain", "vertex", "fragment", "infos", "errors", "message", "vertexBuffers", "bindGroupEntries", "bindGroupLayout", "pipelineLayout", "removeProgram", "program", "createMesh", "usage", "values", "array", "buffer", "mesh", "disposeMesh", "drawGeometry", "pass", "cullMode", "frontFace", "pipelineKey", "pipeline", "uniforms", "renderer", "offset", "base", "textures", "binding", "bindingsChanged", "i", "entries", "boundTextures", "index"]
7
- }
@@ -1,9 +0,0 @@
1
- import{lightGrid as U,worldLights as P}from"../utils/lighting.js";import{computeBounds as T}from"../utils/geometry.js";import{traverse as L,updateCamera as _}from"../utils/scene.js";function O(o){const t=o.renderer.device,a=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"depth"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"comparison"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),s=t.createBuffer({size:80,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),d=t.createSampler({compare:"less-equal",minFilter:"linear",magFilter:"linear"}),u=t.createBuffer({size:32,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});o.renderer.sunlight={layout:a,buffer:s,sampler:d,lights:u,size:0};const r=new Float32Array(20);r.set([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),t.queue.writeBuffer(s,0,r),o._resizeSunlight(1)}function A(o,t){const a=o.renderer.device,s=o.renderer.sunlight;s.size!==t&&(s.texture&&o._destroyTexture(s.texture),s.size=t,s.texture=a.createTexture({size:[t,t],format:"depth32float",usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_SRC}),o._bindSunlight())}function D(o){const t=o.renderer.sunlight;t.bindGroup=o.renderer.device.createBindGroup({layout:t.layout,entries:[{binding:0,resource:{buffer:t.buffer}},{binding:1,resource:t.texture.createView()},{binding:2,resource:t.sampler},{binding:3,resource:{buffer:t.lights}}]})}function z(o){const{device:t,sunlight:a}=o.renderer,s=[];for(const i of o._layers)!i.options.nightLight||!i.root.visible||L(i.root,n=>{if(!n.visible)return!0;n.extras?.lights&&s.push(n)});if(a.lightMeshes?.length===s.length&&s.every((i,n)=>a.lightMeshes[n].mesh===i&&a.lightMeshes[n].lights===i.extras.lights&&i.worldMatrix.every((p,c)=>p===a.lightMeshes[n].matrix[c])))return;const d=s.map(i=>{const n=i._worldLights,p=i.worldMatrix,c=i.extras.lights;if(n?.lights===c&&p.every((S,v)=>S===n.matrix[v]))return n.data;const w=P(c,p);return i._worldLights={lights:c,matrix:[...p],data:w},w}),{data:u,count:r}=U(d,t.limits.maxStorageBufferBindingSize);a.lights.size<u.byteLength&&(o._destroyTexture(a.lights),a.lights=t.createBuffer({size:u.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),o._bindSunlight()),t.queue.writeBuffer(a.lights,0,u),a.lightCount=r,a.lightMeshes=s.map(i=>({mesh:i,lights:i.extras.lights,matrix:[...i.worldMatrix]}))}function F(o,t,a,s){const d=o.renderer,u=d.device,r=d.sunlight;if(!a.length||!s||s.altitude<3){if(!r.enabled)return;const e=new Float32Array(20);e.set([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),u.queue.writeBuffer(r.buffer,0,e),r.enabled=!1;return}const i=new Float32Array(20);r.enabled=!0,o._resizeSunlight(Math.min(2048,u.limits.maxTextureDimension2D));const n=[1/0,1/0,1/0],p=[-1/0,-1/0,-1/0];for(const e of a){e.geometry.bounds||T(e.geometry);const f=e.geometry.bounds,g=new DOMMatrix(e.worldMatrix);for(let l=0;l<8;l++){const h=new DOMPoint(...n.map((y,M)=>l&1<<M?f.max[M]:f.min[M]),1).matrixTransform(g);for(let y=0;y<3;y++){const M=[h.x,h.y,h.z][y]/h.w;n[y]=Math.min(n[y],M),p[y]=Math.max(p[y],M)}}}n[1]=Math.min(0,n[1]);const c=Math.max(100,Math.hypot(...n.map((e,f)=>p[f]-e))),w=n.map((e,f)=>(e+p[f])/2),S={position:w.map((e,f)=>e+s.direction[f]*c*2),target:w,up:[0,0,-1],fov:45,aspect:1,near:1,far:c*5,viewMatrix:[],projectionMatrix:[],projectionViewMatrix:[]};_(S);const v=new DOMMatrix(S.viewMatrix),B=[1/0,1/0,1/0],x=[-1/0,-1/0,-1/0];for(let e=0;e<8;e++){const f=new DOMPoint(...n.map((g,l)=>e&1<<l?p[l]:g),1).matrixTransform(v);[f.x,f.y,f.z].forEach((g,l)=>{B[l]=Math.min(B[l],g-20),x[l]=Math.max(x[l],g+20)})}const b=B.map((e,f)=>x[f]-e),G=new DOMMatrix([2/b[0],0,0,0,0,2/b[1],0,0,0,0,-1/b[2],0,-(x[0]+B[0])/b[0],-(x[1]+B[1])/b[1],x[2]/b[2],1]);if(i.set(G.multiply(v).toFloat32Array()),i[16]=1,u.queue.writeBuffer(r.buffer,0,i),!r.pipeline){r.meshLayout=u.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",hasDynamicOffset:!0}}]}),r.depthLayout=u.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}}]}),r.depthBindGroup=u.createBindGroup({layout:r.depthLayout,entries:[{binding:0,resource:{buffer:r.buffer}}]});const e=u.createShaderModule({code:`
2
- struct Mesh { world: mat4x4<f32> };
3
- @group(0) @binding(0) var<uniform> mesh: Mesh;
4
- @group(1) @binding(0) var<uniform> matrix: mat4x4<f32>;
5
- @vertex fn main(@location(0) position: vec3<f32>) -> @builtin(position) vec4<f32> {
6
- return matrix * mesh.world * vec4<f32>(position, 1.0);
7
- }
8
- `});r.pipeline=u.createRenderPipeline({layout:u.createPipelineLayout({bindGroupLayouts:[r.meshLayout,r.depthLayout]}),vertex:{module:e,entryPoint:"main",buffers:[{arrayStride:12,attributes:[{shaderLocation:0,offset:0,format:"float32x3"}]}]},primitive:{topology:"triangle-list",cullMode:"none"},depthStencil:{format:"depth32float",depthWriteEnabled:!0,depthCompare:"less",depthBias:2,depthBiasSlopeScale:2}})}const m=t.beginRenderPass({colorAttachments:[],depthStencilAttachment:{view:r.texture.createView(),depthClearValue:1,depthLoadOp:"clear",depthStoreOp:"store"}});m.setPipeline(r.pipeline),m.setBindGroup(1,r.depthBindGroup);for(const e of a){const f=d.uniformSlot++*256;d.uniformData.set(e.worldMatrix,f/4),e._shadowBuffer!==d.uniformBuffer&&(e._shadowBuffer=d.uniformBuffer,e._shadowBindGroup=u.createBindGroup({layout:r.meshLayout,entries:[{binding:0,resource:{buffer:d.uniformBuffer,size:64}}]}));for(const h of Object.values(e.geometry.attributes))h.needsUpdate&&(u.queue.writeBuffer(h.buffer,0,h.data),h.needsUpdate=!1);m.setBindGroup(0,e._shadowBindGroup,[f]),m.setVertexBuffer(0,e.geometry.attributes.position.buffer);const g=e.geometry.attributes.index,l=e.geometry.drawRange;g?(m.setIndexBuffer(g.buffer,g.indexFormat),m.drawIndexed(l.count,1,l.start,0,0)):m.draw(l.count,1,l.start,0)}m.end()}export{D as bindSunlight,O as initSunlight,F as renderSunlight,A as resizeSunlight,z as updatePointLights};
9
- //# sourceMappingURL=lighting.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/scene/lighting.js"],
4
- "sourcesContent": ["import { lightGrid, worldLights } from '../utils/lighting.js';\r\nimport { computeBounds } from '../utils/geometry.js';\r\nimport { traverse, updateCamera } from '../utils/scene.js';\r\n\r\n/** Sunlight shadow maps and night point lights. */\r\nexport function initSunlight(backend) {\r\n const device = backend.renderer.device;\r\n const layout = device.createBindGroupLayout({ entries: [\r\n { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: 'uniform' } },\r\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: 'depth' } },\r\n { binding: 2, visibility: GPUShaderStage.FRAGMENT, sampler: { type: 'comparison' } },\r\n { binding: 3, visibility: GPUShaderStage.FRAGMENT, buffer: { type: 'read-only-storage' } },\r\n ] });\r\n const buffer = device.createBuffer({ size: 80, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });\r\n const sampler = device.createSampler({ compare: 'less-equal', minFilter: 'linear', magFilter: 'linear' });\r\n const lights = device.createBuffer({ size: 32, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST });\r\n backend.renderer.sunlight = { layout, buffer, sampler, lights, size: 0 };\r\n const values = new Float32Array(20);\r\n values.set([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);\r\n device.queue.writeBuffer(buffer, 0, values);\r\n backend._resizeSunlight(1);\r\n}\r\n\r\nexport function resizeSunlight(backend, size) {\r\n const device = backend.renderer.device, sun = backend.renderer.sunlight;\r\n if (sun.size === size) return;\r\n if (sun.texture) backend._destroyTexture(sun.texture);\r\n sun.size = size;\r\n sun.texture = device.createTexture({\r\n size: [size, size], format: 'depth32float',\r\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC,\r\n });\r\n backend._bindSunlight();\r\n}\r\n\r\nexport function bindSunlight(backend) {\r\n const sun = backend.renderer.sunlight;\r\n sun.bindGroup = backend.renderer.device.createBindGroup({ layout: sun.layout, entries: [\r\n { binding: 0, resource: { buffer: sun.buffer } },\r\n { binding: 1, resource: sun.texture.createView() },\r\n { binding: 2, resource: sun.sampler },\r\n { binding: 3, resource: { buffer: sun.lights } },\r\n ] });\r\n}\r\n\r\n/** A cached spatial grid limits fragment lighting to nearby lamps, without dropping dense cells. */\r\nexport function updatePointLights(backend) {\r\n const { device, sunlight: sun } = backend.renderer;\r\n const meshes = [];\r\n for (const layer of backend._layers) {\r\n if (!layer.options.nightLight || !layer.root.visible) continue;\r\n traverse(layer.root, mesh => {\r\n if (!mesh.visible) return true;\r\n if (mesh.extras?.lights) meshes.push(mesh);\r\n });\r\n }\r\n if (sun.lightMeshes?.length === meshes.length && meshes.every((mesh, i) => sun.lightMeshes[i].mesh === mesh &&\r\n sun.lightMeshes[i].lights === mesh.extras.lights && mesh.worldMatrix.every((v, j) => v === sun.lightMeshes[i].matrix[j]))) return;\r\n // Per mesh, world-space [x, y, z, radius, r, g, b, intensity] per light: re-packed only when its lights or matrix change.\r\n const packed = meshes.map(mesh => {\r\n const cache = mesh._worldLights, m = mesh.worldMatrix, lights = mesh.extras.lights;\r\n if (cache?.lights === lights && m.every((v, j) => v === cache.matrix[j])) return cache.data;\r\n const values = worldLights(lights, m);\r\n mesh._worldLights = { lights, matrix: [...m], data: values };\r\n return values;\r\n });\r\n const { data, count } = lightGrid(packed, device.limits.maxStorageBufferBindingSize);\r\n if (sun.lights.size < data.byteLength) {\r\n backend._destroyTexture(sun.lights);\r\n sun.lights = device.createBuffer({ size: data.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST });\r\n backend._bindSunlight();\r\n }\r\n device.queue.writeBuffer(sun.lights, 0, data);\r\n sun.lightCount = count;\r\n sun.lightMeshes = meshes.map(mesh => ({ mesh, lights: mesh.extras.lights, matrix: [...mesh.worldMatrix] }));\r\n}\r\n\r\n/** One shared directional depth map. Off-screen but loaded geometry can cast shadows. */\r\nexport function renderSunlight(backend, encoder, meshes, sunlight) {\r\n const renderer = backend.renderer, device = renderer.device, sun = renderer.sunlight;\r\n if (!meshes.length || !sunlight || sunlight.altitude < 3) {\r\n if (!sun.enabled) return;\r\n const values = new Float32Array(20);\r\n values.set([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);\r\n device.queue.writeBuffer(sun.buffer, 0, values);\r\n sun.enabled = false;\r\n return;\r\n }\r\n const values = new Float32Array(20);\r\n sun.enabled = true;\r\n backend._resizeSunlight(Math.min(2048, device.limits.maxTextureDimension2D));\r\n const min = [Infinity, Infinity, Infinity], max = [-Infinity, -Infinity, -Infinity];\r\n for (const mesh of meshes) {\r\n if (!mesh.geometry.bounds) computeBounds(mesh.geometry);\r\n const bounds = mesh.geometry.bounds, matrix = new DOMMatrix(mesh.worldMatrix);\r\n for (let i = 0; i < 8; i++) {\r\n const point = new DOMPoint(...min.map((_, axis) => (i & (1 << axis)) ? bounds.max[axis] : bounds.min[axis]), 1)\r\n .matrixTransform(matrix);\r\n for (let axis = 0; axis < 3; axis++) {\r\n const value = [point.x, point.y, point.z][axis] / point.w;\r\n min[axis] = Math.min(min[axis], value);\r\n max[axis] = Math.max(max[axis], value);\r\n }\r\n }\r\n }\r\n // Include ground receivers below/around the loaded buildings and trees.\r\n min[1] = Math.min(0, min[1]);\r\n const radius = Math.max(100, Math.hypot(...min.map((v, i) => max[i] - v)));\r\n const center = min.map((v, i) => (v + max[i]) / 2);\r\n const lightCamera = {\r\n position: center.map((v, i) => v + sunlight.direction[i] * radius * 2),\r\n target: center, up: [0, 0, -1], fov: 45, aspect: 1, near: 1, far: radius * 5,\r\n viewMatrix: [], projectionMatrix: [], projectionViewMatrix: [],\r\n };\r\n updateCamera(lightCamera);\r\n const view = new DOMMatrix(lightCamera.viewMatrix);\r\n const low = [Infinity, Infinity, Infinity], high = [-Infinity, -Infinity, -Infinity];\r\n for (let i = 0; i < 8; i++) {\r\n const point = new DOMPoint(...min.map((v, axis) => (i & (1 << axis)) ? max[axis] : v), 1).matrixTransform(view);\r\n [point.x, point.y, point.z].forEach((value, axis) => {\r\n low[axis] = Math.min(low[axis], value - 20);\r\n high[axis] = Math.max(high[axis], value + 20);\r\n });\r\n }\r\n const span = low.map((v, i) => high[i] - v);\r\n const projection = new DOMMatrix([\r\n 2 / span[0], 0, 0, 0, 0, 2 / span[1], 0, 0, 0, 0, -1 / span[2], 0,\r\n -(high[0] + low[0]) / span[0], -(high[1] + low[1]) / span[1], high[2] / span[2], 1,\r\n ]);\r\n values.set(projection.multiply(view).toFloat32Array());\r\n values[16] = 1;\r\n device.queue.writeBuffer(sun.buffer, 0, values);\r\n if (!sun.pipeline) {\r\n sun.meshLayout = device.createBindGroupLayout({ entries: [\r\n { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform', hasDynamicOffset: true } },\r\n ] });\r\n // Do not bind the sampled depth texture while it is a render attachment.\r\n sun.depthLayout = device.createBindGroupLayout({ entries: [\r\n { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },\r\n ] });\r\n sun.depthBindGroup = device.createBindGroup({\r\n layout: sun.depthLayout, entries: [{ binding: 0, resource: { buffer: sun.buffer } }],\r\n });\r\n const shader = device.createShaderModule({ code: `\r\n struct Mesh { world: mat4x4<f32> };\r\n @group(0) @binding(0) var<uniform> mesh: Mesh;\r\n @group(1) @binding(0) var<uniform> matrix: mat4x4<f32>;\r\n @vertex fn main(@location(0) position: vec3<f32>) -> @builtin(position) vec4<f32> {\r\n return matrix * mesh.world * vec4<f32>(position, 1.0);\r\n }\r\n ` });\r\n sun.pipeline = device.createRenderPipeline({\r\n layout: device.createPipelineLayout({ bindGroupLayouts: [sun.meshLayout, sun.depthLayout] }),\r\n vertex: { module: shader, entryPoint: 'main', buffers: [\r\n { arrayStride: 12, attributes: [{ shaderLocation: 0, offset: 0, format: 'float32x3' }] },\r\n ] },\r\n primitive: { topology: 'triangle-list', cullMode: 'none' },\r\n depthStencil: { format: 'depth32float', depthWriteEnabled: true, depthCompare: 'less',\r\n depthBias: 2, depthBiasSlopeScale: 2 },\r\n });\r\n }\r\n const pass = encoder.beginRenderPass({\r\n colorAttachments: [],\r\n depthStencilAttachment: { view: sun.texture.createView(), depthClearValue: 1,\r\n depthLoadOp: 'clear', depthStoreOp: 'store' },\r\n });\r\n pass.setPipeline(sun.pipeline);\r\n pass.setBindGroup(1, sun.depthBindGroup);\r\n for (const mesh of meshes) {\r\n const offset = renderer.uniformSlot++ * 256;\r\n renderer.uniformData.set(mesh.worldMatrix, offset / 4);\r\n if (mesh._shadowBuffer !== renderer.uniformBuffer) {\r\n mesh._shadowBuffer = renderer.uniformBuffer;\r\n mesh._shadowBindGroup = device.createBindGroup({ layout: sun.meshLayout, entries: [\r\n { binding: 0, resource: { buffer: renderer.uniformBuffer, size: 64 } },\r\n ] });\r\n }\r\n for (const attribute of Object.values(mesh.geometry.attributes)) {\r\n if (attribute.needsUpdate) {\r\n device.queue.writeBuffer(attribute.buffer, 0, attribute.data);\r\n attribute.needsUpdate = false;\r\n }\r\n }\r\n pass.setBindGroup(0, mesh._shadowBindGroup, [offset]);\r\n pass.setVertexBuffer(0, mesh.geometry.attributes.position.buffer);\r\n const index = mesh.geometry.attributes.index, range = mesh.geometry.drawRange;\r\n if (index) {\r\n pass.setIndexBuffer(index.buffer, index.indexFormat);\r\n pass.drawIndexed(range.count, 1, range.start, 0, 0);\r\n } else pass.draw(range.count, 1, range.start, 0);\r\n }\r\n pass.end();\r\n}\r\n"],
5
- "mappings": "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",
6
- "names": ["lightGrid", "worldLights", "computeBounds", "traverse", "updateCamera", "initSunlight", "backend", "device", "layout", "buffer", "sampler", "lights", "values", "resizeSunlight", "size", "sun", "bindSunlight", "updatePointLights", "meshes", "layer", "mesh", "i", "v", "j", "packed", "cache", "m", "data", "count", "renderSunlight", "encoder", "sunlight", "renderer", "min", "max", "bounds", "matrix", "point", "_", "axis", "value", "radius", "center", "lightCamera", "view", "low", "high", "span", "projection", "shader", "pass", "offset", "attribute", "index", "range"]
7
- }
@@ -1,2 +0,0 @@
1
- import{decodeModel as I,readAccessor as F,nodeMatrix as M,vertexNormals as _,textureSampler as z}from"../utils/model.js";import{emptyNode as v,setParent as x}from"../utils/scene.js";async function D(o){await o._added.promise;const g=new URL(o.modelUrl,document.baseURI).href,T=await fetch(g);if(!T.ok)throw new Error(`Unable to load model: HTTP ${T.status}`);const R=await T.arrayBuffer(),i=I(R),E=new URL(".",g).href;await Promise.all((i.buffers||[]).map(async e=>{if(e.binary)return;const t=await fetch(new URL(e.uri,E).href);if(!t.ok)throw new Error(`Unable to load model buffer: HTTP ${t.status}`);e.binary=await t.arrayBuffer()})),await o._added.promise;const A=await Promise.all((i.images||[]).map(async e=>{let t;if(e.bufferView!==void 0){const s=i.bufferViews[e.bufferView],f=i.buffers[s.buffer].binary;t=new Blob([f.slice(s.byteOffset||0,(s.byteOffset||0)+s.byteLength)],{type:e.mimeType})}else{const s=await fetch(new URL(e.uri,E).href);if(!s.ok)throw new Error(`Unable to load model texture: HTTP ${s.status}`);t=await s.blob()}return createImageBitmap(t,{premultiplyAlpha:"none",colorSpaceConversion:"none"})})),y=new Map,p=(e,t=!1)=>{if(!e)return null;if((e.texCoord||0)!==0||e.extensions)throw new Error("Model textures currently require untransformed TEXCOORD_0 UVs");const s=o.renderer.device,f=`${e.index}:${t}`;if(!y.has(f)){const d=i.textures[e.index],l=i.samplers?.[d.sampler]||{},u=A[d.source],c=t?"rgba8unorm-srgb":"rgba8unorm",r=z(l);y.set(f,{device:s,texture:s.createTexture({size:[u.width,u.height],format:c,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),sampler:s.createSampler(r),samplerOptions:r,format:c,srgb:t,image:u,flipY:!1,uploaded:null})}return y.get(f)},B=(i.materials||[]).map(e=>{const t=e.pbrMetallicRoughness||{};return{color:(t.baseColorFactor||[1,1,1,1]).slice(0,3),opacity:t.baseColorFactor?.[3]??1,metallic:t.metallicFactor??1,roughness:t.roughnessFactor??1,baseTexture:p(t.baseColorTexture,!0),metalTexture:p(t.metallicRoughnessTexture),emissiveTexture:p(e.emissiveTexture,!0),occlusionTexture:p(e.occlusionTexture),emissive:e.emissiveFactor||[0,0,0],occlusionStrength:e.occlusionTexture?.strength??1,alphaMode:e.alphaMode||"OPAQUE",alphaCutoff:e.alphaCutoff??.5,doubleSided:e.doubleSided}});let U;{const e=new Set,t=[],s=d=>{if(e.has(d))throw new Error("Cyclic glTF nodes");const l=i.nodes[d];if(!l)throw new Error("Invalid glTF node");e.add(d);const u={...v(),name:l.name};if(u.matrix=M(l),l.mesh!==void 0)for(const c of i.meshes[l.mesh].primitives){const r={};for(const[a,n]of[["POSITION","position"],["NORMAL","normal"],["TEXCOORD_0","uv"]])c.attributes[a]!==void 0&&(r[n]=F(i,c.attributes[a]));if(!r.position)throw new Error("glTF mesh has no positions");const h=r.position.data.length/3;if(r.position.size!==3||h<3||Object.values(r).some(a=>a.data.length/a.size!==h))throw new Error("Invalid glTF vertex attributes");if(c.indices!==void 0){const a=F(i,c.indices);if(r.index={size:1,data:a.indices},![Uint8Array,Uint16Array,Uint32Array].some(n=>a.indices instanceof n)||a.size!==1||a.indices.length%3||[...a.indices].some(n=>n>=h))throw new Error("Invalid glTF triangle indices")}if(!r.index&&h%3)throw new Error("Incomplete glTF triangle");if(!r.normal){const a=_(r.position.data,r.index?.data);r.normal={size:3,data:a}}const m=B[c.material]||{color:[1,1,1],metallic:1};if([m.baseTexture,m.metalTexture,m.emissiveTexture,m.occlusionTexture].some(Boolean)&&!r.uv)throw new Error("Textured model mesh requires UV coordinates");const O=o._createProgram(m);t.push(O);const w=o.renderer.device;r.index?.data instanceof Uint8Array&&(r.index.data=Uint16Array.from(r.index.data));for(const[a,n]of Object.entries(r))n.size||=1,n.count=n.data.length/n.size,n.indexFormat=n.data instanceof Uint32Array?"uint32":"uint16",n.buffer=w.createBuffer({size:Math.max(4,n.data.byteLength),usage:a==="index"?GPUBufferUsage.INDEX|GPUBufferUsage.COPY_DST:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST}),w.queue.writeBuffer(n.buffer,0,n.data);const C={device:w,attributes:r,drawRange:{start:0,count:r.index?.count||r.position.count}};t.push(C);const b={...v(),device:w,geometry:C,program:O,id:L.Layer.types["3d"]._nextId++,renderOrder:0};b.name=i.meshes[l.mesh].name,b.extras=l.extras||{},x(b,u)}for(const c of l.children||[])x(s(c),u);return e.delete(d),u},f=i.scenes?.[i.scene||0];if(!f)throw new Error("Missing glTF scene");try{U=f.nodes.map(s)}catch(d){for(const l of t)if(l.attributes)for(const u of Object.values(l.attributes))u.buffer.destroy();else o._removeProgram(l);throw d}}const P={...v(),id:g,extras:i.extras||{}};if(!U.length)throw new Error("Expected a glTF model with a non-empty scene");for(const e of U)x(e,P);if(o.model=P,o.options.rotation){const[e,t=e,s=e]=o.options.rotation;o.model.rotation[0]=e,o.model.rotation[1]=t,o.model.rotation[2]=s}if(o.options.scale){const[e,t=e,s=e]=o.options.scale;o.model.scale[0]=e,o.model.scale[1]=t,o.model.scale[2]=s}x(o.model,o.root)}export{D as loadModel};
2
- //# sourceMappingURL=model.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/scene/model.js"],
4
- "sourcesContent": ["import { decodeModel, readAccessor, nodeMatrix, vertexNormals, textureSampler } from '../utils/model.js';\nimport { emptyNode, setParent } from '../utils/scene.js';\n\n/** glTF/GLB model loading. */\n/** Load the configured GLB/glTF (static triangles) under `root`; GPU resources need attachment. */\nexport async function loadModel(backend) {\n await backend._added.promise;\n const url = new URL(backend.modelUrl, document.baseURI).href;\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Unable to load model: HTTP ${response.status}`);\n }\n const data = await response.arrayBuffer();\n const description = decodeModel(data);\n const directory = new URL('.', url).href;\n await Promise.all((description.buffers || []).map(async buffer => {\n if (buffer.binary) {\n return;\n }\n const response = await fetch(new URL(buffer.uri, directory).href);\n if (!response.ok) {\n throw new Error(`Unable to load model buffer: HTTP ${response.status}`);\n }\n buffer.binary = await response.arrayBuffer();\n }));\n await backend._added.promise;\n const images = await Promise.all((description.images || []).map(async image => {\n let blob;\n if (image.bufferView !== undefined) {\n const view = description.bufferViews[image.bufferView];\n const buffer = description.buffers[view.buffer].binary;\n blob = new Blob([buffer.slice(view.byteOffset || 0, (view.byteOffset || 0) + view.byteLength)],\n { type: image.mimeType });\n } else {\n const response = await fetch(new URL(image.uri, directory).href);\n if (!response.ok) throw new Error(`Unable to load model texture: HTTP ${response.status}`);\n blob = await response.blob();\n }\n // Preserve straight alpha and raw samples; GPU sRGB formats do color decoding.\n return createImageBitmap(blob, { premultiplyAlpha: 'none', colorSpaceConversion: 'none' });\n }));\n const textures = new Map();\n const textureFor = (reference, color = false) => {\n if (!reference) return null;\n if ((reference.texCoord || 0) !== 0 || reference.extensions) {\n throw new Error('Model textures currently require untransformed TEXCOORD_0 UVs');\n }\n const device = backend.renderer.device;\n // A glTF image may serve both color and data maps: those cannot share a GPU format.\n const key = `${reference.index}:${color}`;\n if (!textures.has(key)) {\n const texture = description.textures[reference.index];\n const sampler = description.samplers?.[texture.sampler] || {};\n const image = images[texture.source];\n const format = color ? 'rgba8unorm-srgb' : 'rgba8unorm';\n const samplerOptions = textureSampler(sampler);\n textures.set(key, {\n device,\n texture: device.createTexture({\n size: [image.width, image.height],\n format,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,\n }),\n sampler: device.createSampler(samplerOptions),\n samplerOptions,\n format,\n srgb: color,\n image,\n flipY: false,\n uploaded: null,\n });\n }\n return textures.get(key);\n };\n // Convert glTF materials directly to the shader's retained CPU styles.\n const materials = (description.materials || []).map(material => {\n const pbr = material.pbrMetallicRoughness || {};\n return {\n color: (pbr.baseColorFactor || [1, 1, 1, 1]).slice(0, 3),\n opacity: pbr.baseColorFactor?.[3] ?? 1,\n metallic: pbr.metallicFactor ?? 1,\n roughness: pbr.roughnessFactor ?? 1,\n baseTexture: textureFor(pbr.baseColorTexture, true),\n metalTexture: textureFor(pbr.metallicRoughnessTexture),\n emissiveTexture: textureFor(material.emissiveTexture, true),\n occlusionTexture: textureFor(material.occlusionTexture),\n emissive: material.emissiveFactor || [0, 0, 0],\n occlusionStrength: material.occlusionTexture?.strength ?? 1,\n alphaMode: material.alphaMode || 'OPAQUE',\n alphaCutoff: material.alphaCutoff ?? 0.5,\n doubleSided: material.doubleSided,\n };\n });\n let nodes;\n {\n // Track only the recursion path: shared mesh references are valid, cycles are not.\n const active = new Set(), resources = [];\n const node = index => {\n if (active.has(index)) throw new Error('Cyclic glTF nodes');\n const spec = description.nodes[index];\n if (!spec) throw new Error('Invalid glTF node');\n active.add(index);\n const group = {\n ...emptyNode(),\n name: spec.name\n };\n group.matrix = nodeMatrix(spec);\n if (spec.mesh !== undefined) {\n for (const primitive of description.meshes[spec.mesh].primitives) {\n const attributes = {};\n for (const [semantic, name] of [['POSITION', 'position'], ['NORMAL', 'normal'], ['TEXCOORD_0', 'uv']]) {\n if (primitive.attributes[semantic] !== undefined) attributes[name] = readAccessor(description, primitive.attributes[semantic]);\n }\n if (!attributes.position) throw new Error('glTF mesh has no positions');\n const vertexCount = attributes.position.data.length / 3;\n if (attributes.position.size !== 3 || vertexCount < 3 ||\n Object.values(attributes).some(attribute => attribute.data.length / attribute.size !== vertexCount)) throw new Error('Invalid glTF vertex attributes');\n if (primitive.indices !== undefined) {\n const index = readAccessor(description, primitive.indices);\n attributes.index = { size: 1, data: index.indices };\n if (![Uint8Array, Uint16Array, Uint32Array].some(Type => index.indices instanceof Type) ||\n index.size !== 1 || index.indices.length % 3 || [...index.indices].some(i => i >= vertexCount)) throw new Error('Invalid glTF triangle indices');\n }\n if (!attributes.index && vertexCount % 3) throw new Error('Incomplete glTF triangle');\n if (!attributes.normal) {\n const normals = vertexNormals(attributes.position.data, attributes.index?.data);\n attributes.normal = { size: 3, data: normals };\n }\n const style = materials[primitive.material] || { color: [1, 1, 1], metallic: 1 };\n if ([style.baseTexture, style.metalTexture, style.emissiveTexture, style.occlusionTexture].some(Boolean) && !attributes.uv) {\n throw new Error('Textured model mesh requires UV coordinates');\n }\n const program = backend._createProgram(style);\n resources.push(program);\n const device = backend.renderer.device;\n if (attributes.index?.data instanceof Uint8Array) {\n attributes.index.data = Uint16Array.from(attributes.index.data);\n }\n for (const [name, attribute] of Object.entries(attributes)) {\n attribute.size ||= 1;\n attribute.count = attribute.data.length / attribute.size;\n attribute.indexFormat = attribute.data instanceof Uint32Array ? 'uint32' : 'uint16';\n attribute.buffer = device.createBuffer({\n size: Math.max(4, attribute.data.byteLength),\n usage: name === 'index'\n ? GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST\n : GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n device.queue.writeBuffer(attribute.buffer, 0, attribute.data);\n }\n const geometry = {\n device,\n attributes,\n drawRange: { start: 0, count: attributes.index?.count || attributes.position.count },\n };\n resources.push(geometry);\n const mesh = {\n ...emptyNode(),\n device,\n geometry,\n program,\n id: L.Layer.types['3d']._nextId++,\n renderOrder: 0\n };\n mesh.name = description.meshes[spec.mesh].name; mesh.extras = spec.extras || {};\n setParent(mesh, group);\n }\n }\n for (const child of spec.children || []) setParent(node(child), group);\n active.delete(index);\n return group;\n };\n const scene = description.scenes?.[description.scene || 0];\n if (!scene) throw new Error('Missing glTF scene');\n try {\n nodes = scene.nodes.map(node);\n } catch (error) {\n // Parsing can fail after earlier primitives allocated buffers/programs.\n for (const resource of resources) {\n if (resource.attributes) {\n for (const attribute of Object.values(resource.attributes)) attribute.buffer.destroy();\n } else backend._removeProgram(resource);\n }\n throw error;\n }\n }\n const model = {\n ...emptyNode(),\n id: url,\n extras: description.extras || {},\n };\n if (!nodes.length) throw new Error('Expected a glTF model with a non-empty scene');\n for (const node of nodes) setParent(node, model);\n backend.model = model;\n if (backend.options.rotation) {\n const [x, y = x, z = x] = backend.options.rotation;\n backend.model.rotation[0] = x; backend.model.rotation[1] = y; backend.model.rotation[2] = z;\n }\n if (backend.options.scale) {\n const [x, y = x, z = x] = backend.options.scale;\n backend.model.scale[0] = x; backend.model.scale[1] = y; backend.model.scale[2] = z;\n }\n setParent(backend.model, backend.root);\n}\n"],
5
- "mappings": "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",
6
- "names": ["decodeModel", "readAccessor", "nodeMatrix", "vertexNormals", "textureSampler", "emptyNode", "setParent", "loadModel", "backend", "url", "response", "data", "description", "directory", "buffer", "images", "image", "blob", "view", "textures", "textureFor", "reference", "color", "device", "key", "texture", "sampler", "format", "samplerOptions", "materials", "material", "pbr", "nodes", "active", "resources", "node", "index", "spec", "group", "primitive", "attributes", "semantic", "name", "vertexCount", "attribute", "Type", "i", "normals", "style", "program", "geometry", "mesh", "child", "scene", "error", "resource", "model", "x", "y", "z"]
7
- }
@@ -1,2 +0,0 @@
1
- import{intersectMeshes as p}from"../utils/picking.js";import{traverse as c,updateWorldMatrix as m,updateCamera as y}from"../utils/scene.js";function v(t,e,r=t.root.children,o=!0){if(!t.renderer)return[];const s=t._map.getContainer().getBoundingClientRect();m(t.scene),y(t.camera);const n=new DOMMatrix(t.camera.projectionViewMatrix).inverse();if(![...n.toFloat64Array()].every(Number.isFinite))throw new Error("Singular 3D transform");t.raycaster.origin[0]=t.camera.position[0],t.raycaster.origin[1]=t.camera.position[1],t.raycaster.origin[2]=t.camera.position[2];const l=new DOMPoint((e.clientX-s.left)/s.width*2-1,-((e.clientY-s.top)/s.height)*2+1,0,1).matrixTransform(n),u=[l.x/l.w,l.y/l.w,l.z/l.w];t.raycaster.direction[0]=u[0]-t.raycaster.origin[0],t.raycaster.direction[1]=u[1]-t.raycaster.origin[1],t.raycaster.direction[2]=u[2]-t.raycaster.origin[2];const f=Math.hypot(...t.raycaster.direction)||1;t.raycaster.direction[0]/=f,t.raycaster.direction[1]/=f,t.raycaster.direction[2]/=f;const a=[];for(const h of r)o?c(h,g=>{g.geometry&&g.visible&&a.push(g)}):h.geometry&&h.visible&&a.push(h);return p(t.raycaster,a,t.renderer.uniformData?.[55])}function _(t,e){if(!t.root||!t.camera)return null;for(const r of t.raycast(e,t.root.children,!!t.model)){if(t.model){let i=r.object;for(;i&&i!==t.model;)i=i.parent;if(i===t.model)return{id:t.model.id,properties:t.model.extras,model:t.model,mesh:r.object,point:r.point}}const o=r.object.extras?.featureFaces;if(!o)continue;let s=0,n=o.length-1;for(;s<=n;){const i=s+n>>1,l=o[i];if(r.faceIndex<l.faceStart)n=i-1;else if(r.faceIndex>=l.faceEnd)s=i+1;else return{...l,mesh:r.object,point:r.point}}}return null}function w(t,e){e?.model&&(e=null),!(t.highlightedFeature?.mesh===e?.mesh&&t.highlightedFeature?.vertexStart===e?.vertexStart)&&(t.highlightedFeature&&(t.highlightedFeature.mesh.highlight=null),t.highlightedFeature=e,e&&(e.mesh.highlight=[e.vertexStart,e.vertexEnd]),t.update())}function d(t,e,r){const o=t._tooltip;if(!o)return;if(e){o.replaceChildren(t.options.tooltipContent(e)),o.hidden=!1;const n=t.container.getBoundingClientRect(),i=r.clientX-n.left,l=r.clientY-n.top;o.style.left=`${i+o.offsetWidth+16>n.width?i-o.offsetWidth-12:i+12}px`,o.style.top=`${l+o.offsetHeight+16>n.height?l-o.offsetHeight-12:l+12}px`}else o.hidden=!0;const s=t._shared;s&&([...s._layers].some(i=>i._tooltip&&!i._tooltip.hidden)?(s._cursor===void 0&&(s._cursor=t.container.style.cursor),t.container.style.cursor="pointer"):s._cursor!==void 0&&(t.container.style.cursor=s._cursor,delete s._cursor))}function C(t,e){t.hoveredFeature=t._findFeature(e),t._setHighlight(t.hoveredFeature),t._showFeature(t.hoveredFeature,e),t.fire("featurehover",{feature:t.hoveredFeature,originalEvent:e})}function j(t,e){const r=t._findFeature(e);t.hoveredFeature=r,t._setHighlight(r),t._showFeature(r,e),t.fire("featureclick",{feature:r,originalEvent:e})}function M(t){t.hoveredFeature=null,t._setHighlight(null),t._showFeature(null),t.fire("featurehover",{feature:null})}export{_ as findFeature,j as onClick,M as onPointerLeave,C as onPointerMove,v as raycast,w as setHighlight,d as showFeature};
2
- //# sourceMappingURL=picking.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/scene/picking.js"],
4
- "sourcesContent": ["import { intersectMeshes } from '../utils/picking.js';\r\nimport { traverse, updateWorldMatrix, updateCamera } from '../utils/scene.js';\r\n\r\n/** Raycasting, hover/click highlight and tooltips. */\r\n/**\r\n * Finds the objects under a mouse or pointer event, nearest first.\r\n *\r\n * @param {MouseEvent} event\r\n * @param {Object[]} [objects] Defaults to this layer's root children, not all map layers.\r\n * @param {boolean} [recursive] Also test the descendants of `objects`.\r\n * @returns {Object[]} Nearest hit per mesh: object, shared-world point/distance and triangle faceIndex.\r\n */\r\nexport function raycast(backend, event, objects = backend.root.children, recursive = true) {\r\n if (!backend.renderer) {\r\n return [];\r\n }\r\n const rect = backend._map.getContainer().getBoundingClientRect();\r\n updateWorldMatrix(backend.scene);\r\n updateCamera(backend.camera);\r\n // Unproject the mouse (-1..1) into a world-space ray from the camera.\r\n const inverseCamera = new DOMMatrix(backend.camera.projectionViewMatrix).inverse();\r\n const inverseCameraValues = inverseCamera.toFloat64Array();\r\n if (![...inverseCameraValues].every(Number.isFinite)) {\r\n throw new Error('Singular 3D transform');\r\n }\r\n backend.raycaster.origin[0] = backend.camera.position[0];\r\n backend.raycaster.origin[1] = backend.camera.position[1];\r\n backend.raycaster.origin[2] = backend.camera.position[2];\r\n const unprojected = new DOMPoint(\r\n ((event.clientX - rect.left) / rect.width) * 2 - 1,\r\n -((event.clientY - rect.top) / rect.height) * 2 + 1,\r\n 0,\r\n 1\r\n ).matrixTransform(inverseCamera);\r\n const end = [\r\n unprojected.x / unprojected.w,\r\n unprojected.y / unprojected.w,\r\n unprojected.z / unprojected.w\r\n ];\r\n backend.raycaster.direction[0] = end[0] - backend.raycaster.origin[0];\r\n backend.raycaster.direction[1] = end[1] - backend.raycaster.origin[1];\r\n backend.raycaster.direction[2] = end[2] - backend.raycaster.origin[2];\r\n const rayLength = Math.hypot(...backend.raycaster.direction) || 1;\r\n backend.raycaster.direction[0] /= rayLength;\r\n backend.raycaster.direction[1] /= rayLength;\r\n backend.raycaster.direction[2] /= rayLength;\r\n const meshes = [];\r\n for (const object of objects) {\r\n if (recursive) traverse(object, mesh => { if\r\n (mesh.geometry && mesh.visible) meshes.push(mesh);\r\n });\r\n else if (object.geometry && object.visible) meshes.push(object);\r\n }\r\n return intersectMeshes(backend.raycaster, meshes, backend.renderer.uniformData?.[55]);\r\n}\r\n\r\n/**\r\n * Translate a geometry hit into a configured model or batched source feature.\r\n * Sorted half-open face ranges permit binary search without a feature per triangle.\r\n * @returns {PickedFeature|null}\r\n */\r\nexport function findFeature(backend, event) {\r\n if (!backend.root || !backend.camera) return null;\r\n for (const hit of backend.raycast(event, backend.root.children, Boolean(backend.model))) {\r\n if (backend.model) {\r\n let object = hit.object;\r\n while (object && object !== backend.model) object = object.parent;\r\n if (object === backend.model) {\r\n return {\r\n id: backend.model.id, properties: backend.model.extras,\r\n model: backend.model, mesh: hit.object, point: hit.point\r\n };\r\n }\r\n }\r\n const ranges = hit.object.extras?.featureFaces;\r\n if (!ranges) continue;\r\n let low = 0, high = ranges.length - 1;\r\n while (low <= high) {\r\n const middle = (low + high) >> 1;\r\n const range = ranges[middle];\r\n if (hit.faceIndex < range.faceStart) high = middle - 1;\r\n else if (hit.faceIndex >= range.faceEnd) low = middle + 1;\r\n else return { ...range, mesh: hit.object, point: hit.point };\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n/** Highlight a source vertex range in the shader; vertex colors stay untouched. */\r\nexport function setHighlight(backend, feature) {\r\n if (feature?.model) feature = null;\r\n if (backend.highlightedFeature?.mesh === feature?.mesh &&\r\n backend.highlightedFeature?.vertexStart === feature?.vertexStart) return;\r\n if (backend.highlightedFeature) backend.highlightedFeature.mesh.highlight = null;\r\n backend.highlightedFeature = feature;\r\n if (feature) feature.mesh.highlight = [feature.vertexStart, feature.vertexEnd];\r\n backend.update();\r\n}\r\n\r\n/** Update tooltip content/position and arbitrate cursor ownership across shared layers. */\r\nexport function showFeature(backend, feature, event) {\r\n const tooltip = backend._tooltip;\r\n if (!tooltip) return;\r\n if (feature) {\r\n tooltip.replaceChildren(backend.options.tooltipContent(feature));\r\n tooltip.hidden = false;\r\n const rect = backend.container.getBoundingClientRect();\r\n const x = event.clientX - rect.left, y = event.clientY - rect.top;\r\n tooltip.style.left = `${x + tooltip.offsetWidth + 16 > rect.width ? x - tooltip.offsetWidth - 12 : x + 12}px`;\r\n tooltip.style.top = `${y + tooltip.offsetHeight + 16 > rect.height ? y - tooltip.offsetHeight - 12 : y + 12}px`;\r\n } else {\r\n tooltip.hidden = true;\r\n }\r\n const shared = backend._shared;\r\n if (shared) {\r\n const visible = [...shared._layers].some(layer => layer._tooltip && !layer._tooltip.hidden);\r\n if (visible) {\r\n if (shared._cursor === undefined) shared._cursor = backend.container.style.cursor;\r\n backend.container.style.cursor = 'pointer';\r\n } else if (shared._cursor !== undefined) {\r\n backend.container.style.cursor = shared._cursor;\r\n delete shared._cursor;\r\n }\r\n }\r\n}\r\n\r\n/** Hover is transient; featurehover also reports misses with feature:null. */\r\nexport function onPointerMove(backend, event) {\r\n backend.hoveredFeature = backend._findFeature(event);\r\n backend._setHighlight(backend.hoveredFeature);\r\n backend._showFeature(backend.hoveredFeature, event);\r\n backend.fire('featurehover', { feature: backend.hoveredFeature, originalEvent: event });\r\n}\r\n\r\n/** Emit click without moving the map or pinning the tooltip. */\r\nexport function onClick(backend, event) {\r\n const feature = backend._findFeature(event);\r\n backend.hoveredFeature = feature;\r\n backend._setHighlight(feature);\r\n backend._showFeature(feature, event);\r\n backend.fire('featureclick', { feature, originalEvent: event });\r\n}\r\n\r\n/** Clear hover, highlight and tooltip without retaining a selected feature. */\r\nexport function onPointerLeave(backend) {\r\n backend.hoveredFeature = null;\r\n backend._setHighlight(null);\r\n backend._showFeature(null);\r\n backend.fire('featurehover', { feature: null });\r\n}\r\n"],
5
- "mappings": "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",
6
- "names": ["intersectMeshes", "traverse", "updateWorldMatrix", "updateCamera", "raycast", "backend", "event", "objects", "recursive", "rect", "inverseCamera", "unprojected", "end", "rayLength", "meshes", "object", "mesh", "findFeature", "hit", "ranges", "low", "high", "middle", "range", "setHighlight", "feature", "showFeature", "tooltip", "x", "y", "shared", "layer", "onPointerMove", "onClick", "onPointerLeave"]
7
- }
@@ -1,2 +0,0 @@
1
- import{decodeHeader as I,decodeDirectory as T,decompress as m,tileId as p}from"../utils/pmtiles.js";async function P(e,r,s,f){if(f?.throwIfAborted(),!Number.isSafeInteger(r)||!Number.isSafeInteger(s)||r<0||s<=0||!Number.isSafeInteger(r+s))throw new Error("Invalid PMTiles byte range");const i=await fetch(e.url,{headers:{Range:`bytes=${r}-${r+s-1}`},signal:f});if(!i.ok)throw new Error(`Unable to read PMTiles: HTTP ${i.status}`);const a=i.headers.get("ETag");if(e._etag&&a!==e._etag)throw new Error("PMTiles archive changed; recreate the layer");a&&(e._etag=a);let t=await i.arrayBuffer();if(i.status===200)t=t.slice(r,r+s);else if(i.status!==206||!i.headers.get("Content-Range")?.startsWith(`bytes ${r}-${r+s-1}/`))throw new Error("Invalid PMTiles range response");if(t.byteLength!==s)throw new Error("Truncated PMTiles range");return t}function M(e){return e._header||=e._read(0,127).then(I)}async function x(e,r,s,f,i){const a=p(r,s,f);i?.throwIfAborted();const t=await e.getHeader();if(i?.throwIfAborted(),r<t.minZoom||r>t.maxZoom)return;let d=t.rootDirectoryOffset,c=t.rootDirectoryLength;const y=new Set;for(let _=0;_<4;_++){if(y.has(d))throw new Error("Cyclic PMTiles directory");y.add(d);const h=`${d}:${c}`;if(!e._directories.has(h)){e._directories.size>=32&&e._directories.delete(e._directories.keys().next().value);const n=e._read(d,c).then(u=>m(u,t.internalCompression)).then(T).catch(u=>{throw e._directories.get(h)===n&&e._directories.delete(h),u});e._directories.set(h,n)}const w=await e._directories.get(h);i?.throwIfAborted();let g=0,l=w.length-1;for(;g<=l;){const n=g+l>>1;w[n].tileId<=a?g=n+1:l=n-1}const o=w[l];if(!o)return;if(o.runLength){if(a-o.tileId>=o.runLength)return;if(o.offset+o.length>t.tileDataLength)throw new Error("PMTiles tile outside data section");const n=await m(await e._read(t.tileDataOffset+o.offset,o.length,i),t.tileCompression);return i?.throwIfAborted(),{data:n}}if(o.offset+o.length>t.leafDirectoryLength)throw new Error("PMTiles directory outside leaf section");d=t.leafDirectoryOffset+o.offset,c=o.length}throw new Error("PMTiles directory depth exceeds four levels")}export{M as getHeader,x as getZxy,P as read};
2
- //# sourceMappingURL=pmtiles.js.map