mmd-anim-cli 0.4.1

CLI diagnostics and roundtrip tools for mmd-anim
mmd-anim-cli-0.4.1 is not a library.

mmd-anim

mmd-anim is a Rust animation foundation for playing MikuMikuDance animation across multiple platforms.

It loads PMX/VMD data and evaluates world matrices, skinning matrices, morph weights, and IK state at any frame. The library is designed so the same runtime can be called from browsers, command-line tools, Rust applications, mobile applications, game engines, and other host environments.

Status

mmd-anim is still in an evaluation stage.

It is tested against data exported from the original MMD and against several PMX/VMD assets, but real-world usage is still limited. APIs and features are not frozen yet, and breaking changes may happen before 1.0. Feedback is welcome.

Runtime Evaluation

  • Load a PMX model and convert it into runtime-ready model data.
  • Load a VMD motion and convert bone, camera, light, and other motion tracks into a playable form.
  • Interpolate between keyframes with MMD-style Bezier interpolation for translation and rotation.
  • Bullet Physics simulation for MMD models is available through the CLI and native API.

Test Foundation

mmd-anim is a shared animation foundation for multiple projects, so test coverage focuses on keeping evaluated results correct.

The repository includes tests for:

  • animation evaluation, bone hierarchy evaluation, IK, append transforms, morphs, and format read/write paths;
  • round-trip checks that write parsed data and read it back without changing the represented content;
  • frame-by-frame PMX/VMD runtime evaluation against expected results;
  • maintainer CLI diagnostics for inspecting loaded models and evaluated state;
  • C ABI and WASM smoke checks to confirm host-facing APIs use the same runtime path.

Recommended public release checks:

cargo test --workspace
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo doc --workspace --no-deps

Used By

mmd-anim is developed as the shared animation backend for MMD-related projects.

  • three-mmd-loader: A Three.js MMD loader that uses mmd-anim as its animation and format backend.
  • maya_mmd_tools: A Maya plugin for editing MMD animation. It uses mmd-anim for full-bake VMD import and as the source of truth for its rig implementation.
  • unity-mmd-loader: An MMD loader optimized for Unity 6 and URP, using mmd-anim for importing and as its core animation runtime.

More integrations can share the same runtime core through the Rust API, C ABI, or WASM wrapper.

Supported Formats

Format support overview. "Loading" means parsing a file into structured data. "Writing" means outputting the target file format.

Format Loading Writing
PMX model sections + soft-body header diagnostics writing / JSON conversion / generation from mesh data
PMD model structure + partial runtime import writing / JSON conversion
VMD supported supported
VPD supported supported
PMM header, timeline, display state, referenced assets, PMMv2 summaries, and selected keyframe payload metadata partial support: rewriting selected parts of the original data and experimental generation of single-model PMX/VMD scenes
X/VAC text X mesh, material, UV, normal, vertex color + VAC settings and raw lines text X / VAC wrapper writing
FBX not supported Experimental binary export for PMX meshes, skeletons, skinning, bind poses, and vertex morphs (blendshapes), as well as runtime-baked VMD bone and vertex-morph animation.

Rust Usage

[dependencies]
mmd-anim = "0.4.1"

Native Hosts (C ABI)

Native applications and game engines can use the C ABI from mmd-anim-ffi. It is not tied to a specific engine; any host that can call a C ABI can use it (Unity is one example). The header is crates/mmd-anim-ffi/include/mmd_runtime.h.

// 1. Create a model from PMX bytes
mmd_runtime_model_t* model =
    mmd_runtime_model_create_from_pmx_bytes(pmx_bytes, pmx_len);

// 2. Create an animation clip from VMD bytes
mmd_runtime_clip_t* clip =
    mmd_runtime_clip_create_from_vmd_bytes_for_model(model, vmd_bytes, vmd_len);

// 3. Create an instance
mmd_runtime_instance_t* instance =
    mmd_runtime_instance_create_for_model(model);

// 4. Evaluate a frame
mmd_runtime_instance_evaluate_clip_frame(instance, clip, 300.0f);

// 5. Copy world matrices
size_t len = mmd_runtime_instance_world_matrix_f32_len(instance);
mmd_runtime_instance_copy_world_matrices(instance, out_f32, len);

// 6. Free resources
mmd_runtime_instance_free(instance);
mmd_runtime_clip_free(clip);
mmd_runtime_model_free(model);

The intended split is that the host owns meshes, materials, and textures, while this runtime provides matrices, morph state, and IK state. To generate PMX from host-side geometry data, use mmd_runtime_export_pmx_from_parts. Input arrays remain owned by the caller, and returned bytes must be freed with mmd_runtime_byte_buffer_free.

