Python library and CLI for converting between Second Life / OpenSim .anim binary animation files and BVH (Biovision Hierarchy) format.
Status: Alpha / under active development. The package structure, ADR, and skeleton data are in place; the core modules are scaffolded but not yet implemented. See ADR-001 for the design contract and Roadmap for current progress.
The SL/OpenSim .anim format is a compact binary encoding used for in-world animations (body, face, fingers, wings, tail — the full Bento skeleton). Despite decades of community content in this format, no reliable open-source Python converter exists.
The immediate driver is the RuthAndRoth Hand Pose Library — 42 hand pose .anim files by Chimera Firecaster. The longer-term goal is a general-purpose pipeline for importing and exporting SL/OpenSim animations to modern toolchains (BVH → Blender → GLB).
.anim→ BVH: Full Bento skeleton support (face, fingers, wings, tail)- BVH →
.anim: Round-trip conversion for OpenSim upload - Batch processing: Convert entire directories
- Library API: Import and use programmatically
- No external dependencies: pure-Python, stdlib only
# From source (until published to PyPI)
git clone https://github.com/increasinglyHuman/openSim-anim-tools.git
cd openSim-anim-tools
pip install -e .Requires Python 3.10+.
# Single file
anim2bvh input.anim -o output.bvh
bvh2anim input.bvh -o output.anim
# Batch (directory)
anim2bvh ./anims/ -o ./bvhs/
# With options
anim2bvh input.anim --fps 30 --skeleton avatar_skeleton.xmlfrom opensim_anim import AnimFile, bvh_write
# Parse .anim
anim = AnimFile.from_file("Bento_HandRelax1.anim")
print(anim.joints) # Joint names and keyframes
print(anim.duration) # Animation duration in seconds
print(anim.priority) # Animation priority level
# Convert to BVH
bvh_write(anim, "output.bvh", fps=30)
# Or as string
bvh_text = anim.to_bvh(fps=30)The .anim binary format encodes:
- Header: version, priority, duration, ease in/out, loop flags, hand pose enum
- Per joint: name, priority, rotation keyframes (U16-quantized truncated quaternion — W reconstructed from XYZ), position keyframes (U16-quantized, ±5 m range), timestamps (U16 over duration)
Full spec and conversion strategy in ADR-001.
Includes the SL Bento skeleton definition (avatar_skeleton.xml) for correct bone hierarchy and rest-pose offsets in BVH output. Supports 132+ bones:
- 26 animation bones (mPelvis → mHead, arms, legs)
- 26 collision volume bones
- 46 face bones (Bento)
- 30 finger bones (Bento)
- Wings, tail, hind limbs
# Clone and set up an isolated environment
git clone https://github.com/increasinglyHuman/openSim-anim-tools.git
cd openSim-anim-tools
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
# Run tests (once implemented)
python -m pytestopensim_anim/
├── __init__.py # Public API: AnimFile, bvh_write
├── anim_parser.py # .anim binary reader/writer
├── bvh_writer.py # BVH text output
├── skeleton.py # avatar_skeleton.xml parser
├── quat_math.py # Quaternion ↔ Euler, slerp
├── cli.py # anim2bvh / bvh2anim entry points
└── data/
└── avatar_skeleton.xml
docs/adr/
└── ADR-001-*.md # Design decisions
tests/ # Round-trip and fixture-based tests
This project follows the Human-AI Codebase Standards used across the poqpoq ecosystem — spec-driven development (ADR before code), self-describing modules (structural + semantic headers), commit messages that explain why. Both human and AI contributions are welcome; AI co-authored work uses Co-Authored-By: trailers.
Before opening a PR that introduces a new subsystem, please add or update an ADR under docs/adr/.
- Project scaffold, ADR-001, skeleton data bundled
-
anim_parser.py— port Firestormanim_tool.pyto Python 3 with dataclasses -
skeleton.py—avatar_skeleton.xml→ bone tree + rest offsets -
quat_math.py— quaternion decoding, slerp, per-bone Euler order -
bvh_writer.py— hierarchy + motion block output -
cli.py—anim2bvh/bvh2animcommands, batch mode - Round-trip tests against the RuthAndRoth hand pose corpus
-
bvh_to_animpath (reverse direction) - PyPI release (0.1.0)
This library is built to support several sister projects:
- BlackBox Animator — GLB animation editor with IK (imports SL/OpenSim animations for retargeting).
- BlackBox Avatar — web character creator (uses converted hand poses as layered finger animations).
- BlackBox Skinner — vertex weight painter (potential consumer for weight-transfer pipelines).
- poqpoq World — AI-first metaverse (runtime consumer via Babylon.js).
The library has no runtime dependency on these projects; they consume it as a conversion utility.
.animparser foundation: Firestorm'sanim_tool.pyby Brad Payne / Nat Goodspeed (LGPL 2.1)- Skeleton data:
avatar_skeleton.xmlfrom Second Life (Linden Lab) - Reference hand pose library: RuthAndRoth/Extras — Chimera Firecaster et al.
- OpenSim
BinBVHAnimation.cs— per-bone Euler order reference (OpenSimulator project)
LGPL 2.1 (inherited from the Firestorm parser foundation). See LICENSE.