From 5527d4cbaf170882b907a2e34f04ba0054396399 Mon Sep 17 00:00:00 2001 From: snkmcb Date: Tue, 22 Sep 2026 20:30:37 +0900 Subject: [PATCH] docs: adopt MmdMaterialAPI policy --- README.md | 13 +- docs/README.md | 5 +- docs/architecture/DEPENDENCIES.md | 2 +- docs/architecture/PACKAGE_CONTRACT.md | 23 ++- docs/architecture/WORKSPACE.md | 9 +- docs/design/DESIGN_POLICY.md | 90 +++++--- docs/design/MATERIAL_POLICY.md | 192 +++++++++++++----- docs/design/STAGE_CONTRACT.md | 34 +++- docs/reference/CAPABILITY_MATRIX.md | 4 +- docs/reference/SOURCE_MAPPING.md | 1 + .../reports/2026-09-16-phase4-local-models.md | 2 +- docs/roadmap/README.md | 24 ++- docs/roadmap/current.md | 43 +++- 13 files changed, 325 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 54ec5b1..4832b39 100644 --- a/README.md +++ b/README.md @@ -82,10 +82,14 @@ contract is [docs/design/PHYSICS_INTEGRATION.md](docs/design/PHYSICS_INTEGRATION | `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 -[admission test](docs/design/DESIGN_POLICY.md#6-the-schema-admission-test); the -first stage uses standard schemas only. Identities and dependency directions -are fixed in [docs/architecture/WORKSPACE.md](docs/architecture/WORKSPACE.md). +`MmdMaterialAPI` passed the +[admission test](docs/design/DESIGN_POLICY.md#6-the-schema-admission-test) on +2026-09-22 for the `hydra-toon` consumer. The current stage-contract v1 still +uses schema-less `mmd:material:*` attributes; Phase 8 adds `mmdSchema`, applies +the API as a backward-compatible contract-v1 addition, and adds the independent +`mmdImaging` bridge without renaming those properties. Identities and dependency +directions are fixed in +[docs/architecture/WORKSPACE.md](docs/architecture/WORKSPACE.md). ## What the importer will author @@ -93,6 +97,7 @@ are fixed in [docs/architecture/WORKSPACE.md](docs/architecture/WORKSPACE.md). /Asset UsdSkelRoot, kind = component, defaultPrim; Y-up, meters geo/Mesh UsdGeomMesh, skinned; one GeomSubset per material mtl/ UsdShadeMaterial: MMD semantics + /preview and /mtlx graphs + (Phase 8 target: + MmdMaterialAPI) skel/Skeleton UsdSkelSkeleton in canonical joint order morph/ UsdSkelBlendShape for vertex morphs; others preserved declaratively rig/Bones, rig/ik/ MMD control semantics: IK chains, append relations, axes — never solved diff --git a/docs/README.md b/docs/README.md index 767ac0a..f93897e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -53,8 +53,9 @@ place that says what is implemented. skinning, morph layout, and the stage-contract version; - [design/PMX_CONTRACT.md](design/PMX_CONTRACT.md) — how PMX 2.0/2.1 bytes are read and what each source concept becomes in the canonical model; - - [design/MATERIAL_POLICY.md](design/MATERIAL_POLICY.md) — `UsdPreviewSurface`, - MaterialX `gltf_pbr`, and the native MMD material semantics; + - [design/MATERIAL_POLICY.md](design/MATERIAL_POLICY.md) — `MmdMaterialAPI`, + native MMD semantics, `UsdPreviewSurface` / MaterialX fallbacks, and the + `mmdImaging` → `hydra-toon` boundary; - [design/TEXT_ENCODING_POLICY.md](design/TEXT_ENCODING_POLICY.md) — text decoding, source names versus USD identifiers, collisions, texture paths; - [design/MOTION_CONTRACT.md](design/MOTION_CONTRACT.md) — the MMD-specific diff --git a/docs/architecture/DEPENDENCIES.md b/docs/architecture/DEPENDENCIES.md index d701641..3e119f5 100644 --- a/docs/architecture/DEPENDENCIES.md +++ b/docs/architecture/DEPENDENCIES.md @@ -50,7 +50,7 @@ calls the MaterialX library. The MaterialX document version it declares | An image decoder in the importer | the importer never reads texture pixels; authoring stays independent of image content and of whether files exist ([TEXT_ENCODING_POLICY.md §7.3](../design/TEXT_ENCODING_POLICY.md#73-no-filesystem-access-while-authoring)) | | ICU, `iconv`, OS code-page APIs | PMX text is UTF-8 or UTF-16LE, decoded by the parser; CP932 (for VMD, PMD) uses a table the project owns ([TEXT_ENCODING_POLICY.md §9](../design/TEXT_ENCODING_POLICY.md#9-pmd-and-vmd)) | | A third-party PMX parser, by default | PMX is a bounded format; a purpose-built parser avoids inheriting an application's semantics ([DESIGN_POLICY.md §10](../design/DESIGN_POLICY.md#10-parser-strategy)) — adoption is possible only through §4 | -| OpenExec, Hydra, `hydra-toon`, `usd-stage-runner` | the importer neither evaluates nor renders ([WORKSPACE.md §2.2](WORKSPACE.md#22-forbidden-edges)); `mmdControl` evaluates as a plain library, and a runtime that wants it as an OpenExec node wraps it there | +| OpenExec, Hydra render delegates, `hydra-toon`, `usd-stage-runner` | the importer neither evaluates nor renders ([WORKSPACE.md §2.2](WORKSPACE.md#22-forbidden-edges)); `mmdImaging` uses only OpenUSD's UsdImaging API, `mmdControl` evaluates as a plain library, and a runtime that wants it as an OpenExec node wraps it there | | `motion-connectors`, device SDKs, network transports | live input reaches this repository only as the shared core's types, if at all ([WORKSPACE.md §2.2](WORKSPACE.md#22-forbidden-edges)) | | A copy of any `usd-motion-plugins` algorithm | generic motion is consumed, never duplicated ([WORKSPACE.md §7](WORKSPACE.md#7-invariants), invariant 9) | diff --git a/docs/architecture/PACKAGE_CONTRACT.md b/docs/architecture/PACKAGE_CONTRACT.md index 70e7412..c8611ac 100644 --- a/docs/architecture/PACKAGE_CONTRACT.md +++ b/docs/architecture/PACKAGE_CONTRACT.md @@ -7,7 +7,7 @@ installed-consumer lane ([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-21): the two Phase 0 packages exist, `mmd_inspect` installs +Status (2026-09-22): 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`, `mmdSkeletonAdapter` and `mmdMotionAdapter` since Phase 9. Identities and @@ -145,6 +145,22 @@ installed package contract. The installed-consumer lane binds a generated VMD to a generated PMX, evaluates it, and builds a shared `MotionClip` through both installed adapters. +## Planned Phase 8 plugin packages + +These identities are admitted by the design but do not exist in the current +install. Their exact library filenames and resource layout become binding when +the first installed-consumer fixture lands: + +| Bundle | Discovery | Public responsibility | +| --- | --- | --- | +| `mmdSchema` | OpenUSD plug registry and generated C++/Python API | Single-apply `MmdMaterialAPI`, its `mmd:material:*` declarations and tokens; no PMX record mirror | +| `mmdImaging` | OpenUSD plug registry | UsdImaging adapter from a composed `MmdMaterialAPI` to renderer-consumable Hydra data; no parser, importer or GPU implementation | + +The two bundles are separately discoverable: tools that only inspect the +schema do not load an imaging adapter. `mmdImaging` requires `mmdSchema` and +the matching OpenUSD UsdImaging runtime. Neither package requires +`hydra-toon`; the renderer consumes the published imaging contract. + ## `usdMmdFileFormat` A plugin bundle, found by OpenUSD's plug registry rather than by CMake. It @@ -161,7 +177,10 @@ relative to itself, and the installed bundle keeps the source bundle's shape. A host makes the plugin available by putting `plugin/resources/usdMmdFileFormat` on `PXR_PLUGINPATH_NAME`, with OpenUSD -26.08's libraries on the loader path. It needs no other package at run time. +26.08's libraries on the loader path. The current bundle needs no other package +at run time. From the Phase 8 migration it will include `mmdSchema` in its +declared plugin closure so the applied `MmdMaterialAPI` is discoverable; +it will not depend on `mmdImaging` or `hydra-toon`. ## `mmd_inspect` diff --git a/docs/architecture/WORKSPACE.md b/docs/architecture/WORKSPACE.md index 3d980e3..ac2fcb0 100644 --- a/docs/architecture/WORKSPACE.md +++ b/docs/architecture/WORKSPACE.md @@ -70,7 +70,8 @@ created ahead of that. | Identity | Kind | Directory | Role | Created when | | --- | --- | --- | --- | --- | | `mmdMaterial` | plain static CMake library | `libs/mmdMaterial/` | Canonical material semantics, extracted from `mmdModel` | material translation outgrows `mmdModel`, or a second consumer needs it alone ([DESIGN_POLICY.md §5.3](../design/DESIGN_POLICY.md#53-mmdmaterial--deferred)) | -| `mmdSchema` | plugin bundle (`usd-schema`) | `plugins/mmdSchema/` | Narrow applied API schemas | an API passes the admission test ([DESIGN_POLICY.md §6](../design/DESIGN_POLICY.md#6-the-schema-admission-test)) | +| `mmdSchema` | plugin bundle (`usd-schema`) | `plugins/mmdSchema/` | `MmdMaterialAPI`; no catch-all PMX schema | Phase 8 material work. The API passed the admission test on 2026-09-22 for the `hydra-toon` consumer ([DESIGN_POLICY.md §6](../design/DESIGN_POLICY.md#6-the-schema-admission-test)) | +| `mmdImaging` | plugin bundle (`usd-imaging`) | `plugins/mmdImaging/` | Exposes `MmdMaterialAPI` through UsdImaging data; no PMX parsing and no renderer-private GPU representation | Phase 8, after `MmdMaterialAPI` exists ([MATERIAL_POLICY.md §12](../design/MATERIAL_POLICY.md#12-rendering-and-integration-belong-elsewhere)) | | `usdVmdFileFormat` | plugin bundle (`usd-fileformat`) | `plugins/usdVmdFileFormat/` | `.vmd` `SdfFileFormat` over `motionVmd` | MOT-O2 is resolved against `usd-motion-plugins`' standalone motion stage (`/Animation`) ([MOTION_CONTRACT.md §9](../design/MOTION_CONTRACT.md#9-open-questions)) | | `mmd_convert` | CLI executable | `tools/mmdConvert/` | PMX → `.usda`/`.usdc` on disk | `usdcat` over the file format proves insufficient | | `mmdPmd` | plain static CMake library | `libs/mmdPmd/` | PMD syntax with its own CP932 policy | PMD support is decided ([DESIGN_POLICY.md §16](../design/DESIGN_POLICY.md#16-decisions-deliberately-left-flexible)) | @@ -87,7 +88,7 @@ live in a lower-camel directory. mmdPmx ──────────────→ (nothing in this repository; no OpenUSD) mmdModel ────────────→ mmdPmx (no OpenUSD) usdMmdFileFormat ────→ mmdModel, mmdPmx, OpenUSD - mmdSchema (only if it exists) + mmdSchema (from Phase 8) mmd_inspect ─────────→ mmdPmx (no OpenUSD) motionVmd ───────────→ nothing (no OpenUSD) mmdMotionBinding ────→ mmdModel, motionVmd (no OpenUSD) @@ -97,6 +98,7 @@ mmdControl ──────────→ mmdMotionBinding, mmdModel (no (later) mmdMaterial ─────────→ nothing in this repository; mmdModel → mmdMaterial mmdSchema ───────────→ OpenUSD only +mmdImaging ──────────→ mmdSchema, OpenUSD UsdImaging only mmdSkeletonAdapter ──→ mmdModel, usd-motion-plugins motionRetarget (OpenUSD foundation types only, through it) @@ -124,13 +126,14 @@ USD in the process | `mmdPmx → OpenUSD` | the parser exposes source facts, not USD policy | | `mmdPmx → mmdModel`, `mmdPmx → usdMmdFileFormat` | syntax never knows its consumers | | `mmdModel → OpenUSD`, `mmdModel → Hydra` | canonical semantics are renderer- and USD-independent | +| `mmdImaging → mmdPmx`, `mmdModel`, `usdMmdFileFormat`, `hydra-toon` | the adapter reads the composed `MmdMaterialAPI` contract and publishes imaging data; it neither reparses source data nor owns renderer code | | `motionVmd → usdMmdFileFormat`, `motionVmd → mmdModel`, `motionVmd → mmdPmx`, `vmd_inspect → mmdModel`, `vmd_inspect → mmdPmx` | a VMD never needs a model to parse | | `mmdModel → motionVmd`, `mmdModel → mmdMotionBinding` | a model never knows the motions bound to it; binding is its own step ([MOTION_CONTRACT.md §8](../design/MOTION_CONTRACT.md#8-binding-a-vmd-to-a-pmx-model)) | | `mmdMotionBinding → OpenUSD` | binding produces data a runtime consumes, not a stage | | `mmdControl → OpenUSD`, `mmdControl → usd-motion-plugins`, `mmdModel → mmdControl`, `mmdMotionBinding → mmdControl` | evaluation produces MMD-domain transforms; the model and the binding stay data, and normalization is the adapter's alone | | `mmdPmx`, `mmdModel`, `motionVmd`, `mmdMotionBinding`, `mmdControl` or `usdMmdFileFormat` `→ usd-motion-plugins` | only the two narrow adapter components cross into the shared motion core (§2.4), so parsing and evaluation remain independent | | any component → `motion-connectors`, a device SDK, a network transport | live input is normalized by `motion-connectors` into the shared core, never read here | -| `usdMmdFileFormat → hydra-toon` | the renderer consumes the stage, never the reverse | +| `usdMmdFileFormat → hydra-toon` | the renderer consumes `MmdMaterialAPI` through the USD/UsdImaging contract, never the importer or PMX | | `usdMmdFileFormat → usd-stage-runner` | the importer has no update loop | | parser, canonical model or importer → `usd-physics-plugins` | the static path only preserves physics; only a future MMD runtime adapter may consume the optional shared package ([PHYSICS_INTEGRATION.md §8](../design/PHYSICS_INTEGRATION.md#8-dependency-policy)) | | any component → Jolt, PhysX, Bullet or another physics backend | backend ownership is `usd-physics-plugins`'; even the future MMD coupling adapter depends only on the shared contract | diff --git a/docs/design/DESIGN_POLICY.md b/docs/design/DESIGN_POLICY.md index b8ea3b3..0ec07f6 100644 --- a/docs/design/DESIGN_POLICY.md +++ b/docs/design/DESIGN_POLICY.md @@ -86,7 +86,7 @@ carries, in this order of priority: 2. generic material realizations (`UsdPreviewSurface`, MaterialX `gltf_pbr`); 3. MMD-native semantics where nothing generic can hold them. -An MMD-aware renderer such as a future `hydra-toon` reads level 3 as well; a +An MMD-aware renderer such as `hydra-toon` reads level 3 as well; a generic consumer ignores it and still sees a correct, bound, skinned model (§11). @@ -143,8 +143,10 @@ What deliberately does **not** carry over: embeds its textures in a GLB container. A PMX references external files, so standard `ArResolver` behavior is sufficient ([TEXT_ENCODING_POLICY.md §7](TEXT_ENCODING_POLICY.md#7-texture-paths)). -- **No schema bundle by default.** `vrmSchema` exists because VRM has typed - semantics consumers read. `mmdSchema` must pass its own admission test (§6). +- **No catch-all schema bundle.** `vrmSchema` exists because VRM has typed + semantics consumers read. `MmdMaterialAPI` has now passed this repository's + admission test for `hydra-toon`; that admits only the narrow material API, + not a schema mirror of PMX (§6). - **No humanoid assumption.** MMD bone names are a community convention, not a humanoid specification, so the importer authors no humanoid semantics. Retargeting still needs a humanoid map, and the shared motion core leaves @@ -293,9 +295,20 @@ Neither owns a generic algorithm or target-avatar knowledge: sampling, retargeting, recording and `UsdSkelAnimation` authoring are used from the shared core ([MOTION_CONTRACT.md §10](MOTION_CONTRACT.md#10-normalizing-into-the-shared-motion-core)). +### 5.8 `mmdSchema` and `mmdImaging` — the renderer edge (Phase 8) + +`mmdSchema` owns the generated single-apply `MmdMaterialAPI` and its tokens. +`usdMmdFileFormat` applies that API and authors through its accessors in Phase +8. `mmdImaging` reads the composed API and exposes its values +through UsdImaging for `hydra-toon`; it depends on neither the parser, +canonical model nor importer, and owns no GPU representation. This keeps the +contract usable by any renderer and lets `hydra-toon` consume MMD and MToon +through independent format adapters +([MATERIAL_POLICY.md §12](MATERIAL_POLICY.md#12-rendering-and-integration-belong-elsewhere)). + ## 6. The schema admission test -`mmdSchema` is not created because `vrmSchema` exists. A candidate API schema +`mmdSchema` is not created merely because `vrmSchema` exists. A candidate API schema (`MmdModelAPI`, `MmdMaterialAPI`, `MmdBoneAPI`, `MmdPhysicsAPI`, …) is admitted only if it passes: @@ -304,14 +317,24 @@ only if it passes: If not, the value stays as provenance, custom data, or is not authored. -The v1 stage therefore has **no custom typed prim schemas and no applied API +Stage-contract v1 has **no custom typed prim schemas and no applied API schemas**. Semantics that a consumer evaluates are authored as namespaced -custom attributes (`mmd:material:*`, `mmd:morph:*`, …) whose names a later -applied API schema can declare verbatim, so admitting a schema does not change -the authored stage -([STAGE_CONTRACT.md §3](STAGE_CONTRACT.md#3-authoring-conventions)). An API is -proposed when a real consumer asks for one, and the proposal cites that -consumer. `mmdSchema` must not become a dump of the PMX binary structure. +custom attributes (`mmd:material:*`, `mmd:morph:*`, …), so a later applied API +can declare the names verbatim +([STAGE_CONTRACT.md §3](STAGE_CONTRACT.md#3-authoring-conventions)). + +`MmdMaterialAPI` passed the test on 2026-09-22: `hydra-toon` must discover MMD +materials and read their canonical values from a composed USD stage without +PMX access. The single-apply API declares only the existing +`mmd:material:*` contract; provenance remains `customData`, and morph, rig and +physics properties remain schema-less until they independently pass this test. +Applying the API is a backward-compatible stage-contract v1 addition: the +property names, types and meanings do not change, and existing readers may +ignore the applied-schema metadata +([MATERIAL_POLICY.md §4.3](MATERIAL_POLICY.md#43-mmdmaterialapi)). A generated +API plus a UsdImaging adapter is the renderer boundary; a third material +realization graph is not. `mmdSchema` must not become a dump of the PMX binary +structure. ## 7. Deformation, morph and bone-control policy @@ -444,7 +467,7 @@ what it does not understand: | --- | --- | --- | | 1 | Any USD tool | mesh, materials, skeleton, skinning, blend shapes, textures | | 2 | A MaterialX-aware renderer | the `gltf_pbr` realization | -| 3 | An MMD-aware Hydra renderer (`hydra-toon`) | toon ramp, sphere map, outline, MMD alpha and draw behavior | +| 3 | An MMD-aware Hydra renderer (`hydra-toon`) | `MmdMaterialAPI` through a UsdImaging adapter: toon ramp, sphere map, outline, MMD alpha and draw behavior | | 4 | An avatar runtime (`usd-avatar-runtime`) | VMD, IK, bone control, morph composition, physics, live motion | This layering is preferred to making every USD consumer understand MMD. @@ -506,7 +529,7 @@ sequence ever appear, both get a qualifier, as they do in `usd-vrm-plugins`. | **5 — control semantics** | Narrow MMD semantics for IK, append transforms, axes, morph composition and material morphs — schema only where §6 admits one. | A consumer can reconstruct every IK chain and append relation from the stage alone. | | **6 — physics preservation** | Standard `UsdPhysics` where it matches; everything else preserved. | No simulation; every rigid body and joint recoverable. | | **7 — VMD** | Model-independent `libs/motionVmd` (defined as extraction-ready; VMD stays here since 2026-09-17, §9.1), bound to a model by `mmdMotionBinding`; the hand-off to the shared motion core is Phase 9; `usdVmdFileFormat` only once direct stage-open has a contract. | Per [MOTION_CONTRACT.md](MOTION_CONTRACT.md). | -| **8 — avatar runtime composition** | Composition through OpenStrata with `usd-vrm-plugins`, `usd-motion-plugins`, `usd-physics-plugins`, `motion-connectors`, `hydra-toon` and `usd-stage-runner`, under `usd-avatar-runtime`; MMD-specific physics coupling follows [PHYSICS_INTEGRATION.md](PHYSICS_INTEGRATION.md). | The runtime, not this repository, is the avatar execution environment; physics can progress from `followBone` through dynamic bodies to bone feedback without putting a solver in the importer. | +| **8 — avatar runtime composition** | Composition through OpenStrata with `usd-vrm-plugins`, `usd-motion-plugins`, `usd-physics-plugins`, `motion-connectors`, `hydra-toon` and `usd-stage-runner`, under `usd-avatar-runtime`; this repository first supplies `MmdMaterialAPI` and its UsdImaging bridge, while MMD-specific physics coupling follows [PHYSICS_INTEGRATION.md](PHYSICS_INTEGRATION.md). | The runtime, not this repository, is the avatar execution environment; `hydra-toon` consumes MMD semantics without PMX or importer dependencies, and physics can progress from `followBone` through dynamic bodies to bone feedback without putting a renderer or solver in the importer. | | **9 — shared motion core adoption** | `mmdControl` evaluates a bound motion over the control rig; `mmdMotionAdapter` builds a `MotionClip`, while `mmdSkeletonAdapter` builds a `SkeletonDescriptor`, `SourceRestPose` and humanoid `RetargetMap`, against `usd-motion-plugins`' installed `motionCore` and `motionRetarget`; MOT-O5, MOT-O6 and MOT-O7 resolved ([MOTION_CONTRACT.md §10](MOTION_CONTRACT.md#10-normalizing-into-the-shared-motion-core)). | On synthetic rigs with known answers, IK and append evaluation match; the same inputs give the same bits; a VMD-derived `MotionClip`, authored by the shared core as `UsdSkelAnimation`, poses the PMX stage's skeleton with legs driven by IK; the same clip retargets to a non-MMD synthetic skeleton through the shared retarget with no MMD code on that path; no generic motion algorithm exists in this repository. | Phases are numbered in the order they were defined, not the order they run. @@ -560,15 +583,17 @@ structural ones, a change to WORKSPACE.md first. | 9 | The static importer / runtime evaluator boundary | §2.2 | | 10 | VMD is never hard-wired into PMX loading | §9 | | 11 | This repository consumes `usd-motion-plugins` only through its narrow motion and skeleton adapters, and is never consumed by it | [WORKSPACE.md §2.4](../architecture/WORKSPACE.md#24-edges-out-of-this-repository) | +| 12 | `MmdMaterialAPI` is the canonical USD schema for MMD material semantics; `preview` and `mtlx` remain fallbacks | [MATERIAL_POLICY.md §4.3](MATERIAL_POLICY.md#43-mmdmaterialapi) | ## 16. Decisions deliberately left flexible Not frozen, and not to be frozen until at least two plausible consumers or one -real implementation demonstrate the need: custom MMD API schema names; the -physics backend; `mmdControl`'s public API, until Phase 9 has a consumer; an -SDEF GPU implementation; the toon renderer's architecture; the humanoid role -table's contents (MOT-O6); Python or JavaScript bindings; USD export policy; -PMD support. The retarget API is not on this list: it is +real implementation demonstrate the need: any MMD API schema beyond +`MmdMaterialAPI`; a shared USD-level `ToonMaterialAPI`; the physics backend; +`mmdControl`'s public API, until Phase 9 has a consumer; an SDEF GPU +implementation; `hydra-toon`'s private GPU and common-runtime architecture; +the humanoid role table's contents (MOT-O6); Python or JavaScript bindings; USD +export policy; PMD support. The retarget API is not on this list: it is `usd-motion-plugins`', not this repository's to freeze or leave open. ## 17. Non-goals for the first releases @@ -588,19 +613,18 @@ Some of these exist elsewhere in the ecosystem (§18); none belongs here. ┌──────────────────────┼──────────────────────┐ usd-motion-plugins usd-stage-runner hydra-toon └─────────────── USD scene contract ──────────┘ - ▲ - usd-mmd-plugins - ┌──────────────────┴──────────────────┐ - usdMmdFileFormat usdVmdFileFormat (later) - │ │ - mmdModel ── mmdSchema (only if §6) motionVmd - │ \ / - mmdPmx └──── mmdMotionBinding ──────┘ - │ │ - PMX mmdControl (Phase 9) - │ - mmdMotionAdapter (Phase 9) ─┐ - mmdSkeletonAdapter (Phase 9) ─┴→ usd-motion-plugins + ▲ ▲ + usdMmdFileFormat mmdImaging + ▲ ▲ │ + mmdModel mmdSchema/MmdMaterialAPI + ▲ + mmdPmx ← PMX + + VMD ─→ motionVmd ─→ mmdMotionBinding ─→ mmdControl (Phase 9) + ├─→ mmdMotionAdapter ───┐ + mmdModel ─────└─→ mmdSkeletonAdapter ┴→ usd-motion-plugins + + usdVmdFileFormat (later) reads motionVmd once MOT-O2 is resolved. ``` Every arrow points toward a more general contract. The PMX parser knows nothing @@ -615,7 +639,7 @@ than forcing them into one library. | `usd-motion-plugins` | motion representation (`MotionPose`, `MotionClip`), humanoid joint semantics, sampling, retarget, recording, the `UsdSkelAnimation` bridge | | `usd-physics-plugins` | backend-neutral physics worlds, stepping, queries and backend integration | | `motion-connectors` | live external inputs, normalized into `usd-motion-plugins`' types | -| `hydra-toon` | toon rendering, consuming the USD contract — never PMX | +| `hydra-toon` | MToon and MMD toon rendering through format-specific schema adapters, consuming the USD contract — never PMX | | `usd-stage-runner` | the update and evaluation loop | | `usd-avatar-runtime` | OpenStrata composition, scheduling of evaluation, and the cross-format avatar contract | @@ -638,7 +662,7 @@ the Phase that first authors it lands with a fixture, and binding from then. | Implementation policy | Here | Why | Status | | --- | --- | --- | --- | | §6.1, §6.8 — `/Asset` is a `UsdGeomXform`; `/Asset/rig/SkelRoot/Skeleton` | `/Asset` is the `UsdSkelRoot` when the model has bones; the skeleton is `/Asset/skel/Skeleton` | `UsdSkel` only skins geometry beneath a `SkelRoot`, so meshes under `/Asset/geo` would not deform under `/Asset/rig/SkelRoot`. The `skel`/`rig` split is `usd-vrm-plugins`' layout and matches §7.3's own deformation/control split ([STAGE_CONTRACT.md §4.1](STAGE_CONTRACT.md#41-why-asset-is-the-skelroot)). | binding (Phase 2) | -| §10 — a `native` child under each material | Native semantics are attributes on the `UsdShadeMaterial` itself | A child graph reads as a third realization; the material prim is where identity and semantics already live in the VRM material policy ([MATERIAL_POLICY.md §3](MATERIAL_POLICY.md#3-hierarchy)). | binding (Phases 2 and 3) | +| §10 — a `native` child under each material | Native semantics are `mmd:material:*` attributes on the `UsdShadeMaterial` itself, declared by `MmdMaterialAPI` from Phase 8 | A child graph reads as a third realization; the material prim is where identity and semantics already live. The API formalizes the existing attributes without becoming a realization ([MATERIAL_POLICY.md §3](MATERIAL_POLICY.md#3-hierarchy)). | binding for attributes (Phases 2 and 3); API authoring scheduled in Phase 8 | | §27 — `customLayerData.mmdSchemaContractVersion` | `/Asset.customData.mmd:stageContractVersion` | Layer metadata is not composed, so it is lost once the asset is referenced; `/Asset` customData travels with the reference, and matches `vrm:schemaContractVersion` ([STAGE_CONTRACT.md §2](STAGE_CONTRACT.md#2-contract-version)). | binding (Phase 0) | | §19 — `mmdModel` may or may not depend on `mmdPmx`; OpenUSD unspecified | `mmdModel → mmdPmx`; no OpenUSD in either | §26's `Canonicalize(const pmx::Document&)` settles the first; the second keeps canonical MMD usable by non-USD tools ([WORKSPACE.md §2](../architecture/WORKSPACE.md#2-dependency-directions)). | binding (Phase 2) | | §15.2 — stable-ID precedence includes transliteration and recognized roles | Contract v1 uses the English name or an index fallback only | Both a transliteration table and a role table would become part of the stage ABI; they stay open until a consumer needs them ([TEXT_ENCODING_POLICY.md §6](TEXT_ENCODING_POLICY.md#6-stable-identifiers)). | binding (Phase 2) | diff --git a/docs/design/MATERIAL_POLICY.md b/docs/design/MATERIAL_POLICY.md index 71c230e..d7f4913 100644 --- a/docs/design/MATERIAL_POLICY.md +++ b/docs/design/MATERIAL_POLICY.md @@ -1,15 +1,17 @@ # Material policy -> Status: **binding for Phase 3**; authored from Phase 3, except what Phase 2 already -> authors with fixtures — one `UsdShadeMaterial` per PMX material at its -> §3 path, bound by its subset; `mmd:material:doubleSided` and the three -> texture slots of §4.1; and the provenance of §4.2 but `mmd:sourceMemo` — -> which is binding. It fixes how a PMX material -> becomes a `UsdShadeMaterial`: the hierarchy, the canonical MMD semantics, and -> the two portable realizations. It follows the shape of `usd-vrm-plugins`' -> material architecture policy so that one renderer can read both families, -> and on material questions it wins over -> [STAGE_CONTRACT.md](STAGE_CONTRACT.md). Section numbers are stable. +> Status: **binding for Phase 3 and for the planned material-schema migration**. +> Phase 3 authors one `UsdShadeMaterial` per PMX material, the +> `mmd:material:*` attributes in §4.1, provenance in §4.2, and the two portable +> realizations. Stage-contract v1 authors those attributes as schema-less custom +> attributes. `MmdMaterialAPI` passed the schema admission test on 2026-09-22; +> Phase 8 applies it while retaining the same property names, types and meanings +> as a backward-compatible stage-contract v1 addition (§4.3, §14). This +> document fixes the hierarchy, canonical MMD semantics, portable realizations +> and renderer boundary. It follows the +> shape of `usd-vrm-plugins`' material architecture without treating MMD as +> MToon, and on material questions it wins over +> [STAGE_CONTRACT.md](STAGE_CONTRACT.md). Existing section numbers are stable. --- @@ -30,9 +32,11 @@ realization from the semantics — never one realization from another. PMX material ↓ canonical MMD material semantics (mmdModel) + ↓ +MmdMaterialAPI formal USD contract (Phase 8 target) ├→ UsdPreviewSurface unlit-compatible fallback /preview ├→ MaterialX gltf_pbr unlit-compatible portable path /mtlx - └→ MMD toon realization hydra-toon, elsewhere (not authored here) + └→ UsdImaging adapter hydra-toon, elsewhere (not authored here) ``` The cost is that the same source parameter is read by several generators. What @@ -43,6 +47,7 @@ requires reading nothing but the semantics. ```text /Asset/mtl/ UsdShadeMaterial + applied API: MmdMaterialAPI (Phase 8 target) mmd:material:* canonical MMD semantics (§4) customData: provenance (§4.2) outputs:surface → preview.outputs:surface @@ -77,37 +82,42 @@ requires reading nothing but the semantics. child graph reads as a third realization and the material prim is where identity and semantics already live ([DESIGN_POLICY.md §19](DESIGN_POLICY.md#19-where-this-document-departs-from-the-implementation-policy)). +- Applying `MmdMaterialAPI` does not create a new child or realization. It + declares the existing canonical properties and identifies the prim as an MMD + material. Bindings and render-context outputs continue to target the + `UsdShadeMaterial`. ## 4. Canonical material semantics ### 4.1 Attributes Every material carries its full MMD semantics, whether or not any realization -uses them. They are plain custom attributes, so an `MmdMaterialAPI` admitted -later can declare the same names without changing the stage. +uses them. The shipped stage-contract v1 implementation authors them as plain +custom attributes. Phase 8 declares the same names through `MmdMaterialAPI`; no +consumer has to translate an old property name to a new one. -| Attribute | Type | Source | -| --- | --- | --- | -| `mmd:material:diffuseColor` | `color4f` | diffuse RGBA | -| `mmd:material:specularColor` | `color3f` | specular | -| `mmd:material:specularPower` | `float` | specular power | -| `mmd:material:ambientColor` | `color3f` | ambient | -| `mmd:material:doubleSided` | `uniform bool` | flag `0x01` | -| `mmd:material:groundShadow` | `bool` | flag `0x02` | -| `mmd:material:castSelfShadow` | `bool` | flag `0x04` | -| `mmd:material:receiveSelfShadow` | `bool` | flag `0x08` | -| `mmd:material:drawEdge` | `bool` | flag `0x10` | -| `mmd:material:vertexColor` | `bool` | flag `0x20` (2.1) | -| `mmd:material:drawPoints` | `bool` | flag `0x40` (2.1) | -| `mmd:material:drawLines` | `bool` | flag `0x80` (2.1) | -| `mmd:material:edgeColor` | `color4f` | edge color | -| `mmd:material:edgeSize` | `float` | edge size | -| `mmd:material:texture` | `asset` | base texture (absent when none) | -| `mmd:material:sphereTexture` | `asset` | sphere texture (absent when none) | -| `mmd:material:sphereMode` | `token` | `disabled`, `multiply`, `add`, `subTexture` | -| `mmd:material:toonSource` | `token` | `none`, `individual`, `shared` (§7) | -| `mmd:material:toonTexture` | `asset` | individual toon texture (only when `individual`) | -| `mmd:material:sharedToonIndex` | `int` | shared toon slot 0–9 (only when `shared`) | +| Attribute | Type | PMX source | Authoring | +| --- | --- | --- | --- | +| `mmd:material:diffuseColor` | `color4f` | diffuse RGBA | required | +| `mmd:material:specularColor` | `color3f` | specular | required | +| `mmd:material:specularPower` | `float` | specular power | required | +| `mmd:material:ambientColor` | `color3f` | ambient | required | +| `mmd:material:doubleSided` | `uniform bool` | flag `0x01` | required | +| `mmd:material:groundShadow` | `bool` | flag `0x02` | required | +| `mmd:material:castSelfShadow` | `bool` | flag `0x04` | required | +| `mmd:material:receiveSelfShadow` | `bool` | flag `0x08` | required | +| `mmd:material:drawEdge` | `bool` | flag `0x10` | required | +| `mmd:material:vertexColor` | `bool` | flag `0x20` (2.1 meaning) | required; preserved in 2.0 without assigning 2.1 meaning | +| `mmd:material:drawPoints` | `bool` | flag `0x40` (2.1 meaning) | required; preserved in 2.0 without assigning 2.1 meaning | +| `mmd:material:drawLines` | `bool` | flag `0x80` (2.1 meaning) | required; preserved in 2.0 without assigning 2.1 meaning | +| `mmd:material:edgeColor` | `color4f` | edge color | required even when `drawEdge = false` | +| `mmd:material:edgeSize` | `float` | edge size | required even when `drawEdge = false` | +| `mmd:material:texture` | `asset` | base texture | only when the slot names a safe asset path | +| `mmd:material:sphereTexture` | `asset` | sphere texture | only when the slot names a safe asset path | +| `mmd:material:sphereMode` | `token` | `disabled`, `multiply`, `add`, `subTexture` | required | +| `mmd:material:toonSource` | `token` | `none`, `individual`, `shared` (§7) | required | +| `mmd:material:toonTexture` | `asset` | individual toon texture | only when `toonSource = individual` and the path is safe | +| `mmd:material:sharedToonIndex` | `int` | shared toon slot 0–9 | only when `toonSource = shared` | Colors are authored as stored: MMD specifies them without a declared color space, and the importer does not reinterpret them. @@ -121,6 +131,38 @@ the verbatim decoded texture strings `mmd:sourceTexturePath`, the path is unsafe or does not resolve ([TEXT_ENCODING_POLICY.md §7](TEXT_ENCODING_POLICY.md#7-texture-paths)). +### 4.3 `MmdMaterialAPI` + +`MmdMaterialAPI` is a **single-apply API schema** on `UsdShadeMaterial`. It is +the formal USD contract for §4.1, not a renderer implementation and not a copy +of the PMX record layout. It passed +[DESIGN_POLICY.md §6](DESIGN_POLICY.md#6-the-schema-admission-test) because an +MMD-aware renderer needs to discover and read these values from a composed USD +stage without PMX access. + +The generated API exposes every §4.1 property, tokens for `sphereMode` and +`toonSource`, and schema fallbacks that are neutral when a property is absent: + +| Property family | Schema fallback | +| --- | --- | +| diffuse | `(1, 1, 1, 1)` | +| specular, ambient | `(0, 0, 0)` | +| specular power | `0` | +| drawing and shadow flags | `false` | +| edge color, edge size | `(0, 0, 0, 0)`, `0` | +| asset-valued texture slots | empty asset path | +| sphere mode | `disabled` | +| toon source, shared toon index | `none`, `-1` | + +The importer still authors every scalar and flag that exists in a PMX material; +fallbacks define robust reads, not permission to discard source values. Asset +slots remain conditional as §4.1 states. Provenance stays in `customData` and +is deliberately outside the API. + +Consumers use generated schema accessors rather than treating attribute-name +strings as their public interface. During migration they must also accept a +stage-contract v1 material with the same schema-less properties (§14). + ## 5. UsdPreviewSurface realization The broad compatibility fallback, and the easiest one to debug. To keep the @@ -235,21 +277,43 @@ color and size, and the texture, sphere and toon tints. The stage never contains a precomputed material per morph, and a morph never edits the material prims. -## 12. Rendering belongs elsewhere +## 12. Rendering and integration belong elsewhere + +`usd-mmd-plugins` defines and authors MMD semantics; it contains no toon +renderer, outline pass, shadow algorithm or GPU shader. `hydra-toon` consumes +the composed USD contract and never parses PMX. The portable `gltf_pbr` path +stays the default realization; MMD-aware rendering is an additional path, not a +replacement. + +An applied API schema alone does not make arbitrary prim properties appear in +a Hydra material network. The fixed integration boundary is therefore: + +```text +UsdShadeMaterial + MmdMaterialAPI + ↓ + UsdImaging adapter + ↓ + Hydra material representation + ↓ + hydra-toon +``` + +The adapter exposes the API's semantics through the Hydra data-source or +material-data mechanism appropriate to the OpenUSD version. It does not add a +third `toon` realization graph, and `hydra-toon` does not depend on +`usdMmdFileFormat`, `mmdModel` or `mmdPmx`. -`usd-mmd-plugins` contains no MMD renderer. A toon renderer (`hydra-toon`) -consumes this contract; it never parses PMX, and the same renderer can serve -MToon from `usd-vrm-plugins` through its own semantic reading. The portable -`gltf_pbr` path stays the default realization; toon rendering is an additional -path, not a replacement. +`hydra-toon` may normalize `MmdMaterialAPI` and the independent +`VrmMtoonMaterialAPI` into a renderer-private runtime representation. That is +an implementation convenience, not a claim that MMD and MToon have the same +material model. MMD-only concepts — sphere multiply/add, sub-texture UVs, +shared toon slots, ground/self-shadow flags and vertex edge scale — remain +explicit extensions where they cannot be shared faithfully. -A known gap for that consumer: custom attributes on a material prim do not -reach a Hydra render delegate by themselves — `UsdImaging` passes the material -*network*, not arbitrary prim properties. `hydra-toon` will need either an -admitted `MmdMaterialAPI` with an imaging adapter that exposes it, or a third -realization graph for its own render context. That choice is deferred to when -`hydra-toon` exists to be a real consumer (MAT-O4), and either answer keeps §4 -unchanged. +No USD-level `ToonMaterialAPI` is introduced now. A common API may be +reconsidered only after both MMD and VRM paths have been implemented and stable +common semantics are demonstrated. Shared abstractions are extracted from +working concrete adapters, not designed ahead of them. ## 13. Open questions @@ -258,4 +322,34 @@ unchanged. | MAT-O1 | Roughness from specular power | resolved for the current portable realizations: they are unlit and author `roughness = 1`; `specularPower` remains canonical for an MMD-aware realization | Phase 3 | | MAT-O2 | Alpha mode without decoding images: the importer never reads texture pixels, so it cannot know whether a texture has alpha | resolved: blend when the material names a base texture or diffuse alpha < 1; opaque otherwise | Phase 3 | | MAT-O3 | Missing individual toon texture | resolved: preserve the source path and provenance, author a safe asset path when available so USD validation can report an unresolved file, and never fall back to a shared ramp | Phase 3 | -| MAT-O4 | How `hydra-toon` reads MMD semantics | `MmdMaterialAPI` + imaging adapter, or a toon realization graph | when `hydra-toon` consumes the stage | +| MAT-O4 | How `hydra-toon` reads MMD semantics | resolved: applied `MmdMaterialAPI` + UsdImaging adapter; no toon realization graph | design fixed 2026-09-22; implementation in Phase 8 | + +## 14. Migration and implementation order + +The policy is implemented without rewriting the already shipped Phase 3 +contract: + +1. **Inventory — complete in this document.** §4.1 fixes names, types, + required/conditional authoring and PMX mapping; §4.3 fixes fallbacks. +2. **Schema bundle.** Add `mmdSchema` with the single-apply + `MmdMaterialAPI`, generated C++/Python accessors and token declarations. +3. **Importer migration.** Apply the API and author through its accessors while + keeping the §4.1 property values byte-for-byte equivalent. The applied-schema + metadata is an additive stage-contract v1 change, not a semantic version bump. +4. **Fallback regression.** Keep `/preview` and `/mtlx` graph boundaries and + appearance unchanged; they remain generic fallbacks, not canonical data. +5. **Hydra bridge.** Implement and test the UsdImaging adapter independently + of the renderer's GPU representation. +6. **MMD renderer path.** Bring up diffuse/alpha, toon ramp, sphere + multiply/add, sub-texture, outline, shadow flags, material morph runtime, + then advanced UV and vertex-color behavior. +7. **Common-runtime review.** Compare the completed MMD and VRM adapters and + extract only proven renderer-private common code. Revisit a USD-level + `ToonMaterialAPI` only with evidence from both. + +Compatibility is asymmetric and explicit: a schema-aware reader accepts an +earlier contract-v1 material by reading the same names even when +`MmdMaterialAPI` is not applied; an existing reader can ignore `apiSchemas` and +continues to see the same custom properties and fallback graphs. No migration +renames a property or turns PreviewSurface or MaterialX into the source of +truth. diff --git a/docs/design/STAGE_CONTRACT.md b/docs/design/STAGE_CONTRACT.md index dedc89d..406ef94 100644 --- a/docs/design/STAGE_CONTRACT.md +++ b/docs/design/STAGE_CONTRACT.md @@ -19,6 +19,12 @@ > graph boundaries are binding from Phase 3; their interior shader node names > remain realization-local. > +> `MmdMaterialAPI` is admitted but not yet authored by the current contract-v1 +> implementation. Its planned application is additive within contract v1: the +> existing `mmd:material:*` names, types and meanings remain unchanged, and +> readers have an explicit compatibility path +> ([MATERIAL_POLICY.md §14](MATERIAL_POLICY.md#14-migration-and-implementation-order)). +> > This document fixes the exact USD that `usdMmdFileFormat` authors from a PMX: > stage metadata, prim hierarchy, types, names, the coordinate conversion, and > the layout of skeleton, materials, morphs, control rig and physics. Material graphs are detailed in @@ -50,8 +56,9 @@ layer's `customLayerData` is no longer visible from the composed stage, while The version increments **only** when downstream interpretation changes incompatibly: a path, type, name, unit, basis, or property meaning a consumer could depend on. It does not change for parser refactors, diagnostic wording, -build-system changes, performance work, or the addition of a property a -consumer can ignore. +build-system changes, performance work, the addition of a property a consumer +can ignore, or applying `MmdMaterialAPI` while its existing properties retain +the same names, types and meanings. ## 3. Authoring conventions @@ -67,11 +74,13 @@ consumer can ignore. - **Provenance of an element that is not a prim** — a joint, a vertex — is a parallel array attribute on the prim that owns the elements (`mmd:bone:sourceName` on the Skeleton, for example). -- **Semantics a consumer evaluates are namespaced custom attributes**: +- **Semantics a consumer evaluates are namespaced attributes**: `mmd:material:*`, `mmd:morph:*`, `mmd:rig:*`, `mmd:physics:*`. They are - attributes rather than customData so they can be queried, overridden in a - stronger layer, and later declared verbatim by an applied API schema without - changing the stage ([DESIGN_POLICY.md §6](DESIGN_POLICY.md#6-the-schema-admission-test)). + attributes rather than customData so they can be queried and overridden in a + stronger layer. The current implementation authors all of them as custom + attributes; Phase 8 applies `MmdMaterialAPI` and declares the existing + material names verbatim, while the other families remain schema-less + ([DESIGN_POLICY.md §6](DESIGN_POLICY.md#6-the-schema-admission-test)). - **Per-vertex MMD data is a primvar** in the `mmd:` namespace (`primvars:mmd:uv1`, `primvars:mmd:edgeScale`, …), so it follows the mesh through any primvar-aware pipeline. @@ -91,7 +100,7 @@ consumer can ignore. │ └─ Mesh UsdGeomMesh + UsdSkelBindingAPI │ └─ UsdGeomSubset (familyName = materialBind), one per non-empty material ├─ mtl Scope -│ └─ UsdShadeMaterial (graphs: MATERIAL_POLICY.md) +│ └─ UsdShadeMaterial (Phase 8: + MmdMaterialAPI; graphs: MATERIAL_POLICY.md) ├─ skel Scope │ └─ Skeleton UsdSkelSkeleton ├─ morph Scope (Phase 4) @@ -429,7 +438,10 @@ vertex. One `UsdShadeMaterial` per PMX material at `/Asset/mtl/`, in material-table order, carrying the MMD source semantics as `mmd:material:*` attributes and two realization graphs, `preview` and `mtlx`. Bindings target -the material prim, never a node inside it. Fully specified in +the material prim, never a node inside it. The current implementation authors +schema-less custom attributes; Phase 8 applies the single-apply +`MmdMaterialAPI` and authors the same properties through its generated +accessors. Fully specified in [MATERIAL_POLICY.md](MATERIAL_POLICY.md). Each material carries its provenance (`mmd:sourceName`, @@ -441,6 +453,12 @@ full MMD semantics are authored as `mmd:material:*` attributes, and both portable realization graphs are present from Phase 3 as specified by MATERIAL_POLICY.md. +`MmdMaterialAPI` is canonical identification and declaration, not a third +realization. A schema-aware consumer uses its generated accessors when the API +is applied and accepts the same schema-less property names on an earlier +contract-v1 asset. PreviewSurface and MaterialX remain generic fallbacks and are +never used to reconstruct canonical MMD values. + The material-table index is also MMD's **draw order**, which alpha-blended MMD rendering depends on; it is preserved as `mmd:sourceIndex` and consumers that need draw order read it from there. diff --git a/docs/reference/CAPABILITY_MATRIX.md b/docs/reference/CAPABILITY_MATRIX.md index 2e73f76..0963c9a 100644 --- a/docs/reference/CAPABILITY_MATRIX.md +++ b/docs/reference/CAPABILITY_MATRIX.md @@ -160,6 +160,7 @@ lane against digest-pinned `usd-motion-plugins` v0.5.0 packages. | `UsdPreviewSurface` | approximated | approximated | 3 | [MATERIAL §5](../design/MATERIAL_POLICY.md#5-usdpreviewsurface-realization) | | MaterialX `gltf_pbr` | approximated | approximated | 3 | [MATERIAL §6](../design/MATERIAL_POLICY.md#6-materialx-gltf_pbr-realization) | | Native MMD material semantics | preserved | preserved | 3 | [MATERIAL §4](../design/MATERIAL_POLICY.md#4-canonical-material-semantics) | +| `MmdMaterialAPI` application | — (planned; current v1 properties are schema-less) | — (planned; current v1 properties are schema-less) | 8 | [MATERIAL §4.3](../design/MATERIAL_POLICY.md#43-mmdmaterialapi), [§14](../design/MATERIAL_POLICY.md#14-migration-and-implementation-order) | | Sphere textures | preserved | preserved | 3 | [MATERIAL §8](../design/MATERIAL_POLICY.md#8-sphere-textures) | | Toon ramps (individual and shared) | preserved | preserved | 3 | [MATERIAL §7](../design/MATERIAL_POLICY.md#7-toon-ramps) | | Edge / outline | preserved | preserved | 3 | [MATERIAL §9](../design/MATERIAL_POLICY.md#9-edges) | @@ -195,7 +196,8 @@ lane against digest-pinned `usd-motion-plugins` v0.5.0 packages. | A VMD as a `MotionClip`, and a PMX model as a retarget target (`SkeletonDescriptor`, humanoid `RetargetMap`) | supported — see [Shared-motion adapters](#shared-motion-adapters-mmdskeletonadapter-mmdmotionadapter) | [MOTION §10](../design/MOTION_CONTRACT.md#10-normalizing-into-the-shared-motion-core), [§12](../design/MOTION_CONTRACT.md#12-the-humanoid-role-table) | | Retargeting, recording, `UsdSkelAnimation` authoring of motion | unsupported by design | `usd-motion-plugins` ([MOTION §10.6](../design/MOTION_CONTRACT.md#106-what-this-repository-does-not-do-with-the-result)) | | Physics simulation | unsupported by design | `usd-stage-runner` or another runtime | -| Toon rendering | unsupported by design | `hydra-toon` | +| `MmdMaterialAPI` → Hydra data (`mmdImaging`) | — (planned for Phase 8) | [MATERIAL §12](../design/MATERIAL_POLICY.md#12-rendering-and-integration-belong-elsewhere) | +| Toon rendering | unsupported by design | `hydra-toon`; this repository supplies the schema and imaging adapter, not the renderer | | Opening a `.vmd` as a stage (`usdVmdFileFormat`) | — (waits for MOT-O2) | [MOTION §2](../design/MOTION_CONTRACT.md#2-components-and-boundaries) | | VMD playback | unsupported by design | a runtime scheduling `mmdControl` (Phase 8) | | VMD bake to `UsdSkelAnimation` | — (end-to-end acceptance remains) | `mmdControl` evaluates, the adapters normalize, the shared core authors ([MOTION §8.2](../design/MOTION_CONTRACT.md#82-a-bake-is-not-a-data-conversion)) | diff --git a/docs/reference/SOURCE_MAPPING.md b/docs/reference/SOURCE_MAPPING.md index a929bc5..fcf53d5 100644 --- a/docs/reference/SOURCE_MAPPING.md +++ b/docs/reference/SOURCE_MAPPING.md @@ -51,6 +51,7 @@ Paths are abbreviated: `Mesh` is `/Asset/geo/Mesh`, `Skel` is | PMX field | USD | Phase | | --- | --- | :---: | +| (material semantics contract) | Current contract v1: schema-less `mmd:material:*`; Phase 8: the same properties declared by applied `MmdMaterialAPI` | 8 | | name / English name | `Mtl` identifier; customData `mmd:sourceName` / `mmd:sourceEnglishName` | 2 | | (table index) | `Mtl` customData `mmd:sourceIndex` (= draw order) | 2 | | face count | `Mesh/` `GeomSubset.indices` + `material:binding` | 2 | diff --git a/docs/reports/2026-09-16-phase4-local-models.md b/docs/reports/2026-09-16-phase4-local-models.md index 2dfa4b8..11ee02e 100644 --- a/docs/reports/2026-09-16-phase4-local-models.md +++ b/docs/reports/2026-09-16-phase4-local-models.md @@ -69,7 +69,7 @@ and with no light in the scene: - The result is flat, with no toon ramp, no sphere-map highlight and no outline. That is the intended portable path, not a defect: MMD-specific shading stays declarative on the material prim for an MMD-aware renderer - ([MATERIAL_POLICY.md §12](../design/MATERIAL_POLICY.md#12-rendering-belongs-elsewhere)). + ([MATERIAL_POLICY.md §12](../design/MATERIAL_POLICY.md#12-rendering-and-integration-belong-elsewhere)). ## What it did not cover diff --git a/docs/roadmap/README.md b/docs/roadmap/README.md index c951a44..bf705db 100644 --- a/docs/roadmap/README.md +++ b/docs/roadmap/README.md @@ -11,7 +11,7 @@ Legend: ✅ done · 🚧 in progress · ⬜ not started · ⛔ blocked | Document | Contents | | --- | --- | -| [current.md](current.md) | The remaining milestones — Phase 9 shared motion adoption, then Phase 8 avatar, motion and physics runtime composition — and the part of each this repository owes or waits for. | +| [current.md](current.md) | The remaining milestones — Phase 9 shared motion adoption, then the Phase 8 material-schema, renderer, avatar and physics composition work — and the part of each this repository owes or waits for. | | [../releases/](../releases/README.md) | What each released version shipped, and how a release is cut. | ## One sequence @@ -36,7 +36,7 @@ in.** No other document states a version for a Phase. | 5 | control semantics | ✅ done | [v0.1.0](../releases/v0.1.0.md) | | 6 | physics preservation | ✅ done | [v0.1.0](../releases/v0.1.0.md) | | 7 | VMD | ✅ done | [v0.1.0](../releases/v0.1.0.md) | -| 8 | avatar runtime composition, including optional physics coupling | ⬜ | unassigned, and owned mostly outside this repository | +| 8 | `MmdMaterialAPI`, renderer bridge and avatar runtime composition, including optional physics coupling | ⬜ | unassigned; schema/adapter work is here, composition is owned mostly outside this repository | | 9 | shared motion core adoption — runs before Phase 8 | 🚧 skeletal evaluator, adapters and end-to-end acceptance done; expression interoperability and open rest-pose evidence remain | unassigned | Phases 0–7 ship together in v0.1.0, the first release, decided on @@ -47,7 +47,7 @@ Phase 7 too. It is a 0.x release because no consumer has used the packages yet: Phase 8's consumer may still show a contract wrong ([current.md](current.md)). No earlier Phase had a release of its own. -Where things stand, as of 2026-09-21: +Where things stand, as of 2026-09-22: - The documentation baseline exists: the design policy, six focused design contracts, the workspace contract, and reference pages that state what is @@ -62,8 +62,9 @@ Where things stand, as of 2026-09-21: importer authors the mesh, material prims and subsets, skeleton and skinning, and the workspace, standalone, sanitizer and documentation lanes cover the implementation. -- Phase 3, the material triad, is done: canonical MMD material semantics on - every material prim, plus the unlit `preview` and MaterialX `mtlx` +- Phase 3, the material triad, is done: canonical MMD material semantics as + schema-less `mmd:material:*` attributes on every contract-v1 material prim, + plus the unlit `preview` and MaterialX `mtlx` realizations. Its last two items closed on 2026-09-16 — the standalone golden agrees on every supported platform, and three distributed models render through Storm with their source colors @@ -120,9 +121,14 @@ Where things stand, as of 2026-09-21: stage skeleton and a non-MMD skeleton ([report](../reports/2026-09-22-phase9-motion-acceptance.md)). Expression interoperability and MOT-O10 remain. -- Phase 8, avatar runtime composition, follows Phase 9 and is owned mostly - outside this repository. Its MMD physics work consumes the already-authored - stage through `usd-physics-plugins`; the importer never gains a solver +- Phase 8 follows Phase 9. Before renderer composition, this repository adds + the admitted `MmdMaterialAPI`, applies it as a backward-compatible + contract-v1 addition without renaming any `mmd:material:*` property, and + supplies the UsdImaging bridge consumed by `hydra-toon`. The shared renderer + may normalize MMD and MToon privately, but their USD schemas remain separate. + The rest of avatar composition is owned mostly outside this repository. Its + MMD physics work consumes the already-authored stage through + `usd-physics-plugins`; the importer never gains a renderer or solver ([PHYSICS_INTEGRATION.md](../design/PHYSICS_INTEGRATION.md)). ## Open decisions @@ -150,7 +156,7 @@ schedules them. | MOT-O3 | Which runtime owns MMD IK and append evaluation for baking | [MOTION §9](../design/MOTION_CONTRACT.md#9-open-questions) | resolved in Phase 7; superseded 2026-09-17 — `mmdControl`, here | | PMX-O2 | QDEF verification | [PMX §16](../design/PMX_CONTRACT.md#16-open-questions) | a consumer | | PMX-O4 | Morph category from display frames | [PMX §16](../design/PMX_CONTRACT.md#16-open-questions) | a consumer | -| MAT-O4 | How `hydra-toon` reads MMD semantics | [MATERIAL §13](../design/MATERIAL_POLICY.md#13-open-questions) | `hydra-toon` | +| MAT-O4 | How `hydra-toon` reads MMD semantics | [MATERIAL §13](../design/MATERIAL_POLICY.md#13-open-questions) | resolved 2026-09-22 — `MmdMaterialAPI` + UsdImaging adapter; implementation is Phase 8 | | MOT-O4 | Camera and light tracks | [MOTION §9](../design/MOTION_CONTRACT.md#9-open-questions) | a consumer | | MOT-O8 | Evaluating MMD motion from a stage alone | [MOTION §9](../design/MOTION_CONTRACT.md#9-open-questions) | a consumer that holds only the stage | | MOT-O11 | Whether a knee starts from its keyed rotation | [MOTION §9](../design/MOTION_CONTRACT.md#9-open-questions) | nothing (MMD's output to compare against) | diff --git a/docs/roadmap/current.md b/docs/roadmap/current.md index 41fa231..0bc5653 100644 --- a/docs/roadmap/current.md +++ b/docs/roadmap/current.md @@ -1,8 +1,9 @@ -# Phase 9, then Phase 8 — shared motion, avatar and physics composition +# Phase 9, then Phase 8 — shared motion, material and avatar composition Status: 🚧 Phase 9 in progress — `mmdControl`, both shared-motion adapters, skeletal end-to-end acceptance, MOT-O5, MOT-O6 and MOT-O9 are done; Phase 8 -not started. +implementation has not started, but its `MmdMaterialAPI` and Hydra boundary are +now decided. Two Phases remain, and they run in this order although they are numbered the other way ([DESIGN_POLICY.md §14](../design/DESIGN_POLICY.md#14-phases)): @@ -12,7 +13,8 @@ other way ([DESIGN_POLICY.md §14](../design/DESIGN_POLICY.md#14-phases)): `usd-motion-plugins` as a `MotionClip` (`mmdMotionAdapter`), while `mmdSkeletonAdapter` exposes the PMX skeleton for generic retargeting ([MOTION_CONTRACT.md §10](../design/MOTION_CONTRACT.md#10-normalizing-into-the-shared-motion-core)). -- **Phase 8 — avatar runtime composition.** `usd-avatar-runtime` composes this +- **Phase 8 — material and avatar runtime composition.** This repository adds + `MmdMaterialAPI` and its UsdImaging bridge; `usd-avatar-runtime` composes this repository with `usd-vrm-plugins`, `usd-motion-plugins`, `usd-physics-plugins`, `motion-connectors`, `hydra-toon` and `usd-stage-runner` through @@ -32,7 +34,7 @@ test. `mmdMotionAdapter` and `mmdSkeletonAdapter` are implemented. ## Outcome ```text -.pmx ─→ usdMmdFileFormat ─→ /Asset stage +.pmx ─→ usdMmdFileFormat ─→ /Asset stage ─→ MmdMaterialAPI ─→ UsdImaging adapter ─→ hydra-toon .vmd ─→ motionVmd ─→ mmdMotionBinding ─→ mmdControl ─→ mmdMotionAdapter ─→ MotionClip .pmx ─→ mmdModel ─→ mmdSkeletonAdapter ─→ SkeletonDescriptor / RetargetMap │ @@ -97,6 +99,39 @@ usd-avatar-runtime: composes the above per frame and coordinates rendering ## Phase 8 — what remains +### Material schema and renderer integration + +Phase 3 remains complete: contract-v1 stages already preserve every canonical +MMD material value and carry generic `preview` and `mtlx` fallbacks. Phase 8 +formalizes that existing contract for an MMD-aware renderer; it does not replace +or reinterpret the fallbacks +([MATERIAL_POLICY.md](../design/MATERIAL_POLICY.md)). + +- ✅ **Schema decision and attribute inventory** (2026-09-22): + `MmdMaterialAPI` is a single-apply API on `UsdShadeMaterial`; existing + `mmd:material:*` names, types and meanings are retained, neutral fallbacks are + fixed, provenance stays outside the API, and MAT-O4 is resolved as an + UsdImaging adapter rather than a third realization graph. +- ⬜ Add the `mmdSchema` plugin with generated C++/Python accessors and tokens; + admit no other MMD schema by association. +- ⬜ Apply `MmdMaterialAPI` and author through it in `usdMmdFileFormat` as an + additive stage-contract v1 change. Test both directions of compatibility: + schema-aware consumers read earlier schema-less v1 attributes, while existing + consumers can ignore `apiSchemas` and still read the unchanged properties and + fallback graphs. +- ⬜ Keep `/preview` and `/mtlx` output, appearance and golden coverage stable + while migrating the canonical authoring path. +- ⬜ Implement a UsdImaging adapter that exposes `MmdMaterialAPI` to Hydra + without making the importer depend on `hydra-toon`. +- ⬜ Bring up the `hydra-toon` MMD path in this order: diffuse/alpha, toon + ramp, sphere multiply/add, sub-texture, outline, shadow flags, material morph + runtime, then advanced UV and vertex-color behavior. +- ⬜ After both `VrmMtoonMaterialAPI` and `MmdMaterialAPI` paths work, evaluate + renderer-private common code. Do not introduce a USD-level `ToonMaterialAPI` + until the two concrete implementations demonstrate stable common semantics. + +### Avatar runtime composition + - ⬜ Consume the packages from `usd-avatar-runtime` — `usdMmdFileFormat`, and `motionVmd`, `mmdMotionBinding`, `mmdControl`, `mmdMotionAdapter` and `mmdSkeletonAdapter` for