import { Document } from '@gltf-transform/core'; import type { BoneMap } from './retarget'; export interface SkelNodeDef { name: string; /** local rest transform, column-major 16 */ local: number[]; parent: string | null; } export interface CanonicalSkeleton { /** every node in the skeleton subtree (joints + structural, e.g. metacarpals), DFS order */ nodes: SkelNodeDef[]; /** the 68 skin joints, in skin joint order */ jointNames: string[]; /** world rest transform per node, accumulated from the skeleton root (root parent = identity) */ worldByName: Map; skeletonRootName: string; } /** * Reads the canonical helix-humanoid@1 rest skeleton out of a shipped body GLB (body-m-default): the * full bone subtree (local rest transforms + hierarchy) and the skin's joint order. World transforms * are recomputed from the skeleton root down (independent of the source file's mesh-node ancestor), * so a rebuilt copy with the root at scene identity reproduces them exactly. */ export declare function extractCanonicalSkeleton(document: Document): CanonicalSkeleton; export interface ConformResult { mode: 'embed' | 'repose'; /** Uniform scale baked onto the source joint worlds before fitting (1 = rig already matched the mesh's units; 0.01 = cm rig snapped to a meter mesh). */ unitScale: number; /** 'embed' only: mapped bones whose rest orientation was re-aimed onto the source's segment direction (0 in 'repose'). */ restAimed: number; verticesProcessed: number; jointsRebuilt: number; /** warrior joint name -> helix joint that received its weights (via map, or nearest mapped ancestor) */ weightTargets: Record; } export interface ConformOptions { /** * 'embed' (default): keep the source mesh EXACTLY (no distortion), embed the canonical skeleton at the * source's own joint positions with canonical orientations. 'repose': re-pose the mesh onto the * canonical rest via frame-based deltas (mesh conforms to canonical proportions — use only when a rig * with canonical proportions is wanted over preserving the source character's silhouette). */ mode?: 'embed' | 'repose'; } /** * Retargets a source character onto `helix-humanoid@1` so the PLATFORM's shared clips drive it. * * 'embed' (default, the better retarget): the source mesh is left byte-for-byte unchanged and the * canonical 68-bone skeleton is fitted INTO it (segment-aimed canonical orientations at the source's * joint positions, §fitSkeletonToWarrior). Clips — authored as local rotations relative to the canonical * rest — produce the correct WORLD-space motion regardless of the source's bone-axis convention or bind * pose, because the aimed rests subtract the source-bind-vs-canonical direction delta at the IBM. Output * IBMs = inverse(fitted world), so LBS at rest reproduces the pristine source bind pose. * * 'repose' re-poses the mesh onto the canonical rest via frame-based rest-pose correction (kept for * cases wanting canonical proportions); it reshapes the mesh and is not the default. * * Source joints with no map entry fold onto their nearest mapped ancestor. */ export declare function conformToHelixRest(warrior: Document, canon: CanonicalSkeleton, boneMap: BoneMap, opts?: ConformOptions): ConformResult;