cozyclay 2.1.1 → 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 +60 -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 +3 -3
- 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-msLI71g1.js → first-shot-handoff-CC4xe4HM.js} +1 -1
- package/dist/assets/{landing-ChUvB_zL.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/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 +150 -2624
- 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 +42 -413
- 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/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 +9 -51
- 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/TopBar.jsx +5 -84
- package/src/shell/ViewportToolbar.jsx +10 -70
- 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/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 +19 -16
- package/src/studio-agent-motion.js +9 -9
- package/src/studio-agent-protocol.js +41 -71
- package/src/studio-app-binding.js +25 -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/knip-baseline.json +0 -179
- package/tools/loc-baseline.json +31 -81
- 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 +8 -124
- package/bin/agent/motion-runtime.mjs +0 -76
- package/dist/ardy/cskel27-rest.json +0 -557
- package/dist/assets/analytics-C9pMpW7s.js +0 -1
- package/dist/assets/app-B_2XB9rw.css +0 -1
- package/dist/assets/app-DAuvKPP8.js +0 -4920
- package/dist/assets/config-Bx7pYsD9.js +0 -1
- package/dist/assets/config-DeoFTYzb.css +0 -1
- package/dist/assets/demo-CvKuBgy5.js +0 -1
- package/dist/assets/scene-asset-sync-DKkpjKBV.js +0 -19
- package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
- package/dist/assets/ticket-BPk2Ni95.js +0 -1
- package/dist/assets/workflow-jJRBR94Z.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 -182
- 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/root-drop.js
DELETED
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
import { sliceMotion } from "./trim.js";
|
|
2
|
-
|
|
3
|
-
// A vertical drop authored ONTO a take. ARDY generates motion on flat
|
|
4
|
-
// ground — nothing in a generated clip can carry a body off a 14 m roof.
|
|
5
|
-
// The plunge is previs staging, not motion synthesis, so it is applied to
|
|
6
|
-
// the decoded clip as a rigid vertical offset: every joint of a frame moves
|
|
7
|
-
// down by the same amount, and the amount follows a gravity curve.
|
|
8
|
-
//
|
|
9
|
-
// Seconds, not frames: a take crosses two clocks on its way in (ARDY's
|
|
10
|
-
// 20 fps, the 24 fps production timeline), and a boundary in seconds means
|
|
11
|
-
// the caller never has to know which side of the retime it is speaking to.
|
|
12
|
-
|
|
13
|
-
/** Validated {fromS, toS, meters} or null — malformed input is no drop. */
|
|
14
|
-
export function normalizeRootDrop(drop) {
|
|
15
|
-
if (!drop || typeof drop !== "object" || Array.isArray(drop)) return null;
|
|
16
|
-
const fromS = Number(drop.fromS ?? drop.from_s);
|
|
17
|
-
const toS = Number(drop.toS ?? drop.to_s);
|
|
18
|
-
const meters = Number(drop.meters);
|
|
19
|
-
if (!Number.isFinite(fromS) || !Number.isFinite(toS) || !Number.isFinite(meters)) return null;
|
|
20
|
-
if (fromS < 0 || toS <= fromS || meters <= 0) return null;
|
|
21
|
-
return { fromS, toS, meters };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** Point-in-footprint on the floor plane, honouring the support's yaw. */
|
|
25
|
-
function insideSupport(support, px, pz) {
|
|
26
|
-
const yaw = ((support.rotDeg ?? 0) * Math.PI) / 180;
|
|
27
|
-
const cos = Math.cos(yaw);
|
|
28
|
-
const sin = Math.sin(yaw);
|
|
29
|
-
const dx = px - support.x;
|
|
30
|
-
const dz = pz - support.z;
|
|
31
|
-
const lx = cos * dx - sin * dz;
|
|
32
|
-
const lz = sin * dx + cos * dz;
|
|
33
|
-
return Math.abs(lx) <= support.width / 2 && Math.abs(lz) <= support.depth / 2;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const SUPPORT_FEET = [21, 22, 25, 26];
|
|
37
|
-
const smoothstep = (value) => {
|
|
38
|
-
const t = Math.max(0, Math.min(1, value));
|
|
39
|
-
return t * t * (3 - 2 * t);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Lift a take onto an explicitly authored scene surface. ARDY clips are
|
|
44
|
-
* normally rooted on the deck, so a performer climbing onto a prop needs a
|
|
45
|
-
* small, time-continuous offset while their root is inside that prop's
|
|
46
|
-
* footprint. We require a real upward root trend before applying anything;
|
|
47
|
-
* a flat walk through a prop therefore stays untouched.
|
|
48
|
-
*
|
|
49
|
-
* `supports` are world-space rectangles with an explicit `supportY` (the top
|
|
50
|
-
* of the surface). `subjectX/Y/Z` supply the character's scene anchor and
|
|
51
|
-
* `worldScale` converts canonical clip units to scene metres, matching the
|
|
52
|
-
* transform used by `autoRoofDrop`. The input motion is never mutated. The
|
|
53
|
-
* returned object carries `surfaceRise` diagnostics.
|
|
54
|
-
*/
|
|
55
|
-
export function applySupportRise(
|
|
56
|
-
motion,
|
|
57
|
-
supports,
|
|
58
|
-
{ subjectX = 0, subjectY = 0, subjectZ = 0, rotationDeg = 0, minRise = 0.08, minSlope = 0.04, lookbackFrames = 6, blendFrames = 6, maxOffset = 1.5, worldScale = 1 } = {},
|
|
59
|
-
) {
|
|
60
|
-
if (!motion || !Number.isFinite(motion.fps) || motion.fps <= 0 || !motion.rootPos || !motion.posedJoints) return motion;
|
|
61
|
-
const frames = Number(motion.frames);
|
|
62
|
-
if (!Number.isInteger(frames) || frames < 2 || motion.rootPos.length < frames * 3) return motion;
|
|
63
|
-
const joints = motion.posedJoints.length / (frames * 3);
|
|
64
|
-
if (!Number.isInteger(joints) || joints <= 0) return motion;
|
|
65
|
-
const scale = Number.isFinite(Number(worldScale)) && Number(worldScale) > 0 ? Number(worldScale) : 1;
|
|
66
|
-
if (!Array.isArray(supports) || !supports.length) return motion;
|
|
67
|
-
const candidates = supports.filter((support) =>
|
|
68
|
-
support && Number.isFinite(Number(support.supportY)) && Number(support.width) > 0 && Number(support.depth) > 0,
|
|
69
|
-
);
|
|
70
|
-
if (!candidates.length) return motion;
|
|
71
|
-
const radians = (Number(rotationDeg) || 0) * Math.PI / 180;
|
|
72
|
-
const cos = Math.cos(radians), sin = Math.sin(radians);
|
|
73
|
-
const worldAt = (frame) => {
|
|
74
|
-
const dx = motion.rootPos[frame * 3] - motion.rootPos[0];
|
|
75
|
-
const dz = motion.rootPos[frame * 3 + 2] - motion.rootPos[2];
|
|
76
|
-
return { x: Number(subjectX) + (dx * cos + dz * sin) * scale, z: Number(subjectZ) + (-dx * sin + dz * cos) * scale };
|
|
77
|
-
};
|
|
78
|
-
const points = Array.from({ length: frames }, (_, frame) => worldAt(frame));
|
|
79
|
-
const feet = SUPPORT_FEET.filter((joint) => joint < joints);
|
|
80
|
-
const footWorldAt = (frame, joint) => {
|
|
81
|
-
const p = (frame * joints + joint) * 3;
|
|
82
|
-
// posedJoints and rootPos are both frame-local; subtract the root from
|
|
83
|
-
// the same frame before rotating into world space. Using frame zero here
|
|
84
|
-
// made a walking foot drift with the accumulated root travel and caused
|
|
85
|
-
// support detection to miss later chair/platform contacts.
|
|
86
|
-
const dx = motion.posedJoints[p] - motion.rootPos[frame * 3];
|
|
87
|
-
const dz = motion.posedJoints[p + 2] - motion.rootPos[frame * 3 + 2];
|
|
88
|
-
return { x: Number(subjectX) + (dx * cos + dz * sin) * scale, z: Number(subjectZ) + (-dx * sin + dz * cos) * scale };
|
|
89
|
-
};
|
|
90
|
-
const inside = candidates.map((support) => points.map((point, frame) => insideSupport({
|
|
91
|
-
x: Number(support.x) || 0, z: Number(support.z) || 0,
|
|
92
|
-
rotDeg: Number(support.rotDeg) || 0, width: Number(support.width), depth: Number(support.depth),
|
|
93
|
-
}, point.x, point.z) || feet.some((joint) => {
|
|
94
|
-
const foot = footWorldAt(frame, joint);
|
|
95
|
-
return insideSupport({
|
|
96
|
-
x: Number(support.x) || 0, z: Number(support.z) || 0,
|
|
97
|
-
rotDeg: Number(support.rotDeg) || 0, width: Number(support.width), depth: Number(support.depth),
|
|
98
|
-
}, foot.x, foot.z);
|
|
99
|
-
})));
|
|
100
|
-
let selected = null;
|
|
101
|
-
for (let si = 0; si < candidates.length; si += 1) {
|
|
102
|
-
const support = candidates[si];
|
|
103
|
-
// A performer often enters a prop's footprint before lifting a foot
|
|
104
|
-
// (approach, brace, then climb). Search the first second of continuous
|
|
105
|
-
// support occupancy instead of requiring the rise on the boundary frame.
|
|
106
|
-
let entry = -1;
|
|
107
|
-
for (let frame = 0; frame < frames; frame += 1) {
|
|
108
|
-
if (!inside[si][frame]) { entry = -1; continue; }
|
|
109
|
-
// A take can begin already standing on a platform. Treat frame 0 as
|
|
110
|
-
// an entry so the same evidence search handles both approaches and
|
|
111
|
-
// starts-on-support clips.
|
|
112
|
-
if (entry < 0 && (frame === 0 || !inside[si][frame - 1])) entry = frame;
|
|
113
|
-
if (entry < 0 || frame - entry > Math.round(motion.fps)) continue;
|
|
114
|
-
const from = Math.max(0, frame - Math.max(1, Math.round(lookbackFrames)));
|
|
115
|
-
// A foot can enter the footprint one or two frames before the body
|
|
116
|
-
// commits to the climb. Look a short distance ahead, while retaining
|
|
117
|
-
// the entry frame as the point where the blend begins.
|
|
118
|
-
const evidenceFrame = Math.min(frames - 1, frame + Math.max(1, Math.round(lookbackFrames)));
|
|
119
|
-
const rise = (motion.rootPos[evidenceFrame * 3 + 1] - motion.rootPos[from * 3 + 1]) * scale;
|
|
120
|
-
const slope = rise / ((evidenceFrame - from) / motion.fps);
|
|
121
|
-
if (rise < Number(minRise) || slope < Number(minSlope)) continue;
|
|
122
|
-
if (!feet.length) continue;
|
|
123
|
-
const supportRect = {
|
|
124
|
-
x: Number(support.x) || 0, z: Number(support.z) || 0,
|
|
125
|
-
rotDeg: Number(support.rotDeg) || 0, width: Number(support.width), depth: Number(support.depth),
|
|
126
|
-
};
|
|
127
|
-
const occupiedYs = [];
|
|
128
|
-
for (let probe = evidenceFrame; probe < frames && inside[si][probe] && probe <= evidenceFrame + Math.round(motion.fps * 0.75); probe += 1) {
|
|
129
|
-
// A climb often straddles the deck and the prop: one foot remains
|
|
130
|
-
// on the floor while the other is already on the seat. Measuring the
|
|
131
|
-
// minimum of *all* feet therefore used the deck foot as the seat
|
|
132
|
-
// datum and left the climbing foot below the authored support. Use
|
|
133
|
-
// only feet whose XZ footprint is actually on this support.
|
|
134
|
-
const onSupport = feet.filter((joint) => {
|
|
135
|
-
const foot = footWorldAt(probe, joint);
|
|
136
|
-
return insideSupport(supportRect, foot.x, foot.z);
|
|
137
|
-
});
|
|
138
|
-
// Root occupancy is valid evidence while the pelvis is over a support
|
|
139
|
-
// but the feet have not entered its rectangle yet. In that phase keep
|
|
140
|
-
// the legacy all-foot fallback; once a foot is actually on the support,
|
|
141
|
-
// use only those feet so a deck foot cannot set the seat datum.
|
|
142
|
-
const ys = (onSupport.length ? onSupport : feet)
|
|
143
|
-
.map((joint) => motion.posedJoints[(probe * joints + joint) * 3 + 1] * scale).filter(Number.isFinite);
|
|
144
|
-
// If a second foot is still on the deck but its footprint overlaps
|
|
145
|
-
// the prop edge, the lower sample is not the seat contact. The upper
|
|
146
|
-
// supported foot is the conservative datum; when both feet are on
|
|
147
|
-
// the same surface their heights agree.
|
|
148
|
-
if (ys.length) occupiedYs.push(Math.max(...ys));
|
|
149
|
-
}
|
|
150
|
-
occupiedYs.sort((a, b) => a - b);
|
|
151
|
-
const observedFootY = occupiedYs[Math.floor(occupiedYs.length * 0.7)];
|
|
152
|
-
const onSupportAtEvidence = feet.filter((joint) => {
|
|
153
|
-
const foot = footWorldAt(evidenceFrame, joint);
|
|
154
|
-
return insideSupport(supportRect, foot.x, foot.z);
|
|
155
|
-
});
|
|
156
|
-
const footYs = (onSupportAtEvidence.length ? onSupportAtEvidence : feet)
|
|
157
|
-
.map((joint) => motion.posedJoints[(evidenceFrame * joints + joint) * 3 + 1] * scale).filter(Number.isFinite);
|
|
158
|
-
if (!footYs.length) continue;
|
|
159
|
-
const baseY = Number(subjectY) || 0;
|
|
160
|
-
const offsetWorld = Number(support.supportY) - (baseY + (Number.isFinite(observedFootY) ? observedFootY : Math.min(...footYs)));
|
|
161
|
-
if (!(offsetWorld > 0.01) || offsetWorld > Number(maxOffset)) continue;
|
|
162
|
-
selected = {
|
|
163
|
-
si,
|
|
164
|
-
frame,
|
|
165
|
-
support,
|
|
166
|
-
offset: offsetWorld / scale,
|
|
167
|
-
offsetWorld,
|
|
168
|
-
rise,
|
|
169
|
-
slope,
|
|
170
|
-
baseRootY: motion.rootPos[from * 3 + 1],
|
|
171
|
-
};
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
if (selected) break;
|
|
175
|
-
}
|
|
176
|
-
if (!selected) return motion;
|
|
177
|
-
const { si, frame: enter, offset, offsetWorld, support, rise, slope, baseRootY } = selected;
|
|
178
|
-
let exit = frames - 1;
|
|
179
|
-
for (let frame = enter + 1; frame < frames; frame += 1) {
|
|
180
|
-
if (!inside[si][frame]) { exit = frame; break; }
|
|
181
|
-
}
|
|
182
|
-
// Some shots climb and then step down while the root remains inside a
|
|
183
|
-
// generous footprint (a chair turn, a platform landing, or a jump in
|
|
184
|
-
// place). Release the lift when the root has come back near its pre-climb
|
|
185
|
-
// level; otherwise the rigid support offset would leave the performer
|
|
186
|
-
// floating even though the take has visibly descended.
|
|
187
|
-
let release = exit;
|
|
188
|
-
const descendThreshold = Math.max(Number(minRise), 0.08);
|
|
189
|
-
let peakRootY = motion.rootPos[enter * 3 + 1];
|
|
190
|
-
for (let frame = enter + 1; frame <= exit; frame += 1) {
|
|
191
|
-
peakRootY = Math.max(peakRootY, motion.rootPos[frame * 3 + 1]);
|
|
192
|
-
const current = motion.rootPos[frame * 3 + 1];
|
|
193
|
-
if (peakRootY - current >= descendThreshold && current <= baseRootY + descendThreshold * 0.5) {
|
|
194
|
-
release = frame;
|
|
195
|
-
break;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
const blend = Math.max(1, Math.round(blendFrames));
|
|
199
|
-
const offsets = new Float32Array(frames);
|
|
200
|
-
for (let frame = enter; frame < frames; frame += 1) {
|
|
201
|
-
const up = smoothstep((frame - enter + 1) / blend);
|
|
202
|
-
const down = release < frames - 1 ? smoothstep((release - frame) / blend) : 1;
|
|
203
|
-
offsets[frame] = offset * Math.min(up, down);
|
|
204
|
-
}
|
|
205
|
-
const rootPos = Float32Array.from(motion.rootPos);
|
|
206
|
-
const posedJoints = Float32Array.from(motion.posedJoints);
|
|
207
|
-
const jointCount = Math.round(posedJoints.length / frames / 3);
|
|
208
|
-
for (let frame = 0; frame < frames; frame += 1) {
|
|
209
|
-
const dy = offsets[frame];
|
|
210
|
-
if (!dy) continue;
|
|
211
|
-
rootPos[frame * 3 + 1] += dy;
|
|
212
|
-
for (let joint = 0; joint < jointCount; joint += 1) posedJoints[(frame * jointCount + joint) * 3 + 1] += dy;
|
|
213
|
-
}
|
|
214
|
-
return {
|
|
215
|
-
...motion,
|
|
216
|
-
rootPos,
|
|
217
|
-
posedJoints,
|
|
218
|
-
surfaceRise: { applied: true, supportY: Number(support.supportY), offset, offsetWorld, worldScale: scale, enterFrame: enter, exitFrame: exit, releaseFrame: release, rise, slope },
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Stage a fall the author did not have to ask for: a character standing on a
|
|
224
|
-
* raised support (a roof — place_character's y) whose take walks past the
|
|
225
|
-
* support's edge should drop, because ARDY only generates flat-ground motion.
|
|
226
|
-
*
|
|
227
|
-
* `subject` is { x, z, y, rotationDeg } — the character's blocking, with the
|
|
228
|
-
* take's root rotation. `supports` are world-space tops: { x, z, rotDeg,
|
|
229
|
-
* topY, width, depth }. The walk is sampled with the same root convention
|
|
230
|
-
* playback uses (frame-zero anchored, yaw-rotated into scene space).
|
|
231
|
-
*
|
|
232
|
-
* Returns a { fromS, toS, meters } drop, or null when the character is on
|
|
233
|
-
* the ground, never stood on a support, or never leaves it — null means
|
|
234
|
-
* "stage nothing", so this is safe to leave on the load path.
|
|
235
|
-
*/
|
|
236
|
-
export function autoRoofDrop(motion, subject, supports, { gravity = 9.81, topTolerance = 0.3, fallTimeScale = 1.15, worldScale = 1 } = {}) {
|
|
237
|
-
if (!motion || !Number.isFinite(motion.fps) || motion.fps <= 0 || !motion.rootPos) return null;
|
|
238
|
-
const frames = motion.frames;
|
|
239
|
-
if (!Number.isFinite(frames) || frames < 2) return null;
|
|
240
|
-
const y = Number(subject?.y) || 0;
|
|
241
|
-
if (y <= 0.05 || !Array.isArray(supports) || supports.length === 0) return null;
|
|
242
|
-
const scale = Number.isFinite(Number(worldScale)) && Number(worldScale) > 0 ? Number(worldScale) : 1;
|
|
243
|
-
|
|
244
|
-
const radians = ((Number.isFinite(subject.rotationDeg) ? subject.rotationDeg : 0) * Math.PI) / 180;
|
|
245
|
-
const cos = Math.cos(radians);
|
|
246
|
-
const sin = Math.sin(radians);
|
|
247
|
-
const worldAt = (frame) => {
|
|
248
|
-
const dx = motion.rootPos[frame * 3] - motion.rootPos[0];
|
|
249
|
-
const dz = motion.rootPos[frame * 3 + 2] - motion.rootPos[2];
|
|
250
|
-
return {
|
|
251
|
-
x: subject.x + (dx * cos + dz * sin) * scale,
|
|
252
|
-
z: subject.z + (-dx * sin + dz * cos) * scale,
|
|
253
|
-
};
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
const start = worldAt(0);
|
|
257
|
-
const carriers = supports.filter((support) =>
|
|
258
|
-
support.width > 0 && support.depth > 0 &&
|
|
259
|
-
Math.abs(support.topY - y) <= topTolerance &&
|
|
260
|
-
insideSupport(support, start.x, start.z));
|
|
261
|
-
if (carriers.length === 0) return null;
|
|
262
|
-
|
|
263
|
-
for (let frame = 1; frame < frames; frame += 1) {
|
|
264
|
-
const point = worldAt(frame);
|
|
265
|
-
if (carriers.some((support) => insideSupport(support, point.x, point.z))) continue;
|
|
266
|
-
// Land on the tallest lower support under the exit point, else the street.
|
|
267
|
-
const landing = supports.reduce((top, support) =>
|
|
268
|
-
support.topY < y - topTolerance && support.topY > top && insideSupport(support, point.x, point.z)
|
|
269
|
-
? support.topY
|
|
270
|
-
: top, 0);
|
|
271
|
-
const meters = y - landing;
|
|
272
|
-
if (meters <= 0) return null;
|
|
273
|
-
const fromS = frame / motion.fps;
|
|
274
|
-
// Near-real gravity: a lightly stretched clock keeps weight without
|
|
275
|
-
// drifting into moon-fall. The readability comes from applyAutoFall's
|
|
276
|
-
// ballistic arc and impact cut, not from slowing the clock down.
|
|
277
|
-
return { fromS, toS: fromS + Math.sqrt((2 * meters) / gravity) * fallTimeScale, meters };
|
|
278
|
-
}
|
|
279
|
-
return null;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Bake an auto-staged fall so it reads like a stunt, not a glitch:
|
|
284
|
-
* - past the edge the root leaves the authored walk path and flies a true
|
|
285
|
-
* ballistic arc — the exit velocity carries, gravity owns the vertical;
|
|
286
|
-
* - the horizontal drift stops at impact (bodies do not keep strolling);
|
|
287
|
-
* - the take is cut just after the landing, because whatever the flat-ground
|
|
288
|
-
* clip does next (walking away twelve metres underground-level) is comedy.
|
|
289
|
-
* Explicit MCP drops keep the rigid applyRootDrop bake below.
|
|
290
|
-
*/
|
|
291
|
-
export function applyAutoFall(motion, spec, { landHoldS = 0.35, launchLookbackS = 0.15, worldScale = 1 } = {}) {
|
|
292
|
-
if (!spec || !motion || !Number.isFinite(motion.fps) || motion.fps <= 0) return motion;
|
|
293
|
-
const fps = motion.fps;
|
|
294
|
-
const scale = Number.isFinite(Number(worldScale)) && Number(worldScale) > 0 ? Number(worldScale) : 1;
|
|
295
|
-
const fExit = Math.max(0, Math.round(spec.fromS * fps));
|
|
296
|
-
if (fExit >= motion.frames - 1) return motion;
|
|
297
|
-
const fallS = Math.max(spec.toS - spec.fromS, 1 / fps);
|
|
298
|
-
const joints = Math.round(motion.posedJoints.length / motion.frames / 3);
|
|
299
|
-
const rootPos = Float32Array.from(motion.rootPos);
|
|
300
|
-
const posedJoints = Float32Array.from(motion.posedJoints);
|
|
301
|
-
const lookback = Math.max(1, Math.round(launchLookbackS * fps));
|
|
302
|
-
const f0 = Math.max(0, fExit - lookback);
|
|
303
|
-
const span = Math.max(1, fExit - f0);
|
|
304
|
-
const vx = ((rootPos[fExit * 3] - rootPos[f0 * 3]) / span) * fps;
|
|
305
|
-
const vz = ((rootPos[fExit * 3 + 2] - rootPos[f0 * 3 + 2]) / span) * fps;
|
|
306
|
-
const exitX = rootPos[fExit * 3];
|
|
307
|
-
const exitZ = rootPos[fExit * 3 + 2];
|
|
308
|
-
const fLand = Math.min(motion.frames - 1, Math.ceil(spec.toS * fps));
|
|
309
|
-
for (let f = fExit + 1; f < motion.frames; f += 1) {
|
|
310
|
-
const t = (f - fExit) / fps;
|
|
311
|
-
const progress = Math.min(t / fallS, 1);
|
|
312
|
-
const air = Math.min(t, fallS);
|
|
313
|
-
const dy = -(spec.meters / scale) * progress * progress;
|
|
314
|
-
const dx = exitX + vx * air - rootPos[f * 3];
|
|
315
|
-
const dz = exitZ + vz * air - rootPos[f * 3 + 2];
|
|
316
|
-
rootPos[f * 3] += dx;
|
|
317
|
-
rootPos[f * 3 + 1] += dy;
|
|
318
|
-
rootPos[f * 3 + 2] += dz;
|
|
319
|
-
for (let j = 0; j < joints; j += 1) {
|
|
320
|
-
const base = (f * joints + j) * 3;
|
|
321
|
-
posedJoints[base] += dx;
|
|
322
|
-
posedJoints[base + 1] += dy;
|
|
323
|
-
posedJoints[base + 2] += dz;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
const rotMats = Float32Array.from(motion.rotMats);
|
|
327
|
-
for (let f = fLand + 1; f < motion.frames; f += 1) {
|
|
328
|
-
rootPos.set(rootPos.subarray(fLand * 3, fLand * 3 + 3), f * 3);
|
|
329
|
-
posedJoints.set(
|
|
330
|
-
posedJoints.subarray(fLand * joints * 3, (fLand + 1) * joints * 3),
|
|
331
|
-
f * joints * 3,
|
|
332
|
-
);
|
|
333
|
-
rotMats.set(
|
|
334
|
-
rotMats.subarray(fLand * joints * 9, (fLand + 1) * joints * 9),
|
|
335
|
-
f * joints * 9,
|
|
336
|
-
);
|
|
337
|
-
}
|
|
338
|
-
const baked = { ...motion, rootPos, posedJoints, rotMats };
|
|
339
|
-
const fEnd = Math.min(motion.frames - 1, Math.ceil((spec.toS + landHoldS) * fps));
|
|
340
|
-
return fEnd < motion.frames - 1 ? sliceMotion(baked, 0, fEnd) : baked;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* The clip with the drop applied. The input clip is never mutated — the
|
|
345
|
-
* caller may hold it as a trim source — and an invalid drop returns the
|
|
346
|
-
* clip untouched, so this is safe to leave on the load path unconditionally.
|
|
347
|
-
*
|
|
348
|
-
* The curve is t² (uniform acceleration): a body leaving a roof gathers
|
|
349
|
-
* speed, and an eased-both-ends fall reads as a elevator, not gravity.
|
|
350
|
-
*/
|
|
351
|
-
export function applyRootDrop(motion, drop, { worldScale = 1 } = {}) {
|
|
352
|
-
const spec = normalizeRootDrop(drop);
|
|
353
|
-
if (!spec || !motion || !Number.isFinite(motion.fps) || motion.fps <= 0) return motion;
|
|
354
|
-
const scale = Number.isFinite(Number(worldScale)) && Number(worldScale) > 0 ? Number(worldScale) : 1;
|
|
355
|
-
const frames = motion.frames;
|
|
356
|
-
if (!Number.isFinite(frames) || frames <= 0) return motion;
|
|
357
|
-
|
|
358
|
-
const posedJoints = Float32Array.from(motion.posedJoints);
|
|
359
|
-
const rootPos = Float32Array.from(motion.rootPos);
|
|
360
|
-
const joints = Math.round(posedJoints.length / frames / 3);
|
|
361
|
-
for (let f = 0; f < frames; f += 1) {
|
|
362
|
-
const t = Math.min(Math.max((f / motion.fps - spec.fromS) / (spec.toS - spec.fromS), 0), 1);
|
|
363
|
-
if (t === 0) continue;
|
|
364
|
-
const dy = -(spec.meters / scale) * t * t;
|
|
365
|
-
for (let j = 0; j < joints; j += 1) posedJoints[(f * joints + j) * 3 + 1] += dy;
|
|
366
|
-
rootPos[f * 3 + 1] += dy;
|
|
367
|
-
}
|
|
368
|
-
return { ...motion, posedJoints, rootPos };
|
|
369
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { TIMELINE_FRAME_FPS } from "../scenes.js";
|
|
2
|
-
|
|
3
|
-
const PROMPT_BLOCK_FRAMES = 2 * TIMELINE_FRAME_FPS;
|
|
4
|
-
const PROMPT_RESIZE_BLOCK_PX = 120; // one deliberate drag step = one prompt block
|
|
5
|
-
|
|
6
|
-
/** Resize from the immutable pointer-down frame. Keeping both the frame and
|
|
7
|
-
* pixel origin fixed prevents a growing timeline from feeding its new frame
|
|
8
|
-
* count back into the next pointermove and exploding exponentially. */
|
|
9
|
-
export function promptResizeFrame(startFrame, startClientX, clientX) {
|
|
10
|
-
const blocks = (clientX - startClientX) / PROMPT_RESIZE_BLOCK_PX;
|
|
11
|
-
const blockDelta = Math.sign(blocks) * Math.round(Math.abs(blocks));
|
|
12
|
-
return startFrame + blockDelta * PROMPT_BLOCK_FRAMES;
|
|
13
|
-
}
|
package/src/ardy/to-cskel27.js
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CozyClayPoseV1 -> the two npz arrays cclay_constrained_generate.load_poses
|
|
3
|
-
* reads (local_rot_mats 27x3x3, posed_joints 27x3; the generator then runs its
|
|
4
|
-
* own FK, consulting only posed_joints[0] as the root).
|
|
5
|
-
*
|
|
6
|
-
* The 19 joints CozyClay authors map through each Mixamo bone's armature-space
|
|
7
|
-
* rest rotation Rb (cskel27-rest.json): L = Rb @ basis @ Rb^T. ARDY has four
|
|
8
|
-
* torso segments where Mixamo has three, so Mixamo Spine/Spine1 target ARDY
|
|
9
|
-
* Spine1/Spine2, matching playback's map. The remaining joints get identity;
|
|
10
|
-
* `filled_identity` records them and `rotation_constraint_indices` identifies
|
|
11
|
-
* the rotations that are genuinely authored.
|
|
12
|
-
*
|
|
13
|
-
* Proportions are never hardcoded: bone offsets come from the reference frame
|
|
14
|
-
* of the same base clip the pose will constrain (mirroring
|
|
15
|
-
* motion_constraints.derive_bone_offsets), and the root rides on that frame's
|
|
16
|
-
* own root. If ARDY ever reproportions cskel27, the clip proportions stay
|
|
17
|
-
* correct by construction.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import {
|
|
21
|
-
COZYCLAY_BONES,
|
|
22
|
-
COZYCLAY_TO_CSKEL27,
|
|
23
|
-
CSKEL27_JOINTS,
|
|
24
|
-
} from "./cskel27.js";
|
|
25
|
-
import { CSKEL27_NEUTRAL } from "./cskel27-neutral.js";
|
|
26
|
-
import {
|
|
27
|
-
basisQuaternionToLocalRotation,
|
|
28
|
-
deriveBoneOffsets,
|
|
29
|
-
forwardKinematics,
|
|
30
|
-
} from "./convert.js";
|
|
31
|
-
|
|
32
|
-
// Tolerance on |norm - 1| for pose quaternions, and on orthonormality /
|
|
33
|
-
// determinant for emitted matrices. Float32-serialized source data is off by
|
|
34
|
-
// ~1e-7 at worst, so 1e-6 is comfortably above input noise while still
|
|
35
|
-
// catching real corruption.
|
|
36
|
-
const UNIT_TOLERANCE = 1e-6;
|
|
37
|
-
|
|
38
|
-
const IDENTITY = [
|
|
39
|
-
[1, 0, 0],
|
|
40
|
-
[0, 1, 0],
|
|
41
|
-
[0, 0, 1],
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
const SOURCE_BY_TARGET = new Map(
|
|
45
|
-
COZYCLAY_BONES.map((source) => [
|
|
46
|
-
CSKEL27_JOINTS[COZYCLAY_TO_CSKEL27[source]],
|
|
47
|
-
source,
|
|
48
|
-
])
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
const CANONICAL_ROOT_Y = -Math.min(...CSKEL27_NEUTRAL.map((joint) => joint[1]));
|
|
52
|
-
|
|
53
|
-
/** Floor-aligned CoreSkeleton27 reference used when no clip reference is
|
|
54
|
-
* supplied. A generated motion is not a skeleton definition: borrowing its
|
|
55
|
-
* frame-zero root made a rolling clip lower every authored pose by 10 cm.
|
|
56
|
-
* The neutral skeleton is stable, deterministic, and keeps both toes at Y=0. */
|
|
57
|
-
export function canonicalCskel27Reference() {
|
|
58
|
-
return {
|
|
59
|
-
local_rot_mats: CSKEL27_JOINTS.map(() => IDENTITY.map((row) => row.slice())),
|
|
60
|
-
posed_joints: CSKEL27_NEUTRAL.map(([x, y, z]) => [x, y + CANONICAL_ROOT_Y, z]),
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function isFiniteNumber(value) {
|
|
65
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function determinant3(m) {
|
|
69
|
-
return (
|
|
70
|
-
m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
|
|
71
|
-
m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) +
|
|
72
|
-
m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0])
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function requireUnitQuaternion(q, bone) {
|
|
77
|
-
if (!Array.isArray(q) || q.length !== 4 || !q.every(isFiniteNumber)) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
`poseToCskel27: bone "${bone}" is not a [w, x, y, z] quaternion of four finite numbers`
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
const norm = Math.hypot(q[0], q[1], q[2], q[3]);
|
|
83
|
-
if (Math.abs(norm - 1) > UNIT_TOLERANCE) {
|
|
84
|
-
throw new Error(
|
|
85
|
-
`poseToCskel27: bone "${bone}" is not a unit quaternion (norm ${norm})`
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// A matrix must stay inside the rotation group: rows orthonormal (unit
|
|
91
|
-
// length, pairwise orthogonal) and right-handed.
|
|
92
|
-
function requireRotationMatrix(m, label) {
|
|
93
|
-
for (let i = 0; i < 3; i += 1) {
|
|
94
|
-
const row = m[i];
|
|
95
|
-
const normSq = row[0] * row[0] + row[1] * row[1] + row[2] * row[2];
|
|
96
|
-
if (Math.abs(normSq - 1) > UNIT_TOLERANCE) {
|
|
97
|
-
throw new Error(
|
|
98
|
-
`poseToCskel27: ${label} is not orthonormal (row ${i} has squared length ${normSq})`
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
for (let j = i + 1; j < 3; j += 1) {
|
|
102
|
-
const other = m[j];
|
|
103
|
-
const dot = row[0] * other[0] + row[1] * other[1] + row[2] * other[2];
|
|
104
|
-
if (Math.abs(dot) > UNIT_TOLERANCE) {
|
|
105
|
-
throw new Error(
|
|
106
|
-
`poseToCskel27: ${label} is not orthonormal (rows ${i} and ${j} dot to ${dot})`
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const det = determinant3(m);
|
|
112
|
-
if (Math.abs(det - 1) > UNIT_TOLERANCE) {
|
|
113
|
-
throw new Error(`poseToCskel27: ${label} has determinant ${det}, not +1`);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Convert a CozyClayPoseV1 into the frame arrays the ARDY generator expects.
|
|
119
|
-
* `rest` is the parsed public/ardy/cskel27-rest.json, `reference` a parsed
|
|
120
|
-
* ardy.frame.v1 fixture from the base motion the pose will constrain.
|
|
121
|
-
* Returns { local_rot_mats, posed_joints, filled_identity }.
|
|
122
|
-
*/
|
|
123
|
-
export function poseToCskel27({ pose, rest, reference }) {
|
|
124
|
-
if (!pose || typeof pose !== "object") {
|
|
125
|
-
throw new Error(
|
|
126
|
-
`poseToCskel27: pose is ${pose === null ? "null" : typeof pose}, expected an object`
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
if (pose.schema !== "cozyclay.pose.v1") {
|
|
130
|
-
throw new Error(
|
|
131
|
-
`poseToCskel27: unsupported pose schema ${JSON.stringify(pose.schema)} — expected "cozyclay.pose.v1"`
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
if (!pose.bones || typeof pose.bones !== "object" || Array.isArray(pose.bones)) {
|
|
135
|
-
throw new Error("poseToCskel27: pose.bones must be an object keyed by mixamo bone name");
|
|
136
|
-
}
|
|
137
|
-
if (pose.root !== undefined) {
|
|
138
|
-
if (!Array.isArray(pose.root) || pose.root.length !== 3 || !pose.root.every(isFiniteNumber)) {
|
|
139
|
-
throw new Error("poseToCskel27: pose.root must be [x, y, z] finite metres when present");
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
for (const bone of COZYCLAY_BONES) {
|
|
144
|
-
if (!(bone in pose.bones)) {
|
|
145
|
-
throw new Error(`poseToCskel27: pose.bones is missing "${bone}"`);
|
|
146
|
-
}
|
|
147
|
-
requireUnitQuaternion(pose.bones[bone], bone);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (!rest || !Array.isArray(rest.joints)) {
|
|
151
|
-
throw new Error("poseToCskel27: rest must be parsed cskel27-rest.json with a joints array");
|
|
152
|
-
}
|
|
153
|
-
const restByJoint = new Map();
|
|
154
|
-
for (const entry of rest.joints) {
|
|
155
|
-
if (!entry || typeof entry.name !== "string") {
|
|
156
|
-
throw new Error("poseToCskel27: rest.joints entries must carry a string name");
|
|
157
|
-
}
|
|
158
|
-
if (entry.rest !== null) {
|
|
159
|
-
if (
|
|
160
|
-
!Array.isArray(entry.rest) ||
|
|
161
|
-
entry.rest.length !== 3 ||
|
|
162
|
-
!entry.rest.every(
|
|
163
|
-
(row) => Array.isArray(row) && row.length === 3 && row.every(isFiniteNumber)
|
|
164
|
-
)
|
|
165
|
-
) {
|
|
166
|
-
throw new Error(
|
|
167
|
-
`poseToCskel27: rest for "${entry.name}" is neither null nor a 3x3 finite matrix`
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
restByJoint.set(entry.name, entry.rest);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const local_rot_mats = new Array(CSKEL27_JOINTS.length);
|
|
175
|
-
const filled_identity = [];
|
|
176
|
-
const rotation_constraint_indices = [];
|
|
177
|
-
for (let index = 0; index < CSKEL27_JOINTS.length; index += 1) {
|
|
178
|
-
const name = CSKEL27_JOINTS[index];
|
|
179
|
-
const sourceName = SOURCE_BY_TARGET.get(name);
|
|
180
|
-
const rb = sourceName ? restByJoint.get(sourceName) : null;
|
|
181
|
-
if (sourceName && rb !== null && rb !== undefined) {
|
|
182
|
-
// L = Rb @ basis @ Rb^T; basisQuaternionToLocalRotation is the
|
|
183
|
-
// quatToMat + basisToLocal composition from convert.js.
|
|
184
|
-
local_rot_mats[index] = basisQuaternionToLocalRotation(
|
|
185
|
-
pose.bones[sourceName],
|
|
186
|
-
rb
|
|
187
|
-
);
|
|
188
|
-
rotation_constraint_indices.push(index);
|
|
189
|
-
} else {
|
|
190
|
-
// Fresh identity per joint so callers can never alias a shared
|
|
191
|
-
// constant by mutating one row.
|
|
192
|
-
local_rot_mats[index] = IDENTITY.map((row) => row.slice());
|
|
193
|
-
filled_identity.push({
|
|
194
|
-
joint: name,
|
|
195
|
-
reason: sourceName ? "no rest rotation" : "not authored",
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
for (let index = 0; index < CSKEL27_JOINTS.length; index += 1) {
|
|
201
|
-
requireRotationMatrix(
|
|
202
|
-
local_rot_mats[index],
|
|
203
|
-
`${CSKEL27_JOINTS[index]} (local_rot_mats[${index}])`
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// A reference may still supply different skeleton proportions, but its
|
|
208
|
-
// frame-zero root is never copied. Placement is authored explicitly in
|
|
209
|
-
// pose.root; otherwise the canonical floor-aligned neutral root is used.
|
|
210
|
-
// This decouples body shape from whichever motion happened to be selected.
|
|
211
|
-
const skeleton = reference ?? canonicalCskel27Reference();
|
|
212
|
-
if (!Array.isArray(skeleton.posed_joints) || !Array.isArray(skeleton.local_rot_mats)) {
|
|
213
|
-
throw new Error("poseToCskel27: reference must carry posed_joints and local_rot_mats");
|
|
214
|
-
}
|
|
215
|
-
const offsets = deriveBoneOffsets(skeleton.posed_joints, skeleton.local_rot_mats);
|
|
216
|
-
const canonicalRoot = canonicalCskel27Reference().posed_joints[0];
|
|
217
|
-
const posed_joints = forwardKinematics(local_rot_mats, offsets, pose.root ?? canonicalRoot);
|
|
218
|
-
|
|
219
|
-
return {
|
|
220
|
-
local_rot_mats,
|
|
221
|
-
posed_joints,
|
|
222
|
-
filled_identity,
|
|
223
|
-
rotation_constraint_indices,
|
|
224
|
-
};
|
|
225
|
-
}
|
package/src/ardy/trim.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// trim.js — cut a loaded take to a frame range. The slice is a NEW motion
|
|
2
|
-
// object in the exact npz-decoded shape; the caller keeps the original, so
|
|
3
|
-
// trimming is non-destructive and re-trimming always cuts from the full
|
|
4
|
-
// take. Frame 0 of the slice becomes the playback anchor: applyMotionFrame
|
|
5
|
-
// re-anchors X/Z on the anchor frame, so a mid-clip cut plays at the
|
|
6
|
-
// character's placement instead of teleporting to the original frame 0.
|
|
7
|
-
// The spread carries every non-array field with the slice — `personScale`
|
|
8
|
-
// included: a cut is the same performer, and a take that lost its stature
|
|
9
|
-
// mid-edit would replay the remaining frames at the wrong stride length.
|
|
10
|
-
|
|
11
|
-
import { CSKEL27_JOINTS } from "./cskel27.js";
|
|
12
|
-
|
|
13
|
-
export function sliceMotion(motion, startFrame, endFrame) {
|
|
14
|
-
if (!motion || !Number.isInteger(motion.frames) || motion.frames < 1) {
|
|
15
|
-
throw new Error("sliceMotion: motion.frames must be a positive integer");
|
|
16
|
-
}
|
|
17
|
-
if (!Number.isInteger(startFrame) || !Number.isInteger(endFrame)) {
|
|
18
|
-
throw new Error("sliceMotion: startFrame and endFrame must be integers");
|
|
19
|
-
}
|
|
20
|
-
if (startFrame < 0 || endFrame >= motion.frames || startFrame > endFrame) {
|
|
21
|
-
throw new Error(`sliceMotion: range ${startFrame}..${endFrame} is outside 0..${motion.frames - 1}`);
|
|
22
|
-
}
|
|
23
|
-
const joints = CSKEL27_JOINTS.length;
|
|
24
|
-
const frames = endFrame - startFrame + 1;
|
|
25
|
-
return {
|
|
26
|
-
...motion,
|
|
27
|
-
frames,
|
|
28
|
-
rotMats: motion.rotMats.slice(startFrame * joints * 9, (endFrame + 1) * joints * 9),
|
|
29
|
-
rootPos: motion.rootPos.slice(startFrame * 3, (endFrame + 1) * 3),
|
|
30
|
-
posedJoints: motion.posedJoints.slice(startFrame * joints * 3, (endFrame + 1) * joints * 3),
|
|
31
|
-
anchorFrame: 0,
|
|
32
|
-
};
|
|
33
|
-
}
|