Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 62 additions & 41 deletions .github/workflows/ost-source-ci.yml

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ jobs:
set -euo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends libx11-dev libxt-dev
- name: Bootstrap ost 0.22.10 (pinned release asset, checksum-verified)
- name: Bootstrap ost 0.23.2 (pinned release asset, checksum-verified)
shell: bash
run: |
set -euo pipefail
Expand All @@ -123,7 +123,7 @@ jobs:
*) echo "::error title=ost bootstrap::no ost release asset for ${RUNNER_OS}-${RUNNER_ARCH}" ; exit 1 ;;
esac
asset="ost-cli-${triple}.${ext}"
base="https://github.com/animu-sphere/open-strata/releases/download/v0.22.10"
base="https://github.com/animu-sphere/open-strata/releases/download/v0.23.2"
curl -fsSLo "$asset" "$base/$asset"
curl -fsSLo "$asset.sha256" "$base/$asset.sha256"
actual="$( (command -v sha256sum > /dev/null && sha256sum "$asset" || shasum -a 256 "$asset") | cut -d' ' -f1 )"
Expand Down Expand Up @@ -155,8 +155,8 @@ jobs:
version="$(ost --version)"
fi
echo "$version"
if [ "$version" != "ost 0.22.10" ]; then
echo "::error title=ost bootstrap::expected 'ost 0.22.10', got '$version'" ; exit 1
if [ "$version" != "ost 0.23.2" ]; then
echo "::error title=ost bootstrap::expected 'ost 0.23.2', got '$version'" ; exit 1
fi
# Restore only: the pull request lanes own these entries, and a release
# run must not write a cache a later pull request would trust.
Expand All @@ -165,7 +165,7 @@ jobs:
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .ost-ci-home/artifacts
key: ost-registry-0.22.10-${{ runner.os }}-${{ runner.arch }}-${{ matrix.cache_cell }}-${{ matrix.runtime_artifact }}
key: ost-registry-0.23.2-${{ runner.os }}-${{ runner.arch }}-${{ matrix.cache_cell }}-${{ matrix.runtime_artifact }}
# The cache-hit test is the same predicate as the gate below, so a cached
# record that would fail the gate drops through to a fresh pull.
- name: Pull the pinned runtime SDK from its remote reference
Expand All @@ -189,6 +189,9 @@ jobs:
--require-openusd "${{ matrix.require_openusd }}" --require-openusd-version 26.08
ost runtime pull cy2026 --profile usd --from-artifact "${{ matrix.runtime_artifact }}" --force
ost runtime validate cy2026 --profile usd --json > /dev/null
- name: Pull digest-pinned external library artifacts
shell: bash
run: ost library pull --target cy2026 --profile usd --json
- name: Set up host Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ strata.lock
# its OST_HOME (the materialized runtime).
/.ost-ci/
/.ost-ci-home/
/.ost-*/

# Built plugin libraries are staged into each bundle's lib/ by the build, and
# tools into their own bin/.
Expand Down
28 changes: 23 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,23 @@ Stage-contract version: **1**, authored since the Phase 0 importer.

### Added

- **Phase 9 shared-motion adapters.** `mmdSkeletonAdapter` implements role-table
version 1 and builds the PMX stage's `SkeletonDescriptor`, source rest and
target `RetargetMap`; `mmdMotionAdapter` samples `mmdControl` over an explicit
time range into evaluated `MotionClip` poses, root motion, namespaced MMD
morph channels and a reserved visibility channel. Non-finite evaluated
values are rejected at the shared boundary rather than replaced. Their
manifests consume digest-pinned `motionCore` and
`motionRetarget` v0.5.0 artifacts, and unit, boundary and installed-consumer
tests cover both edges. Source and release CI pin `ost` 0.23.2 so those
external artifacts are parsed, pulled and composed into root builds. CI
also forwards the host-resolved Python development paths into the clean
installed-consumer configure, provisions Python for Windows runtime
validation, and recognizes the complete macOS OpenUSD foundation closure.
`mmdMotionBinding` now preserves the VMD model name
as provenance. End-to-end retarget and `UsdSkelAnimation` authoring remains
Phase 9 work. (`MOTION_CONTRACT.md` §10, §12.)