WASM / Browser

The browser build uses wasm-pack build --target web. A Node.js-only build is not used.

cd .\crates\mmd-anim-wasm\harness
npm run build

Generated files are written to crates/mmd-anim-wasm/harness/pkg/.

import init, {
  exportMmdFormatBytes,
  exportPmxFromParts,
  exportVmdAnimationJsonBytes,
  parseMmdFormatJson,
  WasmMmdClip,
  WasmMmdModel,
  WasmMmdRuntimeInstance,
} from "./pkg/mmd_anim_wasm.js";

await init();

// Runtime evaluation
const model = WasmMmdModel.fromPmxBytes(pmxBytes);
const clip = WasmMmdClip.fromVmdBytesForModel(model, vmdBytes);
const runtime = WasmMmdRuntimeInstance.forModel(model);

runtime.evaluateClipFrame(clip, 300);
const world = runtime.worldMatrices();

// Explicitly free resources when they are no longer needed.
runtime.free();
clip.free();
model.free();

// Loading / writing without a runtime handle
const json = parseMmdFormatJson(vmdBytes, "motion.vmd");
const exportedBytes = exportVmdAnimationJsonBytes(json);
const normalizedBytes = exportMmdFormatBytes(vmdBytes, "motion.vmd");

// Generate PMX from typed arrays
const generatedPmxBytes = exportPmxFromParts(
  JSON.stringify({
    modelName: "generated",
    materials: [{ name: "mat", faceCount: 1 }],
    bones: [{ name: "root", parentIndex: -1, position: [0, 0, 0] }],
  }),
  positionsXyz,
  normalsXyz,
  uvsXy,
  indices,
  skinIndices,
  skinWeights,
  edgeScale,
);

CLI

mmd-anim-cli is a command-line tool for inspecting, converting, and diagnosing MMD format files (PMX, VMD, VPD, PMM, X/VAC).

cargo install mmd-anim-cli
mmd-anim --help

Source builds of the CLI, native API, or physics crate require a C++ compiler for the target. Bullet itself does not need to be installed separately. Prebuilt CLI binaries from GitHub Releases can be used directly.

You can export animated FBX files from PMX and VMD inputs.

mmd-anim convert-fbx model.pmx model.fbx --vmd motion.vmd --max-frame 120

Crates

Crate Role
mmd-anim Main public crate. Provides the evaluation core and format handling through one entry point.
mmd-anim-runtime Format-independent evaluation core: model arena, pose, VMD evaluation, append transforms, IK, and morphs.
mmd-anim-format PMX/VMD runtime import, format detection, structured loading, and PMX/PMD/VMD/VPD/X/VAC writing.
mmd-anim-physics-bullet Bullet Physics backend for MMD. Builds the bundled Bullet3 sources for the target and integrates them with the runtime and PMX formats.
mmd-anim-ffi C ABI for native hosts. Exposes runtime operations, PMX parts writing, sparse curves, and physics simulation. Repository-local and not published to crates.io.
mmd-anim-wasm wasm-bindgen wrapper for browsers. Exposes runtime operations, loading/writing APIs, PMX parts writing, and sparse curves. Workspace-local and not published to crates.io.
mmd-anim-cli Command-line tool for inspecting, converting, and diagnosing MMD format files, including maintainer-local oracle and numeric comparison schemas. Installable via cargo install mmd-anim-cli.

For normal library use, depend on mmd-anim. Advanced users who only need a lower layer can depend on mmd-anim-format or mmd-anim-runtime directly. Use mmd-anim-physics-bullet to access the physics backend directly from Rust.

Current Limitations

  • Evaluation core: PMD loading and partial runtime import are supported for bones, IK, morph slots, and vertex morph offsets, but renderer-side vertex deformation and full PMD compatibility are not claimed yet.
  • Writing: PMX generation from parts currently covers the initial range of geometry, materials, bones, display frames, morphs, and physics. PMM writing is limited to the data currently represented by the PMM manifest parser.
  • PMM: Supported PMM data currently includes project header information, timeline-derived values, display state, initial model-slot data, referenced assets, PMMv2 summary information, and asset/header consistency diagnostics. The PMM exporter can re-emit that limited manifest/header/slot/asset-reference surface as a PMMv2 file, but it is not a full PMM project-graph exporter. Keyframe payloads, full camera/light/accessory/self-shadow tracks, and other binary project graph data that are only summarized or not preserved by the parser cannot be reconstructed from PmmParsedManifest.
  • X/VAC: Text X mesh, material, normal, UV, vertex color, and common VAC line order are handled. Binary X is diagnostic-only.

Japanese README

References

This project was developed with reference to: