From ff1b7c91b94d7b0ee52865c0c2587bba1144a0e0 Mon Sep 17 00:00:00 2001 From: Ken Jakubzak Date: Sat, 26 Jul 2025 01:38:38 -0700 Subject: [PATCH 01/48] First iteration of proposal draft to introduce khr avatar extensions Updated skeleton_biped Updated mapping README updates Fixing contributors list as well as some logical errors in the extension schemas --- extensions/2.0/Khronos/KHR_avatar/README.md | 151 ++++++++++ .../KHR_avatar_expression_joint/README.md | 162 +++++++++++ .../KHR_avatar_expression_mapping/README.md | 104 +++++++ .../README.md | 193 +++++++++++++ .../README.md | 119 ++++++++ .../KHR_avatar_expression_texture/README.md | 263 ++++++++++++++++++ .../KHR_avatar_mesh_annotation/README.md | 115 ++++++++ .../README.md | 95 +++++++ .../KHR_avatar_skeleton_bindpose/README.md | 122 ++++++++ .../KHR_avatar_skeleton_biped/README.md | 140 ++++++++++ .../KHR_avatar_skeleton_mapping/README.md | 155 +++++++++++ .../KHR_avatar_virtual_joints/README.md | 109 ++++++++ 12 files changed, 1728 insertions(+) create mode 100644 extensions/2.0/Khronos/KHR_avatar/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md create mode 100644 extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md diff --git a/extensions/2.0/Khronos/KHR_avatar/README.md b/extensions/2.0/Khronos/KHR_avatar/README.md new file mode 100644 index 0000000000..284603a124 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar/README.md @@ -0,0 +1,151 @@ +# KHR_avatar + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. + +Dependencies: `KHR_xmp_json_ld` +This extension also leverages the `KHR_xmp_json_ld` pattern for attaching extensible metadata as JSON-LD blocks within glTF assets. For background on this approach, see: +[KHR_xmp_json_ld](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_xmp_json_ld) + +## Overview + +The `KHR_avatar` extension designates a glTF asset as representing an avatar. This top-level marker enables tools and runtimes to interpret the asset as containing avatar-specific content such as rigging, blendshapes, animation retargeting, or metadata. + +This extension does not define avatar features directly but acts as a root declaration that avatar-related extensions may be present, and that consumers should treat the asset using avatar-specific logic and pipelines. It's part of the wider set of KHR avatar extensions that are meant to be building blocks to represent a contract stating functionality and data requirements between a given model and an endpoint. + +The extension supports referencing the source `scene` that represents the avatar and optionally includes structured metadata through the `KHR_xmp_json_ld` mechanism. + +## Extension Schema + +```json +{ + "extensions": { + "KHR_avatar": { + "sceneIndex": 0 + } + } +} +``` + +### Properties + +| Property | Type | Description | +|--------------|---------|-----------------------------------------------------------------------------| +| `sceneIndex` | integer | Index of the glTF `scene` representing the avatar. Used to distinguish the avatar root when multiple scenes exist. | + +## Metadata Attachment: JSON_XMP_LD + +Avatar metadata should be expressed using the `KHR_xmp_json_ld` format, a structured mechanism for attaching JSON-LD metadata blocks to glTF files. In the context of `KHR_avatar`, this allows consistent expression of avatar provenance, licensing, creator, versioning, and intended use, among others. + +The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as part of the defined extension usage. Metadata keys and structures are defined in the shared Khronos Avatar Metadata schema (TBD). + +| DC/XMP_JSON_LD Property | Why | Required | +|-------------------------|------------------------------------------------------------------------------|----------| +| dc:title | | Yes | +| dc:creator | | Yes | +| dc:license | | No | +| dc:rights | | No | +| dc:created | Date on which the asset was created | No | +| dc:publisher | Identifies the entity responsible for making the resource available; important for understanding the source and authority of the content. | No | +| dc:description | Context and a summary of the content | No | +| dc:subject | Can potentially be used for content tagging/association | No | +| dc:source | Important for tracing the provenance and ensuring proper attribution. | Yes | +| khr:version | | No | +| khr:thumbnailImage | | No | + +## Example + +```json +{ + "asset": { + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [0] + } + ], + "nodes": [ + { + "name": "AvatarRoot" + } + ], + "extensionsUsed": [ + "KHR_avatar", + "KHR_xmp_json_ld" + ], + "extensions": { + "KHR_avatar": { + "sceneIndex": 0 + }, + + "KHR_xmp_json_ld": { + "packets": [ + { + "@context": { + "dc": "http://purl.org/dc/elements/1.1/", + "vrm": "https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/meta.md" + }, + "dc:title": "Example Model", + "dc:creator": { + "@list": [ + "Author1", + "AuthorEmail1@email.com", + "Author2", + "AuthorEmail2@email.com" + ] + }, + "dc:license": { + "@list": [ + "https://vrm.dev/licenses/1.0/", + "https://example.com/third-party-license" + ] + }, + "dc:created": "2023-05-05", + "dc:rights": "Copyright information about the model", + "dc:publisher": "Imaginary Corporation A, LLC", + "dc:description": "A sentence, or paragraph describing the avatar at hand", + "dc:subject": { + "@list": [ + "Example trait", + "Another example trait" + ] + }, + "dc:source": "imaginaryCompany.com/avatarl", + "khr:version": "1.0", + "khr:thumbnailImage": 0 +} + ] + } + } +} +``` + +## Implementation Notes + +- `sceneIndex` is required and indicates what scene a particular avatar belongs to +- Consumers should use this marker as a signal to search for additional avatar-related extensions, including skeletal, expression, and other khronos avatar extensions. +- Support for `JSON_XMP_LD` is encouraged to ensure interoperable metadata across tools and runtimes. + +## Known Implementations + + +## License + +This extension specification is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md new file mode 100644 index 0000000000..0cd9d19809 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md @@ -0,0 +1,162 @@ +# KHR_avatar_expression_joint + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_avatar` +Typically used in conjunction with: `KHR_avatar_expression_mapping` + +## Overview + +The `KHR_avatar_expression_joint` extension provides a semantic mapping between facial expressions and joint transformations in the glTF node hierarchy. It enables tools and runtimes to associate expressions like `blink`, `smile`, or `jawOpen` with specific nodes whose transforms are animated using standard glTF animation channels. + +This extension is purely descriptive: it does not define or store animation data itself. + +## Expression Vocabulary + +Expression types include: + +- **Emotions**: `happy`, `angry`, `surprised`, etc. +- **Visemes**: `aa`, `ee`, `th`, `oo`, etc. +- **Modifiers**: `left`, `right`, `upper`, `lower`, etc. +- **Gestures and Actions**: `blink`, `smile`, `jawOpen`, etc. + +Optionally, these may be aligned with industry standards, such as [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). + +## Extension Schema + +```json +{ + "extensions": { + "KHR_avatar_expression_mapping": { + "expressions": [ + { + "expression": "smile", + "animation": 0, + "channels": [0,1,2] + }, + { + "expression": "frown", + "animation": 1, + "channels": [0,1] + } + ] + } + } +} +``` + +### Properties + +| Property | Type | Description | +|--------------|---------|-----------------------------------------------------------------------------| +| `expressions`| array | Array of mappings between animation/channels and expression labels. | +| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | +| `expression` | string | Expression name this joint contributes to. | +| `channels` | array | array representing channels that must correspond to either `"rotation"`, `"translation"`, or `"scale"`; indicates transform types. | + +## Animation Integration (Expressions Tab Recommendation) + +- Expression timing, blending, and control must use glTF `animations` channels. +- Animations targeting expression-driven `rotation`, `translation`, or `scale` must conform to glTF 2.0's animation model. +- This ensures consistency, ease of implementation, and interoperability across runtimes. + +Each animation channel used to drive an expression should operate within a **normalized 0-to-1 range**, where: +- `0.0` indicates the expression is fully inactive. +- `1.0` indicates the expression is fully active. + +The transformation values themselves (e.g., degree of rotation or distance of translation) should scale proportionally with the normalized input range. + +This approach simplifies avatar implementation by centralizing expression playback in the glTF animation system and unifying runtime logic for blending and prioritization. + +### Recommended Interpolation for Binary Expressions + +For expressions that represent binary or toggle states (such as `blinkLeft`, `blinkRight`, or `jawOpen`), the use of glTF animation channels with `"interpolation": "STEP"` is strongly recommended. + +STEP interpolation ensures that an expression toggles cleanly between fully off (`0.0`) and fully on (`1.0`) states, providing crisp visual transitions and avoiding interpolation artifacts that could occur with `LINEAR` interpolation in binary scenarios. + + +## Example: Expression with glTF Animation + +Here is how an expression-driven joint defined in this extension could interact with glTF's native animation system: + +### Step 1: Define a Semantic Mapping in this Extension + +```json +{ + "extensions": { + "KHR_avatar_expression_mapping": { + "expressions": [ + { + "expression": "smile", + "animation": 0, + "channels": [0,1,2] + }, + { + "expression": "frown", + "animation": 1, + "channels": [0,1,3] + } + ] + } + } +} +``` + +This maps the joint at node index `5` to the expression `"smile"`, using rotation as its mode of influence. + +### Step 2: Animate the Joint Using Standard glTF Channels + +In the main glTF `animations[]`, use standard animation targeting to animate the `rotation` of node 5: + +```json +{ + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "node": 5, + "path": "rotation" + } + } + ], + "samplers": [ + { + "input": 0, + "output": 1, + "interpolation": "LINEAR" + } + ] + } + ] +} +``` + +This animation channel should rotate the joint in a way that corresponds to a `smile` expression. The weights of the keyframes must reflect the normalized [0.0 – 1.0] expression activation. + + +## Implementation Notes + +- Multiple joints may be assigned to the same expression. +- Expression states should be normalized to the [0.0–1.0] range for consistent runtime interpretation. +- This extension does not conflict with standard rigging or skinning systems. + +## License + +This extension is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md new file mode 100644 index 0000000000..bc4ed9ce80 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md @@ -0,0 +1,104 @@ +# KHR_avatar_expression_mapping + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_avatar` +Can be used alongside: `KHR_avatar_expression_morphtargets` or other expression sources + +## Overview + + +## Reference Expression Vocabulary +Expression names may be grouped into categories including: + +- **Emotions** (e.g., `happy`, `angry`, `surprised`) +- **Visemes** (e.g., `aa`, `oo`, `th`) +- **Modifiers** (e.g., `left`, `right`, `upper`, `lower`) +- **Gestures and Actions** (e.g., `blink`, `smile`, `jawOpen`) + +Implementers are encouraged to use this vocabulary directly or map custom expressions to it using `KHR_avatar_expression_mapping`. + +The `KHR_avatar_expression_mapping` extension provides a general-purpose mechanism for mapping expression names used in an avatar’s mesh to a known expression vocabulary or rig specification. This allows different authoring pipelines or runtimes to translate between heterogeneous expression sets. + +## Extension Schema + +```json +{ + "extensions": { + "KHR_avatar_expression_mapping": { + "mappings": { + "smileLeft": [ + { "target": "Smile", "weight": 0.8 }, + { "target": "LeftCheekRaise", "weight": 0.2 } + ], + "jawOpen": [ + { "target": "MouthOpen", "weight": 1.0 } + ] + } + } + } +} +``` + +### Properties + +| Property | Type | Description | +|--------------|---------|-----------------------------------------------------------------------------| +| `mappings` | object | Dictionary mapping expression names to reference vocabulary terms. | +| `target` | string | Name of the expression in the target vocabulary. | +| `weight` | number | Influence of this target. Must sum to 1.0 per expression key. | + + +### Mapping Types + +This extension supports both one-to-one and one-to-many mappings: + +- **One-to-one**: An expression maps directly to a single reference vocabulary term with weight 1.0. +- **One-to-many**: An expression is composed from multiple reference terms, blended using assigned weights. + +This allows developers to bridge between custom expression sets and shared vocabularies. + +## Implementation Notes + +- This extension is typically used at the top level of the glTF file. +- Expression names should match those used in `KHR_avatar_expression_morphtargets`, animation tracks, or tracking pipelines. +- Tools can interpret this mapping to apply automatic translation between expression sets. + +## Example + +```json +{ + "extensionsUsed": [ + "KHR_avatar_expression_mapping" + ], + "extensions": { + "KHR_avatar_expression_mapping": { + "mappings": { + "smileLeft": [ + { "target": "Smile", "weight": 0.8 }, + { "target": "LeftCheekRaise", "weight": 0.2 } + ] + } + } + } +} +``` + +## License + +This extension specification is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md new file mode 100644 index 0000000000..a260a21907 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md @@ -0,0 +1,193 @@ +# KHR_avatar_expression_morphtarget + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Used in conjunction with: `KHR_avatar`, `KHR_avatar_expression_mapping` + +## Overview + +The `KHR_avatar_expression_morphtarget` extension provides semantic bindings between avatar expressions and specific morph target indices in a glTF mesh. These mappings enable higher-level expression control systems to reference the correct blendshapes when driving facial animation using glTF animation channels. + +This extension does **not** define animation data itself. Instead, it enables consistent reference of morph target indices across tools, runtimes, and expressions. + +## Reference Expression Vocabulary +Potential expression categories include: + +- **Emotions** (e.g., `happy`, `angry`, `surprised`) +- **Visemes** (e.g., `aa`, `oo`, `th`) +- **Modifiers** (e.g., `left`, `right`, `upper`, `lower`) +- **Gestures and Actions** (e.g., `blink`, `smile`, `jawOpen`) + +Optionally, these may be aligned with industry standards, such as the [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). + +## Extension Schema + +```json +{ + "extensions": { + "KHR_avatar_expression_mapping": { + "expressions": [ + { + "expression": "smile", + "animation": 0, + "channel": 0 + }, + { + "expression": "frown", + "animation": 1, + "channel": 0 + } + ] + } + } +} +``` + +### Properties + +| Property | Type | Description | +|--------------|---------|-----------------------------------------------------------------------------| +| `expressions`| array | Array of mappings between animation/channels and expression labels. | +| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | +| `expression` | string | Expression name this joint contributes to. | +| `channel` | integet | Index representing the `"weights"` channel | + +## Animation Integration (Expressions Tab Recommendation) + +This extension **does not animate morph targets directly**. It provides metadata only. + +All morph target expressions should be driven using standard glTF animation channels, targeting the `weights` path on the corresponding node: + +```json +{ + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "node": 0, + "path": "weights" + } + } + ], + "samplers": [ + { + "input": 0, + "output": 1, + "interpolation": "LINEAR" + } + ] + } + ] +} +``` + +- Use `"interpolation": "STEP"` for binary/toggle expressions like `blink`. +- Each element of the `weights` array corresponds to one morph target on the associated mesh primitive. +- Expression systems should coordinate with these indices using the bindings declared by this extension. + + +## Example: Expression with glTF Animation + +### Step 1: Bind Expression to Morph Target + +```json +{ + "extensions": { + "KHR_avatar_expression_morphtarget": { + "expressions": [ + { + "expression": "smile", + "animation": 0, + "channel": 0 + }, + { + "expression": "frown", + "animation": 1, + "channel": 0 + } + ] + } + } +} +``` + +This binds morph target index 2 on mesh 0, primitive 0, to the expression `"blinkLeft"`. + +### Step 2: Animate the Morph Target via Node Weights + +```json +{ + "nodes": [ + { + "mesh": 0, + "weights": [0.0, 0.0, 0.0] + } + ], + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "node": 0, + "path": "weights" + } + } + ], + "samplers": [ + { + "input": 0, + "output": 1, + "interpolation": "STEP" + } + ] + } + ] +} +``` + +The animation should update the relevant morph target weight (in this case index 2) between `0.0` and `1.0` to control the `"blinkLeft"` expression. The usage of `STEP` interpolation ensures clean toggles between on/off states. + + +## Implementation Notes + +- This extension provides a consistent mapping between expression names and mesh targets, allowing glTF animation data to be expressive-aware. +- Multiple morph targets can be bound to the same expression. +- Tools may use this metadata to validate expression sets, retarget avatar blendshape names, or drive runtime animation. + +### Recommended Interpolation for Binary Expressions + +For expressions that represent binary or toggle states (such as eye blinks, mouth open/close states, or other on/off expressions), the use of glTF animation channels with `"interpolation": "STEP"` is strongly recommended. + +Using STEP interpolation ensures that the expression toggles cleanly between fully off (0) and fully on (1) states, providing crisp transitions and avoiding unintended interpolation artifacts. + + +All expression-driven changes defined by this extension should rely on standard glTF animation mechanisms as described in the Khronos [Expressions Tab](https://docs.google.com/document/d/1ALRCPbXqQuWZvA9Sm2TsBFuW75h-of_lfD6sN7QwFU0/edit?pli=1&tab=t.x433oui5434f). + +- Expression timing, blending, and control must use glTF `animations` channels. +- Animations targeting expression-driven `weights` (for morphtargets) +- This ensures consistency, ease of implementation, and interoperability across runtimes. + +This approach simplifies avatar implementation by centralizing expression playback in the glTF animation system, reducing custom handling and improving cross-platform compatibility. + + +## License + +This extension specification is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md new file mode 100644 index 0000000000..d72eeb0213 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md @@ -0,0 +1,119 @@ +# KHR_avatar_expression_procedural + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_avatar` +Works alongside: `KHR_avatar_expression_mapping`, `KHR_avatar_expression_joint`, `KHR_avatar_expression_morphtargets`. + +## Overview + +The `KHR_avatar_expression_procedural` extension introduces a metadata layer that defines which expressions are expected to be procedurally generated or controlled at runtime. This includes expressions such as: + +- **Timed blinking** +- **Eye darting** +- **Idle mouth movement** +- **Microexpressions** +- **Randomized twitches or gestures** + +By labeling expressions as procedural, this extension enables runtime systems (e.g., animation controllers, live-tracking systems, or AI avatars) to drive those expressions without conflict with animation data or user inputs. + +This metadata is **descriptive only**: it does not contain animation or behavior logic itself. Instead, it signals to tools and engines that the following expressions are *expected to be dynamically generated*. + +## Use Cases + +- Define which expressions are not statically animated but generated procedurally +- Avoid conflict between procedural and baked expression systems +- Inform rig exporters or runtime systems which expressions are reserved for real-time generation +- Enable consistent behavior across platforms + +## Schema + +```json +{ + "extensions": { + "KHR_avatar_expression_procedural": { + "proceduralExpressions": [ + { + "expression": "blinkLeft", + "mode": "timed" + }, + { + "expression": "mouthTwitch", + "mode": "random" + } + ] + } + } +} +``` + +### Properties + +| Property | Type | Description | +|-------------------------|----------|--------------------------------------------------------------------------------------| +| `proceduralExpressions` | array | List of expression metadata entries that are intended to be procedurally controlled | +| `expression` | string | Expression name as defined in the expression mapping vocabulary | +| `mode` | string | Enum: `"timed"`, `"random"`, `"live"`, `"scripted"` — describes the procedural strategy | + +## Procedural Modes + +| Mode | Meaning | +|------------|-------------------------------------------------------------------------| +| `timed` | The expression occurs in regular intervals (e.g., blinking every 5s) | +| `random` | The expression fires with stochastic timing or weights | +| `live` | Driven by live-captured inputs (e.g., webcam, eye tracking) | +| `scripted` | Driven by external dialogue, AI logic, or gameplay sequences | +| `mixed` | Combines two or more procedural sources, such as live tracking + scripted cues | + + +## Expression Control Behavior + +To help define how procedural expressions interact with animation systems, this extension introduces an additional field called `conflictResolution`, inspired by the [VRM 1.0 specification](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md#lip-sync-procedural). + +Each procedural expression may declare a resolution strategy for combining procedural output with baked animation data. + +### `conflictResolution` Enum + +| Value | Meaning | +|----------|-------------------------------------------------------------------------| +| `none` | No procedural influence. The expression is controlled exclusively by animation or input. | +| `block` | Procedural output *overrides* animation data while active. | +| `blend` | Procedural and animation data may be blended or accumulated together. | + +### Example with Resolution Mode + +```json +{ + "expression": "blinkLeft", + "mode": "timed", + "conflictResolution": "blend" +} +``` + +This allows developers to distinguish expressions meant to supplement animation (e.g., micro-blinks over emotive acting) versus those that must fully override input (e.g., forced gaze). + + +## Implementation Notes + +- This extension is schema-only and does not contain behavior logic or animation data. +- Runtimes may use this to suppress baked animation for procedural targets. +- The expression names should align with the shared vocabulary defined in the `KHR_avatar_expression_mapping`. + +## License + +This extension is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md new file mode 100644 index 0000000000..b360eb4930 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md @@ -0,0 +1,263 @@ +# KHR_avatar_expression_texture + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_avatar`,`KHR_animation_pointer` +Can be used alongside: `KHR_avatar_expression_mapping` + +## Overview + +The `KHR_avatar_expression_texture` extension enables expression-level control using texture swaps or UV transformations. This approach is beneficial for avatars that represent expressions visually via changes in texture, such as cartoon or anime-style characters. + +- Expression timing, blending, and control must use glTF `animations` channels. +- Animations targeting expression-driven texture transforms must adhere strictly to glTF animation standards and khr_animation_pointer semantics. + +## Reference Expression Vocabulary + +Expressions may be categorized as: + +- **Emotions** (e.g., `happy`, `angry`, `surprised`) +- **Visemes** (e.g., `aa`, `oo`, `th`) +- **Modifiers** (e.g., `left`, `right`, `upper`, `lower`) +- **Gestures and Actions** (e.g., `blink`, `smile`, `jawOpen`) + +Optionally, these may be aligned with industry standards, such as [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). + +## Extension Schema + +```json +{ + "extensions": { + "KHR_avatar_expression_texture": { + "expressions": [ + { + "material": 2, + "texture": 5, + "expression": "happy", + "animation": 0, + "channels": [0] + }, + { + "material": 2, + "texture": 5, + "expression": "angry", + "animation": 1, + "channels": [0,1] + } + ] + } + } +} +``` + +### Properties + +| Property | Type | Description | +|---------------------|----------------|-------------------------------------------------------------------------------| +| `expressions` | array | List of texture-expression bindings. | +| `material` | integer | Index into the glTF `materials` array. | +| `texture` | integer | (Optional) Index into the glTF `textures` array, defining a replacement texture. | +| `textureTransform` | object | (Optional) UV transformations for texture-based expressions. | +| `expression` | string | Expression name associated with this texture or UV change. | + +### textureTransform properties + +| Property | Type | Description | +|----------|-----------|--------------------------------------| +| `offset` | float[2] | UV offset for texture placement. | +| `scale` | float[2] | UV scale for texture transformation. | + + +### Recommended Interpolation for Binary Expressions + +For expressions that represent binary or toggle states (such as eye blinks, mouth open/close states, or other on/off expressions), the use of glTF animation channels with `"interpolation": "STEP"` is strongly recommended. + +Using STEP interpolation ensures that the expression toggles cleanly between fully off (0) and fully on (1) states, providing crisp transitions and avoiding unintended interpolation artifacts. + + +### Integration with KHR_animation_pointer + +For animations that involve texture swaps or UV transformations, implementations should rely on the [`KHR_animation_pointer`](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_animation_pointer) extension. This provides a standardized mechanism for animating texture and UV transform properties via JSON pointers. + +This method ensures consistent and interoperable animation targeting for texture-based expressions across glTF runtimes. + +## Clarifications on Texture Manipulations + +### Texture Swaps + +Dynamic texture swaps are not explicitly defined within the core glTF 2.0 specification. To implement runtime texture swapping: + +- Predefine all textures in the glTF `textures` array. +- Use the [`KHR_animation_pointer`](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_animation_pointer) extension to animate pointers that reference texture indices within material definitions. + +### UV Transformations + +UV manipulations (offset, scale, rotation) require the widely adopted [`KHR_texture_transform`](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform) extension. + +- Animate properties within `KHR_texture_transform` using `KHR_animation_pointer`. +- Ensure these transforms are included explicitly in the glTF material definitions to enable animations. + +### Example Animation Setup using KHR_animation_pointer + +```json +{ + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "extensions": { + "KHR_animation_pointer": { + "pointer": "/materials/2/pbrMetallicRoughness/baseColorTexture/index" + } + } + } + }, + { + "sampler": 1, + "target": { + "extensions": { + "KHR_animation_pointer": { + "pointer": "/materials/3/pbrMetallicRoughness/baseColorTexture/extensions/KHR_texture_transform/offset" + } + } + } + } + ], + "samplers": [ + { + "input": 0, + "output": 1, + "interpolation": "STEP" + }, + { + "input": 2, + "output": 3, + "interpolation": "LINEAR" + } + ] + } + ] +} +``` + +This clearly separates semantic bindings (the domain of this extension) from runtime animation states (handled by standard glTF animation mechanisms). + +### Recommended Interpolation for Binary Expressions + +For expressions that represent binary or toggle states (such as eye blinks, mouth open/close states, or other on/off expressions), the use of glTF animation channels with `"interpolation": "STEP"` is strongly recommended. + +Using STEP interpolation ensures that the expression toggles cleanly between fully off (0) and fully on (1) states, providing crisp transitions and avoiding unintended interpolation artifacts. + + +## Example: Expression with glTF Animation + +### Step 1: Bind Expressions to Materials + +```json +{ + "extensions": { + "KHR_avatar_expression_texture": { + "expressions": [ + { + "material": 2, + "texture": 5, + "expression": "happy", + "animation": 0, + "channels": [0, 1] + }, + { + "material": 2, + "texture": 5, + "expression": "angry", + "animation": 1, + "channels": [0,1] + } + ] + } + } +} +``` + +This binds material index 2 to the `"happy"` expression and material index 3 to `"angry"`. + +### Step 2: Animate Texture Properties Using KHR_animation_pointer + +Animation of either the texture index or texture transform must be implemented using `KHR_animation_pointer`. + +```json +{ + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "extensions": { + "KHR_animation_pointer": { + "pointer": "/materials/2/pbrMetallicRoughness/baseColorTexture/index" + } + } + } + }, + { + "sampler": 1, + "target": { + "extensions": { + "KHR_animation_pointer": { + "pointer": "/materials/3/pbrMetallicRoughness/baseColorTexture/extensions/KHR_texture_transform/offset" + } + } + } + } + ], + "samplers": [ + { + "input": 0, + "output": 1, + "interpolation": "STEP" + }, + { + "input": 2, + "output": 3, + "interpolation": "LINEAR" + } + ] + } + ] +} +``` + +## Implementation Notes + +- Use this extension when morph targets or joint animations alone are insufficient or stylistically undesirable for expressions. +- Expression-driven texture swaps or UV transformations are typically applied to materials on facial regions, such as eyes or mouth. +- This extension does not define animation sequences, only the semantic binding between expressions and textures or UV transforms. +- The `STEP` interpolation is ideal for switching texture indices (e.g., on/off or binary swaps). +- The `LINEAR` interpolation may be used for UV offset transitions or subtle animations. + +### Runtime Behavior + +- Expression weights should animate between `0.0` (off) and `1.0` (fully active). +- The avatar system uses these animations to blend or toggle texture visuals in accordance with semantic expressions. + + +## License + +This extension specification is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md new file mode 100644 index 0000000000..f08d878e5c --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md @@ -0,0 +1,115 @@ +# KHR_avatar_mesh_annotation + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_avatar` +Can be used alongside rendering-related extensions. + +## Overview + +The `KHR_avatar_mesh_annotation` extension enables arbitrary per-mesh metadata annotations for avatar models. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic. + +Unlike expression bindings or skeletons, this extension focuses on **attaching structured metadata to glTF mesh primitives or submeshes**. Examples include: + +- Indicating occlusion, hit zones, body regions, or cosmetics +- Tagging subregions with gameplay affordances (e.g., "touchable", "selectable") +- Supporting accessibility metadata (e.g., limb representation for low-vision aid) +- Facilitating layered rendering systems or shadow pass rules + +## Motivation + +Avatar models often contain complex geometry with overlapping purposes—hair, clothing, limbs, devices, accessories, etc. Many applications need to reason about specific mesh subsets for: + +- Avatar customization layers +- Haptic or interaction targeting +- Runtime layering and decal application +- Streaming/LOD switching + +This extension provides a consistent, schema-driven approach to labeling such mesh regions without requiring custom parsing or glTF structural abuse. + +## Schema + +Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i]`), and stored in the `KHR_avatar_mesh_annotation` extension: + +```json +{ + "meshes": [ + { + "primitives": [ + { + "attributes": { ... }, + "extensions": { + "KHR_avatar_mesh_annotation": { + "tags": ["eyewear", "selectable"], + "region": "face" + } + } + } + ] + } + ] +} +``` + +### Properties + +| Property | Type | Description | +|------------------|---------------|-----------------------------------------------------------------------------| +| `tags` | string[] | List of free-form labels applicable to this primitive | +| `customData` | object | Optional freeform object for runtime-specific annotations (optional) | + +## Use Cases & Examples + +### 2. Touch Targets + +```json +"tags": ["touchable", "interactionZone"] +``` + +Used by interaction or accessibility systems to identify meaningful geometry. + +### 3. Region Metadata for Accessibility + +```json +"tags": ["left_hand"] +``` + +This can drive voiceover descriptions, haptics, or visual aids for users with assistive needs. + +### 4. Selectable Cosmetic Submeshes + +```json +"tags": ["eyewear", "customizable"] +``` + +Allows filtering of optional accessories or togglable cosmetic parts. + +## Implementation Notes + +- Annotations apply at the granularity of `mesh.primitive`, enabling fine control. +- Tags are non-authoritative but enable semantic interoperability across runtimes. +- `customData` allows developers to store app-specific structured metadata (e.g., color categories, tracking weights, heatmaps). +- If this extension is not understood by a client, it should be safely ignored with no visual or functional change. + +## Relation to Other Extensions + +- **Complements `KHR_materials_variants`** by labeling which primitives may be toggled/swapped. + +## License + +This extension is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md new file mode 100644 index 0000000000..0f741a8d5b --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md @@ -0,0 +1,95 @@ +# KHR_avatar_mesh_annotation_rendering + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_avatar` + +## Overview + +The `KHR_avatar_mesh_annotation_rendering` extension provides structured metadata for avatar mesh primitives related to **visibility and render-time behavior**. It complements the core glTF material and LOD systems by exposing semantic visibility rules such as “first-person only”, “always visible”, etc. + +This extension is intended to support use cases such as: + +- Hiding certain parts of an avatar (like head or hair) in first-person mode +- Marking components that must always be rendered (e.g., eyes) +- Toggling cosmetic parts based on camera mode or gameplay state +- Managing specialized render passes (shadows, reflections, etc.) + +## Use Cases + +- First-person camera hiding for head/hair geometry +- Consistent behavior for accessories across render modes +- Semantic control of pass inclusion (e.g., do not render in reflection pass) +- Optimization by excluding off-screen or nested mesh content + +## Extension Schema + +This extension is defined per `mesh.primitive`, allowing fine-grained render behavior control. + +```json +{ + "meshes": [ + { + "primitives": [ + { + "extensions": { + "KHR_avatar_mesh_annotation_rendering": { + "renderVisibility": "firstPersonOnly", + "renderTags": ["eyewear", "forceRender"] + } + } + } + ] + } + ] +} +``` + +### Properties + +| Property | Type | Description | +|------------------|-------------|-----------------------------------------------------------------------------| +| `renderVisibility` | string | Controls camera-based visibility. Enum: `"always"` | `"firstPersonOnly"` | `"thirdPersonOnly"` | `"never"` | +| `renderTags` | string[] | Optional list of semantic labels for custom rendering logic | + +## Recommended Usage Patterns + +### First-Person Hiding + +```json +"renderVisibility": "thirdPersonOnly" +``` + +Used to hide geometry (e.g., head, hair, hats) in first-person mode to prevent obstruction. + +### Always-Visible Elements + +```json +"renderVisibility": "always" +``` + +Used for elements like top meshes that should always remain active regardless of view or culling. + +## Implementation Notes + +- These properties have no effect unless supported by the runtime. +- Runtimes may map `renderVisibility` values to camera tag groups or dynamic material toggles. + +## License + +This extension is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md new file mode 100644 index 0000000000..d89f53dc94 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md @@ -0,0 +1,122 @@ +# KHR_avatar_skeleton_bindpose + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_avatar` + +## Overview + +**THIS EXTENSION IS VERY MUCH WORK IN PROGRESS** + +The `KHR_avatar_skeleton_bindpose` extension defines a canonical bind pose for the avatar's skeleton. This pose serves as a neutral reference that supports animation retargeting, mesh deformation validation, and consistency across toolchains. It is particularly useful when the glTF `skins[].inverseBindMatrices` are insufficient or absent for expressing the true skeletal rest position. + +## Extension Schema + + +```json +{ + "extensions": { + "KHR_avatar_skeleton_bindpose": { + "poseType": "TPose", + "skeleton": 0, + "jointBindPoses": [ + { + "joint": 0, + "matrix": [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ] + } + ] + } + } +} +``` + + +### Properties + +| Property | Type | Description | +|------------------|-----------|-----------------------------------------------------------------------------| + +| `poseType` | string | Enum: `TPose`, `APose`, `Custom`. Declares the avatar’s general pose classification. | +| `skeleton` | integer | Index into glTF `skins[]`; defines the joint set this bind pose applies to. | + +| `jointBindPoses` | array | List of bind pose matrices, each associated with a joint node index. | +| `joint` | integer | Index of the joint node in the glTF `nodes` array. | +| `matrix` | float[16] | Column-major 4x4 matrix defining the joint’s bind pose in model space. | + +## Relationship to glTF 2.0 Skinning + +In glTF 2.0, `skins[].inverseBindMatrices` define the transformation from joint space to mesh space. However, those matrices may not capture the canonical rest pose or may be preprocessed for runtime purposes. + +This extension supplements or overrides that mechanism by defining joint rest positions explicitly in model space, allowing authoring tools and runtimes to perform consistent deformation or retargeting operations. + +> Note: This extension does not require that these bind pose matrices be used for skinning directly—they are semantic references to a "T-pose" or other neutral position. + + +### poseType Enum + +| Value | Description | +|-----------|-----------------------------------------------------------------------------| +| `TPose` | Arms extended horizontally. Common neutral rest pose for retargeting. | +| `APose` | Arms angled downward. Used by some avatar authoring tools. | +| `Custom` | Any pose that does not fit T-Pose or A-Pose definitions. | + + +## Implementation Notes + +- A joint listed in `jointBindPoses` must exist in the `nodes` array. +- The bind pose matrix must be specified in model space (i.e., world-relative). +- This extension can be used in tandem with `skins[].inverseBindMatrices`, but is intended to expose clearer semantic meaning. + +## Example + +```json +{ + "asset": { + "version": "2.0" + }, + "extensionsUsed": [ + "KHR_avatar", + "KHR_avatar_skeleton_biped", + "KHR_avatar_skeleton_bindpose" + ], + "extensions": { + "KHR_avatar_skeleton_bindpose": { + "jointBindPoses": [ + { + "joint": 0, + "matrix": [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ] + } + ] + } + } +} +``` + +## License + +This extension specification is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md new file mode 100644 index 0000000000..b63a87ae49 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md @@ -0,0 +1,140 @@ +# KHR_avatar_skeleton_biped + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Depends on: `KHR_avatar` + +## Overview + +**THIS EXTENSION IS VERY MUCH WORK IN PROGRESS** + +The `KHR_avatar_skeleton_biped` extension enables bipedal avatars. Like with other avatar extensions, its presence represents the data contract that the model itself is a bipedal character model. This extension enables clarifying what joints are for retargeting and compatibility across tools and platforms by specifying a canonical set of joints and their hierarchical structure. + +This extension does not modify the glTF skinning or animation system, but instead annotates the avatar’s node hierarchy to indicate which nodes represent canonical joints in a bipedal skeleton. + +## Extension Schema Example + +```json +{ + "extensions": { + "KHR_avatar_skeleton_biped": { + "joints": { + "hips": 0, + "spine": 1, + "chest": 2, + "neck": 3, + "head": 4, + "leftUpperLeg": 5, + "leftLowerLeg": 6, + "leftFoot": 7, + "rightUpperLeg": 8, + "rightLowerLeg": 9, + "rightFoot": 10, + "leftUpperArm": 11, + "leftLowerArm": 12, + "leftHand": 13, + "rightUpperArm": 14, + "rightLowerArm": 15, + "rightHand": 16 + } + } + } +} +``` + +### Properties + +| Property | Type | Description | +|----------------|-------------------|-----------------------------------------------------------------------------| +| `joints` | object | Mapping from canonical biped joint names to node indices in the glTF file. | + +Each joint name corresponds to a node present in the glTF node hierarchy. The hierarchy as it exists then informs the skeletal hierarchy for parsing purposes. + +## Example + +```json +{ + "asset": { + "version": "2.0" + }, + "nodes": [ + { "name": "Hips" }, + { "name": "Spine", "parent": 0 }, + { "name": "Chest", "parent": 1 }, + { "name": "Neck", "parent": 2 }, + { "name": "Head", "parent": 3 }, + ... + ], + "extensionsUsed": [ + "KHR_avatar", + "KHR_avatar_skeleton_biped" + ], + "extensions": { + "KHR_avatar_skeleton_biped": { + "joints": { + "hips": 0, + "spine": 1, + "chest": 2, + "neck": 3, + "head": 4 + } + } + } +} +``` + +## Relationship to glTF 2.0 Skinning + +The `KHR_avatar_skeleton_biped` extension builds on top of the core glTF 2.0 skinning system. It does **not** introduce new skinning mechanics, but instead annotates which nodes in the existing `skins[].joints[]` structure correspond to meaningful joints in a developer-defined skeletal rig. + +The joint indices specified in the `joints` dictionary refer directly to elements within the glTF `nodes` array, and should match those used in a valid `skin` structure: + +- The avatar mesh should be associated with a `skin`, per [glTF 2.0 Skinning](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#skins). +- The joints listed in this extension must be a subset of the joints defined in `skins[j].joints`. + +This enables runtime engines to extract semantic meaning from joint hierarchies already used for mesh deformation, supporting animation retargeting and avatar interoperability. + +## Skeletal Mapping Support + +Rather than define mapping logic directly in this extension, developers should use the standalone [`KHR_avatar_skeleton_mapping`](./KHR_avatar_skeleton_mapping_README.md) extension for any one-to-one or one-to-many joint remapping between different rig topologies. + +That extension supports weighted joint translation and enables cleaner separation between semantic labeling (this extension) and rig interoperability (mapping). + +## Skeleton Standardization (In Progress) + +This extension currently avoids defining any required or default biped joint hierarchy. + +> **Why?** +> Standardizing on a single joint hierarchy would inadvertently lock the majority of developers into a single rig structure, limiting flexibility for studios and tools that use different conventions. + +Instead, this extension enables **declarative labeling** of a bipedal skeleton using your rig's native hierarchy, and encourages semantic interoperability through mapping via the `KHR_avatar_skeleton_mapping` extension. + +As the ecosystem matures, guidance or profiles may emerge for common structures—but this extension deliberately avoids enforcing that at this time. + +## Implementation Notes + +- This extension is non-destructive and overlays semantic information atop the existing glTF node hierarchy. +- Tools can use this extension to retarget animation between avatars, align expressions, or validate rigging consistency. +- The specified joint indices must form a valid hierarchy rooted at a common ancestor (usually `hips`). + +## Known Implementations +None, TBD + +## License + +This extension specification is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md new file mode 100644 index 0000000000..c41a2319cd --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md @@ -0,0 +1,155 @@ +# KHR_avatar_skeleton_mapping + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_avatar` +Typically used in conjunction with: `KHR_avatar_skeleton_biped` + +## Overview + +The `KHR_avatar_skeleton_mapping` extension provides a mechanism to map a skeleton rig to a reference rig, enabling retargeting and compatibility across different skeleton topologies. This extension is particularly useful for normalizing diverse rig structures across platforms and authoring tools. It provides one-to-one and one-to-many mapping; with the expectation that distributed weights add up to 1.0. + +## Extension Schema + +```json +{ + "extensions": { + "KHR_avatar_skeleton_mapping": { + "mappings": { + "Spine1": [ + { "target": "spine", "weight": 0.5 }, + { "target": "chest", "weight": 0.5 } + ], + "JawJoint": [ + { "target": "jaw", "weight": 1.0 } + ] + } + } + } +} +``` + +### Properties + +| Property | Type | Description | +|--------------|---------|-----------------------------------------------------------------------------| +| `mappings` | object | Dictionary mapping source joint names to reference rig joint names. | +| `target` | string | Name of the reference joint. | +| `weight` | number | Influence of this target in the mapping. Must sum to 1.0 per source joint. | + + +### Mapping Types + +This extension supports both one-to-one and one-to-many mappings: + +- **One-to-one**: A source joint maps directly to a single reference joint with a weight of 1.0. +- **One-to-many**: A source joint influences multiple reference joints, each with a fractional weight (all weights must sum to 1.0). + +This provides flexibility for approximating intermediate or compound joints across rig topologies. + + +## Mapping to Known Standard Rigs + +In many real-world scenarios, developers must remap an avatar's native joint structure to a **known, standardized rig**—such as a runtime's internal avatar model or a predefined specification like VRM's Humanoid rig. + +This extension supports such cases by allowing one-to-one or one-to-many weighted mappings between a model’s joints and those of a **target standard rig**. + +These standard rigs are typically defined by the consuming platform, runtime, or service provider. Each standard rig: +- Defines a fixed joint name vocabulary and hierarchy. +- Is assumed to be known at runtime and used for animation playback, retargeting, IK, or expression control. + +### Example: Mapping to VRM Humanoid + +The [VRM 1.0 Humanoid specification](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/humanoid.md) defines a standardized set of joints used across VRM-compatible platforms. + +Here’s an example mapping from a custom rig into VRM Humanoid: + +```json +{ + "extensions": { + "KHR_avatar_skeleton_mapping": { + "source": "localRig", + "target": "vrmHumanoid", + "mappings": [ + { + "source": "myRig_hips", + "targets": [ + { "joint": "hips", "weight": 1.0 } + ] + }, + { + "source": "myRig_head", + "targets": [ + { "joint": "head", "weight": 1.0 } + ] + }, + { + "source": "myRig_leftFoot", + "targets": [ + { "joint": "leftFoot", "weight": 0.8 }, + { "joint": "leftToeBase", "weight": 0.2 } + ] + } + ] + } + } +} +``` + +In this example: +- `"source"` is the custom rig's joint name. +- `"joint"` in the `"targets"` is a joint name defined by the target standard rig (here, VRM Humanoid). +- The system using this extension must understand what `"vrmHumanoid"` means (i.e., the joint vocabulary and structure must be pre-declared by the consuming runtime). + +## Mapping Registry and Target Namespaces + +While this extension does not mandate a central registry, developers are encouraged to: +- Document the name and structure of their standard rigs +- Reuse identifiers like `"vrmHumanoid"`, `"unityHumanoid"`, or `"metaRig"` consistently +- Provide a public schema or joint list for validation and interoperability + + +## Implementation Notes + +- Joint names are assumed to refer to nodes in the `nodes` array. +- The reference rig vocabulary may be shared across engines or projects. +- This extension does not modify skinning behavior, but informs tooling and runtime animation retargeting. + +## Example + +```json +{ + "extensionsUsed": [ + "KHR_avatar_skeleton_mapping" + ], + "extensions": { + "KHR_avatar_skeleton_mapping": { + "mappings": { + "Spine1": [ + { "target": "spine", "weight": 0.5 }, + { "target": "chest", "weight": 0.5 } + ] + } + } + } +} +``` + +## License + +This extension specification is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md b/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md new file mode 100644 index 0000000000..98a2986827 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md @@ -0,0 +1,109 @@ +# KHR_avatar_virtual_joints + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- Ernest Lee, Individual Contributor +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_avatar` + +## Overview + +The `KHR_avatar_virtual_joints` extension introduces *virtual joints*—custom transform nodes that exist relative to the avatar’s skeletal hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. + +Virtual joints are defined via an offset transform relative to a single parent joint, and do **not** participate in skinning. They are evaluated at runtime for behavior logic and procedural animation. + +This extension is inspired in part by constructs like `lookAt` in VRM and aims to unify such functionality into a generic system usable across multiple glTF-based runtimes. + +## Use Cases + +- **Look-at targets** (for head/eye tracking) +- **Attachment points** (e.g., a weapon or tool socket) +- **Sitting or standing targets** +- **Hint points** for IK solvers +- **Camera or gaze anchors** + +## Schema + +```json +{ + "extensions": { + "KHR_avatar_virtual_joints": { + "virtualJoints": [ + { + "name": "arm_socket", + "parentJoint": 18, + "translation": [0.0, 0.1, 0.0], + "rotation": [0.0, 0.0, 0.0, 1.0] + }, + { + "name": "lookAt_target", + "parentJoint": 8, + "translation": [0.0, 0.0, 0.35], + "rotation": [0.0, 0.0, 0.0, 1.0] + }, + { + "name": "sitting_point", + "parentJoint": 0, + "translation": [0.0, 0.0, -0.2], + "rotation": [0.0, 0.0, 0.0, 1.0] + } + ] + } + } +} +``` + +### Properties + +| Property | Type | Description | +|----------------|-----------|-----------------------------------------------------------------------------| +| `name` | string | Semantic identifier of the virtual joint | +| `parentJoint` | integer | Index into the glTF `nodes[]` array representing the base joint | +| `translation` | float[3] | Local offset (X, Y, Z) relative to the parent joint | +| `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent joint | + +## Examples + +### Arm Attachment Virtual Joint + +- **Name**: `"arm_socket"` +- **Parent**: Between elbow and wrist (e.g., joint index 18) +- **Offset**: `(0.0, 0.1, 0.0)` +- **Usage**: Anchor for attaching objects + +### Look At Virtual Joint + +- **Name**: `"lookAt_target"` +- **Parent**: `"head"` joint (e.g., joint index 8) +- **Offset**: `(0.0, 0.0, 0.35)` +- **Usage**: Target for runtime look-at behavior (eyes/head alignment). + +### Sitting Point Virtual Joint + +- **Name**: `"sitting_point"` +- **Parent**: `"pelvis"` joint (e.g., joint index 0) +- **Offset**: `(0.0, 0.0, -0.2)` +- **Usage**: Anchor point for aligning seated positions. + +## Implementation Notes + +- Virtual joints should exist only within this extension and **must not overlap with joints used in skinning**. +- Their transformation is computed at runtime by applying the offset to the parent joint’s world transform. +- Tools and runtimes may expose these as attachable sockets or semantic retargeting anchors. + +## License + +This extension is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html From 1413d202bc5147393268e49d8f4ac642316f298c Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 28 Jul 2025 15:55:49 -0700 Subject: [PATCH 02/48] Updated Contributes list as requested --- extensions/2.0/Khronos/KHR_avatar/README.md | 2 +- .../KHR_avatar_expression_joint/README.md | 65 +------------------ .../KHR_avatar_expression_mapping/README.md | 2 +- .../README.md | 2 +- .../README.md | 2 +- .../KHR_avatar_expression_texture/README.md | 3 +- .../KHR_avatar_mesh_annotation/README.md | 2 +- .../README.md | 2 +- .../KHR_avatar_skeleton_bindpose/README.md | 2 +- .../KHR_avatar_skeleton_biped/README.md | 2 +- .../KHR_avatar_skeleton_mapping/README.md | 2 +- .../KHR_avatar_virtual_joints/README.md | 4 +- 12 files changed, 14 insertions(+), 76 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_avatar/README.md b/extensions/2.0/Khronos/KHR_avatar/README.md index 284603a124..fc5ab303bf 100644 --- a/extensions/2.0/Khronos/KHR_avatar/README.md +++ b/extensions/2.0/Khronos/KHR_avatar/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md index 0cd9d19809..14e503c7ff 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor @@ -68,7 +68,7 @@ Optionally, these may be aligned with industry standards, such as [Facial Action | `expression` | string | Expression name this joint contributes to. | | `channels` | array | array representing channels that must correspond to either `"rotation"`, `"translation"`, or `"scale"`; indicates transform types. | -## Animation Integration (Expressions Tab Recommendation) +## Animation Integration - Expression timing, blending, and control must use glTF `animations` channels. - Animations targeting expression-driven `rotation`, `translation`, or `scale` must conform to glTF 2.0's animation model. @@ -89,67 +89,6 @@ For expressions that represent binary or toggle states (such as `blinkLeft`, `bl STEP interpolation ensures that an expression toggles cleanly between fully off (`0.0`) and fully on (`1.0`) states, providing crisp visual transitions and avoiding interpolation artifacts that could occur with `LINEAR` interpolation in binary scenarios. -## Example: Expression with glTF Animation - -Here is how an expression-driven joint defined in this extension could interact with glTF's native animation system: - -### Step 1: Define a Semantic Mapping in this Extension - -```json -{ - "extensions": { - "KHR_avatar_expression_mapping": { - "expressions": [ - { - "expression": "smile", - "animation": 0, - "channels": [0,1,2] - }, - { - "expression": "frown", - "animation": 1, - "channels": [0,1,3] - } - ] - } - } -} -``` - -This maps the joint at node index `5` to the expression `"smile"`, using rotation as its mode of influence. - -### Step 2: Animate the Joint Using Standard glTF Channels - -In the main glTF `animations[]`, use standard animation targeting to animate the `rotation` of node 5: - -```json -{ - "animations": [ - { - "channels": [ - { - "sampler": 0, - "target": { - "node": 5, - "path": "rotation" - } - } - ], - "samplers": [ - { - "input": 0, - "output": 1, - "interpolation": "LINEAR" - } - ] - } - ] -} -``` - -This animation channel should rotate the joint in a way that corresponds to a `smile` expression. The weights of the keyframes must reflect the normalized [0.0 – 1.0] expression activation. - - ## Implementation Notes - Multiple joints may be assigned to the same expression. diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md index bc4ed9ce80..5d558861fd 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md index a260a21907..a042c9d269 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md index d72eeb0213..cea78cfe58 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md index b360eb4930..c72c4fbe00 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor @@ -256,7 +256,6 @@ Animation of either the texture index or texture transform must be implemented u - Expression weights should animate between `0.0` (off) and `1.0` (fully active). - The avatar system uses these animations to blend or toggle texture visuals in accordance with semantic expressions. - ## License This extension specification is licensed under the Khronos Group Extension License. diff --git a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md index f08d878e5c..1e042c54f5 100644 --- a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor diff --git a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md index 0f741a8d5b..35abe8a66e 100644 --- a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md index d89f53dc94..d67d254a86 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md index b63a87ae49..7ee80e9685 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md index c41a2319cd..4f9c5ad372 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor diff --git a/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md b/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md index 98a2986827..01d92b4d62 100644 --- a/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md @@ -4,7 +4,7 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- Ernest Lee, Individual Contributor +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor @@ -17,7 +17,7 @@ Written against the glTF 2.0 specification. Dependent on: `KHR_avatar` - + ## Overview The `KHR_avatar_virtual_joints` extension introduces *virtual joints*—custom transform nodes that exist relative to the avatar’s skeletal hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. From 7b4723ea3c96d9f95a580c7d45cbdabb97935ab4 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 28 Jul 2025 21:58:07 -0700 Subject: [PATCH 03/48] Addressing some comments - Added Nick Burkard to the list of contributors - Changed Verbiage where needed to ensure there's no implication of a vocabulary definition as part of the phase 1 set of extensions. - Resolved as many formatting concerns as possible --- extensions/2.0/Khronos/KHR_avatar/README.md | 113 +++++++++--------- .../KHR_avatar_expression_joint/README.md | 37 +++--- .../KHR_avatar_expression_mapping/README.md | 36 +++--- .../README.md | 28 ++--- .../README.md | 39 +++--- .../KHR_avatar_expression_texture/README.md | 44 ++++--- .../KHR_avatar_mesh_annotation/README.md | 11 +- .../README.md | 3 +- .../KHR_avatar_skeleton_bindpose/README.md | 17 ++- .../KHR_avatar_skeleton_biped/README.md | 8 +- .../KHR_avatar_skeleton_mapping/README.md | 37 +++--- .../KHR_avatar_virtual_joints/README.md | 39 +++--- 12 files changed, 198 insertions(+), 214 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_avatar/README.md b/extensions/2.0/Khronos/KHR_avatar/README.md index fc5ab303bf..c59c6f2366 100644 --- a/extensions/2.0/Khronos/KHR_avatar/README.md +++ b/extensions/2.0/Khronos/KHR_avatar/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -53,26 +54,31 @@ Avatar metadata should be expressed using the `KHR_xmp_json_ld` format, a struct The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as part of the defined extension usage. Metadata keys and structures are defined in the shared Khronos Avatar Metadata schema (TBD). -| DC/XMP_JSON_LD Property | Why | Required | -|-------------------------|------------------------------------------------------------------------------|----------| -| dc:title | | Yes | -| dc:creator | | Yes | -| dc:license | | No | -| dc:rights | | No | -| dc:created | Date on which the asset was created | No | +| DC/XMP_JSON_LD Property | Why | Required | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| dc:title | | Yes | +| dc:creator | | Yes | +| dc:license | | No | +| dc:rights | | No | +| dc:created | Date on which the asset was created | No | | dc:publisher | Identifies the entity responsible for making the resource available; important for understanding the source and authority of the content. | No | -| dc:description | Context and a summary of the content | No | -| dc:subject | Can potentially be used for content tagging/association | No | -| dc:source | Important for tracing the provenance and ensuring proper attribution. | Yes | -| khr:version | | No | -| khr:thumbnailImage | | No | +| dc:description | Context and a summary of the content | No | +| dc:subject | Can potentially be used for content tagging/association | No | +| dc:source | Important for tracing the provenance and ensuring proper attribution. | Yes | +| khr:version | | No | +| khr:thumbnailImage | | No | ## Example ```json { "asset": { - "version": "2.0" + "version": "2.0", + "extensions": { + "KHR_xmp_json_ld": { + "packet": 0 + } + } }, "scene": 0, "scenes": [ @@ -85,52 +91,46 @@ The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as par "name": "AvatarRoot" } ], - "extensionsUsed": [ - "KHR_avatar", - "KHR_xmp_json_ld" - ], + "extensionsUsed": ["KHR_avatar", "KHR_xmp_json_ld"], "extensions": { "KHR_avatar": { "sceneIndex": 0 }, - + "KHR_xmp_json_ld": { - "packets": [ - { - "@context": { - "dc": "http://purl.org/dc/elements/1.1/", - "vrm": "https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/meta.md" - }, - "dc:title": "Example Model", - "dc:creator": { - "@list": [ - "Author1", - "AuthorEmail1@email.com", - "Author2", - "AuthorEmail2@email.com" - ] - }, - "dc:license": { - "@list": [ - "https://vrm.dev/licenses/1.0/", - "https://example.com/third-party-license" - ] - }, - "dc:created": "2023-05-05", - "dc:rights": "Copyright information about the model", - "dc:publisher": "Imaginary Corporation A, LLC", - "dc:description": "A sentence, or paragraph describing the avatar at hand", - "dc:subject": { - "@list": [ - "Example trait", - "Another example trait" - ] - }, - "dc:source": "imaginaryCompany.com/avatarl", - "khr:version": "1.0", - "khr:thumbnailImage": 0 -} - ] + "packets": [ + { + "@context": { + "dc": "http://purl.org/dc/elements/1.1/", + "vrm": "https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/meta.md" + }, + "dc:title": "Example Model", + "dc:creator": { + "@list": [ + "Author1", + "AuthorEmail1@email.com", + "Author2", + "AuthorEmail2@email.com" + ] + }, + "dc:license": { + "@list": [ + "https://vrm.dev/licenses/1.0/", + "https://example.com/third-party-license" + ] + }, + "dc:created": "2023-05-05", + "dc:rights": "Copyright information about the model", + "dc:publisher": "Imaginary Corporation A, LLC", + "dc:description": "A sentence, or paragraph describing the avatar at hand", + "dc:subject": { + "@list": ["Example trait", "Another example trait"] + }, + "dc:source": "imaginaryCompany.com/avatarl", + "khr:version": "1.0", + "khr:thumbnailImage": 0 + } + ] } } } @@ -138,13 +138,12 @@ The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as par ## Implementation Notes -- `sceneIndex` is required and indicates what scene a particular avatar belongs to +- `sceneIndex` is required and represennts the index of the glTF `scene` representing the avatar. Used to distinguish the avatar root when multiple scenes exist. - Consumers should use this marker as a signal to search for additional avatar-related extensions, including skeletal, expression, and other khronos avatar extensions. -- Support for `JSON_XMP_LD` is encouraged to ensure interoperable metadata across tools and runtimes. +- Support for `KHR_xmp_json_ld` is encouraged to ensure interoperable metadata across tools and runtimes. ## Known Implementations - ## License This extension specification is licensed under the Khronos Group Extension License. diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md index 14e503c7ff..7ad10880d4 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -15,7 +16,7 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Dependent on: `KHR_avatar` Typically used in conjunction with: `KHR_avatar_expression_mapping` @@ -25,33 +26,33 @@ The `KHR_avatar_expression_joint` extension provides a semantic mapping between This extension is purely descriptive: it does not define or store animation data itself. -## Expression Vocabulary +## Reference Expression Categories/Vocabularies Expression types include: -- **Emotions**: `happy`, `angry`, `surprised`, etc. -- **Visemes**: `aa`, `ee`, `th`, `oo`, etc. -- **Modifiers**: `left`, `right`, `upper`, `lower`, etc. -- **Gestures and Actions**: `blink`, `smile`, `jawOpen`, etc. +- **Emotions** (e.g. `happy`, `angry`, `surprised`) +- **Visemes** (e.g. `aa`, `oo`, `th`) +- **Modifiers** (e.g. `left`, `right`, `upper`, `lower`) +- **Gestures and Actions** (e.g. `blink`, `smile`, `jawOpen`) -Optionally, these may be aligned with industry standards, such as [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). +Optionally, these may be aligned with industry standards, such as [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). ## Extension Schema ```json { - "extensions": { - "KHR_avatar_expression_mapping": { + "extensions": { + "KHR_avatar_expression_joint": { "expressions": [ { "expression": "smile", "animation": 0, - "channels": [0,1,2] + "channels": [0, 1, 2] }, { "expression": "frown", "animation": 1, - "channels": [0,1] + "channels": [0, 1] } ] } @@ -61,12 +62,12 @@ Optionally, these may be aligned with industry standards, such as [Facial Action ### Properties -| Property | Type | Description | -|--------------|---------|-----------------------------------------------------------------------------| -| `expressions`| array | Array of mappings between animation/channels and expression labels. | -| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | -| `expression` | string | Expression name this joint contributes to. | -| `channels` | array | array representing channels that must correspond to either `"rotation"`, `"translation"`, or `"scale"`; indicates transform types. | +| Property | Type | Description | +| ------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| `expressions` | array | Array of mappings between animation/channels and expression labels. | +| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | +| `expression` | string | Expression name this joint contributes to. | +| `channels` | array | array representing channels that must correspond to either `"rotation"`, `"translation"`, or `"scale"`; indicates transform types. | ## Animation Integration @@ -75,6 +76,7 @@ Optionally, these may be aligned with industry standards, such as [Facial Action - This ensures consistency, ease of implementation, and interoperability across runtimes. Each animation channel used to drive an expression should operate within a **normalized 0-to-1 range**, where: + - `0.0` indicates the expression is fully inactive. - `1.0` indicates the expression is fully active. @@ -88,7 +90,6 @@ For expressions that represent binary or toggle states (such as `blinkLeft`, `bl STEP interpolation ensures that an expression toggles cleanly between fully off (`0.0`) and fully on (`1.0`) states, providing crisp visual transitions and avoiding interpolation artifacts that could occur with `LINEAR` interpolation in binary scenarios. - ## Implementation Notes - Multiple joints may be assigned to the same expression. diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md index 5d558861fd..4d8d8bed38 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -15,24 +16,22 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Dependent on: `KHR_avatar` Can be used alongside: `KHR_avatar_expression_morphtargets` or other expression sources ## Overview +## Reference Expression Categories/Vocabularies -## Reference Expression Vocabulary Expression names may be grouped into categories including: -- **Emotions** (e.g., `happy`, `angry`, `surprised`) -- **Visemes** (e.g., `aa`, `oo`, `th`) -- **Modifiers** (e.g., `left`, `right`, `upper`, `lower`) -- **Gestures and Actions** (e.g., `blink`, `smile`, `jawOpen`) +- **Emotions** (e.g. `happy`, `angry`, `surprised`) +- **Visemes** (e.g. `aa`, `oo`, `th`) +- **Modifiers** (e.g. `left`, `right`, `upper`, `lower`) +- **Gestures and Actions** (e.g. `blink`, `smile`, `jawOpen`) -Implementers are encouraged to use this vocabulary directly or map custom expressions to it using `KHR_avatar_expression_mapping`. - -The `KHR_avatar_expression_mapping` extension provides a general-purpose mechanism for mapping expression names used in an avatar’s mesh to a known expression vocabulary or rig specification. This allows different authoring pipelines or runtimes to translate between heterogeneous expression sets. +The `KHR_avatar_expression_mapping` extension provides a general-purpose mechanism for mapping expression names used in an avatar to a known expression vocabulary. This allows different authoring pipelines or runtimes to translate between heterogeneous expression sets. ## Extension Schema @@ -45,9 +44,7 @@ The `KHR_avatar_expression_mapping` extension provides a general-purpose mechani { "target": "Smile", "weight": 0.8 }, { "target": "LeftCheekRaise", "weight": 0.2 } ], - "jawOpen": [ - { "target": "MouthOpen", "weight": 1.0 } - ] + "jawOpen": [{ "target": "MouthOpen", "weight": 1.0 }] } } } @@ -56,12 +53,11 @@ The `KHR_avatar_expression_mapping` extension provides a general-purpose mechani ### Properties -| Property | Type | Description | -|--------------|---------|-----------------------------------------------------------------------------| -| `mappings` | object | Dictionary mapping expression names to reference vocabulary terms. | -| `target` | string | Name of the expression in the target vocabulary. | -| `weight` | number | Influence of this target. Must sum to 1.0 per expression key. | - +| Property | Type | Description | +| ---------- | ------ | ------------------------------------------------------------------ | +| `mappings` | object | Dictionary mapping expression names to reference vocabulary terms. | +| `target` | string | Name of the expression in the target vocabulary. | +| `weight` | number | Influence of this target. Must sum to 1.0 per expression key. | ### Mapping Types @@ -82,9 +78,7 @@ This allows developers to bridge between custom expression sets and shared vocab ```json { - "extensionsUsed": [ - "KHR_avatar_expression_mapping" - ], + "extensionsUsed": ["KHR_avatar_expression_mapping"], "extensions": { "KHR_avatar_expression_mapping": { "mappings": { diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md index a042c9d269..b144058064 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -25,6 +26,7 @@ The `KHR_avatar_expression_morphtarget` extension provides semantic bindings bet This extension does **not** define animation data itself. Instead, it enables consistent reference of morph target indices across tools, runtimes, and expressions. ## Reference Expression Vocabulary + Potential expression categories include: - **Emotions** (e.g., `happy`, `angry`, `surprised`) @@ -32,14 +34,14 @@ Potential expression categories include: - **Modifiers** (e.g., `left`, `right`, `upper`, `lower`) - **Gestures and Actions** (e.g., `blink`, `smile`, `jawOpen`) -Optionally, these may be aligned with industry standards, such as the [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). +Optionally, these may be aligned with industry standards, such as the [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). ## Extension Schema ```json { - "extensions": { - "KHR_avatar_expression_mapping": { + "extensions": { + "KHR_avatar_expression_morphtarget": { "expressions": [ { "expression": "smile", @@ -59,12 +61,12 @@ Optionally, these may be aligned with industry standards, such as the [Facial Ac ### Properties -| Property | Type | Description | -|--------------|---------|-----------------------------------------------------------------------------| -| `expressions`| array | Array of mappings between animation/channels and expression labels. | -| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | -| `expression` | string | Expression name this joint contributes to. | -| `channel` | integet | Index representing the `"weights"` channel | +| Property | Type | Description | +| ------------- | ------- | ------------------------------------------------------------------------------ | +| `expressions` | array | Array of mappings between animation/channels and expression labels. | +| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | +| `expression` | string | Expression name this joint contributes to. | +| `channel` | integet | Index representing the `"weights"` channel | ## Animation Integration (Expressions Tab Recommendation) @@ -101,7 +103,6 @@ All morph target expressions should be driven using standard glTF animation chan - Each element of the `weights` array corresponds to one morph target on the associated mesh primitive. - Expression systems should coordinate with these indices using the bindings declared by this extension. - ## Example: Expression with glTF Animation ### Step 1: Bind Expression to Morph Target @@ -110,7 +111,7 @@ All morph target expressions should be driven using standard glTF animation chan { "extensions": { "KHR_avatar_expression_morphtarget": { - "expressions": [ + "expressions": [ { "expression": "smile", "animation": 0, @@ -121,7 +122,7 @@ All morph target expressions should be driven using standard glTF animation chan "animation": 1, "channel": 0 } - ] + ] } } } @@ -164,7 +165,6 @@ This binds morph target index 2 on mesh 0, primitive 0, to the expression `"blin The animation should update the relevant morph target weight (in this case index 2) between `0.0` and `1.0` to control the `"blinkLeft"` expression. The usage of `STEP` interpolation ensures clean toggles between on/off states. - ## Implementation Notes - This extension provides a consistent mapping between expression names and mesh targets, allowing glTF animation data to be expressive-aware. @@ -177,7 +177,6 @@ For expressions that represent binary or toggle states (such as eye blinks, mout Using STEP interpolation ensures that the expression toggles cleanly between fully off (0) and fully on (1) states, providing crisp transitions and avoiding unintended interpolation artifacts. - All expression-driven changes defined by this extension should rely on standard glTF animation mechanisms as described in the Khronos [Expressions Tab](https://docs.google.com/document/d/1ALRCPbXqQuWZvA9Sm2TsBFuW75h-of_lfD6sN7QwFU0/edit?pli=1&tab=t.x433oui5434f). - Expression timing, blending, and control must use glTF `animations` channels. @@ -186,7 +185,6 @@ All expression-driven changes defined by this extension should rely on standard This approach simplifies avatar implementation by centralizing expression playback in the glTF animation system, reducing custom handling and improving cross-platform compatibility. - ## License This extension specification is licensed under the Khronos Group Extension License. diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md index cea78cfe58..4b808501c2 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -15,7 +16,7 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Dependent on: `KHR_avatar` Works alongside: `KHR_avatar_expression_mapping`, `KHR_avatar_expression_joint`, `KHR_avatar_expression_morphtargets`. @@ -31,7 +32,7 @@ The `KHR_avatar_expression_procedural` extension introduces a metadata layer tha By labeling expressions as procedural, this extension enables runtime systems (e.g., animation controllers, live-tracking systems, or AI avatars) to drive those expressions without conflict with animation data or user inputs. -This metadata is **descriptive only**: it does not contain animation or behavior logic itself. Instead, it signals to tools and engines that the following expressions are *expected to be dynamically generated*. +This metadata is **descriptive only**: it does not contain animation or behavior logic itself. Instead, it signals to tools and engines that the following expressions are _expected to be dynamically generated_. ## Use Cases @@ -63,23 +64,22 @@ This metadata is **descriptive only**: it does not contain animation or behavior ### Properties -| Property | Type | Description | -|-------------------------|----------|--------------------------------------------------------------------------------------| -| `proceduralExpressions` | array | List of expression metadata entries that are intended to be procedurally controlled | -| `expression` | string | Expression name as defined in the expression mapping vocabulary | -| `mode` | string | Enum: `"timed"`, `"random"`, `"live"`, `"scripted"` — describes the procedural strategy | +| Property | Type | Description | +| ----------------------- | ------ | --------------------------------------------------------------------------------------- | +| `proceduralExpressions` | array | List of expression metadata entries that are intended to be procedurally controlled | +| `expression` | string | Expression name as defined in the expression mapping vocabulary | +| `mode` | string | Enum: `"timed"`, `"random"`, `"live"`, `"scripted"` — describes the procedural strategy | ## Procedural Modes -| Mode | Meaning | -|------------|-------------------------------------------------------------------------| -| `timed` | The expression occurs in regular intervals (e.g., blinking every 5s) | -| `random` | The expression fires with stochastic timing or weights | -| `live` | Driven by live-captured inputs (e.g., webcam, eye tracking) | -| `scripted` | Driven by external dialogue, AI logic, or gameplay sequences | +| Mode | Meaning | +| ---------- | ------------------------------------------------------------------------------ | +| `timed` | The expression occurs in regular intervals (e.g., blinking every 5s) | +| `random` | The expression fires with stochastic timing or weights | +| `live` | Driven by live-captured inputs (e.g., webcam, eye tracking) | +| `scripted` | Driven by external dialogue, AI logic, or gameplay sequences | | `mixed` | Combines two or more procedural sources, such as live tracking + scripted cues | - ## Expression Control Behavior To help define how procedural expressions interact with animation systems, this extension introduces an additional field called `conflictResolution`, inspired by the [VRM 1.0 specification](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md#lip-sync-procedural). @@ -88,11 +88,11 @@ Each procedural expression may declare a resolution strategy for combining proce ### `conflictResolution` Enum -| Value | Meaning | -|----------|-------------------------------------------------------------------------| -| `none` | No procedural influence. The expression is controlled exclusively by animation or input. | -| `block` | Procedural output *overrides* animation data while active. | -| `blend` | Procedural and animation data may be blended or accumulated together. | +| Value | Meaning | +| ------- | ---------------------------------------------------------------------------------------- | +| `none` | No procedural influence. The expression is controlled exclusively by animation or input. | +| `block` | Procedural output _overrides_ animation data while active. | +| `blend` | Procedural and animation data may be blended or accumulated together. | ### Example with Resolution Mode @@ -106,7 +106,6 @@ Each procedural expression may declare a resolution strategy for combining proce This allows developers to distinguish expressions meant to supplement animation (e.g., micro-blinks over emotive acting) versus those that must fully override input (e.g., forced gaze). - ## Implementation Notes - This extension is schema-only and does not contain behavior logic or animation data. diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md index c72c4fbe00..4988ae1954 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -16,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar`,`KHR_animation_pointer` +Dependent on: `KHR_avatar`,`KHR_animation_pointer` Can be used alongside: `KHR_avatar_expression_mapping` ## Overview @@ -30,12 +31,12 @@ The `KHR_avatar_expression_texture` extension enables expression-level control u Expressions may be categorized as: -- **Emotions** (e.g., `happy`, `angry`, `surprised`) -- **Visemes** (e.g., `aa`, `oo`, `th`) -- **Modifiers** (e.g., `left`, `right`, `upper`, `lower`) -- **Gestures and Actions** (e.g., `blink`, `smile`, `jawOpen`) +- **Emotions** (e.g. `happy`, `angry`, `surprised`) +- **Visemes** (e.g. `aa`, `oo`, `th`) +- **Modifiers** (e.g. `left`, `right`, `upper`, `lower`) +- **Gestures and Actions** (e.g. `blink`, `smile`, `jawOpen`) -Optionally, these may be aligned with industry standards, such as [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). +Optionally, these may be aligned with industry standards, such as [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). ## Extension Schema @@ -56,7 +57,7 @@ Optionally, these may be aligned with industry standards, such as [Facial Action "texture": 5, "expression": "angry", "animation": 1, - "channels": [0,1] + "channels": [0, 1] } ] } @@ -66,21 +67,20 @@ Optionally, these may be aligned with industry standards, such as [Facial Action ### Properties -| Property | Type | Description | -|---------------------|----------------|-------------------------------------------------------------------------------| -| `expressions` | array | List of texture-expression bindings. | -| `material` | integer | Index into the glTF `materials` array. | -| `texture` | integer | (Optional) Index into the glTF `textures` array, defining a replacement texture. | -| `textureTransform` | object | (Optional) UV transformations for texture-based expressions. | -| `expression` | string | Expression name associated with this texture or UV change. | +| Property | Type | Description | +| ------------------ | ------- | -------------------------------------------------------------------------------- | +| `expressions` | array | List of texture-expression bindings. | +| `material` | integer | Index into the glTF `materials` array. | +| `texture` | integer | (Optional) Index into the glTF `textures` array, defining a replacement texture. | +| `textureTransform` | object | (Optional) UV transformations for texture-based expressions. | +| `expression` | string | Expression name associated with this texture or UV change. | ### textureTransform properties -| Property | Type | Description | -|----------|-----------|--------------------------------------| -| `offset` | float[2] | UV offset for texture placement. | -| `scale` | float[2] | UV scale for texture transformation. | - +| Property | Type | Description | +| -------- | -------- | ------------------------------------ | +| `offset` | float[2] | UV offset for texture placement. | +| `scale` | float[2] | UV scale for texture transformation. | ### Recommended Interpolation for Binary Expressions @@ -88,7 +88,6 @@ For expressions that represent binary or toggle states (such as eye blinks, mout Using STEP interpolation ensures that the expression toggles cleanly between fully off (0) and fully on (1) states, providing crisp transitions and avoiding unintended interpolation artifacts. - ### Integration with KHR_animation_pointer For animations that involve texture swaps or UV transformations, implementations should rely on the [`KHR_animation_pointer`](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_animation_pointer) extension. This provides a standardized mechanism for animating texture and UV transform properties via JSON pointers. @@ -106,7 +105,7 @@ Dynamic texture swaps are not explicitly defined within the core glTF 2.0 specif ### UV Transformations -UV manipulations (offset, scale, rotation) require the widely adopted [`KHR_texture_transform`](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform) extension. +UV manipulations (offset, scale, rotation) require the widely adopted [`KHR_texture_transform`](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform) extension. - Animate properties within `KHR_texture_transform` using `KHR_animation_pointer`. - Ensure these transforms are included explicitly in the glTF material definitions to enable animations. @@ -164,7 +163,6 @@ For expressions that represent binary or toggle states (such as eye blinks, mout Using STEP interpolation ensures that the expression toggles cleanly between fully off (0) and fully on (1) states, providing crisp transitions and avoiding unintended interpolation artifacts. - ## Example: Expression with glTF Animation ### Step 1: Bind Expressions to Materials @@ -186,7 +184,7 @@ Using STEP interpolation ensures that the expression toggles cleanly between ful "texture": 5, "expression": "angry", "animation": 1, - "channels": [0,1] + "channels": [0, 1] } ] } diff --git a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md index 1e042c54f5..892be3171e 100644 --- a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -32,7 +33,7 @@ Unlike expression bindings or skeletons, this extension focuses on **attaching s ## Motivation -Avatar models often contain complex geometry with overlapping purposes—hair, clothing, limbs, devices, accessories, etc. Many applications need to reason about specific mesh subsets for: +Avatar models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets for: - Avatar customization layers - Haptic or interaction targeting @@ -67,10 +68,10 @@ Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i] ### Properties -| Property | Type | Description | -|------------------|---------------|-----------------------------------------------------------------------------| -| `tags` | string[] | List of free-form labels applicable to this primitive | -| `customData` | object | Optional freeform object for runtime-specific annotations (optional) | +| Property | Type | Description | +| ------------ | -------- | -------------------------------------------------------------------- | +| `tags` | string[] | List of free-form labels applicable to this primitive | +| `customData` | object | Optional freeform object for runtime-specific annotations (optional) | ## Use Cases & Examples diff --git a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md index 35abe8a66e..b91324ae8f 100644 --- a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -15,7 +16,7 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Dependent on: `KHR_avatar` ## Overview diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md index d67d254a86..7f0682de92 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -15,7 +16,7 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Dependent on: `KHR_avatar` ## Overview @@ -26,7 +27,6 @@ The `KHR_avatar_skeleton_bindpose` extension defines a canonical bind pose for t ## Extension Schema - ```json { "extensions": { @@ -49,7 +49,6 @@ The `KHR_avatar_skeleton_bindpose` extension defines a canonical bind pose for t } ``` - ### Properties | Property | Type | Description | @@ -70,15 +69,13 @@ This extension supplements or overrides that mechanism by defining joint rest po > Note: This extension does not require that these bind pose matrices be used for skinning directly—they are semantic references to a "T-pose" or other neutral position. - ### poseType Enum -| Value | Description | -|-----------|-----------------------------------------------------------------------------| -| `TPose` | Arms extended horizontally. Common neutral rest pose for retargeting. | -| `APose` | Arms angled downward. Used by some avatar authoring tools. | -| `Custom` | Any pose that does not fit T-Pose or A-Pose definitions. | - +| Value | Description | +| -------- | --------------------------------------------------------------------- | +| `TPose` | Arms extended horizontally. Common neutral rest pose for retargeting. | +| `APose` | Arms angled downward. Used by some avatar authoring tools. | +| `Custom` | Any pose that does not fit T-Pose or A-Pose definitions. | ## Implementation Notes diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md index 7ee80e9685..4e78bdd2da 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -58,9 +59,9 @@ This extension does not modify the glTF skinning or animation system, but instea ### Properties -| Property | Type | Description | -|----------------|-------------------|-----------------------------------------------------------------------------| -| `joints` | object | Mapping from canonical biped joint names to node indices in the glTF file. | +| Property | Type | Description | +| -------- | ------ | -------------------------------------------------------------------------- | +| `joints` | object | Mapping from biped joint names to node indices in the glTF file. | Each joint name corresponds to a node present in the glTF node hierarchy. The hierarchy as it exists then informs the skeletal hierarchy for parsing purposes. @@ -132,6 +133,7 @@ As the ecosystem matures, guidance or profiles may emerge for common structures - The specified joint indices must form a valid hierarchy rooted at a common ancestor (usually `hips`). ## Known Implementations + None, TBD ## License diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md index 4f9c5ad372..68ccf3a042 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -15,13 +16,13 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Dependent on: `KHR_avatar` Typically used in conjunction with: `KHR_avatar_skeleton_biped` ## Overview -The `KHR_avatar_skeleton_mapping` extension provides a mechanism to map a skeleton rig to a reference rig, enabling retargeting and compatibility across different skeleton topologies. This extension is particularly useful for normalizing diverse rig structures across platforms and authoring tools. It provides one-to-one and one-to-many mapping; with the expectation that distributed weights add up to 1.0. +The `KHR_avatar_skeleton_mapping` extension provides a mechanism to map a skeleton rig to a reference rig, enabling retargeting and compatibility across different skeleton topologies. This extension is particularly useful for normalizing diverse rig structures across platforms and authoring tools. It provides one-to-one and one-to-many mapping; with the expectation that distributed weights add up to 1.0. ## Extension Schema @@ -34,9 +35,7 @@ The `KHR_avatar_skeleton_mapping` extension provides a mechanism to map a skelet { "target": "spine", "weight": 0.5 }, { "target": "chest", "weight": 0.5 } ], - "JawJoint": [ - { "target": "jaw", "weight": 1.0 } - ] + "JawJoint": [{ "target": "jaw", "weight": 1.0 }] } } } @@ -45,12 +44,11 @@ The `KHR_avatar_skeleton_mapping` extension provides a mechanism to map a skelet ### Properties -| Property | Type | Description | -|--------------|---------|-----------------------------------------------------------------------------| -| `mappings` | object | Dictionary mapping source joint names to reference rig joint names. | -| `target` | string | Name of the reference joint. | -| `weight` | number | Influence of this target in the mapping. Must sum to 1.0 per source joint. | - +| Property | Type | Description | +| ---------- | ------ | -------------------------------------------------------------------------- | +| `mappings` | object | Dictionary mapping source joint names to reference rig joint names. | +| `target` | string | Name of the reference joint. | +| `weight` | number | Influence of this target in the mapping. Must sum to 1.0 per source joint. | ### Mapping Types @@ -61,7 +59,6 @@ This extension supports both one-to-one and one-to-many mappings: This provides flexibility for approximating intermediate or compound joints across rig topologies. - ## Mapping to Known Standard Rigs In many real-world scenarios, developers must remap an avatar's native joint structure to a **known, standardized rig**—such as a runtime's internal avatar model or a predefined specification like VRM's Humanoid rig. @@ -69,6 +66,7 @@ In many real-world scenarios, developers must remap an avatar's native joint str This extension supports such cases by allowing one-to-one or one-to-many weighted mappings between a model’s joints and those of a **target standard rig**. These standard rigs are typically defined by the consuming platform, runtime, or service provider. Each standard rig: + - Defines a fixed joint name vocabulary and hierarchy. - Is assumed to be known at runtime and used for animation playback, retargeting, IK, or expression control. @@ -87,15 +85,11 @@ Here’s an example mapping from a custom rig into VRM Humanoid: "mappings": [ { "source": "myRig_hips", - "targets": [ - { "joint": "hips", "weight": 1.0 } - ] + "targets": [{ "joint": "hips", "weight": 1.0 }] }, { "source": "myRig_head", - "targets": [ - { "joint": "head", "weight": 1.0 } - ] + "targets": [{ "joint": "head", "weight": 1.0 }] }, { "source": "myRig_leftFoot", @@ -111,6 +105,7 @@ Here’s an example mapping from a custom rig into VRM Humanoid: ``` In this example: + - `"source"` is the custom rig's joint name. - `"joint"` in the `"targets"` is a joint name defined by the target standard rig (here, VRM Humanoid). - The system using this extension must understand what `"vrmHumanoid"` means (i.e., the joint vocabulary and structure must be pre-declared by the consuming runtime). @@ -118,11 +113,11 @@ In this example: ## Mapping Registry and Target Namespaces While this extension does not mandate a central registry, developers are encouraged to: + - Document the name and structure of their standard rigs - Reuse identifiers like `"vrmHumanoid"`, `"unityHumanoid"`, or `"metaRig"` consistently - Provide a public schema or joint list for validation and interoperability - ## Implementation Notes - Joint names are assumed to refer to nodes in the `nodes` array. @@ -133,9 +128,7 @@ While this extension does not mandate a central registry, developers are encoura ```json { - "extensionsUsed": [ - "KHR_avatar_skeleton_mapping" - ], + "extensionsUsed": ["KHR_avatar_skeleton_mapping"], "extensions": { "KHR_avatar_skeleton_mapping": { "mappings": { diff --git a/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md b/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md index 01d92b4d62..69d2c466b8 100644 --- a/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md @@ -8,6 +8,7 @@ - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. - Leonard Daly, Individual Contributor +- Nick Burkard, Meta ## Status @@ -15,12 +16,12 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Dependent on: `KHR_avatar` - + ## Overview -The `KHR_avatar_virtual_joints` extension introduces *virtual joints*—custom transform nodes that exist relative to the avatar’s skeletal hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. +The `KHR_avatar_virtual_joints` extension introduces _virtual joints_—custom transform nodes that exist relative to the avatar’s skeletal hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. Virtual joints are defined via an offset transform relative to a single parent joint, and do **not** participate in skinning. They are evaluated at runtime for behavior logic and procedural animation. @@ -67,34 +68,34 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t ### Properties -| Property | Type | Description | -|----------------|-----------|-----------------------------------------------------------------------------| -| `name` | string | Semantic identifier of the virtual joint | -| `parentJoint` | integer | Index into the glTF `nodes[]` array representing the base joint | -| `translation` | float[3] | Local offset (X, Y, Z) relative to the parent joint | -| `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent joint | +| Property | Type | Description | +| ------------- | -------- | ------------------------------------------------------------------------- | +| `name` | string | Semantic identifier of the virtual joint | +| `parentJoint` | integer | Index into the glTF `nodes[]` array representing the base joint | +| `translation` | float[3] | Local offset (X, Y, Z) relative to the parent joint | +| `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent joint | ## Examples ### Arm Attachment Virtual Joint -- **Name**: `"arm_socket"` -- **Parent**: Between elbow and wrist (e.g., joint index 18) -- **Offset**: `(0.0, 0.1, 0.0)` -- **Usage**: Anchor for attaching objects +- **Name**: `"arm_socket"` +- **Parent**: Between elbow and wrist (e.g., joint index 18) +- **Offset**: `(0.0, 0.1, 0.0)` +- **Usage**: Anchor for attaching objects ### Look At Virtual Joint -- **Name**: `"lookAt_target"` -- **Parent**: `"head"` joint (e.g., joint index 8) -- **Offset**: `(0.0, 0.0, 0.35)` +- **Name**: `"lookAt_target"` +- **Parent**: `"head"` joint (e.g., joint index 8) +- **Offset**: `(0.0, 0.0, 0.35)` - **Usage**: Target for runtime look-at behavior (eyes/head alignment). ### Sitting Point Virtual Joint -- **Name**: `"sitting_point"` -- **Parent**: `"pelvis"` joint (e.g., joint index 0) -- **Offset**: `(0.0, 0.0, -0.2)` +- **Name**: `"sitting_point"` +- **Parent**: `"pelvis"` joint (e.g., joint index 0) +- **Offset**: `(0.0, 0.0, -0.2)` - **Usage**: Anchor point for aligning seated positions. ## Implementation Notes From de2169f89787064bc316d0b8c7e7c78ed1903488 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 28 Jul 2025 21:58:19 -0700 Subject: [PATCH 04/48] Update README.md --- extensions/2.0/Khronos/KHR_avatar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/2.0/Khronos/KHR_avatar/README.md b/extensions/2.0/Khronos/KHR_avatar/README.md index c59c6f2366..e713e16fb0 100644 --- a/extensions/2.0/Khronos/KHR_avatar/README.md +++ b/extensions/2.0/Khronos/KHR_avatar/README.md @@ -48,7 +48,7 @@ The extension supports referencing the source `scene` that represents the avatar |--------------|---------|-----------------------------------------------------------------------------| | `sceneIndex` | integer | Index of the glTF `scene` representing the avatar. Used to distinguish the avatar root when multiple scenes exist. | -## Metadata Attachment: JSON_XMP_LD +## Metadata Attachment: KHR_xmp_json_ld Avatar metadata should be expressed using the `KHR_xmp_json_ld` format, a structured mechanism for attaching JSON-LD metadata blocks to glTF files. In the context of `KHR_avatar`, this allows consistent expression of avatar provenance, licensing, creator, versioning, and intended use, among others. From de03ddbeaf31a5c6832bb33357dd266f9618244d Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 28 Jul 2025 22:34:35 -0700 Subject: [PATCH 05/48] Update README.md --- extensions/2.0/Khronos/KHR_avatar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/2.0/Khronos/KHR_avatar/README.md b/extensions/2.0/Khronos/KHR_avatar/README.md index e713e16fb0..5a7408345c 100644 --- a/extensions/2.0/Khronos/KHR_avatar/README.md +++ b/extensions/2.0/Khronos/KHR_avatar/README.md @@ -138,7 +138,7 @@ The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as par ## Implementation Notes -- `sceneIndex` is required and represennts the index of the glTF `scene` representing the avatar. Used to distinguish the avatar root when multiple scenes exist. +- `sceneIndex` is required is the index of the glTF `scene` corresponding to the avatar. Used to distinguish the avatar root when multiple scenes exist. - Consumers should use this marker as a signal to search for additional avatar-related extensions, including skeletal, expression, and other khronos avatar extensions. - Support for `KHR_xmp_json_ld` is encouraged to ensure interoperable metadata across tools and runtimes. From 4a1f58a84aa5f9934b749779b89678727d3d2a5c Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 28 Jul 2025 22:37:49 -0700 Subject: [PATCH 06/48] Grammar am bad Frankly, I've been out of practice with git for far too long, and have forgotten that git commits for a PR are more...eternal than my current active workflow. --- extensions/2.0/Khronos/KHR_avatar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/2.0/Khronos/KHR_avatar/README.md b/extensions/2.0/Khronos/KHR_avatar/README.md index 5a7408345c..1f8db3ec50 100644 --- a/extensions/2.0/Khronos/KHR_avatar/README.md +++ b/extensions/2.0/Khronos/KHR_avatar/README.md @@ -138,7 +138,7 @@ The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as par ## Implementation Notes -- `sceneIndex` is required is the index of the glTF `scene` corresponding to the avatar. Used to distinguish the avatar root when multiple scenes exist. +- `sceneIndex` is required, representing the index of the glTF `scene` corresponding to the avatar. Used to distinguish the avatar root when multiple scenes exist. - Consumers should use this marker as a signal to search for additional avatar-related extensions, including skeletal, expression, and other khronos avatar extensions. - Support for `KHR_xmp_json_ld` is encouraged to ensure interoperable metadata across tools and runtimes. From 685b1c3cad5535f2c120d4b28e4e364b557c393e Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 30 Jul 2025 12:06:29 -0700 Subject: [PATCH 07/48] Updated KHR_avatar_skeleton_biped readme to be more prescriptive --- extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md index 4e78bdd2da..913ae360a9 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md @@ -111,7 +111,7 @@ This enables runtime engines to extract semantic meaning from joint hierarchies ## Skeletal Mapping Support -Rather than define mapping logic directly in this extension, developers should use the standalone [`KHR_avatar_skeleton_mapping`](./KHR_avatar_skeleton_mapping_README.md) extension for any one-to-one or one-to-many joint remapping between different rig topologies. +Rather than define mapping logic directly in this extension, developers should use the [`KHR_avatar_skeleton_mapping`](./KHR_avatar_skeleton_mapping_README.md) extension in conjunction with this one for any one-to-one or one-to-many joint remapping between different rig topologies. That extension supports weighted joint translation and enables cleaner separation between semantic labeling (this extension) and rig interoperability (mapping). From 5effdee59142b53d86c0ea306537eb5db07c3c19 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Fri, 8 Aug 2025 21:42:35 -0700 Subject: [PATCH 08/48] Update the expressions extension descriptions to be more descriptive Defining more explicitly what we intend when we write "expression" (in regards to these extensions being for face-associated motions) --- .../KHR_avatar_expression_mapping/README.md | 14 ++++++++------ .../KHR_avatar_expression_morphtarget/README.md | 16 +++++++++------- .../KHR_avatar_expression_procedural/README.md | 7 +++++-- .../KHR_avatar_expression_texture/README.md | 14 ++++++++------ 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md index 4d8d8bed38..aea5ecb519 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md @@ -24,14 +24,16 @@ Can be used alongside: `KHR_avatar_expression_morphtargets` or other expression ## Reference Expression Categories/Vocabularies -Expression names may be grouped into categories including: +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. -- **Emotions** (e.g. `happy`, `angry`, `surprised`) -- **Visemes** (e.g. `aa`, `oo`, `th`) -- **Modifiers** (e.g. `left`, `right`, `upper`, `lower`) -- **Gestures and Actions** (e.g. `blink`, `smile`, `jawOpen`) +For examples of relevant types of expressions, you can reference concepts such as: -The `KHR_avatar_expression_mapping` extension provides a general-purpose mechanism for mapping expression names used in an avatar to a known expression vocabulary. This allows different authoring pipelines or runtimes to translate between heterogeneous expression sets. +- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) +- **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) +- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) +- **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) + +Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). ## Extension Schema diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md index b144058064..dd981379e1 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md @@ -25,16 +25,18 @@ The `KHR_avatar_expression_morphtarget` extension provides semantic bindings bet This extension does **not** define animation data itself. Instead, it enables consistent reference of morph target indices across tools, runtimes, and expressions. -## Reference Expression Vocabulary +## Reference Expression Categories/Vocabularies -Potential expression categories include: +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. -- **Emotions** (e.g., `happy`, `angry`, `surprised`) -- **Visemes** (e.g., `aa`, `oo`, `th`) -- **Modifiers** (e.g., `left`, `right`, `upper`, `lower`) -- **Gestures and Actions** (e.g., `blink`, `smile`, `jawOpen`) +For examples of relevant types of expressions, you can reference concepts such as: -Optionally, these may be aligned with industry standards, such as the [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). +- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) +- **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) +- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) +- **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) + +Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). ## Extension Schema diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md index 4b808501c2..7d7ed4e9ef 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md @@ -30,6 +30,8 @@ The `KHR_avatar_expression_procedural` extension introduces a metadata layer tha - **Microexpressions** - **Randomized twitches or gestures** +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. + By labeling expressions as procedural, this extension enables runtime systems (e.g., animation controllers, live-tracking systems, or AI avatars) to drive those expressions without conflict with animation data or user inputs. This metadata is **descriptive only**: it does not contain animation or behavior logic itself. Instead, it signals to tools and engines that the following expressions are _expected to be dynamically generated_. @@ -39,7 +41,6 @@ This metadata is **descriptive only**: it does not contain animation or behavior - Define which expressions are not statically animated but generated procedurally - Avoid conflict between procedural and baked expression systems - Inform rig exporters or runtime systems which expressions are reserved for real-time generation -- Enable consistent behavior across platforms ## Schema @@ -67,11 +68,13 @@ This metadata is **descriptive only**: it does not contain animation or behavior | Property | Type | Description | | ----------------------- | ------ | --------------------------------------------------------------------------------------- | | `proceduralExpressions` | array | List of expression metadata entries that are intended to be procedurally controlled | -| `expression` | string | Expression name as defined in the expression mapping vocabulary | +| `expression` | string | Corresponding expression name | | `mode` | string | Enum: `"timed"`, `"random"`, `"live"`, `"scripted"` — describes the procedural strategy | ## Procedural Modes +TODO: Need to discuss the items below; there is concern around these particular fields and assertions that end applications should decide how to control these + | Mode | Meaning | | ---------- | ------------------------------------------------------------------------------ | | `timed` | The expression occurs in regular intervals (e.g., blinking every 5s) | diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md index 4988ae1954..6c75156c38 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md @@ -29,14 +29,16 @@ The `KHR_avatar_expression_texture` extension enables expression-level control u ## Reference Expression Vocabulary -Expressions may be categorized as: +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. -- **Emotions** (e.g. `happy`, `angry`, `surprised`) -- **Visemes** (e.g. `aa`, `oo`, `th`) -- **Modifiers** (e.g. `left`, `right`, `upper`, `lower`) -- **Gestures and Actions** (e.g. `blink`, `smile`, `jawOpen`) +For examples of relevant types of expressions, you can reference concepts such as: -Optionally, these may be aligned with industry standards, such as [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). +- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) +- **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) +- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) +- **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) + +Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). ## Extension Schema From 22b69b9b6949dea196f62a0c48e48d03c4c69796 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 20 Aug 2025 20:34:18 -0700 Subject: [PATCH 09/48] Updating the mapping extensions Updating the mapping extensions to enable multiple rig/skeleton and expression set maps in an instance of the extension (given it's a top-level extension). There were also some contradictions in these; which I cleaned up and tried to address. These will be touched up once we make the switch to the KHR_character base --- .../KHR_avatar_expression_mapping/README.md | 29 +++++-- .../KHR_avatar_skeleton_mapping/README.md | 83 ++++++++----------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md index aea5ecb519..46b9b8e8fd 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md @@ -22,15 +22,17 @@ Can be used alongside: `KHR_avatar_expression_morphtargets` or other expression ## Overview +This extension is intended to enable encoding multiple expression set mappings, mapping expression animations currently present in the model to expressions that a runtime/endpoint understands and can handle. + ## Reference Expression Categories/Vocabularies -Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. For examples of relevant types of expressions, you can reference concepts such as: -- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) +- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) - **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) -- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) +- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) - **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). @@ -41,12 +43,21 @@ Optionally, these expressions may be aligned with industry standards (or an endp { "extensions": { "KHR_avatar_expression_mapping": { - "mappings": { - "smileLeft": [ - { "target": "Smile", "weight": 0.8 }, - { "target": "LeftCheekRaise", "weight": 0.2 } - ], - "jawOpen": [{ "target": "MouthOpen", "weight": 1.0 }] + "expressionSetMappings": { + "example_1": { + "smileLeft": [ + { "target": "Smile", "weight": 0.8 }, + { "target": "LeftCheekRaise", "weight": 0.2 } + ], + "jawOpen": [{ "target": "MouthOpen", "weight": 1.0 }] + }, + "example_2": { + "smileLeft": [ + { "target": "smile_small", "weight": 0.2 }, + { "target": "left_dimple", "weight": 0.8 } + ], + "jawOpen": [{ "target": "mouth_open", "weight": 1.0 }] + } } } } diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md index 68ccf3a042..c92483daba 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md @@ -24,53 +24,7 @@ Typically used in conjunction with: `KHR_avatar_skeleton_biped` The `KHR_avatar_skeleton_mapping` extension provides a mechanism to map a skeleton rig to a reference rig, enabling retargeting and compatibility across different skeleton topologies. This extension is particularly useful for normalizing diverse rig structures across platforms and authoring tools. It provides one-to-one and one-to-many mapping; with the expectation that distributed weights add up to 1.0. -## Extension Schema - -```json -{ - "extensions": { - "KHR_avatar_skeleton_mapping": { - "mappings": { - "Spine1": [ - { "target": "spine", "weight": 0.5 }, - { "target": "chest", "weight": 0.5 } - ], - "JawJoint": [{ "target": "jaw", "weight": 1.0 }] - } - } - } -} -``` - -### Properties - -| Property | Type | Description | -| ---------- | ------ | -------------------------------------------------------------------------- | -| `mappings` | object | Dictionary mapping source joint names to reference rig joint names. | -| `target` | string | Name of the reference joint. | -| `weight` | number | Influence of this target in the mapping. Must sum to 1.0 per source joint. | - -### Mapping Types - -This extension supports both one-to-one and one-to-many mappings: - -- **One-to-one**: A source joint maps directly to a single reference joint with a weight of 1.0. -- **One-to-many**: A source joint influences multiple reference joints, each with a fractional weight (all weights must sum to 1.0). - -This provides flexibility for approximating intermediate or compound joints across rig topologies. - -## Mapping to Known Standard Rigs - -In many real-world scenarios, developers must remap an avatar's native joint structure to a **known, standardized rig**—such as a runtime's internal avatar model or a predefined specification like VRM's Humanoid rig. - -This extension supports such cases by allowing one-to-one or one-to-many weighted mappings between a model’s joints and those of a **target standard rig**. - -These standard rigs are typically defined by the consuming platform, runtime, or service provider. Each standard rig: - -- Defines a fixed joint name vocabulary and hierarchy. -- Is assumed to be known at runtime and used for animation playback, retargeting, IK, or expression control. - -### Example: Mapping to VRM Humanoid +### Extension Schema/Example: Mapping to VRM Humanoid The [VRM 1.0 Humanoid specification](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/humanoid.md) defines a standardized set of joints used across VRM-compatible platforms. @@ -78,6 +32,7 @@ Here’s an example mapping from a custom rig into VRM Humanoid: ```json { + "extensionsUsed": ["KHR_avatar_skeleton_mapping"], "extensions": { "KHR_avatar_skeleton_mapping": { "source": "localRig", @@ -110,6 +65,40 @@ In this example: - `"joint"` in the `"targets"` is a joint name defined by the target standard rig (here, VRM Humanoid). - The system using this extension must understand what `"vrmHumanoid"` means (i.e., the joint vocabulary and structure must be pre-declared by the consuming runtime). +### Breakdown and Lower-Level Properties + +The structure of the data contained in the extension can be described as a dictionary of dictionaries: + +Target Skeleton/Rig Name : Joint Mapping Dictionary + Joint Name : List/Array of objects containing the below properties + +| Property | Type | Description | +| ---------- | ------ | ------------------------------------------------------------------ | +| `target` | string | Name of the joint in the target vocabulary. | +| `weight` | number | Influence of this target. Must sum to 1.0 per joint key. | + +### Mapping Types + +This extension supports both one-to-one and one-to-many mappings (as well as multiple instances of those mapping sets): + +- **One-to-one**: A source joint maps directly to a single reference joint with a weight of 1.0. +- **One-to-many**: A source joint influences multiple reference joints, each with a fractional weight (all weights must sum to 1.0). + +This provides flexibility for approximating intermediate or compound joints across rig topologies. + +## Mapping to Known Standard Rigs + +In many real-world scenarios, developers must remap an avatar's native joint structure to a **known, standardized rig**—such as a runtime's internal avatar model or a predefined specification like VRM's Humanoid rig. + +This extension supports such cases by allowing one-to-one or one-to-many weighted mappings between a model’s joints and those of a **target standard rig**. + +These standard rigs are typically defined by the consuming platform, runtime, or service provider. Each standard rig: + +- Defines a fixed joint name vocabulary and hierarchy. +- Is assumed to be known at runtime and used for animation playback, retargeting, IK, or expression control. + + + ## Mapping Registry and Target Namespaces While this extension does not mandate a central registry, developers are encouraged to: From f89a0e37e38d48cc3ec03bf2ddda055b0629972c Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 20 Aug 2025 20:36:38 -0700 Subject: [PATCH 10/48] Addressing minor self-nit --- .../KHR_avatar_skeleton_mapping/README.md | 89 +++++++------------ 1 file changed, 33 insertions(+), 56 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md index c92483daba..18b2872665 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md @@ -24,6 +24,17 @@ Typically used in conjunction with: `KHR_avatar_skeleton_biped` The `KHR_avatar_skeleton_mapping` extension provides a mechanism to map a skeleton rig to a reference rig, enabling retargeting and compatibility across different skeleton topologies. This extension is particularly useful for normalizing diverse rig structures across platforms and authoring tools. It provides one-to-one and one-to-many mapping; with the expectation that distributed weights add up to 1.0. +## Mapping to Known Standard Rigs + +In many real-world scenarios, developers must remap an avatar's native joint structure to a **known, standardized rig**—such as a runtime's internal avatar model or a predefined specification like VRM's Humanoid rig. + +This extension supports such cases by allowing one-to-one or one-to-many weighted mappings between a model’s joints and those of a **target standard rig**. + +These standard rigs are typically defined by the consuming platform, runtime, or service provider. Each standard rig: + +- Defines a fixed joint name vocabulary and hierarchy. +- Is assumed to be known at runtime and used for animation playback, retargeting, or IK purposes. + ### Extension Schema/Example: Mapping to VRM Humanoid The [VRM 1.0 Humanoid specification](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/humanoid.md) defines a standardized set of joints used across VRM-compatible platforms. @@ -35,25 +46,24 @@ Here’s an example mapping from a custom rig into VRM Humanoid: "extensionsUsed": ["KHR_avatar_skeleton_mapping"], "extensions": { "KHR_avatar_skeleton_mapping": { - "source": "localRig", - "target": "vrmHumanoid", - "mappings": [ - { - "source": "myRig_hips", - "targets": [{ "joint": "hips", "weight": 1.0 }] - }, - { - "source": "myRig_head", - "targets": [{ "joint": "head", "weight": 1.0 }] + "skeletalRigMappings": { + "vrmHumanoid": { + "myRig_hips": [{ "target": "hips", "weight": 1.0 }], + "myRig_head": [{ "target": "head", "weight": 1.0 }], + "myRig_leftFoot": [ + { "target": "leftFoot", "weight": 0.8 }, + { "target": "leftToeBase", "weight": 0.2 } + ] }, - { - "source": "myRig_leftFoot", - "targets": [ - { "joint": "leftFoot", "weight": 0.8 }, - { "joint": "leftToeBase", "weight": 0.2 } + "example_rig": { + "myRig_hips": [{ "target": "hip_bone", "weight": 1.0 }], + "myRig_head": [{ "target": "head_bone", "weight": 1.0 }], + "myRig_leftFoot": [ + { "target": "l_foot_bone", "weight": 0.8 }, + { "target": "l_toe_bone", "weight": 0.2 } ] } - ] + } } } } @@ -61,21 +71,19 @@ Here’s an example mapping from a custom rig into VRM Humanoid: In this example: -- `"source"` is the custom rig's joint name. -- `"joint"` in the `"targets"` is a joint name defined by the target standard rig (here, VRM Humanoid). -- The system using this extension must understand what `"vrmHumanoid"` means (i.e., the joint vocabulary and structure must be pre-declared by the consuming runtime). +- `"target"` is a joint name defined by the target standard rig (here, VRM Humanoid, or a hypotheical example_rig system). +- The system using this extension may understand what `"vrmHumanoid"` or `"example_rig"` means (i.e., the joint vocabulary and structure must be pre-declared by the consuming runtime); and if so can leverage the provided joint mappings ### Breakdown and Lower-Level Properties The structure of the data contained in the extension can be described as a dictionary of dictionaries: -Target Skeleton/Rig Name : Joint Mapping Dictionary - Joint Name : List/Array of objects containing the below properties +Target Skeleton/Rig Name : Joint Mapping Dictionary (Joint Name : List/Array of objects containing the below properties) -| Property | Type | Description | -| ---------- | ------ | ------------------------------------------------------------------ | -| `target` | string | Name of the joint in the target vocabulary. | -| `weight` | number | Influence of this target. Must sum to 1.0 per joint key. | +| Property | Type | Description | +| -------- | ------ | -------------------------------------------------------- | +| `target` | string | Name of the joint in the target vocabulary. | +| `weight` | number | Influence of this target. Must sum to 1.0 per joint key. | ### Mapping Types @@ -86,19 +94,6 @@ This extension supports both one-to-one and one-to-many mappings (as well as mul This provides flexibility for approximating intermediate or compound joints across rig topologies. -## Mapping to Known Standard Rigs - -In many real-world scenarios, developers must remap an avatar's native joint structure to a **known, standardized rig**—such as a runtime's internal avatar model or a predefined specification like VRM's Humanoid rig. - -This extension supports such cases by allowing one-to-one or one-to-many weighted mappings between a model’s joints and those of a **target standard rig**. - -These standard rigs are typically defined by the consuming platform, runtime, or service provider. Each standard rig: - -- Defines a fixed joint name vocabulary and hierarchy. -- Is assumed to be known at runtime and used for animation playback, retargeting, IK, or expression control. - - - ## Mapping Registry and Target Namespaces While this extension does not mandate a central registry, developers are encouraged to: @@ -113,24 +108,6 @@ While this extension does not mandate a central registry, developers are encoura - The reference rig vocabulary may be shared across engines or projects. - This extension does not modify skinning behavior, but informs tooling and runtime animation retargeting. -## Example - -```json -{ - "extensionsUsed": ["KHR_avatar_skeleton_mapping"], - "extensions": { - "KHR_avatar_skeleton_mapping": { - "mappings": { - "Spine1": [ - { "target": "spine", "weight": 0.5 }, - { "target": "chest", "weight": 0.5 } - ] - } - } - } -} -``` - ## License This extension specification is licensed under the Khronos Group Extension License. From a520102bca6d194888d7447ba11563f11a7b81c6 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 12:55:20 -0700 Subject: [PATCH 11/48] Changing namespaces to KHR_character and KHR_character_avatar --- .../2.0/Khronos/KHR_character/README.md | 150 ++++++++++++++++++ .../README.md | 20 +-- .../README.md | 26 +-- .../KHR_character_expression_joint/README.md | 104 ++++++++++++ .../README.md | 51 +++--- .../README.md | 21 +-- .../README.md | 20 +-- .../README.md | 20 +-- .../README.md | 46 +++--- .../README.md | 34 ++-- .../README.md | 14 +- .../README.md | 8 +- 12 files changed, 374 insertions(+), 140 deletions(-) create mode 100644 extensions/2.0/Khronos/KHR_character/README.md rename extensions/2.0/Khronos/{KHR_avatar => KHR_character_avatar}/README.md (86%) rename extensions/2.0/Khronos/{KHR_avatar_expression_joint => KHR_character_expression}/README.md (65%) create mode 100644 extensions/2.0/Khronos/KHR_character_expression_joint/README.md rename extensions/2.0/Khronos/{KHR_avatar_expression_mapping => KHR_character_expression_mapping}/README.md (71%) rename extensions/2.0/Khronos/{KHR_avatar_expression_morphtarget => KHR_character_expression_morphtarget}/README.md (85%) rename extensions/2.0/Khronos/{KHR_avatar_expression_procedural => KHR_character_expression_procedural}/README.md (86%) rename extensions/2.0/Khronos/{KHR_avatar_expression_texture => KHR_character_expression_texture}/README.md (91%) rename extensions/2.0/Khronos/{KHR_avatar_skeleton_bindpose => KHR_character_skeleton_bindpose}/README.md (57%) rename extensions/2.0/Khronos/{KHR_avatar_skeleton_biped => KHR_character_skeleton_biped}/README.md (67%) rename extensions/2.0/Khronos/{KHR_avatar_skeleton_mapping => KHR_character_skeleton_mapping}/README.md (82%) rename extensions/2.0/Khronos/{KHR_avatar_virtual_joints => KHR_character_virtual_joints}/README.md (87%) diff --git a/extensions/2.0/Khronos/KHR_character/README.md b/extensions/2.0/Khronos/KHR_character/README.md new file mode 100644 index 0000000000..5fe25b9db8 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character/README.md @@ -0,0 +1,150 @@ +# KHR_character + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor +- Nick Burkard, Meta + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. + +Dependencies: `KHR_xmp_json_ld` +This extension also leverages the `KHR_xmp_json_ld` pattern for attaching extensible metadata as JSON-LD blocks within glTF assets. For background on this approach, see: +[KHR_xmp_json_ld](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_xmp_json_ld) + +## Overview + +The `KHR_character` extension designates a glTF asset as representing an character. This top-level marker enables tools and runtimes to interpret the asset as containing character-specific content such as rigging, blendshapes, animation retargeting, or metadata. + +This extension does not define character features directly but acts as a root declaration that character-related extensions may be present, and that consumers should treat the asset using character-specific logic and pipelines. It's part of the wider set of KHR character extensions that are meant to be building blocks to represent a contract stating functionality and data requirements between a given model and an endpoint. + +The extension supports referencing the source `scene` that represents the character and optionally includes structured metadata through the `KHR_xmp_json_ld` mechanism. + +## Extension Schema + +```json +{ + "extensions": { + "KHR_character": { + "sceneIndex": 0 + } + } +} +``` + +### Properties + +| Property | Type | Description | +| ------------ | ------- | ------------------------------------------------------------------------------------------------------------------------ | +| `sceneIndex` | integer | Index of the glTF `scene` representing the character. Used to distinguish the character root when multiple scenes exist. | + +## Metadata Attachment: KHR_xmp_json_ld + +character metadata should be expressed using the `KHR_xmp_json_ld` format, a structured mechanism for attaching JSON-LD metadata blocks to glTF files. In the context of `KHR_character`, this allows consistent expression of character provenance, licensing, creator, versioning, and intended use, among others. + +The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as part of the defined extension usage. Metadata keys and structures are defined in the shared Khronos character Metadata schema (TBD). + +| DC/XMP_JSON_LD Property | Why | Required | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| dc:title | | Yes | +| dc:creator | | Yes | +| dc:license | | No | +| dc:rights | | No | +| dc:created | Date on which the asset was created | No | +| dc:publisher | Identifies the entity responsible for making the resource available; important for understanding the source and authority of the content. | No | +| dc:description | Context and a summary of the content | No | +| dc:subject | Can potentially be used for content tagging/association | No | +| dc:source | Important for tracing the provenance and ensuring proper attribution. | Yes | +| khr:version | | No | +| khr:thumbnailImage | | No | + +## Example + +```json +{ + "asset": { + "version": "2.0", + "extensions": { + "KHR_xmp_json_ld": { + "packet": 0 + } + } + }, + "scene": 0, + "scenes": [ + { + "nodes": [0] + } + ], + "nodes": [ + { + "name": "characterRoot" + } + ], + "extensionsUsed": ["KHR_character", "KHR_xmp_json_ld"], + "extensions": { + "KHR_character": { + "sceneIndex": 0 + }, + + "KHR_xmp_json_ld": { + "packets": [ + { + "@context": { + "dc": "http://purl.org/dc/elements/1.1/", + "vrm": "https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/meta.md" + }, + "dc:title": "Example Model", + "dc:creator": { + "@list": [ + "Author1", + "AuthorEmail1@email.com", + "Author2", + "AuthorEmail2@email.com" + ] + }, + "dc:license": { + "@list": [ + "https://vrm.dev/licenses/1.0/", + "https://example.com/third-party-license" + ] + }, + "dc:created": "2023-05-05", + "dc:rights": "Copyright information about the model", + "dc:publisher": "Imaginary Corporation A, LLC", + "dc:description": "A sentence, or paragraph describing the character at hand", + "dc:subject": { + "@list": ["Example trait", "Another example trait"] + }, + "dc:source": "imaginaryCompany.com/characterl", + "khr:version": "1.0", + "khr:thumbnailImage": 0 + } + ] + } + } +} +``` + +## Implementation Notes + +- `sceneIndex` is required, representing the index of the glTF `scene` corresponding to the character. Used to distinguish the character root when multiple scenes exist. +- Consumers should use this marker as a signal to search for additional character-related extensions, including skeletal, expression, and other khronos character extensions. +- Support for `KHR_xmp_json_ld` is encouraged to ensure interoperable metadata across tools and runtimes. + +## Known Implementations + +## License + +This extension specification is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar/README.md b/extensions/2.0/Khronos/KHR_character_avatar/README.md similarity index 86% rename from extensions/2.0/Khronos/KHR_avatar/README.md rename to extensions/2.0/Khronos/KHR_character_avatar/README.md index 1f8db3ec50..3c0b35b3bf 100644 --- a/extensions/2.0/Khronos/KHR_avatar/README.md +++ b/extensions/2.0/Khronos/KHR_character_avatar/README.md @@ -1,4 +1,4 @@ -# KHR_avatar +# KHR_character_avatar ## Contributors @@ -18,16 +18,18 @@ Written against the glTF 2.0 specification. -Dependencies: `KHR_xmp_json_ld` +Dependencies: `KHR_xmp_json_ld`, `KHR_character` This extension also leverages the `KHR_xmp_json_ld` pattern for attaching extensible metadata as JSON-LD blocks within glTF assets. For background on this approach, see: [KHR_xmp_json_ld](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_xmp_json_ld) ## Overview -The `KHR_avatar` extension designates a glTF asset as representing an avatar. This top-level marker enables tools and runtimes to interpret the asset as containing avatar-specific content such as rigging, blendshapes, animation retargeting, or metadata. +The `KHR_character_avatar` extension designates a glTF asset as representing an avatar. This top-level marker enables tools and runtimes to interpret the asset as containing avatar-specific content such as rigging, blendshapes, animation retargeting, or metadata. This extension does not define avatar features directly but acts as a root declaration that avatar-related extensions may be present, and that consumers should treat the asset using avatar-specific logic and pipelines. It's part of the wider set of KHR avatar extensions that are meant to be building blocks to represent a contract stating functionality and data requirements between a given model and an endpoint. +This extension is dependent on the KHR_character extension; which defines related functionality pertaining to more generalized characters. + The extension supports referencing the source `scene` that represents the avatar and optionally includes structured metadata through the `KHR_xmp_json_ld` mechanism. ## Extension Schema @@ -35,7 +37,7 @@ The extension supports referencing the source `scene` that represents the avatar ```json { "extensions": { - "KHR_avatar": { + "KHR_character_avatar": { "sceneIndex": 0 } } @@ -44,13 +46,13 @@ The extension supports referencing the source `scene` that represents the avatar ### Properties -| Property | Type | Description | -|--------------|---------|-----------------------------------------------------------------------------| +| Property | Type | Description | +| ------------ | ------- | ------------------------------------------------------------------------------------------------------------------ | | `sceneIndex` | integer | Index of the glTF `scene` representing the avatar. Used to distinguish the avatar root when multiple scenes exist. | ## Metadata Attachment: KHR_xmp_json_ld -Avatar metadata should be expressed using the `KHR_xmp_json_ld` format, a structured mechanism for attaching JSON-LD metadata blocks to glTF files. In the context of `KHR_avatar`, this allows consistent expression of avatar provenance, licensing, creator, versioning, and intended use, among others. +Avatar metadata should be expressed using the `KHR_xmp_json_ld` format, a structured mechanism for attaching JSON-LD metadata blocks to glTF files. In the context of `KHR_character_avatar`, this allows consistent expression of avatar provenance, licensing, creator, versioning, and intended use, among others. The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as part of the defined extension usage. Metadata keys and structures are defined in the shared Khronos Avatar Metadata schema (TBD). @@ -91,9 +93,9 @@ The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as par "name": "AvatarRoot" } ], - "extensionsUsed": ["KHR_avatar", "KHR_xmp_json_ld"], + "extensionsUsed": ["KHR_character_avatar", "KHR_xmp_json_ld"], "extensions": { - "KHR_avatar": { + "KHR_character_avatar": { "sceneIndex": 0 }, diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md b/extensions/2.0/Khronos/KHR_character_expression/README.md similarity index 65% rename from extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md rename to extensions/2.0/Khronos/KHR_character_expression/README.md index 7ad10880d4..ea5c72328e 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_joint/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression/README.md @@ -1,4 +1,4 @@ -# KHR_avatar_expression_joint +# KHR_character_expression_joint ## Contributors @@ -17,32 +17,34 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar` -Typically used in conjunction with: `KHR_avatar_expression_mapping` +Dependent on: `KHR_character` +Typically used in conjunction with: `KHR_character_expression_mapping` ## Overview -The `KHR_avatar_expression_joint` extension provides a semantic mapping between facial expressions and joint transformations in the glTF node hierarchy. It enables tools and runtimes to associate expressions like `blink`, `smile`, or `jawOpen` with specific nodes whose transforms are animated using standard glTF animation channels. +The `KHR_character_expression_joint` extension provides a semantic mapping between facial expression names and joint-based animations. It enables tools and runtimes to associate expressions like `blink`, `smile`, or `jawOpen` with specific nodes whose transforms are animated using standard glTF animation channels. This extension is purely descriptive: it does not define or store animation data itself. ## Reference Expression Categories/Vocabularies -Expression types include: +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. -- **Emotions** (e.g. `happy`, `angry`, `surprised`) -- **Visemes** (e.g. `aa`, `oo`, `th`) -- **Modifiers** (e.g. `left`, `right`, `upper`, `lower`) -- **Gestures and Actions** (e.g. `blink`, `smile`, `jawOpen`) +For examples of relevant types of expressions, you can reference concepts such as: -Optionally, these may be aligned with industry standards, such as [Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System). +- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) +- **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) +- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) +- **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) + +Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). ## Extension Schema ```json { "extensions": { - "KHR_avatar_expression_joint": { + "KHR_character_expression_joint": { "expressions": [ { "expression": "smile", @@ -82,7 +84,7 @@ Each animation channel used to drive an expression should operate within a **nor The transformation values themselves (e.g., degree of rotation or distance of translation) should scale proportionally with the normalized input range. -This approach simplifies avatar implementation by centralizing expression playback in the glTF animation system and unifying runtime logic for blending and prioritization. +This approach simplifies character implementation by centralizing expression playback in the glTF animation system and unifying runtime logic for blending and prioritization. ### Recommended Interpolation for Binary Expressions diff --git a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md new file mode 100644 index 0000000000..fa0a7a32b3 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md @@ -0,0 +1,104 @@ +# KHR_character_expression_joint + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor +- Nick Burkard, Meta + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Dependent on: `KHR_character`,`KHR_character_expression` +Typically used in conjunction with: `KHR_character_expression_mapping` + +## Overview + +The `KHR_character_expression_joint` extension provides a semantic mapping between facial expression names and joint-based animations. It enables tools and runtimes to associate expressions like `blink`, `smile`, or `jawOpen` with specific nodes whose transforms are animated using standard glTF animation channels. + +This extension is purely descriptive: it does not define or store animation data itself. + +## Reference Expression Categories/Vocabularies + +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. + +For examples of relevant types of expressions, you can reference concepts such as: + +- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) +- **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) +- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) +- **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) + +Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). + +## Extension Schema + +```json +{ + "extensions": { + "KHR_character_expression_joint": { + "expressions": [ + { + "expression": "smile", + "animation": 0, + "channels": [0, 1, 2] + }, + { + "expression": "frown", + "animation": 1, + "channels": [0, 1] + } + ] + } + } +} +``` + +### Properties + +| Property | Type | Description | +| ------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| `expressions` | array | Array of mappings between animation/channels and expression labels. | +| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | +| `expression` | string | Expression name this joint contributes to. | +| `channels` | array | array representing channels that must correspond to either `"rotation"`, `"translation"`, or `"scale"`; indicates transform types. | + +## Animation Integration + +- Expression timing, blending, and control must use glTF `animations` channels. +- Animations targeting expression-driven `rotation`, `translation`, or `scale` must conform to glTF 2.0's animation model. +- This ensures consistency, ease of implementation, and interoperability across runtimes. + +Each animation channel used to drive an expression should operate within a **normalized 0-to-1 range**, where: + +- `0.0` indicates the expression is fully inactive. +- `1.0` indicates the expression is fully active. + +The transformation values themselves (e.g., degree of rotation or distance of translation) should scale proportionally with the normalized input range. + +This approach simplifies character implementation by centralizing expression playback in the glTF animation system and unifying runtime logic for blending and prioritization. + +### Recommended Interpolation for Binary Expressions + +For expressions that represent binary or toggle states (such as `blinkLeft`, `blinkRight`, or `jawOpen`), the use of glTF animation channels with `"interpolation": "STEP"` is strongly recommended. + +STEP interpolation ensures that an expression toggles cleanly between fully off (`0.0`) and fully on (`1.0`) states, providing crisp visual transitions and avoiding interpolation artifacts that could occur with `LINEAR` interpolation in binary scenarios. + +## Implementation Notes + +- Multiple joints may be assigned to the same expression. +- Expression states should be normalized to the [0.0–1.0] range for consistent runtime interpretation. +- This extension does not conflict with standard rigging or skinning systems. + +## License + +This extension is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md similarity index 71% rename from extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md rename to extensions/2.0/Khronos/KHR_character_expression_mapping/README.md index 46b9b8e8fd..e66db768f8 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md @@ -1,4 +1,4 @@ -# KHR_avatar_expression_mapping +# KHR_character_expression_mapping ## Contributors @@ -17,8 +17,8 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar` -Can be used alongside: `KHR_avatar_expression_morphtargets` or other expression sources +Dependent on: `KHR_character`,`KHR_character_expression` +Can be used alongside: `KHR_character_expression_morphtarget`, `KHR_character_expression_joints`, `KHR_character_expression_texture` or other expression sources ## Overview @@ -37,21 +37,22 @@ For examples of relevant types of expressions, you can reference concepts such a Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). -## Extension Schema +## Extension Schema/Example ```json { + "extensionsUsed": ["KHR_character_expression_mapping"], "extensions": { - "KHR_avatar_expression_mapping": { + "KHR_character_expression_mapping": { "expressionSetMappings": { - "example_1": { + "example_set_1": { "smileLeft": [ { "target": "Smile", "weight": 0.8 }, { "target": "LeftCheekRaise", "weight": 0.2 } ], "jawOpen": [{ "target": "MouthOpen", "weight": 1.0 }] }, - "example_2": { + "example_set_2": { "smileLeft": [ { "target": "smile_small", "weight": 0.2 }, { "target": "left_dimple", "weight": 0.8 } @@ -64,17 +65,19 @@ Optionally, these expressions may be aligned with industry standards (or an endp } ``` -### Properties +### Breakdown and Lower-Level Properties -| Property | Type | Description | -| ---------- | ------ | ------------------------------------------------------------------ | -| `mappings` | object | Dictionary mapping expression names to reference vocabulary terms. | -| `target` | string | Name of the expression in the target vocabulary. | -| `weight` | number | Influence of this target. Must sum to 1.0 per expression key. | +The structure of the data contained in the extension can be described as a dictionary of dictionaries: +Target Expression Set Name : Expression Mapping Dictionary (Expression Name : List/Array of objects containing the below properties) + +| Property | Type | Description | +| -------- | ------ | ------------------------------------------------------------- | +| `target` | string | Name of the expression in the target vocabulary. | +| `weight` | number | Influence of this target. Must sum to 1.0 per expression key. | ### Mapping Types -This extension supports both one-to-one and one-to-many mappings: +This extension supports both one-to-one and one-to-many mappings (as well as multiple instances of those mapping sets): - **One-to-one**: An expression maps directly to a single reference vocabulary term with weight 1.0. - **One-to-many**: An expression is composed from multiple reference terms, blended using assigned weights. @@ -84,27 +87,9 @@ This allows developers to bridge between custom expression sets and shared vocab ## Implementation Notes - This extension is typically used at the top level of the glTF file. -- Expression names should match those used in `KHR_avatar_expression_morphtargets`, animation tracks, or tracking pipelines. +- Expression names should match those used in `KHR_character_expression_morphtarget`, `KHR_character_expression_texture`, or `KHR_character_expression_joint`; - Tools can interpret this mapping to apply automatic translation between expression sets. -## Example - -```json -{ - "extensionsUsed": ["KHR_avatar_expression_mapping"], - "extensions": { - "KHR_avatar_expression_mapping": { - "mappings": { - "smileLeft": [ - { "target": "Smile", "weight": 0.8 }, - { "target": "LeftCheekRaise", "weight": 0.2 } - ] - } - } - } -} -``` - ## License This extension specification is licensed under the Khronos Group Extension License. diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md similarity index 85% rename from extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md rename to extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md index dd981379e1..e1f29f83f9 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md @@ -1,4 +1,4 @@ -# KHR_avatar_expression_morphtarget +# KHR_character_expression_morphtarget ## Contributors @@ -17,23 +17,24 @@ ## Dependencies Written against the glTF 2.0 specification. -Used in conjunction with: `KHR_avatar`, `KHR_avatar_expression_mapping` +Dependent on: `KHR_character`,`KHR_character_expression` +Used in conjunction with: `KHR_character_expression_mapping` ## Overview -The `KHR_avatar_expression_morphtarget` extension provides semantic bindings between avatar expressions and specific morph target indices in a glTF mesh. These mappings enable higher-level expression control systems to reference the correct blendshapes when driving facial animation using glTF animation channels. +The `KHR_character_expression_morphtarget` extension provides semantic bindings between character expressions and specific morph target indices in a glTF mesh. These mappings enable higher-level expression control systems to reference the correct blendshapes when driving facial animation using glTF animation channels. This extension does **not** define animation data itself. Instead, it enables consistent reference of morph target indices across tools, runtimes, and expressions. ## Reference Expression Categories/Vocabularies -Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. For examples of relevant types of expressions, you can reference concepts such as: -- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) +- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) - **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) -- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) +- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) - **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). @@ -43,7 +44,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp ```json { "extensions": { - "KHR_avatar_expression_morphtarget": { + "KHR_character_expression_morphtarget": { "expressions": [ { "expression": "smile", @@ -112,7 +113,7 @@ All morph target expressions should be driven using standard glTF animation chan ```json { "extensions": { - "KHR_avatar_expression_morphtarget": { + "KHR_character_expression_morphtarget": { "expressions": [ { "expression": "smile", @@ -171,7 +172,7 @@ The animation should update the relevant morph target weight (in this case index - This extension provides a consistent mapping between expression names and mesh targets, allowing glTF animation data to be expressive-aware. - Multiple morph targets can be bound to the same expression. -- Tools may use this metadata to validate expression sets, retarget avatar blendshape names, or drive runtime animation. +- Tools may use this metadata to validate expression sets, retarget character blendshape names, or drive runtime animation. ### Recommended Interpolation for Binary Expressions @@ -185,7 +186,7 @@ All expression-driven changes defined by this extension should rely on standard - Animations targeting expression-driven `weights` (for morphtargets) - This ensures consistency, ease of implementation, and interoperability across runtimes. -This approach simplifies avatar implementation by centralizing expression playback in the glTF animation system, reducing custom handling and improving cross-platform compatibility. +This approach simplifies character implementation by centralizing expression playback in the glTF animation system, reducing custom handling and improving cross-platform compatibility. ## License diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md similarity index 86% rename from extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md rename to extensions/2.0/Khronos/KHR_character_expression_procedural/README.md index 7d7ed4e9ef..1b5ee16894 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md @@ -1,4 +1,4 @@ -# KHR_avatar_expression_procedural +# KHR_character_expression_procedural ## Contributors @@ -17,12 +17,12 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar` -Works alongside: `KHR_avatar_expression_mapping`, `KHR_avatar_expression_joint`, `KHR_avatar_expression_morphtargets`. +Dependent on: `KHR_character`,`KHR_character_expression` +Works alongside: `KHR_character_expression_mapping`, `KHR_character_expression_joint`, `KHR_character_expression_texture`, `KHR_character_expression_morphtargets`. ## Overview -The `KHR_avatar_expression_procedural` extension introduces a metadata layer that defines which expressions are expected to be procedurally generated or controlled at runtime. This includes expressions such as: +The `KHR_character_expression_procedural` extension introduces a metadata layer that defines which expressions are expected to be procedurally generated or controlled at runtime. This includes expressions such as: - **Timed blinking** - **Eye darting** @@ -30,9 +30,9 @@ The `KHR_avatar_expression_procedural` extension introduces a metadata layer tha - **Microexpressions** - **Randomized twitches or gestures** -Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. -By labeling expressions as procedural, this extension enables runtime systems (e.g., animation controllers, live-tracking systems, or AI avatars) to drive those expressions without conflict with animation data or user inputs. +By labeling expressions as procedural, this extension enables runtime systems (e.g., animation controllers, live-tracking systems, or AI characters) to drive those expressions without conflict with animation data or user inputs. This metadata is **descriptive only**: it does not contain animation or behavior logic itself. Instead, it signals to tools and engines that the following expressions are _expected to be dynamically generated_. @@ -47,7 +47,7 @@ This metadata is **descriptive only**: it does not contain animation or behavior ```json { "extensions": { - "KHR_avatar_expression_procedural": { + "KHR_character_expression_procedural": { "proceduralExpressions": [ { "expression": "blinkLeft", @@ -68,12 +68,12 @@ This metadata is **descriptive only**: it does not contain animation or behavior | Property | Type | Description | | ----------------------- | ------ | --------------------------------------------------------------------------------------- | | `proceduralExpressions` | array | List of expression metadata entries that are intended to be procedurally controlled | -| `expression` | string | Corresponding expression name | +| `expression` | string | Corresponding expression name | | `mode` | string | Enum: `"timed"`, `"random"`, `"live"`, `"scripted"` — describes the procedural strategy | ## Procedural Modes -TODO: Need to discuss the items below; there is concern around these particular fields and assertions that end applications should decide how to control these +TODO: Need to discuss the items below; there is concern around these particular fields and assertions that end applications should decide how to control these | Mode | Meaning | | ---------- | ------------------------------------------------------------------------------ | @@ -113,7 +113,7 @@ This allows developers to distinguish expressions meant to supplement animation - This extension is schema-only and does not contain behavior logic or animation data. - Runtimes may use this to suppress baked animation for procedural targets. -- The expression names should align with the shared vocabulary defined in the `KHR_avatar_expression_mapping`. +- The expression names should align with the shared vocabulary defined in the `KHR_character_expression_mapping`. ## License diff --git a/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md similarity index 91% rename from extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md rename to extensions/2.0/Khronos/KHR_character_expression_texture/README.md index 6c75156c38..163a6d3ef5 100644 --- a/extensions/2.0/Khronos/KHR_avatar_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md @@ -1,4 +1,4 @@ -# KHR_avatar_expression_texture +# KHR_character_expression_texture ## Contributors @@ -17,25 +17,25 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar`,`KHR_animation_pointer` -Can be used alongside: `KHR_avatar_expression_mapping` +Dependent on: `KHR_character`, `KHR_animation_pointer`, `KHR_character_expression` +Can be used alongside: `KHR_character_expression_mapping` ## Overview -The `KHR_avatar_expression_texture` extension enables expression-level control using texture swaps or UV transformations. This approach is beneficial for avatars that represent expressions visually via changes in texture, such as cartoon or anime-style characters. +The `KHR_character_expression_texture` extension enables expression-level control using texture swaps or UV transformations. This approach is beneficial for characters that represent expressions visually via changes in texture, such as cartoon or anime-style characters. - Expression timing, blending, and control must use glTF `animations` channels. - Animations targeting expression-driven texture transforms must adhere strictly to glTF animation standards and khr_animation_pointer semantics. ## Reference Expression Vocabulary -Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. For examples of relevant types of expressions, you can reference concepts such as: -- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) +- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) - **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) -- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) +- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) - **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). @@ -45,7 +45,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp ```json { "extensions": { - "KHR_avatar_expression_texture": { + "KHR_character_expression_texture": { "expressions": [ { "material": 2, @@ -172,7 +172,7 @@ Using STEP interpolation ensures that the expression toggles cleanly between ful ```json { "extensions": { - "KHR_avatar_expression_texture": { + "KHR_character_expression_texture": { "expressions": [ { "material": 2, @@ -254,7 +254,7 @@ Animation of either the texture index or texture transform must be implemented u ### Runtime Behavior - Expression weights should animate between `0.0` (off) and `1.0` (fully active). -- The avatar system uses these animations to blend or toggle texture visuals in accordance with semantic expressions. +- The character system uses these animations to blend or toggle texture visuals in accordance with semantic expressions. ## License diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md similarity index 57% rename from extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md rename to extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md index 7f0682de92..139539ba6c 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_bindpose/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md @@ -1,4 +1,4 @@ -# KHR_avatar_skeleton_bindpose +# KHR_character_skeleton_bindpose ## Contributors @@ -17,31 +17,26 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar` +Dependent on: `KHR_character` ## Overview **THIS EXTENSION IS VERY MUCH WORK IN PROGRESS** -The `KHR_avatar_skeleton_bindpose` extension defines a canonical bind pose for the avatar's skeleton. This pose serves as a neutral reference that supports animation retargeting, mesh deformation validation, and consistency across toolchains. It is particularly useful when the glTF `skins[].inverseBindMatrices` are insufficient or absent for expressing the true skeletal rest position. +The `KHR_character_skeleton_bindpose` extension defines a canonical bind pose for the character's skeleton. This pose serves as a neutral reference that supports animation retargeting, mesh deformation validation, and consistency across toolchains. It is particularly useful when the glTF `skins[].inverseBindMatrices` are insufficient or absent for expressing the true skeletal rest position. ## Extension Schema ```json { "extensions": { - "KHR_avatar_skeleton_bindpose": { + "KHR_character_skeleton_bindpose": { "poseType": "TPose", "skeleton": 0, "jointBindPoses": [ { "joint": 0, - "matrix": [ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ] + "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] } ] } @@ -51,15 +46,15 @@ The `KHR_avatar_skeleton_bindpose` extension defines a canonical bind pose for t ### Properties -| Property | Type | Description | -|------------------|-----------|-----------------------------------------------------------------------------| +| Property | Type | Description | +| -------- | ---- | ----------- | -| `poseType` | string | Enum: `TPose`, `APose`, `Custom`. Declares the avatar’s general pose classification. | -| `skeleton` | integer | Index into glTF `skins[]`; defines the joint set this bind pose applies to. | +| `poseType` | string | Enum: `TPose`, `APose`, `Custom`. Declares the character’s general pose classification. | +| `skeleton` | integer | Index into glTF `skins[]`; defines the joint set this bind pose applies to. | -| `jointBindPoses` | array | List of bind pose matrices, each associated with a joint node index. | -| `joint` | integer | Index of the joint node in the glTF `nodes` array. | -| `matrix` | float[16] | Column-major 4x4 matrix defining the joint’s bind pose in model space. | +| `jointBindPoses` | array | List of bind pose matrices, each associated with a joint node index. | +| `joint` | integer | Index of the joint node in the glTF `nodes` array. | +| `matrix` | float[16] | Column-major 4x4 matrix defining the joint’s bind pose in model space. | ## Relationship to glTF 2.0 Skinning @@ -74,7 +69,7 @@ This extension supplements or overrides that mechanism by defining joint rest po | Value | Description | | -------- | --------------------------------------------------------------------- | | `TPose` | Arms extended horizontally. Common neutral rest pose for retargeting. | -| `APose` | Arms angled downward. Used by some avatar authoring tools. | +| `APose` | Arms angled downward. Used by some character authoring tools. | | `Custom` | Any pose that does not fit T-Pose or A-Pose definitions. | ## Implementation Notes @@ -91,21 +86,16 @@ This extension supplements or overrides that mechanism by defining joint rest po "version": "2.0" }, "extensionsUsed": [ - "KHR_avatar", - "KHR_avatar_skeleton_biped", - "KHR_avatar_skeleton_bindpose" + "KHR_character", + "KHR_character_skeleton_biped", + "KHR_character_skeleton_bindpose" ], "extensions": { - "KHR_avatar_skeleton_bindpose": { + "KHR_character_skeleton_bindpose": { "jointBindPoses": [ { "joint": 0, - "matrix": [ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ] + "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] } ] } diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md similarity index 67% rename from extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md rename to extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md index 913ae360a9..6d395d0173 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_biped/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md @@ -1,4 +1,4 @@ -# KHR_avatar_skeleton_biped +# KHR_character_skeleton_biped ## Contributors @@ -17,22 +17,22 @@ ## Dependencies Written against the glTF 2.0 specification. -Depends on: `KHR_avatar` +Depends on: `KHR_character` ## Overview **THIS EXTENSION IS VERY MUCH WORK IN PROGRESS** -The `KHR_avatar_skeleton_biped` extension enables bipedal avatars. Like with other avatar extensions, its presence represents the data contract that the model itself is a bipedal character model. This extension enables clarifying what joints are for retargeting and compatibility across tools and platforms by specifying a canonical set of joints and their hierarchical structure. +The `KHR_character_skeleton_biped` extension enables bipedal characters. Like with other character extensions, its presence represents the data contract that the model itself is a bipedal character model. This extension enables clarifying what joints are for retargeting and compatibility across tools and platforms by specifying a canonical set of joints and their hierarchical structure. -This extension does not modify the glTF skinning or animation system, but instead annotates the avatar’s node hierarchy to indicate which nodes represent canonical joints in a bipedal skeleton. +This extension does not modify the glTF skinning or animation system, but instead annotates the character’s node hierarchy to indicate which nodes represent canonical joints in a bipedal skeleton. ## Extension Schema Example ```json { "extensions": { - "KHR_avatar_skeleton_biped": { + "KHR_character_skeleton_biped": { "joints": { "hips": 0, "spine": 1, @@ -59,9 +59,9 @@ This extension does not modify the glTF skinning or animation system, but instea ### Properties -| Property | Type | Description | -| -------- | ------ | -------------------------------------------------------------------------- | -| `joints` | object | Mapping from biped joint names to node indices in the glTF file. | +| Property | Type | Description | +| -------- | ------ | ---------------------------------------------------------------- | +| `joints` | object | Mapping from biped joint names to node indices in the glTF file. | Each joint name corresponds to a node present in the glTF node hierarchy. The hierarchy as it exists then informs the skeletal hierarchy for parsing purposes. @@ -81,11 +81,11 @@ Each joint name corresponds to a node present in the glTF node hierarchy. The hi ... ], "extensionsUsed": [ - "KHR_avatar", - "KHR_avatar_skeleton_biped" + "KHR_character", + "KHR_character_skeleton_biped" ], "extensions": { - "KHR_avatar_skeleton_biped": { + "KHR_character_skeleton_biped": { "joints": { "hips": 0, "spine": 1, @@ -100,18 +100,18 @@ Each joint name corresponds to a node present in the glTF node hierarchy. The hi ## Relationship to glTF 2.0 Skinning -The `KHR_avatar_skeleton_biped` extension builds on top of the core glTF 2.0 skinning system. It does **not** introduce new skinning mechanics, but instead annotates which nodes in the existing `skins[].joints[]` structure correspond to meaningful joints in a developer-defined skeletal rig. +The `KHR_character_skeleton_biped` extension builds on top of the core glTF 2.0 skinning system. It does **not** introduce new skinning mechanics, but instead annotates which nodes in the existing `skins[j].joints[]` structure correspond to meaningful joints in a developer-defined skeletal rig. The joint indices specified in the `joints` dictionary refer directly to elements within the glTF `nodes` array, and should match those used in a valid `skin` structure: -- The avatar mesh should be associated with a `skin`, per [glTF 2.0 Skinning](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#skins). +- The character mesh should be associated with a `skin`, per [glTF 2.0 Skinning](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#skins). - The joints listed in this extension must be a subset of the joints defined in `skins[j].joints`. -This enables runtime engines to extract semantic meaning from joint hierarchies already used for mesh deformation, supporting animation retargeting and avatar interoperability. +This enables runtime engines to extract semantic meaning from joint hierarchies already used for mesh deformation, supporting animation retargeting and character interoperability. ## Skeletal Mapping Support -Rather than define mapping logic directly in this extension, developers should use the [`KHR_avatar_skeleton_mapping`](./KHR_avatar_skeleton_mapping_README.md) extension in conjunction with this one for any one-to-one or one-to-many joint remapping between different rig topologies. +Rather than define mapping logic directly in this extension, developers should use the [`KHR_character_skeleton_mapping`](./KHR_character_skeleton_mapping_README.md) extension in conjunction with this one for any one-to-one or one-to-many joint remapping between different rig topologies. That extension supports weighted joint translation and enables cleaner separation between semantic labeling (this extension) and rig interoperability (mapping). @@ -122,14 +122,14 @@ This extension currently avoids defining any required or default biped joint hie > **Why?** > Standardizing on a single joint hierarchy would inadvertently lock the majority of developers into a single rig structure, limiting flexibility for studios and tools that use different conventions. -Instead, this extension enables **declarative labeling** of a bipedal skeleton using your rig's native hierarchy, and encourages semantic interoperability through mapping via the `KHR_avatar_skeleton_mapping` extension. +Instead, this extension enables **declarative labeling** of a bipedal skeleton using your rig's native hierarchy, and encourages semantic interoperability through mapping via the `KHR_character_skeleton_mapping` extension. As the ecosystem matures, guidance or profiles may emerge for common structures—but this extension deliberately avoids enforcing that at this time. ## Implementation Notes - This extension is non-destructive and overlays semantic information atop the existing glTF node hierarchy. -- Tools can use this extension to retarget animation between avatars, align expressions, or validate rigging consistency. +- Tools can use this extension to retarget animation between characters, align expressions, or validate rigging consistency. - The specified joint indices must form a valid hierarchy rooted at a common ancestor (usually `hips`). ## Known Implementations diff --git a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md similarity index 82% rename from extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md rename to extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md index 18b2872665..2680dd867b 100644 --- a/extensions/2.0/Khronos/KHR_avatar_skeleton_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md @@ -1,4 +1,4 @@ -# KHR_avatar_skeleton_mapping +# KHR_character_skeleton_mapping ## Contributors @@ -17,16 +17,16 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar` -Typically used in conjunction with: `KHR_avatar_skeleton_biped` +Dependent on: `KHR_character` +Typically used in conjunction with: `KHR_character_skeleton_biped` ## Overview -The `KHR_avatar_skeleton_mapping` extension provides a mechanism to map a skeleton rig to a reference rig, enabling retargeting and compatibility across different skeleton topologies. This extension is particularly useful for normalizing diverse rig structures across platforms and authoring tools. It provides one-to-one and one-to-many mapping; with the expectation that distributed weights add up to 1.0. +The `KHR_character_skeleton_mapping` extension provides a mechanism to map a skeleton rig to a reference rig, enabling retargeting and compatibility across different skeleton topologies. This extension is particularly useful for normalizing diverse rig structures across platforms and authoring tools. It provides one-to-one and one-to-many mapping; with the expectation that distributed weights add up to 1.0. ## Mapping to Known Standard Rigs -In many real-world scenarios, developers must remap an avatar's native joint structure to a **known, standardized rig**—such as a runtime's internal avatar model or a predefined specification like VRM's Humanoid rig. +In many real-world scenarios, developers must remap an character's native joint structure to a **known, standardized rig**—such as a runtime's internal character model or a predefined specification like VRM's Humanoid rig. This extension supports such cases by allowing one-to-one or one-to-many weighted mappings between a model’s joints and those of a **target standard rig**. @@ -43,9 +43,9 @@ Here’s an example mapping from a custom rig into VRM Humanoid: ```json { - "extensionsUsed": ["KHR_avatar_skeleton_mapping"], + "extensionsUsed": ["KHR_character_skeleton_mapping"], "extensions": { - "KHR_avatar_skeleton_mapping": { + "KHR_character_skeleton_mapping": { "skeletalRigMappings": { "vrmHumanoid": { "myRig_hips": [{ "target": "hips", "weight": 1.0 }], diff --git a/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md b/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md similarity index 87% rename from extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md rename to extensions/2.0/Khronos/KHR_character_virtual_joints/README.md index 69d2c466b8..cb3f151d7b 100644 --- a/extensions/2.0/Khronos/KHR_avatar_virtual_joints/README.md +++ b/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md @@ -1,4 +1,4 @@ -# KHR_avatar_virtual_joints +# KHR_character_virtual_joints ## Contributors @@ -17,11 +17,11 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar` +Dependent on: `KHR_character` ## Overview -The `KHR_avatar_virtual_joints` extension introduces _virtual joints_—custom transform nodes that exist relative to the avatar’s skeletal hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. +The `KHR_character_virtual_joints` extension introduces _virtual joints_—custom transform nodes that exist relative to the character’s skeletal hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. Virtual joints are defined via an offset transform relative to a single parent joint, and do **not** participate in skinning. They are evaluated at runtime for behavior logic and procedural animation. @@ -40,7 +40,7 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t ```json { "extensions": { - "KHR_avatar_virtual_joints": { + "KHR_character_virtual_joints": { "virtualJoints": [ { "name": "arm_socket", From dd2159ae7bf8c15c80ed8d6ffa9846fdcd7d1662 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 14:20:30 -0700 Subject: [PATCH 12/48] Small updates --- .../2.0/Khronos/KHR_character/README.md | 3 +- .../Khronos/KHR_character_avatar/README.md | 96 +--------------- .../KHR_character_expression/README.md | 104 ------------------ .../KHR_character_expression_joint/README.md | 2 +- .../README.md | 2 +- .../README.md | 2 +- .../README.md | 2 +- .../README.md | 2 +- .../README.md | 16 +-- .../README.md | 14 ++- .../KHR_character_skeleton_bindpose/README.md | 2 +- .../KHR_character_skeleton_biped/README.md | 2 +- .../KHR_character_skeleton_mapping/README.md | 2 +- .../KHR_character_virtual_joints/README.md | 2 +- 14 files changed, 30 insertions(+), 221 deletions(-) delete mode 100644 extensions/2.0/Khronos/KHR_character_expression/README.md rename extensions/2.0/Khronos/{KHR_avatar_mesh_annotation => KHR_character_mesh_annotation}/README.md (80%) rename extensions/2.0/Khronos/{KHR_avatar_mesh_annotation_rendering => KHR_character_mesh_annotation_rendering}/README.md (78%) diff --git a/extensions/2.0/Khronos/KHR_character/README.md b/extensions/2.0/Khronos/KHR_character/README.md index 5fe25b9db8..3f2365f0b7 100644 --- a/extensions/2.0/Khronos/KHR_character/README.md +++ b/extensions/2.0/Khronos/KHR_character/README.md @@ -18,7 +18,8 @@ Written against the glTF 2.0 specification. -Dependencies: `KHR_xmp_json_ld` +Requires the extensions: `KHR_xmp_json_ld` + This extension also leverages the `KHR_xmp_json_ld` pattern for attaching extensible metadata as JSON-LD blocks within glTF assets. For background on this approach, see: [KHR_xmp_json_ld](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_xmp_json_ld) diff --git a/extensions/2.0/Khronos/KHR_character_avatar/README.md b/extensions/2.0/Khronos/KHR_character_avatar/README.md index 3c0b35b3bf..80f9264317 100644 --- a/extensions/2.0/Khronos/KHR_character_avatar/README.md +++ b/extensions/2.0/Khronos/KHR_character_avatar/README.md @@ -18,20 +18,16 @@ Written against the glTF 2.0 specification. -Dependencies: `KHR_xmp_json_ld`, `KHR_character` -This extension also leverages the `KHR_xmp_json_ld` pattern for attaching extensible metadata as JSON-LD blocks within glTF assets. For background on this approach, see: -[KHR_xmp_json_ld](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_xmp_json_ld) +Requires the extension(s): `KHR_xmp_json_ld`, `KHR_character` ## Overview The `KHR_character_avatar` extension designates a glTF asset as representing an avatar. This top-level marker enables tools and runtimes to interpret the asset as containing avatar-specific content such as rigging, blendshapes, animation retargeting, or metadata. -This extension does not define avatar features directly but acts as a root declaration that avatar-related extensions may be present, and that consumers should treat the asset using avatar-specific logic and pipelines. It's part of the wider set of KHR avatar extensions that are meant to be building blocks to represent a contract stating functionality and data requirements between a given model and an endpoint. +This extension does not define avatar features directly but acts as a root declaration that avatar-related extensions may be present, and that consumers should treat the asset using avatar-specific logic and pipelines. It's part of the wider set of KHR character and avatar extensions that are meant to be building blocks to represent a contract stating functionality and data requirements between a given model and an endpoint. This extension is dependent on the KHR_character extension; which defines related functionality pertaining to more generalized characters. -The extension supports referencing the source `scene` that represents the avatar and optionally includes structured metadata through the `KHR_xmp_json_ld` mechanism. - ## Extension Schema ```json @@ -50,94 +46,6 @@ The extension supports referencing the source `scene` that represents the avatar | ------------ | ------- | ------------------------------------------------------------------------------------------------------------------ | | `sceneIndex` | integer | Index of the glTF `scene` representing the avatar. Used to distinguish the avatar root when multiple scenes exist. | -## Metadata Attachment: KHR_xmp_json_ld - -Avatar metadata should be expressed using the `KHR_xmp_json_ld` format, a structured mechanism for attaching JSON-LD metadata blocks to glTF files. In the context of `KHR_character_avatar`, this allows consistent expression of avatar provenance, licensing, creator, versioning, and intended use, among others. - -The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as part of the defined extension usage. Metadata keys and structures are defined in the shared Khronos Avatar Metadata schema (TBD). - -| DC/XMP_JSON_LD Property | Why | Required | -| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | -------- | -| dc:title | | Yes | -| dc:creator | | Yes | -| dc:license | | No | -| dc:rights | | No | -| dc:created | Date on which the asset was created | No | -| dc:publisher | Identifies the entity responsible for making the resource available; important for understanding the source and authority of the content. | No | -| dc:description | Context and a summary of the content | No | -| dc:subject | Can potentially be used for content tagging/association | No | -| dc:source | Important for tracing the provenance and ensuring proper attribution. | Yes | -| khr:version | | No | -| khr:thumbnailImage | | No | - -## Example - -```json -{ - "asset": { - "version": "2.0", - "extensions": { - "KHR_xmp_json_ld": { - "packet": 0 - } - } - }, - "scene": 0, - "scenes": [ - { - "nodes": [0] - } - ], - "nodes": [ - { - "name": "AvatarRoot" - } - ], - "extensionsUsed": ["KHR_character_avatar", "KHR_xmp_json_ld"], - "extensions": { - "KHR_character_avatar": { - "sceneIndex": 0 - }, - - "KHR_xmp_json_ld": { - "packets": [ - { - "@context": { - "dc": "http://purl.org/dc/elements/1.1/", - "vrm": "https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/meta.md" - }, - "dc:title": "Example Model", - "dc:creator": { - "@list": [ - "Author1", - "AuthorEmail1@email.com", - "Author2", - "AuthorEmail2@email.com" - ] - }, - "dc:license": { - "@list": [ - "https://vrm.dev/licenses/1.0/", - "https://example.com/third-party-license" - ] - }, - "dc:created": "2023-05-05", - "dc:rights": "Copyright information about the model", - "dc:publisher": "Imaginary Corporation A, LLC", - "dc:description": "A sentence, or paragraph describing the avatar at hand", - "dc:subject": { - "@list": ["Example trait", "Another example trait"] - }, - "dc:source": "imaginaryCompany.com/avatarl", - "khr:version": "1.0", - "khr:thumbnailImage": 0 - } - ] - } - } -} -``` - ## Implementation Notes - `sceneIndex` is required, representing the index of the glTF `scene` corresponding to the avatar. Used to distinguish the avatar root when multiple scenes exist. diff --git a/extensions/2.0/Khronos/KHR_character_expression/README.md b/extensions/2.0/Khronos/KHR_character_expression/README.md deleted file mode 100644 index ea5c72328e..0000000000 --- a/extensions/2.0/Khronos/KHR_character_expression/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# KHR_character_expression_joint - -## Contributors - -- Ken Jakubzak, Meta -- Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire -- Shinnosuke Iwaki / VirtualCast, Inc. -- 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor -- Nick Burkard, Meta - -## Status - -**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. - -## Dependencies - -Written against the glTF 2.0 specification. -Dependent on: `KHR_character` -Typically used in conjunction with: `KHR_character_expression_mapping` - -## Overview - -The `KHR_character_expression_joint` extension provides a semantic mapping between facial expression names and joint-based animations. It enables tools and runtimes to associate expressions like `blink`, `smile`, or `jawOpen` with specific nodes whose transforms are animated using standard glTF animation channels. - -This extension is purely descriptive: it does not define or store animation data itself. - -## Reference Expression Categories/Vocabularies - -Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. - -For examples of relevant types of expressions, you can reference concepts such as: - -- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) -- **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) -- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) -- **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) - -Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). - -## Extension Schema - -```json -{ - "extensions": { - "KHR_character_expression_joint": { - "expressions": [ - { - "expression": "smile", - "animation": 0, - "channels": [0, 1, 2] - }, - { - "expression": "frown", - "animation": 1, - "channels": [0, 1] - } - ] - } - } -} -``` - -### Properties - -| Property | Type | Description | -| ------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| `expressions` | array | Array of mappings between animation/channels and expression labels. | -| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | -| `expression` | string | Expression name this joint contributes to. | -| `channels` | array | array representing channels that must correspond to either `"rotation"`, `"translation"`, or `"scale"`; indicates transform types. | - -## Animation Integration - -- Expression timing, blending, and control must use glTF `animations` channels. -- Animations targeting expression-driven `rotation`, `translation`, or `scale` must conform to glTF 2.0's animation model. -- This ensures consistency, ease of implementation, and interoperability across runtimes. - -Each animation channel used to drive an expression should operate within a **normalized 0-to-1 range**, where: - -- `0.0` indicates the expression is fully inactive. -- `1.0` indicates the expression is fully active. - -The transformation values themselves (e.g., degree of rotation or distance of translation) should scale proportionally with the normalized input range. - -This approach simplifies character implementation by centralizing expression playback in the glTF animation system and unifying runtime logic for blending and prioritization. - -### Recommended Interpolation for Binary Expressions - -For expressions that represent binary or toggle states (such as `blinkLeft`, `blinkRight`, or `jawOpen`), the use of glTF animation channels with `"interpolation": "STEP"` is strongly recommended. - -STEP interpolation ensures that an expression toggles cleanly between fully off (`0.0`) and fully on (`1.0`) states, providing crisp visual transitions and avoiding interpolation artifacts that could occur with `LINEAR` interpolation in binary scenarios. - -## Implementation Notes - -- Multiple joints may be assigned to the same expression. -- Expression states should be normalized to the [0.0–1.0] range for consistent runtime interpretation. -- This extension does not conflict with standard rigging or skinning systems. - -## License - -This extension is licensed under the Khronos Group Extension License. -See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md index fa0a7a32b3..9c7ab38fca 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character`,`KHR_character_expression` +Dependent on: `KHR_character` Typically used in conjunction with: `KHR_character_expression_mapping` ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md index e66db768f8..9a836989fb 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character`,`KHR_character_expression` +Dependent on: `KHR_character` Can be used alongside: `KHR_character_expression_morphtarget`, `KHR_character_expression_joints`, `KHR_character_expression_texture` or other expression sources ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md index e1f29f83f9..efdb2f4dbd 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character`,`KHR_character_expression` +Dependent on: `KHR_character` Used in conjunction with: `KHR_character_expression_mapping` ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md index 1b5ee16894..fd384a9aa3 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character`,`KHR_character_expression` +Dependent on: `KHR_character` Works alongside: `KHR_character_expression_mapping`, `KHR_character_expression_joint`, `KHR_character_expression_texture`, `KHR_character_expression_morphtargets`. ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md index 163a6d3ef5..89e0ca884f 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character`, `KHR_animation_pointer`, `KHR_character_expression` +Dependent on: `KHR_character`, `KHR_animation_pointer` Can be used alongside: `KHR_character_expression_mapping` ## Overview diff --git a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_character_mesh_annotation/README.md similarity index 80% rename from extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md rename to extensions/2.0/Khronos/KHR_character_mesh_annotation/README.md index 892be3171e..54f4183f75 100644 --- a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation/README.md +++ b/extensions/2.0/Khronos/KHR_character_mesh_annotation/README.md @@ -1,4 +1,6 @@ -# KHR_avatar_mesh_annotation +# KHR_character_mesh_annotation + +### TODO - REFACTOR and potentially consolidate with KHR_character_mesh_annotation_rendering ## Contributors @@ -17,12 +19,12 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar` +Dependent on: `KHR_character` Can be used alongside rendering-related extensions. ## Overview -The `KHR_avatar_mesh_annotation` extension enables arbitrary per-mesh metadata annotations for avatar models. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic. +The `KHR_character_mesh_annotation` extension enables arbitrary per-mesh metadata annotations for character models. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic. Unlike expression bindings or skeletons, this extension focuses on **attaching structured metadata to glTF mesh primitives or submeshes**. Examples include: @@ -33,9 +35,9 @@ Unlike expression bindings or skeletons, this extension focuses on **attaching s ## Motivation -Avatar models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets for: +character models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets for: -- Avatar customization layers +- character customization layers - Haptic or interaction targeting - Runtime layering and decal application - Streaming/LOD switching @@ -44,7 +46,7 @@ This extension provides a consistent, schema-driven approach to labeling such me ## Schema -Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i]`), and stored in the `KHR_avatar_mesh_annotation` extension: +Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i]`), and stored in the `KHR_character_mesh_annotation` extension: ```json { @@ -54,7 +56,7 @@ Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i] { "attributes": { ... }, "extensions": { - "KHR_avatar_mesh_annotation": { + "KHR_character_mesh_annotation": { "tags": ["eyewear", "selectable"], "region": "face" } diff --git a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md b/extensions/2.0/Khronos/KHR_character_mesh_annotation_rendering/README.md similarity index 78% rename from extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md rename to extensions/2.0/Khronos/KHR_character_mesh_annotation_rendering/README.md index b91324ae8f..5336ccf10a 100644 --- a/extensions/2.0/Khronos/KHR_avatar_mesh_annotation_rendering/README.md +++ b/extensions/2.0/Khronos/KHR_character_mesh_annotation_rendering/README.md @@ -1,4 +1,6 @@ -# KHR_avatar_mesh_annotation_rendering +# KHR_character_mesh_annotation_rendering + +### TODO - REFACTOR and potentially consolidate with KHR_character_mesh_annotation ## Contributors @@ -17,18 +19,18 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_avatar` +Requires the extension(s): `KHR_character` ## Overview -The `KHR_avatar_mesh_annotation_rendering` extension provides structured metadata for avatar mesh primitives related to **visibility and render-time behavior**. It complements the core glTF material and LOD systems by exposing semantic visibility rules such as “first-person only”, “always visible”, etc. +The `KHR_character_mesh_annotation_rendering` extension provides structured metadata for character mesh primitives related to **visibility and render-time behavior**. It complements the core glTF material and LOD systems by exposing semantic visibility rules such as “first-person only” and “always visible”. This extension is intended to support use cases such as: -- Hiding certain parts of an avatar (like head or hair) in first-person mode +- Hiding certain parts of an character (like head or hair) in first-person mode - Marking components that must always be rendered (e.g., eyes) - Toggling cosmetic parts based on camera mode or gameplay state -- Managing specialized render passes (shadows, reflections, etc.) +- Managing specialized render passes (e.g. shadows, reflections) ## Use Cases @@ -48,7 +50,7 @@ This extension is defined per `mesh.primitive`, allowing fine-grained render beh "primitives": [ { "extensions": { - "KHR_avatar_mesh_annotation_rendering": { + "KHR_character_mesh_annotation_rendering": { "renderVisibility": "firstPersonOnly", "renderTags": ["eyewear", "forceRender"] } diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md index 139539ba6c..625152b488 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character` +Requires the extension(s): `KHR_character` ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md index 6d395d0173..73cba586cd 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Depends on: `KHR_character` +Requires the extension(s): `KHR_character` ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md index 2680dd867b..2d1fc7823d 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character` +Requires the extension(s): `KHR_character` Typically used in conjunction with: `KHR_character_skeleton_biped` ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md b/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md index cb3f151d7b..ed130b58bb 100644 --- a/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md +++ b/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character` +Requires the extension(s): `KHR_character` ## Overview From 55bd2179f55921762e7263feb4817c9a736be765 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 14:41:46 -0700 Subject: [PATCH 13/48] More minor updates --- extensions/2.0/Khronos/KHR_character_expression_joint/README.md | 2 +- .../2.0/Khronos/KHR_character_expression_mapping/README.md | 2 +- .../2.0/Khronos/KHR_character_expression_morphtarget/README.md | 2 +- .../2.0/Khronos/KHR_character_expression_procedural/README.md | 2 +- .../2.0/Khronos/KHR_character_expression_texture/README.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md index 9c7ab38fca..f47519cfbb 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character` +Requires the extension(s): `KHR_character` Typically used in conjunction with: `KHR_character_expression_mapping` ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md index 9a836989fb..5dcf192b1f 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character` +Requires the extension(s): `KHR_character` Can be used alongside: `KHR_character_expression_morphtarget`, `KHR_character_expression_joints`, `KHR_character_expression_texture` or other expression sources ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md index efdb2f4dbd..a35aa638d7 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character` +Requires the extension(s): `KHR_character` Used in conjunction with: `KHR_character_expression_mapping` ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md index fd384a9aa3..fe20d41df8 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character` +Requires the extension(s): `KHR_character` Works alongside: `KHR_character_expression_mapping`, `KHR_character_expression_joint`, `KHR_character_expression_texture`, `KHR_character_expression_morphtargets`. ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md index 89e0ca884f..f15758ca15 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character`, `KHR_animation_pointer` +Requires the extension(s): `KHR_character`, `KHR_animation_pointer` Can be used alongside: `KHR_character_expression_mapping` ## Overview From c461bab7d50e8f7edfea213112ae71c125f4fa75 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 14:42:07 -0700 Subject: [PATCH 14/48] Add virtual joint example for non-rotation-respecting virtual joint --- .../KHR_character_virtual_joints/README.md | 53 ++++++++++++++++--- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md b/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md index ed130b58bb..06833008e2 100644 --- a/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md +++ b/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md @@ -34,6 +34,7 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t - **Sitting or standing targets** - **Hint points** for IK solvers - **Camera or gaze anchors** +- **UI Attach points** - UI attachments that potentially need to not respect the rotation of the parent joints (e.g. a wrist UI in an AR/VR experience that needs to always be above the ) ## Schema @@ -46,19 +47,33 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t "name": "arm_socket", "parentJoint": 18, "translation": [0.0, 0.1, 0.0], - "rotation": [0.0, 0.0, 0.0, 1.0] + "rotation": [0.0, 0.0, 0.0, 1.0], + "respectParentPosition": true, + "respectParentRotation": true }, { "name": "lookAt_target", "parentJoint": 8, "translation": [0.0, 0.0, 0.35], - "rotation": [0.0, 0.0, 0.0, 1.0] + "rotation": [0.0, 0.0, 0.0, 1.0], + "respectParentPosition": true, + "respectParentRotation": true }, { "name": "sitting_point", "parentJoint": 0, "translation": [0.0, 0.0, -0.2], - "rotation": [0.0, 0.0, 0.0, 1.0] + "rotation": [0.0, 0.0, 0.0, 1.0], + "respectParentPosition": true, + "respectParentRotation": true + }, + { + "name": "wrist_ui", + "parentJoint": 19, + "translation": [0.0, 0.25, 0.0], + "rotation": [0.0, 0.0, 0.0, 1.0], + "respectParentPosition": true, + "respectParentRotation": false } ] } @@ -72,8 +87,10 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t | ------------- | -------- | ------------------------------------------------------------------------- | | `name` | string | Semantic identifier of the virtual joint | | `parentJoint` | integer | Index into the glTF `nodes[]` array representing the base joint | -| `translation` | float[3] | Local offset (X, Y, Z) relative to the parent joint | +| `translation` | float[3] | Initialized local offset (X, Y, Z) relative to the parent joint | | `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent joint | +| `respectParentPosition` | bool | bool to determine whether this should respect the parent joint position post-initialization | +| `respectParentRotation` | bool | bool to determine whether this should respect the parent joint rotation post-initialization | ## Examples @@ -81,23 +98,43 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t - **Name**: `"arm_socket"` - **Parent**: Between elbow and wrist (e.g., joint index 18) -- **Offset**: `(0.0, 0.1, 0.0)` -- **Usage**: Anchor for attaching objects +- **Translation**: `(0.0, 0.1, 0.0)` +- **Rotation**: `(0.0, 0.0, 0.0, 1.0)` +- **respectParentPosition**: `true` +- **respectParentRotation**: `true` +- **Usage**: Anchor for attaching objects, which want to respect the positions/rotation of the parent joints ### Look At Virtual Joint - **Name**: `"lookAt_target"` - **Parent**: `"head"` joint (e.g., joint index 8) -- **Offset**: `(0.0, 0.0, 0.35)` +- **Translation**: `(0.0, 0.0, 0.35)` +- **Rotation**: `(0.0, 0.0, 0.0, 1.0)` +- **respectParentPosition**: `true` +- **respectParentRotation**: `true` - **Usage**: Target for runtime look-at behavior (eyes/head alignment). ### Sitting Point Virtual Joint - **Name**: `"sitting_point"` - **Parent**: `"pelvis"` joint (e.g., joint index 0) -- **Offset**: `(0.0, 0.0, -0.2)` +- **Translation**: `(0.0, 0.0, -0.2)` +- **Rotation**: `(0.0, 0.0, 0.0, 1.0)` +- **respectParentPosition**: `true` +- **respectParentRotation**: `true` - **Usage**: Anchor point for aligning seated positions. + +### Wrist UI Virtual Joint + +- **Name**: `"wrist_ui_socket"` +- **Parent**: `"wrist"` joint (e.g., joint index 19) +- **Offset**: `(0.0, .25, 0.0)` +- **Rotation**: `(0.0, 0.0, 0.0, 1.0)` +- **respectParentPosition**: `true` +- **respectParentRotation**: `false` +- **Usage**: Anchor point for wrist UI, which may wish to respect the parent joint's position, but not the rotation. + ## Implementation Notes - Virtual joints should exist only within this extension and **must not overlap with joints used in skinning**. From 3822282ebd574b4ef17cbb8a6b333946ce4d3e9d Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 15:23:10 -0700 Subject: [PATCH 15/48] Update typed expression extensions to reflect a centralized expression extension --- .../KHR_character_expression/README.md | 142 ++++++++++++++++++ .../KHR_character_expression_joint/README.md | 25 +-- .../README.md | 2 +- .../README.md | 39 +++-- .../README.md | 4 +- .../README.md | 55 ++++--- 6 files changed, 214 insertions(+), 53 deletions(-) create mode 100644 extensions/2.0/Khronos/KHR_character_expression/README.md diff --git a/extensions/2.0/Khronos/KHR_character_expression/README.md b/extensions/2.0/Khronos/KHR_character_expression/README.md new file mode 100644 index 0000000000..f07e88755c --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_expression/README.md @@ -0,0 +1,142 @@ +# KHR_character_expression + +## Contributors + +- Ken Jakubzak, Meta +- Hideaki Eguchi / VirtualCast, Inc. +- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- Shinnosuke Iwaki / VirtualCast, Inc. +- 0b5vr / pixiv Inc. +- Leonard Daly, Individual Contributor +- Nick Burkard, Meta + +## Status + +**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. + +## Dependencies + +Written against the glTF 2.0 specification. +Requires the extension(s): `KHR_character` + +## Overview + +The `KHR_character_expression` extension provides a common interface for facial expression animations. It enables tools and runtimes to associate expressions like `blink`, `smile`, or `jawOpen` with specific animations in the glTF model's animations field. + +When used in conjunction with the other expression extensions, enables a data contract with endpoints allowing them to understand just what kind of data is present and being powered. + +This extension is purely descriptive: it does not define or store animation data itself. + +## Reference Expression Categories/Vocabularies + +Expressions in this context describe face-localized animations used to drive small and/or larger movements across the face and/or down-chain meshes needed for reasonable conveyance of emotion/intent. + +For examples of relevant types of expressions, you can reference concepts such as: + +- **Emotions** (Emotion-derived facial movements such as what [VRM defines as presets](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md), e.g. `happy`, `angry`, `surprised`) +- **Visemes** (A visual representations of mouth movements for parts of speech, e.g. `aa`, `oo`, `th`) +- **FACS** ([Facial Action Coding System (FACS)](https://en.wikipedia.org/wiki/Facial_Action_Coding_System) which is a system intended to describe visually distinguishable facial movements (and is often split further based on left/right), e.g. `brow lowerer`, `chin raiser`, `lid droop`) +- **Gestures and Actions** (Larger descriptors that describe general facial actionse (but not emotion), e.g. `blink`, `smile`, `jawOpen`) + +Optionally, these expressions may be aligned with industry standards (or an endpoint/experiences expected expressions set). + +## Extension Schema + +```json +{ + "extensions": { + "KHR_character_expression": { + "expressions": [ + { + "expression": "smile", + "animation": 0 + }, + { + "expression": "frown", + "animation": 1 + } + ] + } + } +} +``` + +### Properties + +| Property | Type | Description | +| ------------- | ------- | ------------------------------------------------------------------------------ | +| `expressions` | array | Array of mappings between animation/channels and expression labels. | +| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | +| `expression` | string | Expression name this joint contributes to. | + +## Animation Integration + +- Expression timing, blending, and control must use glTF `animations` channels. +- This ensures consistency, ease of implementation, and interoperability across runtimes. + +Each animation channel used to drive an expression should operate within a **normalized 0-to-1 range**, where: + +- `0.0` indicates the expression is fully inactive. +- `1.0` indicates the expression is fully active. + +The transformation values themselves (e.g., degree of rotation or distance of translation) should scale proportionally with the normalized input range. + +This approach simplifies character implementation by centralizing expression playback in the glTF animation system and unifying runtime logic for blending and prioritization. + +### Recommended Interpolation for Binary Expressions + +For expressions that represent binary or toggle states (such as `blinkLeft`, `blinkRight`, or `jawOpen`), the use of glTF animation channels with `"interpolation": "STEP"` is strongly recommended. + +STEP interpolation ensures that an expression toggles cleanly between fully off (`0.0`) and fully on (`1.0`) states, providing crisp visual transitions and avoiding interpolation artifacts that could occur with `LINEAR` interpolation in binary scenarios. + +## Extension Example w/ typed extensions + +```json +{ + "extensions": { + "KHR_character_expression": { + "expressions": [ + { + "expression": "smile", + "animation": 0, + "extensions": { + "KHR_avatar_expression_joint": { + "channels": [0, 1] + }, + "KHR_avatar_expression_texture": { + "channels": [2] + }, + "KHR_avatar_expression_morphtarget": { + "channels": [4, 5] + } + } + }, + { + "expression": "frown", + "animation": 1, + "extensions": { + "KHR_avatar_expression_joint": { + "channels": [0] + }, + "KHR_avatar_expression_texture": { + "channels": [1, 2] + }, + "KHR_avatar_expression_morphtarget": { + "channels": [3] + } + } + } + ] + } + } +} +``` + +## Implementation Notes + +- Expression states should be normalized to the [0.0–1.0] range for consistent runtime interpretation. + +## License + +This extension is licensed under the Khronos Group Extension License. +See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md index f47519cfbb..5bc2b70f82 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character` +Requires the extension(s): `KHR_character`,`KHR_character_expression` Typically used in conjunction with: `KHR_character_expression_mapping` ## Overview @@ -44,17 +44,25 @@ Optionally, these expressions may be aligned with industry standards (or an endp ```json { "extensions": { - "KHR_character_expression_joint": { + "KHR_character_expression": { "expressions": [ { "expression": "smile", "animation": 0, - "channels": [0, 1, 2] + "extensions": { + "KHR_avatar_expression_joint": { + "channels": [0, 1, 2] + } + } }, { "expression": "frown", "animation": 1, - "channels": [0, 1] + "extensions": { + "KHR_avatar_expression_joint": { + "channels": [0, 1] + } + } } ] } @@ -64,12 +72,9 @@ Optionally, these expressions may be aligned with industry standards (or an endp ### Properties -| Property | Type | Description | -| ------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| `expressions` | array | Array of mappings between animation/channels and expression labels. | -| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | -| `expression` | string | Expression name this joint contributes to. | -| `channels` | array | array representing channels that must correspond to either `"rotation"`, `"translation"`, or `"scale"`; indicates transform types. | +| Property | Type | Description | +| ---------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------- | +| `channels` | array | array representing channels that must correspond to either `"rotation"`, `"translation"`, or `"scale"`; indicates transform types. | ## Animation Integration diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md index 5dcf192b1f..216a0a67b4 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character` +Requires the extension(s): `KHR_character`,`KHR_character_expression` Can be used alongside: `KHR_character_expression_morphtarget`, `KHR_character_expression_joints`, `KHR_character_expression_texture` or other expression sources ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md index a35aa638d7..76e6569138 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character` +Requires the extension(s): `KHR_character`,`KHR_character_expression` Used in conjunction with: `KHR_character_expression_mapping` ## Overview @@ -44,17 +44,25 @@ Optionally, these expressions may be aligned with industry standards (or an endp ```json { "extensions": { - "KHR_character_expression_morphtarget": { + "KHR_character_expression": { "expressions": [ { "expression": "smile", "animation": 0, - "channel": 0 + "extensions": { + "KHR_avatar_expressions_morphtarget": { + "channels": [0] + } + } }, { "expression": "frown", "animation": 1, - "channel": 0 + "extensions": { + "KHR_avatar_expressions_morphtarget": { + "channels": [0] + } + } } ] } @@ -64,12 +72,9 @@ Optionally, these expressions may be aligned with industry standards (or an endp ### Properties -| Property | Type | Description | -| ------------- | ------- | ------------------------------------------------------------------------------ | -| `expressions` | array | Array of mappings between animation/channels and expression labels. | -| `animation` | integer | Index into the glTF `animations[]` array representing an expression animation. | -| `expression` | string | Expression name this joint contributes to. | -| `channel` | integet | Index representing the `"weights"` channel | +| Property | Type | Description | +| --------- | ------- | ------------------------------------------ | +| `channel` | integet | Index representing the `"weights"` channel | ## Animation Integration (Expressions Tab Recommendation) @@ -113,17 +118,25 @@ All morph target expressions should be driven using standard glTF animation chan ```json { "extensions": { - "KHR_character_expression_morphtarget": { + "KHR_character_expression": { "expressions": [ { "expression": "smile", "animation": 0, - "channel": 0 + "extensions": { + "KHR_avatar_expressions_morphtarget": { + "channels": [0] + } + } }, { "expression": "frown", "animation": 1, - "channel": 0 + "extensions": { + "KHR_avatar_expressions_morphtarget": { + "channels": [0] + } + } } ] } diff --git a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md index fe20d41df8..849595b31f 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md @@ -12,12 +12,14 @@ ## Status +### TODO - REFACTOR and address some of the concerns around this current implementation, as well as incorporate it into the refactored extension hierarchy with KHR_character_expression + **Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. ## Dependencies Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character` +Requires the extension(s): `KHR_character`,`KHR_character_expression` Works alongside: `KHR_character_expression_mapping`, `KHR_character_expression_joint`, `KHR_character_expression_texture`, `KHR_character_expression_morphtargets`. ## Overview diff --git a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md index f15758ca15..7aeb852657 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md @@ -17,7 +17,7 @@ ## Dependencies Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character`, `KHR_animation_pointer` +Requires the extension(s): `KHR_character`, `KHR_character_expression`, `KHR_animation_pointer` Can be used alongside: `KHR_character_expression_mapping` ## Overview @@ -45,21 +45,25 @@ Optionally, these expressions may be aligned with industry standards (or an endp ```json { "extensions": { - "KHR_character_expression_texture": { + "KHR_character_expression": { "expressions": [ { - "material": 2, - "texture": 5, "expression": "happy", "animation": 0, - "channels": [0] + "extensions": { + "KHR_avatar_expression_texture": { + "channels": [0] + } + } }, { - "material": 2, - "texture": 5, "expression": "angry", "animation": 1, - "channels": [0, 1] + "extensions": { + "KHR_avatar_expression_texture": { + "channels": [0, 1] + } + } } ] } @@ -69,13 +73,10 @@ Optionally, these expressions may be aligned with industry standards (or an endp ### Properties -| Property | Type | Description | -| ------------------ | ------- | -------------------------------------------------------------------------------- | -| `expressions` | array | List of texture-expression bindings. | -| `material` | integer | Index into the glTF `materials` array. | -| `texture` | integer | (Optional) Index into the glTF `textures` array, defining a replacement texture. | -| `textureTransform` | object | (Optional) UV transformations for texture-based expressions. | -| `expression` | string | Expression name associated with this texture or UV change. | +| Property | Type | Description | +| -------- | ---- | ----------- | + +| `channel` | array | Array representing the target channels that are texture transform-based | ### textureTransform properties @@ -84,12 +85,6 @@ Optionally, these expressions may be aligned with industry standards (or an endp | `offset` | float[2] | UV offset for texture placement. | | `scale` | float[2] | UV scale for texture transformation. | -### Recommended Interpolation for Binary Expressions - -For expressions that represent binary or toggle states (such as eye blinks, mouth open/close states, or other on/off expressions), the use of glTF animation channels with `"interpolation": "STEP"` is strongly recommended. - -Using STEP interpolation ensures that the expression toggles cleanly between fully off (0) and fully on (1) states, providing crisp transitions and avoiding unintended interpolation artifacts. - ### Integration with KHR_animation_pointer For animations that involve texture swaps or UV transformations, implementations should rely on the [`KHR_animation_pointer`](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_animation_pointer) extension. This provides a standardized mechanism for animating texture and UV transform properties via JSON pointers. @@ -172,21 +167,25 @@ Using STEP interpolation ensures that the expression toggles cleanly between ful ```json { "extensions": { - "KHR_character_expression_texture": { + "KHR_character_expression": { "expressions": [ { - "material": 2, - "texture": 5, "expression": "happy", "animation": 0, - "channels": [0, 1] + "extensions": { + "KHR_avatar_expression_texture": { + "channels": [0, 1] + } + } }, { - "material": 2, - "texture": 5, "expression": "angry", "animation": 1, - "channels": [0, 1] + "extensions": { + "KHR_avatar_expression_texture": { + "channels": [0, 1] + } + } } ] } From 085360fb26d0464e7c7815d4e004608bf937988a Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 15:27:39 -0700 Subject: [PATCH 16/48] Fit nits with last commit --- .../2.0/Khronos/KHR_character_expression_joint/README.md | 4 ++-- .../KHR_character_expression_morphtarget/README.md | 8 ++++---- .../Khronos/KHR_character_expression_texture/README.md | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md index 5bc2b70f82..b6c14f7cb5 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md @@ -50,7 +50,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp "expression": "smile", "animation": 0, "extensions": { - "KHR_avatar_expression_joint": { + "KHR_character_expression_joint": { "channels": [0, 1, 2] } } @@ -59,7 +59,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp "expression": "frown", "animation": 1, "extensions": { - "KHR_avatar_expression_joint": { + "KHR_character_expression_joint": { "channels": [0, 1] } } diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md index 76e6569138..4982d981f1 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md @@ -50,7 +50,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp "expression": "smile", "animation": 0, "extensions": { - "KHR_avatar_expressions_morphtarget": { + "KHR_character_expressions_morphtarget": { "channels": [0] } } @@ -59,7 +59,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp "expression": "frown", "animation": 1, "extensions": { - "KHR_avatar_expressions_morphtarget": { + "KHR_character_expressions_morphtarget": { "channels": [0] } } @@ -124,7 +124,7 @@ All morph target expressions should be driven using standard glTF animation chan "expression": "smile", "animation": 0, "extensions": { - "KHR_avatar_expressions_morphtarget": { + "KHR_character_expressions_morphtarget": { "channels": [0] } } @@ -133,7 +133,7 @@ All morph target expressions should be driven using standard glTF animation chan "expression": "frown", "animation": 1, "extensions": { - "KHR_avatar_expressions_morphtarget": { + "KHR_character_expressions_morphtarget": { "channels": [0] } } diff --git a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md index 7aeb852657..0332e6ae0f 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md @@ -51,7 +51,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp "expression": "happy", "animation": 0, "extensions": { - "KHR_avatar_expression_texture": { + "KHR_character_expression_texture": { "channels": [0] } } @@ -60,7 +60,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp "expression": "angry", "animation": 1, "extensions": { - "KHR_avatar_expression_texture": { + "KHR_character_expression_texture": { "channels": [0, 1] } } @@ -173,7 +173,7 @@ Using STEP interpolation ensures that the expression toggles cleanly between ful "expression": "happy", "animation": 0, "extensions": { - "KHR_avatar_expression_texture": { + "KHR_character_expression_texture": { "channels": [0, 1] } } @@ -182,7 +182,7 @@ Using STEP interpolation ensures that the expression toggles cleanly between ful "expression": "angry", "animation": 1, "extensions": { - "KHR_avatar_expression_texture": { + "KHR_character_expression_texture": { "channels": [0, 1] } } From 59993b8fa78eaba26b2125dab1277f01941429a6 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 15:57:10 -0700 Subject: [PATCH 17/48] Iterated on KHR_character_expression_procedural Removed some of the problematic fields that caused concern (around classification of what kind of procedural trigger it'd have). Merged this pattern in with the current KHR_character_expression pattern. --- .../README.md | 56 +++++++------------ 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md index 849595b31f..f1fa23837a 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md @@ -12,14 +12,14 @@ ## Status -### TODO - REFACTOR and address some of the concerns around this current implementation, as well as incorporate it into the refactored extension hierarchy with KHR_character_expression +### TODO - Iterate on this to address some of the concerns around this current implementation, as well as incorporate it into the refactored extension hierarchy with KHR_character_expression **Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. ## Dependencies Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character`,`KHR_character_expression` +Requires the extension(s): `KHR_character`,`KHR_character_expression` Works alongside: `KHR_character_expression_mapping`, `KHR_character_expression_joint`, `KHR_character_expression_texture`, `KHR_character_expression_morphtargets`. ## Overview @@ -49,15 +49,25 @@ This metadata is **descriptive only**: it does not contain animation or behavior ```json { "extensions": { - "KHR_character_expression_procedural": { - "proceduralExpressions": [ + "KHR_character_expression": { + "expressions": [ { - "expression": "blinkLeft", - "mode": "timed" + "expression": "blink_left", + "animation": 0, + "extensions": { + "KHR_character_expression_procedural": { + "conflictResolution": "none" + } + } }, { - "expression": "mouthTwitch", - "mode": "random" + "expression": "mouth_purse", + "animation": 1, + "extensions": { + "KHR_character_expression_procedural": { + "conflictResolution": "blend" + } + } } ] } @@ -67,23 +77,9 @@ This metadata is **descriptive only**: it does not contain animation or behavior ### Properties -| Property | Type | Description | -| ----------------------- | ------ | --------------------------------------------------------------------------------------- | -| `proceduralExpressions` | array | List of expression metadata entries that are intended to be procedurally controlled | -| `expression` | string | Corresponding expression name | -| `mode` | string | Enum: `"timed"`, `"random"`, `"live"`, `"scripted"` — describes the procedural strategy | - -## Procedural Modes - -TODO: Need to discuss the items below; there is concern around these particular fields and assertions that end applications should decide how to control these - -| Mode | Meaning | -| ---------- | ------------------------------------------------------------------------------ | -| `timed` | The expression occurs in regular intervals (e.g., blinking every 5s) | -| `random` | The expression fires with stochastic timing or weights | -| `live` | Driven by live-captured inputs (e.g., webcam, eye tracking) | -| `scripted` | Driven by external dialogue, AI logic, or gameplay sequences | -| `mixed` | Combines two or more procedural sources, such as live tracking + scripted cues | +| Property | Type | Description | +| -------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `conflictResolution` | string | Conflict Resolution route used to determine the resolution strategy when multiple sources (procedural and non-procedural) want to control a given expression | ## Expression Control Behavior @@ -99,15 +95,6 @@ Each procedural expression may declare a resolution strategy for combining proce | `block` | Procedural output _overrides_ animation data while active. | | `blend` | Procedural and animation data may be blended or accumulated together. | -### Example with Resolution Mode - -```json -{ - "expression": "blinkLeft", - "mode": "timed", - "conflictResolution": "blend" -} -``` This allows developers to distinguish expressions meant to supplement animation (e.g., micro-blinks over emotive acting) versus those that must fully override input (e.g., forced gaze). @@ -115,7 +102,6 @@ This allows developers to distinguish expressions meant to supplement animation - This extension is schema-only and does not contain behavior logic or animation data. - Runtimes may use this to suppress baked animation for procedural targets. -- The expression names should align with the shared vocabulary defined in the `KHR_character_expression_mapping`. ## License From 18d2d884a0087db8bb54f1d9716de75974104a98 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 22:09:27 -0700 Subject: [PATCH 18/48] Testing mesh annotation refactor --- .../README.md | 24 ++++++--------- .../README.md | 29 +++++++++---------- 2 files changed, 22 insertions(+), 31 deletions(-) rename extensions/2.0/Khronos/{KHR_character_mesh_annotation => KHR_mesh_annotation}/README.md (71%) rename extensions/2.0/Khronos/{KHR_character_mesh_annotation_rendering => KHR_mesh_annotation_renderviews}/README.md (64%) diff --git a/extensions/2.0/Khronos/KHR_character_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md similarity index 71% rename from extensions/2.0/Khronos/KHR_character_mesh_annotation/README.md rename to extensions/2.0/Khronos/KHR_mesh_annotation/README.md index 54f4183f75..3318594a9c 100644 --- a/extensions/2.0/Khronos/KHR_character_mesh_annotation/README.md +++ b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md @@ -1,6 +1,6 @@ -# KHR_character_mesh_annotation +# KHR_mesh_annotation -### TODO - REFACTOR and potentially consolidate with KHR_character_mesh_annotation_rendering +### TODO - REFACTOR and potentially consolidate with KHR_mesh_annotation_rendering ## Contributors @@ -19,15 +19,13 @@ ## Dependencies Written against the glTF 2.0 specification. -Dependent on: `KHR_character` Can be used alongside rendering-related extensions. ## Overview -The `KHR_character_mesh_annotation` extension enables arbitrary per-mesh metadata annotations for character models. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic. - -Unlike expression bindings or skeletons, this extension focuses on **attaching structured metadata to glTF mesh primitives or submeshes**. Examples include: +The `KHR_mesh_annotation` extension enables arbitrary per-mesh metadata annotations for character models. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic. +Examples include: - Indicating occlusion, hit zones, body regions, or cosmetics - Tagging subregions with gameplay affordances (e.g., "touchable", "selectable") - Supporting accessibility metadata (e.g., limb representation for low-vision aid) @@ -35,9 +33,9 @@ Unlike expression bindings or skeletons, this extension focuses on **attaching s ## Motivation -character models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets for: +This was thought of as part of the avatar/character extension proposals; as character models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets for: -- character customization layers +- Character customization layers - Haptic or interaction targeting - Runtime layering and decal application - Streaming/LOD switching @@ -46,7 +44,7 @@ This extension provides a consistent, schema-driven approach to labeling such me ## Schema -Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i]`), and stored in the `KHR_character_mesh_annotation` extension: +Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i]`), and stored in the `KHR_mesh_annotation` extension: ```json { @@ -56,9 +54,9 @@ Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i] { "attributes": { ... }, "extensions": { - "KHR_character_mesh_annotation": { + "KHR_mesh_annotation": { "tags": ["eyewear", "selectable"], - "region": "face" + "customData": { } } } } @@ -108,10 +106,6 @@ Allows filtering of optional accessories or togglable cosmetic parts. - `customData` allows developers to store app-specific structured metadata (e.g., color categories, tracking weights, heatmaps). - If this extension is not understood by a client, it should be safely ignored with no visual or functional change. -## Relation to Other Extensions - -- **Complements `KHR_materials_variants`** by labeling which primitives may be toggled/swapped. - ## License This extension is licensed under the Khronos Group Extension License. diff --git a/extensions/2.0/Khronos/KHR_character_mesh_annotation_rendering/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation_renderviews/README.md similarity index 64% rename from extensions/2.0/Khronos/KHR_character_mesh_annotation_rendering/README.md rename to extensions/2.0/Khronos/KHR_mesh_annotation_renderviews/README.md index 5336ccf10a..c6f0d2d808 100644 --- a/extensions/2.0/Khronos/KHR_character_mesh_annotation_rendering/README.md +++ b/extensions/2.0/Khronos/KHR_mesh_annotation_renderviews/README.md @@ -1,6 +1,4 @@ -# KHR_character_mesh_annotation_rendering - -### TODO - REFACTOR and potentially consolidate with KHR_character_mesh_annotation +# KHR_mesh_annotation_rendview ## Contributors @@ -18,19 +16,13 @@ ## Dependencies -Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character` +Written against the glTF 2.0 specification. ## Overview -The `KHR_character_mesh_annotation_rendering` extension provides structured metadata for character mesh primitives related to **visibility and render-time behavior**. It complements the core glTF material and LOD systems by exposing semantic visibility rules such as “first-person only” and “always visible”. - -This extension is intended to support use cases such as: +The `KHR_mesh_annotation_rendview` extension provides structured metadata for character mesh primitives related to **visibility and render-time behavior**. It complements the core glTF material and LOD systems by exposing semantic visibility rules such as “first-person only” and “always visible”. -- Hiding certain parts of an character (like head or hair) in first-person mode -- Marking components that must always be rendered (e.g., eyes) -- Toggling cosmetic parts based on camera mode or gameplay state -- Managing specialized render passes (e.g. shadows, reflections) +This extension is intended to support use cases such as hiding certain parts of an character (like head or hair) in first-person mode, or marking components that must always be rendered (e.g., eyes) ## Use Cases @@ -49,10 +41,16 @@ This extension is defined per `mesh.primitive`, allowing fine-grained render beh { "primitives": [ { + "attributes": { ... }, "extensions": { - "KHR_character_mesh_annotation_rendering": { - "renderVisibility": "firstPersonOnly", - "renderTags": ["eyewear", "forceRender"] + "KHR_mesh_annotation": { + "tags": ["eyewear", "selectable"], + "customData": { }, + "extensions": { + "KHR_mesh_annotation_rendview": { + "renderVisibility": "firstPersonOnly" + } + } } } } @@ -67,7 +65,6 @@ This extension is defined per `mesh.primitive`, allowing fine-grained render beh | Property | Type | Description | |------------------|-------------|-----------------------------------------------------------------------------| | `renderVisibility` | string | Controls camera-based visibility. Enum: `"always"` | `"firstPersonOnly"` | `"thirdPersonOnly"` | `"never"` | -| `renderTags` | string[] | Optional list of semantic labels for custom rendering logic | ## Recommended Usage Patterns From 2ec0909173a5ca5fbe20d7cf9ac79f014ec9fea5 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 22:17:36 -0700 Subject: [PATCH 19/48] Changed virtual joints to virtual transforms --- .../README.md | 51 ++++++++++--------- 1 file changed, 28 insertions(+), 23 deletions(-) rename extensions/2.0/Khronos/{KHR_character_virtual_joints => KHR_character_virtual_transforms}/README.md (65%) diff --git a/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md b/extensions/2.0/Khronos/KHR_character_virtual_transforms/README.md similarity index 65% rename from extensions/2.0/Khronos/KHR_character_virtual_joints/README.md rename to extensions/2.0/Khronos/KHR_character_virtual_transforms/README.md index 06833008e2..1f39cf9f11 100644 --- a/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md +++ b/extensions/2.0/Khronos/KHR_character_virtual_transforms/README.md @@ -1,4 +1,4 @@ -# KHR_character_virtual_joints +# KHR_character_virtual_transforms ## Contributors @@ -21,18 +21,19 @@ Requires the extension(s): `KHR_character` ## Overview -The `KHR_character_virtual_joints` extension introduces _virtual joints_—custom transform nodes that exist relative to the character’s skeletal hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. +The `KHR_character_virtual_transforms` extension introduces _virtual transforms_—custom transform nodes that exist relative to the character’s skeletal/node hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. -Virtual joints are defined via an offset transform relative to a single parent joint, and do **not** participate in skinning. They are evaluated at runtime for behavior logic and procedural animation. +Virtual joints are defined via an offset transform relative to the parent nodes, and do **not** participate in skinning. If there are multiple parent nodes, the expected behavior is to have it be based on a translation directly between those nodes position-wise. They are evaluated at runtime for behavior logic and procedural animation. This extension is inspired in part by constructs like `lookAt` in VRM and aims to unify such functionality into a generic system usable across multiple glTF-based runtimes. +**TODO**: Need to work on proposed logic for interpolation when multiple parent nodes; this likely needs to be some sort of field with established lerp logic types. We could make the stance that it's a pure 50/50 split; but I imagine that might cause some eyebrows to be raised. + ## Use Cases - **Look-at targets** (for head/eye tracking) - **Attachment points** (e.g., a weapon or tool socket) - **Sitting or standing targets** -- **Hint points** for IK solvers - **Camera or gaze anchors** - **UI Attach points** - UI attachments that potentially need to not respect the rotation of the parent joints (e.g. a wrist UI in an AR/VR experience that needs to always be above the ) @@ -41,39 +42,43 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t ```json { "extensions": { - "KHR_character_virtual_joints": { - "virtualJoints": [ + "KHR_character_virtual_transforms": { + "virtualTransforms": [ { "name": "arm_socket", - "parentJoint": 18, + "parentNodes": [18, 19], "translation": [0.0, 0.1, 0.0], "rotation": [0.0, 0.0, 0.0, 1.0], "respectParentPosition": true, - "respectParentRotation": true + "respectParentRotation": true, + "tags": [] }, { "name": "lookAt_target", - "parentJoint": 8, + "parentNodes": [8], "translation": [0.0, 0.0, 0.35], "rotation": [0.0, 0.0, 0.0, 1.0], "respectParentPosition": true, - "respectParentRotation": true + "respectParentRotation": true, + "tags": [] }, { "name": "sitting_point", - "parentJoint": 0, + "parentNodes": [0], "translation": [0.0, 0.0, -0.2], "rotation": [0.0, 0.0, 0.0, 1.0], "respectParentPosition": true, - "respectParentRotation": true + "respectParentRotation": true, + "tags": [] }, { "name": "wrist_ui", - "parentJoint": 19, + "parentNodes": [19], "translation": [0.0, 0.25, 0.0], "rotation": [0.0, 0.0, 0.0, 1.0], "respectParentPosition": true, - "respectParentRotation": false + "respectParentRotation": false, + "tags": [] } ] } @@ -86,54 +91,54 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t | Property | Type | Description | | ------------- | -------- | ------------------------------------------------------------------------- | | `name` | string | Semantic identifier of the virtual joint | -| `parentJoint` | integer | Index into the glTF `nodes[]` array representing the base joint | +| `parentNodes` | Array | Array of indices for nodes in the glTF `nodes[]` array | `translation` | float[3] | Initialized local offset (X, Y, Z) relative to the parent joint | | `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent joint | | `respectParentPosition` | bool | bool to determine whether this should respect the parent joint position post-initialization | | `respectParentRotation` | bool | bool to determine whether this should respect the parent joint rotation post-initialization | +| `tags` | Array | Array of strings used to denote tags that can be attributed to the virtual transform | ## Examples ### Arm Attachment Virtual Joint - +Example - Anchor for attaching objects, which want to respect the positions/rotation of the parent joints - **Name**: `"arm_socket"` - **Parent**: Between elbow and wrist (e.g., joint index 18) - **Translation**: `(0.0, 0.1, 0.0)` - **Rotation**: `(0.0, 0.0, 0.0, 1.0)` - **respectParentPosition**: `true` - **respectParentRotation**: `true` -- **Usage**: Anchor for attaching objects, which want to respect the positions/rotation of the parent joints +- **tags**: Array of strings used to denote semantic tags. ### Look At Virtual Joint - +Example - Target for runtime look-at behavior (eyes/head alignment) - **Name**: `"lookAt_target"` - **Parent**: `"head"` joint (e.g., joint index 8) - **Translation**: `(0.0, 0.0, 0.35)` - **Rotation**: `(0.0, 0.0, 0.0, 1.0)` - **respectParentPosition**: `true` - **respectParentRotation**: `true` -- **Usage**: Target for runtime look-at behavior (eyes/head alignment). +- **tags**: Array of strings used to denote semantic tags. ### Sitting Point Virtual Joint - +Example - Anchor point for aligning seated positions. - **Name**: `"sitting_point"` - **Parent**: `"pelvis"` joint (e.g., joint index 0) - **Translation**: `(0.0, 0.0, -0.2)` - **Rotation**: `(0.0, 0.0, 0.0, 1.0)` - **respectParentPosition**: `true` - **respectParentRotation**: `true` -- **Usage**: Anchor point for aligning seated positions. ### Wrist UI Virtual Joint - +Example - Anchor point for wrist UI, which may wish to respect the parent joint's position, but not the rotation. - **Name**: `"wrist_ui_socket"` - **Parent**: `"wrist"` joint (e.g., joint index 19) - **Offset**: `(0.0, .25, 0.0)` - **Rotation**: `(0.0, 0.0, 0.0, 1.0)` - **respectParentPosition**: `true` - **respectParentRotation**: `false` -- **Usage**: Anchor point for wrist UI, which may wish to respect the parent joint's position, but not the rotation. +- **tags**: Array of strings used to denote semantic tags. ## Implementation Notes From c321afab3bf46ef13398d694a8b710b7cb7a740c Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 22:29:30 -0700 Subject: [PATCH 20/48] Minor nit fixes --- .../2.0/Khronos/KHR_mesh_annotation/README.md | 11 ++--------- .../README.md | 15 ++++++++------- 2 files changed, 10 insertions(+), 16 deletions(-) rename extensions/2.0/Khronos/{KHR_mesh_annotation_renderviews => KHR_mesh_annotation_renderview}/README.md (66%) diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md index 3318594a9c..11e307c813 100644 --- a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md +++ b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md @@ -23,7 +23,7 @@ Can be used alongside rendering-related extensions. ## Overview -The `KHR_mesh_annotation` extension enables arbitrary per-mesh metadata annotations for character models. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic. +The `KHR_mesh_annotation` extension enables arbitrary per-mesh metadata annotations. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic. Examples include: - Indicating occlusion, hit zones, body regions, or cosmetics @@ -33,14 +33,7 @@ Examples include: ## Motivation -This was thought of as part of the avatar/character extension proposals; as character models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets for: - -- Character customization layers -- Haptic or interaction targeting -- Runtime layering and decal application -- Streaming/LOD switching - -This extension provides a consistent, schema-driven approach to labeling such mesh regions without requiring custom parsing or glTF structural abuse. +This was thought of as part of the avatar/character extension proposals; as character models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets, or attribute specific information about them (with it beiong on a per-primitive basis; as each primitive can be a different entity entirely). ## Schema diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation_renderviews/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md similarity index 66% rename from extensions/2.0/Khronos/KHR_mesh_annotation_renderviews/README.md rename to extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md index c6f0d2d808..f07c75bfcc 100644 --- a/extensions/2.0/Khronos/KHR_mesh_annotation_renderviews/README.md +++ b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md @@ -1,4 +1,4 @@ -# KHR_mesh_annotation_rendview +# KHR_mesh_annotation_renderiew ## Contributors @@ -20,16 +20,17 @@ Written against the glTF 2.0 specification. ## Overview -The `KHR_mesh_annotation_rendview` extension provides structured metadata for character mesh primitives related to **visibility and render-time behavior**. It complements the core glTF material and LOD systems by exposing semantic visibility rules such as “first-person only” and “always visible”. +The `KHR_mesh_annotation_renderview` extension provides structured metadata for character mesh primitives related to **visibility and render-time behavior**. It complements the core glTF material and LOD systems by exposing semantic visibility rules such as “first-person only” and “always visible”. This extension is intended to support use cases such as hiding certain parts of an character (like head or hair) in first-person mode, or marking components that must always be rendered (e.g., eyes) +This was thought of as part of the avatar/character extension proposals; as character models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets, or attribute specific information about them (with it beiong on a per-primitive basis; as each primitive can be a different entity entirely). Enabling visibility on a per-node basis would result in downchain nodes being disabled when it's not intended/desired; having a granular setting for this allows for more flexibility. + ## Use Cases -- First-person camera hiding for head/hair geometry -- Consistent behavior for accessories across render modes -- Semantic control of pass inclusion (e.g., do not render in reflection pass) -- Optimization by excluding off-screen or nested mesh content +- First-person camera hiding for head/hair geometry or other geometry +- Denoting when there's a completely different alternate mesh for one perspective versus the other + ## Extension Schema @@ -47,7 +48,7 @@ This extension is defined per `mesh.primitive`, allowing fine-grained render beh "tags": ["eyewear", "selectable"], "customData": { }, "extensions": { - "KHR_mesh_annotation_rendview": { + "KHR_mesh_annotation_renderview": { "renderVisibility": "firstPersonOnly" } } From 985455a2044fe927a7f65611a9ba8dac0e5f8105 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 2 Sep 2025 22:44:51 -0700 Subject: [PATCH 21/48] More implementation notes --- .../2.0/Khronos/KHR_mesh_annotation_renderview/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md index f07c75bfcc..4fca99fe66 100644 --- a/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md +++ b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md @@ -87,8 +87,10 @@ Used for elements like top meshes that should always remain active regardless of ## Implementation Notes -- These properties have no effect unless supported by the runtime. -- Runtimes may map `renderVisibility` values to camera tag groups or dynamic material toggles. +These properties have no effect unless supported by the runtime. + +Runtimes may choose to ignore renderVisibility settings if it directly causes downchain issues with their experiences (or a generalized incompatibility). In this case, our recommendation for +those runtimes or tools is to take these settings into account in some capacity if implementing their own mesh-culling logic for a given model. Of course given different uses of a model, your mileage may vary with this. For example, if used with a character in an experience that has a different camera perspective than what the original content creator thought of when baking the asset; it's up to the developer to determine what's more important (respecting the render visibility setting or the continuity of said experience). ## License From f560e6ee6864658950d4b3e80b3762c8494b547d Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 3 Sep 2025 21:22:18 -0700 Subject: [PATCH 22/48] Update extensions/2.0/Khronos/KHR_character_virtual_transforms/README.md Co-authored-by: Kitlith --- .../2.0/Khronos/KHR_character_virtual_transforms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/2.0/Khronos/KHR_character_virtual_transforms/README.md b/extensions/2.0/Khronos/KHR_character_virtual_transforms/README.md index 1f39cf9f11..51e9419f7c 100644 --- a/extensions/2.0/Khronos/KHR_character_virtual_transforms/README.md +++ b/extensions/2.0/Khronos/KHR_character_virtual_transforms/README.md @@ -23,7 +23,7 @@ Requires the extension(s): `KHR_character` The `KHR_character_virtual_transforms` extension introduces _virtual transforms_—custom transform nodes that exist relative to the character’s skeletal/node hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. -Virtual joints are defined via an offset transform relative to the parent nodes, and do **not** participate in skinning. If there are multiple parent nodes, the expected behavior is to have it be based on a translation directly between those nodes position-wise. They are evaluated at runtime for behavior logic and procedural animation. +Virtual transforms are defined via an offset transform relative to the parent nodes, and do **not** participate in skinning. If there are multiple parent nodes, the expected behavior is to have it be based on a translation directly between those nodes position-wise. They are evaluated at runtime for behavior logic and procedural animation. This extension is inspired in part by constructs like `lookAt` in VRM and aims to unify such functionality into a generic system usable across multiple glTF-based runtimes. From 639579c71b0db1865d9cc9b0127bbd78b993e69c Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 8 Sep 2025 21:09:04 -0700 Subject: [PATCH 23/48] Minor nits and moving virtual transform to KHR --- .../2.0/Khronos/KHR_mesh_annotation/README.md | 1 + .../KHR_mesh_annotation_renderview/README.md | 14 +++++++++-- .../README.md | 24 +++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) rename extensions/2.0/Khronos/{KHR_character_virtual_joints => KHR_virtual_transform}/README.md (72%) diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md index 11e307c813..a1d48e0680 100644 --- a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md +++ b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md @@ -26,6 +26,7 @@ Can be used alongside rendering-related extensions. The `KHR_mesh_annotation` extension enables arbitrary per-mesh metadata annotations. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic. Examples include: + - Indicating occlusion, hit zones, body regions, or cosmetics - Tagging subregions with gameplay affordances (e.g., "touchable", "selectable") - Supporting accessibility metadata (e.g., limb representation for low-vision aid) diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md index 4fca99fe66..5f62e88e6a 100644 --- a/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md +++ b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md @@ -1,4 +1,4 @@ -# KHR_mesh_annotation_renderiew +# KHR_mesh_annotation_renderview ## Contributors @@ -75,7 +75,15 @@ This extension is defined per `mesh.primitive`, allowing fine-grained render beh "renderVisibility": "thirdPersonOnly" ``` -Used to hide geometry (e.g., head, hair, hats) in first-person mode to prevent obstruction. +Used to hide geometry (e.g., head, hair, hats) in first-person modes to prevent obstruction. + +### First-Person Hiding + +```json +"renderVisibility": "firstPersonOnly" +``` + +Used to hide geometry (e.g. alternate first-person meshes or meshes containing more detail more relevant to first-person modes) in third-person mode. ### Always-Visible Elements @@ -92,6 +100,8 @@ These properties have no effect unless supported by the runtime. Runtimes may choose to ignore renderVisibility settings if it directly causes downchain issues with their experiences (or a generalized incompatibility). In this case, our recommendation for those runtimes or tools is to take these settings into account in some capacity if implementing their own mesh-culling logic for a given model. Of course given different uses of a model, your mileage may vary with this. For example, if used with a character in an experience that has a different camera perspective than what the original content creator thought of when baking the asset; it's up to the developer to determine what's more important (respecting the render visibility setting or the continuity of said experience). +**Considerations for Cameras** There is a world where there's an extension that provides suggested virtual camera transforms in conjunction with this set of visibility settings; but that would likely be a follow-up extension on top of this, which would then (as noted above) still be something that would need be be handled as recommendation rather than absolute. + ## License This extension is licensed under the Khronos Group Extension License. diff --git a/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md b/extensions/2.0/Khronos/KHR_virtual_transform/README.md similarity index 72% rename from extensions/2.0/Khronos/KHR_character_virtual_joints/README.md rename to extensions/2.0/Khronos/KHR_virtual_transform/README.md index 06833008e2..33a9703b8c 100644 --- a/extensions/2.0/Khronos/KHR_character_virtual_joints/README.md +++ b/extensions/2.0/Khronos/KHR_virtual_transform/README.md @@ -1,4 +1,8 @@ +<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md # KHR_character_virtual_joints +======== +# KHR_virtual_transforms +>>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md ## Contributors @@ -21,12 +25,23 @@ Requires the extension(s): `KHR_character` ## Overview +<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md The `KHR_character_virtual_joints` extension introduces _virtual joints_—custom transform nodes that exist relative to the character’s skeletal hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. +======== +The `KHR_virtual_transforms` extension introduces _virtual transforms_; metadata-informed virtual 'nodes' that exist relative to the a model's skeletal/node hierarchy, but are not nodes themselves and have settings whether to respect the parent nodes position/rotation at runtime. These virtual transforms serve as semantic attachment or control points for applications/systems to utilize; without it needing to be tied to a literal node hierarchy. + +In the context of characters, these virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. For other types of models, they can be leveraged for UI attach points, etc. +>>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md Virtual joints are defined via an offset transform relative to a single parent joint, and do **not** participate in skinning. They are evaluated at runtime for behavior logic and procedural animation. This extension is inspired in part by constructs like `lookAt` in VRM and aims to unify such functionality into a generic system usable across multiple glTF-based runtimes. +<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md +======== +**TODO**: Need to work on proposed logic for interpolation when multiple parent nodes; this likely needs to be some sort of field with established lerp logic types. We could make the stance that it's a pure 50/50 split; but I imagine that might cause some eyebrows to be raised. In general this likely needs a few revs, even past moving it out of the character set of extensions. + +>>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md ## Use Cases - **Look-at targets** (for head/eye tracking) @@ -41,8 +56,13 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t ```json { "extensions": { +<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md "KHR_character_virtual_joints": { "virtualJoints": [ +======== + "KHR_virtual_transforms": { + "virtualTransforms": [ +>>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md { "name": "arm_socket", "parentJoint": 18, @@ -122,7 +142,11 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t - **Rotation**: `(0.0, 0.0, 0.0, 1.0)` - **respectParentPosition**: `true` - **respectParentRotation**: `true` +<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md - **Usage**: Anchor point for aligning seated positions. +======== +- **tags**: Array of strings used to denote semantic tags. +>>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md ### Wrist UI Virtual Joint From 3b3403863cd1f12a1a19bc8d0b40093dc18b7666 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 8 Sep 2025 21:10:27 -0700 Subject: [PATCH 24/48] Update README.md --- .../Khronos/KHR_virtual_transform/README.md | 86 ++++++++----------- 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_virtual_transform/README.md b/extensions/2.0/Khronos/KHR_virtual_transform/README.md index 33a9703b8c..1194f1964a 100644 --- a/extensions/2.0/Khronos/KHR_virtual_transform/README.md +++ b/extensions/2.0/Khronos/KHR_virtual_transform/README.md @@ -1,8 +1,4 @@ -<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md -# KHR_character_virtual_joints -======== -# KHR_virtual_transforms ->>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md +# KHR_virtual_transform ## Contributors @@ -21,79 +17,69 @@ ## Dependencies Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character` ## Overview -<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md -The `KHR_character_virtual_joints` extension introduces _virtual joints_—custom transform nodes that exist relative to the character’s skeletal hierarchy but are **not part of the skinned joint structure**. These virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. -======== -The `KHR_virtual_transforms` extension introduces _virtual transforms_; metadata-informed virtual 'nodes' that exist relative to the a model's skeletal/node hierarchy, but are not nodes themselves and have settings whether to respect the parent nodes position/rotation at runtime. These virtual transforms serve as semantic attachment or control points for applications/systems to utilize; without it needing to be tied to a literal node hierarchy. +The `KHR_virtual_transform` extension introduces _virtual transforms_; metadata-informed virtual 'nodes' that exist relative to the a model's skeletal/node hierarchy, but are not nodes themselves and have settings whether to respect the parent nodes position/rotation at runtime. These virtual transforms serve as semantic attachment or control points for applications/systems to utilize; without it needing to be tied to a literal node hierarchy. -In the context of characters, these virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. For other types of models, they can be leveraged for UI attach points, etc. ->>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md +In the context of characters, these virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. For other types of models, they can be leveraged for UI attach points, etc. -Virtual joints are defined via an offset transform relative to a single parent joint, and do **not** participate in skinning. They are evaluated at runtime for behavior logic and procedural animation. +Virtual joints are defined via an offset transform relative to the parent nodes, and do **not** participate in skinning. If there are multiple parent nodes, the expected behavior is to have it be based on a translation directly between those nodes position-wise. They are evaluated at runtime for behavior logic and procedural animation. This extension is inspired in part by constructs like `lookAt` in VRM and aims to unify such functionality into a generic system usable across multiple glTF-based runtimes. -<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md -======== **TODO**: Need to work on proposed logic for interpolation when multiple parent nodes; this likely needs to be some sort of field with established lerp logic types. We could make the stance that it's a pure 50/50 split; but I imagine that might cause some eyebrows to be raised. In general this likely needs a few revs, even past moving it out of the character set of extensions. ->>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md ## Use Cases - **Look-at targets** (for head/eye tracking) - **Attachment points** (e.g., a weapon or tool socket) - **Sitting or standing targets** -- **Hint points** for IK solvers - **Camera or gaze anchors** -- **UI Attach points** - UI attachments that potentially need to not respect the rotation of the parent joints (e.g. a wrist UI in an AR/VR experience that needs to always be above the ) +- **UI Attach points** - UI attachments that potentially need to not respect the rotation of the parent joints/nodes (e.g. a wrist UI in an AR/VR experience that needs to always be above the ) ## Schema ```json { "extensions": { -<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md - "KHR_character_virtual_joints": { - "virtualJoints": [ -======== - "KHR_virtual_transforms": { + "KHR_virtual_transform": { "virtualTransforms": [ ->>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md { "name": "arm_socket", - "parentJoint": 18, + "parentNodes": [18, 19], "translation": [0.0, 0.1, 0.0], "rotation": [0.0, 0.0, 0.0, 1.0], "respectParentPosition": true, - "respectParentRotation": true + "respectParentRotation": true, + "tags": [] }, { "name": "lookAt_target", - "parentJoint": 8, + "parentNodes": [8], "translation": [0.0, 0.0, 0.35], "rotation": [0.0, 0.0, 0.0, 1.0], "respectParentPosition": true, - "respectParentRotation": true + "respectParentRotation": true, + "tags": [] }, { "name": "sitting_point", - "parentJoint": 0, + "parentNodes": [0], "translation": [0.0, 0.0, -0.2], "rotation": [0.0, 0.0, 0.0, 1.0], "respectParentPosition": true, - "respectParentRotation": true + "respectParentRotation": true, + "tags": [] }, { "name": "wrist_ui", - "parentJoint": 19, + "parentNodes": [19], "translation": [0.0, 0.25, 0.0], "rotation": [0.0, 0.0, 0.0, 1.0], "respectParentPosition": true, - "respectParentRotation": false + "respectParentRotation": false, + "tags": [] } ] } @@ -103,61 +89,65 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t ### Properties -| Property | Type | Description | -| ------------- | -------- | ------------------------------------------------------------------------- | -| `name` | string | Semantic identifier of the virtual joint | -| `parentJoint` | integer | Index into the glTF `nodes[]` array representing the base joint | -| `translation` | float[3] | Initialized local offset (X, Y, Z) relative to the parent joint | -| `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent joint | -| `respectParentPosition` | bool | bool to determine whether this should respect the parent joint position post-initialization | -| `respectParentRotation` | bool | bool to determine whether this should respect the parent joint rotation post-initialization | +| Property | Type | Description | +| ----------------------- | -------- | ------------------------------------------------------------------------------------------- | +| `name` | string | Semantic identifier of the virtual joint | +| `parentNodes` | Array | Array of indices for nodes in the glTF `nodes[]` array | +| `translation` | float[3] | Initialized local offset (X, Y, Z) relative to the parent joint | +| `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent joint | +| `respectParentPosition` | bool | bool to determine whether this should respect the parent joint position post-initialization | +| `respectParentRotation` | bool | bool to determine whether this should respect the parent joint rotation post-initialization | +| `tags` | Array | Array of strings used to denote tags that can be attributed to the virtual transform | ## Examples ### Arm Attachment Virtual Joint +Example - Anchor for attaching objects, which want to respect the positions/rotation of the parent joints + - **Name**: `"arm_socket"` - **Parent**: Between elbow and wrist (e.g., joint index 18) - **Translation**: `(0.0, 0.1, 0.0)` - **Rotation**: `(0.0, 0.0, 0.0, 1.0)` - **respectParentPosition**: `true` - **respectParentRotation**: `true` -- **Usage**: Anchor for attaching objects, which want to respect the positions/rotation of the parent joints +- **tags**: Array of strings used to denote semantic tags. ### Look At Virtual Joint +Example - Target for runtime look-at behavior (eyes/head alignment) + - **Name**: `"lookAt_target"` - **Parent**: `"head"` joint (e.g., joint index 8) - **Translation**: `(0.0, 0.0, 0.35)` - **Rotation**: `(0.0, 0.0, 0.0, 1.0)` - **respectParentPosition**: `true` - **respectParentRotation**: `true` -- **Usage**: Target for runtime look-at behavior (eyes/head alignment). +- **tags**: Array of strings used to denote semantic tags. ### Sitting Point Virtual Joint +Example - Anchor point for aligning seated positions. + - **Name**: `"sitting_point"` - **Parent**: `"pelvis"` joint (e.g., joint index 0) - **Translation**: `(0.0, 0.0, -0.2)` - **Rotation**: `(0.0, 0.0, 0.0, 1.0)` - **respectParentPosition**: `true` - **respectParentRotation**: `true` -<<<<<<<< Updated upstream:extensions/2.0/Khronos/KHR_character_virtual_joints/README.md -- **Usage**: Anchor point for aligning seated positions. -======== - **tags**: Array of strings used to denote semantic tags. ->>>>>>>> Stashed changes:extensions/2.0/Khronos/KHR_virtual_transforms/README.md - ### Wrist UI Virtual Joint +Example - Anchor point for wrist UI, which may wish to respect the parent joint's position, but not the rotation. + - **Name**: `"wrist_ui_socket"` - **Parent**: `"wrist"` joint (e.g., joint index 19) - **Offset**: `(0.0, .25, 0.0)` - **Rotation**: `(0.0, 0.0, 0.0, 1.0)` - **respectParentPosition**: `true` - **respectParentRotation**: `false` -- **Usage**: Anchor point for wrist UI, which may wish to respect the parent joint's position, but not the rotation. +- **tags**: Array of strings used to denote semantic tags. ## Implementation Notes From de832360f33387f7e85b00480cf2ce0368e997e4 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 8 Sep 2025 21:16:05 -0700 Subject: [PATCH 25/48] Update README.md Update README.md --- .../2.0/Khronos/KHR_virtual_transform/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_virtual_transform/README.md b/extensions/2.0/Khronos/KHR_virtual_transform/README.md index 1194f1964a..3e6e7a1a81 100644 --- a/extensions/2.0/Khronos/KHR_virtual_transform/README.md +++ b/extensions/2.0/Khronos/KHR_virtual_transform/README.md @@ -24,7 +24,7 @@ The `KHR_virtual_transform` extension introduces _virtual transforms_; metadata- In the context of characters, these virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. For other types of models, they can be leveraged for UI attach points, etc. -Virtual joints are defined via an offset transform relative to the parent nodes, and do **not** participate in skinning. If there are multiple parent nodes, the expected behavior is to have it be based on a translation directly between those nodes position-wise. They are evaluated at runtime for behavior logic and procedural animation. +Virtual transforms are defined via an offset transform relative to the parent nodes, and do **not** participate in skinning. If there are multiple parent nodes, the expected behavior is to have it be based on a translation directly between those nodes position-wise. They are evaluated at runtime for behavior logic and procedural animation. This extension is inspired in part by constructs like `lookAt` in VRM and aims to unify such functionality into a generic system usable across multiple glTF-based runtimes. @@ -91,7 +91,7 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t | Property | Type | Description | | ----------------------- | -------- | ------------------------------------------------------------------------------------------- | -| `name` | string | Semantic identifier of the virtual joint | +| `name` | string | Semantic identifier of the virtual transform | | `parentNodes` | Array | Array of indices for nodes in the glTF `nodes[]` array | | `translation` | float[3] | Initialized local offset (X, Y, Z) relative to the parent joint | | `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent joint | @@ -101,7 +101,7 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t ## Examples -### Arm Attachment Virtual Joint +### Arm Attachment Virtual Transform Example - Anchor for attaching objects, which want to respect the positions/rotation of the parent joints @@ -113,7 +113,7 @@ Example - Anchor for attaching objects, which want to respect the positions/rota - **respectParentRotation**: `true` - **tags**: Array of strings used to denote semantic tags. -### Look At Virtual Joint +### Look At Virtual Transform Example - Target for runtime look-at behavior (eyes/head alignment) @@ -125,7 +125,7 @@ Example - Target for runtime look-at behavior (eyes/head alignment) - **respectParentRotation**: `true` - **tags**: Array of strings used to denote semantic tags. -### Sitting Point Virtual Joint +### Sitting Point Virtual Transform Example - Anchor point for aligning seated positions. @@ -137,7 +137,7 @@ Example - Anchor point for aligning seated positions. - **respectParentRotation**: `true` - **tags**: Array of strings used to denote semantic tags. -### Wrist UI Virtual Joint +### Wrist UI Virtual Transform Example - Anchor point for wrist UI, which may wish to respect the parent joint's position, but not the rotation. @@ -151,7 +151,7 @@ Example - Anchor point for wrist UI, which may wish to respect the parent joint' ## Implementation Notes -- Virtual joints should exist only within this extension and **must not overlap with joints used in skinning**. +- Virtual transforms should exist only within this extension and **must not overlap with joints used in skinning**. - Their transformation is computed at runtime by applying the offset to the parent joint’s world transform. - Tools and runtimes may expose these as attachable sockets or semantic retargeting anchors. From 9e54e5177e8595a5e69582665e666c2a89740eb5 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 10 Sep 2025 10:51:40 -0700 Subject: [PATCH 26/48] Update extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md Co-authored-by: Takahiro --- extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md index 73cba586cd..2543e780a3 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md @@ -105,7 +105,7 @@ The `KHR_character_skeleton_biped` extension builds on top of the core glTF 2.0 The joint indices specified in the `joints` dictionary refer directly to elements within the glTF `nodes` array, and should match those used in a valid `skin` structure: - The character mesh should be associated with a `skin`, per [glTF 2.0 Skinning](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#skins). -- The joints listed in this extension must be a subset of the joints defined in `skins[j].joints`. +- The joints listed in this extension must be a subset of the joints defined in `skins[].joints`. This enables runtime engines to extract semantic meaning from joint hierarchies already used for mesh deformation, supporting animation retargeting and character interoperability. From 522371b10229b811535fdb6920adb597934e84e5 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 10 Sep 2025 10:52:03 -0700 Subject: [PATCH 27/48] Update extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md Co-authored-by: Takahiro --- extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md index 2543e780a3..c82710ba24 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md @@ -100,7 +100,7 @@ Each joint name corresponds to a node present in the glTF node hierarchy. The hi ## Relationship to glTF 2.0 Skinning -The `KHR_character_skeleton_biped` extension builds on top of the core glTF 2.0 skinning system. It does **not** introduce new skinning mechanics, but instead annotates which nodes in the existing `skins[j].joints[]` structure correspond to meaningful joints in a developer-defined skeletal rig. +The `KHR_character_skeleton_biped` extension builds on top of the core glTF 2.0 skinning system. It does **not** introduce new skinning mechanics, but instead annotates which nodes in the existing `skins[].joints[]` structure correspond to meaningful joints in a developer-defined skeletal rig. The joint indices specified in the `joints` dictionary refer directly to elements within the glTF `nodes` array, and should match those used in a valid `skin` structure: From e5c010d3423b783c5137727a6cc4e167962430c1 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Sat, 20 Sep 2025 19:43:09 -0700 Subject: [PATCH 28/48] Updates to bindpose, mapping, and virtual transform extension readmes bindpose - switched to per-skin indexing, and an expectation of having a matrix per-joint mapping - switched to a single joint mapping, as multi-joint mapping is going to come in a later phase with more complex methods of retargeting/remapping virtual transform - similarly removed the multiple node parents concept --- .../KHR_character_skeleton_bindpose/README.md | 89 +++++++---- .../KHR_character_skeleton_mapping/README.md | 61 +++---- .../Khronos/KHR_virtual_transform/README.md | 149 ++++++++++++------ 3 files changed, 197 insertions(+), 102 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md index 625152b488..8ebb39c0de 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md @@ -16,31 +16,35 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Requires the extension(s): `KHR_character` ## Overview -**THIS EXTENSION IS VERY MUCH WORK IN PROGRESS** - -The `KHR_character_skeleton_bindpose` extension defines a canonical bind pose for the character's skeleton. This pose serves as a neutral reference that supports animation retargeting, mesh deformation validation, and consistency across toolchains. It is particularly useful when the glTF `skins[].inverseBindMatrices` are insufficient or absent for expressing the true skeletal rest position. +The `KHR_character_skeleton_bindpose` extension defines a canonical bind pose for the character's skeleton. This pose serves as a neutral reference that supports animation retargeting, mesh deformation validation, and consistency across toolchains. The bind pose is defined per-skin and uses the same joint ordering as the skin's joints array for direct mapping and maximum simplicity. ## Extension Schema +This extension is applied to individual skins in the glTF file, providing bind pose data that corresponds directly to the skin's joint array. + ```json { - "extensions": { - "KHR_character_skeleton_bindpose": { - "poseType": "TPose", - "skeleton": 0, - "jointBindPoses": [ - { - "joint": 0, - "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + "skins": [ + { + "joints": [2, 5, 8, 12], + "extensions": { + "KHR_character_skeleton_bindpose": { + "poseType": "TPose", + "bindPoses": [ + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.5, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.5, 0, 1] } + ] } - ] + } } - } + ] } ``` @@ -48,13 +52,33 @@ The `KHR_character_skeleton_bindpose` extension defines a canonical bind pose fo | Property | Type | Description | | -------- | ---- | ----------- | +| `poseType` | string | Enum: `TPose`, `APose`, `Custom`. Declares the character's general pose classification. | +| `bindPoses` | array | List of bind pose matrices corresponding directly to the skin's joints array. Each entry at index i corresponds to the joint at joints[i]. | + +#### bindPoses Array + +Each entry in the `bindPoses` array contains: + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `matrix` | float[16] | Column-major 4x4 matrix defining the joint's bind pose in model space. | + +## Per-Skin Joint Indexing + +The `bindPoses` array uses per-skin joint indexing for maximum simplicity and glTF alignment: + +- **Direct Mapping**: Each entry in the bind pose array corresponds directly to the joint at the same index in the skin's joints array. +- **Simplicity**: No need for extra mapping or referencing—just match the order. +- **Consistency**: This matches how glTF handles skinning weights and inverse bind matrices, making it intuitive for tool and engine implementers. +- **Efficiency**: No redundant data; everything is scoped to the skin and its joints. -| `poseType` | string | Enum: `TPose`, `APose`, `Custom`. Declares the character’s general pose classification. | -| `skeleton` | integer | Index into glTF `skins[]`; defines the joint set this bind pose applies to. | +### Example Mapping -| `jointBindPoses` | array | List of bind pose matrices, each associated with a joint node index. | -| `joint` | integer | Index of the joint node in the glTF `nodes` array. | -| `matrix` | float[16] | Column-major 4x4 matrix defining the joint’s bind pose in model space. | +Given a skin with `"joints": [2, 5, 8, 12]`: +- `bindPoses[0]` corresponds to joint node 2 +- `bindPoses[1]` corresponds to joint node 5 +- `bindPoses[2]` corresponds to joint node 8 +- `bindPoses[3]` corresponds to joint node 12 ## Relationship to glTF 2.0 Skinning @@ -74,9 +98,10 @@ This extension supplements or overrides that mechanism by defining joint rest po ## Implementation Notes -- A joint listed in `jointBindPoses` must exist in the `nodes` array. +- The number of bind poses must match the number of joints in the skin's joints array. - The bind pose matrix must be specified in model space (i.e., world-relative). - This extension can be used in tandem with `skins[].inverseBindMatrices`, but is intended to expose clearer semantic meaning. +- Validation should ensure that bindPoses array length equals joints array length. ## Example @@ -90,20 +115,26 @@ This extension supplements or overrides that mechanism by defining joint rest po "KHR_character_skeleton_biped", "KHR_character_skeleton_bindpose" ], - "extensions": { - "KHR_character_skeleton_bindpose": { - "jointBindPoses": [ - { - "joint": 0, - "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] + "skins": [ + { + "joints": [0, 1, 2, 3], + "extensions": { + "KHR_character_skeleton_bindpose": { + "poseType": "TPose", + "bindPoses": [ + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.5, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.5, 0, 1] } + ] } - ] + } } - } + ] } ``` ## License -This extension specification is licensed under the Khronos Group Extension License. +This extension specification is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md index 2d1fc7823d..402a8450cb 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md @@ -16,19 +16,19 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Requires the extension(s): `KHR_character` Typically used in conjunction with: `KHR_character_skeleton_biped` ## Overview -The `KHR_character_skeleton_mapping` extension provides a mechanism to map a skeleton rig to a reference rig, enabling retargeting and compatibility across different skeleton topologies. This extension is particularly useful for normalizing diverse rig structures across platforms and authoring tools. It provides one-to-one and one-to-many mapping; with the expectation that distributed weights add up to 1.0. +The `KHR_character_skeleton_mapping` extension provides a mechanism to map a skeleton rig to a reference rig, enabling retargeting and compatibility across different skeleton topologies. This extension is particularly useful for normalizing diverse rig structures across platforms and authoring tools. It provides one-to-one mapping for maximum simplicity and compatibility. ## Mapping to Known Standard Rigs In many real-world scenarios, developers must remap an character's native joint structure to a **known, standardized rig**—such as a runtime's internal character model or a predefined specification like VRM's Humanoid rig. -This extension supports such cases by allowing one-to-one or one-to-many weighted mappings between a model’s joints and those of a **target standard rig**. +This extension supports such cases by allowing one-to-one mappings between a model's joints and those of a **target standard rig**. These standard rigs are typically defined by the consuming platform, runtime, or service provider. Each standard rig: @@ -39,7 +39,7 @@ These standard rigs are typically defined by the consuming platform, runtime, or The [VRM 1.0 Humanoid specification](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/humanoid.md) defines a standardized set of joints used across VRM-compatible platforms. -Here’s an example mapping from a custom rig into VRM Humanoid: +Here's an example mapping from a custom rig into VRM Humanoid: ```json { @@ -48,20 +48,20 @@ Here’s an example mapping from a custom rig into VRM Humanoid: "KHR_character_skeleton_mapping": { "skeletalRigMappings": { "vrmHumanoid": { - "myRig_hips": [{ "target": "hips", "weight": 1.0 }], - "myRig_head": [{ "target": "head", "weight": 1.0 }], - "myRig_leftFoot": [ - { "target": "leftFoot", "weight": 0.8 }, - { "target": "leftToeBase", "weight": 0.2 } - ] + "myRig_hips": "hips", + "myRig_head": "head", + "myRig_leftFoot": "leftFoot", + "myRig_rightFoot": "rightFoot", + "myRig_leftHand": "leftHand", + "myRig_rightHand": "rightHand" }, "example_rig": { - "myRig_hips": [{ "target": "hip_bone", "weight": 1.0 }], - "myRig_head": [{ "target": "head_bone", "weight": 1.0 }], - "myRig_leftFoot": [ - { "target": "l_foot_bone", "weight": 0.8 }, - { "target": "l_toe_bone", "weight": 0.2 } - ] + "myRig_hips": "hip_bone", + "myRig_head": "head_bone", + "myRig_leftFoot": "l_foot_bone", + "myRig_rightFoot": "r_foot_bone", + "myRig_leftHand": "l_hand_bone", + "myRig_rightHand": "r_hand_bone" } } } @@ -71,28 +71,29 @@ Here’s an example mapping from a custom rig into VRM Humanoid: In this example: -- `"target"` is a joint name defined by the target standard rig (here, VRM Humanoid, or a hypotheical example_rig system). -- The system using this extension may understand what `"vrmHumanoid"` or `"example_rig"` means (i.e., the joint vocabulary and structure must be pre-declared by the consuming runtime); and if so can leverage the provided joint mappings +- The key is the source joint name from the model's native rig (e.g., `"myRig_hips"`) +- The value is the target joint name defined by the target standard rig (e.g., `"hips"` for VRM Humanoid) +- The system using this extension may understand what `"vrmHumanoid"` or `"example_rig"` means (i.e., the joint vocabulary and structure must be pre-declared by the consuming runtime) ### Breakdown and Lower-Level Properties The structure of the data contained in the extension can be described as a dictionary of dictionaries: -Target Skeleton/Rig Name : Joint Mapping Dictionary (Joint Name : List/Array of objects containing the below properties) +**Target Skeleton/Rig Name** : **Joint Mapping Dictionary** (Source Joint Name : Target Joint Name) -| Property | Type | Description | -| -------- | ------ | -------------------------------------------------------- | -| `target` | string | Name of the joint in the target vocabulary. | -| `weight` | number | Influence of this target. Must sum to 1.0 per joint key. | +Each mapping entry is simply: + +| Key (Source Joint) | Value (Target Joint) | Description | +| ------------------ | -------------------- | -------------------------------------------------------- | +| string | string | Direct mapping from source joint name to target joint name in the target vocabulary | ### Mapping Types -This extension supports both one-to-one and one-to-many mappings (as well as multiple instances of those mapping sets): +This extension supports one-to-one mappings: -- **One-to-one**: A source joint maps directly to a single reference joint with a weight of 1.0. -- **One-to-many**: A source joint influences multiple reference joints, each with a fractional weight (all weights must sum to 1.0). +- **One-to-one**: A source joint maps directly to a single target joint via a simple string value. -This provides flexibility for approximating intermediate or compound joints across rig topologies. +This approach ensures maximum simplicity, compatibility across all engines and tools, and follows glTF's design philosophy of keeping core extensions simple and stable. ## Mapping Registry and Target Namespaces @@ -104,11 +105,13 @@ While this extension does not mandate a central registry, developers are encoura ## Implementation Notes -- Joint names are assumed to refer to nodes in the `nodes` array. +- Source joint names (keys) are assumed to refer to nodes in the glTF `nodes` array. +- Target joint names (values) are defined by the target rig's vocabulary. - The reference rig vocabulary may be shared across engines or projects. - This extension does not modify skinning behavior, but informs tooling and runtime animation retargeting. +- For validation, ensure that all source joint names correspond to valid glTF nodes. ## License -This extension specification is licensed under the Khronos Group Extension License. +This extension specification is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_virtual_transform/README.md b/extensions/2.0/Khronos/KHR_virtual_transform/README.md index 3e6e7a1a81..3a5821b2b4 100644 --- a/extensions/2.0/Khronos/KHR_virtual_transform/README.md +++ b/extensions/2.0/Khronos/KHR_virtual_transform/README.md @@ -16,27 +16,26 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. ## Overview -The `KHR_virtual_transform` extension introduces _virtual transforms_; metadata-informed virtual 'nodes' that exist relative to the a model's skeletal/node hierarchy, but are not nodes themselves and have settings whether to respect the parent nodes position/rotation at runtime. These virtual transforms serve as semantic attachment or control points for applications/systems to utilize; without it needing to be tied to a literal node hierarchy. +The `KHR_virtual_transform` extension introduces _virtual transforms_; metadata-informed virtual 'nodes' that exist relative to a model's skeletal/node hierarchy, but are not nodes themselves and have settings whether to respect the parent node's position/rotation/scale at runtime. These virtual transforms serve as semantic attachment or control points for applications/systems to utilize; without it needing to be tied to a literal node hierarchy. In the context of characters, these virtual transforms serve as semantic attachment or control points for systems like look-at targeting, item equipping, IK hints, and seating positions. For other types of models, they can be leveraged for UI attach points, etc. -Virtual transforms are defined via an offset transform relative to the parent nodes, and do **not** participate in skinning. If there are multiple parent nodes, the expected behavior is to have it be based on a translation directly between those nodes position-wise. They are evaluated at runtime for behavior logic and procedural animation. +Virtual transforms are defined via an offset transform relative to a single parent node, forming a tree structure that matches glTF's core specification. They do **not** participate in skinning and are evaluated at runtime for behavior logic and procedural animation. This extension is inspired in part by constructs like `lookAt` in VRM and aims to unify such functionality into a generic system usable across multiple glTF-based runtimes. -**TODO**: Need to work on proposed logic for interpolation when multiple parent nodes; this likely needs to be some sort of field with established lerp logic types. We could make the stance that it's a pure 50/50 split; but I imagine that might cause some eyebrows to be raised. In general this likely needs a few revs, even past moving it out of the character set of extensions. - ## Use Cases - **Look-at targets** (for head/eye tracking) - **Attachment points** (e.g., a weapon or tool socket) - **Sitting or standing targets** - **Camera or gaze anchors** -- **UI Attach points** - UI attachments that potentially need to not respect the rotation of the parent joints/nodes (e.g. a wrist UI in an AR/VR experience that needs to always be above the ) +- **UI Attach points** - UI attachments that potentially need to maintain consistent size regardless of parent scaling +- **Reference markers** - Debug or measurement points that should be scale-independent ## Schema @@ -46,40 +45,59 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t "KHR_virtual_transform": { "virtualTransforms": [ { - "name": "arm_socket", - "parentNodes": [18, 19], + "name": "right_hand_attach", + "parent": 18, "translation": [0.0, 0.1, 0.0], "rotation": [0.0, 0.0, 0.0, 1.0], + "scale": [1.0, 1.0, 1.0], "respectParentPosition": true, "respectParentRotation": true, - "tags": [] + "respectParentScale": true, + "tags": ["weapon_socket"] }, { "name": "lookAt_target", - "parentNodes": [8], + "parent": 8, "translation": [0.0, 0.0, 0.35], "rotation": [0.0, 0.0, 0.0, 1.0], + "scale": [1.0, 1.0, 1.0], "respectParentPosition": true, "respectParentRotation": true, - "tags": [] + "respectParentScale": true, + "tags": ["look_at"] }, { "name": "sitting_point", - "parentNodes": [0], + "parent": 0, "translation": [0.0, 0.0, -0.2], "rotation": [0.0, 0.0, 0.0, 1.0], + "scale": [1.0, 1.0, 1.0], "respectParentPosition": true, "respectParentRotation": true, - "tags": [] + "respectParentScale": true, + "tags": ["seating"] }, { "name": "wrist_ui", - "parentNodes": [19], + "parent": 19, "translation": [0.0, 0.25, 0.0], "rotation": [0.0, 0.0, 0.0, 1.0], + "scale": [1.0, 1.0, 1.0], "respectParentPosition": true, "respectParentRotation": false, - "tags": [] + "respectParentScale": false, + "tags": ["ui"] + }, + { + "name": "debug_marker", + "parent": 5, + "translation": [0.0, 0.0, 0.0], + "rotation": [0.0, 0.0, 0.0, 1.0], + "scale": [0.1, 0.1, 0.1], + "respectParentPosition": true, + "respectParentRotation": false, + "respectParentScale": false, + "tags": ["debug", "marker"] } ] } @@ -92,70 +110,113 @@ This extension is inspired in part by constructs like `lookAt` in VRM and aims t | Property | Type | Description | | ----------------------- | -------- | ------------------------------------------------------------------------------------------- | | `name` | string | Semantic identifier of the virtual transform | -| `parentNodes` | Array | Array of indices for nodes in the glTF `nodes[]` array | -| `translation` | float[3] | Initialized local offset (X, Y, Z) relative to the parent joint | -| `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent joint | -| `respectParentPosition` | bool | bool to determine whether this should respect the parent joint position post-initialization | -| `respectParentRotation` | bool | bool to determine whether this should respect the parent joint rotation post-initialization | -| `tags` | Array | Array of strings used to denote tags that can be attributed to the virtual transform | +| `parent` | integer | Index of the parent node in the glTF `nodes[]` array | +| `translation` | float[3] | Local offset (X, Y, Z) relative to the parent node. Default: [0.0, 0.0, 0.0] | +| `rotation` | float[4] | Local orientation as quaternion (X, Y, Z, W) relative to the parent node. Default: [0.0, 0.0, 0.0, 1.0] | +| `scale` | float[3] | Local scale (X, Y, Z) relative to the parent node. Default: [1.0, 1.0, 1.0] | +| `respectParentPosition` | boolean | Whether this should respect the parent node position post-initialization. Default: true | +| `respectParentRotation` | boolean | Whether this should respect the parent node rotation post-initialization. Default: true | +| `respectParentScale` | boolean | Whether this should respect the parent node scale post-initialization. Default: true | +| `tags` | string[] | Array of strings used to denote tags that can be attributed to the virtual transform | + +## Hierarchy Structure + +Virtual transforms follow glTF's standard tree hierarchy model: + +- Each virtual transform has exactly one parent node (or none, if it's a root) +- This forms a **tree** structure (no cycles, no nodes with multiple parents) +- The world transform of a virtual transform is computed by recursively multiplying its local transform by its parent's world transform +- This matches the glTF core specification and how most 3D engines and DCC tools operate + +## Transform Calculation + +The world transform of a virtual transform is calculated as: + +1. Start with the virtual transform's local transform (translation, rotation, scale) +2. If `respectParentPosition` is true, apply the parent node's world position +3. If `respectParentRotation` is true, apply the parent node's world rotation +4. If `respectParentScale` is true, apply the parent node's world scale + +This provides complete control over which aspects of the parent's transform affect the virtual transform, enabling use cases such as UI elements that follow position but maintain independent size and orientation. ## Examples -### Arm Attachment Virtual Transform +### Right Hand Attachment Virtual Transform -Example - Anchor for attaching objects, which want to respect the positions/rotation of the parent joints +Example - Anchor for attaching objects, which want to respect all aspects of the parent joint transform -- **Name**: `"arm_socket"` -- **Parent**: Between elbow and wrist (e.g., joint index 18) -- **Translation**: `(0.0, 0.1, 0.0)` -- **Rotation**: `(0.0, 0.0, 0.0, 1.0)` +- **Name**: `"right_hand_attach"` +- **Parent**: Right hand node (e.g., node index 18) +- **Translation**: `[0.0, 0.1, 0.0]` +- **Rotation**: `[0.0, 0.0, 0.0, 1.0]` - **respectParentPosition**: `true` - **respectParentRotation**: `true` -- **tags**: Array of strings used to denote semantic tags. +- **respectParentScale**: `true` +- **tags**: `["weapon_socket"]` ### Look At Virtual Transform Example - Target for runtime look-at behavior (eyes/head alignment) - **Name**: `"lookAt_target"` -- **Parent**: `"head"` joint (e.g., joint index 8) -- **Translation**: `(0.0, 0.0, 0.35)` -- **Rotation**: `(0.0, 0.0, 0.0, 1.0)` +- **Parent**: Head joint (e.g., node index 8) +- **Translation**: `[0.0, 0.0, 0.35]` +- **Rotation**: `[0.0, 0.0, 0.0, 1.0]` - **respectParentPosition**: `true` - **respectParentRotation**: `true` -- **tags**: Array of strings used to denote semantic tags. +- **respectParentScale**: `true` +- **tags**: `["look_at"]` ### Sitting Point Virtual Transform Example - Anchor point for aligning seated positions. - **Name**: `"sitting_point"` -- **Parent**: `"pelvis"` joint (e.g., joint index 0) -- **Translation**: `(0.0, 0.0, -0.2)` -- **Rotation**: `(0.0, 0.0, 0.0, 1.0)` +- **Parent**: Pelvis joint (e.g., node index 0) +- **Translation**: `[0.0, 0.0, -0.2]` +- **Rotation**: `[0.0, 0.0, 0.0, 1.0]` - **respectParentPosition**: `true` - **respectParentRotation**: `true` -- **tags**: Array of strings used to denote semantic tags. +- **respectParentScale**: `true` +- **tags**: `["seating"]` ### Wrist UI Virtual Transform -Example - Anchor point for wrist UI, which may wish to respect the parent joint's position, but not the rotation. +Example - Anchor point for wrist UI, which follows position but maintains independent rotation and size. + +- **Name**: `"wrist_ui"` +- **Parent**: Wrist joint (e.g., node index 19) +- **Translation**: `[0.0, 0.25, 0.0]` +- **Rotation**: `[0.0, 0.0, 0.0, 1.0]` +- **respectParentPosition**: `true` +- **respectParentRotation**: `false` +- **respectParentScale**: `false` +- **tags**: `["ui"]` + +### Debug Marker Virtual Transform + +Example - A debug marker that follows the parent's position but maintains independent orientation and consistent size. -- **Name**: `"wrist_ui_socket"` -- **Parent**: `"wrist"` joint (e.g., joint index 19) -- **Offset**: `(0.0, .25, 0.0)` -- **Rotation**: `(0.0, 0.0, 0.0, 1.0)` +- **Name**: `"debug_marker"` +- **Parent**: Spine joint (e.g., node index 5) +- **Translation**: `[0.0, 0.0, 0.0]` +- **Rotation**: `[0.0, 0.0, 0.0, 1.0]` +- **Scale**: `[0.1, 0.1, 0.1]` (small marker) - **respectParentPosition**: `true` - **respectParentRotation**: `false` -- **tags**: Array of strings used to denote semantic tags. +- **respectParentScale**: `false` (maintains consistent size) +- **tags**: `["debug", "marker"]` ## Implementation Notes - Virtual transforms should exist only within this extension and **must not overlap with joints used in skinning**. -- Their transformation is computed at runtime by applying the offset to the parent joint’s world transform. +- Their transformation is computed at runtime by applying the offset to the parent node's world transform. - Tools and runtimes may expose these as attachable sockets or semantic retargeting anchors. +- The single-parent hierarchy ensures compatibility with all glTF-compliant tools and engines. +- For advanced constraint-based relationships (multiple influences), consider using a dedicated constraint system rather than multiple parents in the scene graph. +- The three `respectParent*` flags provide fine-grained control over transform inheritance, enabling use cases from fully-inherited transforms to completely independent positioning. ## License -This extension is licensed under the Khronos Group Extension License. +This extension is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html From 7994f0ead4240faeb1e4268ddfef1dc7a19c83bd Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Sun, 21 Sep 2025 18:15:14 -0700 Subject: [PATCH 29/48] Initial Draft Schemas Created initial versions of the draft schemas --- .../schema/glTF.KHR_character.schema.json | 11 +++ .../glTF.KHR_character_avatar.schema.json | 22 +++++ .../glTF.KHR_character_expression.schema.json | 40 +++++++++ ...KHR_character_expression_joint.schema.json | 28 ++++++ ...R_character_expression_mapping.schema.json | 28 ++++++ ...aracter_expression_morphtarget.schema.json | 28 ++++++ ...haracter_expression_procedural.schema.json | 28 ++++++ ...R_character_expression_texture.schema.json | 28 ++++++ ...HR_character_skeleton_bindpose.schema.json | 41 +++++++++ ...F.KHR_character_skeleton_biped.schema.json | 26 ++++++ ...KHR_character_skeleton_mapping.schema.json | 26 ++++++ .../primitive.KHR_mesh_annotation.schema.json | 24 +++++ ...KHR_mesh_annotation_renderview.schema.json | 17 ++++ .../glTF.KHR_virtual_transform.schema.json | 90 +++++++++++++++++++ 14 files changed, 437 insertions(+) create mode 100644 extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_expression/schema/glTF.KHR_character_expression.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_expression_joint/schema/KHR_character_expression.KHR_character_expression_joint.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_expression_mapping/schema/KHR_character_expression.KHR_character_expression_mapping.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_expression_morphtarget/schema/KHR_character_expression.KHR_character_expression_morphtarget.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_expression_texture/schema/KHR_character_expression.KHR_character_expression_texture.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_skeleton_biped/schema/glTF.KHR_character_skeleton_biped.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json create mode 100644 extensions/2.0/Khronos/KHR_mesh_annotation/schema/primitive.KHR_mesh_annotation.schema.json create mode 100644 extensions/2.0/Khronos/KHR_mesh_annotation_renderview/schema/KHR_mesh_annotation.KHR_mesh_annotation_renderview.schema.json create mode 100644 extensions/2.0/Khronos/KHR_virtual_transform/schema/glTF.KHR_virtual_transform.schema.json diff --git a/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json new file mode 100644 index 0000000000..04aba33bb1 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character glTF Document Extension", + "type": "object", + "description": "glTF extension for character-specific metadata and properties.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "extensions": { }, + "extras": { } + } +} diff --git a/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json b/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json new file mode 100644 index 0000000000..99f5198f3d --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_avatar glTF Document Extension", + "type": "object", + "description": "glTF extension that designates a glTF asset as representing an avatar.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "sceneIndex": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index of the glTF scene representing the avatar. Used to distinguish the avatar root when multiple scenes exist." + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "sceneIndex" + ] +} diff --git a/extensions/2.0/Khronos/KHR_character_expression/schema/glTF.KHR_character_expression.schema.json b/extensions/2.0/Khronos/KHR_character_expression/schema/glTF.KHR_character_expression.schema.json new file mode 100644 index 0000000000..b95a982a63 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_expression/schema/glTF.KHR_character_expression.schema.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_expression glTF Document Extension", + "type": "object", + "description": "glTF extension that provides a common interface for facial expression animations.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "expressions": { + "type": "array", + "description": "Array of mappings between animation/channels and expression labels.", + "items": { + "type": "object", + "properties": { + "expression": { + "type": "string", + "description": "Expression name this animation contributes to." + }, + "animation": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index into the glTF animations array representing an expression animation." + }, + "extensions": { }, + "extras": { } + }, + "required": ["expression", "animation"], + "additionalProperties": false + }, + "minItems": 1 + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "expressions" + ] +} diff --git a/extensions/2.0/Khronos/KHR_character_expression_joint/schema/KHR_character_expression.KHR_character_expression_joint.schema.json b/extensions/2.0/Khronos/KHR_character_expression_joint/schema/KHR_character_expression.KHR_character_expression_joint.schema.json new file mode 100644 index 0000000000..9eef27fc11 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_expression_joint/schema/KHR_character_expression.KHR_character_expression_joint.schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_expression_joint KHR_character_expression Extension", + "type": "object", + "description": "glTF extension that extends KHR_character_expression to specify joint-based expression animations.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "channels": { + "type": "array", + "description": "Array of animation channel indices that drive joint-based expressions.", + "items": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index of the animation channel in the referenced animation." + }, + "minItems": 1, + "uniqueItems": true + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "channels" + ] +} diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/KHR_character_expression.KHR_character_expression_mapping.schema.json b/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/KHR_character_expression.KHR_character_expression_mapping.schema.json new file mode 100644 index 0000000000..c3f29173f9 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/KHR_character_expression.KHR_character_expression_mapping.schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_expression_mapping KHR_character_expression Extension", + "type": "object", + "description": "glTF extension that extends KHR_character_expression to specify expression mapping information.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "channels": { + "type": "array", + "description": "Array of animation channel indices that drive expression mapping.", + "items": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index of the animation channel in the referenced animation." + }, + "minItems": 1, + "uniqueItems": true + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "channels" + ] +} diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/schema/KHR_character_expression.KHR_character_expression_morphtarget.schema.json b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/schema/KHR_character_expression.KHR_character_expression_morphtarget.schema.json new file mode 100644 index 0000000000..dd0b97a6d3 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/schema/KHR_character_expression.KHR_character_expression_morphtarget.schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_expression_morphtarget KHR_character_expression Extension", + "type": "object", + "description": "glTF extension that extends KHR_character_expression to specify morph target-based expression animations.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "channels": { + "type": "array", + "description": "Array of animation channel indices that drive morph target-based expressions.", + "items": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index of the animation channel in the referenced animation." + }, + "minItems": 1, + "uniqueItems": true + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "channels" + ] +} diff --git a/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json b/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json new file mode 100644 index 0000000000..b46035bc02 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_expression_procedural KHR_character_expression Extension", + "type": "object", + "description": "glTF extension that extends KHR_character_expression to specify procedural expression animations.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "channels": { + "type": "array", + "description": "Array of animation channel indices that drive procedural expressions.", + "items": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index of the animation channel in the referenced animation." + }, + "minItems": 1, + "uniqueItems": true + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "channels" + ] +} diff --git a/extensions/2.0/Khronos/KHR_character_expression_texture/schema/KHR_character_expression.KHR_character_expression_texture.schema.json b/extensions/2.0/Khronos/KHR_character_expression_texture/schema/KHR_character_expression.KHR_character_expression_texture.schema.json new file mode 100644 index 0000000000..e4fff590f7 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_expression_texture/schema/KHR_character_expression.KHR_character_expression_texture.schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_expression_texture KHR_character_expression Extension", + "type": "object", + "description": "glTF extension that extends KHR_character_expression to specify texture-based expression animations.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "channels": { + "type": "array", + "description": "Array of animation channel indices that drive texture-based expressions.", + "items": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index of the animation channel in the referenced animation." + }, + "minItems": 1, + "uniqueItems": true + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "channels" + ] +} diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json new file mode 100644 index 0000000000..d4981583c8 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_skeleton_bindpose glTF Skin Extension", + "type": "object", + "description": "glTF extension that defines a canonical bind pose for the character's skeleton applied to individual skins.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "poseType": { + "type": "string", + "description": "The type of pose this bind pose represents.", + "enum": ["TPose", "APose", "Custom"], + "default": "TPose" + }, + "bindPoses": { + "type": "array", + "description": "Array of bind pose matrices corresponding directly to the skin's joints array. Each entry at index i corresponds to the joint at joints[i].", + "items": { + "type": "object", + "properties": { + "matrix": { + "type": "array", + "description": "Column-major 4x4 matrix defining the joint's bind pose in model space.", + "items": { + "type": "number" + }, + "minItems": 16, + "maxItems": 16 + } + }, + "required": ["matrix"], + "additionalProperties": false + }, + "minItems": 1 + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "bindPoses" + ] +} diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_biped/schema/glTF.KHR_character_skeleton_biped.schema.json b/extensions/2.0/Khronos/KHR_character_skeleton_biped/schema/glTF.KHR_character_skeleton_biped.schema.json new file mode 100644 index 0000000000..df4c5465ae --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_skeleton_biped/schema/glTF.KHR_character_skeleton_biped.schema.json @@ -0,0 +1,26 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_skeleton_biped glTF Document Extension", + "type": "object", + "description": "glTF extension that enables bipedal characters by specifying a canonical set of joints and their hierarchical structure.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "joints": { + "type": "object", + "description": "Mapping from biped joint names to node indices in the glTF file.", + "additionalProperties": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index of the node in the glTF nodes array that represents this joint." + } + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "joints" + ] +} diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json new file mode 100644 index 0000000000..f638341ac4 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json @@ -0,0 +1,26 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_skeleton_mapping glTF Document Extension", + "type": "object", + "description": "glTF extension that provides a mechanism to map a skeleton rig to a reference rig for retargeting and compatibility.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "skeletalRigMappings": { + "type": "object", + "description": "Dictionary of target rig mappings. Each key is a target rig name, each value is a mapping dictionary.", + "additionalProperties": { + "type": "object", + "description": "Joint mapping dictionary. Each key is a source joint name, each value is the target joint name.", + "additionalProperties": { + "type": "string", + "description": "Target joint name in the target rig vocabulary." + } + } + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "skeletalRigMappings" + ] +} diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation/schema/primitive.KHR_mesh_annotation.schema.json b/extensions/2.0/Khronos/KHR_mesh_annotation/schema/primitive.KHR_mesh_annotation.schema.json new file mode 100644 index 0000000000..bdaa439a25 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_mesh_annotation/schema/primitive.KHR_mesh_annotation.schema.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_mesh_annotation glTF Mesh Primitive Extension", + "type": "object", + "description": "glTF extension that enables arbitrary per-mesh metadata annotations at the primitive level.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "tags": { + "type": "array", + "description": "List of free-form labels applicable to this primitive.", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "customData": { + "type": "object", + "description": "Optional freeform object for runtime-specific annotations.", + "additionalProperties": true + }, + "extensions": { }, + "extras": { } + } +} diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/schema/KHR_mesh_annotation.KHR_mesh_annotation_renderview.schema.json b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/schema/KHR_mesh_annotation.KHR_mesh_annotation_renderview.schema.json new file mode 100644 index 0000000000..bf5c6ac2ff --- /dev/null +++ b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/schema/KHR_mesh_annotation.KHR_mesh_annotation_renderview.schema.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_mesh_annotation_renderview KHR_mesh_annotation Extension", + "type": "object", + "description": "glTF extension that provides structured metadata for character mesh primitives related to visibility and render-time behavior.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "renderVisibility": { + "type": "string", + "description": "Controls camera-based visibility.", + "enum": ["always", "firstPersonOnly", "thirdPersonOnly", "never"], + "default": "always" + }, + "extensions": { }, + "extras": { } + } +} diff --git a/extensions/2.0/Khronos/KHR_virtual_transform/schema/glTF.KHR_virtual_transform.schema.json b/extensions/2.0/Khronos/KHR_virtual_transform/schema/glTF.KHR_virtual_transform.schema.json new file mode 100644 index 0000000000..0f44283e40 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_virtual_transform/schema/glTF.KHR_virtual_transform.schema.json @@ -0,0 +1,90 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_virtual_transform glTF Document Extension", + "type": "object", + "description": "glTF extension that introduces virtual transforms - semantic attachment or control points relative to the model's node hierarchy.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "virtualTransforms": { + "type": "array", + "description": "Array of virtual transform objects.", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Semantic identifier of the virtual transform." + }, + "parent": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index of the parent node in the glTF nodes array." + }, + "translation": { + "type": "array", + "description": "Local offset (X, Y, Z) relative to the parent node.", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3, + "default": [0.0, 0.0, 0.0] + }, + "rotation": { + "type": "array", + "description": "Local orientation as quaternion (X, Y, Z, W) relative to the parent node.", + "items": { + "type": "number" + }, + "minItems": 4, + "maxItems": 4, + "default": [0.0, 0.0, 0.0, 1.0] + }, + "scale": { + "type": "array", + "description": "Local scale (X, Y, Z) relative to the parent node.", + "items": { + "type": "number" + }, + "minItems": 3, + "maxItems": 3, + "default": [1.0, 1.0, 1.0] + }, + "respectParentPosition": { + "type": "boolean", + "description": "Whether this should respect the parent node position post-initialization.", + "default": true + }, + "respectParentRotation": { + "type": "boolean", + "description": "Whether this should respect the parent node rotation post-initialization.", + "default": true + }, + "respectParentScale": { + "type": "boolean", + "description": "Whether this should respect the parent node scale post-initialization.", + "default": true + }, + "tags": { + "type": "array", + "description": "Array of strings used to denote tags that can be attributed to the virtual transform.", + "items": { + "type": "string" + } + } + }, + "required": ["name", "parent"], + "additionalProperties": false + }, + "minItems": 1 + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "virtualTransforms" + ] +} From 8a092132dea5feda4e02eff775ae4d06d26b6324 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Sun, 21 Sep 2025 18:50:08 -0700 Subject: [PATCH 30/48] Update khr_mesh_annotation readme Added more description for khr_mesh_annotation's tag and customData fields (and behavior if they're not identified). Also changed the accessibility tag example. --- extensions/2.0/Khronos/KHR_mesh_annotation/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md index a1d48e0680..f95b77d2a6 100644 --- a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md +++ b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md @@ -80,7 +80,7 @@ Used by interaction or accessibility systems to identify meaningful geometry. ### 3. Region Metadata for Accessibility ```json -"tags": ["left_hand"] +"tags": ["accept button", "UI"] ``` This can drive voiceover descriptions, haptics, or visual aids for users with assistive needs. @@ -97,10 +97,11 @@ Allows filtering of optional accessories or togglable cosmetic parts. - Annotations apply at the granularity of `mesh.primitive`, enabling fine control. - Tags are non-authoritative but enable semantic interoperability across runtimes. -- `customData` allows developers to store app-specific structured metadata (e.g., color categories, tracking weights, heatmaps). +- `tags` allows developers to store free-form labels that can be used to identify, enhance, or provide additional context to the primitive (that may or may not be app-specific). If this metadata is not understood by a client, it should be safely ignored with no visual or functional change. +- `customData` allows developers to store app-specific structured metadata (e.g., color categories, tracking weights, heatmaps). If this metadata is not understood by a client, it should be safely ignored with no visual or functional change. - If this extension is not understood by a client, it should be safely ignored with no visual or functional change. ## License -This extension is licensed under the Khronos Group Extension License. +This extension is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html From 99861a37d529fdc7dcd0e4d65fdfc80140c10ba5 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Sun, 21 Sep 2025 19:14:58 -0700 Subject: [PATCH 31/48] Fixed readme typo --- extensions/2.0/Khronos/KHR_mesh_annotation/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md index f95b77d2a6..63908db55d 100644 --- a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md +++ b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md @@ -65,7 +65,7 @@ Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i] | Property | Type | Description | | ------------ | -------- | -------------------------------------------------------------------- | | `tags` | string[] | List of free-form labels applicable to this primitive | -| `customData` | object | Optional freeform object for runtime-specific annotations (optional) | +| `customData` | object | Optional free-form object for runtime-specific annotations (optional) | ## Use Cases & Examples From d2e7ccad85d97067bbc3e7c1ed53f637beb2ea39 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 7 Oct 2025 07:59:32 -0700 Subject: [PATCH 32/48] Addressing bad copy/paste and stale documentation Addressing a bad copy paste/assignment between KHR_character and KHR_character_avatar when generating the schemas that was pointed out during the Character and Avatar TSG working session. --- .../schema/glTF.KHR_character.schema.json | 17 +++++++++++--- .../Khronos/KHR_character_avatar/README.md | 23 ++----------------- .../glTF.KHR_character_avatar.schema.json | 23 +++++++------------ 3 files changed, 24 insertions(+), 39 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json index 04aba33bb1..20c4c9540b 100644 --- a/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json +++ b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json @@ -5,7 +5,18 @@ "description": "glTF extension for character-specific metadata and properties.", "allOf": [ { "$ref": "glTFProperty.schema.json" } ], "properties": { - "extensions": { }, - "extras": { } - } + "sceneIndex": { + "allOf": [ + { + "$ref": "glTFid.schema.json" + } + ], + "description": "Index of the glTF scene representing the avatar. Used to distinguish the avatar root when multiple scenes exist." + }, + "extensions": {}, + "extras": {} + }, + "required": [ + "sceneIndex" + ] } diff --git a/extensions/2.0/Khronos/KHR_character_avatar/README.md b/extensions/2.0/Khronos/KHR_character_avatar/README.md index 80f9264317..9c5302fce2 100644 --- a/extensions/2.0/Khronos/KHR_character_avatar/README.md +++ b/extensions/2.0/Khronos/KHR_character_avatar/README.md @@ -28,33 +28,14 @@ This extension does not define avatar features directly but acts as a root decla This extension is dependent on the KHR_character extension; which defines related functionality pertaining to more generalized characters. -## Extension Schema - -```json -{ - "extensions": { - "KHR_character_avatar": { - "sceneIndex": 0 - } - } -} -``` - -### Properties - -| Property | Type | Description | -| ------------ | ------- | ------------------------------------------------------------------------------------------------------------------ | -| `sceneIndex` | integer | Index of the glTF `scene` representing the avatar. Used to distinguish the avatar root when multiple scenes exist. | - ## Implementation Notes -- `sceneIndex` is required, representing the index of the glTF `scene` corresponding to the avatar. Used to distinguish the avatar root when multiple scenes exist. - Consumers should use this marker as a signal to search for additional avatar-related extensions, including skeletal, expression, and other khronos avatar extensions. -- Support for `KHR_xmp_json_ld` is encouraged to ensure interoperable metadata across tools and runtimes. +- `KHR_xmp_json_ld` is required to ensure interoperable metadata across tools and runtimes. ## Known Implementations ## License -This extension specification is licensed under the Khronos Group Extension License. +This extension specification is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json b/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json index 99f5198f3d..3e6631ef88 100644 --- a/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json +++ b/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json @@ -3,20 +3,13 @@ "title": "KHR_character_avatar glTF Document Extension", "type": "object", "description": "glTF extension that designates a glTF asset as representing an avatar.", - "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "allOf": [ + { + "$ref": "glTFProperty.schema.json" + } + ], "properties": { - "sceneIndex": { - "allOf": [ - { - "$ref": "glTFid.schema.json" - } - ], - "description": "Index of the glTF scene representing the avatar. Used to distinguish the avatar root when multiple scenes exist." - }, - "extensions": { }, - "extras": { } - }, - "required": [ - "sceneIndex" - ] + "extensions": {}, + "extras": {} + } } From f13ade36d416665848573eeb66bd8f006dd1e7a5 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 7 Oct 2025 12:30:09 -0700 Subject: [PATCH 33/48] Minor formatting consistency fixes Realized that the formatting done on some of these areas prettified it in a way that is inconsistent with other extensions in the Khronos repo (new lines around the allOf fields). Fixed this. --- .../schema/glTF.KHR_character.schema.json | 10 +++------- .../schema/glTF.KHR_character_avatar.schema.json | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json index 20c4c9540b..9b2fa0b565 100644 --- a/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json +++ b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json @@ -6,15 +6,11 @@ "allOf": [ { "$ref": "glTFProperty.schema.json" } ], "properties": { "sceneIndex": { - "allOf": [ - { - "$ref": "glTFid.schema.json" - } - ], + "allOf": [{ "$ref": "glTFid.schema.json" }], "description": "Index of the glTF scene representing the avatar. Used to distinguish the avatar root when multiple scenes exist." }, - "extensions": {}, - "extras": {} + "extensions": { }, + "extras": { } }, "required": [ "sceneIndex" diff --git a/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json b/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json index 3e6631ef88..80bfdd4f24 100644 --- a/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json +++ b/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json @@ -3,13 +3,9 @@ "title": "KHR_character_avatar glTF Document Extension", "type": "object", "description": "glTF extension that designates a glTF asset as representing an avatar.", - "allOf": [ - { - "$ref": "glTFProperty.schema.json" - } - ], + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], "properties": { - "extensions": {}, - "extras": {} + "extensions": { }, + "extras": { } } } From c7ae046aae49df744bfaac18c7385269b9aed0b5 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 13 Oct 2025 13:09:54 -0700 Subject: [PATCH 34/48] Fixes to khr_character_expression_mapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Functionally, one-to-many compositions like this are describing how to achieve a particular destination expression, and the way it’s written right now could technically achieve that; but is convoluted. It should be reversed: : { , } It also doesn’t make sense to require them to add up to 1.0, as blendshapes don’t really behave that way (and if anything, the weights should reflect how much they contribute to the expression and the max value they should be). I've made changes to make it clearer, and fixed up the schema (gave it the gltf. prepend and added proper detail as it was really a placeholder before). Following up with fixing up the schemas elsewhere as well. --- .../README.md | 32 ++++++++------ ...R_character_expression_mapping.schema.json | 28 ------------ ...R_character_expression_mapping.schema.json | 44 +++++++++++++++++++ 3 files changed, 63 insertions(+), 41 deletions(-) delete mode 100644 extensions/2.0/Khronos/KHR_character_expression_mapping/schema/KHR_character_expression.KHR_character_expression_mapping.schema.json create mode 100644 extensions/2.0/Khronos/KHR_character_expression_mapping/schema/glTF.KHR_character_expression_mapping.schema.json diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md index 216a0a67b4..834200d51a 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md @@ -16,7 +16,7 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Requires the extension(s): `KHR_character`,`KHR_character_expression` Can be used alongside: `KHR_character_expression_morphtarget`, `KHR_character_expression_joints`, `KHR_character_expression_texture` or other expression sources @@ -46,18 +46,24 @@ Optionally, these expressions may be aligned with industry standards (or an endp "KHR_character_expression_mapping": { "expressionSetMappings": { "example_set_1": { - "smileLeft": [ - { "target": "Smile", "weight": 0.8 }, - { "target": "LeftCheekRaise", "weight": 0.2 } + "Smile": [ + { "source": "smileLeft", "weight": 0.8 }, + { "source": "smileRight", "weight": 0.8 }, ], - "jawOpen": [{ "target": "MouthOpen", "weight": 1.0 }] + "LeftCheekRaise": [ + { "source": "smileLeft", "weight": 0.2 } + ], + "MouthOpen": [{ "source": "jawOpen", "weight": 1.0 }] }, "example_set_2": { - "smileLeft": [ - { "target": "smile_small", "weight": 0.2 }, - { "target": "left_dimple", "weight": 0.8 } + "smile_small": [ + { "source": "smileLeft", "weight": 0.2 } + { "source": "smileRight", "weight": 0.2 } + ], + "left_dimple": [ + { "source": "smileLeft", "weight": 0.8 } ], - "jawOpen": [{ "target": "mouth_open", "weight": 1.0 }] + "mouth_open": [{ "source": "jawOpen", "weight": 1.0 }] } } } @@ -72,14 +78,14 @@ Target Expression Set Name : Expression Mapping Dictionary (Expression Name : Li | Property | Type | Description | | -------- | ------ | ------------------------------------------------------------- | -| `target` | string | Name of the expression in the target vocabulary. | -| `weight` | number | Influence of this target. Must sum to 1.0 per expression key. | +| `source` | string | Name of the source expression in the model. | +| `weight` | number | Relative influence of this source expression on the target. Weights represent the proportional contribution needed to achieve the desired target result and do not need to sum to any specific value. | ### Mapping Types This extension supports both one-to-one and one-to-many mappings (as well as multiple instances of those mapping sets): -- **One-to-one**: An expression maps directly to a single reference vocabulary term with weight 1.0. +- **One-to-one**: An expression maps directly to a single reference vocabulary term with a proportional weight. - **One-to-many**: An expression is composed from multiple reference terms, blended using assigned weights. This allows developers to bridge between custom expression sets and shared vocabularies. @@ -92,5 +98,5 @@ This allows developers to bridge between custom expression sets and shared vocab ## License -This extension specification is licensed under the Khronos Group Extension License. +This extension specification is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/KHR_character_expression.KHR_character_expression_mapping.schema.json b/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/KHR_character_expression.KHR_character_expression_mapping.schema.json deleted file mode 100644 index c3f29173f9..0000000000 --- a/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/KHR_character_expression.KHR_character_expression_mapping.schema.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema", - "title": "KHR_character_expression_mapping KHR_character_expression Extension", - "type": "object", - "description": "glTF extension that extends KHR_character_expression to specify expression mapping information.", - "allOf": [ { "$ref": "glTFProperty.schema.json" } ], - "properties": { - "channels": { - "type": "array", - "description": "Array of animation channel indices that drive expression mapping.", - "items": { - "allOf": [ - { - "$ref": "glTFid.schema.json" - } - ], - "description": "Index of the animation channel in the referenced animation." - }, - "minItems": 1, - "uniqueItems": true - }, - "extensions": { }, - "extras": { } - }, - "required": [ - "channels" - ] -} diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/glTF.KHR_character_expression_mapping.schema.json b/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/glTF.KHR_character_expression_mapping.schema.json new file mode 100644 index 0000000000..245d1af711 --- /dev/null +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/glTF.KHR_character_expression_mapping.schema.json @@ -0,0 +1,44 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "title": "KHR_character_expression_mapping glTF Document Extension", + "type": "object", + "description": "glTF extension that enables encoding multiple expression set mappings, mapping source expressions present in the model to target expressions that a runtime/endpoint understands.", + "allOf": [ { "$ref": "glTFProperty.schema.json" } ], + "properties": { + "expressionSetMappings": { + "type": "object", + "description": "Dictionary of expression set mappings, where each key is a target expression set name.", + "additionalProperties": { + "type": "object", + "description": "Expression mapping dictionary where each key is a target expression name and each value is an array of source expression mappings.", + "additionalProperties": { + "type": "array", + "description": "Array of source expression mappings that contribute to the target expression.", + "items": { + "type": "object", + "properties": { + "source": { + "type": "string", + "description": "Name of the source expression in the model." + }, + "weight": { + "type": "number", + "description": "Relative influence of this source expression on the target. Weights represent the proportional contribution needed to achieve the desired target result." + } + }, + "required": [ + "source", + "weight" + ] + }, + "minItems": 1 + } + } + }, + "extensions": { }, + "extras": { } + }, + "required": [ + "expressionSetMappings" + ] +} From 53935f5fddbeaf311f05b51a9e45de438e340beb Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Thu, 16 Oct 2025 09:37:12 -0700 Subject: [PATCH 35/48] Change KHR_character_skeleton_biped README to be clearer Realized some of the verbiage on this has led to some misunderstandings when reading the proposal. I've added some context above the example schema as well as rephrased the first section to make it less confusing; sorry for the churn! --- .../Khronos/KHR_character_skeleton_biped/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md index c82710ba24..3011cdeb6d 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md @@ -16,19 +16,21 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Requires the extension(s): `KHR_character` ## Overview **THIS EXTENSION IS VERY MUCH WORK IN PROGRESS** -The `KHR_character_skeleton_biped` extension enables bipedal characters. Like with other character extensions, its presence represents the data contract that the model itself is a bipedal character model. This extension enables clarifying what joints are for retargeting and compatibility across tools and platforms by specifying a canonical set of joints and their hierarchical structure. +The `KHR_character_skeleton_biped` extension represents a data contract between the model and the environment using the model that the model is a bipedal character model. -This extension does not modify the glTF skinning or animation system, but instead annotates the character’s node hierarchy to indicate which nodes represent canonical joints in a bipedal skeleton. +This extension does not modify the glTF skinning or animation system, but instead creates a top-level mapping of the named joints of its skeletal structure to the nodes they correspond to in the node hierarchy. ## Extension Schema Example +NOTE that the below is an example of what the extension might contain, and is not representative of a Khronos-backed skeletal vocabulary. + ```json { "extensions": { @@ -119,7 +121,7 @@ That extension supports weighted joint translation and enables cleaner separatio This extension currently avoids defining any required or default biped joint hierarchy. -> **Why?** +> **Why?** > Standardizing on a single joint hierarchy would inadvertently lock the majority of developers into a single rig structure, limiting flexibility for studios and tools that use different conventions. Instead, this extension enables **declarative labeling** of a bipedal skeleton using your rig's native hierarchy, and encourages semantic interoperability through mapping via the `KHR_character_skeleton_mapping` extension. @@ -138,5 +140,5 @@ None, TBD ## License -This extension specification is licensed under the Khronos Group Extension License. +This extension specification is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html From df66d5f62772b6a21cd035bf2fce888f68484a9b Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 10 Dec 2025 13:02:41 -0800 Subject: [PATCH 36/48] Fixing KHR_character_expression_morphtarget inconsistencies Addressing the issues 0b5vr pointed out --- .../KHR_character_expression_morphtarget/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md index 4982d981f1..c4b4473e6f 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md @@ -50,7 +50,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp "expression": "smile", "animation": 0, "extensions": { - "KHR_character_expressions_morphtarget": { + "KHR_character_expression_morphtarget": { "channels": [0] } } @@ -59,7 +59,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp "expression": "frown", "animation": 1, "extensions": { - "KHR_character_expressions_morphtarget": { + "KHR_character_expression_morphtarget": { "channels": [0] } } @@ -74,7 +74,7 @@ Optionally, these expressions may be aligned with industry standards (or an endp | Property | Type | Description | | --------- | ------- | ------------------------------------------ | -| `channel` | integet | Index representing the `"weights"` channel | +| `channel` | integer | Index representing the `"weights"` channel | ## Animation Integration (Expressions Tab Recommendation) @@ -124,7 +124,7 @@ All morph target expressions should be driven using standard glTF animation chan "expression": "smile", "animation": 0, "extensions": { - "KHR_character_expressions_morphtarget": { + "KHR_character_expression_morphtarget": { "channels": [0] } } @@ -133,7 +133,7 @@ All morph target expressions should be driven using standard glTF animation chan "expression": "frown", "animation": 1, "extensions": { - "KHR_character_expressions_morphtarget": { + "KHR_character_expression_morphtarget": { "channels": [0] } } From 1812744e7efea653ed09bdc7b2b2853794b32c97 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 10 Dec 2025 13:08:07 -0800 Subject: [PATCH 37/48] Delaying KHR_character_avatar until we have more specific use-cases. RE: https://github.com/KhronosGroup/glTF/pull/2512#issuecomment-3590408185 --- .../Khronos/KHR_character_avatar/README.md | 41 ------------------- .../glTF.KHR_character_avatar.schema.json | 11 ----- 2 files changed, 52 deletions(-) delete mode 100644 extensions/2.0/Khronos/KHR_character_avatar/README.md delete mode 100644 extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json diff --git a/extensions/2.0/Khronos/KHR_character_avatar/README.md b/extensions/2.0/Khronos/KHR_character_avatar/README.md deleted file mode 100644 index 9c5302fce2..0000000000 --- a/extensions/2.0/Khronos/KHR_character_avatar/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# KHR_character_avatar - -## Contributors - -- Ken Jakubzak, Meta -- Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire -- Shinnosuke Iwaki / VirtualCast, Inc. -- 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor -- Nick Burkard, Meta - -## Status - -**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. - -## Dependencies - -Written against the glTF 2.0 specification. - -Requires the extension(s): `KHR_xmp_json_ld`, `KHR_character` - -## Overview - -The `KHR_character_avatar` extension designates a glTF asset as representing an avatar. This top-level marker enables tools and runtimes to interpret the asset as containing avatar-specific content such as rigging, blendshapes, animation retargeting, or metadata. - -This extension does not define avatar features directly but acts as a root declaration that avatar-related extensions may be present, and that consumers should treat the asset using avatar-specific logic and pipelines. It's part of the wider set of KHR character and avatar extensions that are meant to be building blocks to represent a contract stating functionality and data requirements between a given model and an endpoint. - -This extension is dependent on the KHR_character extension; which defines related functionality pertaining to more generalized characters. - -## Implementation Notes - -- Consumers should use this marker as a signal to search for additional avatar-related extensions, including skeletal, expression, and other khronos avatar extensions. -- `KHR_xmp_json_ld` is required to ensure interoperable metadata across tools and runtimes. - -## Known Implementations - -## License - -This extension specification is licensed under the Khronos Group Extension License. -See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json b/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json deleted file mode 100644 index 80bfdd4f24..0000000000 --- a/extensions/2.0/Khronos/KHR_character_avatar/schema/glTF.KHR_character_avatar.schema.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema", - "title": "KHR_character_avatar glTF Document Extension", - "type": "object", - "description": "glTF extension that designates a glTF asset as representing an avatar.", - "allOf": [ { "$ref": "glTFProperty.schema.json" } ], - "properties": { - "extensions": { }, - "extras": { } - } -} From 3e4bff57dc98e8bb173dde871c239b5fbe6a59b5 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 10 Dec 2025 13:08:40 -0800 Subject: [PATCH 38/48] Delaying KHR_mesh_annotation Delaying due to identifying whether we want to utilize and recommend EXT_structural_metadata for this purpose. If not we'd likely iterate on extensions with an upcoming LOD/Renderview extension set proposal --- .../2.0/Khronos/KHR_mesh_annotation/README.md | 107 ------------------ .../primitive.KHR_mesh_annotation.schema.json | 24 ---- 2 files changed, 131 deletions(-) delete mode 100644 extensions/2.0/Khronos/KHR_mesh_annotation/README.md delete mode 100644 extensions/2.0/Khronos/KHR_mesh_annotation/schema/primitive.KHR_mesh_annotation.schema.json diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation/README.md deleted file mode 100644 index 63908db55d..0000000000 --- a/extensions/2.0/Khronos/KHR_mesh_annotation/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# KHR_mesh_annotation - -### TODO - REFACTOR and potentially consolidate with KHR_mesh_annotation_rendering - -## Contributors - -- Ken Jakubzak, Meta -- Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire -- Shinnosuke Iwaki / VirtualCast, Inc. -- 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor -- Nick Burkard, Meta - -## Status - -**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. - -## Dependencies - -Written against the glTF 2.0 specification. -Can be used alongside rendering-related extensions. - -## Overview - -The `KHR_mesh_annotation` extension enables arbitrary per-mesh metadata annotations. This provides a generalized way for creators and tools to semantically tag portions of geometry for gameplay, rendering, accessibility, customization, or runtime logic. - -Examples include: - -- Indicating occlusion, hit zones, body regions, or cosmetics -- Tagging subregions with gameplay affordances (e.g., "touchable", "selectable") -- Supporting accessibility metadata (e.g., limb representation for low-vision aid) -- Facilitating layered rendering systems or shadow pass rules - -## Motivation - -This was thought of as part of the avatar/character extension proposals; as character models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets, or attribute specific information about them (with it beiong on a per-primitive basis; as each primitive can be a different entity entirely). - -## Schema - -Annotations are attached at the **primitive level** (i.e., a `mesh.primitives[i]`), and stored in the `KHR_mesh_annotation` extension: - -```json -{ - "meshes": [ - { - "primitives": [ - { - "attributes": { ... }, - "extensions": { - "KHR_mesh_annotation": { - "tags": ["eyewear", "selectable"], - "customData": { } - } - } - } - ] - } - ] -} -``` - -### Properties - -| Property | Type | Description | -| ------------ | -------- | -------------------------------------------------------------------- | -| `tags` | string[] | List of free-form labels applicable to this primitive | -| `customData` | object | Optional free-form object for runtime-specific annotations (optional) | - -## Use Cases & Examples - -### 2. Touch Targets - -```json -"tags": ["touchable", "interactionZone"] -``` - -Used by interaction or accessibility systems to identify meaningful geometry. - -### 3. Region Metadata for Accessibility - -```json -"tags": ["accept button", "UI"] -``` - -This can drive voiceover descriptions, haptics, or visual aids for users with assistive needs. - -### 4. Selectable Cosmetic Submeshes - -```json -"tags": ["eyewear", "customizable"] -``` - -Allows filtering of optional accessories or togglable cosmetic parts. - -## Implementation Notes - -- Annotations apply at the granularity of `mesh.primitive`, enabling fine control. -- Tags are non-authoritative but enable semantic interoperability across runtimes. -- `tags` allows developers to store free-form labels that can be used to identify, enhance, or provide additional context to the primitive (that may or may not be app-specific). If this metadata is not understood by a client, it should be safely ignored with no visual or functional change. -- `customData` allows developers to store app-specific structured metadata (e.g., color categories, tracking weights, heatmaps). If this metadata is not understood by a client, it should be safely ignored with no visual or functional change. -- If this extension is not understood by a client, it should be safely ignored with no visual or functional change. - -## License - -This extension is licensed under the Khronos Group Extension License. -See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation/schema/primitive.KHR_mesh_annotation.schema.json b/extensions/2.0/Khronos/KHR_mesh_annotation/schema/primitive.KHR_mesh_annotation.schema.json deleted file mode 100644 index bdaa439a25..0000000000 --- a/extensions/2.0/Khronos/KHR_mesh_annotation/schema/primitive.KHR_mesh_annotation.schema.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema", - "title": "KHR_mesh_annotation glTF Mesh Primitive Extension", - "type": "object", - "description": "glTF extension that enables arbitrary per-mesh metadata annotations at the primitive level.", - "allOf": [ { "$ref": "glTFProperty.schema.json" } ], - "properties": { - "tags": { - "type": "array", - "description": "List of free-form labels applicable to this primitive.", - "items": { - "type": "string" - }, - "uniqueItems": true - }, - "customData": { - "type": "object", - "description": "Optional freeform object for runtime-specific annotations.", - "additionalProperties": true - }, - "extensions": { }, - "extras": { } - } -} From 8caa03010749cbfc8e179d50918535345493c83f Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 10 Dec 2025 13:09:20 -0800 Subject: [PATCH 39/48] Delaying KHR_mesh_annotation_renderview https://github.com/KhronosGroup/glTF/pull/2512#issuecomment-3590408185 Delaying and will add to the above-mentioned LOD/Renderview extension set proposal we'll be iterating on in the future. --- .../KHR_mesh_annotation_renderview/README.md | 108 ------------------ ...KHR_mesh_annotation_renderview.schema.json | 17 --- 2 files changed, 125 deletions(-) delete mode 100644 extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md delete mode 100644 extensions/2.0/Khronos/KHR_mesh_annotation_renderview/schema/KHR_mesh_annotation.KHR_mesh_annotation_renderview.schema.json diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md deleted file mode 100644 index 5f62e88e6a..0000000000 --- a/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/README.md +++ /dev/null @@ -1,108 +0,0 @@ -# KHR_mesh_annotation_renderview - -## Contributors - -- Ken Jakubzak, Meta -- Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire -- Shinnosuke Iwaki / VirtualCast, Inc. -- 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor -- Nick Burkard, Meta - -## Status - -**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. - -## Dependencies - -Written against the glTF 2.0 specification. - -## Overview - -The `KHR_mesh_annotation_renderview` extension provides structured metadata for character mesh primitives related to **visibility and render-time behavior**. It complements the core glTF material and LOD systems by exposing semantic visibility rules such as “first-person only” and “always visible”. - -This extension is intended to support use cases such as hiding certain parts of an character (like head or hair) in first-person mode, or marking components that must always be rendered (e.g., eyes) - -This was thought of as part of the avatar/character extension proposals; as character models often contain complex geometry with overlapping purposes (e.g. hair, clothing, limbs, devices, accessories). Many applications need to reason about specific mesh subsets, or attribute specific information about them (with it beiong on a per-primitive basis; as each primitive can be a different entity entirely). Enabling visibility on a per-node basis would result in downchain nodes being disabled when it's not intended/desired; having a granular setting for this allows for more flexibility. - -## Use Cases - -- First-person camera hiding for head/hair geometry or other geometry -- Denoting when there's a completely different alternate mesh for one perspective versus the other - - -## Extension Schema - -This extension is defined per `mesh.primitive`, allowing fine-grained render behavior control. - -```json -{ - "meshes": [ - { - "primitives": [ - { - "attributes": { ... }, - "extensions": { - "KHR_mesh_annotation": { - "tags": ["eyewear", "selectable"], - "customData": { }, - "extensions": { - "KHR_mesh_annotation_renderview": { - "renderVisibility": "firstPersonOnly" - } - } - } - } - } - ] - } - ] -} -``` - -### Properties - -| Property | Type | Description | -|------------------|-------------|-----------------------------------------------------------------------------| -| `renderVisibility` | string | Controls camera-based visibility. Enum: `"always"` | `"firstPersonOnly"` | `"thirdPersonOnly"` | `"never"` | - -## Recommended Usage Patterns - -### First-Person Hiding - -```json -"renderVisibility": "thirdPersonOnly" -``` - -Used to hide geometry (e.g., head, hair, hats) in first-person modes to prevent obstruction. - -### First-Person Hiding - -```json -"renderVisibility": "firstPersonOnly" -``` - -Used to hide geometry (e.g. alternate first-person meshes or meshes containing more detail more relevant to first-person modes) in third-person mode. - -### Always-Visible Elements - -```json -"renderVisibility": "always" -``` - -Used for elements like top meshes that should always remain active regardless of view or culling. - -## Implementation Notes - -These properties have no effect unless supported by the runtime. - -Runtimes may choose to ignore renderVisibility settings if it directly causes downchain issues with their experiences (or a generalized incompatibility). In this case, our recommendation for -those runtimes or tools is to take these settings into account in some capacity if implementing their own mesh-culling logic for a given model. Of course given different uses of a model, your mileage may vary with this. For example, if used with a character in an experience that has a different camera perspective than what the original content creator thought of when baking the asset; it's up to the developer to determine what's more important (respecting the render visibility setting or the continuity of said experience). - -**Considerations for Cameras** There is a world where there's an extension that provides suggested virtual camera transforms in conjunction with this set of visibility settings; but that would likely be a follow-up extension on top of this, which would then (as noted above) still be something that would need be be handled as recommendation rather than absolute. - -## License - -This extension is licensed under the Khronos Group Extension License. -See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/schema/KHR_mesh_annotation.KHR_mesh_annotation_renderview.schema.json b/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/schema/KHR_mesh_annotation.KHR_mesh_annotation_renderview.schema.json deleted file mode 100644 index bf5c6ac2ff..0000000000 --- a/extensions/2.0/Khronos/KHR_mesh_annotation_renderview/schema/KHR_mesh_annotation.KHR_mesh_annotation_renderview.schema.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema", - "title": "KHR_mesh_annotation_renderview KHR_mesh_annotation Extension", - "type": "object", - "description": "glTF extension that provides structured metadata for character mesh primitives related to visibility and render-time behavior.", - "allOf": [ { "$ref": "glTFProperty.schema.json" } ], - "properties": { - "renderVisibility": { - "type": "string", - "description": "Controls camera-based visibility.", - "enum": ["always", "firstPersonOnly", "thirdPersonOnly", "never"], - "default": "always" - }, - "extensions": { }, - "extras": { } - } -} From 1e93bfa1243e01f8e40494c935a38c80c8595750 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Tue, 16 Dec 2025 23:02:00 -0800 Subject: [PATCH 40/48] Delaying KHR_character_skeleton_biped --- .../KHR_character_skeleton_biped/README.md | 144 ------------------ ...F.KHR_character_skeleton_biped.schema.json | 26 ---- 2 files changed, 170 deletions(-) delete mode 100644 extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md delete mode 100644 extensions/2.0/Khronos/KHR_character_skeleton_biped/schema/glTF.KHR_character_skeleton_biped.schema.json diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md deleted file mode 100644 index 3011cdeb6d..0000000000 --- a/extensions/2.0/Khronos/KHR_character_skeleton_biped/README.md +++ /dev/null @@ -1,144 +0,0 @@ -# KHR_character_skeleton_biped - -## Contributors - -- Ken Jakubzak, Meta -- Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire -- Shinnosuke Iwaki / VirtualCast, Inc. -- 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor -- Nick Burkard, Meta - -## Status - -**Draft** – This extension is not yet ratified by the Khronos Group and is subject to change. - -## Dependencies - -Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character` - -## Overview - -**THIS EXTENSION IS VERY MUCH WORK IN PROGRESS** - -The `KHR_character_skeleton_biped` extension represents a data contract between the model and the environment using the model that the model is a bipedal character model. - -This extension does not modify the glTF skinning or animation system, but instead creates a top-level mapping of the named joints of its skeletal structure to the nodes they correspond to in the node hierarchy. - -## Extension Schema Example - -NOTE that the below is an example of what the extension might contain, and is not representative of a Khronos-backed skeletal vocabulary. - -```json -{ - "extensions": { - "KHR_character_skeleton_biped": { - "joints": { - "hips": 0, - "spine": 1, - "chest": 2, - "neck": 3, - "head": 4, - "leftUpperLeg": 5, - "leftLowerLeg": 6, - "leftFoot": 7, - "rightUpperLeg": 8, - "rightLowerLeg": 9, - "rightFoot": 10, - "leftUpperArm": 11, - "leftLowerArm": 12, - "leftHand": 13, - "rightUpperArm": 14, - "rightLowerArm": 15, - "rightHand": 16 - } - } - } -} -``` - -### Properties - -| Property | Type | Description | -| -------- | ------ | ---------------------------------------------------------------- | -| `joints` | object | Mapping from biped joint names to node indices in the glTF file. | - -Each joint name corresponds to a node present in the glTF node hierarchy. The hierarchy as it exists then informs the skeletal hierarchy for parsing purposes. - -## Example - -```json -{ - "asset": { - "version": "2.0" - }, - "nodes": [ - { "name": "Hips" }, - { "name": "Spine", "parent": 0 }, - { "name": "Chest", "parent": 1 }, - { "name": "Neck", "parent": 2 }, - { "name": "Head", "parent": 3 }, - ... - ], - "extensionsUsed": [ - "KHR_character", - "KHR_character_skeleton_biped" - ], - "extensions": { - "KHR_character_skeleton_biped": { - "joints": { - "hips": 0, - "spine": 1, - "chest": 2, - "neck": 3, - "head": 4 - } - } - } -} -``` - -## Relationship to glTF 2.0 Skinning - -The `KHR_character_skeleton_biped` extension builds on top of the core glTF 2.0 skinning system. It does **not** introduce new skinning mechanics, but instead annotates which nodes in the existing `skins[].joints[]` structure correspond to meaningful joints in a developer-defined skeletal rig. - -The joint indices specified in the `joints` dictionary refer directly to elements within the glTF `nodes` array, and should match those used in a valid `skin` structure: - -- The character mesh should be associated with a `skin`, per [glTF 2.0 Skinning](https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#skins). -- The joints listed in this extension must be a subset of the joints defined in `skins[].joints`. - -This enables runtime engines to extract semantic meaning from joint hierarchies already used for mesh deformation, supporting animation retargeting and character interoperability. - -## Skeletal Mapping Support - -Rather than define mapping logic directly in this extension, developers should use the [`KHR_character_skeleton_mapping`](./KHR_character_skeleton_mapping_README.md) extension in conjunction with this one for any one-to-one or one-to-many joint remapping between different rig topologies. - -That extension supports weighted joint translation and enables cleaner separation between semantic labeling (this extension) and rig interoperability (mapping). - -## Skeleton Standardization (In Progress) - -This extension currently avoids defining any required or default biped joint hierarchy. - -> **Why?** -> Standardizing on a single joint hierarchy would inadvertently lock the majority of developers into a single rig structure, limiting flexibility for studios and tools that use different conventions. - -Instead, this extension enables **declarative labeling** of a bipedal skeleton using your rig's native hierarchy, and encourages semantic interoperability through mapping via the `KHR_character_skeleton_mapping` extension. - -As the ecosystem matures, guidance or profiles may emerge for common structures—but this extension deliberately avoids enforcing that at this time. - -## Implementation Notes - -- This extension is non-destructive and overlays semantic information atop the existing glTF node hierarchy. -- Tools can use this extension to retarget animation between characters, align expressions, or validate rigging consistency. -- The specified joint indices must form a valid hierarchy rooted at a common ancestor (usually `hips`). - -## Known Implementations - -None, TBD - -## License - -This extension specification is licensed under the Khronos Group Extension License. -See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_biped/schema/glTF.KHR_character_skeleton_biped.schema.json b/extensions/2.0/Khronos/KHR_character_skeleton_biped/schema/glTF.KHR_character_skeleton_biped.schema.json deleted file mode 100644 index df4c5465ae..0000000000 --- a/extensions/2.0/Khronos/KHR_character_skeleton_biped/schema/glTF.KHR_character_skeleton_biped.schema.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema", - "title": "KHR_character_skeleton_biped glTF Document Extension", - "type": "object", - "description": "glTF extension that enables bipedal characters by specifying a canonical set of joints and their hierarchical structure.", - "allOf": [ { "$ref": "glTFProperty.schema.json" } ], - "properties": { - "joints": { - "type": "object", - "description": "Mapping from biped joint names to node indices in the glTF file.", - "additionalProperties": { - "allOf": [ - { - "$ref": "glTFid.schema.json" - } - ], - "description": "Index of the node in the glTF nodes array that represents this joint." - } - }, - "extensions": { }, - "extras": { } - }, - "required": [ - "joints" - ] -} From 56868be463e24472308fcb284d1b0019154fce6c Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 17 Dec 2025 00:01:19 -0800 Subject: [PATCH 41/48] Updated KHR_character_expression_morphtarget to explicitly depend on KHR_animation_pointer Based on 0b5vr's feedback, it became more obvious that we should have this extension rely on KHR_animation_pointer so we could animation explicit weights indices rather than the whole property. I've updated the README to reflect this. --- .../README.md | 143 +++++++++++++++++- 1 file changed, 140 insertions(+), 3 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md index c4b4473e6f..53a23ed341 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md @@ -16,10 +16,12 @@ ## Dependencies -Written against the glTF 2.0 specification. -Requires the extension(s): `KHR_character`,`KHR_character_expression` +Written against the glTF 2.0 specification. +Requires the extension(s): `KHR_character`, `KHR_character_expression`, `KHR_animation_pointer` Used in conjunction with: `KHR_character_expression_mapping` +> **Note:** This extension explicitly requires `KHR_animation_pointer`. Implementations **MUST** support `KHR_animation_pointer` to use this extension. The `KHR_animation_pointer` extension enables animation of individual morph target weights via JSON pointers, which is essential for granular expression control. + ## Overview The `KHR_character_expression_morphtarget` extension provides semantic bindings between character expressions and specific morph target indices in a glTF mesh. These mappings enable higher-level expression control systems to reference the correct blendshapes when driving facial animation using glTF animation channels. @@ -111,6 +113,141 @@ All morph target expressions should be driven using standard glTF animation chan - Each element of the `weights` array corresponds to one morph target on the associated mesh primitive. - Expression systems should coordinate with these indices using the bindings declared by this extension. +### Integration with KHR_animation_pointer + +For advanced animation control of morph target weights, implementations should use the [`KHR_animation_pointer`](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_animation_pointer) extension. This provides a standardized mechanism for animating weights via JSON pointers. + +As defined in the [glTF Object Model](https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/ObjectModel.adoc#core-pointers), the following pointer templates are supported for morph target weights: + +| Pointer | Type | Description | +| ------- | ---- | ----------- | +| `/nodes/{}/weights` | `float[]` | Animate all morph target weights on a node simultaneously | +| `/nodes/{}/weights/{}` | `float` | Animate a specific morph target weight by index | + +Where `{}` is replaced with the corresponding array element index (e.g., `/nodes/0/weights` or `/nodes/0/weights/2`). + +### Example: Animating All Weights on a Node + +This example animates all morph target weights on a node using the `/nodes/i/weights` pointer: + +```json +{ + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "path": "pointer", + "extensions": { + "KHR_animation_pointer": { + "pointer": "/nodes/0/weights" + } + } + } + } + ], + "samplers": [ + { + "input": 0, + "output": 1, + "interpolation": "LINEAR" + } + ] + } + ] +} +``` + +### Example: Animating a Specific Weight Index + +For more granular control, you can animate individual morph target weights using the `/nodes/i/weights/j` pointer. This is particularly useful when you want to animate a single expression without affecting other morph targets: + +```json +{ + "animations": [ + { + "channels": [ + { + "sampler": 0, + "target": { + "path": "pointer", + "extensions": { + "KHR_animation_pointer": { + "pointer": "/nodes/0/weights/2" + } + } + } + } + ], + "samplers": [ + { + "input": 0, + "output": 1, + "interpolation": "STEP" + } + ] + } + ] +} +``` + +In this example, only the morph target at index 2 (e.g., `blinkLeft`) is animated, while other weights remain unchanged. + +### Example: Animating Multiple Specific Weights + +To animate multiple specific morph targets independently (e.g., left and right blinks with different timing): + +```json +{ + "animations": [ + { + "name": "blink", + "channels": [ + { + "sampler": 0, + "target": { + "path": "pointer", + "extensions": { + "KHR_animation_pointer": { + "pointer": "/nodes/0/weights/2" + } + } + } + }, + { + "sampler": 1, + "target": { + "path": "pointer", + "extensions": { + "KHR_animation_pointer": { + "pointer": "/nodes/0/weights/3" + } + } + } + } + ], + "samplers": [ + { + "input": 0, + "output": 1, + "interpolation": "STEP" + }, + { + "input": 2, + "output": 3, + "interpolation": "STEP" + } + ] + } + ] +} +``` + +This allows `blinkLeft` (weight index 2) and `blinkRight` (weight index 3) to be animated with different timing samplers. + +This method ensures consistent and interoperable animation targeting for morph target-based expressions across glTF runtimes. + ## Example: Expression with glTF Animation ### Step 1: Bind Expression to Morph Target @@ -203,5 +340,5 @@ This approach simplifies character implementation by centralizing expression pla ## License -This extension specification is licensed under the Khronos Group Extension License. +This extension specification is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html From 34c6689f849e3136606b2972c598065921871acd Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 17 Dec 2025 00:07:35 -0800 Subject: [PATCH 42/48] KHR_character_skeleton_bindpose update Adding IPose pose type, as well as modified the bindpose extension to enable multiple poseType/bindpose definitions --- .../KHR_character_skeleton_bindpose/README.md | 81 ++++++++++++++----- ...HR_character_skeleton_bindpose.schema.json | 44 ++++++---- 2 files changed, 87 insertions(+), 38 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md index 8ebb39c0de..1ae0e07a30 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md @@ -21,11 +21,11 @@ Requires the extension(s): `KHR_character` ## Overview -The `KHR_character_skeleton_bindpose` extension defines a canonical bind pose for the character's skeleton. This pose serves as a neutral reference that supports animation retargeting, mesh deformation validation, and consistency across toolchains. The bind pose is defined per-skin and uses the same joint ordering as the skin's joints array for direct mapping and maximum simplicity. +The `KHR_character_skeleton_bindpose` extension defines one or more canonical bind poses for the character's skeleton. These poses serve as neutral references that support animation retargeting, mesh deformation validation, and consistency across toolchains. Multiple bind poses can be defined per-skin (each with a unique pose type), using the same joint ordering as the skin's joints array for direct mapping and maximum simplicity. ## Extension Schema -This extension is applied to individual skins in the glTF file, providing bind pose data that corresponds directly to the skin's joint array. +This extension is applied to individual skins in the glTF file, providing bind pose data that corresponds directly to the skin's joint array. Multiple bind poses can be defined, each with a unique `poseType`. ```json { @@ -34,12 +34,25 @@ This extension is applied to individual skins in the glTF file, providing bind p "joints": [2, 5, 8, 12], "extensions": { "KHR_character_skeleton_bindpose": { - "poseType": "TPose", - "bindPoses": [ - { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }, - { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.5, 0, 1] }, - { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.0, 0, 1] }, - { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.5, 0, 1] } + "poses": [ + { + "poseType": "TPose", + "bindPoses": [ + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.5, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.5, 0, 1] } + ] + }, + { + "poseType": "IPose", + "bindPoses": [ + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.5, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.5, 0, 1] } + ] + } ] } } @@ -52,7 +65,15 @@ This extension is applied to individual skins in the glTF file, providing bind p | Property | Type | Description | | -------- | ---- | ----------- | -| `poseType` | string | Enum: `TPose`, `APose`, `Custom`. Declares the character's general pose classification. | +| `poses` | array | Array of pose definitions. Each pose has a unique `poseType` and corresponding `bindPoses` array. | + +#### poses Array + +Each entry in the `poses` array contains: + +| Property | Type | Description | +| -------- | ---- | ----------- | +| `poseType` | string | Enum: `TPose`, `APose`, `IPose`, `Custom`. Declares the pose classification for this bind pose set. | | `bindPoses` | array | List of bind pose matrices corresponding directly to the skin's joints array. Each entry at index i corresponds to the joint at joints[i]. | #### bindPoses Array @@ -75,6 +96,7 @@ The `bindPoses` array uses per-skin joint indexing for maximum simplicity and gl ### Example Mapping Given a skin with `"joints": [2, 5, 8, 12]`: + - `bindPoses[0]` corresponds to joint node 2 - `bindPoses[1]` corresponds to joint node 5 - `bindPoses[2]` corresponds to joint node 8 @@ -90,18 +112,20 @@ This extension supplements or overrides that mechanism by defining joint rest po ### poseType Enum -| Value | Description | -| -------- | --------------------------------------------------------------------- | -| `TPose` | Arms extended horizontally. Common neutral rest pose for retargeting. | -| `APose` | Arms angled downward. Used by some character authoring tools. | -| `Custom` | Any pose that does not fit T-Pose or A-Pose definitions. | +| Value | Description | +| -------- | ------------------------------------------------------------------------------------ | +| `TPose` | Arms extended horizontally. Common neutral rest pose for retargeting. | +| `APose` | Arms angled downward (~45°). Used by some character authoring tools. | +| `IPose` | Arms resting at sides, parallel to the body. Natural standing pose. | +| `Custom` | Any pose that does not fit T-Pose, A-Pose, or I-Pose definitions. | ## Implementation Notes -- The number of bind poses must match the number of joints in the skin's joints array. +- Each `poseType` value must be unique within the `poses` array. A skin cannot have two poses with the same `poseType`. +- The number of bind poses in each `bindPoses` array must match the number of joints in the skin's joints array. - The bind pose matrix must be specified in model space (i.e., world-relative). - This extension can be used in tandem with `skins[].inverseBindMatrices`, but is intended to expose clearer semantic meaning. -- Validation should ensure that bindPoses array length equals joints array length. +- Validation should ensure that each bindPoses array length equals joints array length. ## Example @@ -120,12 +144,25 @@ This extension supplements or overrides that mechanism by defining joint rest po "joints": [0, 1, 2, 3], "extensions": { "KHR_character_skeleton_bindpose": { - "poseType": "TPose", - "bindPoses": [ - { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }, - { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.5, 0, 1] }, - { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.0, 0, 1] }, - { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.5, 0, 1] } + "poses": [ + { + "poseType": "TPose", + "bindPoses": [ + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.5, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.0, 0, 1] }, + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1.5, 0, 1] } + ] + }, + { + "poseType": "IPose", + "bindPoses": [ + { "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] }, + { "matrix": [0.707, 0, -0.707, 0, 0, 1, 0, 0, 0.707, 0, 0.707, 0, 0, 0.5, 0, 1] }, + { "matrix": [0.707, 0, -0.707, 0, 0, 1, 0, 0, 0.707, 0, 0.707, 0, 0, 1.0, 0, 1] }, + { "matrix": [0.707, 0, -0.707, 0, 0, 1, 0, 0, 0.707, 0, 0.707, 0, 0, 1.5, 0, 1] } + ] + } ] } } diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json index d4981583c8..854e24965a 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json +++ b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json @@ -2,32 +2,44 @@ "$schema": "http://json-schema.org/draft-04/schema", "title": "KHR_character_skeleton_bindpose glTF Skin Extension", "type": "object", - "description": "glTF extension that defines a canonical bind pose for the character's skeleton applied to individual skins.", + "description": "glTF extension that defines one or more canonical bind poses for the character's skeleton applied to individual skins.", "allOf": [ { "$ref": "glTFProperty.schema.json" } ], "properties": { - "poseType": { - "type": "string", - "description": "The type of pose this bind pose represents.", - "enum": ["TPose", "APose", "Custom"], - "default": "TPose" - }, - "bindPoses": { + "poses": { "type": "array", - "description": "Array of bind pose matrices corresponding directly to the skin's joints array. Each entry at index i corresponds to the joint at joints[i].", + "description": "Array of pose definitions. Each pose has a unique poseType and corresponding bindPoses array.", "items": { "type": "object", "properties": { - "matrix": { + "poseType": { + "type": "string", + "description": "The type of pose this bind pose represents.", + "enum": ["TPose", "APose", "IPose", "Custom"], + "default": "TPose" + }, + "bindPoses": { "type": "array", - "description": "Column-major 4x4 matrix defining the joint's bind pose in model space.", + "description": "Array of bind pose matrices corresponding directly to the skin's joints array. Each entry at index i corresponds to the joint at joints[i].", "items": { - "type": "number" + "type": "object", + "properties": { + "matrix": { + "type": "array", + "description": "Column-major 4x4 matrix defining the joint's bind pose in model space.", + "items": { + "type": "number" + }, + "minItems": 16, + "maxItems": 16 + } + }, + "required": ["matrix"], + "additionalProperties": false }, - "minItems": 16, - "maxItems": 16 + "minItems": 1 } }, - "required": ["matrix"], + "required": ["poseType", "bindPoses"], "additionalProperties": false }, "minItems": 1 @@ -36,6 +48,6 @@ "extras": { } }, "required": [ - "bindPoses" + "poses" ] } From 9dcf07527088d52896605703536037a742f81f07 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 17 Dec 2025 00:25:21 -0800 Subject: [PATCH 43/48] Update KHR_character to use rootNode instead of sceneIndex After discussing it with the TSG; switching to the root node index makes more sense here given scenes aren't really well-supported across the board. Also added new contributors to the extension --- .../2.0/Khronos/KHR_character/README.md | 24 ++++++++++--------- .../schema/glTF.KHR_character.schema.json | 6 ++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character/README.md b/extensions/2.0/Khronos/KHR_character/README.md index 3f2365f0b7..ec4afe3591 100644 --- a/extensions/2.0/Khronos/KHR_character/README.md +++ b/extensions/2.0/Khronos/KHR_character/README.md @@ -4,11 +4,13 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status @@ -20,7 +22,7 @@ Written against the glTF 2.0 specification. Requires the extensions: `KHR_xmp_json_ld` -This extension also leverages the `KHR_xmp_json_ld` pattern for attaching extensible metadata as JSON-LD blocks within glTF assets. For background on this approach, see: +This extension also leverages the `KHR_xmp_json_ld` pattern for attaching extensible metadata as JSON-LD blocks within glTF assets. For background on this approach, see: [KHR_xmp_json_ld](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_xmp_json_ld) ## Overview @@ -29,7 +31,7 @@ The `KHR_character` extension designates a glTF asset as representing an charact This extension does not define character features directly but acts as a root declaration that character-related extensions may be present, and that consumers should treat the asset using character-specific logic and pipelines. It's part of the wider set of KHR character extensions that are meant to be building blocks to represent a contract stating functionality and data requirements between a given model and an endpoint. -The extension supports referencing the source `scene` that represents the character and optionally includes structured metadata through the `KHR_xmp_json_ld` mechanism. +The extension supports referencing the root `node` that represents the character and optionally includes structured metadata through the `KHR_xmp_json_ld` mechanism. ## Extension Schema @@ -37,7 +39,7 @@ The extension supports referencing the source `scene` that represents the charac { "extensions": { "KHR_character": { - "sceneIndex": 0 + "rootNode": 0 } } } @@ -45,9 +47,9 @@ The extension supports referencing the source `scene` that represents the charac ### Properties -| Property | Type | Description | -| ------------ | ------- | ------------------------------------------------------------------------------------------------------------------------ | -| `sceneIndex` | integer | Index of the glTF `scene` representing the character. Used to distinguish the character root when multiple scenes exist. | +| Property | Type | Description | +| ---------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `rootNode` | integer | Index of the glTF `node` representing the root of the character hierarchy. This node should be a common ancestor of all nodes containing character-related data, such as meshes, skins, and animations. | ## Metadata Attachment: KHR_xmp_json_ld @@ -95,7 +97,7 @@ The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as par "extensionsUsed": ["KHR_character", "KHR_xmp_json_ld"], "extensions": { "KHR_character": { - "sceneIndex": 0 + "rootNode": 0 }, "KHR_xmp_json_ld": { @@ -139,7 +141,7 @@ The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as par ## Implementation Notes -- `sceneIndex` is required, representing the index of the glTF `scene` corresponding to the character. Used to distinguish the character root when multiple scenes exist. +- `rootNode` is required, representing the index of the glTF `node` that serves as the root of the character hierarchy. This node should be a common ancestor of all nodes containing character-related data, such as meshes, skins, and animations. - Consumers should use this marker as a signal to search for additional character-related extensions, including skeletal, expression, and other khronos character extensions. - Support for `KHR_xmp_json_ld` is encouraged to ensure interoperable metadata across tools and runtimes. @@ -147,5 +149,5 @@ The `KHR_xmp_json_ld` block is placed at the root level of the glTF asset as par ## License -This extension specification is licensed under the Khronos Group Extension License. +This extension specification is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json index 9b2fa0b565..1c972937c0 100644 --- a/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json +++ b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json @@ -5,14 +5,14 @@ "description": "glTF extension for character-specific metadata and properties.", "allOf": [ { "$ref": "glTFProperty.schema.json" } ], "properties": { - "sceneIndex": { + "rootNode": { "allOf": [{ "$ref": "glTFid.schema.json" }], - "description": "Index of the glTF scene representing the avatar. Used to distinguish the avatar root when multiple scenes exist." + "description": "Index of the glTF node representing the root of the character hierarchy. This node should be a common ancestor of all nodes containing character-related data, such as meshes, skins, and animations." }, "extensions": { }, "extras": { } }, "required": [ - "sceneIndex" + "rootNode" ] } From 607430e72f3cd5103428fabf5e3c31ffd33e1048 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 17 Dec 2025 00:28:58 -0800 Subject: [PATCH 44/48] Individual Contributor ->Independent Contributor --- extensions/2.0/Khronos/KHR_character_expression/README.md | 8 ++++---- .../2.0/Khronos/KHR_character_expression_joint/README.md | 8 ++++---- .../Khronos/KHR_character_expression_mapping/README.md | 4 ++-- .../KHR_character_expression_morphtarget/README.md | 4 ++-- .../Khronos/KHR_character_expression_procedural/README.md | 8 ++++---- .../Khronos/KHR_character_expression_texture/README.md | 8 ++++---- .../2.0/Khronos/KHR_character_skeleton_bindpose/README.md | 4 ++-- extensions/2.0/Khronos/KHR_virtual_transform/README.md | 4 ++-- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_expression/README.md b/extensions/2.0/Khronos/KHR_character_expression/README.md index f07e88755c..8c16f2e719 100644 --- a/extensions/2.0/Khronos/KHR_character_expression/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression/README.md @@ -4,10 +4,10 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta ## Status @@ -16,7 +16,7 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Requires the extension(s): `KHR_character` ## Overview @@ -138,5 +138,5 @@ STEP interpolation ensures that an expression toggles cleanly between fully off ## License -This extension is licensed under the Khronos Group Extension License. +This extension is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md index b6c14f7cb5..43b99270bc 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md @@ -4,10 +4,10 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta ## Status @@ -16,7 +16,7 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Requires the extension(s): `KHR_character`,`KHR_character_expression` Typically used in conjunction with: `KHR_character_expression_mapping` @@ -105,5 +105,5 @@ STEP interpolation ensures that an expression toggles cleanly between fully off ## License -This extension is licensed under the Khronos Group Extension License. +This extension is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md index 834200d51a..91e4b519ab 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md @@ -4,10 +4,10 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta ## Status diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md index 53a23ed341..15e76ff4b6 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md @@ -4,10 +4,10 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta ## Status diff --git a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md index f1fa23837a..4ce3adebdc 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md @@ -4,10 +4,10 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta ## Status @@ -18,7 +18,7 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Requires the extension(s): `KHR_character`,`KHR_character_expression` Works alongside: `KHR_character_expression_mapping`, `KHR_character_expression_joint`, `KHR_character_expression_texture`, `KHR_character_expression_morphtargets`. @@ -105,5 +105,5 @@ This allows developers to distinguish expressions meant to supplement animation ## License -This extension is licensed under the Khronos Group Extension License. +This extension is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md index 0332e6ae0f..e86851edfb 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md @@ -4,10 +4,10 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta ## Status @@ -16,7 +16,7 @@ ## Dependencies -Written against the glTF 2.0 specification. +Written against the glTF 2.0 specification. Requires the extension(s): `KHR_character`, `KHR_character_expression`, `KHR_animation_pointer` Can be used alongside: `KHR_character_expression_mapping` @@ -257,5 +257,5 @@ Animation of either the texture index or texture transform must be implemented u ## License -This extension specification is licensed under the Khronos Group Extension License. +This extension specification is licensed under the Khronos Group Extension License. See: https://www.khronos.org/registry/gltf/license.html diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md index 1ae0e07a30..2f5c583557 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md @@ -4,10 +4,10 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta ## Status diff --git a/extensions/2.0/Khronos/KHR_virtual_transform/README.md b/extensions/2.0/Khronos/KHR_virtual_transform/README.md index 3a5821b2b4..c97d672208 100644 --- a/extensions/2.0/Khronos/KHR_virtual_transform/README.md +++ b/extensions/2.0/Khronos/KHR_virtual_transform/README.md @@ -4,10 +4,10 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta ## Status From 1c91e28fcafe0239bd2c260fd477c743130b14d1 Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 17 Dec 2025 00:32:49 -0800 Subject: [PATCH 45/48] Updating README contributor lists with new TSG contributors --- extensions/2.0/Khronos/KHR_character_expression/README.md | 2 ++ .../2.0/Khronos/KHR_character_expression_joint/README.md | 2 ++ .../2.0/Khronos/KHR_character_expression_mapping/README.md | 2 ++ .../Khronos/KHR_character_expression_morphtarget/README.md | 2 ++ .../Khronos/KHR_character_expression_procedural/README.md | 2 ++ .../2.0/Khronos/KHR_character_expression_texture/README.md | 2 ++ .../2.0/Khronos/KHR_character_skeleton_bindpose/README.md | 2 ++ .../2.0/Khronos/KHR_character_skeleton_mapping/README.md | 6 ++++-- extensions/2.0/Khronos/KHR_virtual_transform/README.md | 2 ++ 9 files changed, 20 insertions(+), 2 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_expression/README.md b/extensions/2.0/Khronos/KHR_character_expression/README.md index 8c16f2e719..35146ca267 100644 --- a/extensions/2.0/Khronos/KHR_character_expression/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression/README.md @@ -9,6 +9,8 @@ - 0b5vr / pixiv Inc. - Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status diff --git a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md index 43b99270bc..fdca73df4b 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_joint/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_joint/README.md @@ -9,6 +9,8 @@ - 0b5vr / pixiv Inc. - Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md index 91e4b519ab..3376838e5a 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/README.md @@ -9,6 +9,8 @@ - 0b5vr / pixiv Inc. - Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md index 15e76ff4b6..4012da98f0 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/README.md @@ -9,6 +9,8 @@ - 0b5vr / pixiv Inc. - Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status diff --git a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md index 4ce3adebdc..5ecc2c3521 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/README.md @@ -9,6 +9,8 @@ - 0b5vr / pixiv Inc. - Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status diff --git a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md index e86851edfb..446243dd12 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_texture/README.md +++ b/extensions/2.0/Khronos/KHR_character_expression_texture/README.md @@ -9,6 +9,8 @@ - 0b5vr / pixiv Inc. - Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md index 2f5c583557..4b5a13fd56 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/README.md @@ -9,6 +9,8 @@ - 0b5vr / pixiv Inc. - Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md index 402a8450cb..2725721075 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md @@ -4,11 +4,13 @@ - Ken Jakubzak, Meta - Hideaki Eguchi / VirtualCast, Inc. -- K. S. Ernest (iFire) Lee, Individual Contributor / https://github.com/fire +- K. S. Ernest (iFire) Lee, Independent Contributor / https://github.com/fire - Shinnosuke Iwaki / VirtualCast, Inc. - 0b5vr / pixiv Inc. -- Leonard Daly, Individual Contributor +- Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status diff --git a/extensions/2.0/Khronos/KHR_virtual_transform/README.md b/extensions/2.0/Khronos/KHR_virtual_transform/README.md index c97d672208..a246a4a3c4 100644 --- a/extensions/2.0/Khronos/KHR_virtual_transform/README.md +++ b/extensions/2.0/Khronos/KHR_virtual_transform/README.md @@ -9,6 +9,8 @@ - 0b5vr / pixiv Inc. - Leonard Daly, Independent Contributor - Nick Burkard, Meta +- Sarah Cooney, Microsoft XGTG +- Aaron Franke, Independent Contributor ## Status From 3eb2b6dba900845001ab64c2c301bf1f2da61c5a Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Wed, 17 Dec 2025 00:39:37 -0800 Subject: [PATCH 46/48] KHR_character_skeleton_mapping - Inverted key/value pairs to align with KHR_character_expression_mapping It was pointed out that KHR_character_skeleton_mapping should align more with KHR_character_expression_mapping in terms of the keys being the target names, and the values being the source joint names; so I've updated it to do so. --- .../KHR_character_skeleton_mapping/README.md | 42 +++++++++---------- ...KHR_character_skeleton_mapping.schema.json | 4 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md index 2725721075..9807335922 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md +++ b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/README.md @@ -50,20 +50,20 @@ Here's an example mapping from a custom rig into VRM Humanoid: "KHR_character_skeleton_mapping": { "skeletalRigMappings": { "vrmHumanoid": { - "myRig_hips": "hips", - "myRig_head": "head", - "myRig_leftFoot": "leftFoot", - "myRig_rightFoot": "rightFoot", - "myRig_leftHand": "leftHand", - "myRig_rightHand": "rightHand" + "hips": "myRig_hips", + "head": "myRig_head", + "leftFoot": "myRig_leftFoot", + "rightFoot": "myRig_rightFoot", + "leftHand": "myRig_leftHand", + "rightHand": "myRig_rightHand" }, "example_rig": { - "myRig_hips": "hip_bone", - "myRig_head": "head_bone", - "myRig_leftFoot": "l_foot_bone", - "myRig_rightFoot": "r_foot_bone", - "myRig_leftHand": "l_hand_bone", - "myRig_rightHand": "r_hand_bone" + "hip_bone": "myRig_hips", + "head_bone": "myRig_head", + "l_foot_bone": "myRig_leftFoot", + "r_foot_bone": "myRig_rightFoot", + "l_hand_bone": "myRig_leftHand", + "r_hand_bone": "myRig_rightHand" } } } @@ -73,27 +73,27 @@ Here's an example mapping from a custom rig into VRM Humanoid: In this example: -- The key is the source joint name from the model's native rig (e.g., `"myRig_hips"`) -- The value is the target joint name defined by the target standard rig (e.g., `"hips"` for VRM Humanoid) +- The key is the target joint name defined by the target standard rig (e.g., `"hips"` for VRM Humanoid) +- The value is the source joint name from the model's native rig (e.g., `"myRig_hips"`) - The system using this extension may understand what `"vrmHumanoid"` or `"example_rig"` means (i.e., the joint vocabulary and structure must be pre-declared by the consuming runtime) ### Breakdown and Lower-Level Properties The structure of the data contained in the extension can be described as a dictionary of dictionaries: -**Target Skeleton/Rig Name** : **Joint Mapping Dictionary** (Source Joint Name : Target Joint Name) +**Target Skeleton/Rig Name** : **Joint Mapping Dictionary** (Target Joint Name : Source Joint Name) Each mapping entry is simply: -| Key (Source Joint) | Value (Target Joint) | Description | +| Key (Target Joint) | Value (Source Joint) | Description | | ------------------ | -------------------- | -------------------------------------------------------- | -| string | string | Direct mapping from source joint name to target joint name in the target vocabulary | +| string | string | Direct mapping from target joint name in the target vocabulary to source joint name in the model's native rig | ### Mapping Types This extension supports one-to-one mappings: -- **One-to-one**: A source joint maps directly to a single target joint via a simple string value. +- **One-to-one**: A target joint maps directly to a single source joint via a simple string value. This approach ensures maximum simplicity, compatibility across all engines and tools, and follows glTF's design philosophy of keeping core extensions simple and stable. @@ -107,11 +107,11 @@ While this extension does not mandate a central registry, developers are encoura ## Implementation Notes -- Source joint names (keys) are assumed to refer to nodes in the glTF `nodes` array. -- Target joint names (values) are defined by the target rig's vocabulary. +- Target joint names (keys) are defined by the target rig's vocabulary. +- Source joint names (values) are assumed to refer to nodes in the glTF `nodes` array. - The reference rig vocabulary may be shared across engines or projects. - This extension does not modify skinning behavior, but informs tooling and runtime animation retargeting. -- For validation, ensure that all source joint names correspond to valid glTF nodes. +- For validation, ensure that all source joint names (values) correspond to valid glTF nodes. ## License diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json index f638341ac4..f3d180e318 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json +++ b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json @@ -10,10 +10,10 @@ "description": "Dictionary of target rig mappings. Each key is a target rig name, each value is a mapping dictionary.", "additionalProperties": { "type": "object", - "description": "Joint mapping dictionary. Each key is a source joint name, each value is the target joint name.", + "description": "Joint mapping dictionary. Each key is a target joint name in the target rig vocabulary, each value is the source joint name from the model's native rig.", "additionalProperties": { "type": "string", - "description": "Target joint name in the target rig vocabulary." + "description": "Source joint name from the model's native rig." } } }, From f3f2c90a937fbb1387810c758d1254263eaa0fec Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 12 Jan 2026 12:52:37 -0800 Subject: [PATCH 47/48] Updated schema references to https://json-schema.org/draft/2020-12/schema --- .../Khronos/KHR_character/schema/glTF.KHR_character.schema.json | 2 +- .../schema/glTF.KHR_character_expression.schema.json | 2 +- ...racter_expression.KHR_character_expression_joint.schema.json | 2 +- .../schema/glTF.KHR_character_expression_mapping.schema.json | 2 +- ..._expression.KHR_character_expression_morphtarget.schema.json | 2 +- ...r_expression.KHR_character_expression_procedural.schema.json | 2 +- ...cter_expression.KHR_character_expression_texture.schema.json | 2 +- .../schema/skin.KHR_character_skeleton_bindpose.schema.json | 2 +- .../schema/glTF.KHR_character_skeleton_mapping.schema.json | 2 +- .../schema/glTF.KHR_virtual_transform.schema.json | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json index 1c972937c0..a0225ccd1c 100644 --- a/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json +++ b/extensions/2.0/Khronos/KHR_character/schema/glTF.KHR_character.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_character glTF Document Extension", "type": "object", "description": "glTF extension for character-specific metadata and properties.", diff --git a/extensions/2.0/Khronos/KHR_character_expression/schema/glTF.KHR_character_expression.schema.json b/extensions/2.0/Khronos/KHR_character_expression/schema/glTF.KHR_character_expression.schema.json index b95a982a63..dc899a9cd9 100644 --- a/extensions/2.0/Khronos/KHR_character_expression/schema/glTF.KHR_character_expression.schema.json +++ b/extensions/2.0/Khronos/KHR_character_expression/schema/glTF.KHR_character_expression.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_character_expression glTF Document Extension", "type": "object", "description": "glTF extension that provides a common interface for facial expression animations.", diff --git a/extensions/2.0/Khronos/KHR_character_expression_joint/schema/KHR_character_expression.KHR_character_expression_joint.schema.json b/extensions/2.0/Khronos/KHR_character_expression_joint/schema/KHR_character_expression.KHR_character_expression_joint.schema.json index 9eef27fc11..47b79e415b 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_joint/schema/KHR_character_expression.KHR_character_expression_joint.schema.json +++ b/extensions/2.0/Khronos/KHR_character_expression_joint/schema/KHR_character_expression.KHR_character_expression_joint.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_character_expression_joint KHR_character_expression Extension", "type": "object", "description": "glTF extension that extends KHR_character_expression to specify joint-based expression animations.", diff --git a/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/glTF.KHR_character_expression_mapping.schema.json b/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/glTF.KHR_character_expression_mapping.schema.json index 245d1af711..d582170255 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/glTF.KHR_character_expression_mapping.schema.json +++ b/extensions/2.0/Khronos/KHR_character_expression_mapping/schema/glTF.KHR_character_expression_mapping.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_character_expression_mapping glTF Document Extension", "type": "object", "description": "glTF extension that enables encoding multiple expression set mappings, mapping source expressions present in the model to target expressions that a runtime/endpoint understands.", diff --git a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/schema/KHR_character_expression.KHR_character_expression_morphtarget.schema.json b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/schema/KHR_character_expression.KHR_character_expression_morphtarget.schema.json index dd0b97a6d3..91453ac1dd 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_morphtarget/schema/KHR_character_expression.KHR_character_expression_morphtarget.schema.json +++ b/extensions/2.0/Khronos/KHR_character_expression_morphtarget/schema/KHR_character_expression.KHR_character_expression_morphtarget.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_character_expression_morphtarget KHR_character_expression Extension", "type": "object", "description": "glTF extension that extends KHR_character_expression to specify morph target-based expression animations.", diff --git a/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json b/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json index b46035bc02..b59587c30e 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_character_expression_procedural KHR_character_expression Extension", "type": "object", "description": "glTF extension that extends KHR_character_expression to specify procedural expression animations.", diff --git a/extensions/2.0/Khronos/KHR_character_expression_texture/schema/KHR_character_expression.KHR_character_expression_texture.schema.json b/extensions/2.0/Khronos/KHR_character_expression_texture/schema/KHR_character_expression.KHR_character_expression_texture.schema.json index e4fff590f7..fd3a8c72c8 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_texture/schema/KHR_character_expression.KHR_character_expression_texture.schema.json +++ b/extensions/2.0/Khronos/KHR_character_expression_texture/schema/KHR_character_expression.KHR_character_expression_texture.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_character_expression_texture KHR_character_expression Extension", "type": "object", "description": "glTF extension that extends KHR_character_expression to specify texture-based expression animations.", diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json index 854e24965a..dac61cf32a 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json +++ b/extensions/2.0/Khronos/KHR_character_skeleton_bindpose/schema/skin.KHR_character_skeleton_bindpose.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_character_skeleton_bindpose glTF Skin Extension", "type": "object", "description": "glTF extension that defines one or more canonical bind poses for the character's skeleton applied to individual skins.", diff --git a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json index f3d180e318..a3c10c19f7 100644 --- a/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json +++ b/extensions/2.0/Khronos/KHR_character_skeleton_mapping/schema/glTF.KHR_character_skeleton_mapping.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_character_skeleton_mapping glTF Document Extension", "type": "object", "description": "glTF extension that provides a mechanism to map a skeleton rig to a reference rig for retargeting and compatibility.", diff --git a/extensions/2.0/Khronos/KHR_virtual_transform/schema/glTF.KHR_virtual_transform.schema.json b/extensions/2.0/Khronos/KHR_virtual_transform/schema/glTF.KHR_virtual_transform.schema.json index 0f44283e40..5c6878db7b 100644 --- a/extensions/2.0/Khronos/KHR_virtual_transform/schema/glTF.KHR_virtual_transform.schema.json +++ b/extensions/2.0/Khronos/KHR_virtual_transform/schema/glTF.KHR_virtual_transform.schema.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "KHR_virtual_transform glTF Document Extension", "type": "object", "description": "glTF extension that introduces virtual transforms - semantic attachment or control points relative to the model's node hierarchy.", From ee572d4e3148d2f21bb469f3d0575d6701f91b2e Mon Sep 17 00:00:00 2001 From: Kjakubzak Date: Mon, 12 Jan 2026 13:14:45 -0800 Subject: [PATCH 48/48] Update KHR_character_expression.KHR_character_expression_procedural.schema.json Updated to reflect the documentation. Note that this extension is going to be worked on pretty extensively as part of the Amend work we have planned, so expect further changes. --- ...haracter_expression_procedural.schema.json | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json b/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json index b59587c30e..b89cbf7f1e 100644 --- a/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json +++ b/extensions/2.0/Khronos/KHR_character_expression_procedural/schema/KHR_character_expression.KHR_character_expression_procedural.schema.json @@ -5,24 +5,13 @@ "description": "glTF extension that extends KHR_character_expression to specify procedural expression animations.", "allOf": [ { "$ref": "glTFProperty.schema.json" } ], "properties": { - "channels": { - "type": "array", - "description": "Array of animation channel indices that drive procedural expressions.", - "items": { - "allOf": [ - { - "$ref": "glTFid.schema.json" - } - ], - "description": "Index of the animation channel in the referenced animation." - }, - "minItems": 1, - "uniqueItems": true + "conflictResolution": { + "type": "string", + "description": "Conflict resolution strategy used to determine how multiple sources (procedural and non-procedural) control a given expression.", + "enum": ["none", "block", "blend"], + "default": "none" }, "extensions": { }, "extras": { } - }, - "required": [ - "channels" - ] + } }