- **Physics runtime integration direction.** A proposed focused contract now
fixes the future boundary: the existing `/Asset/physics` stage remains the
hand-off, MMD bone/body coupling stays in this repository, generic
Expand Down Expand Up @@ -76,13 +93,14 @@ Stage-contract version: **1**, authored since the Phase 0 importer.
(`MOTION_CONTRACT.md` §9, §10, §12; `DESIGN_POLICY.md` §5.7, §14, §20.1;
`WORKSPACE.md` §1.2, §2, §2.4; `DEPENDENCIES.md` §6.)

- **The shared-motion edge is split by responsibility.** The planned
`mmdMotionAdapter` now emits only fully evaluated `MotionPose`/`MotionClip`
data. A separate planned `mmdSkeletonAdapter` exposes
- **The shared-motion edge is split by responsibility.** The
`mmdMotionAdapter` emits only fully evaluated `MotionPose`/`MotionClip`
data. A separate `mmdSkeletonAdapter` exposes
`SkeletonDescriptor`, `RetargetMap` and `SourceRestPose` and owns the
versioned MMD humanoid mapping. Both remain narrow consumers of
`usd-motion-plugins`; neither implements generic retargeting. Documentation
only; no component or manifest exists yet. (`MOTION_CONTRACT.md` §10, §12;
`usd-motion-plugins`; neither implements generic retargeting. This boundary
was decided in documentation first and implemented by the adapter change above.
(`MOTION_CONTRACT.md` §10, §12;
`DESIGN_POLICY.md` §5.7; `WORKSPACE.md` §1.2, §2.4.)

- **The design documents follow the `usd-motion-plugins` design policy.**
Expand Down
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ add_subdirectory("tools/vmdInspect")
find_package(pxr REQUIRED CONFIG)
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/UsdMmdOpenUsd.cmake")

# The two Phase 9 adapters are the only libraries that cross into the shared
# motion packages. Resolve them after OpenUSD so motionCore/motionRetarget can
# reuse the already-defined foundation targets, then add the adapters in their
# dependency order.
find_package(motionCore 0.5 CONFIG REQUIRED)
find_package(motionRetarget 0.5 CONFIG REQUIRED)
add_subdirectory("libs/mmdSkeletonAdapter")
add_subdirectory("libs/mmdMotionAdapter")

# The interpreter the integration tests import OpenUSD's Python bindings into.
# It must be the Python OpenUSD was built against, and pxrConfig.cmake names
# that one -- it sets Python3_EXECUTABLE unless it is already defined -- so the
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ assets: PMX models, and VMD motion bound to them.
> identifiers, and `mmd_inspect` reports what a file contains. A VMD is read
> without a model and reported by `vmd_inspect`, and bound to a model by MMD's
> own name rule. Phase 9 now evaluates MMD's IK and append transforms over a
> bound motion; next its motion and skeleton adapters hand evaluated clips and
> bound motion, and its motion and skeleton adapters hand evaluated clips and
> PMX rig descriptions to `usd-motion-plugins`, which retargets and authors
> `UsdSkelAnimation`. Future physics execution consumes the existing static
> `UsdSkelAnimation`. End-to-end retarget and authoring acceptance remains.
> Future physics execution consumes the existing static
> stage through `usd-physics-plugins`; the importer remains solver-free. The
> [capability matrix](docs/reference/CAPABILITY_MATRIX.md) is the only page
> that says what is implemented, and [the roadmap](docs/roadmap/current.md)
Expand Down Expand Up @@ -45,7 +46,7 @@ VMD bytes ─→ motionVmd ─→ mmdMotionBinding (+ mmdModel) ─→ a bound m
syntax, by source name, in the model's
tracks basis
─→ mmdControl ─→ mmdMotionAdapter ─→ MotionClip ─→ usd-motion-plugins
IK, append, (Phase 9, planned) retarget, record, UsdSkelAnimation
IK, append, retarget, record, UsdSkelAnimation
bone morphs

PMX skeleton ─→ mmdSkeletonAdapter ─→ SkeletonDescriptor / RetargetMap
Expand Down Expand Up @@ -77,8 +78,8 @@ contract is [docs/design/PHYSICS_INTEGRATION.md](docs/design/PHYSICS_INTEGRATION
| `motionVmd` | plain C++ library | VMD syntax, CP932 names and tracks — no dependency at all | reads every section |
| `mmdMotionBinding` | plain C++ library | binds a VMD motion to a canonical model by source name, in the model's basis — no OpenUSD, nothing evaluated | exists |
| `mmdControl` | plain C++ library | evaluates a bound motion at an explicit time over MMD's control rig — Bézier curves, bone morphs, appends, IK — into deformation-joint transforms; no OpenUSD, scheduled by a runtime | exists |
| `mmdSkeletonAdapter` | planned plain C++ library | exposes the PMX skeleton, source rest and versioned humanoid map to `usd-motion-plugins`; no retarget algorithm | waits for installable `motionRetarget` |
| `mmdMotionAdapter` | planned plain C++ library | turns fully evaluated MMD poses into `MotionClip`; no target-avatar knowledge | waits for installable `motionCore` and `motionRetarget` |
| `mmdSkeletonAdapter` | plain C++ library | exposes the PMX skeleton, source rest and versioned humanoid map to `usd-motion-plugins`; no retarget algorithm | exists |
| `mmdMotionAdapter` | plain C++ library | turns fully evaluated MMD poses into `MotionClip`; no target-avatar knowledge | exists |
| `vmd_inspect` | CLI | what a VMD contains, without a model or USD | exists ([guide](docs/guides/inspecting.md)) |

`mmdSchema` exists only if an MMD API schema passes the
Expand Down
9 changes: 5 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Documentation is organized by responsibility: each category answers one class
of question. The layout is the one `usd-vrm-plugins`, `open-strata` and
`hydra-merlin` use, so the repositories read the same way.

**The tree holds Phases 0–7 (2026-09-17):** the PMX structural parser reads
**The tree holds Phases 0–7 and most of Phase 9 (2026-09-21):** the PMX structural parser reads
every table of a PMX 2.0 or 2.1 file, `mmd_inspect` reports on it, and `.pmx`
opens as the canonical stage — mesh, UVs, material prims and subsets,
skeleton and skinning, Y-up, in meters. Phase 3 adds canonical MMD material
Expand All @@ -15,9 +15,10 @@ chains, append relations, axes — under `/Asset/rig`, solving nothing, and
Phase 6 every rigid body and joint under `/Asset/physics`, as `UsdPhysics`
where it matches, simulating nothing. Phase 7 reads VMD motion without a
model (`motionVmd`, `vmd_inspect`) and binds it to one by MMD's name rule
(`mmdMotionBinding`), baking nothing. Phase 9, in progress, evaluates MMD's
control rig over a bound motion (`mmdControl`, done) and will hand the result
to `usd-motion-plugins`, through separate motion and skeleton adapters. Future
(`mmdMotionBinding`), baking nothing. Phase 9 evaluates MMD's control rig over
a bound motion (`mmdControl`) and hands the result to `usd-motion-plugins`
through `mmdMotionAdapter` and `mmdSkeletonAdapter`. End-to-end retarget and
animation authoring acceptance remains. Future
physics execution consumes the existing static stage through
`usd-physics-plugins`, with MMD coupling kept here and simulation outside the
importer. Everything
Expand Down
18 changes: 7 additions & 11 deletions docs/architecture/DEPENDENCIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ component links it yet. §7 records the proposed optional runtime edge to
| | |
| --- | --- |
| Pin | OpenUSD **26.08**, exactly (`PXR_VERSION` 2608), enforced by [cmake/UsdMmdOpenUsd.cmake](../../cmake/UsdMmdOpenUsd.cmake) for `ost` and plain-CMake builds alike and declared as `runtime.openusd: "==26.08"` in the bundle manifest; the release the rest of the ecosystem pins (`usd-vrm-plugins` too), because `usd-avatar-runtime` composes every plugin into one OpenUSD process |
| Used by | `usdMmdFileFormat` (and later `mmdSchema`, `usdVmdFileFormat`) only; later `mmdMotionAdapter` too, for the foundation types (`gf`, `tf`, `vt`) `usd-motion-plugins`' `motionCore` and `motionRetarget` expose, and no stage (§6) |
| Used by | `usdMmdFileFormat`; `mmdMotionAdapter` and `mmdSkeletonAdapter` use only the foundation types (`gf`, `tf`, `vt`) exposed through the shared motion packages, and no stage (§6) |
| Modules | linked today: `arch`, `tf`, `gf`, `vt`, `ar`, `sdf`, `usd`, `usdGeom`, `usdPhysics`, `usdShade`, `usdSkel`, `kind` (`usdShade` and `usdSkel` since Phase 2, `usdPhysics` since Phase 6) |
| Not used | OpenExec, Hydra, `usdImaging` — nothing is evaluated or rendered here, so unlike `usd-vrm-plugins`' pin module this one probes for no OpenExec |
| CI runtimes | the OpenUSD 26.08 leaves of OpenStrata's runtime matrix, the same digests `usd-vrm-plugins` pins ([openstrata.ci.yaml](../../openstrata.ci.yaml)) |
Expand All @@ -38,7 +38,7 @@ calls the MaterialX library. The MaterialX document version it declares
| Compilers | MSVC on Windows, Clang on macOS (arm64), GCC on Linux — the three hosted lanes `usd-vrm-plugins` runs |
| Windows flags | `/utf-8`, `NOMINMAX`, applied by `usdmmd_target_defaults()` in [cmake/UsdMmdTargets.cmake](../../cmake/UsdMmdTargets.cmake) ([WORKSPACE.md §5](WORKSPACE.md#5-build-modes)) |
| Python | the Python OpenUSD was built against — 3.13 for the 26.08 runtimes — for stage tests and tooling. The root project finds the interpreter *after* OpenUSD, so it inherits the one `pxrConfig.cmake` names |
| OpenStrata | `ost` **0.22.10**, pinned in `openstrata.ci.yaml` |
| OpenStrata | `ost` **0.23.2**, pinned in `openstrata.ci.yaml`; required for digest-pinned external-library artifacts in root builds |
| Unit-test framework | **none**, as in `usd-vrm-plugins`: each suite is a plain executable that checks with `assert()`, compiled with `NDEBUG` undefined so Release builds still check, and registered with CTest |
| Sanitizers and fuzzing | Clang 18's AddressSanitizer, UndefinedBehaviorSanitizer and libFuzzer, from Ubuntu 24.04's packages, in [parser-sanitizers.yml](../../.github/workflows/parser-sanitizers.yml) only; `mmdPmx`'s `MMDPMX_SANITIZERS` and `MMDPMX_BUILD_FUZZER` options, and the matching `MMDMODEL_`, `MOTIONVMD_` and `MMDMOTIONBINDING_` ones, switch them on, and nothing shipped is built with them. Toolchain runtimes, not dependencies: no code is vendored and nothing links them outside that lane |

Expand Down Expand Up @@ -95,20 +95,16 @@ exact version, and listed in `THIRD_PARTY_NOTICES.md`.

The shared motion core: vendor- and avatar-format-neutral poses and clips,
humanoid joint semantics, sampling, retargeting, recording and the
`UsdSkelAnimation` bridge. Planned, not linked. Its first tag,
`v0.1.0-alpha.1` (2026-09-19), is a source-only pre-release of `motionCore`
alone, and its notes say it is not `v0.1.0`. Its `main` has since received
`motionRetarget` — `SkeletonDescriptor`, `RetargetMap`, `SourceRestPose`,
the root-motion policy and the retarget diagnostics — imported from
`usd-vrm-plugins` on 2026-09-19 ahead of the `v0.2.0` that ships it. Nothing
here links either until each is released.
`UsdSkelAnimation` bridge. v0.5.0 was published on 2026-09-20 with installable
`motionCore` and `motionRetarget`; the two adapters consume their per-target,
digest-pinned OpenStrata artifacts.

| | |
| --- | --- |
| Packages | `motionCore` (`HumanJoint`, `MotionPose`, `RootMotion`, `MotionClip`) and `motionRetarget` (`SkeletonDescriptor`, `RetargetMap`, `SourceRestPose`), each by `find_package(<name> CONFIG)` and linked as `<name>::<name>`; `motionUsd` only where [WORKSPACE.md §2.4](WORKSPACE.md#24-edges-out-of-this-repository) allows it |
| Used by | `mmdMotionAdapter`; later perhaps `usdVmdFileFormat` (MOT-O2) |
| Used by | `mmdMotionAdapter` (`motionCore`) and `mmdSkeletonAdapter` (`motionRetarget`); later perhaps `usdVmdFileFormat` (MOT-O2) |
| Consumed as | an installed package, by `find_package` with a version range admitting the release it was verified against, the way siblings are ([WORKSPACE.md §5](WORKSPACE.md#5-build-modes)) |
| Version | unset until its first release; its `v0.1.0` (core contract) carries `motionCore`, and `v0.2.0` (`motionRetarget`, with `motionUsd`'s reading half) is the one Phase 9 is designed against, since the adapter needs both |
| Version | `>=0.5,<0.6`, verified against v0.5.0 |
| OpenUSD | the same exact pin as §1 |
| Direction | one way: `usd-motion-plugins` never depends on this repository |

Expand Down
42 changes: 37 additions & 5 deletions docs/architecture/PACKAGE_CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ What each installed package promises a consumer: the name it is found by, the
target it links, the headers it installs, and what it needs besides. A
consumer relies on this page and on nothing else in the build tree; the
installed-consumer lane
([WORKSPACE.md §6](WORKSPACE.md#6-tests)) builds against a clean prefix to
keep it true.
([WORKSPACE.md §6](WORKSPACE.md#6-tests)) builds against a clean repository
prefix plus the explicitly pinned external motion packages to keep it true.

Status (2026-09-19): the two Phase 0 packages exist, `mmd_inspect` installs
Status (2026-09-21): the two Phase 0 packages exist, `mmd_inspect` installs
with the workspace since Phase 1, `mmdModel` since Phase 2, `motionVmd`,
`mmdMotionBinding` and `vmd_inspect` since Phase 7, and `mmdControl` since
Phase 9. Identities and
`mmdMotionBinding` and `vmd_inspect` since Phase 7, and `mmdControl`,
`mmdSkeletonAdapter` and `mmdMotionAdapter` since Phase 9. Identities and
dependency edges are [WORKSPACE.md](WORKSPACE.md)'s; this page does not
restate them.

Expand Down Expand Up @@ -110,6 +110,38 @@ builds a consumer that includes `mmdControl/Evaluator.h` and names
five packages alone. The installed-consumer lane's `control_probe` finds
`mmdControl` only, binds a VMD fixture to a PMX fixture and evaluates it.

## `mmdSkeletonAdapter`

| | |
| --- | --- |
| `find_package` | `find_package(mmdSkeletonAdapter 0.1 CONFIG REQUIRED)` |
| Imported target | `mmdSkeletonAdapter::mmdSkeletonAdapter` (static library), which links `mmdModel::mmdModel` and `motionRetarget::motionRetarget` publicly |
| Headers | `include/mmdSkeletonAdapter/` — `Adapter.h` |
| Required packages | `mmdModel` and released `motionRetarget >=0.5,<0.6`; the external package finds `motionCore` and the same OpenUSD foundation runtime |
| Language | C++20 (`cxx_std_20` is a usage requirement) |
| Version compatibility | `SameMinorVersion`, as `mmdPmx` |
| Installed files | `${CMAKE_INSTALL_LIBDIR}/` (the archive), `${CMAKE_INSTALL_LIBDIR}/cmake/mmdSkeletonAdapter/`, and `include/mmdSkeletonAdapter/` |

Its manifest pins `motionRetarget` by archive and OCI digest for each supported
target. The installed-consumer lane verifies the package from outside the
source tree against that external package.

## `mmdMotionAdapter`

| | |
| --- | --- |
| `find_package` | `find_package(mmdMotionAdapter 0.1 CONFIG REQUIRED)` |
| Imported target | `mmdMotionAdapter::mmdMotionAdapter` (static library), which links `mmdControl`, `mmdModel`, `mmdSkeletonAdapter` and `motionCore` publicly |
| Headers | `include/mmdMotionAdapter/` — `Adapter.h`, `Codes.h` |
| Required packages | the three repository packages above and released `motionCore >=0.5,<0.6` |
| Language | C++20 (`cxx_std_20` is a usage requirement) |
| Version compatibility | `SameMinorVersion`, as `mmdPmx` |
| Installed files | `${CMAKE_INSTALL_LIBDIR}/` (the archive), `${CMAKE_INSTALL_LIBDIR}/cmake/mmdMotionAdapter/`, and `include/mmdMotionAdapter/` |

Its manifest pins `motionCore` per target. The installed-consumer lane binds a
generated VMD to a generated PMX, evaluates it, and builds a shared
`MotionClip` through both installed adapters.

## `usdMmdFileFormat`

A plugin bundle, found by OpenUSD's plug registry rather than by CMake. It
Expand Down
Loading
Loading