leaflet-city-mapper 0.0.0-stage → 0.0.2

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 (412) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +78 -2
  3. package/cucumber.mjs +9 -0
  4. package/dist/leaflet-city-mapper.js +2 -0
  5. package/dist/leaflet-city-mapper.js.map +7 -0
  6. package/dist/utils/CELL.js +2 -0
  7. package/dist/utils/CELL.js.map +7 -0
  8. package/dist/utils/addBridges.js +2 -0
  9. package/dist/utils/addBridges.js.map +7 -0
  10. package/dist/utils/addRasterTile.js +2 -0
  11. package/dist/utils/addRasterTile.js.map +7 -0
  12. package/dist/utils/along.js +2 -0
  13. package/dist/utils/along.js.map +7 -0
  14. package/dist/utils/atmosphere.js +2 -0
  15. package/dist/utils/atmosphere.js.map +7 -0
  16. package/dist/utils/attach.js +2 -0
  17. package/dist/utils/attach.js.map +7 -0
  18. package/dist/utils/bindSunlight.js +2 -0
  19. package/dist/utils/bindSunlight.js.map +7 -0
  20. package/dist/utils/box.js +2 -0
  21. package/dist/utils/box.js.map +7 -0
  22. package/dist/utils/bridgeElevation.js +2 -0
  23. package/dist/utils/bridgeElevation.js.map +7 -0
  24. package/dist/utils/build.js +2 -0
  25. package/dist/utils/build.js.map +7 -0
  26. package/dist/utils/cameraControls.js +2 -0
  27. package/dist/utils/cameraControls.js.map +7 -0
  28. package/dist/utils/channel.js +2 -0
  29. package/dist/utils/channel.js.map +7 -0
  30. package/dist/utils/collider.js +2 -0
  31. package/dist/utils/collider.js.map +7 -0
  32. package/dist/utils/colliders.js +2 -0
  33. package/dist/utils/colliders.js.map +7 -0
  34. package/dist/utils/computeBounds.js +2 -0
  35. package/dist/utils/computeBounds.js.map +7 -0
  36. package/dist/utils/conformModelToTerrain.js +2 -0
  37. package/dist/utils/conformModelToTerrain.js.map +7 -0
  38. package/dist/utils/createMesh.js +2 -0
  39. package/dist/utils/createMesh.js.map +7 -0
  40. package/dist/utils/createProgram.js +3 -0
  41. package/dist/utils/createProgram.js.map +7 -0
  42. package/dist/utils/decodeDirectory.js +2 -0
  43. package/dist/utils/decodeDirectory.js.map +7 -0
  44. package/dist/utils/decodeHeader.js +2 -0
  45. package/dist/utils/decodeHeader.js.map +7 -0
  46. package/dist/utils/decodeModel.js +2 -0
  47. package/dist/utils/decodeModel.js.map +7 -0
  48. package/dist/utils/decompress.js +2 -0
  49. package/dist/utils/decompress.js.map +7 -0
  50. package/dist/utils/destroyTexture.js +2 -0
  51. package/dist/utils/destroyTexture.js.map +7 -0
  52. package/dist/utils/disposeMesh.js +2 -0
  53. package/dist/utils/disposeMesh.js.map +7 -0
  54. package/dist/utils/drawGeometry.js +2 -0
  55. package/dist/utils/drawGeometry.js.map +7 -0
  56. package/dist/utils/elevationWGSL.js +24 -0
  57. package/dist/utils/elevationWGSL.js.map +7 -0
  58. package/dist/utils/emptyNode.js +2 -0
  59. package/dist/utils/emptyNode.js.map +7 -0
  60. package/dist/utils/endZoom.js +2 -0
  61. package/dist/utils/endZoom.js.map +7 -0
  62. package/dist/utils/findFeature.js +2 -0
  63. package/dist/utils/findFeature.js.map +7 -0
  64. package/dist/utils/geometry.js +1 -0
  65. package/dist/utils/geometry.js.map +7 -0
  66. package/dist/utils/getElevation.js +2 -0
  67. package/dist/utils/getElevation.js.map +7 -0
  68. package/dist/utils/getHeader.js +2 -0
  69. package/dist/utils/getHeader.js.map +7 -0
  70. package/dist/utils/getZxy.js +2 -0
  71. package/dist/utils/getZxy.js.map +7 -0
  72. package/dist/utils/glass.js +2 -0
  73. package/dist/utils/glass.js.map +7 -0
  74. package/dist/utils/headlight.js +2 -0
  75. package/dist/utils/headlight.js.map +7 -0
  76. package/dist/utils/hit.js +2 -0
  77. package/dist/utils/hit.js.map +7 -0
  78. package/dist/utils/horizontalPosition.js +2 -0
  79. package/dist/utils/horizontalPosition.js.map +7 -0
  80. package/dist/utils/horizontalRay.js +2 -0
  81. package/dist/utils/horizontalRay.js.map +7 -0
  82. package/dist/utils/hull.js +2 -0
  83. package/dist/utils/hull.js.map +7 -0
  84. package/dist/utils/initSunlight.js +2 -0
  85. package/dist/utils/initSunlight.js.map +7 -0
  86. package/dist/utils/initTerrain.js +2 -0
  87. package/dist/utils/initTerrain.js.map +7 -0
  88. package/dist/utils/initTraffic.js +40 -0
  89. package/dist/utils/initTraffic.js.map +7 -0
  90. package/dist/utils/initWalk.js +2 -0
  91. package/dist/utils/initWalk.js.map +7 -0
  92. package/dist/utils/intersectMeshes.js +2 -0
  93. package/dist/utils/intersectMeshes.js.map +7 -0
  94. package/dist/utils/isClockWise.js +2 -0
  95. package/dist/utils/isClockWise.js.map +7 -0
  96. package/dist/utils/lampPostGeometry.js +2 -0
  97. package/dist/utils/lampPostGeometry.js.map +7 -0
  98. package/dist/utils/lightGeometry.js +2 -0
  99. package/dist/utils/lightGeometry.js.map +7 -0
  100. package/dist/utils/lightGrid.js +2 -0
  101. package/dist/utils/lightGrid.js.map +7 -0
  102. package/dist/utils/limbs.js +2 -0
  103. package/dist/utils/limbs.js.map +7 -0
  104. package/dist/utils/loadModel.js +2 -0
  105. package/dist/utils/loadModel.js.map +7 -0
  106. package/dist/utils/loadSource.js +2 -0
  107. package/dist/utils/loadSource.js.map +7 -0
  108. package/dist/utils/loadTerrain.js +2 -0
  109. package/dist/utils/loadTerrain.js.map +7 -0
  110. package/dist/utils/mapCamera.js +2 -0
  111. package/dist/utils/mapCamera.js.map +7 -0
  112. package/dist/utils/materialShaders.js +211 -0
  113. package/dist/utils/materialShaders.js.map +7 -0
  114. package/dist/utils/mirror.js +2 -0
  115. package/dist/utils/mirror.js.map +7 -0
  116. package/dist/utils/moonPosition.js +2 -0
  117. package/dist/utils/moonPosition.js.map +7 -0
  118. package/dist/utils/moves.js +2 -0
  119. package/dist/utils/moves.js.map +7 -0
  120. package/dist/utils/nativeEvents.js +2 -0
  121. package/dist/utils/nativeEvents.js.map +7 -0
  122. package/dist/utils/nativeGeometry.js +2 -0
  123. package/dist/utils/nativeGeometry.js.map +7 -0
  124. package/dist/utils/nativeLayer.js +2 -0
  125. package/dist/utils/nativeLayer.js.map +7 -0
  126. package/dist/utils/nodeMatrix.js +2 -0
  127. package/dist/utils/nodeMatrix.js.map +7 -0
  128. package/dist/utils/onAdd3DLayer.js +2 -0
  129. package/dist/utils/onAdd3DLayer.js.map +7 -0
  130. package/dist/utils/onAddSun.js +2 -0
  131. package/dist/utils/onAddSun.js.map +7 -0
  132. package/dist/utils/onClick.js +2 -0
  133. package/dist/utils/onClick.js.map +7 -0
  134. package/dist/utils/onMapChange.js +2 -0
  135. package/dist/utils/onMapChange.js.map +7 -0
  136. package/dist/utils/onPMTileAdd.js +2 -0
  137. package/dist/utils/onPMTileAdd.js.map +7 -0
  138. package/dist/utils/onPMTileRemove.js +2 -0
  139. package/dist/utils/onPMTileRemove.js.map +7 -0
  140. package/dist/utils/onPointerLeave.js +2 -0
  141. package/dist/utils/onPointerLeave.js.map +7 -0
  142. package/dist/utils/onPointerMove.js +2 -0
  143. package/dist/utils/onPointerMove.js.map +7 -0
  144. package/dist/utils/onRemove3DLayer.js +2 -0
  145. package/dist/utils/onRemove3DLayer.js.map +7 -0
  146. package/dist/utils/onRemoveSun.js +2 -0
  147. package/dist/utils/onRemoveSun.js.map +7 -0
  148. package/dist/utils/onTerrainAdd.js +2 -0
  149. package/dist/utils/onTerrainAdd.js.map +7 -0
  150. package/dist/utils/onTerrainChange.js +2 -0
  151. package/dist/utils/onTerrainChange.js.map +7 -0
  152. package/dist/utils/onTerrainRemove.js +2 -0
  153. package/dist/utils/onTerrainRemove.js.map +7 -0
  154. package/dist/utils/onZoomAnim.js +2 -0
  155. package/dist/utils/onZoomAnim.js.map +7 -0
  156. package/dist/utils/paints.js +2 -0
  157. package/dist/utils/paints.js.map +7 -0
  158. package/dist/utils/parseColor.js +2 -0
  159. package/dist/utils/parseColor.js.map +7 -0
  160. package/dist/utils/parts.js +2 -0
  161. package/dist/utils/parts.js.map +7 -0
  162. package/dist/utils/projectCelestialBody.js +2 -0
  163. package/dist/utils/projectCelestialBody.js.map +7 -0
  164. package/dist/utils/pump.js +2 -0
  165. package/dist/utils/pump.js.map +7 -0
  166. package/dist/utils/rasterTiles.js +2 -0
  167. package/dist/utils/rasterTiles.js.map +7 -0
  168. package/dist/utils/raycast.js +2 -0
  169. package/dist/utils/raycast.js.map +7 -0
  170. package/dist/utils/read.js +2 -0
  171. package/dist/utils/read.js.map +7 -0
  172. package/dist/utils/readAccessor.js +2 -0
  173. package/dist/utils/readAccessor.js.map +7 -0
  174. package/dist/utils/releaseArea.js +2 -0
  175. package/dist/utils/releaseArea.js.map +7 -0
  176. package/dist/utils/removeRasterTile.js +2 -0
  177. package/dist/utils/removeRasterTile.js.map +7 -0
  178. package/dist/utils/render.js +15 -0
  179. package/dist/utils/render.js.map +7 -0
  180. package/dist/utils/renderSunlight.js +13 -0
  181. package/dist/utils/renderSunlight.js.map +7 -0
  182. package/dist/utils/renderers.js +2 -0
  183. package/dist/utils/renderers.js.map +7 -0
  184. package/dist/utils/resizeSunlight.js +2 -0
  185. package/dist/utils/resizeSunlight.js.map +7 -0
  186. package/dist/utils/roofCoverage.js +2 -0
  187. package/dist/utils/roofCoverage.js.map +7 -0
  188. package/dist/utils/routeGeometry.js +2 -0
  189. package/dist/utils/routeGeometry.js.map +7 -0
  190. package/dist/utils/scheduledTrips.js +2 -0
  191. package/dist/utils/scheduledTrips.js.map +7 -0
  192. package/dist/utils/setGeoJSONData.js +2 -0
  193. package/dist/utils/setGeoJSONData.js.map +7 -0
  194. package/dist/utils/setHighlight.js +2 -0
  195. package/dist/utils/setHighlight.js.map +7 -0
  196. package/dist/utils/setPMTileOpacity.js +2 -0
  197. package/dist/utils/setPMTileOpacity.js.map +7 -0
  198. package/dist/utils/setPMTileZIndex.js +2 -0
  199. package/dist/utils/setPMTileZIndex.js.map +7 -0
  200. package/dist/utils/setParent.js +2 -0
  201. package/dist/utils/setParent.js.map +7 -0
  202. package/dist/utils/setTerrainHeight.js +2 -0
  203. package/dist/utils/setTerrainHeight.js.map +7 -0
  204. package/dist/utils/setVertexColor.js +2 -0
  205. package/dist/utils/setVertexColor.js.map +7 -0
  206. package/dist/utils/showFeature.js +2 -0
  207. package/dist/utils/showFeature.js.map +7 -0
  208. package/dist/utils/sizes.js +2 -0
  209. package/dist/utils/sizes.js.map +7 -0
  210. package/dist/utils/skin.js +2 -0
  211. package/dist/utils/skin.js.map +7 -0
  212. package/dist/utils/solarPosition.js +2 -0
  213. package/dist/utils/solarPosition.js.map +7 -0
  214. package/dist/utils/sortMeshes.js +2 -0
  215. package/dist/utils/sortMeshes.js.map +7 -0
  216. package/dist/utils/speed.js +2 -0
  217. package/dist/utils/speed.js.map +7 -0
  218. package/dist/utils/startZoom.js +2 -0
  219. package/dist/utils/startZoom.js.map +7 -0
  220. package/dist/utils/taillight.js +2 -0
  221. package/dist/utils/taillight.js.map +7 -0
  222. package/dist/utils/terrainAtlas.js +2 -0
  223. package/dist/utils/terrainAtlas.js.map +7 -0
  224. package/dist/utils/terrainElevation.js +2 -0
  225. package/dist/utils/terrainElevation.js.map +7 -0
  226. package/dist/utils/terrainGrid.js +2 -0
  227. package/dist/utils/terrainGrid.js.map +7 -0
  228. package/dist/utils/textureSampler.js +2 -0
  229. package/dist/utils/textureSampler.js.map +7 -0
  230. package/dist/utils/tileId.js +2 -0
  231. package/dist/utils/tileId.js.map +7 -0
  232. package/dist/utils/toLanes.js +2 -0
  233. package/dist/utils/toLanes.js.map +7 -0
  234. package/dist/utils/toSRGB.js +2 -0
  235. package/dist/utils/toSRGB.js.map +7 -0
  236. package/dist/utils/tooltip.js +3 -0
  237. package/dist/utils/tooltip.js.map +7 -0
  238. package/dist/utils/traffic.js +2 -0
  239. package/dist/utils/traffic.js.map +7 -0
  240. package/dist/utils/traverse.js +2 -0
  241. package/dist/utils/traverse.js.map +7 -0
  242. package/dist/utils/treeGeometry.js +2 -0
  243. package/dist/utils/treeGeometry.js.map +7 -0
  244. package/dist/utils/triangulate.js +2 -0
  245. package/dist/utils/triangulate.js.map +7 -0
  246. package/dist/utils/tripsAt.js +2 -0
  247. package/dist/utils/tripsAt.js.map +7 -0
  248. package/dist/utils/types.js +2 -0
  249. package/dist/utils/types.js.map +7 -0
  250. package/dist/utils/underEntry.js +2 -0
  251. package/dist/utils/underEntry.js.map +7 -0
  252. package/dist/utils/update.js +2 -0
  253. package/dist/utils/update.js.map +7 -0
  254. package/dist/utils/updateArea.js +2 -0
  255. package/dist/utils/updateArea.js.map +7 -0
  256. package/dist/utils/updateCamera.js +2 -0
  257. package/dist/utils/updateCamera.js.map +7 -0
  258. package/dist/utils/updatePointLights.js +2 -0
  259. package/dist/utils/updatePointLights.js.map +7 -0
  260. package/dist/utils/updateWorldMatrix.js +2 -0
  261. package/dist/utils/updateWorldMatrix.js.map +7 -0
  262. package/dist/utils/vehicleOffsets.js +2 -0
  263. package/dist/utils/vehicleOffsets.js.map +7 -0
  264. package/dist/utils/vehicles.js +2 -0
  265. package/dist/utils/vehicles.js.map +7 -0
  266. package/dist/utils/vertexNormals.js +2 -0
  267. package/dist/utils/vertexNormals.js.map +7 -0
  268. package/dist/utils/walk.js +2 -0
  269. package/dist/utils/walk.js.map +7 -0
  270. package/dist/utils/white.js +2 -0
  271. package/dist/utils/white.js.map +7 -0
  272. package/dist/utils/worldLights.js +2 -0
  273. package/dist/utils/worldLights.js.map +7 -0
  274. package/dist/utils/wrap.js +2 -0
  275. package/dist/utils/wrap.js.map +7 -0
  276. package/package.json +43 -4
  277. package/src/index.js +397 -0
  278. package/src/utils/CELL.js +4 -0
  279. package/src/utils/addBridges.js +66 -0
  280. package/src/utils/addRasterTile.js +112 -0
  281. package/src/utils/along.js +9 -0
  282. package/src/utils/atmosphere.js +20 -0
  283. package/src/utils/attach.js +255 -0
  284. package/src/utils/bindSunlight.js +12 -0
  285. package/src/utils/box.js +1 -0
  286. package/src/utils/bridgeElevation.js +18 -0
  287. package/src/utils/build.js +20 -0
  288. package/src/utils/cameraControls.js +287 -0
  289. package/src/utils/channel.js +4 -0
  290. package/src/utils/collider.js +62 -0
  291. package/src/utils/colliders.js +2 -0
  292. package/src/utils/computeBounds.js +17 -0
  293. package/src/utils/conformModelToTerrain.js +69 -0
  294. package/src/utils/createMesh.js +31 -0
  295. package/src/utils/createProgram.js +92 -0
  296. package/src/utils/decodeDirectory.js +40 -0
  297. package/src/utils/decodeHeader.js +15 -0
  298. package/src/utils/decodeModel.js +43 -0
  299. package/src/utils/decompress.js +5 -0
  300. package/src/utils/destroyTexture.js +7 -0
  301. package/src/utils/disposeMesh.js +13 -0
  302. package/src/utils/drawGeometry.js +122 -0
  303. package/src/utils/elevationWGSL.js +27 -0
  304. package/src/utils/emptyNode.js +9 -0
  305. package/src/utils/endZoom.js +15 -0
  306. package/src/utils/findFeature.js +49 -0
  307. package/src/utils/geometry.js +2 -0
  308. package/src/utils/getElevation.js +10 -0
  309. package/src/utils/getHeader.js +9 -0
  310. package/src/utils/getZxy.js +76 -0
  311. package/src/utils/glass.js +1 -0
  312. package/src/utils/headlight.js +1 -0
  313. package/src/utils/hit.js +41 -0
  314. package/src/utils/horizontalPosition.js +16 -0
  315. package/src/utils/horizontalRay.js +12 -0
  316. package/src/utils/hull.js +1 -0
  317. package/src/utils/initSunlight.js +9 -0
  318. package/src/utils/initTerrain.js +19 -0
  319. package/src/utils/initTraffic.js +93 -0
  320. package/src/utils/initWalk.js +72 -0
  321. package/src/utils/intersectMeshes.js +121 -0
  322. package/src/utils/isClockWise.js +12 -0
  323. package/src/utils/lampPostGeometry.js +26 -0
  324. package/src/utils/lightGeometry.js +22 -0
  325. package/src/utils/lightGrid.js +50 -0
  326. package/src/utils/limbs.js +9 -0
  327. package/src/utils/loadModel.js +217 -0
  328. package/src/utils/loadSource.js +17 -0
  329. package/src/utils/loadTerrain.js +65 -0
  330. package/src/utils/mapCamera.js +432 -0
  331. package/src/utils/materialShaders.js +243 -0
  332. package/src/utils/mirror.js +6 -0
  333. package/src/utils/moonPosition.js +17 -0
  334. package/src/utils/moves.js +11 -0
  335. package/src/utils/nativeEvents.js +77 -0
  336. package/src/utils/nativeGeometry.js +131 -0
  337. package/src/utils/nativeLayer.js +317 -0
  338. package/src/utils/nodeMatrix.js +22 -0
  339. package/src/utils/onAdd3DLayer.js +31 -0
  340. package/src/utils/onAddSun.js +147 -0
  341. package/src/utils/onClick.js +13 -0
  342. package/src/utils/onMapChange.js +16 -0
  343. package/src/utils/onPMTileAdd.js +15 -0
  344. package/src/utils/onPMTileRemove.js +8 -0
  345. package/src/utils/onPointerLeave.js +11 -0
  346. package/src/utils/onPointerMove.js +15 -0
  347. package/src/utils/onRemove3DLayer.js +78 -0
  348. package/src/utils/onRemoveSun.js +3 -0
  349. package/src/utils/onTerrainAdd.js +18 -0
  350. package/src/utils/onTerrainChange.js +13 -0
  351. package/src/utils/onTerrainRemove.js +40 -0
  352. package/src/utils/onZoomAnim.js +14 -0
  353. package/src/utils/paints.js +10 -0
  354. package/src/utils/parseColor.js +42 -0
  355. package/src/utils/parts.js +16 -0
  356. package/src/utils/projectCelestialBody.js +13 -0
  357. package/src/utils/pump.js +226 -0
  358. package/src/utils/rasterTiles.js +285 -0
  359. package/src/utils/raycast.js +60 -0
  360. package/src/utils/read.js +29 -0
  361. package/src/utils/readAccessor.js +68 -0
  362. package/src/utils/releaseArea.js +34 -0
  363. package/src/utils/removeRasterTile.js +13 -0
  364. package/src/utils/render.js +406 -0
  365. package/src/utils/renderSunlight.js +170 -0
  366. package/src/utils/renderers.js +2 -0
  367. package/src/utils/resizeSunlight.js +15 -0
  368. package/src/utils/roofCoverage.js +47 -0
  369. package/src/utils/routeGeometry.js +22 -0
  370. package/src/utils/scheduledTrips.js +29 -0
  371. package/src/utils/setGeoJSONData.js +11 -0
  372. package/src/utils/setHighlight.js +13 -0
  373. package/src/utils/setPMTileOpacity.js +7 -0
  374. package/src/utils/setPMTileZIndex.js +7 -0
  375. package/src/utils/setParent.js +7 -0
  376. package/src/utils/setTerrainHeight.js +10 -0
  377. package/src/utils/setVertexColor.js +14 -0
  378. package/src/utils/showFeature.js +27 -0
  379. package/src/utils/sizes.js +1 -0
  380. package/src/utils/skin.js +2 -0
  381. package/src/utils/solarPosition.js +17 -0
  382. package/src/utils/sortMeshes.js +12 -0
  383. package/src/utils/speed.js +3 -0
  384. package/src/utils/startZoom.js +5 -0
  385. package/src/utils/taillight.js +1 -0
  386. package/src/utils/terrainAtlas.js +21 -0
  387. package/src/utils/terrainElevation.js +20 -0
  388. package/src/utils/terrainGrid.js +23 -0
  389. package/src/utils/textureSampler.js +10 -0
  390. package/src/utils/tileId.js +18 -0
  391. package/src/utils/toLanes.js +7 -0
  392. package/src/utils/toSRGB.js +1 -0
  393. package/src/utils/tooltip.js +6 -0
  394. package/src/utils/traffic.js +315 -0
  395. package/src/utils/traverse.js +6 -0
  396. package/src/utils/treeGeometry.js +45 -0
  397. package/src/utils/triangulate.js +100 -0
  398. package/src/utils/tripsAt.js +16 -0
  399. package/src/utils/types.js +8 -0
  400. package/src/utils/underEntry.js +17 -0
  401. package/src/utils/update.js +18 -0
  402. package/src/utils/updateArea.js +40 -0
  403. package/src/utils/updateCamera.js +32 -0
  404. package/src/utils/updatePointLights.js +38 -0
  405. package/src/utils/updateWorldMatrix.js +47 -0
  406. package/src/utils/vehicleOffsets.js +8 -0
  407. package/src/utils/vehicles.js +65 -0
  408. package/src/utils/vertexNormals.js +30 -0
  409. package/src/utils/walk.js +187 -0
  410. package/src/utils/white.js +1 -0
  411. package/src/utils/worldLights.js +25 -0
  412. package/src/utils/wrap.js +1 -0
