@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,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retargeting: a clip authored for one skeleton drives another with different joint names,
|
|
3
|
+
* bone lengths and rest orientations (E-015: every cosmetic is a rig of its own, and one walk
|
|
4
|
+
* cycle has to play on all of them).
|
|
5
|
+
*
|
|
6
|
+
* `createRetargetMap(source, target, opts?)` pairs target joints with source joints (explicit
|
|
7
|
+
* pairs, then a name match) and precomputes, per matched joint, the two constant rotations that
|
|
8
|
+
* turn a source local rotation into a target local rotation:
|
|
9
|
+
*
|
|
10
|
+
* `Rt[j] = pre[j] · Rs[i] · post[j]`, with
|
|
11
|
+
* `pre[j] = inv(Wt_rest[parent j]) · Ws_rest[parent i]` (source parent frame → target parent frame)
|
|
12
|
+
* `post[j] = inv(pre[j] · Rs_rest[i]) · Rt_rest[j]`.
|
|
13
|
+
*
|
|
14
|
+
* Expanded, that is `Rt = A · (Rs · inv(Rs_rest)) · inv(A) · Rt_rest`: the source joint's
|
|
15
|
+
* rest-relative rotation delta, expressed in the source parent's frame, carried into the target
|
|
16
|
+
* parent's frame through the rest poses, and applied on top of the target's own rest rotation.
|
|
17
|
+
* When the two rigs' bones point the same way in world space at rest (the usual T- or A-pose
|
|
18
|
+
* convention), the target's bones end up pointing where the source's do, whatever its local
|
|
19
|
+
* joint frames look like. Translations stay at the target's rest except the root's, which moves
|
|
20
|
+
* by the source root's rest-relative delta scaled by the hip-height ratio.
|
|
21
|
+
*
|
|
22
|
+
* `retargetPose` allocates nothing; `createRetargetMap` and `retargetClip` allocate (once).
|
|
23
|
+
*/
|
|
24
|
+
import { type AnimationClip } from './clip.js';
|
|
25
|
+
import { type Pose, type Skeleton } from './pose.js';
|
|
26
|
+
export interface RetargetOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Explicit `[source, target]` joint pairs by name or node index. Pairs win over name matching
|
|
29
|
+
* and are the only way to pair joints of a skeleton without `names`.
|
|
30
|
+
*/
|
|
31
|
+
pairs?: Array<[string | number, string | number]>;
|
|
32
|
+
/**
|
|
33
|
+
* Replaces the default name matching: given a source joint name, return the target joint name
|
|
34
|
+
* it drives, or `null` for none. Not called for joints covered by `pairs`.
|
|
35
|
+
*/
|
|
36
|
+
match?: (sourceName: string) => string | null;
|
|
37
|
+
/**
|
|
38
|
+
* The target node whose translation follows its paired source node (the hips). Default: the
|
|
39
|
+
* first matched target node in hierarchy order. A node that ends up unmatched gets none.
|
|
40
|
+
*/
|
|
41
|
+
rootNode?: string | number;
|
|
42
|
+
/**
|
|
43
|
+
* Scale the root's translation delta by the ratio of the rigs' hip heights (the length of the
|
|
44
|
+
* root node's rest world position; 1 when either is 0). Default true.
|
|
45
|
+
*/
|
|
46
|
+
scaleTranslation?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface RetargetMap {
|
|
49
|
+
source: Skeleton;
|
|
50
|
+
target: Skeleton;
|
|
51
|
+
/** Source node per target node, `-1` where the target joint has no source. */
|
|
52
|
+
pairs: Int32Array;
|
|
53
|
+
/** Target joints with no source, by name (index as text when the skeleton has no names). */
|
|
54
|
+
unmatched: string[];
|
|
55
|
+
/** Target node whose translation is transferred, `-1` for none. */
|
|
56
|
+
root: number;
|
|
57
|
+
/** Factor on the root's translation delta (hip-height ratio, or 1). Settable. */
|
|
58
|
+
translationScale: number;
|
|
59
|
+
/** Precomputed rest frames: `pre[j]` (4 floats per target node), applied before the source rotation. */
|
|
60
|
+
pre: Float32Array;
|
|
61
|
+
/** Precomputed rest frames: `post[j]` (4 floats per target node), applied after it. */
|
|
62
|
+
post: Float32Array;
|
|
63
|
+
}
|
|
64
|
+
export interface RetargetClipOptions {
|
|
65
|
+
/** Samples per second. Default: the clip's own key times, merged over its channels. */
|
|
66
|
+
sampleRate?: number;
|
|
67
|
+
/** Name of the baked clip. Default: the source clip's name. */
|
|
68
|
+
name?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Lowercase, drop a `namespace:` or `Armature|` prefix, and strip separators (`_`, `-`, `.`,
|
|
72
|
+
* `:`, `|`, spaces), so `mixamorig:LeftArm`, `Left_Arm` and `left arm` compare equal.
|
|
73
|
+
*/
|
|
74
|
+
export declare function normalizeJointName(name: string): string;
|
|
75
|
+
/**
|
|
76
|
+
* Pair the joints of `source` and `target` and precompute the rest frames `retargetPose` and
|
|
77
|
+
* `retargetClip` use. Pairing, per source joint: `opts.pairs` first; then `opts.match` when
|
|
78
|
+
* given, else the target joint with the same name, else the one whose `normalizeJointName`
|
|
79
|
+
* matches. Two skeletons without names pair by index. Target joints left over are listed in
|
|
80
|
+
* `unmatched` and hold their rest. Allocates; build once per (clip skeleton, character) pair.
|
|
81
|
+
*/
|
|
82
|
+
export declare function createRetargetMap(source: Skeleton, target: Skeleton, opts?: RetargetOptions): RetargetMap;
|
|
83
|
+
/**
|
|
84
|
+
* Write `targetPose` from `sourcePose`: every target node starts at the target's rest; a matched
|
|
85
|
+
* node gets `pre · Rs · post` as its rotation; the root also gets its paired node's translation
|
|
86
|
+
* delta (rotated into the target root's parent frame, scaled by `translationScale`). Scale stays
|
|
87
|
+
* at the target's rest. No allocation.
|
|
88
|
+
*/
|
|
89
|
+
export declare function retargetPose(map: RetargetMap, sourcePose: Pose, targetPose: Pose): void;
|
|
90
|
+
/**
|
|
91
|
+
* Bake `clip` (authored for `map.source`) into a clip for `map.target`: at every sample time
|
|
92
|
+
* the source pose is sampled, retargeted, and written as `LINEAR` rotation keys for each matched
|
|
93
|
+
* target node whose source node the clip rotates, plus translation keys for the root when the
|
|
94
|
+
* clip translates its source. Events and duration are kept. Allocates; a game that would rather
|
|
95
|
+
* pay once than call `retargetPose` per frame.
|
|
96
|
+
*/
|
|
97
|
+
export declare function retargetClip(map: RetargetMap, clip: AnimationClip, opts?: RetargetClipOptions): AnimationClip;
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retargeting: a clip authored for one skeleton drives another with different joint names,
|
|
3
|
+
* bone lengths and rest orientations (E-015: every cosmetic is a rig of its own, and one walk
|
|
4
|
+
* cycle has to play on all of them).
|
|
5
|
+
*
|
|
6
|
+
* `createRetargetMap(source, target, opts?)` pairs target joints with source joints (explicit
|
|
7
|
+
* pairs, then a name match) and precomputes, per matched joint, the two constant rotations that
|
|
8
|
+
* turn a source local rotation into a target local rotation:
|
|
9
|
+
*
|
|
10
|
+
* `Rt[j] = pre[j] · Rs[i] · post[j]`, with
|
|
11
|
+
* `pre[j] = inv(Wt_rest[parent j]) · Ws_rest[parent i]` (source parent frame → target parent frame)
|
|
12
|
+
* `post[j] = inv(pre[j] · Rs_rest[i]) · Rt_rest[j]`.
|
|
13
|
+
*
|
|
14
|
+
* Expanded, that is `Rt = A · (Rs · inv(Rs_rest)) · inv(A) · Rt_rest`: the source joint's
|
|
15
|
+
* rest-relative rotation delta, expressed in the source parent's frame, carried into the target
|
|
16
|
+
* parent's frame through the rest poses, and applied on top of the target's own rest rotation.
|
|
17
|
+
* When the two rigs' bones point the same way in world space at rest (the usual T- or A-pose
|
|
18
|
+
* convention), the target's bones end up pointing where the source's do, whatever its local
|
|
19
|
+
* joint frames look like. Translations stay at the target's rest except the root's, which moves
|
|
20
|
+
* by the source root's rest-relative delta scaled by the hip-height ratio.
|
|
21
|
+
*
|
|
22
|
+
* `retargetPose` allocates nothing; `createRetargetMap` and `retargetClip` allocate (once).
|
|
23
|
+
*/
|
|
24
|
+
import { createClipCursor, sampleClip } from './clip.js';
|
|
25
|
+
import { POSE_NODE_FLOATS, poseToWorld, WORLD_NODE_FLOATS } from './pose.js';
|
|
26
|
+
import { quatMultiply, quatNormalize } from './quat.js';
|
|
27
|
+
/**
|
|
28
|
+
* Lowercase, drop a `namespace:` or `Armature|` prefix, and strip separators (`_`, `-`, `.`,
|
|
29
|
+
* `:`, `|`, spaces), so `mixamorig:LeftArm`, `Left_Arm` and `left arm` compare equal.
|
|
30
|
+
*/
|
|
31
|
+
export function normalizeJointName(name) {
|
|
32
|
+
let s = name;
|
|
33
|
+
const cut = Math.max(s.lastIndexOf(':'), s.lastIndexOf('|'));
|
|
34
|
+
if (cut >= 0)
|
|
35
|
+
s = s.slice(cut + 1);
|
|
36
|
+
return s.toLowerCase().replace(/[\s_\-.:|]+/g, '');
|
|
37
|
+
}
|
|
38
|
+
function resolveNode(skeleton, ref, side) {
|
|
39
|
+
if (typeof ref === 'number') {
|
|
40
|
+
if (ref < 0 || ref >= skeleton.parents.length || (ref | 0) !== ref) {
|
|
41
|
+
throw new Error(`retarget: ${side} node ${ref} is out of range`);
|
|
42
|
+
}
|
|
43
|
+
return ref;
|
|
44
|
+
}
|
|
45
|
+
const names = skeleton.names;
|
|
46
|
+
const i = names ? names.indexOf(ref) : -1;
|
|
47
|
+
if (i < 0)
|
|
48
|
+
throw new Error(`retarget: ${side} skeleton has no node named "${ref}"`);
|
|
49
|
+
return i;
|
|
50
|
+
}
|
|
51
|
+
/** World rest rotation per node (4 floats each), parents before children. Allocates. */
|
|
52
|
+
function restWorldRotations(skeleton) {
|
|
53
|
+
const n = skeleton.parents.length;
|
|
54
|
+
const out = new Float32Array(n * 4);
|
|
55
|
+
for (let i = 0; i < n; i++) {
|
|
56
|
+
const p = skeleton.parents[i];
|
|
57
|
+
const ro = i * POSE_NODE_FLOATS + 3;
|
|
58
|
+
if (p < 0) {
|
|
59
|
+
out[i * 4] = skeleton.rest[ro];
|
|
60
|
+
out[i * 4 + 1] = skeleton.rest[ro + 1];
|
|
61
|
+
out[i * 4 + 2] = skeleton.rest[ro + 2];
|
|
62
|
+
out[i * 4 + 3] = skeleton.rest[ro + 3];
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
quatMultiply(out, i * 4, out, p * 4, skeleton.rest, ro);
|
|
66
|
+
}
|
|
67
|
+
quatNormalize(out, i * 4);
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
/** Hip height: the length of the node's rest world position. */
|
|
72
|
+
function restHeight(skeleton, node) {
|
|
73
|
+
const world = new Float32Array(skeleton.parents.length * WORLD_NODE_FLOATS);
|
|
74
|
+
poseToWorld(skeleton, skeleton.rest, world);
|
|
75
|
+
const o = node * WORLD_NODE_FLOATS;
|
|
76
|
+
return Math.hypot(world[o + 3], world[o + 7], world[o + 11]);
|
|
77
|
+
}
|
|
78
|
+
/** Write the conjugate (inverse, for unit quaternions) of `q[qo..]` at `out[oo..]`. */
|
|
79
|
+
function conjugate(out, oo, q, qo) {
|
|
80
|
+
out[oo] = -q[qo];
|
|
81
|
+
out[oo + 1] = -q[qo + 1];
|
|
82
|
+
out[oo + 2] = -q[qo + 2];
|
|
83
|
+
out[oo + 3] = q[qo + 3];
|
|
84
|
+
}
|
|
85
|
+
const IDENTITY = new Float32Array([0, 0, 0, 1]);
|
|
86
|
+
const tmpA = new Float32Array(4);
|
|
87
|
+
const tmpB = new Float32Array(4);
|
|
88
|
+
/**
|
|
89
|
+
* Pair the joints of `source` and `target` and precompute the rest frames `retargetPose` and
|
|
90
|
+
* `retargetClip` use. Pairing, per source joint: `opts.pairs` first; then `opts.match` when
|
|
91
|
+
* given, else the target joint with the same name, else the one whose `normalizeJointName`
|
|
92
|
+
* matches. Two skeletons without names pair by index. Target joints left over are listed in
|
|
93
|
+
* `unmatched` and hold their rest. Allocates; build once per (clip skeleton, character) pair.
|
|
94
|
+
*/
|
|
95
|
+
export function createRetargetMap(source, target, opts = {}) {
|
|
96
|
+
const src = source;
|
|
97
|
+
const tgt = target;
|
|
98
|
+
const ns = source.parents.length;
|
|
99
|
+
const nt = target.parents.length;
|
|
100
|
+
const pairs = new Int32Array(nt).fill(-1);
|
|
101
|
+
const sourceUsed = new Uint8Array(ns);
|
|
102
|
+
const pair = (s, t) => {
|
|
103
|
+
if (pairs[t] !== -1 || sourceUsed[s])
|
|
104
|
+
return;
|
|
105
|
+
pairs[t] = s;
|
|
106
|
+
sourceUsed[s] = 1;
|
|
107
|
+
};
|
|
108
|
+
for (const [s, t] of opts.pairs ?? []) {
|
|
109
|
+
pair(resolveNode(src, s, 'source'), resolveNode(tgt, t, 'target'));
|
|
110
|
+
}
|
|
111
|
+
if (src.names && tgt.names) {
|
|
112
|
+
const targetByName = new Map();
|
|
113
|
+
const targetByNormal = new Map();
|
|
114
|
+
for (let t = 0; t < nt; t++) {
|
|
115
|
+
const name = tgt.names[t];
|
|
116
|
+
if (name === undefined)
|
|
117
|
+
continue;
|
|
118
|
+
if (!targetByName.has(name))
|
|
119
|
+
targetByName.set(name, t);
|
|
120
|
+
const norm = normalizeJointName(name);
|
|
121
|
+
if (!targetByNormal.has(norm))
|
|
122
|
+
targetByNormal.set(norm, t);
|
|
123
|
+
}
|
|
124
|
+
for (let s = 0; s < ns; s++) {
|
|
125
|
+
if (sourceUsed[s])
|
|
126
|
+
continue;
|
|
127
|
+
const name = src.names[s];
|
|
128
|
+
if (name === undefined)
|
|
129
|
+
continue;
|
|
130
|
+
let t;
|
|
131
|
+
if (opts.match) {
|
|
132
|
+
const wanted = opts.match(name);
|
|
133
|
+
if (wanted !== null)
|
|
134
|
+
t = targetByName.get(wanted) ?? targetByNormal.get(normalizeJointName(wanted));
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
t = targetByName.get(name) ?? targetByNormal.get(normalizeJointName(name));
|
|
138
|
+
}
|
|
139
|
+
if (t !== undefined)
|
|
140
|
+
pair(s, t);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else if (!src.names && !tgt.names && !opts.pairs) {
|
|
144
|
+
for (let i = 0; i < Math.min(ns, nt); i++)
|
|
145
|
+
pair(i, i);
|
|
146
|
+
}
|
|
147
|
+
const unmatched = [];
|
|
148
|
+
for (let t = 0; t < nt; t++) {
|
|
149
|
+
if (pairs[t] === -1)
|
|
150
|
+
unmatched.push(tgt.names?.[t] ?? String(t));
|
|
151
|
+
}
|
|
152
|
+
let root = -1;
|
|
153
|
+
if (opts.rootNode !== undefined) {
|
|
154
|
+
const r = resolveNode(tgt, opts.rootNode, 'target');
|
|
155
|
+
if (pairs[r] !== -1)
|
|
156
|
+
root = r;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
for (let t = 0; t < nt; t++) {
|
|
160
|
+
if (pairs[t] !== -1) {
|
|
161
|
+
root = t;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const ws = restWorldRotations(source);
|
|
167
|
+
const wt = restWorldRotations(target);
|
|
168
|
+
const pre = new Float32Array(nt * 4);
|
|
169
|
+
const post = new Float32Array(nt * 4);
|
|
170
|
+
for (let t = 0; t < nt; t++) {
|
|
171
|
+
const s = pairs[t];
|
|
172
|
+
if (s === -1)
|
|
173
|
+
continue;
|
|
174
|
+
const ps = source.parents[s];
|
|
175
|
+
const pt = target.parents[t];
|
|
176
|
+
// pre = inv(Wt_rest[pt]) · Ws_rest[ps]
|
|
177
|
+
if (pt < 0)
|
|
178
|
+
tmpA.set(IDENTITY);
|
|
179
|
+
else
|
|
180
|
+
conjugate(tmpA, 0, wt, pt * 4);
|
|
181
|
+
if (ps < 0)
|
|
182
|
+
quatMultiply(pre, t * 4, tmpA, 0, IDENTITY, 0);
|
|
183
|
+
else
|
|
184
|
+
quatMultiply(pre, t * 4, tmpA, 0, ws, ps * 4);
|
|
185
|
+
quatNormalize(pre, t * 4);
|
|
186
|
+
// post = inv(pre · Rs_rest[s]) · Rt_rest[t]
|
|
187
|
+
quatMultiply(tmpB, 0, pre, t * 4, source.rest, s * POSE_NODE_FLOATS + 3);
|
|
188
|
+
conjugate(tmpA, 0, tmpB, 0);
|
|
189
|
+
quatMultiply(post, t * 4, tmpA, 0, target.rest, t * POSE_NODE_FLOATS + 3);
|
|
190
|
+
quatNormalize(post, t * 4);
|
|
191
|
+
}
|
|
192
|
+
let translationScale = 1;
|
|
193
|
+
if (root !== -1 && opts.scaleTranslation !== false) {
|
|
194
|
+
const hs = restHeight(source, pairs[root]);
|
|
195
|
+
const ht = restHeight(target, root);
|
|
196
|
+
if (hs > 0 && ht > 0)
|
|
197
|
+
translationScale = ht / hs;
|
|
198
|
+
}
|
|
199
|
+
return { source, target, pairs, unmatched, root, translationScale, pre, post };
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Write `targetPose` from `sourcePose`: every target node starts at the target's rest; a matched
|
|
203
|
+
* node gets `pre · Rs · post` as its rotation; the root also gets its paired node's translation
|
|
204
|
+
* delta (rotated into the target root's parent frame, scaled by `translationScale`). Scale stays
|
|
205
|
+
* at the target's rest. No allocation.
|
|
206
|
+
*/
|
|
207
|
+
export function retargetPose(map, sourcePose, targetPose) {
|
|
208
|
+
const { source, target, pairs, pre, post } = map;
|
|
209
|
+
const tRest = target.rest;
|
|
210
|
+
const sRest = source.rest;
|
|
211
|
+
targetPose.set(tRest);
|
|
212
|
+
const nt = pairs.length;
|
|
213
|
+
for (let t = 0; t < nt; t++) {
|
|
214
|
+
const s = pairs[t];
|
|
215
|
+
if (s === -1)
|
|
216
|
+
continue;
|
|
217
|
+
const to = t * POSE_NODE_FLOATS;
|
|
218
|
+
const so = s * POSE_NODE_FLOATS;
|
|
219
|
+
quatMultiply(targetPose, to + 3, pre, t * 4, sourcePose, so + 3);
|
|
220
|
+
quatMultiply(targetPose, to + 3, targetPose, to + 3, post, t * 4);
|
|
221
|
+
quatNormalize(targetPose, to + 3);
|
|
222
|
+
}
|
|
223
|
+
const root = map.root;
|
|
224
|
+
if (root !== -1) {
|
|
225
|
+
const s = pairs[root];
|
|
226
|
+
const to = root * POSE_NODE_FLOATS;
|
|
227
|
+
const so = s * POSE_NODE_FLOATS;
|
|
228
|
+
const dx = sourcePose[so] - sRest[so];
|
|
229
|
+
const dy = sourcePose[so + 1] - sRest[so + 1];
|
|
230
|
+
const dz = sourcePose[so + 2] - sRest[so + 2];
|
|
231
|
+
// Rotate the delta by pre[root] (source parent frame → target parent frame): v' = q v q*.
|
|
232
|
+
const qo = root * 4;
|
|
233
|
+
const qx = pre[qo];
|
|
234
|
+
const qy = pre[qo + 1];
|
|
235
|
+
const qz = pre[qo + 2];
|
|
236
|
+
const qw = pre[qo + 3];
|
|
237
|
+
const cx = qy * dz - qz * dy;
|
|
238
|
+
const cy = qz * dx - qx * dz;
|
|
239
|
+
const cz = qx * dy - qy * dx;
|
|
240
|
+
const k = map.translationScale;
|
|
241
|
+
targetPose[to] = tRest[to] + k * (dx + 2 * (qw * cx + qy * cz - qz * cy));
|
|
242
|
+
targetPose[to + 1] = tRest[to + 1] + k * (dy + 2 * (qw * cy + qz * cx - qx * cz));
|
|
243
|
+
targetPose[to + 2] = tRest[to + 2] + k * (dz + 2 * (qw * cz + qx * cy - qy * cx));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/** Sorted unique key times over the clip's channels (`[0]` for a clip without keys). */
|
|
247
|
+
function keyTimes(clip) {
|
|
248
|
+
const set = new Set();
|
|
249
|
+
for (const ch of clip.channels)
|
|
250
|
+
for (let i = 0; i < ch.times.length; i++)
|
|
251
|
+
set.add(ch.times[i]);
|
|
252
|
+
if (set.size === 0)
|
|
253
|
+
set.add(0);
|
|
254
|
+
return [...set].sort((a, b) => a - b);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Bake `clip` (authored for `map.source`) into a clip for `map.target`: at every sample time
|
|
258
|
+
* the source pose is sampled, retargeted, and written as `LINEAR` rotation keys for each matched
|
|
259
|
+
* target node whose source node the clip rotates, plus translation keys for the root when the
|
|
260
|
+
* clip translates its source. Events and duration are kept. Allocates; a game that would rather
|
|
261
|
+
* pay once than call `retargetPose` per frame.
|
|
262
|
+
*/
|
|
263
|
+
export function retargetClip(map, clip, opts = {}) {
|
|
264
|
+
const { source, target, pairs } = map;
|
|
265
|
+
let times;
|
|
266
|
+
if (opts.sampleRate !== undefined && opts.sampleRate > 0) {
|
|
267
|
+
const n = Math.max(1, Math.ceil(clip.duration * opts.sampleRate));
|
|
268
|
+
times = [];
|
|
269
|
+
for (let i = 0; i <= n; i++)
|
|
270
|
+
times.push(Math.min(clip.duration, i / opts.sampleRate));
|
|
271
|
+
if (times[times.length - 1] < clip.duration)
|
|
272
|
+
times.push(clip.duration);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
times = keyTimes(clip);
|
|
276
|
+
}
|
|
277
|
+
const rotated = new Uint8Array(source.parents.length);
|
|
278
|
+
const translated = new Uint8Array(source.parents.length);
|
|
279
|
+
for (const ch of clip.channels) {
|
|
280
|
+
if (ch.node < 0 || ch.node >= rotated.length)
|
|
281
|
+
continue;
|
|
282
|
+
if (ch.path === 'rotation')
|
|
283
|
+
rotated[ch.node] = 1;
|
|
284
|
+
else if (ch.path === 'translation')
|
|
285
|
+
translated[ch.node] = 1;
|
|
286
|
+
}
|
|
287
|
+
const nt = pairs.length;
|
|
288
|
+
const rotationOut = new Array(nt).fill(null);
|
|
289
|
+
for (let t = 0; t < nt; t++) {
|
|
290
|
+
const s = pairs[t];
|
|
291
|
+
if (s !== -1 && rotated[s])
|
|
292
|
+
rotationOut[t] = new Float32Array(times.length * 4);
|
|
293
|
+
}
|
|
294
|
+
const root = map.root;
|
|
295
|
+
const rootOut = root !== -1 && translated[pairs[root]] ? new Float32Array(times.length * 3) : null;
|
|
296
|
+
const sourcePose = new Float32Array(source.rest);
|
|
297
|
+
const targetPose = new Float32Array(target.rest);
|
|
298
|
+
const cursor = createClipCursor(clip);
|
|
299
|
+
for (let k = 0; k < times.length; k++) {
|
|
300
|
+
sourcePose.set(source.rest);
|
|
301
|
+
sampleClip(clip, times[k], sourcePose, 1, 'override', cursor);
|
|
302
|
+
retargetPose(map, sourcePose, targetPose);
|
|
303
|
+
for (let t = 0; t < nt; t++) {
|
|
304
|
+
const out = rotationOut[t];
|
|
305
|
+
if (!out)
|
|
306
|
+
continue;
|
|
307
|
+
const o = t * POSE_NODE_FLOATS + 3;
|
|
308
|
+
out[k * 4] = targetPose[o];
|
|
309
|
+
out[k * 4 + 1] = targetPose[o + 1];
|
|
310
|
+
out[k * 4 + 2] = targetPose[o + 2];
|
|
311
|
+
out[k * 4 + 3] = targetPose[o + 3];
|
|
312
|
+
}
|
|
313
|
+
if (rootOut) {
|
|
314
|
+
const o = root * POSE_NODE_FLOATS;
|
|
315
|
+
rootOut[k * 3] = targetPose[o];
|
|
316
|
+
rootOut[k * 3 + 1] = targetPose[o + 1];
|
|
317
|
+
rootOut[k * 3 + 2] = targetPose[o + 2];
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
// Keep neighbouring keys on the same hemisphere so LINEAR slerp takes the short arc.
|
|
321
|
+
for (const out of rotationOut) {
|
|
322
|
+
if (!out)
|
|
323
|
+
continue;
|
|
324
|
+
for (let k = 1; k < times.length; k++) {
|
|
325
|
+
const a = (k - 1) * 4;
|
|
326
|
+
const b = k * 4;
|
|
327
|
+
const dot = out[a] * out[b] +
|
|
328
|
+
out[a + 1] * out[b + 1] +
|
|
329
|
+
out[a + 2] * out[b + 2] +
|
|
330
|
+
out[a + 3] * out[b + 3];
|
|
331
|
+
if (dot < 0) {
|
|
332
|
+
out[b] = -out[b];
|
|
333
|
+
out[b + 1] = -out[b + 1];
|
|
334
|
+
out[b + 2] = -out[b + 2];
|
|
335
|
+
out[b + 3] = -out[b + 3];
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const timesArray = Float32Array.from(times);
|
|
340
|
+
const channels = [];
|
|
341
|
+
if (rootOut) {
|
|
342
|
+
channels.push({
|
|
343
|
+
node: root,
|
|
344
|
+
path: 'translation',
|
|
345
|
+
interpolation: 'LINEAR',
|
|
346
|
+
times: timesArray,
|
|
347
|
+
values: rootOut,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
for (let t = 0; t < nt; t++) {
|
|
351
|
+
const out = rotationOut[t];
|
|
352
|
+
if (!out)
|
|
353
|
+
continue;
|
|
354
|
+
channels.push({
|
|
355
|
+
node: t,
|
|
356
|
+
path: 'rotation',
|
|
357
|
+
interpolation: 'LINEAR',
|
|
358
|
+
times: timesArray,
|
|
359
|
+
values: out,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
const baked = { name: opts.name ?? clip.name, duration: clip.duration, channels };
|
|
363
|
+
if (clip.events)
|
|
364
|
+
baked.events = clip.events.map((e) => ({ ...e }));
|
|
365
|
+
return baked;
|
|
366
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Root motion: split the root node's travel out of a clip so the character animates in place
|
|
3
|
+
* while the game moves its transform by the extracted motion, without guessing at speeds.
|
|
4
|
+
*
|
|
5
|
+
* `extractRootMotion` returns two clips sharing keyframe times: `clip` (in place: the root keeps
|
|
6
|
+
* its first-frame translation and yaw) and `motion` (the root's translation relative to the
|
|
7
|
+
* first frame and its yaw about +Y relative to the first frame). At every keyframe
|
|
8
|
+
* `motion + clip` (translation) and `motion · clip` (rotation) equal the original root transform.
|
|
9
|
+
* `applyRootMotionDelta` samples `motion` at two times and gives the game a position delta in the
|
|
10
|
+
* root's own heading frame plus a yaw delta, handling the loop wrap. Yaw is about +Y (Y up).
|
|
11
|
+
*/
|
|
12
|
+
import { type AnimationClip } from './clip.js';
|
|
13
|
+
export interface RootMotionOptions {
|
|
14
|
+
/**
|
|
15
|
+
* `true`: only the horizontal translation (x, z) moves to `motion`; height and rotation stay in
|
|
16
|
+
* the clip (a hop stays a hop). `false` (default): the whole translation and the yaw about +Y.
|
|
17
|
+
*/
|
|
18
|
+
planar?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface RootMotionSplit {
|
|
21
|
+
/** The clip with its root held in place (first-frame translation and yaw). */
|
|
22
|
+
clip: AnimationClip;
|
|
23
|
+
/** The root's travel, relative to the first frame: a translation and, unless planar, a yaw. */
|
|
24
|
+
motion: AnimationClip;
|
|
25
|
+
}
|
|
26
|
+
/** `[dx, dy, dz, yaw]`: a position delta in the root's heading frame at `t0`, and a yaw delta. */
|
|
27
|
+
export type RootMotionDelta = Float32Array;
|
|
28
|
+
/**
|
|
29
|
+
* Split `clip` into an in-place clip and a motion clip for `rootNode`. Channels are copied, never
|
|
30
|
+
* aliased; the two clips share keyframe times with the input. Translation keeps `CUBICSPLINE`
|
|
31
|
+
* tangents (the in-place side's extracted components get zero tangents); a `CUBICSPLINE`
|
|
32
|
+
* rotation channel on the root comes back as two `LINEAR` channels over its key values. Clips
|
|
33
|
+
* with no root channel yield an empty `motion`. Allocates; call at load time.
|
|
34
|
+
*/
|
|
35
|
+
export declare function extractRootMotion(clip: AnimationClip, rootNode: number, opts?: RootMotionOptions): RootMotionSplit;
|
|
36
|
+
/**
|
|
37
|
+
* The root's motion between `t0` and `t1` of a `motion` clip, into `outDelta` (4 floats):
|
|
38
|
+
* `[dx, dy, dz]` is the position delta expressed in the root's heading frame at `t0` (the motion
|
|
39
|
+
* clip's yaw there, zero at the first key: rotate the delta by the character's own heading, then
|
|
40
|
+
* add it to the position) and `[3]` is the yaw delta in radians about +Y (add it to the
|
|
41
|
+
* heading). When `t1 < t0` the clip has looped: the
|
|
42
|
+
* delta runs `t0 → duration` then `0 → t1`. Returns `outDelta`. No allocation.
|
|
43
|
+
*/
|
|
44
|
+
export declare function applyRootMotionDelta(motionClip: AnimationClip, t0: number, t1: number, outDelta: Float32Array): Float32Array;
|