cozyclay 2.1.1 → 3.0.1
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 +88 -0
- package/README.md +12 -30
- package/bin/agent/agent-routes.mjs +43 -116
- package/bin/agent/agent-runner.mjs +14 -15
- 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/session-store.mjs +2 -2
- package/bin/agent/studio-context-budget.mjs +93 -0
- 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-BWCqdgWA.js +1 -0
- package/dist/assets/app-DfTCxaKk.js +5087 -0
- package/dist/assets/app-f-fkV5uP.css +1 -0
- package/dist/assets/compile-worker-BxKXh07s.js +5 -0
- package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
- package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-DNO8kv_N.js} +1 -1
- package/dist/assets/{landing-ChUvB_zL.js → landing-yfZaJkWc.js} +1 -1
- package/dist/assets/scene-asset-sync-U3kS2rvK.js +20 -0
- package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
- package/dist/assets/workflow-D78eiKTa.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 +151 -2625
- package/src/agent-progress.js +80 -0
- package/src/agent-turn-mark.js +30 -0
- package/src/analytics.js +1 -19
- package/src/app-context.js +12 -2
- 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 +10 -8
- 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 +214 -0
- package/src/commands/objects.js +6 -4
- package/src/commands/shot.js +55 -13
- 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 +53 -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 +47 -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 +60 -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 +79 -0
- package/src/motion3/compile-worker.js +10 -0
- package/src/motion3/compiler/anchors.js +113 -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 +197 -0
- package/src/motion3/compiler/math.js +72 -0
- package/src/motion3/compiler/pose.js +177 -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 +144 -0
- package/src/motion3/compiler/validate-parts.js +118 -0
- package/src/motion3/compiler/validate.js +122 -0
- package/src/motion3/compiler/vocab.js +74 -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 +177 -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 +204 -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/people.js +82 -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 +125 -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 +195 -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 +44 -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/people-checks.js +37 -0
- package/src/motion3/qa/severity.js +38 -0
- package/src/motion3/qa/spec-checks.js +65 -0
- package/src/motion3/qa/style.js +228 -0
- package/src/motion3/qa/wrist-checks.js +69 -0
- package/src/motion3/qa/wrist-obs.js +60 -0
- package/src/motion3/refs.js +129 -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 +113 -0
- package/src/motion3/schema/types.js +149 -0
- package/src/motion3/search.js +117 -0
- package/src/motion3/second-hand.js +112 -0
- package/src/motion3/settle.js +136 -0
- package/src/motion3/skills/basic.js +83 -0
- package/src/motion3/skills/book.js +76 -0
- package/src/motion3/skills/car.js +145 -0
- package/src/motion3/skills/flip.js +200 -0
- package/src/motion3/skills/frames-auto.js +29 -0
- package/src/motion3/skills/impact.js +109 -0
- package/src/motion3/skills/index.js +85 -0
- package/src/motion3/skills/info.js +80 -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/qa-label.js +25 -0
- 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 +16 -14
- package/src/studio-agent-commands.js +19 -16
- package/src/studio-agent-motion.js +9 -9
- package/src/studio-agent-protocol.js +47 -77
- package/src/studio-app-binding.js +27 -47
- 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 +15 -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 +109 -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 +9 -125
- 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
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
2
|
-
import { SUPPORT_SITES } from "./physics-review.js";
|
|
3
|
-
import { useMotionCommands } from '../domains/motion.js';
|
|
4
|
-
import "./physics-panel.css";
|
|
5
|
-
import { isImeComposing } from "../ime.js";
|
|
6
|
-
|
|
7
|
-
// Only the progress panel subscribes. Publishing a percentage must not
|
|
8
|
-
// rerender the full timeline/Studio hundreds of times during a solve.
|
|
9
|
-
export function createPhysicsProgress() {
|
|
10
|
-
let value = 0;
|
|
11
|
-
const listeners = new Set();
|
|
12
|
-
return { getSnapshot: () => value, subscribe: (listener) => { listeners.add(listener); return () => listeners.delete(listener); },
|
|
13
|
-
set: (next) => { if (next === value) return; value = next; for (const listener of listeners) listener(); } };
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function PhysicsPanel({ ko, disabled, running, progress: progressStore, preview, show, options, frame, frames, onOptions, onRun, onShow, onApply, onCancel, onFrame }) {
|
|
17
|
-
const { run } = useMotionCommands();
|
|
18
|
-
const progress = useSyncExternalStore(progressStore.subscribe, progressStore.getSnapshot);
|
|
19
|
-
const [site, setSite] = useState("leftFoot");
|
|
20
|
-
const [start, setStart] = useState(0), [end, setEnd] = useState(0), [mode, setMode] = useState("plant");
|
|
21
|
-
const name = (id) => { const s = SUPPORT_SITES.find((s) => s.id === id); return s ? ko(s.label, s.ko) : id; };
|
|
22
|
-
const set = (patch) => onOptions({ ...options, ...patch });
|
|
23
|
-
const add = () => {
|
|
24
|
-
const a = Math.max(0, Math.min(frames - 1, Math.round(Number(start) || 0)));
|
|
25
|
-
const b = Math.max(a, Math.min(frames - 1, Math.round(Number(end) || 0)));
|
|
26
|
-
set({ overrides: [...options.overrides, { site, start: a, end: b, mode }] });
|
|
27
|
-
};
|
|
28
|
-
const cm = (x) => `${(x * 100).toFixed(2)} cm`;
|
|
29
|
-
const warning = (r) => ({ unsupported: ko("Unexplained body support", "몸을 지탱하는 접촉 미확인"), floor: ko("Floor penetration", "바닥 관통"), float: ko("Contact floats", "접지점 뜸"), slide: ko("Contact drift", "접지점 밀림"), "knee-pop": ko("Knee speed jump", "무릎 튐"), "knee-acceleration": ko("Knee acceleration increased", "무릎 가속도 증가"), "root-acceleration": ko("Root acceleration increased", "골반 가속도 증가"), replay: ko("Playback mismatch", "재생 불일치") }[r] ?? r);
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
if (!preview) return undefined;
|
|
32
|
-
const onKeyDown = (event) => {
|
|
33
|
-
if (event.metaKey || event.ctrlKey || event.altKey) return;
|
|
34
|
-
if (event.key === "Escape") { event.preventDefault(); onCancel?.(); }
|
|
35
|
-
if (event.key === "Enter" && !isImeComposing(event)) { event.preventDefault(); onApply?.(); }
|
|
36
|
-
};
|
|
37
|
-
window.addEventListener("keydown", onKeyDown);
|
|
38
|
-
return () => window.removeEventListener("keydown", onKeyDown);
|
|
39
|
-
}, [preview, onApply, onCancel]);
|
|
40
|
-
return <section className="physics-review" data-testid="physics-panel" aria-label={ko("Physics cleanup", "물리 정리")}>
|
|
41
|
-
<h4>{ko("Physics cleanup", "물리 정리")} <small>{ko("review before applying", "확인 후 적용")}</small></h4>
|
|
42
|
-
<p className="inspector-hint">{ko("Floor-support hypotheses → force + moment check → pelvis + limbs. Flight is preserved; uncertain support stays flagged. Original stays unchanged until Apply.", "바닥 지지 후보 → 힘·회전 검사 → 골반·팔다리를 보정합니다. 비행은 보존하고, 불명확한 지지는 표시해요. 적용 전까지 원본은 바뀌지 않아요.")}</p>
|
|
43
|
-
<fieldset disabled={disabled || running}>
|
|
44
|
-
<label>{ko("Correction strength", "보정 강도")} <output>{Math.round(options.strength * 100)}%</output>
|
|
45
|
-
<input data-testid="physics-strength" type="range" min="0" max="100" step="10" value={options.strength * 100} onChange={(e) => set({ strength: Number(e.target.value) / 100 })} />
|
|
46
|
-
</label>
|
|
47
|
-
<details>
|
|
48
|
-
<summary>{ko("Contact overrides & protected poses", "접지 구간 지정 · 포즈 보호")}</summary>
|
|
49
|
-
<div className="physics-contact-editor">
|
|
50
|
-
<select aria-label={ko("Support point", "접지점")} value={site} onChange={(e) => setSite(e.target.value)}>{SUPPORT_SITES.map((s) => <option key={s.id} value={s.id}>{name(s.id)}</option>)}</select>
|
|
51
|
-
<select aria-label={ko("Contact mode", "접지 방식")} value={mode} onChange={(e) => setMode(e.target.value)}><option value="plant">{ko("Plant", "접지")}</option><option value="free">{ko("Free / moving", "해제 / 이동")}</option></select>
|
|
52
|
-
<input aria-label={ko("First frame", "시작 프레임")} type="number" min="0" max={frames - 1} value={start} onChange={(e) => setStart(e.target.value)} />
|
|
53
|
-
<input aria-label={ko("Last frame", "끝 프레임")} type="number" min="0" max={frames - 1} value={end} onChange={(e) => setEnd(e.target.value)} />
|
|
54
|
-
</div>
|
|
55
|
-
<div className="physics-actions"><button className="btn" onClick={() => { setStart(frame); setEnd(frame); }}>{ko("Use playhead", "현재 프레임")}</button><button data-testid="physics-add-contact" className="btn" onClick={add}>{ko("Add interval", "구간 추가")}</button></div>
|
|
56
|
-
{options.overrides.map((o, i) => <div className="physics-row" key={i}><span>{name(o.site)} · {o.start}–{o.end} · {o.mode === "plant" ? ko("Plant", "접지") : ko("Free", "해제")}</span><button className="btn" aria-label={ko("Remove interval", "구간 삭제")} onClick={() => set({ overrides: options.overrides.filter((_, j) => i !== j) })}>×</button></div>)}
|
|
57
|
-
<button data-testid="physics-protect" className="btn full" onClick={() => set({ protectedFrames: [...new Set([...options.protectedFrames, frame])].sort((a, b) => a - b) })}>{ko(`Protect pose at frame ${frame}`, `${frame}프레임 포즈 보호`)}</button>
|
|
58
|
-
{options.protectedFrames.map((f) => <div key={f} className="physics-row"><button className="btn" onClick={() => onFrame(f)}>{ko("Protected", "보호")} F{f}</button><button className="btn" aria-label={ko("Unprotect pose", "포즈 보호 해제")} onClick={() => set({ protectedFrames: options.protectedFrames.filter((p) => p !== f) })}>×</button></div>)}
|
|
59
|
-
</details>
|
|
60
|
-
<button data-testid="physics-analyse" className="btn full primary" onClick={() => run('motion.autoPhysics', { ...options, apply: false })}>{running ? ko(`Analysing ${progress}%`, `분석 중 ${progress}%`) : ko("Analyse & preview", "분석 · 미리보기")}</button>
|
|
61
|
-
</fieldset>
|
|
62
|
-
{running && <progress max="100" value={progress} aria-label={ko("Analysis progress", "분석 진행률")} />}
|
|
63
|
-
{preview && <div data-testid="physics-results">
|
|
64
|
-
<div className="physics-actions"><button data-testid="physics-original" className={`btn ${!show ? "primary" : ""}`} aria-pressed={!show} onClick={() => onShow(false)}>{ko("Original", "원본")}</button><button data-testid="physics-corrected" className={`btn ${show ? "primary" : ""}`} aria-pressed={show} onClick={() => onShow(true)}>{ko("Corrected preview", "보정 미리보기")}</button></div>
|
|
65
|
-
<table><thead><tr><th>{ko("Measured", "실측")}</th><th>{ko("Before", "전")}</th><th>{ko("After", "후")}</th></tr></thead><tbody>
|
|
66
|
-
{[["penetration", ko("Max floor depth", "최대 바닥 관통"), cm], ["meanSlide", ko("Mean contact drift", "평균 접지 밀림"), cm], ["slide", ko("Max contact drift", "최대 접지 밀림"), cm], ["float", ko("Max contact gap", "최대 접지 뜸"), cm], ["kneeStep", ko("Knee step / frame", "무릎 변화 / 프레임"), (x) => `${x.toFixed(1)}°`]].map(([id, label, fmt]) => <tr key={id}><td>{label}</td><td>{fmt(preview.before[id])}</td><td>{fmt(preview.after[id])}</td></tr>)}
|
|
67
|
-
</tbody></table>
|
|
68
|
-
{preview.support && <p className="inspector-hint" data-testid="physics-support-metrics">
|
|
69
|
-
{ko("Unsupported floating frames", "지지 미확인 부유 프레임")}: {preview.before.unsupportedFrames} → {preview.after.unsupportedFrames}<br />
|
|
70
|
-
{ko("Unexplained floating gap", "지지 미확인 뜸")}: {cm(preview.before.unsupportedGap)} → {cm(preview.after.unsupportedGap)}<br />
|
|
71
|
-
{ko("Peak force residual", "최대 잔여 지지력")}: {preview.before.forceResidual.toFixed(2)} → {preview.after.forceResidual.toFixed(2)} BW<br />
|
|
72
|
-
{ko("Peak moment residual", "최대 잔여 회전력")}: {preview.before.momentResidual.toFixed(2)} → {preview.after.momentResidual.toFixed(2)} BW·H<br />
|
|
73
|
-
{ko("Estimated floor support, not measured forces. Hidden props and joint torque limits are not modeled.", "바닥 지지의 근사 추정입니다. 실제 측정 힘이 아니며 숨은 물체·관절 토크 한계는 모델링하지 않아요.")}
|
|
74
|
-
</p>}
|
|
75
|
-
{preview.performance && <p className="inspector-hint" data-testid="physics-timing">{ko("Analysis", "분석")}: {(preview.performance.totalMs / 1000).toFixed(2)}s · {preview.performance.cacheHit ? ko("source measurements reused", "원본 측정 재사용") : ko("source measured", "원본 측정 포함")}{preview.performance.attempts > 1 && <> · {ko(`${preview.performance.attempts} candidates checked`, `${preview.performance.attempts}개 후보 비교`)}</>}</p>}
|
|
76
|
-
<p className="inspector-hint">{ko("Peak knee acceleration", "최대 무릎 각가속도")}: {preview.before.kneeAcceleration.toFixed(0)} → {preview.after.kneeAcceleration.toFixed(0)}°/s²<br />{ko("Peak root acceleration", "최대 골반 가속도")}: {preview.before.rootAcceleration.toFixed(1)} → {preview.after.rootAcceleration.toFixed(1)} m/s²</p>
|
|
77
|
-
<p className="inspector-hint">{preview.after.surfaceMeasured ? ko("Measured on skinned mesh surfaces, not bone height.", "뼈 높이가 아니라 변형된 캐릭터 표면을 측정했어요.") : ko("Surface unavailable: bone proxy only.", "표면 측정 불가: 뼈 기준 대체 측정이에요.")}</p>
|
|
78
|
-
<details><summary>{ko(`${preview.contacts.spans.length} support intervals`, `접지 ${preview.contacts.spans.length}개 구간`)}</summary><div className="physics-list">{preview.contacts.spans.map((s) => <div className="physics-row" key={s.id}><button className="btn" onClick={() => onFrame(s.start)}>{name(s.site)} F{s.start}–{s.end}{s.manual ? " *" : ""}</button><button className="btn" onClick={() => set({ overrides: [...options.overrides, { site: s.site, start: s.start, end: s.end, mode: "free" }] })}>{ko("Free", "해제")}</button></div>)}</div></details>
|
|
79
|
-
<div className={preview.warnings.length || preview.unresolved.length ? "physics-warning" : "inspector-hint"} role="status">
|
|
80
|
-
{preview.warnings.length || preview.unresolved.length ? ko(`${preview.warnings.length} warnings · ${new Set(preview.unresolved.map((r) => r.frame)).size} unresolved contact / support frames`, `경고 ${preview.warnings.length}건 · 접지·지지 역학 미확정 ${new Set(preview.unresolved.map((r) => r.frame)).size}프레임`) : ko("No measured limit exceeded", "측정 기준 초과 없음")}
|
|
81
|
-
{preview.warnings.map((w, i) => <button className="btn full" key={i} onClick={() => onFrame(w.frame)}>{warning(w.reason)} · F{w.frame}</button>)}
|
|
82
|
-
{!!preview.unresolved.length && <button className="btn full" onClick={() => onFrame(preview.unresolved[0].frame)}>{ko("Go to first unresolved contact", "첫 미해결 접지로 이동")}</button>}
|
|
83
|
-
{!!preview.skippedAir?.length && <p>{ko(`${preview.skippedAir.length} flight spans skipped`, `공중 ${preview.skippedAir.length}구간 보류`)}</p>}
|
|
84
|
-
{!!preview.contacts.rejected.length && <button className="btn full" onClick={() => onFrame(preview.contacts.rejected[0].start)}>{ko(`${preview.contacts.rejected.length} moving support intervals rejected`, `움직이는 접지 ${preview.contacts.rejected.length}구간 제외`)}</button>}
|
|
85
|
-
</div>
|
|
86
|
-
<div className="physics-actions"><button data-testid="physics-cancel" className="btn" onClick={onCancel}>{ko("Cancel", "취소")}</button><button data-testid="physics-apply" className="btn primary" disabled={!preview.changedFrames.length || preview.strength === 0} onClick={() => run('motion.applyPhysics')}>{ko("Apply", "적용")}</button></div><small className="pose-keyhint">{ko("Enter applies · Esc cancels", "Enter 적용 · Esc 취소")}</small>
|
|
87
|
-
</div>}
|
|
88
|
-
</section>;
|
|
89
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import * as THREE from "three";
|
|
2
|
-
import { ikEvaluate, solveIk, solveHipsTranslate } from "./ik.js";
|
|
3
|
-
import { relaxPhysicsRoot } from "./physics-temporal.js";
|
|
4
|
-
|
|
5
|
-
// Feed the surfaces actually reached by IK back into the temporal solve.
|
|
6
|
-
// The first solve's ideal foot target can differ from the real skinned sole;
|
|
7
|
-
// smoothing against the measured target avoids a final projection undoing
|
|
8
|
-
// the temporal solution at contact boundaries.
|
|
9
|
-
export async function refinePhysicsCandidate({ rig, chains, fkJoints, samples, after, contacts, candidate, base, roots, sites, applyRaw, read, strength, protectedFrames, yieldFrame, floorY = 0, onProgress = () => {} }) {
|
|
10
|
-
if (strength <= 0) return;
|
|
11
|
-
const hips = fkJoints.get("hips"), locks = new Set(protectedFrames);
|
|
12
|
-
const targets = after.map((row, f) => sites.filter((s) => s.kind === "foot" || contacts.masks[f].has(s.id)).map((site) => ({ site, target: row.support[site.id].position.clone() })));
|
|
13
|
-
const seeds = after.map((row, f) => [...row.root.clone().sub(samples[f].root).toArray(), roots[f][3], roots[f][4]]);
|
|
14
|
-
const optimized = relaxPhysicsRoot(samples, targets, seeds, protectedFrames);
|
|
15
|
-
const prior = [...after];
|
|
16
|
-
const aim = (bone, child, target) => {
|
|
17
|
-
const p = bone.getWorldPosition(new THREE.Vector3());
|
|
18
|
-
const from = child.getWorldPosition(new THREE.Vector3()).sub(p).normalize(), to = target.clone().sub(p).normalize();
|
|
19
|
-
const delta = new THREE.Quaternion().setFromUnitVectors(from, to);
|
|
20
|
-
const world = bone.getWorldQuaternion(new THREE.Quaternion());
|
|
21
|
-
bone.quaternion.copy(bone.parent.getWorldQuaternion(new THREE.Quaternion()).invert().multiply(delta).multiply(world));
|
|
22
|
-
bone.updateMatrixWorld(true);
|
|
23
|
-
};
|
|
24
|
-
for (let f = 0; f < samples.length; f += 1) {
|
|
25
|
-
if (locks.has(f)) continue;
|
|
26
|
-
applyRaw(f); ikEvaluate(chains, candidate, f, fkJoints, 6); rig.updateMatrixWorld(true);
|
|
27
|
-
const root = hips.bone.getWorldPosition(new THREE.Vector3());
|
|
28
|
-
const desired = samples[f].root.clone().add(new THREE.Vector3(...optimized[f]));
|
|
29
|
-
let influence = strength;
|
|
30
|
-
for (const p of protectedFrames) { const t = Math.min(1, Math.abs(f - p) / 4); influence = Math.min(influence, t * t * (3 - 2 * t)); }
|
|
31
|
-
solveHipsTranslate(hips, desired.sub(root).multiplyScalar(influence), hips.bone.position.clone());
|
|
32
|
-
for (const [id, chain] of chains) {
|
|
33
|
-
const endTarget = targets[f].find((t) => t.site.chain === id && t.site.kind !== "knee");
|
|
34
|
-
if (!endTarget) continue;
|
|
35
|
-
const knee = targets[f].find((t) => t.site.chain === id && t.site.kind === "knee");
|
|
36
|
-
if (knee) {
|
|
37
|
-
aim(chain.bones[0], chain.bones[1], knee.target);
|
|
38
|
-
aim(chain.bones[1], chain.bones[2], endTarget.target);
|
|
39
|
-
} else solveIk({ ...chain, bindPositions: base[f].chains.get(id).map((b) => b.p), lengths: samples[f].chains[id].lengths }, endTarget.target, endTarget.site.kind === "foot" ? { maxExtension: samples[f].chains[id].distance + 0.01, softening: 0.01 } : undefined);
|
|
40
|
-
const end = chain.bones[2]; rig.updateMatrixWorld(true);
|
|
41
|
-
end.quaternion.copy(end.parent.getWorldQuaternion(new THREE.Quaternion()).invert().multiply(prior[f].support[id].rotation));
|
|
42
|
-
rig.updateMatrixWorld(true);
|
|
43
|
-
}
|
|
44
|
-
const entry = candidate.keys.get(f);
|
|
45
|
-
entry.get("hips").p.copy(hips.bone.position);
|
|
46
|
-
for (const [id, chain] of chains) entry.get(id).q = chain.bones.map((b) => b.quaternion.clone());
|
|
47
|
-
applyRaw(f); ikEvaluate(chains, candidate, f, fkJoints, 6); after[f] = read();
|
|
48
|
-
if (f % 12 === 0) { onProgress(80 + Math.round(8 * f / samples.length)); await yieldFrame(); }
|
|
49
|
-
}
|
|
50
|
-
// A swing foot is not a pinned constraint. Use that remaining freedom to
|
|
51
|
-
// smooth knee acceleration instead of forcing the pelvis to absorb every
|
|
52
|
-
// knee-speed change. Planted feet and protected poses remain untouched.
|
|
53
|
-
const angles = {};
|
|
54
|
-
for (const id of ["leftFoot", "rightFoot"]) {
|
|
55
|
-
const original = after.map((s) => s.knees[id] * Math.PI / 180), values = [...original];
|
|
56
|
-
for (let sweep = 0; sweep < 24; sweep += 1) for (let k = 2; k < values.length - 2; k += 1) {
|
|
57
|
-
const f = sweep % 2 ? values.length - 1 - k : k;
|
|
58
|
-
if (locks.has(f) || contacts.masks[f].has(id)) continue;
|
|
59
|
-
const next = (original[f] + 2 * (4 * (values[f - 1] + values[f + 1]) - values[f - 2] - values[f + 2])) / 13;
|
|
60
|
-
values[f] = THREE.MathUtils.clamp(next, original[f] - .14, original[f] + .14);
|
|
61
|
-
}
|
|
62
|
-
angles[id] = values;
|
|
63
|
-
}
|
|
64
|
-
for (let f = 0; f < samples.length; f += 1) {
|
|
65
|
-
if (locks.has(f)) continue;
|
|
66
|
-
applyRaw(f); ikEvaluate(chains, candidate, f, fkJoints, 6); rig.updateMatrixWorld(true);
|
|
67
|
-
const backups = new Map();
|
|
68
|
-
for (const id of ["leftFoot", "rightFoot"]) {
|
|
69
|
-
if (contacts.masks[f].has(id)) continue;
|
|
70
|
-
const chain = chains.get(id), [upper, lower, foot] = chain.bones;
|
|
71
|
-
const h = upper.getWorldPosition(new THREE.Vector3()), k = lower.getWorldPosition(new THREE.Vector3()), p = foot.getWorldPosition(new THREE.Vector3());
|
|
72
|
-
const axis = h.sub(k).normalize(), dir = p.clone().sub(k).normalize();
|
|
73
|
-
const tangent = dir.clone().addScaledVector(axis, -dir.dot(axis)).normalize();
|
|
74
|
-
if (tangent.lengthSq() < .5) continue;
|
|
75
|
-
const from = after[f].knees[id] * Math.PI / 180, to = angles[id][f];
|
|
76
|
-
const targetAt = (w) => axis.clone().multiplyScalar(Math.cos(from + (to - from) * w)).addScaledVector(tangent, Math.sin(from + (to - from) * w)).multiplyScalar(samples[f].chains[id].lengths[1]).add(k);
|
|
77
|
-
let weight = strength;
|
|
78
|
-
for (const lock of protectedFrames) { const t = Math.min(1, Math.abs(f - lock) / 4); weight = Math.min(weight, t * t * (3 - 2 * t)); }
|
|
79
|
-
if (after[f].support[id].floor - floorY + targetAt(weight).y - p.y < .001) {
|
|
80
|
-
let lo = 0, hi = weight;
|
|
81
|
-
for (let n = 0; n < 12; n += 1) { const mid = (lo + hi) / 2; if (after[f].support[id].floor - floorY + targetAt(mid).y - p.y >= .001) lo = mid; else hi = mid; }
|
|
82
|
-
weight = lo;
|
|
83
|
-
}
|
|
84
|
-
backups.set(id, candidate.keys.get(f).get(id).q.map((q) => q.clone()));
|
|
85
|
-
aim(lower, foot, targetAt(weight));
|
|
86
|
-
foot.quaternion.copy(foot.parent.getWorldQuaternion(new THREE.Quaternion()).invert().multiply(after[f].support[id].rotation));
|
|
87
|
-
candidate.keys.get(f).get(id).q = chain.bones.map((b) => b.quaternion.clone());
|
|
88
|
-
}
|
|
89
|
-
applyRaw(f); ikEvaluate(chains, candidate, f, fkJoints, 6); let measured = read();
|
|
90
|
-
// A skin-blended ankle is not perfectly rigid. Reject a smoothing move
|
|
91
|
-
// if the actual surface violates the floor, not just its bone proxy.
|
|
92
|
-
let restored = false;
|
|
93
|
-
for (const [id, q] of backups) if (measured.support[id].floor < floorY - .002) {
|
|
94
|
-
const key = candidate.keys.get(f).get(id), proposed = key.q.map((v) => v.clone());
|
|
95
|
-
const threshold = Math.min(floorY - .002, after[f].support[id].floor);
|
|
96
|
-
let lo = 0, hi = 1;
|
|
97
|
-
// A continuous constrained blend avoids an all-or-nothing knee pop
|
|
98
|
-
// when the exact skinned ankle just crosses the floor threshold.
|
|
99
|
-
for (let pass = 0; pass < 7; pass += 1) {
|
|
100
|
-
const w = (lo + hi) / 2;
|
|
101
|
-
key.q = q.map((v, i) => v.clone().slerp(proposed[i], w));
|
|
102
|
-
applyRaw(f); ikEvaluate(chains, candidate, f, fkJoints, 6);
|
|
103
|
-
if (read().support[id].floor >= threshold) lo = w; else hi = w;
|
|
104
|
-
}
|
|
105
|
-
key.q = q.map((v, i) => v.clone().slerp(proposed[i], lo)); restored = true;
|
|
106
|
-
}
|
|
107
|
-
if (restored) { applyRaw(f); ikEvaluate(chains, candidate, f, fkJoints, 6); measured = read(); }
|
|
108
|
-
after[f] = measured;
|
|
109
|
-
if (f % 12 === 0) { onProgress(88 + Math.round(9 * f / samples.length)); await yieldFrame(); }
|
|
110
|
-
}
|
|
111
|
-
}
|