@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.
- package/CHANGELOG.md +390 -0
- package/LICENSE +21 -0
- package/README.md +333 -2
- package/dist/analytics/analytics.d.ts +80 -0
- package/dist/analytics/analytics.js +129 -0
- package/dist/analytics/index.d.ts +1 -0
- package/dist/analytics/index.js +1 -0
- package/dist/anim/aim.d.ts +43 -0
- package/dist/anim/aim.js +157 -0
- package/dist/anim/clip.d.ts +98 -0
- package/dist/anim/clip.js +282 -0
- package/dist/anim/compress.d.ts +65 -0
- package/dist/anim/compress.js +339 -0
- package/dist/anim/foot-ik.d.ts +74 -0
- package/dist/anim/foot-ik.js +241 -0
- package/dist/anim/graph.d.ts +153 -0
- package/dist/anim/graph.js +532 -0
- package/dist/anim/ik.d.ts +105 -0
- package/dist/anim/ik.js +435 -0
- package/dist/anim/index.d.ts +36 -0
- package/dist/anim/index.js +21 -0
- package/dist/anim/match.d.ts +66 -0
- package/dist/anim/match.js +153 -0
- package/dist/anim/mixer.d.ts +113 -0
- package/dist/anim/mixer.js +314 -0
- package/dist/anim/morph.d.ts +41 -0
- package/dist/anim/morph.js +94 -0
- package/dist/anim/pose.d.ts +74 -0
- package/dist/anim/pose.js +254 -0
- package/dist/anim/quat.d.ts +44 -0
- package/dist/anim/quat.js +187 -0
- package/dist/anim/retarget.d.ts +97 -0
- package/dist/anim/retarget.js +366 -0
- package/dist/anim/root-motion.d.ts +44 -0
- package/dist/anim/root-motion.js +224 -0
- package/dist/anim/skin-pose.d.ts +39 -0
- package/dist/anim/skin-pose.js +53 -0
- package/dist/anim/socket.d.ts +47 -0
- package/dist/anim/socket.js +84 -0
- package/dist/anim/spring-chain.d.ts +73 -0
- package/dist/anim/spring-chain.js +294 -0
- package/dist/assets/atlas.d.ts +90 -0
- package/dist/assets/atlas.js +212 -0
- package/dist/assets/baked.d.ts +33 -0
- package/dist/assets/baked.js +38 -0
- package/dist/assets/bundle.d.ts +88 -0
- package/dist/assets/bundle.js +464 -0
- package/dist/assets/cache.d.ts +56 -0
- package/dist/assets/cache.js +123 -0
- package/dist/assets/gltf-load.d.ts +252 -0
- package/dist/assets/gltf-load.js +661 -0
- package/dist/assets/gltf-skin.d.ts +36 -0
- package/dist/assets/gltf-skin.js +109 -0
- package/dist/assets/gltf.d.ts +706 -0
- package/dist/assets/gltf.js +1376 -0
- package/dist/assets/index.d.ts +20 -0
- package/dist/assets/index.js +10 -0
- package/dist/assets/ktx2.d.ts +71 -0
- package/dist/assets/ktx2.js +213 -0
- package/dist/assets/manifest.d.ts +79 -0
- package/dist/assets/manifest.js +7 -0
- package/dist/assets/meshopt.d.ts +23 -0
- package/dist/assets/meshopt.js +403 -0
- package/dist/audio/audio.d.ts +733 -0
- package/dist/audio/audio.js +2013 -0
- package/dist/audio/dsp.d.ts +61 -0
- package/dist/audio/dsp.js +159 -0
- package/dist/audio/duck.d.ts +44 -0
- package/dist/audio/duck.js +101 -0
- package/dist/audio/envelope.d.ts +53 -0
- package/dist/audio/envelope.js +106 -0
- package/dist/audio/index.d.ts +13 -0
- package/dist/audio/index.js +14 -0
- package/dist/audio/music.d.ts +113 -0
- package/dist/audio/music.js +548 -0
- package/dist/audio/occlusion.d.ts +55 -0
- package/dist/audio/occlusion.js +61 -0
- package/dist/audio/persist.d.ts +23 -0
- package/dist/audio/persist.js +27 -0
- package/dist/audio/recipes.d.ts +55 -0
- package/dist/audio/recipes.js +227 -0
- package/dist/audio/send.d.ts +41 -0
- package/dist/audio/send.js +118 -0
- package/dist/audio/sprites.d.ts +59 -0
- package/dist/audio/sprites.js +43 -0
- package/dist/audio/synth.d.ts +103 -0
- package/dist/audio/synth.js +197 -0
- package/dist/audio/variations.d.ts +25 -0
- package/dist/audio/variations.js +55 -0
- package/dist/audio/zones.d.ts +100 -0
- package/dist/audio/zones.js +167 -0
- package/dist/core/detached-surface.d.ts +44 -0
- package/dist/core/detached-surface.js +104 -0
- package/dist/core/events.d.ts +24 -0
- package/dist/core/events.js +43 -0
- package/dist/core/game.d.ts +409 -0
- package/dist/core/game.js +530 -0
- package/dist/core/hash.d.ts +24 -0
- package/dist/core/hash.js +49 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.js +9 -0
- package/dist/core/loop.d.ts +113 -0
- package/dist/core/loop.js +185 -0
- package/dist/core/math.d.ts +58 -0
- package/dist/core/math.js +210 -0
- package/dist/core/noise.d.ts +40 -0
- package/dist/core/noise.js +247 -0
- package/dist/core/pool.d.ts +42 -0
- package/dist/core/pool.js +85 -0
- package/dist/core/random.d.ts +61 -0
- package/dist/core/random.js +199 -0
- package/dist/core/scene.d.ts +79 -0
- package/dist/core/scene.js +195 -0
- package/dist/core/timer.d.ts +66 -0
- package/dist/core/timer.js +286 -0
- package/dist/fx/billboard-wgsl.d.ts +29 -0
- package/dist/fx/billboard-wgsl.js +158 -0
- package/dist/fx/billboard.d.ts +249 -0
- package/dist/fx/billboard.js +702 -0
- package/dist/fx/debug-draw.d.ts +127 -0
- package/dist/fx/debug-draw.js +523 -0
- package/dist/fx/debug-wgsl.d.ts +7 -0
- package/dist/fx/debug-wgsl.js +32 -0
- package/dist/fx/decals-wgsl.d.ts +15 -0
- package/dist/fx/decals-wgsl.js +173 -0
- package/dist/fx/decals.d.ts +216 -0
- package/dist/fx/decals.js +607 -0
- package/dist/fx/effect.d.ts +129 -0
- package/dist/fx/effect.js +349 -0
- package/dist/fx/effects/hit-spark.json +48 -0
- package/dist/fx/effects/index.d.ts +8 -0
- package/dist/fx/effects/index.js +9 -0
- package/dist/fx/effects/magic-aura.json +47 -0
- package/dist/fx/effects/smoke-puff.json +34 -0
- package/dist/fx/emit-surface.d.ts +40 -0
- package/dist/fx/emit-surface.js +124 -0
- package/dist/fx/flicker.d.ts +30 -0
- package/dist/fx/flicker.js +42 -0
- package/dist/fx/index.d.ts +31 -0
- package/dist/fx/index.js +20 -0
- package/dist/fx/particles-wgsl.d.ts +57 -0
- package/dist/fx/particles-wgsl.js +828 -0
- package/dist/fx/particles.d.ts +566 -0
- package/dist/fx/particles.js +1533 -0
- package/dist/fx/random.d.ts +15 -0
- package/dist/fx/random.js +20 -0
- package/dist/fx/sky-wgsl.d.ts +23 -0
- package/dist/fx/sky-wgsl.js +127 -0
- package/dist/fx/sky.d.ts +96 -0
- package/dist/fx/sky.js +175 -0
- package/dist/fx/text-atlas.d.ts +143 -0
- package/dist/fx/text-atlas.js +327 -0
- package/dist/fx/trail-wgsl.d.ts +11 -0
- package/dist/fx/trail-wgsl.js +42 -0
- package/dist/fx/trail.d.ts +194 -0
- package/dist/fx/trail.js +555 -0
- package/dist/fx/water-wgsl.d.ts +34 -0
- package/dist/fx/water-wgsl.js +197 -0
- package/dist/fx/water.d.ts +176 -0
- package/dist/fx/water.js +371 -0
- package/dist/geom/collide/bvh.d.ts +151 -0
- package/dist/geom/collide/bvh.js +493 -0
- package/dist/geom/collide/debug.d.ts +14 -0
- package/dist/geom/collide/debug.js +74 -0
- package/dist/geom/collide/grid.d.ts +26 -0
- package/dist/geom/collide/grid.js +91 -0
- package/dist/geom/collide/index.d.ts +8 -0
- package/dist/geom/collide/index.js +8 -0
- package/dist/geom/collide/queries.d.ts +70 -0
- package/dist/geom/collide/queries.js +583 -0
- package/dist/geom/collide/serialize.d.ts +14 -0
- package/dist/geom/collide/serialize.js +145 -0
- package/dist/geom/collide/shapes.d.ts +161 -0
- package/dist/geom/collide/shapes.js +686 -0
- package/dist/geom/collide/slide.d.ts +66 -0
- package/dist/geom/collide/slide.js +375 -0
- package/dist/geom/collide/tile-slide.d.ts +88 -0
- package/dist/geom/collide/tile-slide.js +255 -0
- package/dist/geom/geometry.d.ts +95 -0
- package/dist/geom/geometry.js +322 -0
- package/dist/geom/heightfield.d.ts +72 -0
- package/dist/geom/heightfield.js +295 -0
- package/dist/geom/hull.d.ts +27 -0
- package/dist/geom/hull.js +279 -0
- package/dist/geom/index.d.ts +35 -0
- package/dist/geom/index.js +23 -0
- package/dist/geom/iso.d.ts +74 -0
- package/dist/geom/iso.js +89 -0
- package/dist/geom/lod.d.ts +29 -0
- package/dist/geom/lod.js +27 -0
- package/dist/geom/ops.d.ts +47 -0
- package/dist/geom/ops.js +285 -0
- package/dist/geom/primitives.d.ts +97 -0
- package/dist/geom/primitives.js +359 -0
- package/dist/geom/shapes.d.ts +43 -0
- package/dist/geom/shapes.js +88 -0
- package/dist/geom/simplify.d.ts +38 -0
- package/dist/geom/simplify.js +519 -0
- package/dist/geom/split.d.ts +37 -0
- package/dist/geom/split.js +413 -0
- package/dist/geom/sweep.d.ts +83 -0
- package/dist/geom/sweep.js +534 -0
- package/dist/geom/tangents.d.ts +16 -0
- package/dist/geom/tangents.js +124 -0
- package/dist/geom/triangulate.d.ts +19 -0
- package/dist/geom/triangulate.js +147 -0
- package/dist/host/default.d.ts +10 -0
- package/dist/host/default.js +10 -0
- package/dist/host/index.d.ts +4 -0
- package/dist/host/index.js +3 -0
- package/dist/host/types.d.ts +144 -0
- package/dist/host/types.js +1 -0
- package/dist/host/web-links.d.ts +38 -0
- package/dist/host/web-links.js +110 -0
- package/dist/host/web.d.ts +30 -0
- package/dist/host/web.js +216 -0
- package/dist/host/xr.d.ts +24 -0
- package/dist/host/xr.js +59 -0
- package/dist/i18n/i18n.d.ts +59 -0
- package/dist/i18n/i18n.js +241 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/index.js +3 -0
- package/dist/i18n/message.d.ts +72 -0
- package/dist/i18n/message.js +369 -0
- package/dist/i18n/negotiate.d.ts +17 -0
- package/dist/i18n/negotiate.js +58 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -0
- package/dist/input/bindings.d.ts +31 -0
- package/dist/input/bindings.js +141 -0
- package/dist/input/clock.d.ts +44 -0
- package/dist/input/clock.js +49 -0
- package/dist/input/follow.d.ts +133 -0
- package/dist/input/follow.js +218 -0
- package/dist/input/gestures.d.ts +281 -0
- package/dist/input/gestures.js +662 -0
- package/dist/input/glyphs.d.ts +35 -0
- package/dist/input/glyphs.js +216 -0
- package/dist/input/gyro.d.ts +85 -0
- package/dist/input/gyro.js +140 -0
- package/dist/input/index.d.ts +19 -0
- package/dist/input/index.js +16 -0
- package/dist/input/input.d.ts +543 -0
- package/dist/input/input.js +1492 -0
- package/dist/input/look.d.ts +327 -0
- package/dist/input/look.js +681 -0
- package/dist/input/magnify.d.ts +177 -0
- package/dist/input/magnify.js +131 -0
- package/dist/input/pointer-dispatch.d.ts +138 -0
- package/dist/input/pointer-dispatch.js +180 -0
- package/dist/input/pointer-router.d.ts +204 -0
- package/dist/input/pointer-router.js +533 -0
- package/dist/input/pointer-sources.d.ts +164 -0
- package/dist/input/pointer-sources.js +306 -0
- package/dist/input/rays.d.ts +138 -0
- package/dist/input/rays.js +615 -0
- package/dist/input/record.d.ts +209 -0
- package/dist/input/record.js +601 -0
- package/dist/input/touch-zones.d.ts +147 -0
- package/dist/input/touch-zones.js +300 -0
- package/dist/input/types.d.ts +158 -0
- package/dist/input/types.js +1 -0
- package/dist/input/xr-source.d.ts +53 -0
- package/dist/input/xr-source.js +164 -0
- package/dist/nav/astar.d.ts +45 -0
- package/dist/nav/astar.js +182 -0
- package/dist/nav/corridor.d.ts +40 -0
- package/dist/nav/corridor.js +95 -0
- package/dist/nav/crowd.d.ts +94 -0
- package/dist/nav/crowd.js +624 -0
- package/dist/nav/flow.d.ts +61 -0
- package/dist/nav/flow.js +193 -0
- package/dist/nav/grid.d.ts +108 -0
- package/dist/nav/grid.js +210 -0
- package/dist/nav/heap.d.ts +22 -0
- package/dist/nav/heap.js +92 -0
- package/dist/nav/index.d.ts +37 -0
- package/dist/nav/index.js +19 -0
- package/dist/nav/mesh/areas.d.ts +44 -0
- package/dist/nav/mesh/areas.js +98 -0
- package/dist/nav/mesh/bake-options.d.ts +33 -0
- package/dist/nav/mesh/bake-options.js +76 -0
- package/dist/nav/mesh/contour.d.ts +22 -0
- package/dist/nav/mesh/contour.js +323 -0
- package/dist/nav/mesh/flow3.d.ts +35 -0
- package/dist/nav/mesh/flow3.js +229 -0
- package/dist/nav/mesh/links.d.ts +38 -0
- package/dist/nav/mesh/links.js +72 -0
- package/dist/nav/mesh/mesh-path.d.ts +152 -0
- package/dist/nav/mesh/mesh-path.js +643 -0
- package/dist/nav/mesh/mesh-reach.d.ts +78 -0
- package/dist/nav/mesh/mesh-reach.js +450 -0
- package/dist/nav/mesh/navmesh.d.ts +117 -0
- package/dist/nav/mesh/navmesh.js +647 -0
- package/dist/nav/mesh/polymesh.d.ts +24 -0
- package/dist/nav/mesh/polymesh.js +384 -0
- package/dist/nav/mesh/regions.d.ts +12 -0
- package/dist/nav/mesh/regions.js +367 -0
- package/dist/nav/mesh/serialize.d.ts +13 -0
- package/dist/nav/mesh/serialize.js +197 -0
- package/dist/nav/mesh/voxelize.d.ts +111 -0
- package/dist/nav/mesh/voxelize.js +552 -0
- package/dist/nav/obstacles.d.ts +75 -0
- package/dist/nav/obstacles.js +294 -0
- package/dist/nav/path.d.ts +59 -0
- package/dist/nav/path.js +177 -0
- package/dist/nav/query-queue.d.ts +46 -0
- package/dist/nav/query-queue.js +308 -0
- package/dist/nav/reach.d.ts +53 -0
- package/dist/nav/reach.js +148 -0
- package/dist/nav/steer.d.ts +36 -0
- package/dist/nav/steer.js +78 -0
- package/dist/platform/boot.d.ts +28 -0
- package/dist/platform/boot.js +43 -0
- package/dist/platform/device-mode.d.ts +40 -0
- package/dist/platform/device-mode.js +104 -0
- package/dist/platform/device.d.ts +31 -0
- package/dist/platform/device.js +91 -0
- package/dist/platform/environment.d.ts +42 -0
- package/dist/platform/environment.js +82 -0
- package/dist/platform/gpu.d.ts +40 -0
- package/dist/platform/gpu.js +57 -0
- package/dist/platform/index.d.ts +18 -0
- package/dist/platform/index.js +10 -0
- package/dist/platform/letterbox.d.ts +43 -0
- package/dist/platform/letterbox.js +57 -0
- package/dist/platform/links.d.ts +20 -0
- package/dist/platform/links.js +43 -0
- package/dist/platform/screens.d.ts +36 -0
- package/dist/platform/screens.js +138 -0
- package/dist/platform/surface.d.ts +72 -0
- package/dist/platform/surface.js +157 -0
- package/dist/platform/xr-fake.d.ts +168 -0
- package/dist/platform/xr-fake.js +434 -0
- package/dist/platform/xr-surface.d.ts +120 -0
- package/dist/platform/xr-surface.js +214 -0
- package/dist/platform/xr-types.d.ts +262 -0
- package/dist/post/ao.d.ts +12 -0
- package/dist/post/ao.js +136 -0
- package/dist/post/blend.d.ts +27 -0
- package/dist/post/blend.js +129 -0
- package/dist/post/depth-pass.d.ts +43 -0
- package/dist/post/depth-pass.js +118 -0
- package/dist/post/dof.d.ts +1 -0
- package/dist/post/dof.js +66 -0
- package/dist/post/exposure.d.ts +80 -0
- package/dist/post/exposure.js +322 -0
- package/dist/post/index.d.ts +12 -0
- package/dist/post/index.js +11 -0
- package/dist/post/lens-dirt.d.ts +13 -0
- package/dist/post/lens-dirt.js +91 -0
- package/dist/post/lut.d.ts +19 -0
- package/dist/post/lut.js +50 -0
- package/dist/post/motion-blur.d.ts +9 -0
- package/dist/post/motion-blur.js +78 -0
- package/dist/post/post-stack.d.ts +302 -0
- package/dist/post/post-stack.js +1137 -0
- package/dist/post/settings.d.ts +485 -0
- package/dist/post/settings.js +416 -0
- package/dist/post/shaders.d.ts +25 -0
- package/dist/post/shaders.js +410 -0
- package/dist/post/ssr.d.ts +16 -0
- package/dist/post/ssr.js +155 -0
- package/dist/post/taa.d.ts +74 -0
- package/dist/post/taa.js +235 -0
- package/dist/post/white-balance.d.ts +25 -0
- package/dist/post/white-balance.js +98 -0
- package/dist/render/bindings.d.ts +98 -0
- package/dist/render/bindings.js +281 -0
- package/dist/render/blend.d.ts +13 -0
- package/dist/render/blend.js +26 -0
- package/dist/render/camera-2d.d.ts +72 -0
- package/dist/render/camera-2d.js +92 -0
- package/dist/render/camera.d.ts +302 -0
- package/dist/render/camera.js +671 -0
- package/dist/render/color.d.ts +16 -0
- package/dist/render/color.js +41 -0
- package/dist/render/compressed.d.ts +104 -0
- package/dist/render/compressed.js +248 -0
- package/dist/render/diagnostics.d.ts +15 -0
- package/dist/render/diagnostics.js +43 -0
- package/dist/render/dynamic-resolution.d.ts +70 -0
- package/dist/render/dynamic-resolution.js +126 -0
- package/dist/render/fake-gpu.d.ts +204 -0
- package/dist/render/fake-gpu.js +426 -0
- package/dist/render/flipbook.d.ts +56 -0
- package/dist/render/flipbook.js +87 -0
- package/dist/render/frame.d.ts +278 -0
- package/dist/render/frame.js +174 -0
- package/dist/render/fullscreen.d.ts +54 -0
- package/dist/render/fullscreen.js +91 -0
- package/dist/render/gpu-timer.d.ts +73 -0
- package/dist/render/gpu-timer.js +186 -0
- package/dist/render/index.d.ts +53 -0
- package/dist/render/index.js +29 -0
- package/dist/render/instance-list.d.ts +185 -0
- package/dist/render/instance-list.js +547 -0
- package/dist/render/lights.d.ts +181 -0
- package/dist/render/lights.js +233 -0
- package/dist/render/lod.d.ts +54 -0
- package/dist/render/lod.js +52 -0
- package/dist/render/material.d.ts +165 -0
- package/dist/render/material.js +292 -0
- package/dist/render/mesh.d.ts +284 -0
- package/dist/render/mesh.js +472 -0
- package/dist/render/mipmap.d.ts +16 -0
- package/dist/render/mipmap.js +121 -0
- package/dist/render/parallax.d.ts +50 -0
- package/dist/render/parallax.js +47 -0
- package/dist/render/pbr-wgsl.d.ts +31 -0
- package/dist/render/pbr-wgsl.js +119 -0
- package/dist/render/ping-pong.d.ts +42 -0
- package/dist/render/ping-pong.js +74 -0
- package/dist/render/renderer.d.ts +741 -0
- package/dist/render/renderer.js +2486 -0
- package/dist/render/scene-pipelines.d.ts +44 -0
- package/dist/render/scene-pipelines.js +92 -0
- package/dist/render/scene-target.d.ts +170 -0
- package/dist/render/scene-target.js +450 -0
- package/dist/render/shadow.d.ts +74 -0
- package/dist/render/shadow.js +208 -0
- package/dist/render/skin.d.ts +112 -0
- package/dist/render/skin.js +240 -0
- package/dist/render/snapshot.d.ts +36 -0
- package/dist/render/snapshot.js +34 -0
- package/dist/render/standard.d.ts +162 -0
- package/dist/render/standard.js +263 -0
- package/dist/render/texture.d.ts +142 -0
- package/dist/render/texture.js +228 -0
- package/dist/render/tile-layer.d.ts +110 -0
- package/dist/render/tile-layer.js +304 -0
- package/dist/render/transform.d.ts +115 -0
- package/dist/render/transform.js +318 -0
- package/dist/render/wgsl.d.ts +131 -0
- package/dist/render/wgsl.js +528 -0
- package/dist/save/codec.d.ts +49 -0
- package/dist/save/codec.js +169 -0
- package/dist/save/index.d.ts +8 -0
- package/dist/save/index.js +8 -0
- package/dist/save/journal.d.ts +24 -0
- package/dist/save/journal.js +102 -0
- package/dist/save/migrate.d.ts +15 -0
- package/dist/save/migrate.js +37 -0
- package/dist/save/schema.d.ts +72 -0
- package/dist/save/schema.js +154 -0
- package/dist/save/settings.d.ts +28 -0
- package/dist/save/settings.js +59 -0
- package/dist/save/slots.d.ts +56 -0
- package/dist/save/slots.js +200 -0
- package/dist/save/storage.d.ts +35 -0
- package/dist/save/storage.js +62 -0
- package/dist/save/store.d.ts +114 -0
- package/dist/save/store.js +269 -0
- package/dist/testing/fake-host.d.ts +103 -0
- package/dist/testing/fake-host.js +163 -0
- package/dist/testing/fixed-clock.d.ts +25 -0
- package/dist/testing/fixed-clock.js +30 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/test-game.d.ts +76 -0
- package/dist/testing/test-game.js +92 -0
- package/dist/tween/ease.d.ts +77 -0
- package/dist/tween/ease.js +192 -0
- package/dist/tween/index.d.ts +8 -0
- package/dist/tween/index.js +7 -0
- package/dist/tween/timeline.d.ts +78 -0
- package/dist/tween/timeline.js +269 -0
- package/dist/tween/tween.d.ts +168 -0
- package/dist/tween/tween.js +320 -0
- package/dist/ui/anchor.d.ts +206 -0
- package/dist/ui/anchor.js +307 -0
- package/dist/ui/caption.d.ts +122 -0
- package/dist/ui/caption.js +286 -0
- package/dist/ui/cursor.d.ts +105 -0
- package/dist/ui/cursor.js +261 -0
- package/dist/ui/dom.d.ts +30 -0
- package/dist/ui/dom.js +92 -0
- package/dist/ui/floats.d.ts +86 -0
- package/dist/ui/floats.js +260 -0
- package/dist/ui/hud.d.ts +198 -0
- package/dist/ui/hud.js +431 -0
- package/dist/ui/index.d.ts +37 -0
- package/dist/ui/index.js +34 -0
- package/dist/ui/inventory-card.d.ts +52 -0
- package/dist/ui/inventory-card.js +173 -0
- package/dist/ui/inventory-context.d.ts +29 -0
- package/dist/ui/inventory-context.js +125 -0
- package/dist/ui/inventory-drag.d.ts +63 -0
- package/dist/ui/inventory-drag.js +394 -0
- package/dist/ui/inventory-grid.d.ts +66 -0
- package/dist/ui/inventory-grid.js +625 -0
- package/dist/ui/inventory-radial.d.ts +39 -0
- package/dist/ui/inventory-radial.js +168 -0
- package/dist/ui/inventory.d.ts +128 -0
- package/dist/ui/inventory.js +154 -0
- package/dist/ui/layout.d.ts +356 -0
- package/dist/ui/layout.js +856 -0
- package/dist/ui/link.d.ts +64 -0
- package/dist/ui/link.js +155 -0
- package/dist/ui/loading.d.ts +40 -0
- package/dist/ui/loading.js +157 -0
- package/dist/ui/loupe.d.ts +74 -0
- package/dist/ui/loupe.js +164 -0
- package/dist/ui/menu-nav.d.ts +33 -0
- package/dist/ui/menu-nav.js +28 -0
- package/dist/ui/minimap-canvas.d.ts +145 -0
- package/dist/ui/minimap-canvas.js +460 -0
- package/dist/ui/notify.d.ts +40 -0
- package/dist/ui/notify.js +141 -0
- package/dist/ui/orb.d.ts +53 -0
- package/dist/ui/orb.js +304 -0
- package/dist/ui/overlay.d.ts +213 -0
- package/dist/ui/overlay.js +394 -0
- package/dist/ui/padnav.d.ts +53 -0
- package/dist/ui/padnav.js +146 -0
- package/dist/ui/perf.d.ts +130 -0
- package/dist/ui/perf.js +329 -0
- package/dist/ui/rotate-card.d.ts +54 -0
- package/dist/ui/rotate-card.js +97 -0
- package/dist/ui/stack.d.ts +128 -0
- package/dist/ui/stack.js +312 -0
- package/dist/ui/styles.d.ts +13 -0
- package/dist/ui/styles.js +200 -0
- package/dist/ui/text-scale.d.ts +67 -0
- package/dist/ui/text-scale.js +102 -0
- package/dist/ui/theme.d.ts +70 -0
- package/dist/ui/theme.js +98 -0
- package/dist/ui/toast.d.ts +23 -0
- package/dist/ui/toast.js +46 -0
- package/dist/ui/tooltip.d.ts +89 -0
- package/dist/ui/tooltip.js +333 -0
- package/dist/ui/widgets-2.d.ts +134 -0
- package/dist/ui/widgets-2.js +399 -0
- package/dist/ui/widgets-3.d.ts +91 -0
- package/dist/ui/widgets-3.js +212 -0
- package/dist/ui/widgets.d.ts +34 -0
- package/dist/ui/widgets.js +50 -0
- package/dist/ui/world-panel/index.d.ts +5 -0
- package/dist/ui/world-panel/index.js +5 -0
- package/dist/ui/world-panel/layout.d.ts +38 -0
- package/dist/ui/world-panel/layout.js +68 -0
- package/dist/ui/world-panel/paint.d.ts +96 -0
- package/dist/ui/world-panel/paint.js +136 -0
- package/dist/ui/world-panel/panel.d.ts +235 -0
- package/dist/ui/world-panel/panel.js +762 -0
- package/dist/ui/world-panel/wgsl.d.ts +10 -0
- package/dist/ui/world-panel/wgsl.js +52 -0
- package/dist/ui/world-panel/widgets.d.ts +207 -0
- package/dist/ui/world-panel/widgets.js +569 -0
- package/dist/voxel/chunks.d.ts +77 -0
- package/dist/voxel/chunks.js +149 -0
- package/dist/voxel/grid.d.ts +84 -0
- package/dist/voxel/grid.js +223 -0
- package/dist/voxel/index.d.ts +22 -0
- package/dist/voxel/index.js +7 -0
- package/dist/voxel/mesher-worker.d.ts +14 -0
- package/dist/voxel/mesher-worker.js +47 -0
- package/dist/voxel/mesher.d.ts +73 -0
- package/dist/voxel/mesher.js +306 -0
- package/dist/voxel/ray.d.ts +32 -0
- package/dist/voxel/ray.js +73 -0
- package/dist/voxel/wgsl.d.ts +16 -0
- package/dist/voxel/wgsl.js +28 -0
- package/dist/voxel/worker-client.d.ts +79 -0
- package/dist/voxel/worker-client.js +122 -0
- package/package.json +177 -3
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heightfields: a grid of heights a game stands on and clicks. `heightAt` and `normalAt` sample
|
|
3
|
+
* the bilinear surface, `raycastHeightfield` walks the grid cells a ray crosses (DDA) and solves
|
|
4
|
+
* the ray against each cell's bilinear patch exactly, and `heightfieldGeometry` builds the same
|
|
5
|
+
* surface as triangles. Nothing here allocates after the field exists.
|
|
6
|
+
*
|
|
7
|
+
* Layout: `heights[z * width + x]`, row-major by z then x, in height units; a sample `(x, z)`
|
|
8
|
+
* sits in the world at `origin + (x * scale[0], heights * scale[1], z * scale[2])`. Outside the
|
|
9
|
+
* field the surface continues flat from the nearest edge sample.
|
|
10
|
+
*/
|
|
11
|
+
import { type Geometry, type GeometryOptions } from './geometry.js';
|
|
12
|
+
/** A 3-vector the heightfield functions read or write in place. */
|
|
13
|
+
export type HeightfieldVec3 = [number, number, number] | Float32Array | Float64Array;
|
|
14
|
+
/** A ray in world units: `origin` and a direction (`raycastHeightfield` returns distance along it). */
|
|
15
|
+
export interface HeightfieldRay {
|
|
16
|
+
readonly origin: ArrayLike<number>;
|
|
17
|
+
readonly dir: ArrayLike<number>;
|
|
18
|
+
}
|
|
19
|
+
export interface Heightfield {
|
|
20
|
+
/** Samples along x (≥ 2). */
|
|
21
|
+
readonly width: number;
|
|
22
|
+
/** Samples along z (≥ 2). */
|
|
23
|
+
readonly depth: number;
|
|
24
|
+
/** `width × depth` heights, `heights[z * width + x]`, in height units (× `scale[1]`). */
|
|
25
|
+
readonly heights: Float32Array;
|
|
26
|
+
/** World units per sample along x, per height unit, per sample along z. */
|
|
27
|
+
readonly scale: [number, number, number];
|
|
28
|
+
/** World position of sample (0, 0) at height 0. */
|
|
29
|
+
readonly origin: [number, number, number];
|
|
30
|
+
}
|
|
31
|
+
export interface HeightfieldOptions {
|
|
32
|
+
/** Default `[1, 1, 1]`. */
|
|
33
|
+
scale?: [number, number, number];
|
|
34
|
+
/** Default `[0, 0, 0]`. */
|
|
35
|
+
origin?: [number, number, number];
|
|
36
|
+
/** Initial heights (`width × depth`, copied by reference). Default all zero. */
|
|
37
|
+
heights?: Float32Array;
|
|
38
|
+
}
|
|
39
|
+
/** A heightfield of `width × depth` samples; fill `heights` in place. */
|
|
40
|
+
export declare function createHeightfield(width: number, depth: number, opts?: HeightfieldOptions): Heightfield;
|
|
41
|
+
/** World height of the surface under world `(x, z)`: bilinear between the four nearest samples. */
|
|
42
|
+
export declare function heightAt(hf: Heightfield, x: number, z: number): number;
|
|
43
|
+
/**
|
|
44
|
+
* Unit surface normal at world `(x, z)`, written to `out` (y up). Central differences over half
|
|
45
|
+
* a sample on each side, so it is the bilinear surface's slope smoothed across cell edges.
|
|
46
|
+
*/
|
|
47
|
+
export declare function normalAt<T extends HeightfieldVec3>(hf: Heightfield, x: number, z: number, out: T): T;
|
|
48
|
+
/**
|
|
49
|
+
* Nearest intersection of `ray` with the surface, as the distance along `ray.dir` (world units
|
|
50
|
+
* when `dir` is unit length), or -1 for a miss. The ray is clipped to the field's footprint, the
|
|
51
|
+
* cells it crosses are walked in order (DDA), and in each the ray is solved against that cell's
|
|
52
|
+
* bilinear patch (a quadratic in the distance), so a hit lies exactly on `heightAt`. Hits from
|
|
53
|
+
* below count too. `out`, when given, receives the hit point. No allocation.
|
|
54
|
+
*/
|
|
55
|
+
export declare function raycastHeightfield(hf: Heightfield, ray: HeightfieldRay, out?: HeightfieldVec3): number;
|
|
56
|
+
/**
|
|
57
|
+
* `raycastHeightfield` taking the ray as two arrays: `origin` and `dir` (a `Ray` from `input`,
|
|
58
|
+
* a camera's eye and look direction, or plain `[x, y, z]`s), so a game casts without building a
|
|
59
|
+
* `HeightfieldRay`. Returns the distance along `dir` or -1; `out` receives the hit point.
|
|
60
|
+
*/
|
|
61
|
+
export declare function rayHeightfield(hf: Heightfield, origin: ArrayLike<number>, dir: ArrayLike<number>, out?: HeightfieldVec3): number;
|
|
62
|
+
export interface HeightfieldGeometryOptions extends GeometryOptions {
|
|
63
|
+
/** Flat normals from each cell's two triangles instead of the smooth surface normal. Default false. */
|
|
64
|
+
flat?: boolean;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The field as triangles in world units: one vertex per sample (u along x, v along z, 0..1
|
|
68
|
+
* across the field), two triangles per cell, smooth normals from `normalAt`. Promotes to 32-bit
|
|
69
|
+
* indices past 65535 samples. With `flat`, each cell's triangles get their own vertices and face
|
|
70
|
+
* normals (six vertices per cell).
|
|
71
|
+
*/
|
|
72
|
+
export declare function heightfieldGeometry(hf: Heightfield, opts?: HeightfieldGeometryOptions): Geometry;
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heightfields: a grid of heights a game stands on and clicks. `heightAt` and `normalAt` sample
|
|
3
|
+
* the bilinear surface, `raycastHeightfield` walks the grid cells a ray crosses (DDA) and solves
|
|
4
|
+
* the ray against each cell's bilinear patch exactly, and `heightfieldGeometry` builds the same
|
|
5
|
+
* surface as triangles. Nothing here allocates after the field exists.
|
|
6
|
+
*
|
|
7
|
+
* Layout: `heights[z * width + x]`, row-major by z then x, in height units; a sample `(x, z)`
|
|
8
|
+
* sits in the world at `origin + (x * scale[0], heights * scale[1], z * scale[2])`. Outside the
|
|
9
|
+
* field the surface continues flat from the nearest edge sample.
|
|
10
|
+
*/
|
|
11
|
+
import { GeometryWriter } from './geometry.js';
|
|
12
|
+
/** A heightfield of `width × depth` samples; fill `heights` in place. */
|
|
13
|
+
export function createHeightfield(width, depth, opts = {}) {
|
|
14
|
+
if (!(width >= 2) || !(depth >= 2)) {
|
|
15
|
+
throw new Error(`geom: a heightfield needs at least 2×2 samples, got ${width}×${depth}`);
|
|
16
|
+
}
|
|
17
|
+
const heights = opts.heights ?? new Float32Array(width * depth);
|
|
18
|
+
if (heights.length !== width * depth) {
|
|
19
|
+
throw new Error(`geom: heights has ${heights.length} samples, expected ${width * depth}`);
|
|
20
|
+
}
|
|
21
|
+
const s = opts.scale ?? [1, 1, 1];
|
|
22
|
+
const o = opts.origin ?? [0, 0, 0];
|
|
23
|
+
return {
|
|
24
|
+
width,
|
|
25
|
+
depth,
|
|
26
|
+
heights,
|
|
27
|
+
scale: [s[0], s[1], s[2]],
|
|
28
|
+
origin: [o[0], o[1], o[2]],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Bilinear height in grid space (`gx`, `gz` in samples), clamped to the field. Height units. */
|
|
32
|
+
function sampleGrid(hf, gx, gz) {
|
|
33
|
+
const { width, depth, heights } = hf;
|
|
34
|
+
const cx = Math.min(Math.max(gx, 0), width - 1);
|
|
35
|
+
const cz = Math.min(Math.max(gz, 0), depth - 1);
|
|
36
|
+
let x0 = Math.floor(cx);
|
|
37
|
+
let z0 = Math.floor(cz);
|
|
38
|
+
if (x0 >= width - 1)
|
|
39
|
+
x0 = width - 2;
|
|
40
|
+
if (z0 >= depth - 1)
|
|
41
|
+
z0 = depth - 2;
|
|
42
|
+
const u = cx - x0;
|
|
43
|
+
const v = cz - z0;
|
|
44
|
+
const o = z0 * width + x0;
|
|
45
|
+
const h00 = heights[o];
|
|
46
|
+
const h10 = heights[o + 1];
|
|
47
|
+
const h01 = heights[o + width];
|
|
48
|
+
const h11 = heights[o + width + 1];
|
|
49
|
+
return (h00 * (1 - u) + h10 * u) * (1 - v) + (h01 * (1 - u) + h11 * u) * v;
|
|
50
|
+
}
|
|
51
|
+
/** World height of the surface under world `(x, z)`: bilinear between the four nearest samples. */
|
|
52
|
+
export function heightAt(hf, x, z) {
|
|
53
|
+
const gx = (x - hf.origin[0]) / hf.scale[0];
|
|
54
|
+
const gz = (z - hf.origin[2]) / hf.scale[2];
|
|
55
|
+
return hf.origin[1] + sampleGrid(hf, gx, gz) * hf.scale[1];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Unit surface normal at world `(x, z)`, written to `out` (y up). Central differences over half
|
|
59
|
+
* a sample on each side, so it is the bilinear surface's slope smoothed across cell edges.
|
|
60
|
+
*/
|
|
61
|
+
export function normalAt(hf, x, z, out) {
|
|
62
|
+
const hx = hf.scale[0] * 0.5;
|
|
63
|
+
const hz = hf.scale[2] * 0.5;
|
|
64
|
+
const dx = heightAt(hf, x - hx, z) - heightAt(hf, x + hx, z);
|
|
65
|
+
const dz = heightAt(hf, x, z - hz) - heightAt(hf, x, z + hz);
|
|
66
|
+
const nx = dx;
|
|
67
|
+
const ny = 2 * hx;
|
|
68
|
+
const nz = dz * (hx / hz);
|
|
69
|
+
const l = Math.hypot(nx, ny, nz);
|
|
70
|
+
out[0] = nx / l;
|
|
71
|
+
out[1] = ny / l;
|
|
72
|
+
out[2] = nz / l;
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
/** Cells a DDA may visit beyond the grid's own extent before it is forced to stop. */
|
|
76
|
+
const DDA_SLACK = 2;
|
|
77
|
+
const EPS = 1e-9;
|
|
78
|
+
/**
|
|
79
|
+
* Nearest intersection of `ray` with the surface, as the distance along `ray.dir` (world units
|
|
80
|
+
* when `dir` is unit length), or -1 for a miss. The ray is clipped to the field's footprint, the
|
|
81
|
+
* cells it crosses are walked in order (DDA), and in each the ray is solved against that cell's
|
|
82
|
+
* bilinear patch (a quadratic in the distance), so a hit lies exactly on `heightAt`. Hits from
|
|
83
|
+
* below count too. `out`, when given, receives the hit point. No allocation.
|
|
84
|
+
*/
|
|
85
|
+
export function raycastHeightfield(hf, ray, out) {
|
|
86
|
+
const { width, depth, heights, scale, origin } = hf;
|
|
87
|
+
// Grid space: x and z in samples, y in height units.
|
|
88
|
+
const ox = (ray.origin[0] - origin[0]) / scale[0];
|
|
89
|
+
const oy = (ray.origin[1] - origin[1]) / scale[1];
|
|
90
|
+
const oz = (ray.origin[2] - origin[2]) / scale[2];
|
|
91
|
+
const dx = ray.dir[0] / scale[0];
|
|
92
|
+
const dy = ray.dir[1] / scale[1];
|
|
93
|
+
const dz = ray.dir[2] / scale[2];
|
|
94
|
+
// Clip to the footprint 0..width-1 × 0..depth-1.
|
|
95
|
+
let t0 = 0;
|
|
96
|
+
let t1 = Number.POSITIVE_INFINITY;
|
|
97
|
+
if (Math.abs(dx) < EPS) {
|
|
98
|
+
if (ox < 0 || ox > width - 1)
|
|
99
|
+
return -1;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const ta = -ox / dx;
|
|
103
|
+
const tb = (width - 1 - ox) / dx;
|
|
104
|
+
t0 = Math.max(t0, Math.min(ta, tb));
|
|
105
|
+
t1 = Math.min(t1, Math.max(ta, tb));
|
|
106
|
+
}
|
|
107
|
+
if (Math.abs(dz) < EPS) {
|
|
108
|
+
if (oz < 0 || oz > depth - 1)
|
|
109
|
+
return -1;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const ta = -oz / dz;
|
|
113
|
+
const tb = (depth - 1 - oz) / dz;
|
|
114
|
+
t0 = Math.max(t0, Math.min(ta, tb));
|
|
115
|
+
t1 = Math.min(t1, Math.max(ta, tb));
|
|
116
|
+
}
|
|
117
|
+
if (t1 < t0)
|
|
118
|
+
return -1;
|
|
119
|
+
// Starting cell, clamped so a ray entering on the far edge lands in the last cell.
|
|
120
|
+
const sx = ox + dx * t0;
|
|
121
|
+
const sz = oz + dz * t0;
|
|
122
|
+
let cx = Math.floor(sx);
|
|
123
|
+
let cz = Math.floor(sz);
|
|
124
|
+
if (cx < 0)
|
|
125
|
+
cx = 0;
|
|
126
|
+
if (cx > width - 2)
|
|
127
|
+
cx = width - 2;
|
|
128
|
+
if (cz < 0)
|
|
129
|
+
cz = 0;
|
|
130
|
+
if (cz > depth - 2)
|
|
131
|
+
cz = depth - 2;
|
|
132
|
+
const stepX = dx > 0 ? 1 : -1;
|
|
133
|
+
const stepZ = dz > 0 ? 1 : -1;
|
|
134
|
+
const tDeltaX = Math.abs(dx) < EPS ? Number.POSITIVE_INFINITY : Math.abs(1 / dx);
|
|
135
|
+
const tDeltaZ = Math.abs(dz) < EPS ? Number.POSITIVE_INFINITY : Math.abs(1 / dz);
|
|
136
|
+
let tMaxX = Math.abs(dx) < EPS ? Number.POSITIVE_INFINITY : ((dx > 0 ? cx + 1 : cx) - ox) / dx;
|
|
137
|
+
let tMaxZ = Math.abs(dz) < EPS ? Number.POSITIVE_INFINITY : ((dz > 0 ? cz + 1 : cz) - oz) / dz;
|
|
138
|
+
let t = t0;
|
|
139
|
+
const maxSteps = width + depth + DDA_SLACK;
|
|
140
|
+
for (let step = 0; step < maxSteps; step++) {
|
|
141
|
+
const tEnd = Math.min(tMaxX, tMaxZ, t1);
|
|
142
|
+
// The patch of cell (cx, cz): h(u, v) = h00 + a u + b v + c u v, u = x - cx, v = z - cz.
|
|
143
|
+
const o = cz * width + cx;
|
|
144
|
+
const h00 = heights[o];
|
|
145
|
+
const a = heights[o + 1] - h00;
|
|
146
|
+
const b = heights[o + width] - h00;
|
|
147
|
+
const c = h00 - heights[o + 1] - heights[o + width] + heights[o + width + 1];
|
|
148
|
+
// f(t) = y(t) - h(u(t), v(t)), with u(t) = u0 + dx t, v(t) = v0 + dz t:
|
|
149
|
+
const u0 = ox - cx;
|
|
150
|
+
const v0 = oz - cz;
|
|
151
|
+
const qa = -c * dx * dz;
|
|
152
|
+
const qb = dy - a * dx - b * dz - c * (u0 * dz + v0 * dx);
|
|
153
|
+
const qc = oy - h00 - a * u0 - b * v0 - c * u0 * v0;
|
|
154
|
+
const hit = smallestRoot(qa, qb, qc, t, tEnd);
|
|
155
|
+
if (hit >= 0) {
|
|
156
|
+
if (out) {
|
|
157
|
+
out[0] = ray.origin[0] + ray.dir[0] * hit;
|
|
158
|
+
out[1] = ray.origin[1] + ray.dir[1] * hit;
|
|
159
|
+
out[2] = ray.origin[2] + ray.dir[2] * hit;
|
|
160
|
+
}
|
|
161
|
+
return hit;
|
|
162
|
+
}
|
|
163
|
+
if (tEnd >= t1)
|
|
164
|
+
return -1;
|
|
165
|
+
if (tMaxX < tMaxZ) {
|
|
166
|
+
cx += stepX;
|
|
167
|
+
t = tMaxX;
|
|
168
|
+
tMaxX += tDeltaX;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
cz += stepZ;
|
|
172
|
+
t = tMaxZ;
|
|
173
|
+
tMaxZ += tDeltaZ;
|
|
174
|
+
}
|
|
175
|
+
if (cx < 0 || cx > width - 2 || cz < 0 || cz > depth - 2)
|
|
176
|
+
return -1;
|
|
177
|
+
}
|
|
178
|
+
return -1;
|
|
179
|
+
}
|
|
180
|
+
/** Scratch ray for `rayHeightfield` (no allocation per call). */
|
|
181
|
+
const scratchRay = {
|
|
182
|
+
origin: [0, 0, 0],
|
|
183
|
+
dir: [0, 0, 1],
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* `raycastHeightfield` taking the ray as two arrays: `origin` and `dir` (a `Ray` from `input`,
|
|
187
|
+
* a camera's eye and look direction, or plain `[x, y, z]`s), so a game casts without building a
|
|
188
|
+
* `HeightfieldRay`. Returns the distance along `dir` or -1; `out` receives the hit point.
|
|
189
|
+
*/
|
|
190
|
+
export function rayHeightfield(hf, origin, dir, out) {
|
|
191
|
+
scratchRay.origin = origin;
|
|
192
|
+
scratchRay.dir = dir;
|
|
193
|
+
return raycastHeightfield(hf, scratchRay, out);
|
|
194
|
+
}
|
|
195
|
+
/** Smallest root of `a t² + b t + c = 0` within `[lo, hi]`, or -1. */
|
|
196
|
+
function smallestRoot(a, b, c, lo, hi) {
|
|
197
|
+
const tol = 1e-7 * Math.max(1, Math.abs(lo));
|
|
198
|
+
if (Math.abs(a) < 1e-12) {
|
|
199
|
+
if (Math.abs(b) < 1e-12)
|
|
200
|
+
return -1;
|
|
201
|
+
const t = -c / b;
|
|
202
|
+
return t >= lo - tol && t <= hi + tol ? Math.max(lo, t) : -1;
|
|
203
|
+
}
|
|
204
|
+
const disc = b * b - 4 * a * c;
|
|
205
|
+
if (disc < 0)
|
|
206
|
+
return -1;
|
|
207
|
+
const s = Math.sqrt(disc);
|
|
208
|
+
// Stable pair: q avoids cancellation.
|
|
209
|
+
const q = b >= 0 ? -(b + s) / 2 : -(b - s) / 2;
|
|
210
|
+
const r1 = q / a;
|
|
211
|
+
const r2 = q !== 0 ? c / q : r1;
|
|
212
|
+
const tA = Math.min(r1, r2);
|
|
213
|
+
const tB = Math.max(r1, r2);
|
|
214
|
+
if (tA >= lo - tol && tA <= hi + tol)
|
|
215
|
+
return Math.max(lo, tA);
|
|
216
|
+
if (tB >= lo - tol && tB <= hi + tol)
|
|
217
|
+
return Math.max(lo, tB);
|
|
218
|
+
return -1;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* The field as triangles in world units: one vertex per sample (u along x, v along z, 0..1
|
|
222
|
+
* across the field), two triangles per cell, smooth normals from `normalAt`. Promotes to 32-bit
|
|
223
|
+
* indices past 65535 samples. With `flat`, each cell's triangles get their own vertices and face
|
|
224
|
+
* normals (six vertices per cell).
|
|
225
|
+
*/
|
|
226
|
+
export function heightfieldGeometry(hf, opts = {}) {
|
|
227
|
+
const { width, depth, scale, origin } = hf;
|
|
228
|
+
const cells = (width - 1) * (depth - 1);
|
|
229
|
+
if (opts.flat)
|
|
230
|
+
return flatGeometry(hf, opts);
|
|
231
|
+
const w = new GeometryWriter(width * depth, cells * 6, opts);
|
|
232
|
+
const n = [0, 1, 0];
|
|
233
|
+
for (let j = 0; j < depth; j++) {
|
|
234
|
+
for (let i = 0; i < width; i++) {
|
|
235
|
+
const x = origin[0] + i * scale[0];
|
|
236
|
+
const z = origin[2] + j * scale[2];
|
|
237
|
+
const y = origin[1] + hf.heights[j * width + i] * scale[1];
|
|
238
|
+
normalAt(hf, x, z, n);
|
|
239
|
+
w.vertex(x, y, z, n[0], n[1], n[2], i / (width - 1), j / (depth - 1));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
for (let j = 0; j < depth - 1; j++) {
|
|
243
|
+
for (let i = 0; i < width - 1; i++) {
|
|
244
|
+
const a = j * width + i;
|
|
245
|
+
// (i, j) → (i, j+1) → (i+1, j+1) → (i+1, j): +z then +x, normal up.
|
|
246
|
+
w.quad(a, a + width, a + width + 1, a + 1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return w.finish();
|
|
250
|
+
}
|
|
251
|
+
function flatGeometry(hf, opts) {
|
|
252
|
+
const { width, depth, scale, origin, heights } = hf;
|
|
253
|
+
const cells = (width - 1) * (depth - 1);
|
|
254
|
+
const w = new GeometryWriter(cells * 6, cells * 6, opts);
|
|
255
|
+
const px = (i) => origin[0] + i * scale[0];
|
|
256
|
+
const pz = (j) => origin[2] + j * scale[2];
|
|
257
|
+
const py = (i, j) => origin[1] + heights[j * width + i] * scale[1];
|
|
258
|
+
const tri = (i0, j0, i1, j1, i2, j2) => {
|
|
259
|
+
const x0 = px(i0);
|
|
260
|
+
const y0 = py(i0, j0);
|
|
261
|
+
const z0 = pz(j0);
|
|
262
|
+
const x1 = px(i1);
|
|
263
|
+
const y1 = py(i1, j1);
|
|
264
|
+
const z1 = pz(j1);
|
|
265
|
+
const x2 = px(i2);
|
|
266
|
+
const y2 = py(i2, j2);
|
|
267
|
+
const z2 = pz(j2);
|
|
268
|
+
const ax = x1 - x0;
|
|
269
|
+
const ay = y1 - y0;
|
|
270
|
+
const az = z1 - z0;
|
|
271
|
+
const bx = x2 - x0;
|
|
272
|
+
const by = y2 - y0;
|
|
273
|
+
const bz = z2 - z0;
|
|
274
|
+
let nx = ay * bz - az * by;
|
|
275
|
+
let ny = az * bx - ax * bz;
|
|
276
|
+
let nz = ax * by - ay * bx;
|
|
277
|
+
const l = Math.hypot(nx, ny, nz) || 1;
|
|
278
|
+
nx /= l;
|
|
279
|
+
ny /= l;
|
|
280
|
+
nz /= l;
|
|
281
|
+
const uw = width - 1;
|
|
282
|
+
const vd = depth - 1;
|
|
283
|
+
const a = w.vertex(x0, y0, z0, nx, ny, nz, i0 / uw, j0 / vd);
|
|
284
|
+
const b = w.vertex(x1, y1, z1, nx, ny, nz, i1 / uw, j1 / vd);
|
|
285
|
+
const c = w.vertex(x2, y2, z2, nx, ny, nz, i2 / uw, j2 / vd);
|
|
286
|
+
w.tri(a, b, c);
|
|
287
|
+
};
|
|
288
|
+
for (let j = 0; j < depth - 1; j++) {
|
|
289
|
+
for (let i = 0; i < width - 1; i++) {
|
|
290
|
+
tri(i, j, i, j + 1, i + 1, j + 1);
|
|
291
|
+
tri(i, j, i + 1, j + 1, i + 1, j);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return w.finish();
|
|
295
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Geometry } from './geometry.js';
|
|
2
|
+
/**
|
|
3
|
+
* The convex hull of a point set (xyz triples, or a geometry's positions) as a flat-shaded
|
|
4
|
+
* `VERTEX_LAYOUT_3D` geometry: three vertices per triangle, wound counter-clockwise seen from
|
|
5
|
+
* outside, each carrying its face normal, uv 0 and white. Quickhull: start from a tetrahedron of
|
|
6
|
+
* extreme points, then repeatedly lift the farthest outside point of a face, replacing the faces
|
|
7
|
+
* it sees with a fan from their horizon. Points within a small tolerance of a face (scaled to the
|
|
8
|
+
* cloud's extent) count as on it, so a cube's corners give 12 triangles however noisy its inside.
|
|
9
|
+
* Fewer than four points, or a flat or collinear cloud, has no volume: the result is empty.
|
|
10
|
+
*/
|
|
11
|
+
export declare function convexHull(src: Float32Array | Geometry): Geometry;
|
|
12
|
+
export interface CollisionProxyOptions {
|
|
13
|
+
/** Most triangles the proxy may have. */
|
|
14
|
+
maxTriangles: number;
|
|
15
|
+
/**
|
|
16
|
+
* `'hull'` (default): the convex hull, simplified further when it is over budget; solid and
|
|
17
|
+
* cheapest to query, but it fills concavities. `'simplified'`: the mesh itself simplified to
|
|
18
|
+
* the budget; keeps its shape, concavities included.
|
|
19
|
+
*/
|
|
20
|
+
kind?: 'hull' | 'simplified';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A low-triangle stand-in for `g` to hand `createStaticCollider` (as `{ geometry }`) in place of
|
|
24
|
+
* the render mesh: at most `maxTriangles` triangles, in `VERTEX_LAYOUT_3D` for `'hull'` and in
|
|
25
|
+
* `g`'s layout for `'simplified'`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function collisionProxy(g: Geometry, opts: CollisionProxyOptions): Geometry;
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convex hulls (`convexHull`, 3D quickhull) and cheap collision stand-ins for render meshes
|
|
3
|
+
* (`collisionProxy`). Build-time work: allocates freely, deterministic for a given input.
|
|
4
|
+
*/
|
|
5
|
+
import { VERTEX_LAYOUT_3D } from '../render/mesh.js';
|
|
6
|
+
import { computeBounds, createIndices } from './geometry.js';
|
|
7
|
+
import { simplifyGeometry } from './simplify.js';
|
|
8
|
+
const F3 = VERTEX_LAYOUT_3D.floats;
|
|
9
|
+
function emptyGeometry() {
|
|
10
|
+
return {
|
|
11
|
+
vertices: new Float32Array(0),
|
|
12
|
+
indices: new Uint16Array(0),
|
|
13
|
+
bounds: { center: [0, 0, 0], radius: 0 },
|
|
14
|
+
layout: VERTEX_LAYOUT_3D,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** xyz triples from a positions array or a geometry's position lane (float 0 of each vertex). */
|
|
18
|
+
function pointsOf(src) {
|
|
19
|
+
if (src instanceof Float32Array) {
|
|
20
|
+
if (src.length % 3 !== 0)
|
|
21
|
+
throw new Error(`geom: convexHull positions need xyz triples, got ${src.length} floats`);
|
|
22
|
+
return Float64Array.from(src);
|
|
23
|
+
}
|
|
24
|
+
const F = src.layout.floats;
|
|
25
|
+
const n = src.vertices.length / F;
|
|
26
|
+
const out = new Float64Array(n * 3);
|
|
27
|
+
for (let i = 0; i < n; i++) {
|
|
28
|
+
out[i * 3] = src.vertices[i * F];
|
|
29
|
+
out[i * 3 + 1] = src.vertices[i * F + 1];
|
|
30
|
+
out[i * 3 + 2] = src.vertices[i * F + 2];
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The convex hull of a point set (xyz triples, or a geometry's positions) as a flat-shaded
|
|
36
|
+
* `VERTEX_LAYOUT_3D` geometry: three vertices per triangle, wound counter-clockwise seen from
|
|
37
|
+
* outside, each carrying its face normal, uv 0 and white. Quickhull: start from a tetrahedron of
|
|
38
|
+
* extreme points, then repeatedly lift the farthest outside point of a face, replacing the faces
|
|
39
|
+
* it sees with a fan from their horizon. Points within a small tolerance of a face (scaled to the
|
|
40
|
+
* cloud's extent) count as on it, so a cube's corners give 12 triangles however noisy its inside.
|
|
41
|
+
* Fewer than four points, or a flat or collinear cloud, has no volume: the result is empty.
|
|
42
|
+
*/
|
|
43
|
+
export function convexHull(src) {
|
|
44
|
+
const p = pointsOf(src);
|
|
45
|
+
const n = p.length / 3;
|
|
46
|
+
if (n < 4)
|
|
47
|
+
return emptyGeometry();
|
|
48
|
+
const x = (i) => p[i * 3];
|
|
49
|
+
const y = (i) => p[i * 3 + 1];
|
|
50
|
+
const z = (i) => p[i * 3 + 2];
|
|
51
|
+
// Extreme points on each axis; the widest pair seeds the hull.
|
|
52
|
+
const lo = [0, 0, 0];
|
|
53
|
+
const hi = [0, 0, 0];
|
|
54
|
+
for (let i = 1; i < n; i++) {
|
|
55
|
+
for (let k = 0; k < 3; k++) {
|
|
56
|
+
if (p[i * 3 + k] < p[lo[k] * 3 + k])
|
|
57
|
+
lo[k] = i;
|
|
58
|
+
if (p[i * 3 + k] > p[hi[k] * 3 + k])
|
|
59
|
+
hi[k] = i;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
let axis = 0;
|
|
63
|
+
let span = -1;
|
|
64
|
+
for (let k = 0; k < 3; k++) {
|
|
65
|
+
const s = p[hi[k] * 3 + k] - p[lo[k] * 3 + k];
|
|
66
|
+
if (s > span) {
|
|
67
|
+
span = s;
|
|
68
|
+
axis = k;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const eps = 1e-9 + 1e-6 * span;
|
|
72
|
+
if (!(span > eps))
|
|
73
|
+
return emptyGeometry();
|
|
74
|
+
const i0 = lo[axis];
|
|
75
|
+
const i1 = hi[axis];
|
|
76
|
+
// Farthest from the line i0 i1.
|
|
77
|
+
const ex = x(i1) - x(i0);
|
|
78
|
+
const ey = y(i1) - y(i0);
|
|
79
|
+
const ez = z(i1) - z(i0);
|
|
80
|
+
let i2 = -1;
|
|
81
|
+
let best = eps * eps;
|
|
82
|
+
for (let i = 0; i < n; i++) {
|
|
83
|
+
const vx = x(i) - x(i0);
|
|
84
|
+
const vy = y(i) - y(i0);
|
|
85
|
+
const vz = z(i) - z(i0);
|
|
86
|
+
const cx = vy * ez - vz * ey;
|
|
87
|
+
const cy = vz * ex - vx * ez;
|
|
88
|
+
const cz = vx * ey - vy * ex;
|
|
89
|
+
const d = cx * cx + cy * cy + cz * cz;
|
|
90
|
+
if (d > best) {
|
|
91
|
+
best = d;
|
|
92
|
+
i2 = i;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (i2 < 0)
|
|
96
|
+
return emptyGeometry();
|
|
97
|
+
// Farthest from the plane i0 i1 i2.
|
|
98
|
+
const fx = x(i2) - x(i0);
|
|
99
|
+
const fy = y(i2) - y(i0);
|
|
100
|
+
const fz = z(i2) - z(i0);
|
|
101
|
+
let pnx = ey * fz - ez * fy;
|
|
102
|
+
let pny = ez * fx - ex * fz;
|
|
103
|
+
let pnz = ex * fy - ey * fx;
|
|
104
|
+
const pl = Math.hypot(pnx, pny, pnz);
|
|
105
|
+
pnx /= pl;
|
|
106
|
+
pny /= pl;
|
|
107
|
+
pnz /= pl;
|
|
108
|
+
let i3 = -1;
|
|
109
|
+
let bestD = eps;
|
|
110
|
+
for (let i = 0; i < n; i++) {
|
|
111
|
+
const d = Math.abs((x(i) - x(i0)) * pnx + (y(i) - y(i0)) * pny + (z(i) - z(i0)) * pnz);
|
|
112
|
+
if (d > bestD) {
|
|
113
|
+
bestD = d;
|
|
114
|
+
i3 = i;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (i3 < 0)
|
|
118
|
+
return emptyGeometry();
|
|
119
|
+
const faces = [];
|
|
120
|
+
const makeFace = (a, b, c) => {
|
|
121
|
+
const ux = x(b) - x(a);
|
|
122
|
+
const uy = y(b) - y(a);
|
|
123
|
+
const uz = z(b) - z(a);
|
|
124
|
+
const vx = x(c) - x(a);
|
|
125
|
+
const vy = y(c) - y(a);
|
|
126
|
+
const vz = z(c) - z(a);
|
|
127
|
+
let nx = uy * vz - uz * vy;
|
|
128
|
+
let ny = uz * vx - ux * vz;
|
|
129
|
+
let nz = ux * vy - uy * vx;
|
|
130
|
+
const l = Math.hypot(nx, ny, nz) || 1;
|
|
131
|
+
nx /= l;
|
|
132
|
+
ny /= l;
|
|
133
|
+
nz /= l;
|
|
134
|
+
const f = {
|
|
135
|
+
a,
|
|
136
|
+
b,
|
|
137
|
+
c,
|
|
138
|
+
nx,
|
|
139
|
+
ny,
|
|
140
|
+
nz,
|
|
141
|
+
d: nx * x(a) + ny * y(a) + nz * z(a),
|
|
142
|
+
outside: [],
|
|
143
|
+
alive: true,
|
|
144
|
+
};
|
|
145
|
+
faces.push(f);
|
|
146
|
+
edgeOwner.set(a * n + b, f);
|
|
147
|
+
edgeOwner.set(b * n + c, f);
|
|
148
|
+
edgeOwner.set(c * n + a, f);
|
|
149
|
+
return f;
|
|
150
|
+
};
|
|
151
|
+
/** Directed edge `a → b` (key `a · n + b`) to the live face it bounds counter-clockwise. */
|
|
152
|
+
const edgeOwner = new Map();
|
|
153
|
+
const dist = (f, i) => f.nx * x(i) + f.ny * y(i) + f.nz * z(i) - f.d;
|
|
154
|
+
// The tetrahedron, wound outward (away from i3 for the base).
|
|
155
|
+
const above = (x(i3) - x(i0)) * pnx + (y(i3) - y(i0)) * pny + (z(i3) - z(i0)) * pnz > 0;
|
|
156
|
+
const seed = above
|
|
157
|
+
? [makeFace(i0, i2, i1), makeFace(i0, i1, i3), makeFace(i1, i2, i3), makeFace(i2, i0, i3)]
|
|
158
|
+
: [makeFace(i0, i1, i2), makeFace(i0, i3, i1), makeFace(i1, i3, i2), makeFace(i2, i3, i0)];
|
|
159
|
+
const assign = (candidates, i) => {
|
|
160
|
+
let bestFace;
|
|
161
|
+
let bd = eps;
|
|
162
|
+
for (const f of candidates) {
|
|
163
|
+
const d = dist(f, i);
|
|
164
|
+
if (d > bd) {
|
|
165
|
+
bd = d;
|
|
166
|
+
bestFace = f;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
bestFace?.outside.push(i);
|
|
170
|
+
};
|
|
171
|
+
for (let i = 0; i < n; i++) {
|
|
172
|
+
if (i === i0 || i === i1 || i === i2 || i === i3)
|
|
173
|
+
continue;
|
|
174
|
+
assign(seed, i);
|
|
175
|
+
}
|
|
176
|
+
// Faces still to process, in creation order: deterministic.
|
|
177
|
+
for (let fi = 0; fi < faces.length; fi++) {
|
|
178
|
+
const face = faces[fi];
|
|
179
|
+
if (!face.alive || face.outside.length === 0)
|
|
180
|
+
continue;
|
|
181
|
+
// The farthest outside point (lowest index on ties).
|
|
182
|
+
let eye = -1;
|
|
183
|
+
let ed = -1;
|
|
184
|
+
for (const i of face.outside) {
|
|
185
|
+
const d = dist(face, i);
|
|
186
|
+
if (d > ed) {
|
|
187
|
+
ed = d;
|
|
188
|
+
eye = i;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Every face the eye sees: a flood across shared edges from this face (the visible region of
|
|
192
|
+
// a convex hull is connected). Its horizon is the edges whose far face does not see the eye.
|
|
193
|
+
face.alive = false;
|
|
194
|
+
const visible = [face];
|
|
195
|
+
const horizon = [];
|
|
196
|
+
for (let k = 0; k < visible.length; k++) {
|
|
197
|
+
const f = visible[k];
|
|
198
|
+
for (const [a, b] of [
|
|
199
|
+
[f.a, f.b],
|
|
200
|
+
[f.b, f.c],
|
|
201
|
+
[f.c, f.a],
|
|
202
|
+
]) {
|
|
203
|
+
const g = edgeOwner.get(b * n + a);
|
|
204
|
+
if (!g?.alive)
|
|
205
|
+
continue;
|
|
206
|
+
if (dist(g, eye) > eps) {
|
|
207
|
+
g.alive = false;
|
|
208
|
+
visible.push(g);
|
|
209
|
+
}
|
|
210
|
+
else
|
|
211
|
+
horizon.push(a, b);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
for (const f of visible) {
|
|
215
|
+
edgeOwner.delete(f.a * n + f.b);
|
|
216
|
+
edgeOwner.delete(f.b * n + f.c);
|
|
217
|
+
edgeOwner.delete(f.c * n + f.a);
|
|
218
|
+
}
|
|
219
|
+
const created = [];
|
|
220
|
+
for (let k = 0; k < horizon.length; k += 2)
|
|
221
|
+
created.push(makeFace(horizon[k], horizon[k + 1], eye));
|
|
222
|
+
for (const f of visible) {
|
|
223
|
+
for (const i of f.outside)
|
|
224
|
+
if (i !== eye)
|
|
225
|
+
assign(created, i);
|
|
226
|
+
f.outside = [];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const live = faces.filter((f) => f.alive);
|
|
230
|
+
const vertices = new Float32Array(live.length * 3 * F3);
|
|
231
|
+
let o = 0;
|
|
232
|
+
for (const f of live) {
|
|
233
|
+
for (const i of [f.a, f.b, f.c]) {
|
|
234
|
+
vertices[o] = x(i);
|
|
235
|
+
vertices[o + 1] = y(i);
|
|
236
|
+
vertices[o + 2] = z(i);
|
|
237
|
+
vertices[o + 3] = f.nx;
|
|
238
|
+
vertices[o + 4] = f.ny;
|
|
239
|
+
vertices[o + 5] = f.nz;
|
|
240
|
+
vertices[o + 8] = 1;
|
|
241
|
+
vertices[o + 9] = 1;
|
|
242
|
+
vertices[o + 10] = 1;
|
|
243
|
+
vertices[o + 11] = 1;
|
|
244
|
+
o += F3;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const count = live.length * 3;
|
|
248
|
+
const indices = createIndices(count, count);
|
|
249
|
+
for (let i = 0; i < count; i++)
|
|
250
|
+
indices[i] = i;
|
|
251
|
+
return { vertices, indices, bounds: computeBounds(vertices, F3), layout: VERTEX_LAYOUT_3D };
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* A low-triangle stand-in for `g` to hand `createStaticCollider` (as `{ geometry }`) in place of
|
|
255
|
+
* the render mesh: at most `maxTriangles` triangles, in `VERTEX_LAYOUT_3D` for `'hull'` and in
|
|
256
|
+
* `g`'s layout for `'simplified'`.
|
|
257
|
+
*/
|
|
258
|
+
export function collisionProxy(g, opts) {
|
|
259
|
+
const max = Math.max(0, Math.floor(opts.maxTriangles));
|
|
260
|
+
const toBudget = (s) => {
|
|
261
|
+
let out = s;
|
|
262
|
+
// Simplification can stall short of the target where a collapse would fold the surface; a
|
|
263
|
+
// tighter target then gets there.
|
|
264
|
+
for (let k = 0; out.indices.length / 3 > max && k < 8; k++) {
|
|
265
|
+
const over = out.indices.length / 3 - max;
|
|
266
|
+
out = simplifyGeometry(out, { targetTriangles: Math.max(0, max - over) }).geometry;
|
|
267
|
+
}
|
|
268
|
+
return out;
|
|
269
|
+
};
|
|
270
|
+
if ((opts.kind ?? 'hull') === 'simplified') {
|
|
271
|
+
if (g.indices.length / 3 <= max)
|
|
272
|
+
return g;
|
|
273
|
+
return toBudget(simplifyGeometry(g, { targetTriangles: max }).geometry);
|
|
274
|
+
}
|
|
275
|
+
const hull = convexHull(g);
|
|
276
|
+
if (hull.indices.length / 3 <= max)
|
|
277
|
+
return hull;
|
|
278
|
+
return toBudget(simplifyGeometry(hull, { targetTriangles: max }).geometry);
|
|
279
|
+
}
|