@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,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inverse kinematics on a `Pose`: an analytic two-bone solver (feet on uneven ground, a hand on
|
|
3
|
+
* a target) and a one-joint look-at (a head turning to a point). Both run after sampling and
|
|
4
|
+
* before the final `poseToWorld`: they read the world matrices of the pose as sampled
|
|
5
|
+
* (`worldPose`, from a `poseToWorld` the caller already ran, so nothing here walks the skeleton
|
|
6
|
+
* again), and write new local rotations into `pose`. Pure arithmetic; after `createIkChain`
|
|
7
|
+
* nothing allocates per call.
|
|
8
|
+
*
|
|
9
|
+
* Conventions: positions are 3-component `ArrayLike<number>`s; `instanceWorld` is the 3×4
|
|
10
|
+
* row-major instance matrix (`render/transform.ts`) that places the skeleton in the world, or
|
|
11
|
+
* `null` when the target is already in skeleton space. Rotations are expressed as deltas in
|
|
12
|
+
* skeleton space and converted into each joint's parent frame through the parent's world matrix.
|
|
13
|
+
*/
|
|
14
|
+
import { type Pose, type Skeleton } from './pose.js';
|
|
15
|
+
/** The three joints of a two-bone chain: `mid` descends from `root`, `tip` from `mid`. */
|
|
16
|
+
export interface IkChainDesc {
|
|
17
|
+
root: number;
|
|
18
|
+
mid: number;
|
|
19
|
+
tip: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A two-bone chain with its scratch space, from `createIkChain`. Opaque beyond `root`, `mid`,
|
|
23
|
+
* `tip`; pass it to `twoBoneIk` every frame. A plain `IkChainDesc` works too: `twoBoneIk` builds
|
|
24
|
+
* and caches a chain per object, so keep the object rather than writing a new literal per call.
|
|
25
|
+
*/
|
|
26
|
+
export interface IkChain extends IkChainDesc {
|
|
27
|
+
/** @internal nodes from `root` to `tip`, parent before child. */
|
|
28
|
+
readonly path: Int16Array;
|
|
29
|
+
/** @internal index of `mid` in `path`. */
|
|
30
|
+
readonly midIndex: number;
|
|
31
|
+
/** @internal world matrices of the path nodes, 12 floats each. */
|
|
32
|
+
readonly world: Float32Array;
|
|
33
|
+
/** @internal the input local rotations of root and mid (for `weight`). */
|
|
34
|
+
readonly saved: Float32Array;
|
|
35
|
+
}
|
|
36
|
+
export interface TwoBoneIkOptions {
|
|
37
|
+
/** 0..1: how far the solved rotations replace the input ones (slerp). Default 1. */
|
|
38
|
+
weight?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Solve passes. One is exact for rigid bones; a second refines when a chain node carries a
|
|
41
|
+
* non-uniform scale. Default 1.
|
|
42
|
+
*/
|
|
43
|
+
maxIterations?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface LookAtOptions {
|
|
46
|
+
/** 0..1 blend against the input rotation. Default 1. */
|
|
47
|
+
weight?: number;
|
|
48
|
+
/** The joint's local axis that should point at the target. Default `[0, 0, 1]`. */
|
|
49
|
+
forward?: ArrayLike<number>;
|
|
50
|
+
/**
|
|
51
|
+
* World (skeleton-space) up hint: after aiming, the joint rolls about the new forward so the
|
|
52
|
+
* direction that was "up" for it stays up, instead of tilting as it turns. Default: none
|
|
53
|
+
* (the minimal rotation).
|
|
54
|
+
*/
|
|
55
|
+
up?: ArrayLike<number>;
|
|
56
|
+
/** Largest angle (radians) the joint turns away from its input forward. Default `Math.PI`. */
|
|
57
|
+
maxAngle?: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build a chain for `twoBoneIk` over `skeleton`: validates that `mid` descends from `root` and
|
|
61
|
+
* `tip` from `mid` (intermediate nodes, such as twist bones, are allowed) and allocates the
|
|
62
|
+
* scratch space the solver needs. Allocates; call once per chain.
|
|
63
|
+
*/
|
|
64
|
+
export declare function createIkChain(skeleton: Skeleton, chain: IkChainDesc): IkChain;
|
|
65
|
+
export declare const IDENTITY: Float32Array<ArrayBuffer>;
|
|
66
|
+
/** `out = m[mo..] · p` (point, with translation). */
|
|
67
|
+
export declare function transformPoint(out: Float32Array, m: ArrayLike<number>, mo: number, p: ArrayLike<number>): void;
|
|
68
|
+
/** `out = upper3x3(m[mo..]) · d` (direction, no translation); `out` may alias `d`. */
|
|
69
|
+
export declare function transformDir(out: Float32Array, m: ArrayLike<number>, mo: number, d: ArrayLike<number>): void;
|
|
70
|
+
/** A world-space point into skeleton space through the inverse of `instanceWorld`. */
|
|
71
|
+
export declare function toSkeleton(out: Float32Array, p: ArrayLike<number>, instanceWorld: Float32Array | null): void;
|
|
72
|
+
export declare function normalize(a: Float32Array): number;
|
|
73
|
+
/** Any unit vector perpendicular to the unit vector `u`, into `out`. */
|
|
74
|
+
export declare function anyPerpendicular(out: Float32Array, u: Float32Array): void;
|
|
75
|
+
/** The shortest rotation taking unit `a` onto unit `b`, as (unit axis, angle) in `out`. */
|
|
76
|
+
export declare function rotationBetween(out: Float32Array, a: Float32Array, b: Float32Array): void;
|
|
77
|
+
/** Rotate `v` in place by the unit quaternion at `q[qo..]`. */
|
|
78
|
+
export declare function rotateByQuat(v: Float32Array, q: ArrayLike<number>, qo: number): void;
|
|
79
|
+
/** Rotate `p` in place by the (unit axis, angle) delta `d` (Rodrigues). */
|
|
80
|
+
export declare function rotateBy(p: Float32Array, d: Float32Array, angle?: number): void;
|
|
81
|
+
/**
|
|
82
|
+
* Pre-multiply the local rotation of `node` by the skeleton-space delta `d` (unit axis, angle):
|
|
83
|
+
* the axis goes through the inverse of the parent's world 3×3 (`parent`, or the identity for a
|
|
84
|
+
* skeleton root), after an optional extra rotation `pre` of the axis (used when the parent itself
|
|
85
|
+
* has just been rotated by `pre` and `parent` still holds its old matrix).
|
|
86
|
+
*/
|
|
87
|
+
export declare function applyDelta(pose: Pose, node: number, d: Float32Array, parent: ArrayLike<number>, po: number, pre: Float32Array | null): void;
|
|
88
|
+
/**
|
|
89
|
+
* Analytic two-bone IK (law of cosines) with a pole vector. Rotates `chain.root` and `chain.mid`
|
|
90
|
+
* in `pose` so that `chain.tip` reaches `targetWorld`; an unreachable target straightens the
|
|
91
|
+
* chain towards it (no stretching). `poleWorld` picks the bend side (the mid joint moves towards
|
|
92
|
+
* it); `null` keeps the chain's current bend plane. `worldPose` is `poseToWorld` of `pose` as it
|
|
93
|
+
* is on entry (the solver reads it, never rewrites it). `instanceWorld` (3×4 row-major) maps
|
|
94
|
+
* skeleton space to the space the target and pole are given in. `weight` slerps the result
|
|
95
|
+
* against the input rotations. No allocation when `chain` is an `IkChain` (or a reused object).
|
|
96
|
+
*/
|
|
97
|
+
export declare function twoBoneIk(pose: Pose, skeleton: Skeleton, worldPose: Float32Array, chain: IkChainDesc, targetWorld: ArrayLike<number>, poleWorld: ArrayLike<number> | null, instanceWorld: Float32Array | null, opts?: TwoBoneIkOptions): void;
|
|
98
|
+
/**
|
|
99
|
+
* Rotate `joint` in `pose` so that its local `forward` axis points at `targetWorld`, turning at
|
|
100
|
+
* most `maxAngle` radians away from its input direction and blended by `weight`. With an `up`
|
|
101
|
+
* hint the joint also rolls so what was up for it stays up. Reads the joint's world matrix from
|
|
102
|
+
* `worldPose` (`poseToWorld` of the input pose) and its parent's; never rewrites it. No
|
|
103
|
+
* allocation.
|
|
104
|
+
*/
|
|
105
|
+
export declare function lookAt(pose: Pose, skeleton: Skeleton, worldPose: Float32Array, joint: number, targetWorld: ArrayLike<number>, instanceWorld: Float32Array | null, opts?: LookAtOptions): void;
|
package/dist/anim/ik.js
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inverse kinematics on a `Pose`: an analytic two-bone solver (feet on uneven ground, a hand on
|
|
3
|
+
* a target) and a one-joint look-at (a head turning to a point). Both run after sampling and
|
|
4
|
+
* before the final `poseToWorld`: they read the world matrices of the pose as sampled
|
|
5
|
+
* (`worldPose`, from a `poseToWorld` the caller already ran, so nothing here walks the skeleton
|
|
6
|
+
* again), and write new local rotations into `pose`. Pure arithmetic; after `createIkChain`
|
|
7
|
+
* nothing allocates per call.
|
|
8
|
+
*
|
|
9
|
+
* Conventions: positions are 3-component `ArrayLike<number>`s; `instanceWorld` is the 3×4
|
|
10
|
+
* row-major instance matrix (`render/transform.ts`) that places the skeleton in the world, or
|
|
11
|
+
* `null` when the target is already in skeleton space. Rotations are expressed as deltas in
|
|
12
|
+
* skeleton space and converted into each joint's parent frame through the parent's world matrix.
|
|
13
|
+
*/
|
|
14
|
+
import { invertAffine, multiplyAffine, POSE_NODE_FLOATS, WORLD_NODE_FLOATS, writeNodeMatrix, } from './pose.js';
|
|
15
|
+
import { quatFromAxisAngle, quatMultiply, quatNormalize, quatSlerp } from './quat.js';
|
|
16
|
+
const EPS = 1e-6;
|
|
17
|
+
/**
|
|
18
|
+
* Build a chain for `twoBoneIk` over `skeleton`: validates that `mid` descends from `root` and
|
|
19
|
+
* `tip` from `mid` (intermediate nodes, such as twist bones, are allowed) and allocates the
|
|
20
|
+
* scratch space the solver needs. Allocates; call once per chain.
|
|
21
|
+
*/
|
|
22
|
+
export function createIkChain(skeleton, chain) {
|
|
23
|
+
const { root, mid, tip } = chain;
|
|
24
|
+
const parents = skeleton.parents;
|
|
25
|
+
const n = parents.length;
|
|
26
|
+
if (root < 0 || root >= n || mid < 0 || mid >= n || tip < 0 || tip >= n) {
|
|
27
|
+
throw new Error(`IkChain: nodes ${root}, ${mid}, ${tip} must be in [0, ${n})`);
|
|
28
|
+
}
|
|
29
|
+
const nodes = [];
|
|
30
|
+
let node = tip;
|
|
31
|
+
let midIndex = -1;
|
|
32
|
+
while (node >= 0 && node !== root) {
|
|
33
|
+
nodes.push(node);
|
|
34
|
+
node = parents[node];
|
|
35
|
+
}
|
|
36
|
+
if (node !== root)
|
|
37
|
+
throw new Error(`IkChain: tip ${tip} does not descend from root ${root}`);
|
|
38
|
+
nodes.push(root);
|
|
39
|
+
nodes.reverse();
|
|
40
|
+
midIndex = nodes.indexOf(mid);
|
|
41
|
+
if (midIndex <= 0 || midIndex >= nodes.length - 1) {
|
|
42
|
+
throw new Error(`IkChain: mid ${mid} must lie strictly between root ${root} and tip ${tip}`);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
root,
|
|
46
|
+
mid,
|
|
47
|
+
tip,
|
|
48
|
+
path: Int16Array.from(nodes),
|
|
49
|
+
midIndex,
|
|
50
|
+
world: new Float32Array(nodes.length * WORLD_NODE_FLOATS),
|
|
51
|
+
saved: new Float32Array(8),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const chains = new WeakMap();
|
|
55
|
+
function chainFor(skeleton, chain) {
|
|
56
|
+
if ('path' in chain)
|
|
57
|
+
return chain;
|
|
58
|
+
let c = chains.get(chain);
|
|
59
|
+
if (!c || c.root !== chain.root || c.mid !== chain.mid || c.tip !== chain.tip) {
|
|
60
|
+
c = createIkChain(skeleton, chain);
|
|
61
|
+
chains.set(chain, c);
|
|
62
|
+
}
|
|
63
|
+
return c;
|
|
64
|
+
}
|
|
65
|
+
// Scratch, module level: no allocation per call.
|
|
66
|
+
const inv = new Float32Array(WORLD_NODE_FLOATS);
|
|
67
|
+
const local = new Float32Array(WORLD_NODE_FLOATS);
|
|
68
|
+
const tgt = new Float32Array(3);
|
|
69
|
+
const pol = new Float32Array(3);
|
|
70
|
+
const dir = new Float32Array(3);
|
|
71
|
+
const perp = new Float32Array(3);
|
|
72
|
+
const v = new Float32Array(3);
|
|
73
|
+
const m2 = new Float32Array(3);
|
|
74
|
+
const t1 = new Float32Array(3);
|
|
75
|
+
/** A rotation delta in skeleton space: unit axis, angle. */
|
|
76
|
+
const d1 = new Float32Array(4);
|
|
77
|
+
const d2 = new Float32Array(4);
|
|
78
|
+
const dq = new Float32Array(4);
|
|
79
|
+
const axis = new Float32Array(3);
|
|
80
|
+
const fwd = new Float32Array(3);
|
|
81
|
+
const upw = new Float32Array(3);
|
|
82
|
+
const savedRot = new Float32Array(4);
|
|
83
|
+
export const IDENTITY = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0]);
|
|
84
|
+
/** `out = m[mo..] · p` (point, with translation). */
|
|
85
|
+
export function transformPoint(out, m, mo, p) {
|
|
86
|
+
const x = p[0];
|
|
87
|
+
const y = p[1];
|
|
88
|
+
const z = p[2];
|
|
89
|
+
out[0] = m[mo] * x + m[mo + 1] * y + m[mo + 2] * z + m[mo + 3];
|
|
90
|
+
out[1] = m[mo + 4] * x + m[mo + 5] * y + m[mo + 6] * z + m[mo + 7];
|
|
91
|
+
out[2] = m[mo + 8] * x + m[mo + 9] * y + m[mo + 10] * z + m[mo + 11];
|
|
92
|
+
}
|
|
93
|
+
/** `out = upper3x3(m[mo..]) · d` (direction, no translation); `out` may alias `d`. */
|
|
94
|
+
export function transformDir(out, m, mo, d) {
|
|
95
|
+
const x = d[0];
|
|
96
|
+
const y = d[1];
|
|
97
|
+
const z = d[2];
|
|
98
|
+
out[0] = m[mo] * x + m[mo + 1] * y + m[mo + 2] * z;
|
|
99
|
+
out[1] = m[mo + 4] * x + m[mo + 5] * y + m[mo + 6] * z;
|
|
100
|
+
out[2] = m[mo + 8] * x + m[mo + 9] * y + m[mo + 10] * z;
|
|
101
|
+
}
|
|
102
|
+
/** A world-space point into skeleton space through the inverse of `instanceWorld`. */
|
|
103
|
+
export function toSkeleton(out, p, instanceWorld) {
|
|
104
|
+
if (!instanceWorld) {
|
|
105
|
+
out[0] = p[0];
|
|
106
|
+
out[1] = p[1];
|
|
107
|
+
out[2] = p[2];
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
invertAffine(inv, 0, instanceWorld, 0);
|
|
111
|
+
transformPoint(out, inv, 0, p);
|
|
112
|
+
}
|
|
113
|
+
export function normalize(a) {
|
|
114
|
+
const len = Math.hypot(a[0], a[1], a[2]);
|
|
115
|
+
if (len > EPS) {
|
|
116
|
+
const s = 1 / len;
|
|
117
|
+
a[0] *= s;
|
|
118
|
+
a[1] *= s;
|
|
119
|
+
a[2] *= s;
|
|
120
|
+
}
|
|
121
|
+
return len;
|
|
122
|
+
}
|
|
123
|
+
/** Any unit vector perpendicular to the unit vector `u`, into `out`. */
|
|
124
|
+
export function anyPerpendicular(out, u) {
|
|
125
|
+
const ax = Math.abs(u[0]);
|
|
126
|
+
const ay = Math.abs(u[1]);
|
|
127
|
+
const az = Math.abs(u[2]);
|
|
128
|
+
// Cross with the axis u is least aligned with.
|
|
129
|
+
if (ax <= ay && ax <= az) {
|
|
130
|
+
out[0] = 0;
|
|
131
|
+
out[1] = -u[2];
|
|
132
|
+
out[2] = u[1];
|
|
133
|
+
}
|
|
134
|
+
else if (ay <= az) {
|
|
135
|
+
out[0] = u[2];
|
|
136
|
+
out[1] = 0;
|
|
137
|
+
out[2] = -u[0];
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
out[0] = -u[1];
|
|
141
|
+
out[1] = u[0];
|
|
142
|
+
out[2] = 0;
|
|
143
|
+
}
|
|
144
|
+
normalize(out);
|
|
145
|
+
}
|
|
146
|
+
/** The shortest rotation taking unit `a` onto unit `b`, as (unit axis, angle) in `out`. */
|
|
147
|
+
export function rotationBetween(out, a, b) {
|
|
148
|
+
const cx = a[1] * b[2] - a[2] * b[1];
|
|
149
|
+
const cy = a[2] * b[0] - a[0] * b[2];
|
|
150
|
+
const cz = a[0] * b[1] - a[1] * b[0];
|
|
151
|
+
const sin = Math.hypot(cx, cy, cz);
|
|
152
|
+
const cos = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
153
|
+
if (sin < EPS) {
|
|
154
|
+
if (cos >= 0) {
|
|
155
|
+
out[0] = 1;
|
|
156
|
+
out[1] = 0;
|
|
157
|
+
out[2] = 0;
|
|
158
|
+
out[3] = 0;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
anyPerpendicular(out, a);
|
|
162
|
+
out[3] = Math.PI;
|
|
163
|
+
}
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
out[0] = cx / sin;
|
|
167
|
+
out[1] = cy / sin;
|
|
168
|
+
out[2] = cz / sin;
|
|
169
|
+
out[3] = Math.atan2(sin, cos);
|
|
170
|
+
}
|
|
171
|
+
/** Rotate `v` in place by the unit quaternion at `q[qo..]`. */
|
|
172
|
+
export function rotateByQuat(v, q, qo) {
|
|
173
|
+
const qx = q[qo];
|
|
174
|
+
const qy = q[qo + 1];
|
|
175
|
+
const qz = q[qo + 2];
|
|
176
|
+
const qw = q[qo + 3];
|
|
177
|
+
const x = v[0];
|
|
178
|
+
const y = v[1];
|
|
179
|
+
const z = v[2];
|
|
180
|
+
// t = 2 q × v; v' = v + w t + q × t
|
|
181
|
+
const tx = 2 * (qy * z - qz * y);
|
|
182
|
+
const ty = 2 * (qz * x - qx * z);
|
|
183
|
+
const tz = 2 * (qx * y - qy * x);
|
|
184
|
+
v[0] = x + qw * tx + (qy * tz - qz * ty);
|
|
185
|
+
v[1] = y + qw * ty + (qz * tx - qx * tz);
|
|
186
|
+
v[2] = z + qw * tz + (qx * ty - qy * tx);
|
|
187
|
+
}
|
|
188
|
+
/** Rotate `p` in place by the (unit axis, angle) delta `d` (Rodrigues). */
|
|
189
|
+
export function rotateBy(p, d, angle = d[3]) {
|
|
190
|
+
const kx = d[0];
|
|
191
|
+
const ky = d[1];
|
|
192
|
+
const kz = d[2];
|
|
193
|
+
const x = p[0];
|
|
194
|
+
const y = p[1];
|
|
195
|
+
const z = p[2];
|
|
196
|
+
const c = Math.cos(angle);
|
|
197
|
+
const s = Math.sin(angle);
|
|
198
|
+
const dot = (kx * x + ky * y + kz * z) * (1 - c);
|
|
199
|
+
p[0] = x * c + (ky * z - kz * y) * s + kx * dot;
|
|
200
|
+
p[1] = y * c + (kz * x - kx * z) * s + ky * dot;
|
|
201
|
+
p[2] = z * c + (kx * y - ky * x) * s + kz * dot;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Pre-multiply the local rotation of `node` by the skeleton-space delta `d` (unit axis, angle):
|
|
205
|
+
* the axis goes through the inverse of the parent's world 3×3 (`parent`, or the identity for a
|
|
206
|
+
* skeleton root), after an optional extra rotation `pre` of the axis (used when the parent itself
|
|
207
|
+
* has just been rotated by `pre` and `parent` still holds its old matrix).
|
|
208
|
+
*/
|
|
209
|
+
export function applyDelta(pose, node, d, parent, po, pre) {
|
|
210
|
+
if (d[3] === 0)
|
|
211
|
+
return;
|
|
212
|
+
axis[0] = d[0];
|
|
213
|
+
axis[1] = d[1];
|
|
214
|
+
axis[2] = d[2];
|
|
215
|
+
if (pre)
|
|
216
|
+
rotateBy(axis, pre, -pre[3]);
|
|
217
|
+
invertAffine(inv, 0, parent, po);
|
|
218
|
+
transformDir(axis, inv, 0, axis);
|
|
219
|
+
if (normalize(axis) <= EPS)
|
|
220
|
+
return;
|
|
221
|
+
quatFromAxisAngle(dq, 0, axis[0], axis[1], axis[2], d[3]);
|
|
222
|
+
const o = node * POSE_NODE_FLOATS + 3;
|
|
223
|
+
quatMultiply(pose, o, dq, 0, pose, o);
|
|
224
|
+
quatNormalize(pose, o);
|
|
225
|
+
}
|
|
226
|
+
/** Recompute the chain's world matrices from `pose`, the root's parent read from `worldPose`. */
|
|
227
|
+
function refreshChain(c, skeleton, pose, worldPose) {
|
|
228
|
+
const path = c.path;
|
|
229
|
+
for (let i = 0; i < path.length; i++) {
|
|
230
|
+
const node = path[i];
|
|
231
|
+
const o = i * WORLD_NODE_FLOATS;
|
|
232
|
+
if (i === 0) {
|
|
233
|
+
const p = skeleton.parents[node];
|
|
234
|
+
if (p < 0)
|
|
235
|
+
writeNodeMatrix(c.world, o, pose, node * POSE_NODE_FLOATS);
|
|
236
|
+
else {
|
|
237
|
+
writeNodeMatrix(local, 0, pose, node * POSE_NODE_FLOATS);
|
|
238
|
+
multiplyAffine(c.world, o, worldPose, p * WORLD_NODE_FLOATS, local, 0);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
writeNodeMatrix(local, 0, pose, node * POSE_NODE_FLOATS);
|
|
243
|
+
multiplyAffine(c.world, o, c.world, o - WORLD_NODE_FLOATS, local, 0);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Analytic two-bone IK (law of cosines) with a pole vector. Rotates `chain.root` and `chain.mid`
|
|
249
|
+
* in `pose` so that `chain.tip` reaches `targetWorld`; an unreachable target straightens the
|
|
250
|
+
* chain towards it (no stretching). `poleWorld` picks the bend side (the mid joint moves towards
|
|
251
|
+
* it); `null` keeps the chain's current bend plane. `worldPose` is `poseToWorld` of `pose` as it
|
|
252
|
+
* is on entry (the solver reads it, never rewrites it). `instanceWorld` (3×4 row-major) maps
|
|
253
|
+
* skeleton space to the space the target and pole are given in. `weight` slerps the result
|
|
254
|
+
* against the input rotations. No allocation when `chain` is an `IkChain` (or a reused object).
|
|
255
|
+
*/
|
|
256
|
+
export function twoBoneIk(pose, skeleton, worldPose, chain, targetWorld, poleWorld, instanceWorld, opts) {
|
|
257
|
+
const weight = opts?.weight ?? 1;
|
|
258
|
+
if (weight <= 0)
|
|
259
|
+
return;
|
|
260
|
+
const iterations = Math.max(1, opts?.maxIterations ?? 1);
|
|
261
|
+
const c = chainFor(skeleton, chain);
|
|
262
|
+
const path = c.path;
|
|
263
|
+
const last = path.length - 1;
|
|
264
|
+
const rootO = c.root * POSE_NODE_FLOATS + 3;
|
|
265
|
+
const midO = c.mid * POSE_NODE_FLOATS + 3;
|
|
266
|
+
for (let i = 0; i < 4; i++) {
|
|
267
|
+
c.saved[i] = pose[rootO + i];
|
|
268
|
+
c.saved[4 + i] = pose[midO + i];
|
|
269
|
+
}
|
|
270
|
+
for (let i = 0; i <= last; i++) {
|
|
271
|
+
const wo = path[i] * WORLD_NODE_FLOATS;
|
|
272
|
+
c.world.set(worldPose.subarray(wo, wo + WORLD_NODE_FLOATS), i * WORLD_NODE_FLOATS);
|
|
273
|
+
}
|
|
274
|
+
toSkeleton(tgt, targetWorld, instanceWorld);
|
|
275
|
+
if (poleWorld)
|
|
276
|
+
toSkeleton(pol, poleWorld, instanceWorld);
|
|
277
|
+
const W = c.world;
|
|
278
|
+
const mo = c.midIndex * WORLD_NODE_FLOATS;
|
|
279
|
+
const to = last * WORLD_NODE_FLOATS;
|
|
280
|
+
for (let iter = 0; iter < iterations; iter++) {
|
|
281
|
+
const rx = W[3];
|
|
282
|
+
const ry = W[7];
|
|
283
|
+
const rz = W[11];
|
|
284
|
+
const mx = W[mo + 3];
|
|
285
|
+
const my = W[mo + 7];
|
|
286
|
+
const mz = W[mo + 11];
|
|
287
|
+
const tx = W[to + 3];
|
|
288
|
+
const ty = W[to + 7];
|
|
289
|
+
const tz = W[to + 11];
|
|
290
|
+
const a = Math.hypot(mx - rx, my - ry, mz - rz);
|
|
291
|
+
const b = Math.hypot(tx - mx, ty - my, tz - mz);
|
|
292
|
+
if (a <= EPS || b <= EPS)
|
|
293
|
+
break;
|
|
294
|
+
dir[0] = tgt[0] - rx;
|
|
295
|
+
dir[1] = tgt[1] - ry;
|
|
296
|
+
dir[2] = tgt[2] - rz;
|
|
297
|
+
const d = normalize(dir);
|
|
298
|
+
if (d <= EPS)
|
|
299
|
+
break;
|
|
300
|
+
// Out of reach: straight towards the target (cos 1); too close: folded (cos ±1).
|
|
301
|
+
const reach = Math.max(d, Math.abs(a - b), EPS);
|
|
302
|
+
const cos = d >= a + b ? 1 : Math.min(1, Math.max(-1, (a * a + reach * reach - b * b) / (2 * a * reach)));
|
|
303
|
+
const sin = Math.sqrt(Math.max(0, 1 - cos * cos));
|
|
304
|
+
// Bend direction: the pole (or the current mid) projected off the root→target line.
|
|
305
|
+
if (poleWorld) {
|
|
306
|
+
v[0] = pol[0] - rx;
|
|
307
|
+
v[1] = pol[1] - ry;
|
|
308
|
+
v[2] = pol[2] - rz;
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
v[0] = mx - rx;
|
|
312
|
+
v[1] = my - ry;
|
|
313
|
+
v[2] = mz - rz;
|
|
314
|
+
}
|
|
315
|
+
let along = v[0] * dir[0] + v[1] * dir[1] + v[2] * dir[2];
|
|
316
|
+
perp[0] = v[0] - dir[0] * along;
|
|
317
|
+
perp[1] = v[1] - dir[1] * along;
|
|
318
|
+
perp[2] = v[2] - dir[2] * along;
|
|
319
|
+
if (normalize(perp) <= 1e-4) {
|
|
320
|
+
if (poleWorld) {
|
|
321
|
+
// Pole on the line: fall back to the chain's own bend, then to anything perpendicular.
|
|
322
|
+
v[0] = mx - rx;
|
|
323
|
+
v[1] = my - ry;
|
|
324
|
+
v[2] = mz - rz;
|
|
325
|
+
along = v[0] * dir[0] + v[1] * dir[1] + v[2] * dir[2];
|
|
326
|
+
perp[0] = v[0] - dir[0] * along;
|
|
327
|
+
perp[1] = v[1] - dir[1] * along;
|
|
328
|
+
perp[2] = v[2] - dir[2] * along;
|
|
329
|
+
}
|
|
330
|
+
if (normalize(perp) <= 1e-4)
|
|
331
|
+
anyPerpendicular(perp, dir);
|
|
332
|
+
}
|
|
333
|
+
// Where the mid joint must be, then the root rotation that puts it there.
|
|
334
|
+
m2[0] = rx + dir[0] * a * cos + perp[0] * a * sin;
|
|
335
|
+
m2[1] = ry + dir[1] * a * cos + perp[1] * a * sin;
|
|
336
|
+
m2[2] = rz + dir[2] * a * cos + perp[2] * a * sin;
|
|
337
|
+
v[0] = (mx - rx) / a;
|
|
338
|
+
v[1] = (my - ry) / a;
|
|
339
|
+
v[2] = (mz - rz) / a;
|
|
340
|
+
perp[0] = (m2[0] - rx) / a;
|
|
341
|
+
perp[1] = (m2[1] - ry) / a;
|
|
342
|
+
perp[2] = (m2[2] - rz) / a;
|
|
343
|
+
rotationBetween(d1, v, perp);
|
|
344
|
+
// The tip after the root rotation, then the mid rotation that brings it to the target.
|
|
345
|
+
t1[0] = tx - rx;
|
|
346
|
+
t1[1] = ty - ry;
|
|
347
|
+
t1[2] = tz - rz;
|
|
348
|
+
rotateBy(t1, d1);
|
|
349
|
+
t1[0] = t1[0] + rx - m2[0];
|
|
350
|
+
t1[1] = t1[1] + ry - m2[1];
|
|
351
|
+
t1[2] = t1[2] + rz - m2[2];
|
|
352
|
+
normalize(t1);
|
|
353
|
+
v[0] = tgt[0] - m2[0];
|
|
354
|
+
v[1] = tgt[1] - m2[1];
|
|
355
|
+
v[2] = tgt[2] - m2[2];
|
|
356
|
+
if (normalize(v) <= EPS) {
|
|
357
|
+
d2[3] = 0;
|
|
358
|
+
}
|
|
359
|
+
else
|
|
360
|
+
rotationBetween(d2, t1, v);
|
|
361
|
+
const rootParent = skeleton.parents[c.root];
|
|
362
|
+
if (rootParent < 0)
|
|
363
|
+
applyDelta(pose, c.root, d1, IDENTITY, 0, null);
|
|
364
|
+
else
|
|
365
|
+
applyDelta(pose, c.root, d1, worldPose, rootParent * WORLD_NODE_FLOATS, null);
|
|
366
|
+
applyDelta(pose, c.mid, d2, W, mo - WORLD_NODE_FLOATS, d1);
|
|
367
|
+
if (iter + 1 < iterations)
|
|
368
|
+
refreshChain(c, skeleton, pose, worldPose);
|
|
369
|
+
}
|
|
370
|
+
if (weight < 1) {
|
|
371
|
+
quatSlerp(pose, rootO, c.saved, 0, pose, rootO, weight);
|
|
372
|
+
quatSlerp(pose, midO, c.saved, 4, pose, midO, weight);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const DEFAULT_FORWARD = new Float32Array([0, 0, 1]);
|
|
376
|
+
/**
|
|
377
|
+
* Rotate `joint` in `pose` so that its local `forward` axis points at `targetWorld`, turning at
|
|
378
|
+
* most `maxAngle` radians away from its input direction and blended by `weight`. With an `up`
|
|
379
|
+
* hint the joint also rolls so what was up for it stays up. Reads the joint's world matrix from
|
|
380
|
+
* `worldPose` (`poseToWorld` of the input pose) and its parent's; never rewrites it. No
|
|
381
|
+
* allocation.
|
|
382
|
+
*/
|
|
383
|
+
export function lookAt(pose, skeleton, worldPose, joint, targetWorld, instanceWorld, opts) {
|
|
384
|
+
const weight = opts?.weight ?? 1;
|
|
385
|
+
if (weight <= 0)
|
|
386
|
+
return;
|
|
387
|
+
const maxAngle = opts?.maxAngle ?? Math.PI;
|
|
388
|
+
const wo = joint * WORLD_NODE_FLOATS;
|
|
389
|
+
toSkeleton(tgt, targetWorld, instanceWorld);
|
|
390
|
+
transformDir(fwd, worldPose, wo, opts?.forward ?? DEFAULT_FORWARD);
|
|
391
|
+
if (normalize(fwd) <= EPS)
|
|
392
|
+
return;
|
|
393
|
+
v[0] = tgt[0] - worldPose[wo + 3];
|
|
394
|
+
v[1] = tgt[1] - worldPose[wo + 7];
|
|
395
|
+
v[2] = tgt[2] - worldPose[wo + 11];
|
|
396
|
+
if (normalize(v) <= EPS)
|
|
397
|
+
return;
|
|
398
|
+
rotationBetween(d1, fwd, v);
|
|
399
|
+
d1[3] = Math.min(d1[3], Math.max(0, maxAngle));
|
|
400
|
+
if (d1[3] === 0)
|
|
401
|
+
return;
|
|
402
|
+
const o = joint * POSE_NODE_FLOATS + 3;
|
|
403
|
+
for (let i = 0; i < 4; i++)
|
|
404
|
+
savedRot[i] = pose[o + i];
|
|
405
|
+
const parent = skeleton.parents[joint];
|
|
406
|
+
const pm = parent < 0 ? IDENTITY : worldPose;
|
|
407
|
+
const po = parent < 0 ? 0 : parent * WORLD_NODE_FLOATS;
|
|
408
|
+
applyDelta(pose, joint, d1, pm, po, null);
|
|
409
|
+
const up = opts?.up;
|
|
410
|
+
if (up) {
|
|
411
|
+
// The up hint off the old forward, carried along by the aim, against the hint off the new
|
|
412
|
+
// forward: the roll between them is the twist that keeps "up" up.
|
|
413
|
+
upw[0] = up[0];
|
|
414
|
+
upw[1] = up[1];
|
|
415
|
+
upw[2] = up[2];
|
|
416
|
+
let along = upw[0] * fwd[0] + upw[1] * fwd[1] + upw[2] * fwd[2];
|
|
417
|
+
t1[0] = upw[0] - fwd[0] * along;
|
|
418
|
+
t1[1] = upw[1] - fwd[1] * along;
|
|
419
|
+
t1[2] = upw[2] - fwd[2] * along;
|
|
420
|
+
rotateBy(fwd, d1);
|
|
421
|
+
if (normalize(t1) > EPS) {
|
|
422
|
+
rotateBy(t1, d1);
|
|
423
|
+
along = upw[0] * fwd[0] + upw[1] * fwd[1] + upw[2] * fwd[2];
|
|
424
|
+
m2[0] = upw[0] - fwd[0] * along;
|
|
425
|
+
m2[1] = upw[1] - fwd[1] * along;
|
|
426
|
+
m2[2] = upw[2] - fwd[2] * along;
|
|
427
|
+
if (normalize(m2) > EPS) {
|
|
428
|
+
rotationBetween(d2, t1, m2);
|
|
429
|
+
applyDelta(pose, joint, d2, pm, po, null);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
if (weight < 1)
|
|
434
|
+
quatSlerp(pose, o, savedRot, 0, pose, o, weight);
|
|
435
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@thunderclap-engine/engine/anim`: keyframe clips (glTF sampler semantics) sampled into poses,
|
|
3
|
+
* blended and cross-faded by a mixer, resolved into node world matrices and skin joint matrices.
|
|
4
|
+
* Pure arithmetic, no GPU, no allocations per frame.
|
|
5
|
+
*/
|
|
6
|
+
export type { AimOffset, AimOffsetDesc, AimOffsetOptions } from './aim.js';
|
|
7
|
+
export { applyAimOffset, createAimOffset } from './aim.js';
|
|
8
|
+
export type { AnimationChannel, AnimationClip, AnimationEvent, AnimBlendMode, ChannelPath, ClipCursor, Interpolation, } from './clip.js';
|
|
9
|
+
export { channelComponents, clipDuration, createClipCursor, findKeyframe, sampleChannel, sampleClip, sampleWeights, unpackQuat, } from './clip.js';
|
|
10
|
+
export type { CompressClipOptions, CompressedClip, QuantizeClipOptions } from './compress.js';
|
|
11
|
+
export { clipBytes, compressClip, packQuat, quantizeClip } from './compress.js';
|
|
12
|
+
export type { FootIk, FootIkDesc, FootIkFootDesc, FootIkProbe } from './foot-ik.js';
|
|
13
|
+
export { applyFootIk, createFootIk } from './foot-ik.js';
|
|
14
|
+
export type { AnimGraph, AnimGraphBlend1D, AnimGraphBlend2D, AnimGraphBlendPoint, AnimGraphBlendPoint2D, AnimGraphBlendState, AnimGraphClipState, AnimGraphDesc, AnimGraphListener, AnimGraphMatchDesc, AnimGraphParams, AnimGraphStateDesc, AnimGraphTransition, } from './graph.js';
|
|
15
|
+
export { createAnimGraph } from './graph.js';
|
|
16
|
+
export type { IkChain, IkChainDesc, LookAtOptions, TwoBoneIkOptions } from './ik.js';
|
|
17
|
+
export { createIkChain, lookAt, twoBoneIk } from './ik.js';
|
|
18
|
+
export type { FindBestFrameOptions, PoseFeatures, PoseFeaturesOptions, PoseMatch } from './match.js';
|
|
19
|
+
export { buildPoseFeatures, findBestFrame, rootSpacePositions } from './match.js';
|
|
20
|
+
export type { AnimationEventListener, AnimationMixerOptions, AnimPlayOptions, } from './mixer.js';
|
|
21
|
+
export { AnimationAction, AnimationMixer } from './mixer.js';
|
|
22
|
+
export type { MorphBlender, MorphLayout, MorphTarget } from './morph.js';
|
|
23
|
+
export { createMorphBlender } from './morph.js';
|
|
24
|
+
export type { Pose, Skeleton } from './pose.js';
|
|
25
|
+
export { blendPose, copyPose, createPose, inverseBindFromRest, invertAffine, jointCount, multiplyAffine, nodeCount, POSE_NODE_FLOATS, poseToWorld, skinMatrices, validateSkeleton, WORLD_NODE_FLOATS, writeNodeMatrix, } from './pose.js';
|
|
26
|
+
export { quatDot, quatFromAxisAngle, quatFromEuler, quatFromMat3, quatIdentity, quatMultiply, quatNlerp, quatNormalize, quatSlerp, } from './quat.js';
|
|
27
|
+
export type { RetargetClipOptions, RetargetMap, RetargetOptions } from './retarget.js';
|
|
28
|
+
export { createRetargetMap, normalizeJointName, retargetClip, retargetPose } from './retarget.js';
|
|
29
|
+
export type { RootMotionDelta, RootMotionOptions, RootMotionSplit } from './root-motion.js';
|
|
30
|
+
export { applyRootMotionDelta, extractRootMotion } from './root-motion.js';
|
|
31
|
+
export type { SkinPoseSource, SkinPoseTarget } from './skin-pose.js';
|
|
32
|
+
export { skinPose } from './skin-pose.js';
|
|
33
|
+
export type { Socket, SocketLocal } from './socket.js';
|
|
34
|
+
export { attachTransform, createSocket, socketWorld } from './socket.js';
|
|
35
|
+
export type { SpringCapsule, SpringChain, SpringChainDesc, SpringCollider, SpringSphere, } from './spring-chain.js';
|
|
36
|
+
export { createSpringChain, updateSpringChain } from './spring-chain.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@thunderclap-engine/engine/anim`: keyframe clips (glTF sampler semantics) sampled into poses,
|
|
3
|
+
* blended and cross-faded by a mixer, resolved into node world matrices and skin joint matrices.
|
|
4
|
+
* Pure arithmetic, no GPU, no allocations per frame.
|
|
5
|
+
*/
|
|
6
|
+
export { applyAimOffset, createAimOffset } from './aim.js';
|
|
7
|
+
export { channelComponents, clipDuration, createClipCursor, findKeyframe, sampleChannel, sampleClip, sampleWeights, unpackQuat, } from './clip.js';
|
|
8
|
+
export { clipBytes, compressClip, packQuat, quantizeClip } from './compress.js';
|
|
9
|
+
export { applyFootIk, createFootIk } from './foot-ik.js';
|
|
10
|
+
export { createAnimGraph } from './graph.js';
|
|
11
|
+
export { createIkChain, lookAt, twoBoneIk } from './ik.js';
|
|
12
|
+
export { buildPoseFeatures, findBestFrame, rootSpacePositions } from './match.js';
|
|
13
|
+
export { AnimationAction, AnimationMixer } from './mixer.js';
|
|
14
|
+
export { createMorphBlender } from './morph.js';
|
|
15
|
+
export { blendPose, copyPose, createPose, inverseBindFromRest, invertAffine, jointCount, multiplyAffine, nodeCount, POSE_NODE_FLOATS, poseToWorld, skinMatrices, validateSkeleton, WORLD_NODE_FLOATS, writeNodeMatrix, } from './pose.js';
|
|
16
|
+
export { quatDot, quatFromAxisAngle, quatFromEuler, quatFromMat3, quatIdentity, quatMultiply, quatNlerp, quatNormalize, quatSlerp, } from './quat.js';
|
|
17
|
+
export { createRetargetMap, normalizeJointName, retargetClip, retargetPose } from './retarget.js';
|
|
18
|
+
export { applyRootMotionDelta, extractRootMotion } from './root-motion.js';
|
|
19
|
+
export { skinPose } from './skin-pose.js';
|
|
20
|
+
export { attachTransform, createSocket, socketWorld } from './socket.js';
|
|
21
|
+
export { createSpringChain, updateSpringChain } from './spring-chain.js';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pose matching: a transition starts the target clip at the frame nearest the pose it leaves,
|
|
3
|
+
* instead of at 0, so a walk→run blend does not snap a planted foot to the other leg.
|
|
4
|
+
*
|
|
5
|
+
* `buildPoseFeatures` samples a clip at a fixed rate and stores, per sample, the root-space
|
|
6
|
+
* position and velocity of a few joints (feet, hands, head). `findBestFrame` compares a pose's
|
|
7
|
+
* world matrices (plus per-joint velocities) against every sample and returns the time of the
|
|
8
|
+
* cheapest one. Root space is the frame of one node (the first root by default) so a clip's
|
|
9
|
+
* baked travel and the instance's placement drop out. Allocates at build; the query allocates
|
|
10
|
+
* nothing when given an `out`.
|
|
11
|
+
*/
|
|
12
|
+
import { type AnimationClip } from './clip.js';
|
|
13
|
+
import { type Skeleton } from './pose.js';
|
|
14
|
+
export interface PoseFeaturesOptions {
|
|
15
|
+
/** Node indices whose position and velocity make up a feature (feet, hands, head). */
|
|
16
|
+
joints: ArrayLike<number>;
|
|
17
|
+
/** Samples per second along the clip. Default 30. */
|
|
18
|
+
sampleRate?: number;
|
|
19
|
+
/** The node whose frame is "root space". Default: the first node with no parent. */
|
|
20
|
+
root?: number;
|
|
21
|
+
}
|
|
22
|
+
/** Per-sample joint positions and velocities of one clip, from `buildPoseFeatures`. */
|
|
23
|
+
export interface PoseFeatures {
|
|
24
|
+
readonly clip: AnimationClip;
|
|
25
|
+
readonly joints: Int16Array;
|
|
26
|
+
readonly root: number;
|
|
27
|
+
/** Sample times, ascending from 0. */
|
|
28
|
+
readonly times: Float32Array;
|
|
29
|
+
/** `6 × joints` floats per sample: `px py pz vx vy vz` per joint, root space. */
|
|
30
|
+
readonly data: Float32Array;
|
|
31
|
+
/** Floats per sample (`6 × joints`). */
|
|
32
|
+
readonly stride: number;
|
|
33
|
+
}
|
|
34
|
+
export interface FindBestFrameOptions {
|
|
35
|
+
/** Weight of the velocity term (s²; a velocity gap of 1 m/s costs this much). Default 0.05. */
|
|
36
|
+
velocityWeight?: number;
|
|
37
|
+
}
|
|
38
|
+
/** The result of `findBestFrame`: the clip time of the cheapest sample and its cost. */
|
|
39
|
+
export interface PoseMatch {
|
|
40
|
+
time: number;
|
|
41
|
+
cost: number;
|
|
42
|
+
}
|
|
43
|
+
/** @internal The first node with no parent (0 when none). */
|
|
44
|
+
export declare function firstRoot(skeleton: Skeleton): number;
|
|
45
|
+
/**
|
|
46
|
+
* Sample `clip` on `skeleton` every `1 / sampleRate` seconds (the last sample at the clip's
|
|
47
|
+
* duration) and record, per sample and per joint of `opts.joints`, the joint's root-space
|
|
48
|
+
* position and velocity (finite difference to the next sample; the last sample wraps to the
|
|
49
|
+
* first, as a looping clip does). Allocates; call at load.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildPoseFeatures(clip: AnimationClip, skeleton: Skeleton, opts: PoseFeaturesOptions): PoseFeatures;
|
|
52
|
+
/**
|
|
53
|
+
* Root-space positions of `joints` (3 floats each into `out`) from a pose's world matrices:
|
|
54
|
+
* what a velocity for `findBestFrame` is the time derivative of. Allocation-free.
|
|
55
|
+
*/
|
|
56
|
+
export declare function rootSpacePositions(poseWorld: Float32Array, root: number, joints: ArrayLike<number>, out: Float32Array): void;
|
|
57
|
+
/**
|
|
58
|
+
* The sample of `features` nearest a pose: `poseWorld` is `poseToWorld` of that pose (skeleton
|
|
59
|
+
* space; the root node's matrix in it defines root space), `velocity` holds the root-space
|
|
60
|
+
* velocity of each feature joint (`3 × joints` floats in `features.joints` order: the
|
|
61
|
+
* derivative of `rootSpacePositions`, so the root's own travel drops out), or `null` to match
|
|
62
|
+
* on positions alone. Cost per sample is the summed squared position gap plus `velocityWeight`
|
|
63
|
+
* times the summed squared velocity gap. Writes and returns `out` (a shared object when none
|
|
64
|
+
* is given). No allocation with `out`.
|
|
65
|
+
*/
|
|
66
|
+
export declare function findBestFrame(features: PoseFeatures, poseWorld: Float32Array, velocity: ArrayLike<number> | null, opts?: FindBestFrameOptions, out?: PoseMatch): PoseMatch;
|