@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,534 @@
1
+ /**
2
+ * Shapes swept from 2D profiles, all in `VERTEX_LAYOUT_3D`: `extrude` (a closed outline pushed
3
+ * along +z with capped, optionally bevelled ends), `lathe` (an open profile revolved around +y),
4
+ * `sweep` (a closed outline carried along a 3D path with rotation-minimising or Frenet frames),
5
+ * `tube` (a circle swept) and `polygon` (a flat triangulated outline facing +y).
6
+ *
7
+ * Every surface is wound counter-clockwise from outside with u along the outline and v along the
8
+ * sweep, so the tangent frame `computeTangents` derives is right-handed (handedness +1) throughout.
9
+ * Outlines are `Profile2D` (x, y pairs, counter-clockwise; clockwise is reversed on entry).
10
+ */
11
+ import { GeometryWriter } from './geometry.js';
12
+ import { profileArea2, triangulate } from './triangulate.js';
13
+ const TAU = Math.PI * 2;
14
+ /** A counter-clockwise `Float32Array` copy of `profile` (reversed when it came clockwise). */
15
+ function ccwProfile(profile, what) {
16
+ const n = profile.length >> 1;
17
+ if (n < 3)
18
+ throw new Error(`geom: ${what} needs a profile of at least 3 points, got ${n}`);
19
+ const out = new Float32Array(n * 2);
20
+ if (profileArea2(profile) >= 0) {
21
+ for (let i = 0; i < n * 2; i++)
22
+ out[i] = profile[i];
23
+ }
24
+ else {
25
+ for (let i = 0; i < n; i++) {
26
+ out[i * 2] = profile[(n - 1 - i) * 2];
27
+ out[i * 2 + 1] = profile[(n - 1 - i) * 2 + 1];
28
+ }
29
+ }
30
+ return out;
31
+ }
32
+ /**
33
+ * Cumulative length fraction at each point of a profile (`n + 1` entries for a closed outline,
34
+ * the last 1; `n` for an open one), so u and v follow arc length rather than point index.
35
+ */
36
+ function lengthFractions(p, closed) {
37
+ const n = p.length >> 1;
38
+ const out = new Float32Array(closed ? n + 1 : n);
39
+ let acc = 0;
40
+ const edges = closed ? n : n - 1;
41
+ for (let i = 0; i < edges; i++) {
42
+ const j = (i + 1) % n;
43
+ acc += Math.hypot(p[j * 2] - p[i * 2], p[j * 2 + 1] - p[i * 2 + 1]);
44
+ out[i + 1] = acc;
45
+ }
46
+ if (acc > 0)
47
+ for (let i = 0; i < out.length; i++)
48
+ out[i] = out[i] / acc;
49
+ else
50
+ for (let i = 0; i < out.length; i++)
51
+ out[i] = i / Math.max(1, out.length - 1);
52
+ return out;
53
+ }
54
+ /**
55
+ * Smooth outward 2D normals, one per profile point: the normalised sum of the two adjacent edge
56
+ * normals `(dy, -dx)` (one edge at the ends of an open profile).
57
+ */
58
+ function vertexNormals2(p, closed) {
59
+ const n = p.length >> 1;
60
+ const out = new Float32Array(n * 2);
61
+ for (let i = 0; i < n; i++) {
62
+ let nx = 0;
63
+ let ny = 0;
64
+ if (closed || i > 0) {
65
+ const a = (i - 1 + n) % n;
66
+ const dx = p[i * 2] - p[a * 2];
67
+ const dy = p[i * 2 + 1] - p[a * 2 + 1];
68
+ const l = Math.hypot(dx, dy) || 1;
69
+ nx += dy / l;
70
+ ny -= dx / l;
71
+ }
72
+ if (closed || i < n - 1) {
73
+ const b = (i + 1) % n;
74
+ const dx = p[b * 2] - p[i * 2];
75
+ const dy = p[b * 2 + 1] - p[i * 2 + 1];
76
+ const l = Math.hypot(dx, dy) || 1;
77
+ nx += dy / l;
78
+ ny -= dx / l;
79
+ }
80
+ const l = Math.hypot(nx, ny);
81
+ out[i * 2] = l > 0 ? nx / l : 1;
82
+ out[i * 2 + 1] = l > 0 ? ny / l : 0;
83
+ }
84
+ return out;
85
+ }
86
+ function bounds2(p) {
87
+ let minX = Number.POSITIVE_INFINITY;
88
+ let minY = Number.POSITIVE_INFINITY;
89
+ let maxX = Number.NEGATIVE_INFINITY;
90
+ let maxY = Number.NEGATIVE_INFINITY;
91
+ for (let i = 0; i < p.length; i += 2) {
92
+ const x = p[i];
93
+ const y = p[i + 1];
94
+ if (x < minX)
95
+ minX = x;
96
+ if (x > maxX)
97
+ maxX = x;
98
+ if (y < minY)
99
+ minY = y;
100
+ if (y > maxY)
101
+ maxY = y;
102
+ }
103
+ return [minX, minY, maxX - minX || 1, maxY - minY || 1];
104
+ }
105
+ /**
106
+ * A closed outline pushed along z from -depth/2 to +depth/2: flat side normals (two vertices per
107
+ * outline point per row), ear-clipped caps facing ±z, an optional 45° bevel. Side u runs around
108
+ * the outline by arc length (0 at the first point) and v along z (0 at the back); cap uvs span
109
+ * the outline's box in 0..1 (the back cap mirrored in u).
110
+ */
111
+ export function extrude(profile, opts = {}) {
112
+ const p = ccwProfile(profile, 'extrude');
113
+ const n = p.length >> 1;
114
+ const depth = opts.depth ?? 1;
115
+ const rows = Math.floor(opts.segments ?? 1);
116
+ if (!(rows >= 1))
117
+ throw new Error(`geom: extrude segments must be at least 1, got ${rows}`);
118
+ const caps = opts.caps ?? true;
119
+ const bevel = caps ? Math.max(0, opts.bevel ?? 0) : 0;
120
+ const capTris = caps ? triangulate(p) : null;
121
+ const sideV = n * 2 * (rows + 1);
122
+ const sideI = n * rows * 6;
123
+ const capV = caps ? 2 * n : 0;
124
+ const capI = capTris ? capTris.length * 2 : 0;
125
+ const bevV = bevel > 0 ? 2 * n * 4 : 0;
126
+ const bevI = bevel > 0 ? 2 * n * 6 : 0;
127
+ const w = new GeometryWriter(sideV + capV + bevV, sideI + capI + bevI, opts);
128
+ const z0 = -depth / 2 + bevel;
129
+ const z1 = depth / 2 - bevel;
130
+ const frac = lengthFractions(p, true);
131
+ // Sides: one strip per edge, flat normal.
132
+ for (let e = 0; e < n; e++) {
133
+ const f = (e + 1) % n;
134
+ const ax = p[e * 2];
135
+ const ay = p[e * 2 + 1];
136
+ const bx = p[f * 2];
137
+ const by = p[f * 2 + 1];
138
+ const l = Math.hypot(bx - ax, by - ay) || 1;
139
+ const nx = (by - ay) / l;
140
+ const ny = -(bx - ax) / l;
141
+ const base = w.count;
142
+ for (let j = 0; j <= rows; j++) {
143
+ const t = j / rows;
144
+ const z = z0 + (z1 - z0) * t;
145
+ w.vertex(ax, ay, z, nx, ny, 0, frac[e], t);
146
+ w.vertex(bx, by, z, nx, ny, 0, frac[e + 1], t);
147
+ }
148
+ for (let j = 0; j < rows; j++) {
149
+ const a = base + j * 2;
150
+ w.quad(a, a + 1, a + 3, a + 2);
151
+ }
152
+ }
153
+ if (caps && capTris) {
154
+ // Inset outline for the caps (the outline itself without a bevel).
155
+ const inset = new Float32Array(n * 2);
156
+ if (bevel > 0) {
157
+ for (let i = 0; i < n; i++) {
158
+ const a = (i - 1 + n) % n;
159
+ const b = (i + 1) % n;
160
+ const d0x = p[i * 2] - p[a * 2];
161
+ const d0y = p[i * 2 + 1] - p[a * 2 + 1];
162
+ const d1x = p[b * 2] - p[i * 2];
163
+ const d1y = p[b * 2 + 1] - p[i * 2 + 1];
164
+ const l0 = Math.hypot(d0x, d0y) || 1;
165
+ const l1 = Math.hypot(d1x, d1y) || 1;
166
+ const n0x = d0y / l0;
167
+ const n0y = -d0x / l0;
168
+ const n1x = d1y / l1;
169
+ const n1y = -d1x / l1;
170
+ // Mitre: (n0 + n1) / (1 + n0·n1) moves the offset edges by exactly `bevel`.
171
+ const k = Math.max(0.2, 1 + n0x * n1x + n0y * n1y);
172
+ inset[i * 2] = p[i * 2] - (bevel * (n0x + n1x)) / k;
173
+ inset[i * 2 + 1] = p[i * 2 + 1] - (bevel * (n0y + n1y)) / k;
174
+ }
175
+ }
176
+ else {
177
+ inset.set(p);
178
+ }
179
+ const [minX, minY, sx, sy] = bounds2(p);
180
+ const zf = depth / 2;
181
+ const front = w.count;
182
+ for (let i = 0; i < n; i++) {
183
+ const x = inset[i * 2];
184
+ const y = inset[i * 2 + 1];
185
+ w.vertex(x, y, zf, 0, 0, 1, (x - minX) / sx, (y - minY) / sy);
186
+ }
187
+ const back = w.count;
188
+ for (let i = 0; i < n; i++) {
189
+ const x = inset[i * 2];
190
+ const y = inset[i * 2 + 1];
191
+ w.vertex(x, y, -zf, 0, 0, -1, 1 - (x - minX) / sx, (y - minY) / sy);
192
+ }
193
+ for (let t = 0; t < capTris.length; t += 3) {
194
+ const a = capTris[t];
195
+ const b = capTris[t + 1];
196
+ const c = capTris[t + 2];
197
+ w.tri(front + a, front + b, front + c);
198
+ w.tri(back + a, back + c, back + b);
199
+ }
200
+ if (bevel > 0) {
201
+ const s = Math.SQRT1_2;
202
+ for (let e = 0; e < n; e++) {
203
+ const f = (e + 1) % n;
204
+ const ax = p[e * 2];
205
+ const ay = p[e * 2 + 1];
206
+ const bx = p[f * 2];
207
+ const by = p[f * 2 + 1];
208
+ const l = Math.hypot(bx - ax, by - ay) || 1;
209
+ const nx = ((by - ay) / l) * s;
210
+ const ny = (-(bx - ax) / l) * s;
211
+ const u0 = frac[e];
212
+ const u1 = frac[e + 1];
213
+ // Front chamfer: side's front edge (z1) up to the inset cap edge (zf).
214
+ let a = w.vertex(ax, ay, z1, nx, ny, s, u0, 0);
215
+ w.vertex(bx, by, z1, nx, ny, s, u1, 0);
216
+ w.vertex(inset[f * 2], inset[f * 2 + 1], zf, nx, ny, s, u1, 1);
217
+ w.vertex(inset[e * 2], inset[e * 2 + 1], zf, nx, ny, s, u0, 1);
218
+ w.quad(a, a + 1, a + 2, a + 3);
219
+ // Back chamfer: traversed the other way so the winding faces out; v still runs along +z
220
+ // (0 at the cap edge, 1 at the side) so the tangent frame stays right-handed.
221
+ a = w.vertex(bx, by, z0, nx, ny, -s, u1, 1);
222
+ w.vertex(ax, ay, z0, nx, ny, -s, u0, 1);
223
+ w.vertex(inset[e * 2], inset[e * 2 + 1], -zf, nx, ny, -s, u0, 0);
224
+ w.vertex(inset[f * 2], inset[f * 2 + 1], -zf, nx, ny, -s, u1, 0);
225
+ w.quad(a, a + 1, a + 2, a + 3);
226
+ }
227
+ }
228
+ }
229
+ return w.finish();
230
+ }
231
+ /**
232
+ * An open profile of (radius, y) points, ordered along the surface, revolved around +y: smooth
233
+ * normals (adjacent edge normals averaged, outward for a profile traced bottom to top), u around
234
+ * (0 at +z, as `cylinder`), v along the profile by arc length. A zero radius makes a pole.
235
+ */
236
+ export function lathe(profile, opts = {}) {
237
+ const m = profile.length >> 1;
238
+ if (m < 2)
239
+ throw new Error(`geom: lathe needs a profile of at least 2 points, got ${m}`);
240
+ const p = new Float32Array(m * 2);
241
+ for (let i = 0; i < m * 2; i++)
242
+ p[i] = profile[i];
243
+ const cols = Math.floor(opts.segments ?? 24);
244
+ if (!(cols >= 3))
245
+ throw new Error(`geom: lathe segments must be at least 3, got ${cols}`);
246
+ const angle = opts.angle ?? TAU;
247
+ const w = new GeometryWriter(m * (cols + 1), (m - 1) * cols * 6, opts);
248
+ const nrm = vertexNormals2(p, false);
249
+ const frac = lengthFractions(p, false);
250
+ for (let j = 0; j < m; j++) {
251
+ const r = p[j * 2];
252
+ const y = p[j * 2 + 1];
253
+ const nr = nrm[j * 2];
254
+ const ny = nrm[j * 2 + 1];
255
+ for (let i = 0; i <= cols; i++) {
256
+ const phi = (i / cols) * angle;
257
+ const s = Math.sin(phi);
258
+ const c = Math.cos(phi);
259
+ w.vertex(r * s, y, r * c, nr * s, ny, nr * c, i / cols, frac[j]);
260
+ }
261
+ }
262
+ for (let j = 0; j < m - 1; j++) {
263
+ const a = j * (cols + 1);
264
+ const b = a + cols + 1;
265
+ for (let i = 0; i < cols; i++)
266
+ w.quad(a + i, a + i + 1, b + i + 1, b + i);
267
+ }
268
+ return w.finish();
269
+ }
270
+ /**
271
+ * Carry a frame normal from path point `q` to `o` (float offsets) by double reflection: across
272
+ * the chord's bisector plane, then across the plane between the reflected and the new tangent.
273
+ */
274
+ function carryNormal(path, T, q, o, rx, ry, rz) {
275
+ const v1x = path[o] - path[q];
276
+ const v1y = path[o + 1] - path[q + 1];
277
+ const v1z = path[o + 2] - path[q + 2];
278
+ const c1 = v1x * v1x + v1y * v1y + v1z * v1z;
279
+ let tlx = T[q];
280
+ let tly = T[q + 1];
281
+ let tlz = T[q + 2];
282
+ if (c1 > 0) {
283
+ const k = (2 / c1) * (v1x * rx + v1y * ry + v1z * rz);
284
+ rx -= k * v1x;
285
+ ry -= k * v1y;
286
+ rz -= k * v1z;
287
+ const kt = (2 / c1) * (v1x * tlx + v1y * tly + v1z * tlz);
288
+ tlx -= kt * v1x;
289
+ tly -= kt * v1y;
290
+ tlz -= kt * v1z;
291
+ }
292
+ const v2x = T[o] - tlx;
293
+ const v2y = T[o + 1] - tly;
294
+ const v2z = T[o + 2] - tlz;
295
+ const c2 = v2x * v2x + v2y * v2y + v2z * v2z;
296
+ if (c2 > 0) {
297
+ const k = (2 / c2) * (v2x * rx + v2y * ry + v2z * rz);
298
+ rx -= k * v2x;
299
+ ry -= k * v2y;
300
+ rz -= k * v2z;
301
+ }
302
+ return [rx, ry, rz];
303
+ }
304
+ /**
305
+ * A closed outline carried along `path` (x, y, z triples, at least 2 points; the first and last
306
+ * point of a closed path are distinct). Each path point gets a ring of the outline in its frame
307
+ * (outline x along the frame's normal, y along its binormal), smooth normals across the outline,
308
+ * u around the outline by arc length, v along the path by point index. A closed sweep spreads the
309
+ * frame's end-to-start twist over the rings so the seam matches.
310
+ */
311
+ export function sweep(profile, path, opts = {}) {
312
+ const p = ccwProfile(profile, 'sweep');
313
+ const n = p.length >> 1;
314
+ const m = path.length / 3;
315
+ if (!(m >= 2) || m !== Math.floor(m)) {
316
+ throw new Error(`geom: sweep needs a path of at least 2 xyz points, got ${path.length} floats`);
317
+ }
318
+ const closed = opts.closed ?? false;
319
+ const frenet = opts.frames === 'frenet';
320
+ const rings = m;
321
+ const spans = closed ? m : m - 1;
322
+ const w = new GeometryWriter(rings * (n + 1), spans * n * 6, opts);
323
+ const nrm = vertexNormals2(p, true);
324
+ const frac = lengthFractions(p, true);
325
+ // Tangents, central differences (wrapping when closed).
326
+ const T = new Float64Array(m * 3);
327
+ for (let j = 0; j < m; j++) {
328
+ let a = j - 1;
329
+ let b = j + 1;
330
+ if (closed) {
331
+ a = (a + m) % m;
332
+ b %= m;
333
+ }
334
+ else {
335
+ if (a < 0)
336
+ a = 0;
337
+ if (b >= m)
338
+ b = m - 1;
339
+ }
340
+ let tx = path[b * 3] - path[a * 3];
341
+ let ty = path[b * 3 + 1] - path[a * 3 + 1];
342
+ let tz = path[b * 3 + 2] - path[a * 3 + 2];
343
+ const l = Math.hypot(tx, ty, tz);
344
+ if (l > 0) {
345
+ tx /= l;
346
+ ty /= l;
347
+ tz /= l;
348
+ }
349
+ else if (j > 0) {
350
+ tx = T[(j - 1) * 3];
351
+ ty = T[(j - 1) * 3 + 1];
352
+ tz = T[(j - 1) * 3 + 2];
353
+ }
354
+ else {
355
+ tz = 1;
356
+ }
357
+ T[j * 3] = tx;
358
+ T[j * 3 + 1] = ty;
359
+ T[j * 3 + 2] = tz;
360
+ }
361
+ // Normals N (perpendicular to T) per ring; B = T × N.
362
+ const N = new Float64Array(m * 3);
363
+ // Start: the world axis least aligned with T0, made perpendicular.
364
+ {
365
+ const tx = T[0];
366
+ const ty = T[1];
367
+ const tz = T[2];
368
+ const ax = Math.abs(tx);
369
+ const ay = Math.abs(ty);
370
+ const az = Math.abs(tz);
371
+ let ux = 0;
372
+ let uy = 0;
373
+ let uz = 0;
374
+ if (ay <= ax && ay <= az)
375
+ uy = 1;
376
+ else if (ax <= az)
377
+ ux = 1;
378
+ else
379
+ uz = 1;
380
+ const d = ux * tx + uy * ty + uz * tz;
381
+ ux -= d * tx;
382
+ uy -= d * ty;
383
+ uz -= d * tz;
384
+ const l = Math.hypot(ux, uy, uz);
385
+ N[0] = ux / l;
386
+ N[1] = uy / l;
387
+ N[2] = uz / l;
388
+ }
389
+ for (let j = 1; j < m; j++) {
390
+ const o = j * 3;
391
+ const q = o - 3;
392
+ if (frenet) {
393
+ // Curvature direction: the change in tangent, perpendicular to T.
394
+ const a = closed ? ((j - 1 + m) % m) * 3 : Math.max(0, j - 1) * 3;
395
+ const b = closed ? ((j + 1) % m) * 3 : Math.min(m - 1, j + 1) * 3;
396
+ let kx = T[b] - T[a];
397
+ let ky = T[b + 1] - T[a + 1];
398
+ let kz = T[b + 2] - T[a + 2];
399
+ const d = kx * T[o] + ky * T[o + 1] + kz * T[o + 2];
400
+ kx -= d * T[o];
401
+ ky -= d * T[o + 1];
402
+ kz -= d * T[o + 2];
403
+ const l = Math.hypot(kx, ky, kz);
404
+ if (l > 1e-9) {
405
+ N[o] = kx / l;
406
+ N[o + 1] = ky / l;
407
+ N[o + 2] = kz / l;
408
+ continue;
409
+ }
410
+ }
411
+ // Double reflection: the previous normal carried across the chord (see `carryNormal`).
412
+ const [rx0, ry0, rz0] = carryNormal(path, T, q, o, N[q], N[q + 1], N[q + 2]);
413
+ let rx = rx0;
414
+ let ry = ry0;
415
+ let rz = rz0;
416
+ // Re-orthogonalise against T to stop drift.
417
+ const d = rx * T[o] + ry * T[o + 1] + rz * T[o + 2];
418
+ rx -= d * T[o];
419
+ ry -= d * T[o + 1];
420
+ rz -= d * T[o + 2];
421
+ const l = Math.hypot(rx, ry, rz) || 1;
422
+ N[o] = rx / l;
423
+ N[o + 1] = ry / l;
424
+ N[o + 2] = rz / l;
425
+ }
426
+ // Closed: the frame carried once more around to ring 0 differs from N0 by a twist; spread the
427
+ // correction over the rings so ring m-1 meets ring 0 without a step.
428
+ let twist = 0;
429
+ if (closed && !frenet) {
430
+ const q = (m - 1) * 3;
431
+ const [rx, ry, rz] = carryNormal(path, T, q, 0, N[q], N[q + 1], N[q + 2]);
432
+ // Angle from the carried normal to N0 about T0.
433
+ const bx = T[1] * N[2] - T[2] * N[1];
434
+ const by = T[2] * N[0] - T[0] * N[2];
435
+ const bz = T[0] * N[1] - T[1] * N[0];
436
+ const cosA = rx * N[0] + ry * N[1] + rz * N[2];
437
+ const sinA = rx * bx + ry * by + rz * bz;
438
+ twist = Math.atan2(sinA, cosA);
439
+ }
440
+ for (let j = 0; j < rings; j++) {
441
+ const o = j * 3;
442
+ const tx = T[o];
443
+ const ty = T[o + 1];
444
+ const tz = T[o + 2];
445
+ let nx = N[o];
446
+ let ny = N[o + 1];
447
+ let nz = N[o + 2];
448
+ let bx = ty * nz - tz * ny;
449
+ let by = tz * nx - tx * nz;
450
+ let bz = tx * ny - ty * nx;
451
+ if (twist !== 0) {
452
+ // Rotate N, B about T by the share of the twist this ring takes.
453
+ const a = (twist * j) / m;
454
+ const ca = Math.cos(a);
455
+ const sa = Math.sin(a);
456
+ const rnx = nx * ca + bx * sa;
457
+ const rny = ny * ca + by * sa;
458
+ const rnz = nz * ca + bz * sa;
459
+ bx = bx * ca - nx * sa;
460
+ by = by * ca - ny * sa;
461
+ bz = bz * ca - nz * sa;
462
+ nx = rnx;
463
+ ny = rny;
464
+ nz = rnz;
465
+ }
466
+ const px = path[o];
467
+ const py = path[o + 1];
468
+ const pz = path[o + 2];
469
+ const v = j / spans;
470
+ for (let i = 0; i <= n; i++) {
471
+ const k = i % n;
472
+ const x2 = p[k * 2];
473
+ const y2 = p[k * 2 + 1];
474
+ const nx2 = nrm[k * 2];
475
+ const ny2 = nrm[k * 2 + 1];
476
+ w.vertex(px + nx * x2 + bx * y2, py + ny * x2 + by * y2, pz + nz * x2 + bz * y2, nx * nx2 + bx * ny2, ny * nx2 + by * ny2, nz * nx2 + bz * ny2, frac[i], v);
477
+ }
478
+ }
479
+ for (let j = 0; j < spans; j++) {
480
+ const a = j * (n + 1);
481
+ const b = ((j + 1) % rings) * (n + 1);
482
+ for (let i = 0; i < n; i++)
483
+ w.quad(a + i, a + i + 1, b + i + 1, b + i);
484
+ }
485
+ return w.finish();
486
+ }
487
+ /** `sweep` of a circle: a round tube along `path` (`SweepOptions` apply). */
488
+ export function tube(path, opts = {}) {
489
+ const r = opts.radius ?? 0.1;
490
+ const k = Math.floor(opts.segments ?? 12);
491
+ if (!(k >= 3))
492
+ throw new Error(`geom: tube segments must be at least 3, got ${k}`);
493
+ const circle = new Float32Array(k * 2);
494
+ for (let i = 0; i < k; i++) {
495
+ const a = (i / k) * TAU;
496
+ circle[i * 2] = r * Math.cos(a);
497
+ circle[i * 2 + 1] = r * Math.sin(a);
498
+ }
499
+ return sweep(circle, path, opts);
500
+ }
501
+ /**
502
+ * A flat outline in the xz plane facing +y: outline x → x, outline y → -z (so a counter-clockwise
503
+ * outline stays counter-clockwise seen from above), ear-clipped, uv the outline's box in 0..1.
504
+ */
505
+ export function polygon(points, opts = {}) {
506
+ const p = ccwProfile(points, 'polygon');
507
+ const n = p.length >> 1;
508
+ const tris = triangulate(p);
509
+ const two = opts.doubleSided ?? false;
510
+ const y = opts.y ?? 0;
511
+ const w = new GeometryWriter(two ? n * 2 : n, two ? tris.length * 2 : tris.length, opts);
512
+ const [minX, minY, sx, sy] = bounds2(p);
513
+ for (let i = 0; i < n; i++) {
514
+ const x = p[i * 2];
515
+ const z = p[i * 2 + 1];
516
+ w.vertex(x, y, -z, 0, 1, 0, (x - minX) / sx, (z - minY) / sy);
517
+ }
518
+ if (two) {
519
+ for (let i = 0; i < n; i++) {
520
+ const x = p[i * 2];
521
+ const z = p[i * 2 + 1];
522
+ w.vertex(x, y, -z, 0, -1, 0, 1 - (x - minX) / sx, (z - minY) / sy);
523
+ }
524
+ }
525
+ for (let t = 0; t < tris.length; t += 3) {
526
+ w.tri(tris[t], tris[t + 1], tris[t + 2]);
527
+ }
528
+ if (two) {
529
+ for (let t = 0; t < tris.length; t += 3) {
530
+ w.tri(n + tris[t], n + tris[t + 2], n + tris[t + 1]);
531
+ }
532
+ }
533
+ return w.finish();
534
+ }
@@ -0,0 +1,16 @@
1
+ import { type Geometry } from './geometry.js';
2
+ /** A `Geometry` whose `layout` is `VERTEX_LAYOUT_3D_TANGENT` (16 floats per vertex). */
3
+ export type GeometryTangent = Geometry;
4
+ /** Floats per vertex in `VERTEX_LAYOUT_3D_TANGENT`. */
5
+ export declare const TANGENT_FLOATS: number;
6
+ /**
7
+ * Per-vertex tangents in the MikkTSpace manner: each triangle's tangent and bitangent (the
8
+ * directions in which u and v grow across it, scaled by its area over its uv area) are
9
+ * accumulated on its three vertices; each sum is then Gram-Schmidt orthogonalised against the
10
+ * vertex normal and normalised, and w = +1 when `cross(normal, tangent)` points along the accumulated
11
+ * bitangent, -1 when the uv mapping is mirrored. A vertex with no uv area (or none at all) gets
12
+ * an arbitrary unit tangent perpendicular to its normal and w = 1. Returns a new geometry in
13
+ * `VERTEX_LAYOUT_3D_TANGENT` with the same indices object and bounds; the input is untouched.
14
+ * Allocates the output and one scratch array.
15
+ */
16
+ export declare function computeTangents(g: Geometry): GeometryTangent;
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Tangent frames for normal-mapped materials: `computeTangents` turns a `VERTEX_LAYOUT_3D`
3
+ * geometry into one in `VERTEX_LAYOUT_3D_TANGENT` (16 floats: the 12 of the 3D layout, then the
4
+ * unit tangent xyz and its handedness in w).
5
+ */
6
+ import { VERTEX_LAYOUT_3D, VERTEX_LAYOUT_3D_TANGENT } from '../render/mesh.js';
7
+ import { GEOMETRY_FLOATS } from './geometry.js';
8
+ /** Floats per vertex in `VERTEX_LAYOUT_3D_TANGENT`. */
9
+ export const TANGENT_FLOATS = VERTEX_LAYOUT_3D_TANGENT.floats;
10
+ /**
11
+ * Per-vertex tangents in the MikkTSpace manner: each triangle's tangent and bitangent (the
12
+ * directions in which u and v grow across it, scaled by its area over its uv area) are
13
+ * accumulated on its three vertices; each sum is then Gram-Schmidt orthogonalised against the
14
+ * vertex normal and normalised, and w = +1 when `cross(normal, tangent)` points along the accumulated
15
+ * bitangent, -1 when the uv mapping is mirrored. A vertex with no uv area (or none at all) gets
16
+ * an arbitrary unit tangent perpendicular to its normal and w = 1. Returns a new geometry in
17
+ * `VERTEX_LAYOUT_3D_TANGENT` with the same indices object and bounds; the input is untouched.
18
+ * Allocates the output and one scratch array.
19
+ */
20
+ export function computeTangents(g) {
21
+ if (g.layout !== VERTEX_LAYOUT_3D) {
22
+ throw new Error(`geom: computeTangents needs VERTEX_LAYOUT_3D, got '${g.layout.name}'`);
23
+ }
24
+ const F = GEOMETRY_FLOATS;
25
+ const T = TANGENT_FLOATS;
26
+ const src = g.vertices;
27
+ const n = src.length / F;
28
+ const out = new Float32Array(n * T);
29
+ // Tangent sums live in the output's tangent slots; bitangent sums in the scratch array.
30
+ const bit = new Float32Array(n * 3);
31
+ for (let i = 0; i < n; i++)
32
+ out.set(src.subarray(i * F, i * F + F), i * T);
33
+ const idx = g.indices;
34
+ for (let t = 0; t < idx.length; t += 3) {
35
+ const a = idx[t] * F;
36
+ const b = idx[t + 1] * F;
37
+ const c = idx[t + 2] * F;
38
+ const e1x = src[b] - src[a];
39
+ const e1y = src[b + 1] - src[a + 1];
40
+ const e1z = src[b + 2] - src[a + 2];
41
+ const e2x = src[c] - src[a];
42
+ const e2y = src[c + 1] - src[a + 1];
43
+ const e2z = src[c + 2] - src[a + 2];
44
+ const du1 = src[b + 6] - src[a + 6];
45
+ const dv1 = src[b + 7] - src[a + 7];
46
+ const du2 = src[c + 6] - src[a + 6];
47
+ const dv2 = src[c + 7] - src[a + 7];
48
+ const det = du1 * dv2 - du2 * dv1;
49
+ if (det === 0)
50
+ continue;
51
+ const r = 1 / det;
52
+ // Tangent = direction of +u, bitangent = direction of +v (Lengyel); a mirrored mapping
53
+ // flips the sign of `det`, so both still point along +u and +v but B lands on the far side of
54
+ // cross(n, t), which is what w records.
55
+ const tx = (e1x * dv2 - e2x * dv1) * r;
56
+ const ty = (e1y * dv2 - e2y * dv1) * r;
57
+ const tz = (e1z * dv2 - e2z * dv1) * r;
58
+ const bx = (e2x * du1 - e1x * du2) * r;
59
+ const by = (e2y * du1 - e1y * du2) * r;
60
+ const bz = (e2z * du1 - e1z * du2) * r;
61
+ for (let k = 0; k < 3; k++) {
62
+ const v = idx[t + k];
63
+ const o = v * T + 12;
64
+ out[o] = out[o] + tx;
65
+ out[o + 1] = out[o + 1] + ty;
66
+ out[o + 2] = out[o + 2] + tz;
67
+ const p = v * 3;
68
+ bit[p] = bit[p] + bx;
69
+ bit[p + 1] = bit[p + 1] + by;
70
+ bit[p + 2] = bit[p + 2] + bz;
71
+ }
72
+ }
73
+ for (let i = 0; i < n; i++) {
74
+ const o = i * T;
75
+ const nx = out[o + 3];
76
+ const ny = out[o + 4];
77
+ const nz = out[o + 5];
78
+ let tx = out[o + 12];
79
+ let ty = out[o + 13];
80
+ let tz = out[o + 14];
81
+ // Gram-Schmidt: remove the normal component.
82
+ const d = tx * nx + ty * ny + tz * nz;
83
+ tx -= d * nx;
84
+ ty -= d * ny;
85
+ tz -= d * nz;
86
+ let len = Math.hypot(tx, ty, tz);
87
+ if (len < 1e-12) {
88
+ // No usable uv gradient: any unit vector perpendicular to the normal.
89
+ if (Math.abs(nx) < 0.9) {
90
+ tx = 0;
91
+ ty = nz;
92
+ tz = -ny;
93
+ }
94
+ else {
95
+ tx = -nz;
96
+ ty = 0;
97
+ tz = nx;
98
+ }
99
+ len = Math.hypot(tx, ty, tz) || 1;
100
+ }
101
+ tx /= len;
102
+ ty /= len;
103
+ tz /= len;
104
+ // Handedness: does cross(n, t) agree with the accumulated bitangent?
105
+ const cx = ny * tz - nz * ty;
106
+ const cy = nz * tx - nx * tz;
107
+ const cz = nx * ty - ny * tx;
108
+ const p = i * 3;
109
+ const h = cx * bit[p] + cy * bit[p + 1] + cz * bit[p + 2];
110
+ out[o + 12] = tx;
111
+ out[o + 13] = ty;
112
+ out[o + 14] = tz;
113
+ out[o + 15] = h < 0 ? -1 : 1;
114
+ }
115
+ return {
116
+ vertices: out,
117
+ indices: g.indices,
118
+ bounds: {
119
+ center: [g.bounds.center[0], g.bounds.center[1], g.bounds.center[2]],
120
+ radius: g.bounds.radius,
121
+ },
122
+ layout: VERTEX_LAYOUT_3D_TANGENT,
123
+ };
124
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Ear-clipping triangulation of a simple polygon (`triangulate`), the cap step of `extrude` and
3
+ * the whole of `polygon`. Pure arithmetic over x, y pairs.
4
+ */
5
+ /** A closed 2D outline as x, y pairs, counter-clockwise (clockwise is accepted and reversed). */
6
+ export type Profile2D = Float32Array | number[];
7
+ /** Twice the signed area of a profile: positive counter-clockwise, negative clockwise. */
8
+ export declare function profileArea2(profile: Profile2D): number;
9
+ /**
10
+ * Triangulate a simple polygon by ear clipping: up to `n - 2` triangles over the profile's vertex
11
+ * indices, wound counter-clockwise in the profile's plane whatever its input winding. Concave
12
+ * outlines are handled; collinear or repeated points are dropped as zero-area ears (so fewer
13
+ * triangles come back). Self-intersection detection is out of scope: a self-intersecting outline
14
+ * still triangulates completely, but which side is "inside" is undefined there. `Uint16Array` up
15
+ * to 65535 points, `Uint32Array` past it. Fewer than three points gives an empty array. Cost is
16
+ * O(n · r) for r reflex (inward-turning) corners, so convex outlines fan in O(n); a huge outline
17
+ * whose corners jitter in and out of convexity (float32 rounding on a 70000-gon) is quadratic.
18
+ */
19
+ export declare function triangulate(profile: Profile2D): Uint16Array | Uint32Array;