Fountain Coach Gitowner-controlled · read only

laban-rig.git · EXTENSIBILITY.md

laban-rig.git / EXTENSIBILITY.md

revision fc813fbf6ee5e1554e429fb8bf91ffb33f310308 · complete file

# Extensibility Guidelines for the Canonical Humanoid Rig

This document explains **how to extend** the canonical humanoid rig description while
preserving its core goals:

- direct compatibility with **ARKit / iPhone mocap**,  
- maintainability across **file formats** (USD, FBX, glTF, BVH),  
- interoperability with **Laban-style movement analysis**.

---

## 1. Adding More Joints (Hands, Fingers, Face)

The `JointRole` and `LabanPart` enums in the schema are intentionally small and stable.
You can add *more joints* without changing these enums.

### 1.1. Example: Fingers

ARKit defines many hand joints (metacarpals, proximal, intermediate, distal, tip).
To add them:

1. Keep using the **same schema**.
2. Add new `joints` entries with:
   - `id`: a stable canonical name, e.g. `index_proximal_left`.
   - `name`: ARKit's source joint name, e.g. `left_handIndex_1_joint`.
   - `parentId`: e.g. `wrist_left` or the previous finger joint.
   - `side`: `"LEFT"` or `"RIGHT"`.
   - `role`: one of the existing roles, usually `HAND` (you can also introduce roles such as `FINGER_PROXIMAL` if you want a finer taxonomy, but keep that local to your own tools).
   - `labanPart`: `HAND_LEFT` or `HAND_RIGHT`.

For many Laban-related tasks, you only need the **end effector** (wrist, or sometimes fingertip).
But including extra finger joints is useful for animation and hand-gesture studies.

### 1.2. Example: Face

Similarly, ARKit and other systems can track facial joints (eyes, jaw, brows).
To integrate face joints:

- Add them as new `joints` with `side = "CENTER"`, `"LEFT"`, or `"RIGHT"` as appropriate.
- Use `role` values such as `HEAD`, `JAW`, or define new roles like `EYE_CENTER`, `BROW`, etc.
- Keep `labanPart = "HEAD_NECK"` for all face-related joints, unless you introduce finer regions.

Labanotation traditionally emphasizes bodily direction and weight more than fine facial gestures,
so these joints are mostly for animation or additional analysis, not crucial for basic Laban mapping.

---

## 2. Adapting to Other Source Skeletons

The canonical rig uses ARKit as a **reference**, but the schema is agnostic. For any other skeleton:

1. Keep the JSON schema as-is.
2. For each bone/joint in the foreign skeleton, create a `joints` entry:
   - `id`: canonical name you choose (e.g. `pelvis`, `spine_lower`, etc.).
   - `name`: the original name in that source (e.g. `"mixamorig:Hips"`, `"root"`, `"thigh_l"`, etc.).
   - `parentId`: set according to that skeleton's hierarchy.
   - `side`: `"CENTER"`, `"LEFT"`, or `"RIGHT"`.
   - `role`: your best semantic classification (`PELVIS`, `KNEE`, `WRIST`, ...).
   - `labanPart`: which body region this joint belongs to (`TRUNK`, `ARM_LEFT`, ...).

LLMs and tools can then understand **multiple skeletons** by their canonical ids,
even though each skeleton has different native names and potentially different numbers of bones.

### 2.1. Example: Mapping to a Game Engine Rig

For a game engine such as Unity, Unreal, or Godot:

- Maintain a table in code or data:
  - `engineBoneName` → `canonicalId`.
- During import or rig setup, annotate bones with their canonical ids and roles.
- Your procedural animation / analysis logic should always reason in terms of **canonical ids**,
  then look up the engine's native bone to actually set transforms.

---

## 3. Extending Roles and Laban Parts Safely

### 3.1. JointRole

The `JointRole` enum is there to enrich the skeleton with semantic meaning.
You can extend it, but do so under some constraints:

- Prefer to *add* new roles rather than reinterpreting the old ones.
- Document any new roles and their intended use.
- Keep the basic meanings intact:
  - `PELVIS` – the root of the lower trunk.
  - `SPINE_*` – trunk segments from pelvis to neck.
  - `HIP`, `KNEE`, `ANKLE`, `TOE_END` – leg chain.
  - `CLAVICLE`, `SHOULDER`, `ELBOW`, `WRIST`, `HAND` – arm chain.
  - `HEAD`, `NECK_*` – head/neck.

LLMs can often infer what new roles mean if they are self-explanatory strings, but consistency is key.

### 3.2. LabanPart

`LabanPart` is intentionally coarse. If you wish, you can define **sub-parts** like:

- `ARM_LEFT_UPPER`
- `ARM_LEFT_LOWER`
- `HAND_LEFT_THENAR`
- `TRUNK_UPPER`, `TRUNK_LOWER`

This can be helpful for more detailed analysis, but you should maintain a mapping back to the base parts.
For example:

- `ARM_LEFT_UPPER` → base part `ARM_LEFT`.
- `TRUNK_UPPER` → base part `TRUNK`.

This way, basic Laban reasoning (which expects broad body regions) still works.

---

## 4. Preserving ARKit / iPhone Mocap Compatibility

If you want to stay **100% compatible** with Apple mocap, follow these rules:

1. **Do not change the meaning** of any ARKit-derived joints in the example skeleton.
2. When adding ARKit joints, always use the original ARKit joint name in `name`.
3. Keep `coordinateSystem` aligned with ARKit conventions:
   - `upAxis = "Y"`
   - `forwardAxis = "Z"`
   - `rightAxis = "X"`
4. If you create new canonical skeletons for other sources, you may use different coordinate systems,
   but for any ARKit-based skeleton, stay consistent with this one.

---

## 5. Notes for LLM Use

When instructing an LLM to extend this rig:

- Always **include the full `canonical_rig.json`** and this extensibility document in the prompt or context.
- Ask the model to:
  - Respect the existing schema and enums.
  - Add new `joints` entries in the same style.
  - Document any newly introduced `JointRole` or `LabanPart` values.

You can say, for example:

> “Given this canonical rig schema and example skeleton, please extend it with index and thumb finger joints for both hands, using the same style and keeping ARKit compatibility.”

The output should be a **valid JSON** skeleton description matching the schema, ready to be merged into your existing rig or stored as a new variant.

---

## 6. Suggested Directory and Versioning Practice

- Keep `canonical_rig.json` under version control (e.g. Git).
- When making changes:
  - Bump the `version` string.
  - Add a short changelog entry (either in your own CHANGELOG.md or in `metadata`).
- For big changes (e.g., adding a full face rig), consider creating a new `skeletonId` such as:
  - `canonical-arkit-body-face-v2`

This lets code and LLMs explicitly target the appropriate level of detail.