@@ -0,0 +1 @@
1
+ export const glass = [0.12, 0.15, 0.18], tyre = [0.05, 0.05, 0.05];
@@ -0,0 +1 @@
1
+ export const headlight = [1.9, 1.85, 1.7];
@@ -0,0 +1,41 @@
1
+ import { CELL } from './CELL.js';
2
+ import { collider } from './collider.js';
3
+ import { computeBounds } from './computeBounds.js';
4
+ import { horizontalRay } from './horizontalRay.js';
5
+ import { traverse } from './traverse.js';
6
+ import { updateWorldMatrix } from './updateWorldMatrix.js';
7
+
8
+ // Horizontal normal of the nearest wall faced within `reach` metres of the feet at world (x, y, z), walking along
9
+ // the unit (dx, dz); knee and chest rays, so arches and tree crowns above the head let the walker through.
10
+ // ponytail: traffic vehicles and boats move on the GPU and are not obstacles.
11
+
12
+ export function hit(layer, x, y, z, dx, dz, reach) {
13
+ const skip = other => other === layer || ['terrain', 'traffic'].includes(other._type);
14
+ updateWorldMatrix(layer.scene);
15
+ let best = reach, found = null;
16
+ for (const other of layer._shared._layers) {
17
+ if (skip(other)) continue;
18
+ traverse(other.root, mesh => {
19
+ if (!mesh.visible) return true;
20
+ if (!mesh.geometry?.attributes?.position?.data || mesh.program?.depthTest === false) return;
21
+ if (!mesh.geometry.bounds) computeBounds(mesh.geometry);
22
+ const m = mesh.worldMatrix, { center: k, radius } = mesh.geometry.bounds;
23
+ if (Math.hypot(m[0] * k[0] + m[4] * k[1] + m[8] * k[2] + m[12] - x, m[2] * k[0] + m[6] * k[1] + m[10] * k[2] + m[14] - z) >
24
+ radius * Math.hypot(m[0], m[1], m[2]) + reach) return;
25
+ const c = collider(mesh), ox = x - m[12] + c.origin[0], oy = y - m[13] + c.origin[1], oz = z - m[14] + c.origin[2];
26
+ const seen = new Set();
27
+ for (let ix = Math.floor(Math.min(ox, ox + dx * reach) / CELL); ix <= Math.floor(Math.max(ox, ox + dx * reach) / CELL); ix++)
28
+ for (let iz = Math.floor(Math.min(oz, oz + dz * reach) / CELL); iz <= Math.floor(Math.max(oz, oz + dz * reach) / CELL); iz++)
29
+ for (const t of c.cells.get(ix + ',' + iz) || []) {
30
+ // Walls are one-way: walking out of a building (e.g. starting inside one) is allowed.
31
+ if (seen.has(t) || dx * c.nrm[t * 2] + dz * c.nrm[t * 2 + 1] >= 0) continue;
32
+ seen.add(t);
33
+ for (const height of [0.4, 1.5]) {
34
+ const d = horizontalRay(c.tri, t, ox, oy + height, oz, dx, dz);
35
+ if (d >= 0 && d < best) { best = d; found = [c.nrm[t * 2], c.nrm[t * 2 + 1]]; }
36
+ }
37
+ }
38
+ });
39
+ }
40
+ return found;
41
+ }
@@ -0,0 +1,16 @@
1
+
2
+ export function horizontalPosition(d, lat, lng, ascension, declination) {
3
+ const rad = Math.PI / 180;
4
+ const hourAngle = (280.16 + 360.9856235 * d + lng) * rad - ascension;
5
+ const latitude = lat * rad;
6
+ const altitude = Math.asin(Math.sin(latitude) * Math.sin(declination) +
7
+ Math.cos(latitude) * Math.cos(declination) * Math.cos(hourAngle));
8
+ const southAzimuth = Math.atan2(Math.sin(hourAngle),
9
+ Math.cos(hourAngle) * Math.sin(latitude) - Math.tan(declination) * Math.cos(latitude));
10
+ const azimuth = (southAzimuth / rad + 180 + 360) % 360;
11
+ return {
12
+ altitude: altitude / rad, azimuth,
13
+ direction: [Math.sin(azimuth * rad) * Math.cos(altitude), Math.sin(altitude),
14
+ -Math.cos(azimuth * rad) * Math.cos(altitude)]
15
+ };
16
+ }
@@ -0,0 +1,12 @@
1
+ // Möller-Trumbore for the horizontal ray (ox, oy, oz) + d·(dx, 0, dz) against triangle t; returns d or -1.
2
+ export function horizontalRay(v, t, ox, oy, oz, dx, dz) {
3
+ const i = t * 9, ex = v[i + 3] - v[i], ey = v[i + 4] - v[i + 1], ez = v[i + 5] - v[i + 2];
4
+ const fx = v[i + 6] - v[i], fy = v[i + 7] - v[i + 1], fz = v[i + 8] - v[i + 2];
5
+ const px = -dz * fy, py = dz * fx - dx * fz, pz = dx * fy, det = ex * px + ey * py + ez * pz;
6
+ if (Math.abs(det) < 1e-9) return -1;
7
+ const tx = ox - v[i], ty = oy - v[i + 1], tz = oz - v[i + 2], u = (tx * px + ty * py + tz * pz) / det;
8
+ if (u < 0 || u > 1) return -1;
9
+ const qx = ty * ez - tz * ey, qy = tz * ex - tx * ez, qz = tx * ey - ty * ex, w = (dx * qx + dz * qz) / det;
10
+ if (w < 0 || u + w > 1) return -1;
11
+ return (fx * qx + fy * qy + fz * qz) / det;
12
+ }
@@ -0,0 +1 @@
1
+ export const hull = [[-5.5, 30], [5.5, 30], [5.5, -20], [4, -26], [1.5, -30], [-1.5, -30], [-4, -26], [-5.5, -20]];
@@ -0,0 +1,9 @@
1
+ import { onAddSun } from './onAddSun.js';
2
+ import { onRemoveSun } from './onRemoveSun.js';
3
+
4
+ // Sun/moon clock control and sky colours; the control is created on first add (`layer.control`).
5
+ export function initSunlight(layer, options) {
6
+ L.Util.setOptions(layer, options);
7
+ layer.onAdd = map => onAddSun(layer, map);
8
+ layer.onRemove = () => onRemoveSun(layer);
9
+ }
@@ -0,0 +1,19 @@
1
+ import { onTerrainRemove } from './onTerrainRemove.js';
2
+ import { onTerrainAdd } from './onTerrainAdd.js';
3
+
4
+ /**
5
+ * Renders IGN Float32 DEM tiles and PMTiles raster basemaps in the shared WebGPU scene.
6
+ * Source options: `url` (single-zoom Float32 PMTiles DEM); `bridges` (optional GeoJSON deck polygons with Z, see _addBridges).
7
+ */
8
+ export function initTerrain(layer, options) {
9
+ const terrainSource = options.url;
10
+ const layerOptions = { ...options };
11
+ delete layerOptions.url;
12
+ layer._init3D(layerOptions);
13
+ layer.terrainSource = terrainSource;
14
+ layer._terrainTiles = new Map();
15
+ layer._rasterTiles = new Map();
16
+ layer._terrainReady = false;
17
+ layer.onAdd = map => onTerrainAdd(layer, map);
18
+ layer.onRemove = map => onTerrainRemove(layer, map);
19
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Vehicles moving along GeoJSON lanes; a compute pass places them on the GPU every frame.
3
+ * Source options:
4
+ * - `url`: GeoJSON (Multi)LineStrings, or a JS module whose default export `(time, layer, signal)` returns them (time-dependent data);
5
+ * - `vehicle`: 'car' (default) or 'boat'; `side`: offset right of the lane centreline in metres (vehicle default);
6
+ * - `speed`: m/s of `flow` lanes; `outline`: draw the lanes.
7
+ * Lane properties: `flow` (vehicles/h) or `timetable` (see scheduledTrips.js), optional fixed `elevation`
8
+ * in metres, `name`/`description` for the default tooltip. The status line (vehicle count, then the FeatureCollection `note`) sits under the layer's entry in the layers control.
9
+ * The 'sunlight' layer on the same map drives the time; without one, vehicles run live.
10
+ */
11
+ import { build } from './build.js';
12
+ import { tooltip } from './tooltip.js';
13
+ import { speed } from './speed.js';
14
+ import { vehicles } from './vehicles.js';
15
+ import {
16
+ addTraffic,
17
+ placeTraffic,
18
+ removeTraffic,
19
+ readyTraffic,
20
+ tickTraffic,
21
+ updateTraffic,
22
+ updateTrafficTerrain,
23
+ } from './traffic.js';
24
+
25
+ export function initTraffic(layer, { url, vehicle = 'car', side, outline, speed: velocity = speed, ...options } = {}) {
26
+ const { model, lights, side: defaultSide } = vehicles[vehicle];
27
+ side ??= defaultSide;
28
+ layer._init3D({
29
+ tooltip,
30
+ nightLight: Boolean(lights),
31
+ ...options,
32
+ });
33
+ const status = L.DomUtil.create('small', 'traffic-status');
34
+ status.style.cssText = 'display:block;max-width:200px;margin:0 0 4px 20px;color:#555;';
35
+ const template = build(model(0)), stride = template.position.length, vertices = stride / 3;
36
+ const params = new ArrayBuffer(16), paramFloats = new Float32Array(params), paramInts = new Uint32Array(params);
37
+ const state = {
38
+ layer, url, model, lights, side, outline, velocity, status, template, stride, vertices,
39
+ params, paramFloats, paramInts,
40
+ ready: false, frame: undefined, request: undefined, lanes: [], tripsKey: undefined,
41
+ mesh: undefined, route: undefined, litAt: -Infinity,
42
+ trips: [], rebasedAt: 0, nextCheck: -Infinity, elapsed: 0, gpu: null,
43
+ lanesDirty: true, stale: false, loaded: undefined, file: undefined,
44
+ };
45
+ // Lane points are [x, z, ground, cumulative length]. Mirrors along() and place().
46
+ const shader = `
47
+ struct Params { seconds: f32, side: f32, vertices: u32, total: u32 }
48
+ struct Vehicle { start: u32, count: u32, base: f32, speed: f32 }
49
+ @group(0) @binding(0) var<uniform> params: Params;
50
+ @group(0) @binding(1) var<storage, read> model: array<f32>;
51
+ @group(0) @binding(2) var<storage, read> points: array<vec4f>;
52
+ @group(0) @binding(3) var<storage, read> vehicles: array<Vehicle>;
53
+ @group(0) @binding(4) var<storage, read_write> position: array<f32>;
54
+ @group(0) @binding(5) var<storage, read_write> normal: array<f32>;
55
+ @compute @workgroup_size(64)
56
+ fn main(@builtin(global_invocation_id) id: vec3u) {
57
+ let v = id.x;
58
+ if (v >= params.total) { return; }
59
+ let vehicle = vehicles[v / params.vertices];
60
+ let last = vehicle.start + vehicle.count - 1u;
61
+ let length = points[last].w;
62
+ var s = vehicle.base + params.seconds * vehicle.speed;
63
+ s -= length * floor(s / length);
64
+ var i = vehicle.start + 1u;
65
+ while (i < last && points[i].w < s) { i++; }
66
+ let a = points[i - 1u];
67
+ let b = points[i];
68
+ let d = select(b.w - a.w, 1.0, b.w == a.w);
69
+ let t = (s - a.w) / d;
70
+ let dx = (b.x - a.x) / d;
71
+ let dz = (b.y - a.y) / d;
72
+ let cx = a.x + (b.x - a.x) * t - dz * params.side;
73
+ let cz = a.y + (b.y - a.y) * t + dx * params.side;
74
+ let y = a.z + (b.z - a.z) * t;
75
+ let k = (v % params.vertices) * 3u;
76
+ let n = params.vertices * 3u + k;
77
+ let o = v * 3u;
78
+ position[o] = cx - model[k] * dz - model[k + 2u] * dx;
79
+ position[o + 1u] = y + model[k + 1u];
80
+ position[o + 2u] = cz + model[k] * dx - model[k + 2u] * dz;
81
+ normal[o] = -model[n] * dz - model[n + 2u] * dx;
82
+ normal[o + 1u] = model[n + 1u];
83
+ normal[o + 2u] = model[n] * dx - model[n + 2u] * dz;
84
+ }`;
85
+ state.shader = shader;
86
+ state.tick = tickTraffic.bind(null, state);
87
+ state.update = updateTraffic.bind(null, state);
88
+ state.terrain = updateTrafficTerrain.bind(null, state);
89
+ layer._beforeRaycast = placeTraffic.bind(null, state);
90
+ layer.on('ready', readyTraffic.bind(null, state));
91
+ layer.on('add', addTraffic.bind(null, state));
92
+ layer.on('remove', removeTraffic.bind(null, state));
93
+ }
@@ -0,0 +1,72 @@
1
+ import {
2
+ controlOnAdd, onBlur, onKey, onLayerAdd, onLayerRemove, onPointer, onReady, onTerrain, start, step, stop, toggle
3
+ } from './walk.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 `layer.walker` exposes `{ latlng, heading, phase }`.
10
+ * Source options: `speed` (m/s, default 6), `distance` (camera distance in metres, default 20), `position` (button corner, default 'topleft').
11
+ * Visible meshes of the other 3D layers (buildings, trees, models, streetlights) are solid; terrain and traffic are not.
12
+ */
13
+ export function initWalk(layer, {
14
+ speed = 70,
15
+ distance = 20,
16
+ position = 'bottomright',
17
+ ...options
18
+ } = {}) {
19
+ layer._init3D(options);
20
+ const keys = new Set();
21
+ const control = new L.Control({ position });
22
+ const container = L.DomUtil.create('div', 'leaflet-bar leaflet-control');
23
+ container.style.cssText = 'display:flex;align-items:center;background:#fff;';
24
+ const button = L.DomUtil.create('button', '', container);
25
+ button.type = 'button';
26
+ button.title = 'Walk';
27
+ button.setAttribute('aria-label', 'Walk');
28
+ button.setAttribute('aria-pressed', 'false');
29
+ button.textContent = '🚶';
30
+ button.style.cssText = 'width:30px;height:30px;padding:0;border:0;border-radius:4px;background:#fff;font-size:18px;line-height:30px;cursor:pointer;';
31
+ const hint = L.DomUtil.create('small', '', container);
32
+ hint.style.cssText = 'display:none;padding:0 8px;color:#333;white-space:nowrap;';
33
+ hint.textContent = 'W/S: run · A/D: turn · drag: look around · Esc: exit';
34
+ L.DomEvent.disableClickPropagation(container);
35
+
36
+ const context = {
37
+ layer,
38
+ speed,
39
+ distance,
40
+ keys,
41
+ control,
42
+ container,
43
+ button,
44
+ hint,
45
+ meshes: null,
46
+ frame: null,
47
+ last: undefined,
48
+ swing: 0,
49
+ saved: null,
50
+ drag: null,
51
+ ready: false,
52
+ state: layer.walker = { latlng: null, heading: 0, phase: 0 }
53
+ }
54
+ context.step = step.bind(context);
55
+ context.onKey = onKey.bind(context);
56
+ context.onBlur = onBlur.bind(context);
57
+ context.onPointer = onPointer.bind(context);
58
+ context.onTerrain = onTerrain.bind(context);
59
+ context.start = start.bind(context);
60
+ context.stop = stop.bind(context);
61
+ context.toggle = toggle.bind(context);
62
+ context.controlOnAdd = controlOnAdd.bind(context);
63
+ context.onReady = onReady.bind(context);
64
+ context.onLayerAdd = onLayerAdd.bind(context);
65
+ context.onLayerRemove = onLayerRemove.bind(context);
66
+
67
+ control.onAdd = context.controlOnAdd;
68
+ L.DomEvent.on(button, 'click', context.toggle);
69
+ layer.on('ready', context.onReady);
70
+ layer.on('add', context.onLayerAdd);
71
+ layer.on('remove', context.onLayerRemove);
72
+ };
@@ -0,0 +1,121 @@
1
+ import { computeBounds } from "./computeBounds.js";
2
+
3
+ const sub = (a, b) => a.map((v, i) => v - b[i]);
4
+ const cross = (a, b) => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
5
+ const dot = (a, b) => a.reduce((sum, v, i) => sum + v * b[i], 0);
6
+
7
+ /** Nearest triangle hit per mesh, sorted by world-space distance. */
8
+
9
+ export function intersectMeshes(ray, meshes, night = 0) {
10
+ const hits = [],
11
+ a = [0, 0, 0],
12
+ b = [0, 0, 0],
13
+ c = [0, 0, 0];
14
+ for (const mesh of meshes) {
15
+ // Test in mesh-local space; compare distances only after returning to shared world space.
16
+ const inverse = new DOMMatrix(mesh.worldMatrix).inverse();
17
+ const inverseValues = inverse.toFloat64Array();
18
+ if (![...inverseValues].every(Number.isFinite)) {
19
+ throw new Error('Singular 3D transform');
20
+ }
21
+ const localOrigin = new DOMPoint(...ray.origin, 1).matrixTransform(inverse);
22
+ const origin = [
23
+ localOrigin.x / localOrigin.w,
24
+ localOrigin.y / localOrigin.w,
25
+ localOrigin.z / localOrigin.w
26
+ ];
27
+ const localDirection = new DOMPoint(...ray.direction, 0).matrixTransform(inverse);
28
+ const direction = [
29
+ localDirection.x,
30
+ localDirection.y,
31
+ localDirection.z
32
+ ];
33
+ const directionLength = Math.hypot(...direction) || 1;
34
+ direction[0] /= directionLength;
35
+ direction[1] /= directionLength;
36
+ direction[2] /= directionLength;
37
+ // AABB slab test reuses the same local ray as the triangle test.
38
+ if (!mesh.geometry.bounds) {
39
+ computeBounds(mesh.geometry);
40
+ }
41
+ let near = 0, far = Infinity;
42
+ for (let i = 0; i < 3; i++) {
43
+ if (Math.abs(direction[i]) < 1e-12) {
44
+ if (origin[i] < mesh.geometry.bounds.min[i] || origin[i] > mesh.geometry.bounds.max[i]) {
45
+ far = -Infinity;
46
+ break;
47
+ }
48
+ } else {
49
+ const a = (mesh.geometry.bounds.min[i] - origin[i]) / direction[i], b = (mesh.geometry.bounds.max[i] - origin[i]) / direction[i];
50
+ near = Math.max(near, Math.min(a, b));
51
+ far = Math.min(far, Math.max(a, b));
52
+ }
53
+ }
54
+ if (far < near) {
55
+ continue;
56
+ }
57
+ const { position, index } = mesh.geometry.attributes;
58
+ let closest = Infinity, faceIndex;
59
+ for (let i = 0; i < (index?.count || position.count); i += 3) {
60
+ const ai = (index ? index.data[i] : i) * position.size;
61
+ const bi = (index ? index.data[i + 1] : i + 1) * position.size;
62
+ const ci = (index ? index.data[i + 2] : i + 2) * position.size;
63
+ a[0] = position.data[ai];
64
+ a[1] = position.data[ai + 1];
65
+ a[2] = position.data[ai + 2];
66
+ b[0] = position.data[bi];
67
+ b[1] = position.data[bi + 1];
68
+ b[2] = position.data[bi + 2];
69
+ c[0] = position.data[ci];
70
+ c[1] = position.data[ci + 1];
71
+ c[2] = position.data[ci + 2];
72
+ // Moller-Trumbore: barycentric triangle coordinates and local ray distance.
73
+ const e = sub(b, a),
74
+ f = sub(c, a),
75
+ p = cross(direction, f),
76
+ det = dot(e, p);
77
+ if (mesh.program.cullMode === 'none' || mesh.program.cullFace === null
78
+ ? Math.abs(det) < 1e-9 : det < 1e-9) {
79
+ continue;
80
+ }
81
+ const t = sub(origin, a), u = dot(t, p) / det;
82
+ if (u < 0 || u > 1) {
83
+ continue;
84
+ }
85
+ const q = cross(t, e), v = dot(direction, q) / det;
86
+ if (v < 0 || u + v > 1) {
87
+ continue;
88
+ }
89
+ if (mesh.program.nightLight) {
90
+ const uv = mesh.geometry.attributes.uv.data;
91
+ const ids = index ? [index.data[i], index.data[i + 1], index.data[i + 2]] : [i, i + 1, i + 2];
92
+ const x = uv[ids[0] * 2] * (1 - u - v) + uv[ids[1] * 2] * u + uv[ids[2] * 2] * v;
93
+ const y = uv[ids[0] * 2 + 1] * (1 - u - v) + uv[ids[1] * 2 + 1] * u + uv[ids[2] * 2 + 1] * v;
94
+ if (x <= 2 && (!night || x * x + y * y > 0.9)) continue;
95
+ }
96
+ const distance = dot(f, q) / det;
97
+ if (distance > 0 && distance < closest) {
98
+ closest = distance; faceIndex = i / 3;
99
+ }
100
+ }
101
+ if (faceIndex === undefined) continue;
102
+ const point = new DOMPoint(
103
+ direction[0] * closest + origin[0],
104
+ direction[1] * closest + origin[1],
105
+ direction[2] * closest + origin[2],
106
+ 1
107
+ ).matrixTransform(new DOMMatrix(mesh.worldMatrix));
108
+ const worldPoint = [point.x / point.w, point.y / point.w, point.z / point.w];
109
+ hits.push({
110
+ faceIndex,
111
+ object: mesh,
112
+ point: worldPoint,
113
+ distance: Math.hypot(
114
+ worldPoint[0] - ray.origin[0],
115
+ worldPoint[1] - ray.origin[1],
116
+ worldPoint[2] - ray.origin[2]
117
+ )
118
+ });
119
+ }
120
+ return hits.sort((a, b) => a.distance - b.distance);
121
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @returns {boolean} Whether the `{x, y}` points are in clockwise order.
3
+ */
4
+
5
+ export function isClockWise(points) {
6
+ let area = 0;
7
+ for (let i = 0; i < points.length; i++) {
8
+ const a = points[i], b = points[(i + 1) % points.length];
9
+ area += a.x * b.y - b.x * a.y;
10
+ }
11
+ return area < 0;
12
+ }
@@ -0,0 +1,26 @@
1
+ import { parseColor } from "./parseColor.js";
2
+
3
+ /** Schematic support and lamp head; wall-mounted fixtures do not get an invented pole. */
4
+
5
+ export function lampPostGeometry(point, style, addTriangle) {
6
+ const color = parseColor(0x50565a), radius = style.poleRadius;
7
+ if (!Number.isFinite(radius) || radius <= 0) {
8
+ throw new Error('Invalid lamp pole radius');
9
+ }
10
+ const ring = r => Array.from({ length: 6 }, (_, i) => ({
11
+ x: point.x + Math.cos(i * Math.PI / 3) * r,
12
+ y: point.y + Math.sin(i * Math.PI / 3) * r, ground: point.ground, uv: [3, 3],
13
+ }));
14
+ const center = { ...point, uv: [3, 3] };
15
+ for (const [r, low, high] of [[radius, 0, style.top], [radius * 2.5, style.top - 0.25, style.top + 0.15]]) {
16
+ const points = ring(r);
17
+ for (let i = 0; i < 6; i++) {
18
+ const a = points[i], b = points[(i + 1) % 6], angle = (i + 0.5) * Math.PI / 3;
19
+ const nx = Math.cos(angle), nz = -Math.sin(angle);
20
+ addTriangle(a, low, b, low, b, high, nx, 0, nz, color);
21
+ addTriangle(a, low, b, high, a, high, nx, 0, nz, color);
22
+ addTriangle(center, high, a, high, b, high, 0, 1, 0, color);
23
+ addTriangle(center, low, b, low, a, low, 0, -1, 0, color);
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,22 @@
1
+ import { parseColor } from "./parseColor.js";
2
+
3
+ /** Three crossed emitter discs; illumination itself is evaluated on receiving surfaces. */
4
+
5
+ export function lightGeometry(point, style, addTriangle) {
6
+ if (!Number.isFinite(style.lightRadius) || style.lightRadius <= 0) throw new Error('Invalid light radius');
7
+ const color = parseColor(style.color);
8
+ const quad = (a, b, c, d, height, normal) => {
9
+ addTriangle(a, height, b, height, c, height, ...normal, color);
10
+ addTriangle(a, height, c, height, d, height, ...normal, color);
11
+ };
12
+ const r = 0.65;
13
+ const emitter = (u, v, axis) => ({
14
+ x: point.x + (axis === 2 ? 0 : u * r),
15
+ y: point.y + (axis === 1 ? 0 : axis === 2 ? u * r : v * r),
16
+ ground: point.ground + (axis === 0 ? 0 : v * r), uv: [u, v],
17
+ });
18
+ for (let axis = 0; axis < 3; axis++) {
19
+ quad(emitter(-1, -1, axis), emitter(1, -1, axis), emitter(1, 1, axis), emitter(-1, 1, axis),
20
+ style.top, axis === 0 ? [0, 1, 0] : axis === 1 ? [0, 0, 1] : [1, 0, 0]);
21
+ }
22
+ }
@@ -0,0 +1,50 @@
1
+ /** Pack world-space point lights into the shader's spatial grid. */
2
+ export function lightGrid(packed, maxBytes) {
3
+ const count = packed.reduce((sum, values) => sum + values.length / 8, 0), cellSize = 32;
4
+ let data = new Float32Array(8);
5
+ if (count) {
6
+ let minX = Infinity, minZ = Infinity, maxX = -Infinity, maxZ = -Infinity;
7
+ for (const values of packed) for (let i = 0; i < values.length; i += 8) {
8
+ minX = Math.min(minX, values[i] - values[i + 3]);
9
+ maxX = Math.max(maxX, values[i] + values[i + 3]);
10
+ minZ = Math.min(minZ, values[i + 2] - values[i + 3]);
11
+ maxZ = Math.max(maxZ, values[i + 2] + values[i + 3]);
12
+ }
13
+ const columns = Math.ceil((maxX - minX) / cellSize) + 1,
14
+ rows = Math.ceil((maxZ - minZ) / cellSize) + 1;
15
+ const each = callback => {
16
+ for (const values of packed) for (let i = 0; i < values.length; i += 8) {
17
+ const radius = values[i + 3],
18
+ x = values[i] - minX,
19
+ z = values[i + 2] - minZ;
20
+ for (let y = Math.floor((z - radius) / cellSize); y <= Math.floor((z + radius) / cellSize); y++) {
21
+ for (let c = Math.floor((x - radius) / cellSize); c <= Math.floor((x + radius) / cellSize); c++) {
22
+ callback(y * columns + c, values, i);
23
+ }
24
+ }
25
+ }
26
+ };
27
+ // Counting sort: count the lights of each cell, then fill each cell's slice.
28
+ const counts = new Uint32Array(columns * rows),
29
+ next = new Uint32Array(columns * rows);
30
+ each(key => counts[key]++);
31
+ const entries = counts.reduce((sum, value) => sum + value, 0);
32
+ const length = (2 + columns * rows + entries * 2) * 4;
33
+ if (length * 4 > maxBytes) {
34
+ throw new Error('Streetlight grid exceeds GPU storage limit');
35
+ }
36
+ data = new Float32Array(length);
37
+ data.set([minX, minZ, cellSize, columns, rows, count, 0, 0]);
38
+ let offset = 2 + columns * rows;
39
+ for (let key = 0; key < counts.length; key++) if (counts[key]) {
40
+ data[(2 + key) * 4] = next[key] = offset;
41
+ data[(2 + key) * 4 + 1] = counts[key];
42
+ offset += counts[key] * 2;
43
+ }
44
+ each((key, values, i) => {
45
+ for (let j = 0, o = next[key] * 4; j < 8; j++) data[o + j] = values[i + j];
46
+ next[key] += 2;
47
+ });
48
+ }
49
+ return { data, count };
50
+ }
@@ -0,0 +1,9 @@
1
+ // [part, pivot x, pivot y, swing sign]
2
+
3
+ export const limbs = [
4
+ ['body', 0, 0, 0],
5
+ ['leg', -0.09, 0.9, 1],
6
+ ['leg', 0.09, 0.9, -1],
7
+ ['arm', -0.25, 1.42, -1],
8
+ ['arm', 0.25, 1.42, 1]
9
+ ];