business-ops
Business operations: strategy, technology, growth, competitive intelligence, support, finance, HR, legal, operations, sales, productivity, product management.
CPU-only motion data processing pipeline for game animation: BVH import, contact detection, root decomposition, motion blending, FABRIK IK. No GPU required.
$ npx -y skills add notque/vexjoy-agent --skill motion-pipeline --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/motion-pipelineContext preview
The summary Claude sees to decide when to auto-load this skill.
CPU-only motion data processing pipeline for game animation: BVH import, contact detection, root decomposition, motion blending, FABRIK IK. No GPU required.
name: motion-pipeline
promoted_to: game-pipeline
user-invocable: false
description: "CPU-only motion data processing pipeline for game animation: BVH import, contact detection, root decomposition, motion blending, FABRIK IK. No GPU required."
allowed-tools:
- Read
- Bash
- Write
- Edit
- Glob
- Grep
routing:
triggers:
- "mocap"
- "motion data"
- "animation pipeline"
- "BVH import"
- "contact detection"
- "IK solve"
- "motion blend"
- "bone trajectory"
- "root extraction"
- "FABRIK"
- "skeletal animation data"
category: game-animation
pairs_with:
- game-sprite-pipeline
- phaser-gamedev
agents:
- rive-skeletal-animator
- pixijs-combat-renderer
- game-asset-generatorCPU-only motion data processing pipeline for game animation, inspired by Meta's ai4animationpy framework (CC BY-NC 4.0). All operations run on numpy and scipy with no GPU or PyTorch required.
ai4animationpy's `Math/Tensor.py` imports `torch` unconditionally at the top level, which propagates through every module (Animation, Import, IK, Math). This means zero ai4animationpy modules are importable without PyTorch installed. The standalone implementations in `scripts/motion-pipeline.py` replicate the key algorithms from their source code using only numpy + scipy.
# Create venv (one-time)
python3 -m venv /home/feedgen/vexjoy-agent/motion-pipeline-env/
# Install CPU-only deps
motion-pipeline-env/bin/pip install numpy scipy pygltflib Pillow
# Verify
motion-pipeline-env/bin/python -c "import numpy; import scipy; import pygltflib; print('OK')"The venv is gitignored. The skill documents setup; it does not commit the venv.
All commands output JSON to stdout. Errors go to stderr with exit code 1.
Parse a BVH mocap file and print a motion summary.
motion-pipeline-env/bin/python scripts/motion-pipeline.py import-bvh FILE \ [--scale 0.01] # scale cm->m for CMU/Mixamo files
Output fields: `name`, `num_frames`, `num_joints`, `framerate`, `total_time_seconds`, `bones[]`, `root_trajectory` (x/y/z range).
Detect ground contact frames per bone (foot, hand) using height + velocity thresholds. Replicates `ContactModule.GetContacts()` from ai4animationpy.
motion-pipeline-env/bin/python scripts/motion-pipeline.py extract-contacts FILE \ --bones LeftFoot RightFoot \ --height 0.1 \ --vel 0.5
Output: `{ "bones": { "<name>": { "contact_frames": [...] } }, "total_frames": N }`.
Split motion into root trajectory (WHERE + HOW) and per-joint local Euler angles (POSE). Implements the RootModule / MotionModule decomposition pattern.
motion-pipeline-env/bin/python scripts/motion-pipeline.py decompose FILE \ --hip Hips
Output: `root_trajectory.positions[]`, `root_trajectory.velocities[]`, `root_trajectory.facing_directions[]`, `per_joint_euler_zyx_degrees{}`.
First 5 frames shown in stdout; full data requires piping to a file.
Blend two BVH clips at a fixed alpha using SLERP rotations and LERP positions. Clips must share the same bone hierarchy.
motion-pipeline-env/bin/python scripts/motion-pipeline.py blend FILE_A FILE_B \ --alpha 0.5
Output: summary of the blended motion.
Run FABRIK inverse kinematics on a bone chain at a single frame.
motion-pipeline-env/bin/python scripts/motion-pipeline.py solve-ik FILE \ --chain Hips:LeftFoot \ --target 0.2,0.05,0.3 \ --frame 10
Output: `chain[]`, `target[]`, `initial_positions[]`, `solved_positions[]`, `end_effector_error` (metres).
Convert a BVH mocap file into a TypeScript `MoveFrame` function compatible with road-to-aew's `wrestlingMoves.ts` interface. Outputs keyframe-interpolated TypeScript to stdout (and optionally a file).
motion-pipeline-env/bin/python scripts/generate-move-ts.py BVH MOVE_NAME \ [--scale 0.01] \ [--contact-bones LeftToeBase RightToeBase LeftHand RightHand] \ [--num-keyframes 12] \ [--hip-bone Hips] \ [--output path/to/output.ts]
| Argument | Default | Purpose | |---|---|---| | `BVH` | — | Path to .bvh mocap file | | `MOVE_NAME` | — | Kebab-case name (e.g. `roundhouse-kick`) used in TS identifiers | | `--scale` | `0.01` | Position scale; 0.01 converts cm→m for CMU/Mixamo files | | `--contact-bones` | `LeftToeBase RightToeBase LeftHand RightHand` | Bones used to detect the impact window | | `--num-keyframes` | `12` | Keyframe count in the output array (min 2) | | `--hip-bone` | `Hips` | Root bone name for trajectory extraction | | `--output` | stdout only | Write TS to this file path in addition to stdout |
**Implementation note:** The script imports `motion-pipeline.py` as a module via `importlib` rather than calling it as a subprocess. This bypasses the 5-frame truncation applied by the `decompose` CLI command, giving access to all frames.
**Output structure:**
// Generated from roundhouse-kick.bvh on 2026-04-13
// Keyframes: 12, Impact window: 0.45-0.55
const ROUNDHOUSE_KICK_KEYFRAMES = [...] as const;
export function getRoundhouseKick(progress: number): MoveFrame {
// keyframe lookup + linear interpolation
// isImpact based on detected contact window
return { attacker, defender, isImpact };
}The attacker's `offsetX/Y/Z` are root trajectory positions normalized to start at origin. Rotations are in radians (converted from the BVH's Euler ZYX degrees). The defender reaction is computed procedurally: pushed backward at impact, eases to mat post-impact.
**Impact detection:** The script finds the first run of 3+ consecutive contact frames across the specified bones. For strike moves, this captures the moment of hit. For walking/idle clips (feet always down), the window will be frame-0 and `isImpact` will be nearly never true — this is correct behavior
Essays and writing behind this toolkit live at vexjoy.com. VexJoy Agent connects plain-English requests to specialist agents, skills, and workflows. /do selects the knowledge and tools needed for your task.
Repo: notque/vexjoy-agent
Business operations: strategy, technology, growth, competitive intelligence, support, finance, HR, legal, operations, sales, productivity, product management.
Design workflows — UX copy, design systems, design critique, accessibility review, design handoff, user research synthesis. Use when writing UI copy, reviewing…
Marketing: SEO audits, campaign planning, content strategy, email sequences, competitive analysis, brand review, performance reporting.