cozyclay 2.1.0 → 3.0.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 +65 -0
- package/README.md +12 -30
- package/bin/agent/agent-routes.mjs +40 -113
- package/bin/agent/agent-runner.mjs +9 -10
- package/bin/agent/cliproxy-provider.mjs +135 -0
- package/bin/agent/credential-store.mjs +30 -7
- package/bin/agent/pi-tools.mjs +4 -1
- package/bin/agent/provider-keys.mjs +32 -0
- package/bin/agent/provider-login.mjs +110 -0
- package/bin/agent/provider-routes.mjs +99 -0
- package/bin/agent/providers.mjs +19 -97
- package/bin/agent/script-tool.mjs +17 -4
- package/bin/agent/studio-motion-reference.mjs +23 -0
- package/bin/agent/studio-prompt.mjs +1 -1
- package/bin/agent/studio-rebase-text.mjs +32 -0
- package/bin/agent/studio-rebase.mjs +26 -39
- package/bin/agent/studio-tools.mjs +9 -28
- package/bin/agent/tool-arguments.mjs +49 -0
- package/bin/agent/turn-frames.mjs +66 -0
- package/bin/codex-auth.mjs +9 -2
- package/bin/cozyclay.mjs +10 -116
- package/bin/live/cli.mjs +22 -6
- package/bin/mcp-runtime.mjs +2 -12
- package/bin/package-signature.mjs +0 -4
- package/dist/app/index.html +7 -6
- package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
- package/dist/assets/analytics-C9sUnndd.js +1 -0
- package/dist/assets/app-CCh--1Hc.js +5087 -0
- package/dist/assets/app-f-fkV5uP.css +1 -0
- package/dist/assets/compile-worker-CkxiD6lH.js +5 -0
- package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
- package/dist/assets/{first-shot-handoff-BlT33CGf.js → first-shot-handoff-CC4xe4HM.js} +1 -1
- package/dist/assets/{landing-BSesrCpL.js → landing-DjHD8u7k.js} +1 -1
- package/dist/assets/scene-asset-sync-Hx_FzdOH.js +20 -0
- package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
- package/dist/assets/workflow-C4yKH1p4.js +179 -0
- package/dist/cozyclay-package.json +1 -1
- package/dist/index.html +3 -3
- package/dist/llms.txt +14 -0
- package/dist/sw.js +3 -6
- package/dist/workflow/index.html +5 -4
- package/mcp/LIVE-PROTOCOL.md +7 -47
- package/mcp/README.md +16 -26
- package/mcp/live-hub.mjs +6 -10
- package/mcp/package.json +1 -3
- package/mcp/tool-handlers.mjs +4 -168
- package/package.json +3 -22
- package/src/App.jsx +174 -2639
- package/src/agent-progress.js +79 -0
- package/src/agent-turn-mark.js +30 -0
- package/src/analytics.js +1 -19
- package/src/app-context.js +5 -0
- package/src/app-stage.jsx +2 -34
- package/src/asset-pane.jsx +6 -5
- package/src/camera-block.js +21 -0
- package/src/camera-direction.js +120 -0
- package/src/character-kind.js +3 -9
- package/src/command-bus.js +8 -6
- package/src/commands/cast.js +5 -34
- package/src/commands/elements/character.js +1 -1
- package/src/commands/elements/motion.js +1 -6
- package/src/commands/elements/object.js +6 -2
- package/src/commands/elements/shot.js +4 -1
- package/src/commands/elements.js +38 -14
- package/src/commands/index.js +3 -1
- package/src/commands/kits.js +37 -0
- package/src/commands/motion-timing.js +57 -0
- package/src/commands/motion.js +9 -152
- package/src/commands/motion3-compile.js +65 -0
- package/src/commands/motion3.js +207 -0
- package/src/commands/objects.js +6 -4
- package/src/commands/shot.js +49 -11
- package/src/commands/stage.js +14 -1
- package/src/commands/view.js +4 -1
- package/src/document-mirrors.js +42 -0
- package/src/document-store.js +4 -0
- package/src/domains/cast.js +19 -194
- package/src/domains/motion/motion-range-pin-rules.js +1 -1
- package/src/domains/motion/take-source.js +51 -0
- package/src/domains/motion.js +60 -1838
- package/src/domains/scenes.js +12 -55
- package/src/domains/shots.js +2 -2
- package/src/domains/stage.js +4 -2
- package/src/draft-ghost.js +46 -0
- package/src/draft-ghost.jsx +129 -0
- package/src/dualview.jsx +4 -3
- package/src/effects/EffectsLayer.jsx +112 -0
- package/src/effects/effect-meshes.js +232 -0
- package/src/effects/effect-record.js +103 -0
- package/src/effects/emitter.js +59 -0
- package/src/effects/simulate.js +261 -0
- package/src/effects/state.js +59 -0
- package/src/execution-telemetry.js +2 -3
- package/src/first-success-guide.jsx +5 -5
- package/src/ghost-set.js +257 -0
- package/src/held-object-edit.jsx +113 -0
- package/src/held-object-pose.js +175 -0
- package/src/hierarchy-model.js +1 -1
- package/src/hierarchy-panel.jsx +1 -1
- package/src/imported-mesh.jsx +103 -0
- package/src/kits/held.js +84 -0
- package/src/kits/index.js +70 -0
- package/src/kits/smoking.js +57 -0
- package/src/light-blockers.js +93 -0
- package/src/motion/beat-board-model.js +84 -0
- package/src/motion/beat-board.css +124 -0
- package/src/motion/beat-board.jsx +59 -0
- package/src/motion/center-of-mass.js +66 -0
- package/src/motion/fix-collisions.js +850 -0
- package/src/motion/physics-review.js +118 -0
- package/src/{ardy → motion}/physics-support.js +1 -76
- package/src/motion/rig-snapshot.js +22 -0
- package/src/motion/take-segments.jsx +140 -0
- package/src/{ardy → motion}/timeline-coordinates.js +0 -21
- package/src/{ardy → motion}/timeline.css +1 -2
- package/src/{ardy → motion}/timeline.jsx +48 -419
- package/src/motion/waypoints.js +76 -0
- package/src/motion3/beats.js +83 -0
- package/src/motion3/body.js +158 -0
- package/src/motion3/bones.js +47 -0
- package/src/motion3/carried.js +47 -0
- package/src/motion3/compile-job.js +75 -0
- package/src/motion3/compile-worker.js +10 -0
- package/src/motion3/compiler/anchors.js +105 -0
- package/src/motion3/compiler/arm-orient.js +128 -0
- package/src/motion3/compiler/channels.js +125 -0
- package/src/motion3/compiler/compile.js +205 -0
- package/src/motion3/compiler/gait-rhythm.js +97 -0
- package/src/motion3/compiler/grip.js +171 -0
- package/src/motion3/compiler/head-steady.js +48 -0
- package/src/motion3/compiler/hold.js +134 -0
- package/src/motion3/compiler/idle.js +113 -0
- package/src/motion3/compiler/limbs.js +170 -0
- package/src/motion3/compiler/math.js +72 -0
- package/src/motion3/compiler/pose.js +162 -0
- package/src/motion3/compiler/quat.js +49 -0
- package/src/motion3/compiler/skeleton.js +74 -0
- package/src/motion3/compiler/validate-common.js +32 -0
- package/src/motion3/compiler/validate-goals.js +118 -0
- package/src/motion3/compiler/validate-objects.js +143 -0
- package/src/motion3/compiler/validate-parts.js +116 -0
- package/src/motion3/compiler/validate.js +122 -0
- package/src/motion3/compiler/vocab.js +73 -0
- package/src/motion3/compiler/walk-pelvis.js +275 -0
- package/src/motion3/compiler/walk.js +207 -0
- package/src/motion3/compiler/wrist-clamp.js +32 -0
- package/src/motion3/delta.js +47 -0
- package/src/motion3/describe.js +174 -0
- package/src/motion3/docs.js +27 -0
- package/src/motion3/edit-carry.js +21 -0
- package/src/motion3/fix/ease.js +16 -0
- package/src/motion3/fix/ground.js +37 -0
- package/src/motion3/fix/index.js +52 -0
- package/src/motion3/fix/push.js +71 -0
- package/src/motion3/fix/reach.js +46 -0
- package/src/motion3/fix/retime.js +79 -0
- package/src/motion3/fix/self.js +211 -0
- package/src/motion3/fix/slide.js +70 -0
- package/src/motion3/fix/turn.js +51 -0
- package/src/motion3/follow.js +39 -0
- package/src/motion3/free-motion.js +173 -0
- package/src/motion3/grip-choice.js +130 -0
- package/src/motion3/hold-plan.js +157 -0
- package/src/motion3/json-patch.js +77 -0
- package/src/motion3/key-aim.js +105 -0
- package/src/motion3/key-edit.js +82 -0
- package/src/motion3/lenient.js +127 -0
- package/src/motion3/object-keys.js +236 -0
- package/src/motion3/object-pose.js +182 -0
- package/src/motion3/object-tracks.js +12 -0
- package/src/motion3/pipeline.js +102 -0
- package/src/motion3/playback.js +51 -0
- package/src/motion3/probes.js +91 -0
- package/src/motion3/qa/body-checks.js +34 -0
- package/src/motion3/qa/check-names.js +14 -0
- package/src/motion3/qa/checks.js +121 -0
- package/src/motion3/qa/contact-checks.js +51 -0
- package/src/motion3/qa/explain.js +80 -0
- package/src/motion3/qa/fmt.js +5 -0
- package/src/motion3/qa/foot-checks.js +72 -0
- package/src/motion3/qa/geometry.js +77 -0
- package/src/motion3/qa/goals.js +191 -0
- package/src/motion3/qa/ground.js +60 -0
- package/src/motion3/qa/hints-contact.js +179 -0
- package/src/motion3/qa/hints-goal.js +160 -0
- package/src/motion3/qa/hints-knee.js +24 -0
- package/src/motion3/qa/hints-motion.js +209 -0
- package/src/motion3/qa/hints-object.js +91 -0
- package/src/motion3/qa/index.js +42 -0
- package/src/motion3/qa/key-checks.js +82 -0
- package/src/motion3/qa/near.js +96 -0
- package/src/motion3/qa/object-checks.js +135 -0
- package/src/motion3/qa/patch.js +161 -0
- package/src/motion3/qa/severity.js +38 -0
- package/src/motion3/qa/spec-checks.js +65 -0
- package/src/motion3/qa/style.js +218 -0
- package/src/motion3/qa/wrist-checks.js +69 -0
- package/src/motion3/qa/wrist-obs.js +60 -0
- package/src/motion3/refs.js +120 -0
- package/src/motion3/repair-tune.js +121 -0
- package/src/motion3/repair.js +83 -0
- package/src/motion3/report.js +67 -0
- package/src/motion3/rigs/index.js +14 -0
- package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
- package/src/motion3/rigs/x-bot-tpose.json +1 -0
- package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
- package/src/motion3/rigs/y-bot-tpose.json +1 -0
- package/src/motion3/scene.js +60 -0
- package/src/motion3/schema/brief.js +89 -0
- package/src/motion3/schema/fields.js +44 -0
- package/src/motion3/schema/spec-examples.js +46 -0
- package/src/motion3/schema/topics.js +111 -0
- package/src/motion3/schema/types.js +147 -0
- package/src/motion3/search.js +117 -0
- package/src/motion3/second-hand.js +112 -0
- package/src/motion3/skills/basic.js +82 -0
- package/src/motion3/skills/book.js +76 -0
- package/src/motion3/skills/car.js +145 -0
- package/src/motion3/skills/frames-auto.js +29 -0
- package/src/motion3/skills/index.js +83 -0
- package/src/motion3/skills/info.js +65 -0
- package/src/motion3/skills/smoke-kit.js +109 -0
- package/src/motion3/skills/smoke.js +160 -0
- package/src/motion3/spec-store.js +59 -0
- package/src/motion3/take-edit.js +155 -0
- package/src/motion3/take.js +63 -0
- package/src/motion3/timeline.js +127 -0
- package/src/motion3/views.js +121 -0
- package/src/motion3/walk-plan.js +119 -0
- package/src/object-catalog.jsx +7 -1
- package/src/object-colors.js +98 -0
- package/src/object-gizmo-parts.js +115 -0
- package/src/object-gizmo.jsx +37 -122
- package/src/object-glow.js +139 -0
- package/src/object-hidden.js +33 -0
- package/src/object-look.js +196 -0
- package/src/object-size.js +10 -0
- package/src/object-travel.js +71 -6
- package/src/panels/CameraPanel.jsx +7 -7
- package/src/panels/HdrEnvironmentControls.jsx +59 -0
- package/src/panels/LightPanel.jsx +25 -4
- package/src/panels/ObjectLookPanel.jsx +88 -0
- package/src/panels/PoseImagePanel.jsx +1 -1
- package/src/panels/PosePanel.jsx +2 -17
- package/src/panels/RigControlPanel.jsx +5 -53
- package/src/panels/SubjectBox.jsx +4 -1
- package/src/panels/details.css +14 -0
- package/src/posestudio.jsx +4 -27
- package/src/project-browser.jsx +3 -4
- package/src/project-resources.js +18 -31
- package/src/project.js +13 -104
- package/src/props.jsx +25 -280
- package/src/rail-dot-drag.js +23 -0
- package/src/render-passes.js +10 -0
- package/src/resource-status.jsx +1 -0
- package/src/result-modal.jsx +4 -19
- package/src/room.jsx +20 -12
- package/src/scene-assets.js +8 -6
- package/src/scene-light-place.js +72 -0
- package/src/scene-lights.jsx +148 -0
- package/src/scene-objects.js +31 -139
- package/src/scenes.js +15 -105
- package/src/semantic-edit.js +2 -5
- package/src/set-pieces.jsx +183 -0
- package/src/settings-menu.jsx +3 -11
- package/src/shell/BottomDock.jsx +11 -53
- package/src/shell/CompositionGuideButton.jsx +20 -0
- package/src/shell/DetailsSlot.jsx +16 -200
- package/src/shell/GhostsMenuGroup.jsx +74 -0
- package/src/shell/LibrarySlot.jsx +1 -3
- package/src/shell/MenuBar.jsx +3 -3
- package/src/shell/PreferencesDialog.jsx +15 -264
- package/src/shell/PreferencesSlot.jsx +2 -8
- package/src/shell/ShotPreviewHeader.jsx +17 -0
- package/src/shell/TopBar.jsx +5 -83
- package/src/shell/ViewportToolbar.jsx +23 -93
- package/src/shell/agent-glass.css +19 -6
- package/src/shell/details-selection.js +42 -0
- package/src/shell/ghosts-menu.css +22 -0
- package/src/shell/glass-regions.css +29 -3
- package/src/shell/preferences.css +6 -1
- package/src/shell/viewport.css +12 -0
- package/src/shot-authoring.js +4 -7
- package/src/soft-shadows.js +37 -0
- package/src/stage-attach-frames.js +12 -12
- package/src/stage-canvas-rigs.jsx +3 -3
- package/src/stage-capture.jsx +42 -8
- package/src/stage-characters.jsx +22 -216
- package/src/stage-editor-gizmos.jsx +6 -6
- package/src/stage-environment.js +93 -0
- package/src/stage-hdr-builtins.js +107 -0
- package/src/stage-hdr-image.js +116 -0
- package/src/stage-hdr-library.js +70 -0
- package/src/stage-hdr-map.js +94 -0
- package/src/stage-hdr.js +130 -0
- package/src/stage-lighting.js +149 -0
- package/src/stage-occlusion.js +210 -0
- package/src/stage-sky.jsx +159 -0
- package/src/stage-startup-defaults.js +5 -9
- package/src/studio-actions.js +12 -14
- package/src/studio-agent-commands.js +46 -16
- package/src/studio-agent-motion.js +9 -9
- package/src/studio-agent-protocol.js +46 -73
- package/src/studio-app-binding.js +29 -45
- package/src/studio-asset-list.js +17 -0
- package/src/studio-contact-sheet.js +37 -5
- package/src/studio-elements.js +27 -7
- package/src/studio-entity-bounds.js +18 -0
- package/src/studio-error-codes.js +8 -0
- package/src/studio-export-framing.js +152 -0
- package/src/studio-lighting-check.js +103 -0
- package/src/studio-motion-visual.js +150 -0
- package/src/studio-schema-errors.js +80 -0
- package/src/studio-support-gap.js +74 -0
- package/src/styles.css +1 -19
- package/src/timeline-defaults.js +5 -0
- package/src/timeline-extent.js +8 -20
- package/src/tutorial-walk.js +17 -0
- package/src/ui-scrub.js +1 -1
- package/src/use-shot-camera-tracks.js +12 -0
- package/src/view-ghosts.js +97 -0
- package/src/view-ghosts.jsx +49 -0
- package/src/workflow/AgentPanel.jsx +47 -166
- package/src/workflow/AgentProgressCard.jsx +107 -0
- package/src/workflow/AgentReplyText.jsx +37 -0
- package/src/workflow/AgentTurnSteps.jsx +84 -0
- package/src/workflow/LoginPanel.jsx +140 -0
- package/src/workflow/WorkflowBuilder.jsx +7 -23
- package/src/workflow/agent-client.js +54 -51
- package/src/workflow/agent-panel.css +71 -1
- package/src/workflow/agent-progress-card.css +167 -0
- package/src/workflow/agent-progress-view.js +47 -0
- package/src/workflow/agent-turn-steps.css +113 -0
- package/src/workflow/agent-turn.js +191 -0
- package/src/workflow/login-client.js +34 -0
- package/src/workflow/motion-input.js +18 -31
- package/src/workflow/node-schema.js +1 -1
- package/src/workflow/reply-markdown.js +69 -0
- package/src/workflow/scene-asset-sync.js +8 -8
- package/tools/agent-session-stats.mjs +61 -0
- package/tools/dev-full.mjs +5 -56
- package/tools/eslint-baseline.json +12 -13
- package/tools/headless-studio.mjs +85 -0
- package/tools/knip-baseline.json +0 -179
- package/tools/loc-baseline.json +33 -83
- package/tools/motion3/extract-body.mjs +103 -0
- package/tools/motion3/extract-rig.mjs +85 -0
- package/tools/process-supervisor.mjs +0 -88
- package/tools/run-tests.mjs +9 -124
- package/bin/agent/motion-runtime.mjs +0 -76
- package/dist/ardy/cskel27-rest.json +0 -557
- package/dist/assets/analytics-B41FmPYI.js +0 -1
- package/dist/assets/app-Do-Og5Pu.css +0 -1
- package/dist/assets/app-DwP-tl2x.js +0 -4920
- package/dist/assets/config-Bx7pYsD9.js +0 -1
- package/dist/assets/config-DeoFTYzb.css +0 -1
- package/dist/assets/demo-Dt0qZfS7.js +0 -1
- package/dist/assets/scene-asset-sync-BCWDJB1d.js +0 -19
- package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
- package/dist/assets/ticket-jqMhqL88.js +0 -1
- package/dist/assets/workflow-Br-K7Srs.js +0 -179
- package/dist/demo/walk-then-stop.npz +0 -0
- package/mcp/ardy-prompts.mjs +0 -218
- package/src/ardy/auto-fix-panel.css +0 -108
- package/src/ardy/auto-physics.js +0 -1194
- package/src/ardy/client.js +0 -153
- package/src/ardy/convert.js +0 -313
- package/src/ardy/cskel27-neutral.js +0 -39
- package/src/ardy/cskel27.js +0 -77
- package/src/ardy/export.js +0 -165
- package/src/ardy/fix-collisions.js +0 -2257
- package/src/ardy/foot-lock.js +0 -230
- package/src/ardy/motion-calibration.js +0 -118
- package/src/ardy/motion-edit.js +0 -213
- package/src/ardy/motion-url.js +0 -55
- package/src/ardy/mp4-duration.js +0 -102
- package/src/ardy/npz.js +0 -595
- package/src/ardy/physics-panel.css +0 -21
- package/src/ardy/physics-panel.jsx +0 -89
- package/src/ardy/physics-refine.js +0 -111
- package/src/ardy/physics-review.js +0 -567
- package/src/ardy/physics-temporal.js +0 -54
- package/src/ardy/platform-fit-panel.css +0 -64
- package/src/ardy/platform-fit-panel.jsx +0 -41
- package/src/ardy/platform-fit.js +0 -326
- package/src/ardy/playback.js +0 -711
- package/src/ardy/pose-pin.js +0 -97
- package/src/ardy/prompt-clips.js +0 -30
- package/src/ardy/retime.js +0 -211
- package/src/ardy/root-drop.js +0 -369
- package/src/ardy/timeline-resize.js +0 -13
- package/src/ardy/to-cskel27.js +0 -225
- package/src/ardy/trim.js +0 -33
- package/src/ardy/waypoints.js +0 -369
- package/src/ardy-bridge-contract.js +0 -281
- package/src/domains/motion/motion-video-capture.js +0 -664
- package/src/i2v-motion-client.js +0 -77
- package/src/i2v-motion-studio.jsx +0 -180
- package/src/line-edit.js +0 -1348
- package/src/motion/generation.js +0 -105
- package/src/motion-readiness-ui.jsx +0 -67
- package/src/motion-readiness.js +0 -40
- package/src/motion-resources.js +0 -177
- package/src/motion-store.js +0 -65
- package/src/motion-trail.js +0 -601
- package/src/multimodel-ingest.js +0 -394
- package/src/panels/PromptBlocksPanel.jsx +0 -444
- package/src/panels/VideoCapturePanel.jsx +0 -181
- package/src/pose-extract/browser.js +0 -42
- package/src/pose-extract/detector.js +0 -100
- package/src/pose-extract/fit.js +0 -227
- package/src/pose-extract/image-frame.js +0 -51
- package/src/pose-extract/index.js +0 -58
- package/src/pose-extract/keyframes.js +0 -74
- package/src/pose-extract/landmarks.js +0 -162
- package/src/pose-extract/mirror.js +0 -153
- package/src/pose-extract/take.js +0 -131
- package/src/pose-extract/video-frames.js +0 -91
- package/src/take-recipe.js +0 -165
- package/src/trail-key-conflicts.js +0 -39
- package/src/trail-pick.js +0 -59
- package/src/use-i2v-capture-modal.js +0 -15
- package/tools/ardy/BRIDGE.md +0 -37
- package/tools/ardy/GVHMR-NPZ.md +0 -68
- package/tools/ardy/README.md +0 -124
- package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
- package/tools/ardy/artifacts.mjs +0 -34
- package/tools/ardy/bridge.mjs +0 -1732
- package/tools/ardy/bvh-cskel27.mjs +0 -1265
- package/tools/ardy/cclay_constrained_generate.py +0 -561
- package/tools/ardy/cclay_gvhmr_worker.py +0 -264
- package/tools/ardy/cclay_motion_edit.py +0 -510
- package/tools/ardy/cclay_sequence_generate.py +0 -705
- package/tools/ardy/cclay_worker.py +0 -304
- package/tools/ardy/dump-npz.py +0 -205
- package/tools/ardy/extract-rest.mjs +0 -299
- package/tools/ardy/extract.mjs +0 -507
- package/tools/ardy/footage.mjs +0 -467
- package/tools/ardy/gvhmr-floor.mjs +0 -102
- package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
- package/tools/ardy/gvhmr_fastpath.py +0 -168
- package/tools/ardy/gvhmr_trajectory.py +0 -240
- package/tools/ardy/merge-text-encoder.py +0 -160
- package/tools/ardy/mocap-metrics.mjs +0 -200
- package/tools/ardy/mocap-quality-gate.mjs +0 -110
- package/tools/ardy/motion-stabilize.mjs +0 -348
- package/tools/ardy/npz.mjs +0 -414
- package/tools/ardy/pose-to-npz.mjs +0 -106
- package/tools/ardy/prompt-limits.mjs +0 -5
- package/tools/ardy/run-edit-on-box.sh +0 -73
- package/tools/ardy/run-local.mjs +0 -233
- package/tools/ardy/run-on-box.sh +0 -593
- package/tools/ardy/run-sequence-on-box.sh +0 -177
- package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
- package/tools/ardy/runners/index.mjs +0 -18
- package/tools/ardy/runners/local.mjs +0 -455
- package/tools/ardy/runners/proc.mjs +0 -125
- package/tools/ardy/runners/remote.mjs +0 -252
- package/tools/ardy/setup-local.mjs +0 -189
- package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
- package/tools/ardy/setup-text-encoder.py +0 -306
- package/tools/ardy/smpl-cskel27.mjs +0 -178
- package/tools/ardy/visual-qa.mjs +0 -196
- package/tools/ardy/vq-car.mjs +0 -52
- package/tools/bench/EXP3.md +0 -61
- package/tools/bench/cclay_bench_extract_incam.py +0 -125
- package/tools/bench/cclay_bench_extract_obs.py +0 -204
- package/tools/bench/cclay_bench_runner.py +0 -42
- package/tools/bench/cube-contact.mjs +0 -162
- package/tools/bench/exp3.mjs +0 -152
- package/tools/bench/extract-bench-lib.mjs +0 -216
- package/tools/bench/extract-bench.mjs +0 -302
- package/tools/bench/fal-generate.mjs +0 -88
- package/tools/bench/fit/README.md +0 -189
- package/tools/bench/fit/camera.mjs +0 -59
- package/tools/bench/fit/contact.mjs +0 -419
- package/tools/bench/fit/footlock.mjs +0 -234
- package/tools/bench/fit/motion.mjs +0 -85
- package/tools/bench/fit/pin.mjs +0 -27
- package/tools/bench/fit/remote.mjs +0 -105
- package/tools/bench/fit-bench.mjs +0 -126
- package/tools/bench/fit-sanity.mjs +0 -45
- package/tools/bench/metrics.mjs +0 -313
- package/tools/bench/obs/depth.mjs +0 -258
- package/tools/bench/obs/extrinsics.mjs +0 -175
- package/tools/bench/obs/fit_mannequin_betas.py +0 -340
- package/tools/bench/obs/ground.mjs +0 -294
- package/tools/bench/obs/heading.mjs +0 -151
- package/tools/bench/obs/ladder.mjs +0 -555
- package/tools/bench/obs/mannequin-betas.json +0 -124
- package/tools/bench/obs/remote.mjs +0 -83
- package/tools/bench/obs/rest_joints.py +0 -52
- package/tools/bench/obs/ybot-targets.mjs +0 -49
- package/tools/bench/obs-bench.mjs +0 -520
- package/tools/bench/score.mjs +0 -343
- package/tools/bench/summarize.mjs +0 -86
- package/tools/demo-worker/README.md +0 -137
- package/tools/demo-worker/api-client.mjs +0 -233
- package/tools/demo-worker/generate.mjs +0 -301
- package/tools/demo-worker/index.mjs +0 -466
- package/tools/demo-worker/sign-core.mjs +0 -112
- package/tools/demo-worker/sign.mjs +0 -161
- package/tools/gt-render/browser.mjs +0 -159
- package/tools/gt-render/camera-math.mjs +0 -276
- package/tools/gt-render/page.mjs +0 -267
- package/tools/gt-render/render.mjs +0 -514
- package/tools/gt-render/scene-box.mjs +0 -31
- package/tools/gt-render/take-transform.mjs +0 -87
- package/tools/kimodo/compare-seam.mjs +0 -108
- package/tools/kimodo/constraints.mjs +0 -244
- package/tools/kimodo/edit.mjs +0 -259
- package/tools/kimodo/effector-constraints.mjs +0 -200
- package/tools/kimodo/generate.mjs +0 -646
- package/tools/kimodo/local-output.mjs +0 -265
- package/tools/kimodo/measure-pose.mjs +0 -65
- package/tools/kimodo/measure-preserve.mjs +0 -899
- package/tools/kimodo/measure-waypoints.mjs +0 -55
- package/tools/kimodo/mlx-generate.py +0 -111
- package/tools/kimodo/pose-constraints.mjs +0 -248
- package/tools/kimodo/preserve-mask.mjs +0 -543
- package/tools/kimodo/read-npz.mjs +0 -189
- package/tools/kimodo/run-edit-on-box.mjs +0 -155
- package/tools/kimodo/run-sequence-on-box.mjs +0 -178
- package/tools/kimodo/runner.mjs +0 -284
- package/tools/kimodo/seam-batch.mjs +0 -77
- package/tools/kimodo/setup-local.mjs +0 -30
- package/tools/kimodo/setup-on-box.sh +0 -339
- package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
- package/tools/morphgs/assets/gen_truth.py +0 -39
- package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
- package/tools/morphgs/assets/playback-check.mjs +0 -30
- package/tools/morphgs/demo-gate.sh +0 -26
- package/tools/morphgs/fbx2morphgs.mjs +0 -68
- package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
- package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
- package/tools/morphgs/setup-on-cluster.sh +0 -126
- package/tools/projflow/driver.py +0 -1069
- package/tools/projflow/generate.mjs +0 -805
- package/tools/projflow/hml22-to-cskel27.mjs +0 -735
- package/tools/projflow/line-edit-job.mjs +0 -547
- package/tools/projflow/replay.mjs +0 -452
- package/tools/projflow/runner.mjs +0 -269
- package/tools/projflow/service.mjs +0 -742
- package/tools/track/DESIGN.md +0 -513
- package/tools/track/backfill-provenance.mjs +0 -116
- package/tools/track/budget.mjs +0 -8
- package/tools/track/check-rig.mjs +0 -209
- package/tools/track/diagnostics.schema.json +0 -60
- package/tools/track/export-rig.mjs +0 -256
- package/tools/track/fallback.mjs +0 -7
- package/tools/track/fk-parity-fixture.mjs +0 -161
- package/tools/track/gate.mjs +0 -349
- package/tools/track/masks.mjs +0 -318
- package/tools/track/metrics.mjs +0 -201
- package/tools/track/publish-obs.mjs +0 -108
- package/tools/track/py/check_env.py +0 -61
- package/tools/track/py/eval_lr.py +0 -229
- package/tools/track/py/lr_viterbi.py +0 -294
- package/tools/track/py/masks.py +0 -405
- package/tools/track/py/objective.py +0 -382
- package/tools/track/py/rig.py +0 -508
- package/tools/track/py/scene.py +0 -326
- package/tools/track/py/test_joint_indices.py +0 -123
- package/tools/track/py/test_lr_viterbi.py +0 -195
- package/tools/track/py/test_masks.py +0 -229
- package/tools/track/py/test_rig.py +0 -288
- package/tools/track/py/test_scene.py +0 -354
- package/tools/track/py/test_track.py +0 -328
- package/tools/track/py/track.py +0 -411
- package/tools/track/remote.mjs +0 -140
- package/tools/track/rig-dump.mjs +0 -227
- package/tools/track/run-box-tests.mjs +0 -14
- package/tools/track/run-box.mjs +0 -168
- package/tools/track/setup-box.sh +0 -59
- package/tools/track/study-2d.mjs +0 -728
- /package/src/{ardy → motion}/collision-blockers.js +0 -0
- /package/src/{ardy → motion}/ground.js +0 -0
- /package/src/{ardy → motion}/ik-drag.js +0 -0
- /package/src/{ardy → motion}/ik-key-json.js +0 -0
- /package/src/{ardy → motion}/ik.js +0 -0
- /package/src/{ardy → motion}/physics-surface.js +0 -0
- /package/src/{ardy → motion}/playback-clock.js +0 -0
- /package/src/{ardy → motion}/range-pin.js +0 -0
package/src/ardy/pose-pin.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Which frames a generation request pins, and why.
|
|
3
|
-
*
|
|
4
|
-
* The bridge has two modes and they are mutually exclusive. `posePin: true`
|
|
5
|
-
* sends full-body poses and runs the box's pose mode; `segments` (a prompt
|
|
6
|
-
* schedule) uses autoregressive history and demands `posePin: false`. Getting
|
|
7
|
-
* that wrong is a rejected request, so the decision is made here, once, as
|
|
8
|
-
* data — not spread across the call site where it cannot be tested.
|
|
9
|
-
*
|
|
10
|
-
* Pinning is deliberately NOT automatic for a loaded take. Pose mode builds on
|
|
11
|
-
* a fixed implicit reference base, so pinning a whole clip makes a new prompt
|
|
12
|
-
* dress up the same canned root path ("I changed the prompt but got the same
|
|
13
|
-
* walk"). The cases below are the ones where a pin is what the operator asked
|
|
14
|
-
* for:
|
|
15
|
-
*
|
|
16
|
-
* - `startFromPose` — the character's blocking pose is pinned at a chosen
|
|
17
|
-
* frame and the motion is generated around it. The frame is the operator's
|
|
18
|
-
* choice: the first frame to leave from, the last to arrive at, or any
|
|
19
|
-
* frame in between to pass through.
|
|
20
|
-
* - authored IK edits — corrections addressed to specific frames.
|
|
21
|
-
* - block edits — IK keys inside a scheduled block, addressed to that take.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/** Reasons a request ends up unpinned, so the caller can explain itself. */
|
|
25
|
-
export const PIN_BLOCKED = Object.freeze({
|
|
26
|
-
SCHEDULE: "prompt-schedule",
|
|
27
|
-
NOTHING_TO_PIN: "nothing-to-pin",
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @param {object} input
|
|
32
|
-
* @param {boolean} input.startFromPose operator asked to continue from the pose
|
|
33
|
-
* @param {boolean} input.hasPromptSchedule more than one prompt block
|
|
34
|
-
* @param {boolean} input.hasBlockEdits IK keys land inside scheduled blocks
|
|
35
|
-
* @param {boolean} input.waypointMode a root path is being authored
|
|
36
|
-
* @param {number[]} input.ikFrames timeline frames carrying authored IK keys
|
|
37
|
-
* @param {number} input.clipFrames the clip's length in timeline frames
|
|
38
|
-
* @param {{startFrame:number,endFrame:number}[]} input.segments
|
|
39
|
-
* @param {{startFrame:number,endFrame:number}[]} input.editedSegments
|
|
40
|
-
* @returns {{pin: boolean, frames: number[], blockedBy: string|null}}
|
|
41
|
-
*/
|
|
42
|
-
export function planPosePin({
|
|
43
|
-
startFromPose = false,
|
|
44
|
-
poseFrame = 0,
|
|
45
|
-
hasPromptSchedule = false,
|
|
46
|
-
hasBlockEdits = false,
|
|
47
|
-
waypointMode = false,
|
|
48
|
-
ikFrames = [],
|
|
49
|
-
clipFrames = 0,
|
|
50
|
-
segments = [],
|
|
51
|
-
editedSegments = [],
|
|
52
|
-
}) {
|
|
53
|
-
// The pin must land inside the clip the box is about to generate: an
|
|
54
|
-
// out-of-range destination is refused at the far end of the pipeline, so it
|
|
55
|
-
// is clamped here where the clip length is known.
|
|
56
|
-
const pinFrame = Math.max(0, Math.min(Math.max(0, clipFrames - 1), Math.round(poseFrame) || 0));
|
|
57
|
-
// A schedule cannot be pinned at all: the bridge refuses the combination,
|
|
58
|
-
// so an opted-in pose start has to be reported as blocked rather than
|
|
59
|
-
// silently dropped.
|
|
60
|
-
if (hasPromptSchedule && !hasBlockEdits) {
|
|
61
|
-
return {
|
|
62
|
-
pin: false,
|
|
63
|
-
frames: [],
|
|
64
|
-
blockedBy: startFromPose ? PIN_BLOCKED.SCHEDULE : PIN_BLOCKED.NOTHING_TO_PIN,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const wantsPin = hasBlockEdits || ikFrames.length > 0 || startFromPose;
|
|
69
|
-
if (!wantsPin) return { pin: false, frames: [], blockedBy: PIN_BLOCKED.NOTHING_TO_PIN };
|
|
70
|
-
|
|
71
|
-
// A root path is generated from frame 0 outward, so one pin at the start is
|
|
72
|
-
// the whole constraint — pinning later frames would fight the path.
|
|
73
|
-
if (waypointMode) return { pin: true, frames: [0], blockedBy: null };
|
|
74
|
-
|
|
75
|
-
if (hasBlockEdits) {
|
|
76
|
-
const frames = ikFrames.filter((frame) =>
|
|
77
|
-
editedSegments.some((segment) => frame >= segment.startFrame && frame < segment.endFrame)
|
|
78
|
-
);
|
|
79
|
-
return { pin: frames.length > 0, frames, blockedBy: frames.length > 0 ? null : PIN_BLOCKED.NOTHING_TO_PIN };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// A pose placement is exactly one constraint, at the chosen frame. Anything
|
|
83
|
-
// more would pin motion the operator never authored.
|
|
84
|
-
if (ikFrames.length === 0) return { pin: true, frames: [pinFrame], blockedBy: null };
|
|
85
|
-
|
|
86
|
-
const frames = [...new Set([
|
|
87
|
-
...(startFromPose ? [pinFrame] : []),
|
|
88
|
-
...segments.flatMap((segment) => [
|
|
89
|
-
segment.startFrame,
|
|
90
|
-
Math.min(segment.endFrame - 1, segment.startFrame + 1),
|
|
91
|
-
Math.max(segment.startFrame, segment.endFrame - 2),
|
|
92
|
-
segment.endFrame - 1,
|
|
93
|
-
]),
|
|
94
|
-
...ikFrames.filter((frame) => frame >= 0 && frame < clipFrames),
|
|
95
|
-
])].sort((a, b) => a - b);
|
|
96
|
-
return { pin: frames.length > 0, frames, blockedBy: null };
|
|
97
|
-
}
|
package/src/ardy/prompt-clips.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/** Move one prompt clip on the fixed prompt-block grid without changing its
|
|
2
|
-
* duration. Segment generation needs at most one prompt per frame range, so a
|
|
3
|
-
* snapped position that lands inside a neighbor clamps to abut that neighbor
|
|
4
|
-
* instead of overlapping; gaps remain valid and inherit the main prompt.
|
|
5
|
-
*
|
|
6
|
-
* Clock-agnostic: `blockFrames` is the caller's grid, and App.jsx always
|
|
7
|
-
* passes ARDY_PROMPT_HORIZON_FRAMES (2 s on the 24 fps timeline clock = 48).
|
|
8
|
-
* The 40 default is only the bare-call fallback and means nothing on the
|
|
9
|
-
* wire — nothing here ever reaches the bridge unconverted. */
|
|
10
|
-
export function movePromptClipFrames(clips, id, rawStartFrame, blockFrames = 40) {
|
|
11
|
-
const target = clips.find((clip) => clip.id === id);
|
|
12
|
-
if (!target) return clips;
|
|
13
|
-
const duration = target.endFrame - target.startFrame;
|
|
14
|
-
let startFrame = Math.max(0, Math.round(rawStartFrame / blockFrames) * blockFrames);
|
|
15
|
-
// Generated takes lay clips off the block grid (phase seconds are free-form),
|
|
16
|
-
// so every grid position near an off-grid neighbor can overlap it — the clip
|
|
17
|
-
// would refuse to move at all. Slide to touch the neighbor's nearest edge.
|
|
18
|
-
const others = clips.filter((clip) => clip.id !== id);
|
|
19
|
-
for (const clip of others) {
|
|
20
|
-
if (startFrame < clip.endFrame && startFrame + duration > clip.startFrame) {
|
|
21
|
-
const mid = (clip.startFrame + clip.endFrame) / 2;
|
|
22
|
-
startFrame = rawStartFrame + duration / 2 <= mid ? clip.startFrame - duration : clip.endFrame;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const endFrame = startFrame + duration;
|
|
26
|
-
if (startFrame < 0 || startFrame === target.startFrame) return clips;
|
|
27
|
-
const overlaps = others.some((clip) => startFrame < clip.endFrame && endFrame > clip.startFrame);
|
|
28
|
-
if (overlaps) return clips;
|
|
29
|
-
return clips.map((clip) => clip.id === id ? { ...clip, startFrame, endFrame } : clip);
|
|
30
|
-
}
|
package/src/ardy/retime.js
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
// retime.js — duration-preserving resample of a decoded motion between frame
|
|
2
|
-
// clocks. ARDY Core generates on its trained 20 fps clock, filmed takes arrive
|
|
3
|
-
// at 30 or 60; the app timeline runs the production 24 fps one. A 20 fps take
|
|
4
|
-
// counted against a 24 fps reference reads 1.2× fast, so inbound takes are
|
|
5
|
-
// resampled here: rotations slerp between neighbouring source frames, the root
|
|
6
|
-
// lerps, frame 0 stays identical, and the clip's length in seconds does not
|
|
7
|
-
// move — only how densely it is sampled.
|
|
8
|
-
//
|
|
9
|
-
// World joint positions are NOT interpolated. A slerped rotation walks the arc
|
|
10
|
-
// between two frames while a lerped position cuts the chord, so the two used to
|
|
11
|
-
// disagree at every blended frame — and since most 24 fps frames land between
|
|
12
|
-
// source frames, that disagreement was phase-locked to the resample (a 6 Hz
|
|
13
|
-
// pulse from 30 fps, alternating frames from 60). Playback drives bone.position
|
|
14
|
-
// straight from posedJoints, so on screen the shin visibly shortened by up to
|
|
15
|
-
// 2.6 cm and sprang back: the trembling feet. Positions are regenerated by
|
|
16
|
-
// forward kinematics from the retimed rotations instead, which makes constant
|
|
17
|
-
// bone length a property of the output rather than a hope.
|
|
18
|
-
|
|
19
|
-
import { CSKEL27_JOINTS } from "./cskel27.js";
|
|
20
|
-
import { deriveBoneOffsets, forwardKinematics, matToQuat, quatToMat } from "./convert.js";
|
|
21
|
-
import { canonicalCskel27Reference } from "./to-cskel27.js";
|
|
22
|
-
|
|
23
|
-
/** w-first quaternion slerp with hemisphere correction; falls back to a
|
|
24
|
-
* normalised lerp when the arc is too small for a stable sine. Shared with
|
|
25
|
-
* the bridge's BVH conversion (torso stabilization, root-spin repair). */
|
|
26
|
-
export function slerpQuat(a, b, t) {
|
|
27
|
-
let dot = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
|
|
28
|
-
const sign = dot < 0 ? -1 : 1;
|
|
29
|
-
dot *= sign;
|
|
30
|
-
let wa;
|
|
31
|
-
let wb;
|
|
32
|
-
if (dot > 0.9995) {
|
|
33
|
-
wa = 1 - t;
|
|
34
|
-
wb = t;
|
|
35
|
-
} else {
|
|
36
|
-
const theta = Math.acos(Math.min(1, dot));
|
|
37
|
-
const sinTheta = Math.sin(theta);
|
|
38
|
-
wa = Math.sin((1 - t) * theta) / sinTheta;
|
|
39
|
-
wb = Math.sin(t * theta) / sinTheta;
|
|
40
|
-
}
|
|
41
|
-
const out = [
|
|
42
|
-
a[0] * wa + b[0] * sign * wb,
|
|
43
|
-
a[1] * wa + b[1] * sign * wb,
|
|
44
|
-
a[2] * wa + b[2] * sign * wb,
|
|
45
|
-
a[3] * wa + b[3] * sign * wb,
|
|
46
|
-
];
|
|
47
|
-
const norm = Math.hypot(...out);
|
|
48
|
-
return out.map((component) => component / norm);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function readMat(flat, offset) {
|
|
52
|
-
return [
|
|
53
|
-
[flat[offset], flat[offset + 1], flat[offset + 2]],
|
|
54
|
-
[flat[offset + 3], flat[offset + 4], flat[offset + 5]],
|
|
55
|
-
[flat[offset + 6], flat[offset + 7], flat[offset + 8]],
|
|
56
|
-
];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function writeMat(flat, offset, m) {
|
|
60
|
-
flat[offset] = m[0][0]; flat[offset + 1] = m[0][1]; flat[offset + 2] = m[0][2];
|
|
61
|
-
flat[offset + 3] = m[1][0]; flat[offset + 4] = m[1][1]; flat[offset + 5] = m[1][2];
|
|
62
|
-
flat[offset + 6] = m[2][0]; flat[offset + 7] = m[2][1]; flat[offset + 8] = m[2][2];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const JOINTS = CSKEL27_JOINTS.length;
|
|
66
|
-
|
|
67
|
-
// Bone lengths are a property of the skeleton, not of the frame, so the offsets
|
|
68
|
-
// are derived once for the module rather than per take or per frame. Same
|
|
69
|
-
// pairing the BVH bridge uses (tools/ardy/bvh-cskel27.mjs): the canonical
|
|
70
|
-
// cskel27 reference, not a clip's frame zero, so a take whose first frame is
|
|
71
|
-
// noisy cannot smear its noise across the whole clip's proportions.
|
|
72
|
-
const BONE_OFFSETS = (() => {
|
|
73
|
-
const skeleton = canonicalCskel27Reference();
|
|
74
|
-
return deriveBoneOffsets(skeleton.posed_joints, skeleton.local_rot_mats);
|
|
75
|
-
})();
|
|
76
|
-
|
|
77
|
-
// Above this (in npz metres) a take's own posedJoints are not the forward
|
|
78
|
-
// kinematics of its own rotations, so regenerating them would move the take
|
|
79
|
-
// rather than repair it. Measured across every take in tools/ardy/out — filmed
|
|
80
|
-
// extractions and ARDY-generated clips alike — the residual is at most 1e-6 m,
|
|
81
|
-
// pure float32 serialization noise, so 1e-4 m sits 100x above the honest floor
|
|
82
|
-
// and far below any disagreement worth calling one.
|
|
83
|
-
const FK_CONSISTENCY_TOLERANCE = 1e-4;
|
|
84
|
-
|
|
85
|
-
// The 27 local rotations of one frame, as the nested matrices convert.js takes.
|
|
86
|
-
function readLocals(flat, frame) {
|
|
87
|
-
const locals = new Array(JOINTS);
|
|
88
|
-
for (let j = 0; j < JOINTS; j += 1) locals[j] = readMat(flat, (frame * JOINTS + j) * 9);
|
|
89
|
-
return locals;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Does this take's posedJoints already agree with FK of its own rotations?
|
|
94
|
-
* Sampled rather than exhaustive: an inconsistent take is inconsistent by
|
|
95
|
-
* construction (wrong proportions, hand-authored positions, a legacy writer),
|
|
96
|
-
* not on one unlucky frame, and the check must not cost a second FK sweep.
|
|
97
|
-
*/
|
|
98
|
-
function posedJointsFollowRotations(motion) {
|
|
99
|
-
const step = Math.max(1, Math.floor(motion.frames / 16));
|
|
100
|
-
for (let f = 0; f < motion.frames; f += step) {
|
|
101
|
-
const positions = forwardKinematics(
|
|
102
|
-
readLocals(motion.rotMats, f),
|
|
103
|
-
BONE_OFFSETS,
|
|
104
|
-
[motion.rootPos[f * 3], motion.rootPos[f * 3 + 1], motion.rootPos[f * 3 + 2]]
|
|
105
|
-
);
|
|
106
|
-
for (let j = 0; j < JOINTS; j += 1) {
|
|
107
|
-
const p = (f * JOINTS + j) * 3;
|
|
108
|
-
const dx = positions[j][0] - motion.posedJoints[p];
|
|
109
|
-
const dy = positions[j][1] - motion.posedJoints[p + 1];
|
|
110
|
-
const dz = positions[j][2] - motion.posedJoints[p + 2];
|
|
111
|
-
if (Math.hypot(dx, dy, dz) > FK_CONSISTENCY_TOLERANCE) return false;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Resample `{ frames, fps, rotMats, rootPos, posedJoints, ... }` onto
|
|
119
|
-
* `targetFps`. Every other field rides through untouched (`personScale`
|
|
120
|
-
* included — changing the sampling clock does not change how big the filmed
|
|
121
|
-
* performer was), except a present `anchorFrame`, which is rescaled onto the
|
|
122
|
-
* new clock. Same-rate input is
|
|
123
|
-
* returned as-is — retiming is never a copy for its own sake.
|
|
124
|
-
*
|
|
125
|
-
* `posedJoints` comes out of forward kinematics on the retimed rotations, so
|
|
126
|
-
* every bone keeps its length exactly. The one exception is a take whose own
|
|
127
|
-
* posedJoints do not already follow its own rotations: there the positions are
|
|
128
|
-
* the authority and FK would move the take rather than repair it, so those
|
|
129
|
-
* lerp between source frames as before. Nothing in tools/ardy/out is such a
|
|
130
|
-
* take; the branch exists so a legacy or hand-built one is not rewritten.
|
|
131
|
-
*/
|
|
132
|
-
export function retimeMotion(motion, targetFps) {
|
|
133
|
-
if (!motion || !Number.isFinite(motion.fps) || motion.fps <= 0) {
|
|
134
|
-
throw new Error("retimeMotion: motion.fps must be a positive finite number");
|
|
135
|
-
}
|
|
136
|
-
if (!Number.isFinite(targetFps) || targetFps <= 0) {
|
|
137
|
-
throw new Error("retimeMotion: targetFps must be a positive finite number");
|
|
138
|
-
}
|
|
139
|
-
if (motion.fps === targetFps) return motion;
|
|
140
|
-
const srcFrames = motion.frames;
|
|
141
|
-
if (!Number.isInteger(srcFrames) || srcFrames < 1) {
|
|
142
|
-
throw new Error("retimeMotion: motion.frames must be a positive integer");
|
|
143
|
-
}
|
|
144
|
-
const ratio = targetFps / motion.fps;
|
|
145
|
-
const frames = Math.max(1, Math.round(srcFrames * ratio));
|
|
146
|
-
const rotMats = new Float32Array(frames * JOINTS * 9);
|
|
147
|
-
const rootPos = new Float32Array(frames * 3);
|
|
148
|
-
const posedJoints = new Float32Array(frames * JOINTS * 3);
|
|
149
|
-
const regenerate = posedJointsFollowRotations(motion);
|
|
150
|
-
|
|
151
|
-
for (let f = 0; f < frames; f += 1) {
|
|
152
|
-
const s = f / ratio;
|
|
153
|
-
const i0 = Math.min(Math.floor(s), srcFrames - 1);
|
|
154
|
-
const i1 = Math.min(i0 + 1, srcFrames - 1);
|
|
155
|
-
const t = Math.min(Math.max(s - i0, 0), 1);
|
|
156
|
-
const exact = t === 0 || i0 === i1;
|
|
157
|
-
|
|
158
|
-
for (let j = 0; j < JOINTS; j += 1) {
|
|
159
|
-
const src0 = (i0 * JOINTS + j) * 9;
|
|
160
|
-
const dst = (f * JOINTS + j) * 9;
|
|
161
|
-
if (exact) {
|
|
162
|
-
for (let k = 0; k < 9; k += 1) rotMats[dst + k] = motion.rotMats[src0 + k];
|
|
163
|
-
} else {
|
|
164
|
-
const src1 = (i1 * JOINTS + j) * 9;
|
|
165
|
-
const q = slerpQuat(
|
|
166
|
-
matToQuat(readMat(motion.rotMats, src0)),
|
|
167
|
-
matToQuat(readMat(motion.rotMats, src1)),
|
|
168
|
-
t
|
|
169
|
-
);
|
|
170
|
-
writeMat(rotMats, dst, quatToMat(q));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
for (let axis = 0; axis < 3; axis += 1) {
|
|
174
|
-
rootPos[f * 3 + axis] =
|
|
175
|
-
motion.rootPos[i0 * 3 + axis] * (1 - t) + motion.rootPos[i1 * 3 + axis] * t;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (regenerate) {
|
|
179
|
-
// The root is the only position left in the interpolation; every joint
|
|
180
|
-
// below it is placed rigidly off the retimed rotations, which is what
|
|
181
|
-
// keeps bone lengths out of the blend entirely.
|
|
182
|
-
const positions = forwardKinematics(readLocals(rotMats, f), BONE_OFFSETS, [
|
|
183
|
-
rootPos[f * 3],
|
|
184
|
-
rootPos[f * 3 + 1],
|
|
185
|
-
rootPos[f * 3 + 2],
|
|
186
|
-
]);
|
|
187
|
-
for (let j = 0; j < JOINTS; j += 1) {
|
|
188
|
-
const pd = (f * JOINTS + j) * 3;
|
|
189
|
-
posedJoints[pd] = positions[j][0];
|
|
190
|
-
posedJoints[pd + 1] = positions[j][1];
|
|
191
|
-
posedJoints[pd + 2] = positions[j][2];
|
|
192
|
-
}
|
|
193
|
-
} else {
|
|
194
|
-
for (let j = 0; j < JOINTS; j += 1) {
|
|
195
|
-
const p0 = (i0 * JOINTS + j) * 3;
|
|
196
|
-
const p1 = (i1 * JOINTS + j) * 3;
|
|
197
|
-
const pd = (f * JOINTS + j) * 3;
|
|
198
|
-
for (let axis = 0; axis < 3; axis += 1) {
|
|
199
|
-
posedJoints[pd + axis] =
|
|
200
|
-
motion.posedJoints[p0 + axis] * (1 - t) + motion.posedJoints[p1 + axis] * t;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const retimed = { ...motion, frames, fps: targetFps, rotMats, rootPos, posedJoints };
|
|
207
|
-
if (Number.isFinite(motion.anchorFrame)) {
|
|
208
|
-
retimed.anchorFrame = Math.min(frames - 1, Math.round(motion.anchorFrame * ratio));
|
|
209
|
-
}
|
|
210
|
-
return retimed;
|
|
211
|
-
}
|