@thunderclap-engine/engine 0.0.0-stage → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (566) hide show
  1. package/CHANGELOG.md +390 -0
  2. package/LICENSE +21 -0
  3. package/README.md +333 -2
  4. package/dist/analytics/analytics.d.ts +80 -0
  5. package/dist/analytics/analytics.js +129 -0
  6. package/dist/analytics/index.d.ts +1 -0
  7. package/dist/analytics/index.js +1 -0
  8. package/dist/anim/aim.d.ts +43 -0
  9. package/dist/anim/aim.js +157 -0
  10. package/dist/anim/clip.d.ts +98 -0
  11. package/dist/anim/clip.js +282 -0
  12. package/dist/anim/compress.d.ts +65 -0
  13. package/dist/anim/compress.js +339 -0
  14. package/dist/anim/foot-ik.d.ts +74 -0
  15. package/dist/anim/foot-ik.js +241 -0
  16. package/dist/anim/graph.d.ts +153 -0
  17. package/dist/anim/graph.js +532 -0
  18. package/dist/anim/ik.d.ts +105 -0
  19. package/dist/anim/ik.js +435 -0
  20. package/dist/anim/index.d.ts +36 -0
  21. package/dist/anim/index.js +21 -0
  22. package/dist/anim/match.d.ts +66 -0
  23. package/dist/anim/match.js +153 -0
  24. package/dist/anim/mixer.d.ts +113 -0
  25. package/dist/anim/mixer.js +314 -0
  26. package/dist/anim/morph.d.ts +41 -0
  27. package/dist/anim/morph.js +94 -0
  28. package/dist/anim/pose.d.ts +74 -0
  29. package/dist/anim/pose.js +254 -0
  30. package/dist/anim/quat.d.ts +44 -0
  31. package/dist/anim/quat.js +187 -0
  32. package/dist/anim/retarget.d.ts +97 -0
  33. package/dist/anim/retarget.js +366 -0
  34. package/dist/anim/root-motion.d.ts +44 -0
  35. package/dist/anim/root-motion.js +224 -0
  36. package/dist/anim/skin-pose.d.ts +39 -0
  37. package/dist/anim/skin-pose.js +53 -0
  38. package/dist/anim/socket.d.ts +47 -0
  39. package/dist/anim/socket.js +84 -0
  40. package/dist/anim/spring-chain.d.ts +73 -0
  41. package/dist/anim/spring-chain.js +294 -0
  42. package/dist/assets/atlas.d.ts +90 -0
  43. package/dist/assets/atlas.js +212 -0
  44. package/dist/assets/baked.d.ts +33 -0
  45. package/dist/assets/baked.js +38 -0
  46. package/dist/assets/bundle.d.ts +88 -0
  47. package/dist/assets/bundle.js +464 -0
  48. package/dist/assets/cache.d.ts +56 -0
  49. package/dist/assets/cache.js +123 -0
  50. package/dist/assets/gltf-load.d.ts +252 -0
  51. package/dist/assets/gltf-load.js +661 -0
  52. package/dist/assets/gltf-skin.d.ts +36 -0
  53. package/dist/assets/gltf-skin.js +109 -0
  54. package/dist/assets/gltf.d.ts +706 -0
  55. package/dist/assets/gltf.js +1376 -0
  56. package/dist/assets/index.d.ts +20 -0
  57. package/dist/assets/index.js +10 -0
  58. package/dist/assets/ktx2.d.ts +71 -0
  59. package/dist/assets/ktx2.js +213 -0
  60. package/dist/assets/manifest.d.ts +79 -0
  61. package/dist/assets/manifest.js +7 -0
  62. package/dist/assets/meshopt.d.ts +23 -0
  63. package/dist/assets/meshopt.js +403 -0
  64. package/dist/audio/audio.d.ts +733 -0
  65. package/dist/audio/audio.js +2013 -0
  66. package/dist/audio/dsp.d.ts +61 -0
  67. package/dist/audio/dsp.js +159 -0
  68. package/dist/audio/duck.d.ts +44 -0
  69. package/dist/audio/duck.js +101 -0
  70. package/dist/audio/envelope.d.ts +53 -0
  71. package/dist/audio/envelope.js +106 -0
  72. package/dist/audio/index.d.ts +13 -0
  73. package/dist/audio/index.js +14 -0
  74. package/dist/audio/music.d.ts +113 -0
  75. package/dist/audio/music.js +548 -0
  76. package/dist/audio/occlusion.d.ts +55 -0
  77. package/dist/audio/occlusion.js +61 -0
  78. package/dist/audio/persist.d.ts +23 -0
  79. package/dist/audio/persist.js +27 -0
  80. package/dist/audio/recipes.d.ts +55 -0
  81. package/dist/audio/recipes.js +227 -0
  82. package/dist/audio/send.d.ts +41 -0
  83. package/dist/audio/send.js +118 -0
  84. package/dist/audio/sprites.d.ts +59 -0
  85. package/dist/audio/sprites.js +43 -0
  86. package/dist/audio/synth.d.ts +103 -0
  87. package/dist/audio/synth.js +197 -0
  88. package/dist/audio/variations.d.ts +25 -0
  89. package/dist/audio/variations.js +55 -0
  90. package/dist/audio/zones.d.ts +100 -0
  91. package/dist/audio/zones.js +167 -0
  92. package/dist/core/detached-surface.d.ts +44 -0
  93. package/dist/core/detached-surface.js +104 -0
  94. package/dist/core/events.d.ts +24 -0
  95. package/dist/core/events.js +43 -0
  96. package/dist/core/game.d.ts +409 -0
  97. package/dist/core/game.js +530 -0
  98. package/dist/core/hash.d.ts +24 -0
  99. package/dist/core/hash.js +49 -0
  100. package/dist/core/index.d.ts +17 -0
  101. package/dist/core/index.js +9 -0
  102. package/dist/core/loop.d.ts +113 -0
  103. package/dist/core/loop.js +185 -0
  104. package/dist/core/math.d.ts +58 -0
  105. package/dist/core/math.js +210 -0
  106. package/dist/core/noise.d.ts +40 -0
  107. package/dist/core/noise.js +247 -0
  108. package/dist/core/pool.d.ts +42 -0
  109. package/dist/core/pool.js +85 -0
  110. package/dist/core/random.d.ts +61 -0
  111. package/dist/core/random.js +199 -0
  112. package/dist/core/scene.d.ts +79 -0
  113. package/dist/core/scene.js +195 -0
  114. package/dist/core/timer.d.ts +66 -0
  115. package/dist/core/timer.js +286 -0
  116. package/dist/fx/billboard-wgsl.d.ts +29 -0
  117. package/dist/fx/billboard-wgsl.js +158 -0
  118. package/dist/fx/billboard.d.ts +249 -0
  119. package/dist/fx/billboard.js +702 -0
  120. package/dist/fx/debug-draw.d.ts +127 -0
  121. package/dist/fx/debug-draw.js +523 -0
  122. package/dist/fx/debug-wgsl.d.ts +7 -0
  123. package/dist/fx/debug-wgsl.js +32 -0
  124. package/dist/fx/decals-wgsl.d.ts +15 -0
  125. package/dist/fx/decals-wgsl.js +173 -0
  126. package/dist/fx/decals.d.ts +216 -0
  127. package/dist/fx/decals.js +607 -0
  128. package/dist/fx/effect.d.ts +129 -0
  129. package/dist/fx/effect.js +349 -0
  130. package/dist/fx/effects/hit-spark.json +48 -0
  131. package/dist/fx/effects/index.d.ts +8 -0
  132. package/dist/fx/effects/index.js +9 -0
  133. package/dist/fx/effects/magic-aura.json +47 -0
  134. package/dist/fx/effects/smoke-puff.json +34 -0
  135. package/dist/fx/emit-surface.d.ts +40 -0
  136. package/dist/fx/emit-surface.js +124 -0
  137. package/dist/fx/flicker.d.ts +30 -0
  138. package/dist/fx/flicker.js +42 -0
  139. package/dist/fx/index.d.ts +31 -0
  140. package/dist/fx/index.js +20 -0
  141. package/dist/fx/particles-wgsl.d.ts +57 -0
  142. package/dist/fx/particles-wgsl.js +828 -0
  143. package/dist/fx/particles.d.ts +566 -0
  144. package/dist/fx/particles.js +1533 -0
  145. package/dist/fx/random.d.ts +15 -0
  146. package/dist/fx/random.js +20 -0
  147. package/dist/fx/sky-wgsl.d.ts +23 -0
  148. package/dist/fx/sky-wgsl.js +127 -0
  149. package/dist/fx/sky.d.ts +96 -0
  150. package/dist/fx/sky.js +175 -0
  151. package/dist/fx/text-atlas.d.ts +143 -0
  152. package/dist/fx/text-atlas.js +327 -0
  153. package/dist/fx/trail-wgsl.d.ts +11 -0
  154. package/dist/fx/trail-wgsl.js +42 -0
  155. package/dist/fx/trail.d.ts +194 -0
  156. package/dist/fx/trail.js +555 -0
  157. package/dist/fx/water-wgsl.d.ts +34 -0
  158. package/dist/fx/water-wgsl.js +197 -0
  159. package/dist/fx/water.d.ts +176 -0
  160. package/dist/fx/water.js +371 -0
  161. package/dist/geom/collide/bvh.d.ts +151 -0
  162. package/dist/geom/collide/bvh.js +493 -0
  163. package/dist/geom/collide/debug.d.ts +14 -0
  164. package/dist/geom/collide/debug.js +74 -0
  165. package/dist/geom/collide/grid.d.ts +26 -0
  166. package/dist/geom/collide/grid.js +91 -0
  167. package/dist/geom/collide/index.d.ts +8 -0
  168. package/dist/geom/collide/index.js +8 -0
  169. package/dist/geom/collide/queries.d.ts +70 -0
  170. package/dist/geom/collide/queries.js +583 -0
  171. package/dist/geom/collide/serialize.d.ts +14 -0
  172. package/dist/geom/collide/serialize.js +145 -0
  173. package/dist/geom/collide/shapes.d.ts +161 -0
  174. package/dist/geom/collide/shapes.js +686 -0
  175. package/dist/geom/collide/slide.d.ts +66 -0
  176. package/dist/geom/collide/slide.js +375 -0
  177. package/dist/geom/collide/tile-slide.d.ts +88 -0
  178. package/dist/geom/collide/tile-slide.js +255 -0
  179. package/dist/geom/geometry.d.ts +95 -0
  180. package/dist/geom/geometry.js +322 -0
  181. package/dist/geom/heightfield.d.ts +72 -0
  182. package/dist/geom/heightfield.js +295 -0
  183. package/dist/geom/hull.d.ts +27 -0
  184. package/dist/geom/hull.js +279 -0
  185. package/dist/geom/index.d.ts +35 -0
  186. package/dist/geom/index.js +23 -0
  187. package/dist/geom/iso.d.ts +74 -0
  188. package/dist/geom/iso.js +89 -0
  189. package/dist/geom/lod.d.ts +29 -0
  190. package/dist/geom/lod.js +27 -0
  191. package/dist/geom/ops.d.ts +47 -0
  192. package/dist/geom/ops.js +285 -0
  193. package/dist/geom/primitives.d.ts +97 -0
  194. package/dist/geom/primitives.js +359 -0
  195. package/dist/geom/shapes.d.ts +43 -0
  196. package/dist/geom/shapes.js +88 -0
  197. package/dist/geom/simplify.d.ts +38 -0
  198. package/dist/geom/simplify.js +519 -0
  199. package/dist/geom/split.d.ts +37 -0
  200. package/dist/geom/split.js +413 -0
  201. package/dist/geom/sweep.d.ts +83 -0
  202. package/dist/geom/sweep.js +534 -0
  203. package/dist/geom/tangents.d.ts +16 -0
  204. package/dist/geom/tangents.js +124 -0
  205. package/dist/geom/triangulate.d.ts +19 -0
  206. package/dist/geom/triangulate.js +147 -0
  207. package/dist/host/default.d.ts +10 -0
  208. package/dist/host/default.js +10 -0
  209. package/dist/host/index.d.ts +4 -0
  210. package/dist/host/index.js +3 -0
  211. package/dist/host/types.d.ts +144 -0
  212. package/dist/host/types.js +1 -0
  213. package/dist/host/web-links.d.ts +38 -0
  214. package/dist/host/web-links.js +110 -0
  215. package/dist/host/web.d.ts +30 -0
  216. package/dist/host/web.js +216 -0
  217. package/dist/host/xr.d.ts +24 -0
  218. package/dist/host/xr.js +59 -0
  219. package/dist/i18n/i18n.d.ts +59 -0
  220. package/dist/i18n/i18n.js +241 -0
  221. package/dist/i18n/index.d.ts +3 -0
  222. package/dist/i18n/index.js +3 -0
  223. package/dist/i18n/message.d.ts +72 -0
  224. package/dist/i18n/message.js +369 -0
  225. package/dist/i18n/negotiate.d.ts +17 -0
  226. package/dist/i18n/negotiate.js +58 -0
  227. package/dist/index.d.ts +7 -0
  228. package/dist/index.js +1 -0
  229. package/dist/input/bindings.d.ts +31 -0
  230. package/dist/input/bindings.js +141 -0
  231. package/dist/input/clock.d.ts +44 -0
  232. package/dist/input/clock.js +49 -0
  233. package/dist/input/follow.d.ts +133 -0
  234. package/dist/input/follow.js +218 -0
  235. package/dist/input/gestures.d.ts +281 -0
  236. package/dist/input/gestures.js +662 -0
  237. package/dist/input/glyphs.d.ts +35 -0
  238. package/dist/input/glyphs.js +216 -0
  239. package/dist/input/gyro.d.ts +85 -0
  240. package/dist/input/gyro.js +140 -0
  241. package/dist/input/index.d.ts +19 -0
  242. package/dist/input/index.js +16 -0
  243. package/dist/input/input.d.ts +543 -0
  244. package/dist/input/input.js +1492 -0
  245. package/dist/input/look.d.ts +327 -0
  246. package/dist/input/look.js +681 -0
  247. package/dist/input/magnify.d.ts +177 -0
  248. package/dist/input/magnify.js +131 -0
  249. package/dist/input/pointer-dispatch.d.ts +138 -0
  250. package/dist/input/pointer-dispatch.js +180 -0
  251. package/dist/input/pointer-router.d.ts +204 -0
  252. package/dist/input/pointer-router.js +533 -0
  253. package/dist/input/pointer-sources.d.ts +164 -0
  254. package/dist/input/pointer-sources.js +306 -0
  255. package/dist/input/rays.d.ts +138 -0
  256. package/dist/input/rays.js +615 -0
  257. package/dist/input/record.d.ts +209 -0
  258. package/dist/input/record.js +601 -0
  259. package/dist/input/touch-zones.d.ts +147 -0
  260. package/dist/input/touch-zones.js +300 -0
  261. package/dist/input/types.d.ts +158 -0
  262. package/dist/input/types.js +1 -0
  263. package/dist/input/xr-source.d.ts +53 -0
  264. package/dist/input/xr-source.js +164 -0
  265. package/dist/nav/astar.d.ts +45 -0
  266. package/dist/nav/astar.js +182 -0
  267. package/dist/nav/corridor.d.ts +40 -0
  268. package/dist/nav/corridor.js +95 -0
  269. package/dist/nav/crowd.d.ts +94 -0
  270. package/dist/nav/crowd.js +624 -0
  271. package/dist/nav/flow.d.ts +61 -0
  272. package/dist/nav/flow.js +193 -0
  273. package/dist/nav/grid.d.ts +108 -0
  274. package/dist/nav/grid.js +210 -0
  275. package/dist/nav/heap.d.ts +22 -0
  276. package/dist/nav/heap.js +92 -0
  277. package/dist/nav/index.d.ts +37 -0
  278. package/dist/nav/index.js +19 -0
  279. package/dist/nav/mesh/areas.d.ts +44 -0
  280. package/dist/nav/mesh/areas.js +98 -0
  281. package/dist/nav/mesh/bake-options.d.ts +33 -0
  282. package/dist/nav/mesh/bake-options.js +76 -0
  283. package/dist/nav/mesh/contour.d.ts +22 -0
  284. package/dist/nav/mesh/contour.js +323 -0
  285. package/dist/nav/mesh/flow3.d.ts +35 -0
  286. package/dist/nav/mesh/flow3.js +229 -0
  287. package/dist/nav/mesh/links.d.ts +38 -0
  288. package/dist/nav/mesh/links.js +72 -0
  289. package/dist/nav/mesh/mesh-path.d.ts +152 -0
  290. package/dist/nav/mesh/mesh-path.js +643 -0
  291. package/dist/nav/mesh/mesh-reach.d.ts +78 -0
  292. package/dist/nav/mesh/mesh-reach.js +450 -0
  293. package/dist/nav/mesh/navmesh.d.ts +117 -0
  294. package/dist/nav/mesh/navmesh.js +647 -0
  295. package/dist/nav/mesh/polymesh.d.ts +24 -0
  296. package/dist/nav/mesh/polymesh.js +384 -0
  297. package/dist/nav/mesh/regions.d.ts +12 -0
  298. package/dist/nav/mesh/regions.js +367 -0
  299. package/dist/nav/mesh/serialize.d.ts +13 -0
  300. package/dist/nav/mesh/serialize.js +197 -0
  301. package/dist/nav/mesh/voxelize.d.ts +111 -0
  302. package/dist/nav/mesh/voxelize.js +552 -0
  303. package/dist/nav/obstacles.d.ts +75 -0
  304. package/dist/nav/obstacles.js +294 -0
  305. package/dist/nav/path.d.ts +59 -0
  306. package/dist/nav/path.js +177 -0
  307. package/dist/nav/query-queue.d.ts +46 -0
  308. package/dist/nav/query-queue.js +308 -0
  309. package/dist/nav/reach.d.ts +53 -0
  310. package/dist/nav/reach.js +148 -0
  311. package/dist/nav/steer.d.ts +36 -0
  312. package/dist/nav/steer.js +78 -0
  313. package/dist/platform/boot.d.ts +28 -0
  314. package/dist/platform/boot.js +43 -0
  315. package/dist/platform/device-mode.d.ts +40 -0
  316. package/dist/platform/device-mode.js +104 -0
  317. package/dist/platform/device.d.ts +31 -0
  318. package/dist/platform/device.js +91 -0
  319. package/dist/platform/environment.d.ts +42 -0
  320. package/dist/platform/environment.js +82 -0
  321. package/dist/platform/gpu.d.ts +40 -0
  322. package/dist/platform/gpu.js +57 -0
  323. package/dist/platform/index.d.ts +18 -0
  324. package/dist/platform/index.js +10 -0
  325. package/dist/platform/letterbox.d.ts +43 -0
  326. package/dist/platform/letterbox.js +57 -0
  327. package/dist/platform/links.d.ts +20 -0
  328. package/dist/platform/links.js +43 -0
  329. package/dist/platform/screens.d.ts +36 -0
  330. package/dist/platform/screens.js +138 -0
  331. package/dist/platform/surface.d.ts +72 -0
  332. package/dist/platform/surface.js +157 -0
  333. package/dist/platform/xr-fake.d.ts +168 -0
  334. package/dist/platform/xr-fake.js +434 -0
  335. package/dist/platform/xr-surface.d.ts +120 -0
  336. package/dist/platform/xr-surface.js +214 -0
  337. package/dist/platform/xr-types.d.ts +262 -0
  338. package/dist/post/ao.d.ts +12 -0
  339. package/dist/post/ao.js +136 -0
  340. package/dist/post/blend.d.ts +27 -0
  341. package/dist/post/blend.js +129 -0
  342. package/dist/post/depth-pass.d.ts +43 -0
  343. package/dist/post/depth-pass.js +118 -0
  344. package/dist/post/dof.d.ts +1 -0
  345. package/dist/post/dof.js +66 -0
  346. package/dist/post/exposure.d.ts +80 -0
  347. package/dist/post/exposure.js +322 -0
  348. package/dist/post/index.d.ts +12 -0
  349. package/dist/post/index.js +11 -0
  350. package/dist/post/lens-dirt.d.ts +13 -0
  351. package/dist/post/lens-dirt.js +91 -0
  352. package/dist/post/lut.d.ts +19 -0
  353. package/dist/post/lut.js +50 -0
  354. package/dist/post/motion-blur.d.ts +9 -0
  355. package/dist/post/motion-blur.js +78 -0
  356. package/dist/post/post-stack.d.ts +302 -0
  357. package/dist/post/post-stack.js +1137 -0
  358. package/dist/post/settings.d.ts +485 -0
  359. package/dist/post/settings.js +416 -0
  360. package/dist/post/shaders.d.ts +25 -0
  361. package/dist/post/shaders.js +410 -0
  362. package/dist/post/ssr.d.ts +16 -0
  363. package/dist/post/ssr.js +155 -0
  364. package/dist/post/taa.d.ts +74 -0
  365. package/dist/post/taa.js +235 -0
  366. package/dist/post/white-balance.d.ts +25 -0
  367. package/dist/post/white-balance.js +98 -0
  368. package/dist/render/bindings.d.ts +98 -0
  369. package/dist/render/bindings.js +281 -0
  370. package/dist/render/blend.d.ts +13 -0
  371. package/dist/render/blend.js +26 -0
  372. package/dist/render/camera-2d.d.ts +72 -0
  373. package/dist/render/camera-2d.js +92 -0
  374. package/dist/render/camera.d.ts +302 -0
  375. package/dist/render/camera.js +671 -0
  376. package/dist/render/color.d.ts +16 -0
  377. package/dist/render/color.js +41 -0
  378. package/dist/render/compressed.d.ts +104 -0
  379. package/dist/render/compressed.js +248 -0
  380. package/dist/render/diagnostics.d.ts +15 -0
  381. package/dist/render/diagnostics.js +43 -0
  382. package/dist/render/dynamic-resolution.d.ts +70 -0
  383. package/dist/render/dynamic-resolution.js +126 -0
  384. package/dist/render/fake-gpu.d.ts +204 -0
  385. package/dist/render/fake-gpu.js +426 -0
  386. package/dist/render/flipbook.d.ts +56 -0
  387. package/dist/render/flipbook.js +87 -0
  388. package/dist/render/frame.d.ts +278 -0
  389. package/dist/render/frame.js +174 -0
  390. package/dist/render/fullscreen.d.ts +54 -0
  391. package/dist/render/fullscreen.js +91 -0
  392. package/dist/render/gpu-timer.d.ts +73 -0
  393. package/dist/render/gpu-timer.js +186 -0
  394. package/dist/render/index.d.ts +53 -0
  395. package/dist/render/index.js +29 -0
  396. package/dist/render/instance-list.d.ts +185 -0
  397. package/dist/render/instance-list.js +547 -0
  398. package/dist/render/lights.d.ts +181 -0
  399. package/dist/render/lights.js +233 -0
  400. package/dist/render/lod.d.ts +54 -0
  401. package/dist/render/lod.js +52 -0
  402. package/dist/render/material.d.ts +165 -0
  403. package/dist/render/material.js +292 -0
  404. package/dist/render/mesh.d.ts +284 -0
  405. package/dist/render/mesh.js +472 -0
  406. package/dist/render/mipmap.d.ts +16 -0
  407. package/dist/render/mipmap.js +121 -0
  408. package/dist/render/parallax.d.ts +50 -0
  409. package/dist/render/parallax.js +47 -0
  410. package/dist/render/pbr-wgsl.d.ts +31 -0
  411. package/dist/render/pbr-wgsl.js +119 -0
  412. package/dist/render/ping-pong.d.ts +42 -0
  413. package/dist/render/ping-pong.js +74 -0
  414. package/dist/render/renderer.d.ts +741 -0
  415. package/dist/render/renderer.js +2486 -0
  416. package/dist/render/scene-pipelines.d.ts +44 -0
  417. package/dist/render/scene-pipelines.js +92 -0
  418. package/dist/render/scene-target.d.ts +170 -0
  419. package/dist/render/scene-target.js +450 -0
  420. package/dist/render/shadow.d.ts +74 -0
  421. package/dist/render/shadow.js +208 -0
  422. package/dist/render/skin.d.ts +112 -0
  423. package/dist/render/skin.js +240 -0
  424. package/dist/render/snapshot.d.ts +36 -0
  425. package/dist/render/snapshot.js +34 -0
  426. package/dist/render/standard.d.ts +162 -0
  427. package/dist/render/standard.js +263 -0
  428. package/dist/render/texture.d.ts +142 -0
  429. package/dist/render/texture.js +228 -0
  430. package/dist/render/tile-layer.d.ts +110 -0
  431. package/dist/render/tile-layer.js +304 -0
  432. package/dist/render/transform.d.ts +115 -0
  433. package/dist/render/transform.js +318 -0
  434. package/dist/render/wgsl.d.ts +131 -0
  435. package/dist/render/wgsl.js +528 -0
  436. package/dist/save/codec.d.ts +49 -0
  437. package/dist/save/codec.js +169 -0
  438. package/dist/save/index.d.ts +8 -0
  439. package/dist/save/index.js +8 -0
  440. package/dist/save/journal.d.ts +24 -0
  441. package/dist/save/journal.js +102 -0
  442. package/dist/save/migrate.d.ts +15 -0
  443. package/dist/save/migrate.js +37 -0
  444. package/dist/save/schema.d.ts +72 -0
  445. package/dist/save/schema.js +154 -0
  446. package/dist/save/settings.d.ts +28 -0
  447. package/dist/save/settings.js +59 -0
  448. package/dist/save/slots.d.ts +56 -0
  449. package/dist/save/slots.js +200 -0
  450. package/dist/save/storage.d.ts +35 -0
  451. package/dist/save/storage.js +62 -0
  452. package/dist/save/store.d.ts +114 -0
  453. package/dist/save/store.js +269 -0
  454. package/dist/testing/fake-host.d.ts +103 -0
  455. package/dist/testing/fake-host.js +163 -0
  456. package/dist/testing/fixed-clock.d.ts +25 -0
  457. package/dist/testing/fixed-clock.js +30 -0
  458. package/dist/testing/index.d.ts +4 -0
  459. package/dist/testing/index.js +5 -0
  460. package/dist/testing/test-game.d.ts +76 -0
  461. package/dist/testing/test-game.js +92 -0
  462. package/dist/tween/ease.d.ts +77 -0
  463. package/dist/tween/ease.js +192 -0
  464. package/dist/tween/index.d.ts +8 -0
  465. package/dist/tween/index.js +7 -0
  466. package/dist/tween/timeline.d.ts +78 -0
  467. package/dist/tween/timeline.js +269 -0
  468. package/dist/tween/tween.d.ts +168 -0
  469. package/dist/tween/tween.js +320 -0
  470. package/dist/ui/anchor.d.ts +206 -0
  471. package/dist/ui/anchor.js +307 -0
  472. package/dist/ui/caption.d.ts +122 -0
  473. package/dist/ui/caption.js +286 -0
  474. package/dist/ui/cursor.d.ts +105 -0
  475. package/dist/ui/cursor.js +261 -0
  476. package/dist/ui/dom.d.ts +30 -0
  477. package/dist/ui/dom.js +92 -0
  478. package/dist/ui/floats.d.ts +86 -0
  479. package/dist/ui/floats.js +260 -0
  480. package/dist/ui/hud.d.ts +198 -0
  481. package/dist/ui/hud.js +431 -0
  482. package/dist/ui/index.d.ts +37 -0
  483. package/dist/ui/index.js +34 -0
  484. package/dist/ui/inventory-card.d.ts +52 -0
  485. package/dist/ui/inventory-card.js +173 -0
  486. package/dist/ui/inventory-context.d.ts +29 -0
  487. package/dist/ui/inventory-context.js +125 -0
  488. package/dist/ui/inventory-drag.d.ts +63 -0
  489. package/dist/ui/inventory-drag.js +394 -0
  490. package/dist/ui/inventory-grid.d.ts +66 -0
  491. package/dist/ui/inventory-grid.js +625 -0
  492. package/dist/ui/inventory-radial.d.ts +39 -0
  493. package/dist/ui/inventory-radial.js +168 -0
  494. package/dist/ui/inventory.d.ts +128 -0
  495. package/dist/ui/inventory.js +154 -0
  496. package/dist/ui/layout.d.ts +356 -0
  497. package/dist/ui/layout.js +856 -0
  498. package/dist/ui/link.d.ts +64 -0
  499. package/dist/ui/link.js +155 -0
  500. package/dist/ui/loading.d.ts +40 -0
  501. package/dist/ui/loading.js +157 -0
  502. package/dist/ui/loupe.d.ts +74 -0
  503. package/dist/ui/loupe.js +164 -0
  504. package/dist/ui/menu-nav.d.ts +33 -0
  505. package/dist/ui/menu-nav.js +28 -0
  506. package/dist/ui/minimap-canvas.d.ts +145 -0
  507. package/dist/ui/minimap-canvas.js +460 -0
  508. package/dist/ui/notify.d.ts +40 -0
  509. package/dist/ui/notify.js +141 -0
  510. package/dist/ui/orb.d.ts +53 -0
  511. package/dist/ui/orb.js +304 -0
  512. package/dist/ui/overlay.d.ts +213 -0
  513. package/dist/ui/overlay.js +394 -0
  514. package/dist/ui/padnav.d.ts +53 -0
  515. package/dist/ui/padnav.js +146 -0
  516. package/dist/ui/perf.d.ts +130 -0
  517. package/dist/ui/perf.js +329 -0
  518. package/dist/ui/rotate-card.d.ts +54 -0
  519. package/dist/ui/rotate-card.js +97 -0
  520. package/dist/ui/stack.d.ts +128 -0
  521. package/dist/ui/stack.js +312 -0
  522. package/dist/ui/styles.d.ts +13 -0
  523. package/dist/ui/styles.js +200 -0
  524. package/dist/ui/text-scale.d.ts +67 -0
  525. package/dist/ui/text-scale.js +102 -0
  526. package/dist/ui/theme.d.ts +70 -0
  527. package/dist/ui/theme.js +98 -0
  528. package/dist/ui/toast.d.ts +23 -0
  529. package/dist/ui/toast.js +46 -0
  530. package/dist/ui/tooltip.d.ts +89 -0
  531. package/dist/ui/tooltip.js +333 -0
  532. package/dist/ui/widgets-2.d.ts +134 -0
  533. package/dist/ui/widgets-2.js +399 -0
  534. package/dist/ui/widgets-3.d.ts +91 -0
  535. package/dist/ui/widgets-3.js +212 -0
  536. package/dist/ui/widgets.d.ts +34 -0
  537. package/dist/ui/widgets.js +50 -0
  538. package/dist/ui/world-panel/index.d.ts +5 -0
  539. package/dist/ui/world-panel/index.js +5 -0
  540. package/dist/ui/world-panel/layout.d.ts +38 -0
  541. package/dist/ui/world-panel/layout.js +68 -0
  542. package/dist/ui/world-panel/paint.d.ts +96 -0
  543. package/dist/ui/world-panel/paint.js +136 -0
  544. package/dist/ui/world-panel/panel.d.ts +235 -0
  545. package/dist/ui/world-panel/panel.js +762 -0
  546. package/dist/ui/world-panel/wgsl.d.ts +10 -0
  547. package/dist/ui/world-panel/wgsl.js +52 -0
  548. package/dist/ui/world-panel/widgets.d.ts +207 -0
  549. package/dist/ui/world-panel/widgets.js +569 -0
  550. package/dist/voxel/chunks.d.ts +77 -0
  551. package/dist/voxel/chunks.js +149 -0
  552. package/dist/voxel/grid.d.ts +84 -0
  553. package/dist/voxel/grid.js +223 -0
  554. package/dist/voxel/index.d.ts +22 -0
  555. package/dist/voxel/index.js +7 -0
  556. package/dist/voxel/mesher-worker.d.ts +14 -0
  557. package/dist/voxel/mesher-worker.js +47 -0
  558. package/dist/voxel/mesher.d.ts +73 -0
  559. package/dist/voxel/mesher.js +306 -0
  560. package/dist/voxel/ray.d.ts +32 -0
  561. package/dist/voxel/ray.js +73 -0
  562. package/dist/voxel/wgsl.d.ts +16 -0
  563. package/dist/voxel/wgsl.js +28 -0
  564. package/dist/voxel/worker-client.d.ts +79 -0
  565. package/dist/voxel/worker-client.js +122 -0
  566. package/package.json +177 -3
