@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,434 @@
|
|
|
1
|
+
/// <reference path="./xr-types.d.ts" preserve="true" />
|
|
2
|
+
/**
|
|
3
|
+
* A fake WebXR stack for unit tests (ws/xr): `XRSystem`, `XRSession`, `XRFrame`, input sources
|
|
4
|
+
* and the WebXR/WebGPU binding, stepped by hand. `installFakeXr(device)` puts a `navigator.xr`
|
|
5
|
+
* and a `globalThis.XRGPUBinding` in place over a fake GPU device (`createFakeDevice`), so
|
|
6
|
+
* `createGame`'s `ctx.xr.enter()`, `XrSurface` and `XrPointerSource` run end to end in Node;
|
|
7
|
+
* the returned `uninstall` restores the globals. Not exported from any module index.
|
|
8
|
+
*
|
|
9
|
+
* Geometry: two eyes at ±`ipd / 2` on x, looking down -z with a 90° projection, side by side in
|
|
10
|
+
* one `textureType: 'texture'` layer texture (`2 * eyeWidth × eyeHeight`); a `texture-array`
|
|
11
|
+
* layer gives each eye its own array layer. Input sources carry a position and point down -z.
|
|
12
|
+
*/
|
|
13
|
+
function translation(x, y, z) {
|
|
14
|
+
const m = new Float32Array(16);
|
|
15
|
+
m[0] = m[5] = m[10] = m[15] = 1;
|
|
16
|
+
m[12] = x;
|
|
17
|
+
m[13] = y;
|
|
18
|
+
m[14] = z;
|
|
19
|
+
return m;
|
|
20
|
+
}
|
|
21
|
+
/** A rigid transform that is a pure translation, with its inverse. */
|
|
22
|
+
export function fakeTransform(x, y, z) {
|
|
23
|
+
const make = (sx, sy, sz, inv) => ({
|
|
24
|
+
position: { x: sx, y: sy, z: sz, w: 1 },
|
|
25
|
+
orientation: { x: 0, y: 0, z: 0, w: 1 },
|
|
26
|
+
matrix: translation(sx, sy, sz),
|
|
27
|
+
get inverse() {
|
|
28
|
+
return inv();
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
const a = make(x, y, z, () => b);
|
|
32
|
+
const b = make(-x, -y, -z, () => a);
|
|
33
|
+
return a;
|
|
34
|
+
}
|
|
35
|
+
function perspective90(aspect) {
|
|
36
|
+
const near = 0.1;
|
|
37
|
+
const far = 100;
|
|
38
|
+
const m = new Float32Array(16);
|
|
39
|
+
m[0] = 1 / aspect;
|
|
40
|
+
m[5] = 1;
|
|
41
|
+
m[10] = far / (near - far);
|
|
42
|
+
m[11] = -1;
|
|
43
|
+
m[14] = (near * far) / (near - far);
|
|
44
|
+
return m;
|
|
45
|
+
}
|
|
46
|
+
export class FakeXrSpace {
|
|
47
|
+
name;
|
|
48
|
+
constructor(name) {
|
|
49
|
+
this.name = name;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export class FakeXrReferenceSpace extends FakeXrSpace {
|
|
53
|
+
getOffsetReferenceSpace() {
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export class FakeXrJointSpace extends FakeXrSpace {
|
|
58
|
+
jointName;
|
|
59
|
+
constructor(jointName) {
|
|
60
|
+
super(jointName);
|
|
61
|
+
this.jointName = jointName;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** A hand whose joint positions a test sets (`joints.set('thumb-tip', [x, y, z])`). */
|
|
65
|
+
export class FakeXrHand {
|
|
66
|
+
joints = new Map();
|
|
67
|
+
spaces = new Map();
|
|
68
|
+
get size() {
|
|
69
|
+
return this.spaces.size;
|
|
70
|
+
}
|
|
71
|
+
get(joint) {
|
|
72
|
+
let s = this.spaces.get(joint);
|
|
73
|
+
if (!s) {
|
|
74
|
+
s = new FakeXrJointSpace(joint);
|
|
75
|
+
this.spaces.set(joint, s);
|
|
76
|
+
}
|
|
77
|
+
return s;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export class FakeXrInputSource {
|
|
81
|
+
handedness;
|
|
82
|
+
targetRayMode = 'tracked-pointer';
|
|
83
|
+
targetRaySpace;
|
|
84
|
+
gripSpace = null;
|
|
85
|
+
profiles = ['generic-trigger-squeeze'];
|
|
86
|
+
/** Where the target ray starts, in the reference space; it points down -z. */
|
|
87
|
+
position = [0, 1, 0];
|
|
88
|
+
/** `buttons[0]` trigger, `buttons[1]` squeeze. */
|
|
89
|
+
buttons = [
|
|
90
|
+
{ pressed: false, touched: false, value: 0 },
|
|
91
|
+
{ pressed: false, touched: false, value: 0 },
|
|
92
|
+
];
|
|
93
|
+
/** Null for a source without a gamepad (events only). */
|
|
94
|
+
gamepad;
|
|
95
|
+
hand = null;
|
|
96
|
+
constructor(handedness, opts = {}) {
|
|
97
|
+
this.handedness = handedness;
|
|
98
|
+
this.targetRaySpace = new FakeXrSpace(`${handedness}-ray`);
|
|
99
|
+
this.gamepad =
|
|
100
|
+
opts.gamepad === false ? null : { buttons: this.buttons, axes: [] };
|
|
101
|
+
if (opts.hand)
|
|
102
|
+
this.hand = new FakeXrHand();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export class FakeXrFrame {
|
|
106
|
+
session;
|
|
107
|
+
predictedDisplayTime;
|
|
108
|
+
constructor(session, predictedDisplayTime) {
|
|
109
|
+
this.session = session;
|
|
110
|
+
this.predictedDisplayTime = predictedDisplayTime;
|
|
111
|
+
}
|
|
112
|
+
getViewerPose(referenceSpace) {
|
|
113
|
+
if (!this.session.tracking)
|
|
114
|
+
return undefined;
|
|
115
|
+
if (referenceSpace !== this.session.referenceSpace)
|
|
116
|
+
return undefined;
|
|
117
|
+
const s = this.session;
|
|
118
|
+
const [hx, hy, hz] = s.headPosition;
|
|
119
|
+
const half = s.opts.ipd / 2;
|
|
120
|
+
const proj = perspective90(s.opts.eyeWidth / s.opts.eyeHeight);
|
|
121
|
+
const view = (eye, dx) => ({
|
|
122
|
+
eye,
|
|
123
|
+
projectionMatrix: proj,
|
|
124
|
+
transform: fakeTransform(hx + dx, hy, hz),
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
transform: fakeTransform(hx, hy, hz),
|
|
128
|
+
emulatedPosition: false,
|
|
129
|
+
views: [view('left', -half), view('right', half)],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
getPose(space, baseSpace) {
|
|
133
|
+
if (baseSpace !== this.session.referenceSpace)
|
|
134
|
+
return undefined;
|
|
135
|
+
for (const src of this.session.inputSources) {
|
|
136
|
+
if (src.targetRaySpace === space) {
|
|
137
|
+
const [x, y, z] = src.position;
|
|
138
|
+
return { transform: fakeTransform(x, y, z), emulatedPosition: false };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
getJointPose(joint, baseSpace) {
|
|
144
|
+
if (baseSpace !== this.session.referenceSpace)
|
|
145
|
+
return undefined;
|
|
146
|
+
for (const src of this.session.inputSources) {
|
|
147
|
+
const p = src.hand?.joints.get(joint.jointName);
|
|
148
|
+
if (src.hand?.get(joint.jointName) === joint && p) {
|
|
149
|
+
return {
|
|
150
|
+
transform: fakeTransform(p[0], p[1], p[2]),
|
|
151
|
+
emulatedPosition: false,
|
|
152
|
+
radius: 0.01,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
class FakeInputSourceEvent extends Event {
|
|
160
|
+
frame;
|
|
161
|
+
inputSource;
|
|
162
|
+
constructor(type, frame, inputSource) {
|
|
163
|
+
super(type);
|
|
164
|
+
this.frame = frame;
|
|
165
|
+
this.inputSource = inputSource;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
class FakeSourcesChangeEvent extends Event {
|
|
169
|
+
session;
|
|
170
|
+
added;
|
|
171
|
+
removed;
|
|
172
|
+
constructor(session, added, removed) {
|
|
173
|
+
super('inputsourceschange');
|
|
174
|
+
this.session = session;
|
|
175
|
+
this.added = added;
|
|
176
|
+
this.removed = removed;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
export class FakeXrSession extends EventTarget {
|
|
180
|
+
mode;
|
|
181
|
+
init;
|
|
182
|
+
opts;
|
|
183
|
+
inputSources = [];
|
|
184
|
+
referenceSpace = new FakeXrReferenceSpace('reference');
|
|
185
|
+
renderState = { depthNear: 0.1, depthFar: 1000, layers: [] };
|
|
186
|
+
visibilityState = 'visible';
|
|
187
|
+
headPosition = [0, 1.6, 0];
|
|
188
|
+
/** False makes `getViewerPose` return nothing (tracking lost). */
|
|
189
|
+
tracking = true;
|
|
190
|
+
ended = false;
|
|
191
|
+
/** Every `requestReferenceSpace` type asked for. */
|
|
192
|
+
referenceSpaceRequests = [];
|
|
193
|
+
renderStateUpdates = [];
|
|
194
|
+
pending = new Map();
|
|
195
|
+
nextHandle = 1;
|
|
196
|
+
frameTime = 0;
|
|
197
|
+
constructor(mode, init, opts) {
|
|
198
|
+
super();
|
|
199
|
+
this.mode = mode;
|
|
200
|
+
this.init = init;
|
|
201
|
+
this.opts = opts;
|
|
202
|
+
}
|
|
203
|
+
/** The clock of the frame running now (the last `step`), ms. */
|
|
204
|
+
get now() {
|
|
205
|
+
return this.frameTime;
|
|
206
|
+
}
|
|
207
|
+
/** Callbacks waiting for the next frame. */
|
|
208
|
+
get pendingFrames() {
|
|
209
|
+
return this.pending.size;
|
|
210
|
+
}
|
|
211
|
+
requestReferenceSpace(type) {
|
|
212
|
+
this.referenceSpaceRequests.push(type);
|
|
213
|
+
return Promise.resolve(this.referenceSpace);
|
|
214
|
+
}
|
|
215
|
+
updateRenderState(state = {}) {
|
|
216
|
+
this.renderStateUpdates.push(state);
|
|
217
|
+
this.renderState = { ...this.renderState, ...state };
|
|
218
|
+
}
|
|
219
|
+
requestAnimationFrame(callback) {
|
|
220
|
+
const h = this.nextHandle++;
|
|
221
|
+
this.pending.set(h, callback);
|
|
222
|
+
return h;
|
|
223
|
+
}
|
|
224
|
+
cancelAnimationFrame(handle) {
|
|
225
|
+
this.pending.delete(handle);
|
|
226
|
+
}
|
|
227
|
+
/** Run the pending frame callbacks with a new `XRFrame`, `dtMs` after the last one. */
|
|
228
|
+
step(dtMs = 1000 / 72) {
|
|
229
|
+
this.frameTime += dtMs;
|
|
230
|
+
const frame = new FakeXrFrame(this, this.frameTime);
|
|
231
|
+
const cbs = [...this.pending.values()];
|
|
232
|
+
this.pending.clear();
|
|
233
|
+
for (const cb of cbs)
|
|
234
|
+
cb(this.frameTime, frame);
|
|
235
|
+
return frame;
|
|
236
|
+
}
|
|
237
|
+
/** Add an input source (fires `inputsourceschange`). */
|
|
238
|
+
addInputSource(src) {
|
|
239
|
+
this.inputSources.push(src);
|
|
240
|
+
this.dispatchEvent(new FakeSourcesChangeEvent(this, [src], []));
|
|
241
|
+
}
|
|
242
|
+
removeInputSource(src) {
|
|
243
|
+
const i = this.inputSources.indexOf(src);
|
|
244
|
+
if (i < 0)
|
|
245
|
+
return;
|
|
246
|
+
this.inputSources.splice(i, 1);
|
|
247
|
+
this.dispatchEvent(new FakeSourcesChangeEvent(this, [], [src]));
|
|
248
|
+
}
|
|
249
|
+
/** Fire `selectstart` / `selectend` (or `squeeze…`) for a source, as a headset would. */
|
|
250
|
+
fire(kind, src, down) {
|
|
251
|
+
const frame = new FakeXrFrame(this, this.frameTime);
|
|
252
|
+
this.dispatchEvent(new FakeInputSourceEvent(`${kind}${down ? 'start' : 'end'}`, frame, src));
|
|
253
|
+
if (!down)
|
|
254
|
+
this.dispatchEvent(new FakeInputSourceEvent(kind, frame, src));
|
|
255
|
+
}
|
|
256
|
+
end() {
|
|
257
|
+
if (!this.ended) {
|
|
258
|
+
this.ended = true;
|
|
259
|
+
this.pending.clear();
|
|
260
|
+
const ev = new Event('end');
|
|
261
|
+
ev.session = this;
|
|
262
|
+
this.dispatchEvent(ev);
|
|
263
|
+
}
|
|
264
|
+
return Promise.resolve();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
export class FakeXrSystem {
|
|
268
|
+
opts;
|
|
269
|
+
sessions = [];
|
|
270
|
+
constructor(opts) {
|
|
271
|
+
this.opts = opts;
|
|
272
|
+
}
|
|
273
|
+
isSessionSupported(mode) {
|
|
274
|
+
return Promise.resolve(this.opts.supported && mode === 'immersive-vr');
|
|
275
|
+
}
|
|
276
|
+
requestSession(mode, init) {
|
|
277
|
+
if (!this.opts.supported)
|
|
278
|
+
return Promise.reject(new Error('NotSupportedError'));
|
|
279
|
+
const s = new FakeXrSession(mode, init, this.opts);
|
|
280
|
+
this.sessions.push(s);
|
|
281
|
+
return Promise.resolve(s);
|
|
282
|
+
}
|
|
283
|
+
/** The session requested last. */
|
|
284
|
+
get session() {
|
|
285
|
+
const s = this.sessions.at(-1);
|
|
286
|
+
if (!s)
|
|
287
|
+
throw new Error('no session requested');
|
|
288
|
+
return s;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
export class FakeXrProjectionLayer {
|
|
292
|
+
binding;
|
|
293
|
+
init;
|
|
294
|
+
layout = 'stereo';
|
|
295
|
+
mipLevels = 1;
|
|
296
|
+
needsRedraw = false;
|
|
297
|
+
ignoreDepthValues = false;
|
|
298
|
+
fixedFoveation = null;
|
|
299
|
+
destroyed = false;
|
|
300
|
+
/** Textures handed out so far (one per frame when rotating). */
|
|
301
|
+
colorTextures = [];
|
|
302
|
+
depthTextures = [];
|
|
303
|
+
color = null;
|
|
304
|
+
depth = null;
|
|
305
|
+
lastFrameTime = -1;
|
|
306
|
+
constructor(binding, init) {
|
|
307
|
+
this.binding = binding;
|
|
308
|
+
this.init = init;
|
|
309
|
+
}
|
|
310
|
+
get textureType() {
|
|
311
|
+
return this.init.textureType ?? 'texture';
|
|
312
|
+
}
|
|
313
|
+
get textureWidth() {
|
|
314
|
+
const w = this.binding.session.opts.eyeWidth;
|
|
315
|
+
return this.textureType === 'texture' ? 2 * w : w;
|
|
316
|
+
}
|
|
317
|
+
get textureHeight() {
|
|
318
|
+
return this.binding.session.opts.eyeHeight;
|
|
319
|
+
}
|
|
320
|
+
get textureArrayLength() {
|
|
321
|
+
return this.textureType === 'texture' ? 1 : 2;
|
|
322
|
+
}
|
|
323
|
+
/** This frame's textures, made on first use and, when rotating, anew each frame. */
|
|
324
|
+
textures(frameTime) {
|
|
325
|
+
const rotate = this.binding.session.opts.rotateTextures && frameTime !== this.lastFrameTime;
|
|
326
|
+
this.lastFrameTime = frameTime;
|
|
327
|
+
if (!this.color || rotate) {
|
|
328
|
+
const size = [this.textureWidth, this.textureHeight, this.textureArrayLength];
|
|
329
|
+
const device = this.binding.device;
|
|
330
|
+
this.color = device.createTexture({
|
|
331
|
+
label: 'xr-layer-color',
|
|
332
|
+
size,
|
|
333
|
+
format: this.init.colorFormat ?? 'rgba8unorm',
|
|
334
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT,
|
|
335
|
+
});
|
|
336
|
+
this.colorTextures.push(this.color);
|
|
337
|
+
this.depth = this.init.depthStencilFormat
|
|
338
|
+
? device.createTexture({
|
|
339
|
+
label: 'xr-layer-depth',
|
|
340
|
+
size,
|
|
341
|
+
format: this.init.depthStencilFormat,
|
|
342
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT,
|
|
343
|
+
})
|
|
344
|
+
: null;
|
|
345
|
+
if (this.depth)
|
|
346
|
+
this.depthTextures.push(this.depth);
|
|
347
|
+
}
|
|
348
|
+
return { color: this.color, depth: this.depth };
|
|
349
|
+
}
|
|
350
|
+
destroy() {
|
|
351
|
+
this.destroyed = true;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
export class FakeXRGPUBinding {
|
|
355
|
+
session;
|
|
356
|
+
device;
|
|
357
|
+
nativeProjectionScaleFactor = 1;
|
|
358
|
+
layers = [];
|
|
359
|
+
constructor(session, device) {
|
|
360
|
+
this.session = session;
|
|
361
|
+
this.device = device;
|
|
362
|
+
}
|
|
363
|
+
createProjectionLayer(init = {}) {
|
|
364
|
+
const l = new FakeXrProjectionLayer(this, init);
|
|
365
|
+
this.layers.push(l);
|
|
366
|
+
return l;
|
|
367
|
+
}
|
|
368
|
+
getViewSubImage(layer, view) {
|
|
369
|
+
const l = layer;
|
|
370
|
+
const { color, depth } = l.textures(this.session.now);
|
|
371
|
+
const w = this.session.opts.eyeWidth;
|
|
372
|
+
const h = this.session.opts.eyeHeight;
|
|
373
|
+
const right = view.eye === 'right';
|
|
374
|
+
const array = l.textureType === 'texture-array';
|
|
375
|
+
return {
|
|
376
|
+
colorTexture: color,
|
|
377
|
+
depthStencilTexture: depth,
|
|
378
|
+
viewport: { x: right && !array ? w : 0, y: 0, width: w, height: h },
|
|
379
|
+
getViewDescriptor: () => array ? { dimension: '2d', baseArrayLayer: right ? 1 : 0, arrayLayerCount: 1 } : {},
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
getPreferredColorFormat() {
|
|
383
|
+
return 'rgba8unorm';
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Install `navigator.xr` and `XRGPUBinding` fakes. `supported: false` keeps `navigator.xr` but
|
|
388
|
+
* answers no to `immersive-vr`; to test a browser with no WebXR at all, install nothing.
|
|
389
|
+
*/
|
|
390
|
+
export function installFakeXr(opts = {}) {
|
|
391
|
+
const full = {
|
|
392
|
+
eyeWidth: opts.eyeWidth ?? 64,
|
|
393
|
+
eyeHeight: opts.eyeHeight ?? 32,
|
|
394
|
+
ipd: opts.ipd ?? 0.064,
|
|
395
|
+
supported: opts.supported ?? true,
|
|
396
|
+
rotateTextures: opts.rotateTextures ?? false,
|
|
397
|
+
};
|
|
398
|
+
const system = new FakeXrSystem(full);
|
|
399
|
+
const bindings = [];
|
|
400
|
+
const Binding = function (session, device) {
|
|
401
|
+
const b = new FakeXRGPUBinding(session, device);
|
|
402
|
+
bindings.push(b);
|
|
403
|
+
return b;
|
|
404
|
+
};
|
|
405
|
+
const g = globalThis;
|
|
406
|
+
const hadBinding = Object.getOwnPropertyDescriptor(g, 'XRGPUBinding');
|
|
407
|
+
Object.defineProperty(g, 'XRGPUBinding', { value: Binding, configurable: true, writable: true });
|
|
408
|
+
let nav = g.navigator;
|
|
409
|
+
let madeNavigator = false;
|
|
410
|
+
if (!nav) {
|
|
411
|
+
nav = {};
|
|
412
|
+
Object.defineProperty(g, 'navigator', { value: nav, configurable: true, writable: true });
|
|
413
|
+
madeNavigator = true;
|
|
414
|
+
}
|
|
415
|
+
const hadXr = Object.getOwnPropertyDescriptor(nav, 'xr');
|
|
416
|
+
Object.defineProperty(nav, 'xr', { value: system, configurable: true });
|
|
417
|
+
return {
|
|
418
|
+
system,
|
|
419
|
+
bindings,
|
|
420
|
+
step: (dtMs) => system.session.step(dtMs),
|
|
421
|
+
uninstall() {
|
|
422
|
+
if (hadBinding)
|
|
423
|
+
Object.defineProperty(g, 'XRGPUBinding', hadBinding);
|
|
424
|
+
else
|
|
425
|
+
delete g.XRGPUBinding;
|
|
426
|
+
if (madeNavigator)
|
|
427
|
+
delete g.navigator;
|
|
428
|
+
else if (hadXr)
|
|
429
|
+
Object.defineProperty(nav, 'xr', hadXr);
|
|
430
|
+
else
|
|
431
|
+
delete nav.xr;
|
|
432
|
+
},
|
|
433
|
+
};
|
|
434
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/// <reference path="./xr-types.d.ts" preserve="true" />
|
|
2
|
+
/**
|
|
3
|
+
* The XR surface (ws/xr; ARCHITECTURE "Surface"): a `SceneTarget` per eye per frame. Built on
|
|
4
|
+
* the WebXR/WebGPU binding, it makes one `XRProjectionLayer` for the session (colour in
|
|
5
|
+
* `SCENE_FORMAT`, since every material's pipeline writes that format, plus a `DEPTH_FORMAT`
|
|
6
|
+
* depth texture) and each frame turns the viewer pose into `XrEyeView`s: a `Camera` whose
|
|
7
|
+
* projection and view matrices are the `XRView`'s (`viewIndex` = eye index, depth on) and a
|
|
8
|
+
* `SceneTarget` adopting the eye's part of the layer (`SceneTarget.external`). Eyes that share
|
|
9
|
+
* one layer texture (the default `texture` layout, side by side) share one target and differ by
|
|
10
|
+
* `camera.screen`, so the renderer clears it once and scissors each eye to its viewport; a
|
|
11
|
+
* `texture-array` layer gives each eye its own target over its array layer.
|
|
12
|
+
*
|
|
13
|
+
* Two ways to draw the eyes. Direct (the default): each eye is a scene pass into its layer
|
|
14
|
+
* target; the colour goes to the layer as linear HDR, the emissive target is written and
|
|
15
|
+
* dropped and no post stack runs. Through the post stack (`scene: true`, ws/xr-post, what
|
|
16
|
+
* `createGame` uses): the surface keeps `scene`, one HDR `SceneTarget` the size of an eye
|
|
17
|
+
* (allocated on the first frame, resized when the layer's eye size changes), every eye camera
|
|
18
|
+
* covers it whole and the caller renders each eye into it and resolves it into the eye's layer
|
|
19
|
+
* target at `eye.viewport` (`renderer.render(frame, eye.camera, surface.scene)` then
|
|
20
|
+
* `renderer.resolve(surface.scene, eye.target.color.view, eye.viewport)`), so the headset sees
|
|
21
|
+
* the same bloom, tone map and grade as the screen; the layer then takes `colorFormat`, the
|
|
22
|
+
* format the post stack writes (`renderer.format`), and no depth by default.
|
|
23
|
+
*
|
|
24
|
+
* `head` is a camera at the viewer pose with the first eye's projection, for the scenes' one
|
|
25
|
+
* `render(frame, camera, alpha)` call per frame.
|
|
26
|
+
*/
|
|
27
|
+
import { Camera } from '../render/camera.js';
|
|
28
|
+
import { SceneTarget, type SceneTargetAux, type SceneTargetViewport } from '../render/scene-target.js';
|
|
29
|
+
export interface XrSurfaceOptions {
|
|
30
|
+
/** The space poses are expressed in (the game's `local-floor`, `local` or `viewer` space). */
|
|
31
|
+
referenceSpace: XRReferenceSpace;
|
|
32
|
+
/**
|
|
33
|
+
* Colour format of the layer. Default `SCENE_FORMAT`, what the engine's materials write;
|
|
34
|
+
* with `scene` pass the format the post stack writes (`renderer.format`).
|
|
35
|
+
*/
|
|
36
|
+
colorFormat?: GPUTextureFormat;
|
|
37
|
+
/**
|
|
38
|
+
* Depth format of the layer, or null for a layer without depth. Default `DEPTH_FORMAT`, or
|
|
39
|
+
* null with `scene` (depth then lives in the scene target; the layer never receives it).
|
|
40
|
+
*/
|
|
41
|
+
depthStencilFormat?: GPUTextureFormat | null;
|
|
42
|
+
/**
|
|
43
|
+
* Draw the eyes through the post stack (ws/xr-post): keep `scene`, an eye-sized HDR target,
|
|
44
|
+
* give every eye camera the whole of it (`screen` 0,0,1,1) and leave the layer target for
|
|
45
|
+
* `renderer.resolve`. Default false: eyes draw into the layer directly.
|
|
46
|
+
*/
|
|
47
|
+
scene?: boolean;
|
|
48
|
+
/** `texture` (default, eyes side by side in one texture) or `texture-array` (a layer per eye). */
|
|
49
|
+
textureType?: 'texture' | 'texture-array';
|
|
50
|
+
/** The session's near and far planes, metres. Defaults 0.1 and 1000. */
|
|
51
|
+
depthNear?: number;
|
|
52
|
+
depthFar?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Aux attachments the eyes render with (ws/render-11; `createGame({ aux })` passes its own):
|
|
55
|
+
* velocity, rough-metal, as `SceneTargetDesc.aux`. Direct, each eye target adopting the layer
|
|
56
|
+
* makes them (`SceneTarget.external({ aux })`) at the eye's size; with `scene`, the scene
|
|
57
|
+
* target every eye renders into has them and the layer targets, only resolved into, do not.
|
|
58
|
+
* Each eye's camera keeps its own previous view-projection, so an eye's velocity is its own
|
|
59
|
+
* motion. Default none.
|
|
60
|
+
*/
|
|
61
|
+
aux?: SceneTargetAux;
|
|
62
|
+
}
|
|
63
|
+
/** One eye of one frame: where it looks and what it draws into. */
|
|
64
|
+
export interface XrEyeView {
|
|
65
|
+
/** The eye's index in the viewer pose (0 left, 1 right on a headset); `camera.viewIndex`. */
|
|
66
|
+
readonly index: number;
|
|
67
|
+
readonly eye: XREye;
|
|
68
|
+
/**
|
|
69
|
+
* Projection and view from the `XRView`; `screen` is the viewport as a fraction of the target,
|
|
70
|
+
* or the whole unit square when the surface has a `scene` target.
|
|
71
|
+
*/
|
|
72
|
+
readonly camera: Camera;
|
|
73
|
+
/**
|
|
74
|
+
* The target adopting the layer's texture for this eye; shared when the eyes share a texture.
|
|
75
|
+
* With `scene`, what the eye is resolved into, not what it is rendered into.
|
|
76
|
+
*/
|
|
77
|
+
readonly target: SceneTarget;
|
|
78
|
+
/** The eye's part of `target`, in texture pixels (`renderer.resolve`'s viewport). */
|
|
79
|
+
readonly viewport: SceneTargetViewport;
|
|
80
|
+
}
|
|
81
|
+
export declare class XrSurface {
|
|
82
|
+
readonly session: XRSession;
|
|
83
|
+
readonly device: GPUDevice;
|
|
84
|
+
readonly binding: XRGPUBinding;
|
|
85
|
+
readonly layer: XRProjectionLayer;
|
|
86
|
+
readonly referenceSpace: XRReferenceSpace;
|
|
87
|
+
/**
|
|
88
|
+
* A camera at the viewer pose (between the eyes) with the first eye's projection, depth on,
|
|
89
|
+
* updated by `views`: what the scenes record through once per frame.
|
|
90
|
+
*/
|
|
91
|
+
readonly head: Camera;
|
|
92
|
+
/**
|
|
93
|
+
* With `scene: true`, the eye-sized HDR target every eye renders into before `resolve`;
|
|
94
|
+
* made by the first `views` with a pose and resized when the eye size changes. Null before
|
|
95
|
+
* then, and always null for a direct surface.
|
|
96
|
+
*/
|
|
97
|
+
scene: SceneTarget | null;
|
|
98
|
+
private readonly eyes;
|
|
99
|
+
private readonly out;
|
|
100
|
+
private readonly viaScene;
|
|
101
|
+
/** `opts.aux`: on the scene target with `scene`, else on each eye target. */
|
|
102
|
+
private readonly aux;
|
|
103
|
+
private destroyed;
|
|
104
|
+
/**
|
|
105
|
+
* Makes the session's projection layer and installs it (`session.updateRenderState`).
|
|
106
|
+
* Throws where the browser has no `XRGPUBinding`; check `XrSurface.supported()` first.
|
|
107
|
+
*/
|
|
108
|
+
constructor(session: XRSession, device: GPUDevice, opts: XrSurfaceOptions);
|
|
109
|
+
/** True where `XRGPUBinding` exists (the WebXR/WebGPU binding). */
|
|
110
|
+
static supported(): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* The eyes of this frame, in viewer-pose order, each with its camera aimed and its target
|
|
113
|
+
* adopting the layer's texture for the frame. Empty when the pose is unavailable (tracking
|
|
114
|
+
* lost). The array and the views are reused; read them within the frame.
|
|
115
|
+
*/
|
|
116
|
+
views(frame: XRFrame): readonly XrEyeView[];
|
|
117
|
+
private makeScene;
|
|
118
|
+
/** Frees the eye targets' own textures, the scene target and the layer. The session is left to its owner. */
|
|
119
|
+
destroy(): void;
|
|
120
|
+
}
|