@@ -0,0 +1,35 @@
1
+ /**
2
+ * `@thunderclap-engine/engine/geom`: primitive geometry (box, plane, sphere, icosphere, capsule,
3
+ * cylinder, torus) in the engine's 3D vertex layout with bounds, merge and transform helpers,
4
+ * heightfields with bilinear sampling, normals, an exact ray test and a mesh builder, shapes
5
+ * swept from 2D profiles (extrude, lathe, sweep, tube, polygon, stairs, arch), tangent frames
6
+ * and per-geometry operations (flat shading, welding, uv projection, fitting).
7
+ * Pure arithmetic: no GPU, no DOM; `render/` supplies only the layouts and their types.
8
+ */
9
+ export type { Box2, Capsule, Circle, ColliderBounds, ColliderSource, ColliderTransform, Contact, GeomAabb, GeometryMeshSource, GeometrySource, GridSource, HeightfieldSource, PositionsSource, RayHit, Shape, Shape2, SlideOptions, SlideResult, SourceKind, SourceRecord, Sphere, StaticColliderOptions, SweepHit, TileBox, TileGridSource, TileKind, TileMover, TileQuery, TileSlideOptions, TileSlideResult, Vec3Out, WireframeMode, } from './collide/index.js';
10
+ export { ALL_LAYERS, aabbTriangle, applyTransform, capsuleTriangle, carryBy, closestPointTriangle, closestSegmentSegment, closestSegmentTriangle, colliderTriangle, colliderWireframe, colliderWireframeLength, createContact, createHit, createSlideResult, createStaticCollider, createSweepHit, createTileSlideResult, exportCollider, gridSolid, gridTriangles, importCollider, isAabb, isBox2, isCapsule, overlap, overlap2, raycast, raycast2, raycastReg, SOURCE_GEOMETRY, SOURCE_GRID, SOURCE_HEIGHTFIELD, StaticCollider, shapeBounds, shapeTriangle, slide, slide2, slideTiles, sphereTriangle, sweep as sweepShape, sweep2, TILE_EMPTY, TILE_ONE_WAY, TILE_SOLID, triangleNormal, } from './collide/index.js';
11
+ export type { Geometry, GeometryOptions, Rgba } from './geometry.js';
12
+ export { cloneGeometry, computeBounds, createIndices, GEOMETRY_FLOATS, GeometryWriter, mergeGeometry, transformGeometry, UINT16_MAX_VERTICES, } from './geometry.js';
13
+ export type { Heightfield, HeightfieldGeometryOptions, HeightfieldOptions, HeightfieldRay, HeightfieldVec3, } from './heightfield.js';
14
+ export { createHeightfield, heightAt, heightfieldGeometry, normalAt, raycastHeightfield, rayHeightfield, } from './heightfield.js';
15
+ export type { CollisionProxyOptions } from './hull.js';
16
+ export { collisionProxy, convexHull } from './hull.js';
17
+ export type { Iso, IsoHeightAt, IsoOptions, IsoPoint } from './iso.js';
18
+ export { createIso, ISO_ELEV_DEPTH, isoHiddenBy, isoInverseProbe } from './iso.js';
19
+ export type { LodChain } from './lod.js';
20
+ export { projectedSizePx, selectLod } from './lod.js';
21
+ export type { ProjectUvOptions, UvProjection } from './ops.js';
22
+ export { fitBounds, flatShade, flipWinding, projectUv, recenter, weld } from './ops.js';
23
+ export type { BoxOptions, CapsuleOptions, CylinderOptions, IcosphereOptions, PlaneOptions, SphereOptions, TorusOptions, } from './primitives.js';
24
+ export { box, capsule, cylinder, icosphere, plane, sphere, torus } from './primitives.js';
25
+ export type { ArchOptions, StairsOptions } from './shapes.js';
26
+ export { arch, stairs } from './shapes.js';
27
+ export type { SimplifyOptions, SimplifyResult } from './simplify.js';
28
+ export { createLodChain, simplifyGeometry } from './simplify.js';
29
+ export type { SliceOptions, SlicePlane, SliceResult } from './split.js';
30
+ export { sliceGeometry, splitGeometry } from './split.js';
31
+ export type { ExtrudeOptions, LatheOptions, PolygonOptions, Profile2D, SweepOptions, TubeOptions, } from './sweep.js';
32
+ export { extrude, lathe, polygon, sweep, tube } from './sweep.js';
33
+ export type { GeometryTangent } from './tangents.js';
34
+ export { computeTangents, TANGENT_FLOATS } from './tangents.js';
35
+ export { profileArea2, triangulate } from './triangulate.js';
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `@thunderclap-engine/engine/geom`: primitive geometry (box, plane, sphere, icosphere, capsule,
3
+ * cylinder, torus) in the engine's 3D vertex layout with bounds, merge and transform helpers,
4
+ * heightfields with bilinear sampling, normals, an exact ray test and a mesh builder, shapes
5
+ * swept from 2D profiles (extrude, lathe, sweep, tube, polygon, stairs, arch), tangent frames
6
+ * and per-geometry operations (flat shading, welding, uv projection, fitting).
7
+ * Pure arithmetic: no GPU, no DOM; `render/` supplies only the layouts and their types.
8
+ */
9
+ // Collision (ws/collide). The profile `sweep` above keeps its name: the shape sweep is `sweepShape`.
10
+ export { ALL_LAYERS, aabbTriangle, applyTransform, capsuleTriangle, carryBy, closestPointTriangle, closestSegmentSegment, closestSegmentTriangle, colliderTriangle, colliderWireframe, colliderWireframeLength, createContact, createHit, createSlideResult, createStaticCollider, createSweepHit, createTileSlideResult, exportCollider, gridSolid, gridTriangles, importCollider, isAabb, isBox2, isCapsule, overlap, overlap2, raycast, raycast2, raycastReg, SOURCE_GEOMETRY, SOURCE_GRID, SOURCE_HEIGHTFIELD, StaticCollider, shapeBounds, shapeTriangle, slide, slide2, slideTiles, sphereTriangle, sweep as sweepShape, sweep2, TILE_EMPTY, TILE_ONE_WAY, TILE_SOLID, triangleNormal, } from './collide/index.js';
11
+ export { cloneGeometry, computeBounds, createIndices, GEOMETRY_FLOATS, GeometryWriter, mergeGeometry, transformGeometry, UINT16_MAX_VERTICES, } from './geometry.js';
12
+ export { createHeightfield, heightAt, heightfieldGeometry, normalAt, raycastHeightfield, rayHeightfield, } from './heightfield.js';
13
+ export { collisionProxy, convexHull } from './hull.js';
14
+ export { createIso, ISO_ELEV_DEPTH, isoHiddenBy, isoInverseProbe } from './iso.js';
15
+ export { projectedSizePx, selectLod } from './lod.js';
16
+ export { fitBounds, flatShade, flipWinding, projectUv, recenter, weld } from './ops.js';
17
+ export { box, capsule, cylinder, icosphere, plane, sphere, torus } from './primitives.js';
18
+ export { arch, stairs } from './shapes.js';
19
+ export { createLodChain, simplifyGeometry } from './simplify.js';
20
+ export { sliceGeometry, splitGeometry } from './split.js';
21
+ export { extrude, lathe, polygon, sweep, tube } from './sweep.js';
22
+ export { computeTangents, TANGENT_FLOATS } from './tangents.js';
23
+ export { profileArea2, triangulate } from './triangulate.js';
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Isometric (2:1 diamond) projection and its inverse (ws/ergo-2d-2): the maths every
3
+ * isometric game rewrote. Tile space `(tx, ty)` is a square grid turned 45° and squashed to
4
+ * `tileW × tileH` diamonds; elevation `elev` lifts a tile `elevH × elev` px up the screen.
5
+ *
6
+ * x = originX + (tx - ty) × tileW / 2
7
+ * y = originY + (tx + ty) × tileH / 2 - elev × elevH
8
+ *
9
+ * Pure arithmetic in the caller's 2D space (a layer's logical px, a camera's world px): no
10
+ * camera, no map, no allocation (`out` params). `isoInverseProbe` is the pointer-to-tile rule
11
+ * a tactics map needs (the highest elevation whose tile really is that tall wins) and
12
+ * `isoHiddenBy` tells when a tile's top disappears behind a taller front neighbour.
13
+ */
14
+ export interface IsoOptions {
15
+ /** Diamond width and height in px (2:1 is the classic; any ratio works). */
16
+ tileW: number;
17
+ tileH: number;
18
+ /** Px one elevation step lifts a tile. Default `tileH / 2`. */
19
+ elevH?: number;
20
+ /** Position of tile `(0, 0)`'s diamond centre at elevation 0. Default `(0, 0)`. */
21
+ originX?: number;
22
+ originY?: number;
23
+ }
24
+ /** A point `toScreen` / `toTile` fill: any `{ x, y }` (a `CameraPoint`, a `Vec2`). */
25
+ export interface IsoPoint {
26
+ x: number;
27
+ y: number;
28
+ }
29
+ /** Tile heights for `isoInverseProbe` and `isoHiddenBy`: off the map, return a negative number. */
30
+ export type IsoHeightAt = (tx: number, ty: number) => number;
31
+ /**
32
+ * Depth weight of one elevation step in `Iso.depth`: a tile's key is `tx + ty + elev × this`,
33
+ * so elevations under 256 never cross into the next diagonal.
34
+ */
35
+ export declare const ISO_ELEV_DEPTH: number;
36
+ export interface Iso {
37
+ readonly tileW: number;
38
+ readonly tileH: number;
39
+ readonly elevH: number;
40
+ /** Tile `(0, 0)`'s diamond centre at elevation 0. Mutate in place to move the whole lattice. */
41
+ originX: number;
42
+ originY: number;
43
+ /** Diamond centre of tile `(tx, ty)` (fractional allowed) at `elev`, into `out`. */
44
+ toScreen(tx: number, ty: number, elev: number, out: IsoPoint): IsoPoint;
45
+ /**
46
+ * Fractional tile coordinates of screen point `(sx, sy)` assuming the ground there is at
47
+ * `elev`, into `out`. Tile centres are integers: round to pick the tile.
48
+ */
49
+ toTile(sx: number, sy: number, elev: number, out: IsoPoint): IsoPoint;
50
+ /**
51
+ * Painter's-order key: back to front along `tx + ty`, then `elev × ISO_ELEV_DEPTH`. Equal
52
+ * for the tiles of one diagonal, which never overlap on screen.
53
+ */
54
+ depth(tx: number, ty: number, elev: number): number;
55
+ }
56
+ /** Make an `Iso`. Allocates the object once; everything on it is allocation-free. */
57
+ export declare function createIso(opts: IsoOptions): Iso;
58
+ /**
59
+ * The tile under screen point `(sx, sy)` on a map with elevation: tries every elevation from
60
+ * `maxElev` down to 0 and keeps the first tile whose `heightAt` is that elevation, so a pointer
61
+ * over a raised tile's top lands on it and not on the flat tile the same pixel would cover at
62
+ * ground level. Writes the tile into `out` and returns true; writes `(-1, -1)` and returns
63
+ * false when no tile matches (off the map, or over a riser between levels).
64
+ */
65
+ export declare function isoInverseProbe(iso: Iso, sx: number, sy: number, heightAt: IsoHeightAt, maxElev: number, out: IsoPoint): boolean;
66
+ /**
67
+ * True when the whole top of tile `(tx, ty)` (at `heightAt(tx, ty)`) is covered by taller front
68
+ * neighbours: a column (top diamond plus the wall down to the ground) whose top is at least
69
+ * `tileH` px above ours covers our half of the diamond on its side, so the diagonal front
70
+ * neighbour `(tx + 1, ty + 1)` hides the top alone and `(tx + 1, ty)` with `(tx, ty + 1)` hide
71
+ * it together. With the default `elevH` that is two elevation steps; one step covers the lower
72
+ * quarter and leaves the top visible. Off-map neighbours (negative height) hide nothing.
73
+ */
74
+ export declare function isoHiddenBy(iso: Iso, tx: number, ty: number, heightAt: IsoHeightAt): boolean;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Isometric (2:1 diamond) projection and its inverse (ws/ergo-2d-2): the maths every
3
+ * isometric game rewrote. Tile space `(tx, ty)` is a square grid turned 45° and squashed to
4
+ * `tileW × tileH` diamonds; elevation `elev` lifts a tile `elevH × elev` px up the screen.
5
+ *
6
+ * x = originX + (tx - ty) × tileW / 2
7
+ * y = originY + (tx + ty) × tileH / 2 - elev × elevH
8
+ *
9
+ * Pure arithmetic in the caller's 2D space (a layer's logical px, a camera's world px): no
10
+ * camera, no map, no allocation (`out` params). `isoInverseProbe` is the pointer-to-tile rule
11
+ * a tactics map needs (the highest elevation whose tile really is that tall wins) and
12
+ * `isoHiddenBy` tells when a tile's top disappears behind a taller front neighbour.
13
+ */
14
+ /**
15
+ * Depth weight of one elevation step in `Iso.depth`: a tile's key is `tx + ty + elev × this`,
16
+ * so elevations under 256 never cross into the next diagonal.
17
+ */
18
+ export const ISO_ELEV_DEPTH = 1 / 256;
19
+ /** Make an `Iso`. Allocates the object once; everything on it is allocation-free. */
20
+ export function createIso(opts) {
21
+ const { tileW, tileH } = opts;
22
+ if (!(tileW > 0 && tileH > 0))
23
+ throw new Error('createIso: tileW and tileH must be > 0');
24
+ const elevH = opts.elevH ?? tileH / 2;
25
+ const hw = tileW / 2;
26
+ const hh = tileH / 2;
27
+ const iso = {
28
+ tileW,
29
+ tileH,
30
+ elevH,
31
+ originX: opts.originX ?? 0,
32
+ originY: opts.originY ?? 0,
33
+ toScreen(tx, ty, elev, out) {
34
+ out.x = iso.originX + (tx - ty) * hw;
35
+ out.y = iso.originY + (tx + ty) * hh - elev * elevH;
36
+ return out;
37
+ },
38
+ toTile(sx, sy, elev, out) {
39
+ const a = (sx - iso.originX) / hw;
40
+ const b = (sy - iso.originY + elev * elevH) / hh;
41
+ out.x = (a + b) / 2;
42
+ out.y = (b - a) / 2;
43
+ return out;
44
+ },
45
+ depth(tx, ty, elev) {
46
+ return tx + ty + elev * ISO_ELEV_DEPTH;
47
+ },
48
+ };
49
+ return iso;
50
+ }
51
+ /**
52
+ * The tile under screen point `(sx, sy)` on a map with elevation: tries every elevation from
53
+ * `maxElev` down to 0 and keeps the first tile whose `heightAt` is that elevation, so a pointer
54
+ * over a raised tile's top lands on it and not on the flat tile the same pixel would cover at
55
+ * ground level. Writes the tile into `out` and returns true; writes `(-1, -1)` and returns
56
+ * false when no tile matches (off the map, or over a riser between levels).
57
+ */
58
+ export function isoInverseProbe(iso, sx, sy, heightAt, maxElev, out) {
59
+ for (let e = Math.floor(maxElev); e >= 0; e--) {
60
+ iso.toTile(sx, sy, e, out);
61
+ const tx = Math.floor(out.x + 0.5);
62
+ const ty = Math.floor(out.y + 0.5);
63
+ if (heightAt(tx, ty) === e) {
64
+ out.x = tx;
65
+ out.y = ty;
66
+ return true;
67
+ }
68
+ }
69
+ out.x = -1;
70
+ out.y = -1;
71
+ return false;
72
+ }
73
+ /**
74
+ * True when the whole top of tile `(tx, ty)` (at `heightAt(tx, ty)`) is covered by taller front
75
+ * neighbours: a column (top diamond plus the wall down to the ground) whose top is at least
76
+ * `tileH` px above ours covers our half of the diamond on its side, so the diagonal front
77
+ * neighbour `(tx + 1, ty + 1)` hides the top alone and `(tx + 1, ty)` with `(tx, ty + 1)` hide
78
+ * it together. With the default `elevH` that is two elevation steps; one step covers the lower
79
+ * quarter and leaves the top visible. Off-map neighbours (negative height) hide nothing.
80
+ */
81
+ export function isoHiddenBy(iso, tx, ty, heightAt) {
82
+ const e = heightAt(tx, ty);
83
+ if (e < 0)
84
+ return false;
85
+ const lift = iso.tileH / iso.elevH;
86
+ if (heightAt(tx + 1, ty + 1) - e >= lift)
87
+ return true;
88
+ return heightAt(tx + 1, ty) - e >= lift && heightAt(tx, ty + 1) - e >= lift;
89
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Level-of-detail picking: which entry of a LOD chain to draw for an object at a distance, by
3
+ * the height its bounding sphere covers on screen. Pure arithmetic, no allocation.
4
+ */
5
+ import type { Geometry } from './geometry.js';
6
+ /**
7
+ * A LOD chain: `geometries[0]` is the full mesh and each later entry coarser (`createLodChain`
8
+ * builds one); `meshes` the GPU meshes made from them, parallel, when the caller keeps them
9
+ * here; `thresholdsPx[i]` the smallest on-screen height, in pixels, at which level `i` still
10
+ * draws (descending; a missing entry means level `i` only draws as the last level).
11
+ */
12
+ export interface LodChain<M = unknown> {
13
+ geometries: readonly Geometry[];
14
+ meshes?: readonly M[];
15
+ thresholdsPx: readonly number[];
16
+ }
17
+ /**
18
+ * Pixels a bounding sphere of `boundsRadius` covers vertically at `distance` from a perspective
19
+ * camera with vertical field of view `fovY` (radians) drawing `viewportHeight` pixels: its
20
+ * diameter over the view height at that distance. A distance of 0 or less is `Infinity`.
21
+ */
22
+ export declare function projectedSizePx(boundsRadius: number, distance: number, fovY: number, viewportHeight: number): number;
23
+ /**
24
+ * The level to draw: the first `i` whose `thresholdsPx[i]` the projected size reaches
25
+ * (`>=`, so a size exactly on a threshold takes that level), else the last level. `chain` is the
26
+ * level list (only its length is read: a chain's `geometries` or `meshes`) or the level count.
27
+ * Clamped to `0 .. count - 1`; a count below 1 returns 0.
28
+ */
29
+ export declare function selectLod(chain: readonly unknown[] | number, boundsRadius: number, distance: number, fovY: number, viewportHeight: number, thresholdsPx: readonly number[]): number;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Pixels a bounding sphere of `boundsRadius` covers vertically at `distance` from a perspective
3
+ * camera with vertical field of view `fovY` (radians) drawing `viewportHeight` pixels: its
4
+ * diameter over the view height at that distance. A distance of 0 or less is `Infinity`.
5
+ */
6
+ export function projectedSizePx(boundsRadius, distance, fovY, viewportHeight) {
7
+ if (!(distance > 0))
8
+ return Number.POSITIVE_INFINITY;
9
+ return (boundsRadius * viewportHeight) / (distance * Math.tan(fovY * 0.5));
10
+ }
11
+ /**
12
+ * The level to draw: the first `i` whose `thresholdsPx[i]` the projected size reaches
13
+ * (`>=`, so a size exactly on a threshold takes that level), else the last level. `chain` is the
14
+ * level list (only its length is read: a chain's `geometries` or `meshes`) or the level count.
15
+ * Clamped to `0 .. count - 1`; a count below 1 returns 0.
16
+ */
17
+ export function selectLod(chain, boundsRadius, distance, fovY, viewportHeight, thresholdsPx) {
18
+ const count = typeof chain === 'number' ? chain : chain.length;
19
+ const last = Math.max(0, count - 1);
20
+ const px = projectedSizePx(boundsRadius, distance, fovY, viewportHeight);
21
+ const n = Math.min(last, thresholdsPx.length);
22
+ for (let i = 0; i < n; i++) {
23
+ if (px >= thresholdsPx[i])
24
+ return i;
25
+ }
26
+ return last;
27
+ }
@@ -0,0 +1,47 @@
1
+ import { type Geometry } from './geometry.js';
2
+ /**
3
+ * Unshare every vertex: one vertex per triangle corner (`indices.length` of them, indices
4
+ * `0..n-1`), each carrying its triangle's geometric normal; the other attributes are copied from
5
+ * the source corner. A degenerate triangle keeps its source normals. New geometry, same layout.
6
+ */
7
+ export declare function flatShade(g: Geometry): Geometry;
8
+ /**
9
+ * Merge vertices whose position, normal and uv each lie within `epsilon` (per component) of an
10
+ * earlier vertex's: a spatial hash over positions finds candidates, the first occurrence is kept,
11
+ * indices are remapped and shrink to 16-bit when the result fits. Vertex order is otherwise
12
+ * preserved; colour and tangent are taken from the kept vertex. New geometry, same layout.
13
+ */
14
+ export declare function weld(g: Geometry, epsilon?: number): Geometry;
15
+ /**
16
+ * Turn the geometry inside out: every triangle's winding is reversed and every normal negated
17
+ * (and, in the tangent layout, the handedness, so the bitangent keeps its direction). Bounds are
18
+ * unchanged. Mutates and returns `g`.
19
+ */
20
+ export declare function flipWinding(g: Geometry): Geometry;
21
+ /** How `projectUv` maps positions to uvs. */
22
+ export type UvProjection = 'box' | 'planar' | 'cylindrical' | 'spherical';
23
+ export interface ProjectUvOptions {
24
+ /** Multiplies the projected uvs (one number or `[u, v]`). Default 1: 0..1 across the box. */
25
+ scale?: number | [number, number];
26
+ /** `'planar'` only: the axis the plane faces. Default `'y'` (u along x, v along z). */
27
+ axis?: 'x' | 'y' | 'z';
28
+ }
29
+ /**
30
+ * Overwrite the uvs from the positions, relative to the geometry's axis-aligned box so each
31
+ * coordinate spans 0..1 before `scale`:
32
+ * - `'box'`: each vertex takes the plane facing its normal's dominant axis (x: u = z, v = y;
33
+ * y: u = x, v = z; z: u = x, v = y), so a box or a building block tiles on every face;
34
+ * - `'planar'`: one plane for all vertices, facing `axis`;
35
+ * - `'cylindrical'`: u is the angle around +y (0 at +z, as `cylinder`), v the height;
36
+ * - `'spherical'`: u the angle around +y, v the latitude from the box centre (0 at the top).
37
+ * Mutates and returns `g`.
38
+ */
39
+ export declare function projectUv(g: Geometry, mode: UvProjection, opts?: ProjectUvOptions): Geometry;
40
+ /**
41
+ * Scale uniformly about the origin so the longest side of the axis-aligned box equals `size`.
42
+ * Normals are unchanged (a uniform scale keeps them); bounds are recomputed. An empty or
43
+ * zero-extent geometry is left as it is. Mutates and returns `g`.
44
+ */
45
+ export declare function fitBounds(g: Geometry, size: number): Geometry;
46
+ /** Translate so the centre of the axis-aligned box is the origin. Mutates and returns `g`. */
47
+ export declare function recenter(g: Geometry): Geometry;
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Per-geometry operations a level builder reaches for: `flatShade`, `weld`, `flipWinding`,
3
+ * `projectUv`, `fitBounds`, `recenter`. They read the 3D prefix every supported layout shares
4
+ * (position at float 0, normal at 3, uv at 6) and step by `layout.floats`, so they take
5
+ * `VERTEX_LAYOUT_3D` and `VERTEX_LAYOUT_3D_TANGENT` geometry alike. `flipWinding`, `projectUv`,
6
+ * `fitBounds` and `recenter` mutate and return their input; `flatShade` and `weld` return a new
7
+ * geometry (their vertex counts change).
8
+ */
9
+ import { VERTEX_LAYOUT_3D, VERTEX_LAYOUT_3D_TANGENT } from '../render/mesh.js';
10
+ import { computeBounds, createIndices } from './geometry.js';
11
+ const TAU = Math.PI * 2;
12
+ function floatsOf(g, what) {
13
+ if (g.layout !== VERTEX_LAYOUT_3D && g.layout !== VERTEX_LAYOUT_3D_TANGENT) {
14
+ throw new Error(`geom: ${what} needs a 3D vertex layout, got '${g.layout.name}'`);
15
+ }
16
+ return g.layout.floats;
17
+ }
18
+ /** Axis-aligned box of the positions: `[minX, minY, minZ, maxX, maxY, maxZ]` (zeros when empty). */
19
+ function aabb(v, F, out) {
20
+ if (v.length === 0) {
21
+ out.fill(0);
22
+ return out;
23
+ }
24
+ out[0] = out[1] = out[2] = Number.POSITIVE_INFINITY;
25
+ out[3] = out[4] = out[5] = Number.NEGATIVE_INFINITY;
26
+ for (let o = 0; o < v.length; o += F) {
27
+ for (let k = 0; k < 3; k++) {
28
+ const c = v[o + k];
29
+ if (c < out[k])
30
+ out[k] = c;
31
+ if (c > out[3 + k])
32
+ out[3 + k] = c;
33
+ }
34
+ }
35
+ return out;
36
+ }
37
+ // ------------------------------------------------------------------ flatShade
38
+ /**
39
+ * Unshare every vertex: one vertex per triangle corner (`indices.length` of them, indices
40
+ * `0..n-1`), each carrying its triangle's geometric normal; the other attributes are copied from
41
+ * the source corner. A degenerate triangle keeps its source normals. New geometry, same layout.
42
+ */
43
+ export function flatShade(g) {
44
+ const F = floatsOf(g, 'flatShade');
45
+ const src = g.vertices;
46
+ const idx = g.indices;
47
+ const count = idx.length;
48
+ const out = new Float32Array(count * F);
49
+ const indices = createIndices(count, count);
50
+ for (let t = 0; t < count; t += 3) {
51
+ const a = idx[t] * F;
52
+ const b = idx[t + 1] * F;
53
+ const c = idx[t + 2] * F;
54
+ const abx = src[b] - src[a];
55
+ const aby = src[b + 1] - src[a + 1];
56
+ const abz = src[b + 2] - src[a + 2];
57
+ const acx = src[c] - src[a];
58
+ const acy = src[c + 1] - src[a + 1];
59
+ const acz = src[c + 2] - src[a + 2];
60
+ let nx = aby * acz - abz * acy;
61
+ let ny = abz * acx - abx * acz;
62
+ let nz = abx * acy - aby * acx;
63
+ const len = Math.hypot(nx, ny, nz);
64
+ const flat = len > 1e-20;
65
+ if (flat) {
66
+ nx /= len;
67
+ ny /= len;
68
+ nz /= len;
69
+ }
70
+ for (let k = 0; k < 3; k++) {
71
+ const s = idx[t + k] * F;
72
+ const o = (t + k) * F;
73
+ out.set(src.subarray(s, s + F), o);
74
+ if (flat) {
75
+ out[o + 3] = nx;
76
+ out[o + 4] = ny;
77
+ out[o + 5] = nz;
78
+ }
79
+ indices[t + k] = t + k;
80
+ }
81
+ }
82
+ return { vertices: out, indices, bounds: computeBounds(out, F), layout: g.layout };
83
+ }
84
+ // ------------------------------------------------------------------ weld
85
+ /**
86
+ * Merge vertices whose position, normal and uv each lie within `epsilon` (per component) of an
87
+ * earlier vertex's: a spatial hash over positions finds candidates, the first occurrence is kept,
88
+ * indices are remapped and shrink to 16-bit when the result fits. Vertex order is otherwise
89
+ * preserved; colour and tangent are taken from the kept vertex. New geometry, same layout.
90
+ */
91
+ export function weld(g, epsilon = 1e-5) {
92
+ const F = floatsOf(g, 'weld');
93
+ const src = g.vertices;
94
+ const n = src.length / F;
95
+ const inv = 1 / epsilon;
96
+ const cells = new Map();
97
+ const remap = new Uint32Array(n);
98
+ const keep = new Uint32Array(n);
99
+ let kept = 0;
100
+ const key = (cx, cy, cz) =>
101
+ // Three 21-bit cell coordinates folded into one double (exact below 2^53).
102
+ ((cx & 0x1fffff) * 2097152 + (cy & 0x1fffff)) * 2097152 + (cz & 0x1fffff);
103
+ const same = (a, b) => {
104
+ for (let k = 0; k < 8; k++)
105
+ if (Math.abs(src[a + k] - src[b + k]) > epsilon)
106
+ return false;
107
+ return true;
108
+ };
109
+ for (let i = 0; i < n; i++) {
110
+ const o = i * F;
111
+ const cx = Math.round(src[o] * inv);
112
+ const cy = Math.round(src[o + 1] * inv);
113
+ const cz = Math.round(src[o + 2] * inv);
114
+ let found = -1;
115
+ search: for (let dx = -1; dx <= 1; dx++) {
116
+ for (let dy = -1; dy <= 1; dy++) {
117
+ for (let dz = -1; dz <= 1; dz++) {
118
+ const bucket = cells.get(key(cx + dx, cy + dy, cz + dz));
119
+ if (!bucket)
120
+ continue;
121
+ for (const j of bucket) {
122
+ if (same(o, j * F)) {
123
+ found = j;
124
+ break search;
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
130
+ if (found >= 0) {
131
+ remap[i] = remap[found];
132
+ continue;
133
+ }
134
+ remap[i] = kept;
135
+ keep[kept++] = i;
136
+ const k = key(cx, cy, cz);
137
+ const bucket = cells.get(k);
138
+ if (bucket)
139
+ bucket.push(i);
140
+ else
141
+ cells.set(k, [i]);
142
+ }
143
+ const vertices = new Float32Array(kept * F);
144
+ for (let i = 0; i < kept; i++) {
145
+ const s = keep[i] * F;
146
+ vertices.set(src.subarray(s, s + F), i * F);
147
+ }
148
+ const indices = createIndices(kept, g.indices.length);
149
+ for (let t = 0; t < g.indices.length; t++)
150
+ indices[t] = remap[g.indices[t]];
151
+ return { vertices, indices, bounds: computeBounds(vertices, F), layout: g.layout };
152
+ }
153
+ // ------------------------------------------------------------------ flipWinding
154
+ /**
155
+ * Turn the geometry inside out: every triangle's winding is reversed and every normal negated
156
+ * (and, in the tangent layout, the handedness, so the bitangent keeps its direction). Bounds are
157
+ * unchanged. Mutates and returns `g`.
158
+ */
159
+ export function flipWinding(g) {
160
+ const F = floatsOf(g, 'flipWinding');
161
+ const idx = g.indices;
162
+ for (let t = 0; t + 2 < idx.length; t += 3) {
163
+ const b = idx[t + 1];
164
+ idx[t + 1] = idx[t + 2];
165
+ idx[t + 2] = b;
166
+ }
167
+ const v = g.vertices;
168
+ const tangent = F >= 16;
169
+ for (let o = 0; o < v.length; o += F) {
170
+ v[o + 3] = -v[o + 3];
171
+ v[o + 4] = -v[o + 4];
172
+ v[o + 5] = -v[o + 5];
173
+ if (tangent)
174
+ v[o + 15] = -v[o + 15];
175
+ }
176
+ return g;
177
+ }
178
+ /**
179
+ * Overwrite the uvs from the positions, relative to the geometry's axis-aligned box so each
180
+ * coordinate spans 0..1 before `scale`:
181
+ * - `'box'`: each vertex takes the plane facing its normal's dominant axis (x: u = z, v = y;
182
+ * y: u = x, v = z; z: u = x, v = y), so a box or a building block tiles on every face;
183
+ * - `'planar'`: one plane for all vertices, facing `axis`;
184
+ * - `'cylindrical'`: u is the angle around +y (0 at +z, as `cylinder`), v the height;
185
+ * - `'spherical'`: u the angle around +y, v the latitude from the box centre (0 at the top).
186
+ * Mutates and returns `g`.
187
+ */
188
+ export function projectUv(g, mode, opts = {}) {
189
+ const F = floatsOf(g, 'projectUv');
190
+ const v = g.vertices;
191
+ const box = aabb(v, F, AABB);
192
+ const sx = box[3] - box[0] || 1;
193
+ const sy = box[4] - box[1] || 1;
194
+ const sz = box[5] - box[2] || 1;
195
+ const cx = (box[0] + box[3]) / 2;
196
+ const cy = (box[1] + box[4]) / 2;
197
+ const cz = (box[2] + box[5]) / 2;
198
+ const s = opts.scale ?? 1;
199
+ const su = typeof s === 'number' ? s : s[0];
200
+ const sv = typeof s === 'number' ? s : s[1];
201
+ const planarAxis = opts.axis ?? 'y';
202
+ for (let o = 0; o < v.length; o += F) {
203
+ const x = (v[o] - box[0]) / sx;
204
+ const y = (v[o + 1] - box[1]) / sy;
205
+ const z = (v[o + 2] - box[2]) / sz;
206
+ let u;
207
+ let w;
208
+ if (mode === 'box' || mode === 'planar') {
209
+ let axis = planarAxis;
210
+ if (mode === 'box') {
211
+ const ax = Math.abs(v[o + 3]);
212
+ const ay = Math.abs(v[o + 4]);
213
+ const az = Math.abs(v[o + 5]);
214
+ axis = ax >= ay && ax >= az ? 'x' : ay >= az ? 'y' : 'z';
215
+ }
216
+ if (axis === 'x') {
217
+ u = z;
218
+ w = y;
219
+ }
220
+ else if (axis === 'y') {
221
+ u = x;
222
+ w = z;
223
+ }
224
+ else {
225
+ u = x;
226
+ w = y;
227
+ }
228
+ }
229
+ else {
230
+ const dx = v[o] - cx;
231
+ const dz = v[o + 2] - cz;
232
+ u = 0.5 + Math.atan2(dx, dz) / TAU;
233
+ if (mode === 'cylindrical') {
234
+ w = 1 - y;
235
+ }
236
+ else {
237
+ const dy = v[o + 1] - cy;
238
+ const len = Math.hypot(dx, dy, dz);
239
+ w = len > 0 ? Math.acos(Math.max(-1, Math.min(1, dy / len))) / Math.PI : 0;
240
+ }
241
+ }
242
+ v[o + 6] = u * su;
243
+ v[o + 7] = w * sv;
244
+ }
245
+ return g;
246
+ }
247
+ const AABB = new Float64Array(6);
248
+ // ------------------------------------------------------------------ fitBounds / recenter
249
+ /**
250
+ * Scale uniformly about the origin so the longest side of the axis-aligned box equals `size`.
251
+ * Normals are unchanged (a uniform scale keeps them); bounds are recomputed. An empty or
252
+ * zero-extent geometry is left as it is. Mutates and returns `g`.
253
+ */
254
+ export function fitBounds(g, size) {
255
+ const F = floatsOf(g, 'fitBounds');
256
+ const v = g.vertices;
257
+ const box = aabb(v, F, AABB);
258
+ const longest = Math.max(box[3] - box[0], box[4] - box[1], box[5] - box[2]);
259
+ if (!(longest > 0))
260
+ return g;
261
+ const k = size / longest;
262
+ for (let o = 0; o < v.length; o += F) {
263
+ v[o] = v[o] * k;
264
+ v[o + 1] = v[o + 1] * k;
265
+ v[o + 2] = v[o + 2] * k;
266
+ }
267
+ computeBounds(v, F, g.bounds);
268
+ return g;
269
+ }
270
+ /** Translate so the centre of the axis-aligned box is the origin. Mutates and returns `g`. */
271
+ export function recenter(g) {
272
+ const F = floatsOf(g, 'recenter');
273
+ const v = g.vertices;
274
+ const box = aabb(v, F, AABB);
275
+ const cx = (box[0] + box[3]) / 2;
276
+ const cy = (box[1] + box[4]) / 2;
277
+ const cz = (box[2] + box[5]) / 2;
278
+ for (let o = 0; o < v.length; o += F) {
279
+ v[o] = v[o] - cx;
280
+ v[o + 1] = v[o + 1] - cy;
281
+ v[o + 2] = v[o + 2] - cz;
282
+ }
283
+ computeBounds(v, F, g.bounds);
284
+ return g;
285
+ }