@bitmagic/cli 0.1.66-dev.6 → 0.1.66-dev.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -1
- package/assets/blender-level/find_blender.py +3 -1
- package/assets/character-skin-authoring/SKILL.md +43 -0
- package/assets/character-skin-authoring/references/exporters.md +134 -0
- package/assets/character-skin-authoring/references/eyes.md +215 -0
- package/assets/character-skin-authoring/references/materials.md +115 -0
- package/assets/character-skin-authoring/references/playground.md +78 -0
- package/assets/character-skin-authoring/references/profiles.md +97 -0
- package/assets/character-skin-authoring/references/projection.md +190 -0
- package/assets/character-skin-authoring/references/regional-detail.md +72 -0
- package/assets/character-skin-authoring/scripts/assemble_character.py +205 -0
- package/assets/character-skin-authoring/scripts/authored_detail.py +47 -0
- package/assets/character-skin-authoring/scripts/authored_surface_patch.py +83 -0
- package/assets/character-skin-authoring/scripts/brow_groom.py +62 -0
- package/assets/character-skin-authoring/scripts/build_face_detail.py +107 -0
- package/assets/character-skin-authoring/scripts/build_surface_candidate.py +28 -0
- package/assets/character-skin-authoring/scripts/canthus_wall.py +57 -0
- package/assets/character-skin-authoring/scripts/character_build.py +54 -0
- package/assets/character-skin-authoring/scripts/eye_assets.py +333 -0
- package/assets/character-skin-authoring/scripts/eye_opening.py +114 -0
- package/assets/character-skin-authoring/scripts/eye_texture.py +35 -0
- package/assets/character-skin-authoring/scripts/eyelid_detail.py +34 -0
- package/assets/character-skin-authoring/scripts/eyelid_morph.py +171 -0
- package/assets/character-skin-authoring/scripts/eyelid_patch.py +173 -0
- package/assets/character-skin-authoring/scripts/face_atlas.py +51 -0
- package/assets/character-skin-authoring/scripts/geometry_repair.py +112 -0
- package/assets/character-skin-authoring/scripts/glb_arrays.py +13 -0
- package/assets/character-skin-authoring/scripts/glb_output.py +21 -0
- package/assets/character-skin-authoring/scripts/inspect_skin_point.py +66 -0
- package/assets/character-skin-authoring/scripts/normal_patch_height.py +38 -0
- package/assets/character-skin-authoring/scripts/prepare_face_reference.py +23 -0
- package/assets/character-skin-authoring/scripts/regional_atlas.py +51 -0
- package/assets/character-skin-authoring/scripts/select_preview.py +90 -0
- package/assets/character-skin-authoring/scripts/skin_views.py +267 -0
- package/assets/character-skin-authoring/scripts/surface_pbr_maps.py +46 -0
- package/assets/character-skin-authoring/scripts/texture_repair.py +98 -0
- package/assets/character-skin-authoring/scripts/vertex_detail_support.py +80 -0
- package/assets/character-skin-authoring/scripts/vision_blend_materials.py +74 -0
- package/assets/character-skin-authoring/scripts/vision_materials.py +276 -0
- package/assets/character-skin-authoring/scripts/workspace_paths.py +18 -0
- package/assets/metahuman/src/work/metahuman/MetaHumanActor.ts +580 -0
- package/assets/metahuman/src/work/metahuman/MetaHumanLabHooks.ts +122 -0
- package/assets/metahuman/src/work/metahuman/MetaHumanMaterials.ts +500 -0
- package/assets/metahuman/src/work/metahuman/MetaHumanSpeech.ts +242 -0
- package/assets/metahuman/src/work/metahuman/StudioEnvironment.ts +142 -0
- package/assets/metahuman/tools/lipsync/make_line.py +181 -0
- package/assets/metahuman/tools/metahuman/README.md +21 -0
- package/assets/metahuman/tools/metahuman/e2e/eval.mjs +34 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/arm-pose-check.js +32 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/bone-displacement.js +26 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/clip-shoulder.js +41 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/grafted-bones.js +11 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/helper-follow-descent.js +38 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/helper-follow-sweep.js +31 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/helper-joints-inspect.js +10 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/outfit-bad-vertices.js +26 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/outfit-body-material.js +7 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/outfit-own-skeleton.js +8 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/shirt-bone-ownership.js +25 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/shirt-edge-stretch.js +26 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/shirt-long-edges.js +23 -0
- package/assets/metahuman/tools/metahuman/e2e/probes/walk-sampler.js +105 -0
- package/assets/metahuman/tools/metahuman/e2e/shot.mjs +125 -0
- package/assets/metahuman/tools/metahuman/e2e/walk-probe.mjs +43 -0
- package/assets/metahuman/tools/metahuman/merge-skeletons.mjs +69 -0
- package/assets/metahuman/tools/metahuman/package.json +13 -0
- package/assets/metahuman/tools/metahuman/prepare.sh +25 -0
- package/assets/metahuman/tools/metahuman/reorder-body-first.mjs +20 -0
- package/assets/metahuman/tools/metahuman/smooth-outfit-weights.mjs +48 -0
- package/assets/metahuman/tools/metahuman/strip-draco.mjs +32 -0
- package/assets/metahuman/tools/metahuman/transfer-skin-weights.mjs +90 -0
- package/dist/assets/voxelize-glb.d.ts +5 -1
- package/dist/assets/voxelize-glb.js +1 -0
- package/dist/assets/voxelize-glb.js.map +1 -1
- package/dist/assets/vxl-summary.js +2 -2
- package/dist/commands/generate.d.ts +62 -0
- package/dist/commands/generate.js +241 -2
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/init.js +2 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/judge.js +5 -0
- package/dist/commands/judge.js.map +1 -1
- package/dist/commands/verify.js +7 -0
- package/dist/commands/verify.js.map +1 -1
- package/dist/generate/audio-file.d.ts +6 -0
- package/dist/generate/audio-file.js +42 -0
- package/dist/generate/audio-file.js.map +1 -0
- package/dist/generate/model.js +3 -3
- package/dist/generate/model.js.map +1 -1
- package/dist/generate/music.d.ts +4 -3
- package/dist/generate/music.js +6 -23
- package/dist/generate/music.js.map +1 -1
- package/dist/generate/prop.d.ts +19 -1
- package/dist/generate/prop.js +34 -6
- package/dist/generate/prop.js.map +1 -1
- package/dist/generate/stream.d.ts +20 -0
- package/dist/generate/stream.js +15 -1
- package/dist/generate/stream.js.map +1 -1
- package/dist/scaffold/asset-pipeline-skill-files.js +6 -1
- package/dist/scaffold/asset-pipeline-skill-files.js.map +1 -1
- package/dist/scaffold/character-skin-skill-files.d.ts +2 -0
- package/dist/scaffold/character-skin-skill-files.js +49 -0
- package/dist/scaffold/character-skin-skill-files.js.map +1 -0
- package/dist/scaffold/metahuman-skill-files.d.ts +21 -0
- package/dist/scaffold/metahuman-skill-files.js +306 -0
- package/dist/scaffold/metahuman-skill-files.js.map +1 -0
- package/dist/scaffold/project-files.js +28 -19
- package/dist/scaffold/project-files.js.map +1 -1
- package/dist/scaffold/project.js +4 -0
- package/dist/scaffold/project.js.map +1 -1
- package/dist/scaffold/skill-files.js +4 -2
- package/dist/scaffold/skill-files.js.map +1 -1
- package/dist/telemetry/command-context.d.ts +23 -0
- package/dist/telemetry/command-context.js +11 -0
- package/dist/telemetry/command-context.js.map +1 -1
- package/dist/telemetry/report.d.ts +1 -0
- package/dist/telemetry/report.js +4 -1
- package/dist/telemetry/report.js.map +1 -1
- package/dist/tools/bundles.js +8 -0
- package/dist/tools/bundles.js.map +1 -1
- package/dist/verify/browser.js +25 -0
- package/dist/verify/browser.js.map +1 -1
- package/dist/verify/categories.d.ts +16 -0
- package/dist/verify/categories.js +51 -0
- package/dist/verify/categories.js.map +1 -0
- package/package.json +10 -7
package/dist/generate/stream.js
CHANGED
|
@@ -64,26 +64,40 @@ function asMusicOutcome(value) {
|
|
|
64
64
|
}
|
|
65
65
|
return { musicUrl, originalUrl, musicId, durationSeconds };
|
|
66
66
|
}
|
|
67
|
+
/** Same degrade-to-absent rule as `asMusicOutcome`, for the same reason. */
|
|
68
|
+
function asSpeechOutcome(value) {
|
|
69
|
+
if (!isRecord(value))
|
|
70
|
+
return null;
|
|
71
|
+
const { speechUrl, originalUrl, speechId, durationSeconds } = value;
|
|
72
|
+
if (typeof speechUrl !== 'string' || typeof originalUrl !== 'string' || typeof speechId !== 'string'
|
|
73
|
+
|| typeof durationSeconds !== 'number' || !Number.isFinite(durationSeconds)) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return { speechUrl, originalUrl, speechId, durationSeconds };
|
|
77
|
+
}
|
|
67
78
|
function asGenerationOutcome(data) {
|
|
68
79
|
if (!isRecord(data))
|
|
69
80
|
return null;
|
|
70
|
-
const { success, message, patches, glbUrl, masterUrl, imageUrl, vehicle, library, music } = data;
|
|
81
|
+
const { success, message, patches, glbUrl, masterUrl, imageUrl, vehicle, library, music, speech, smartObject } = data;
|
|
71
82
|
if (typeof success !== 'boolean' || typeof message !== 'string' || !Array.isArray(patches)) {
|
|
72
83
|
return null;
|
|
73
84
|
}
|
|
74
85
|
const vehicleOutcome = asVehicleOutcome(vehicle);
|
|
75
86
|
const libraryOutcome = asLibraryOutcome(library);
|
|
76
87
|
const musicOutcome = asMusicOutcome(music);
|
|
88
|
+
const speechOutcome = asSpeechOutcome(speech);
|
|
77
89
|
return {
|
|
78
90
|
success,
|
|
79
91
|
message,
|
|
80
92
|
patches: patches,
|
|
81
93
|
...(typeof glbUrl === 'string' ? { glbUrl } : {}),
|
|
82
94
|
...(typeof masterUrl === 'string' ? { masterUrl } : {}),
|
|
95
|
+
...(isRecord(smartObject) ? { smartObject: smartObject } : {}),
|
|
83
96
|
...(typeof imageUrl === 'string' ? { imageUrl } : {}),
|
|
84
97
|
...(vehicleOutcome ? { vehicle: vehicleOutcome } : {}),
|
|
85
98
|
...(libraryOutcome ? { library: libraryOutcome } : {}),
|
|
86
99
|
...(musicOutcome ? { music: musicOutcome } : {}),
|
|
100
|
+
...(speechOutcome ? { speech: speechOutcome } : {}),
|
|
87
101
|
};
|
|
88
102
|
}
|
|
89
103
|
async function readJsonBody(response) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/generate/stream.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/generate/stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -74,6 +74,9 @@ usage\` is the truth about what was actually spent.
|
|
|
74
74
|
|
|
75
75
|
## Decide, say so, ask only when it is expensive
|
|
76
76
|
|
|
77
|
+
**Ask first only when the route is tens of sparks or many minutes AND the purpose is unsaid; everything
|
|
78
|
+
else you decide, and say the assumption out loud before running it.**
|
|
79
|
+
|
|
77
80
|
Default: you decide, and state the assumption in one line before running anything:
|
|
78
81
|
|
|
79
82
|
> Assuming *prototype*: using \`<route>\` (~N sparks, ~T). Say "polished" and I will use \`<alt>\`.
|
|
@@ -111,6 +114,7 @@ Rows are in recommended order: take the first whose conditions hold.
|
|
|
111
114
|
| \`bitmagic character search\` then \`bitmagic character add\` | prototype; any plausible ready-made body will do | free, instant | \`search\` lists the closest library bodies and changes nothing; \`add\` takes one and never forges. Judge the match yourself — a score says "plausible", not "right" |
|
|
112
115
|
| \`bitmagic character generate\` | the look is genuinely custom; the whole cast will be highres | free and seconds on a library match; else ~15 sparks, ~1.5–4 min (voxel) or ~60 sparks, ~3 min (low-poly) | Library-first by default; a custom head scale or mesh model always forges. It can set the player directly |
|
|
113
116
|
| \`bitmagic character generate\`, forced fresh | polished; exactly this one, no library substitute | ~15 (voxel) / ~60 (low-poly) sparks; minutes | The costly row: ask first if purpose is unknown |
|
|
117
|
+
| \`${PRIMARY_SKILLS_DIR}/importing-metahumans/SKILL.md\` | the creator wants an Epic MetaHuman, an Unreal character, "photoreal" / the highest fidelity | free in sparks; an hour, ~45 MB per character | Not a generator: a prepared export loaded as the high-res player (WebGPU). The whole cast goes highres with it |
|
|
114
118
|
|
|
115
119
|
### A building or landmark
|
|
116
120
|
|
|
@@ -134,7 +138,7 @@ Rows are in recommended order: take the first whose conditions hold.
|
|
|
134
138
|
|
|
135
139
|
| Route | Conditions | ~Cost | Notes |
|
|
136
140
|
|---|---|---|---|
|
|
137
|
-
| \`bitmagic generate vehicle\` from a preset (
|
|
141
|
+
| \`bitmagic generate vehicle\` from a preset (\`--help\` names the preset flag; give it \`?\` to list the names) | no bespoke look needed; prototype | free; ~a minute (Chrome) | Physics, lights, AI built in either way; spawn via \`engine.getVehicleSpawner().spawnAndEnterFromAsset(...)\` |
|
|
138
142
|
| \`bitmagic generate vehicle\` from a description | the look is the point | usage-priced, several sparks; several minutes | NEW asset each run; ask first when purpose is unknown |
|
|
139
143
|
|
|
140
144
|
### A weapon
|
|
@@ -186,6 +190,7 @@ Rows are in recommended order: take the first whose conditions hold.
|
|
|
186
190
|
| \`bitmagic assets add\` | the creator has the track | free | |
|
|
187
191
|
| \`bitmagic generate sound\` | they asked for a premium or generated effect | ~12 sparks; ~30 s | One prompt, one effect |
|
|
188
192
|
| \`bitmagic generate music\` | they asked for original music | ~0.25 sparks/s (30 s ≈ 8, 120 s ≈ 30); ~a minute | Ask first for a long track when purpose is unknown; it can write a file instead of a world asset, for a trailer bed |
|
|
193
|
+
| \`bitmagic generate speech\` | they asked for a spoken line: NPC dialogue, narration | ~0.25 sparks/s (a sentence ≈ 1 spark); a few seconds | A one-shot, not a loop; pick a voice or bring a cloned one. Like music it can write a file instead of a world asset — that file is what the lip-sync tool takes |
|
|
189
194
|
|
|
190
195
|
### A cutscene or video
|
|
191
196
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-pipeline-skill-files.js","sourceRoot":"","sources":["../../src/scaffold/asset-pipeline-skill-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,yBAAyB;IACvC,OAAO;;;;;;;;;;;uCAW8B,kBAAkB
|
|
1
|
+
{"version":3,"file":"asset-pipeline-skill-files.js","sourceRoot":"","sources":["../../src/scaffold/asset-pipeline-skill-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,UAAU,yBAAyB;IACvC,OAAO;;;;;;;;;;;uCAW8B,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuCpD,kBAAkB;;;;;;;;;;;;MAYjB,kBAAkB;MAClB,kBAAkB;;;;;;;;;;MAUlB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAoFI,kBAAkB;;;;;;;uDAOS,kBAAkB;;CAExE,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Vision-led skin authoring: one maintained asset set for every supported agent. */
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { packageAssetsDir } from '../tools/bundles.js';
|
|
5
|
+
const files = [
|
|
6
|
+
'SKILL.md',
|
|
7
|
+
'references/projection.md',
|
|
8
|
+
'references/materials.md',
|
|
9
|
+
'references/exporters.md',
|
|
10
|
+
'references/profiles.md',
|
|
11
|
+
'references/regional-detail.md',
|
|
12
|
+
'references/playground.md',
|
|
13
|
+
'references/eyes.md',
|
|
14
|
+
'scripts/assemble_character.py',
|
|
15
|
+
'scripts/authored_detail.py',
|
|
16
|
+
'scripts/authored_surface_patch.py',
|
|
17
|
+
'scripts/brow_groom.py',
|
|
18
|
+
'scripts/build_face_detail.py',
|
|
19
|
+
'scripts/build_surface_candidate.py',
|
|
20
|
+
'scripts/canthus_wall.py',
|
|
21
|
+
'scripts/character_build.py',
|
|
22
|
+
'scripts/eye_assets.py',
|
|
23
|
+
'scripts/eye_opening.py',
|
|
24
|
+
'scripts/eye_texture.py',
|
|
25
|
+
'scripts/eyelid_detail.py',
|
|
26
|
+
'scripts/eyelid_morph.py',
|
|
27
|
+
'scripts/eyelid_patch.py',
|
|
28
|
+
'scripts/face_atlas.py',
|
|
29
|
+
'scripts/glb_arrays.py',
|
|
30
|
+
'scripts/glb_output.py',
|
|
31
|
+
'scripts/inspect_skin_point.py',
|
|
32
|
+
'scripts/normal_patch_height.py',
|
|
33
|
+
'scripts/prepare_face_reference.py',
|
|
34
|
+
'scripts/regional_atlas.py',
|
|
35
|
+
'scripts/select_preview.py',
|
|
36
|
+
'scripts/skin_views.py',
|
|
37
|
+
'scripts/surface_pbr_maps.py',
|
|
38
|
+
'scripts/texture_repair.py',
|
|
39
|
+
'scripts/geometry_repair.py',
|
|
40
|
+
'scripts/vertex_detail_support.py',
|
|
41
|
+
'scripts/vision_blend_materials.py',
|
|
42
|
+
'scripts/vision_materials.py',
|
|
43
|
+
'scripts/workspace_paths.py',
|
|
44
|
+
];
|
|
45
|
+
export const CHARACTER_SKIN_SKILLS = files.map((file) => [
|
|
46
|
+
`character-skin-authoring/${file}`,
|
|
47
|
+
() => fs.readFileSync(path.join(packageAssetsDir(), 'character-skin-authoring', file), 'utf8'),
|
|
48
|
+
]);
|
|
49
|
+
//# sourceMappingURL=character-skin-skill-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"character-skin-skill-files.js","sourceRoot":"","sources":["../../src/scaffold/character-skin-skill-files.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,MAAM,KAAK,GAAG;IACZ,UAAU;IACV,0BAA0B;IAC1B,yBAAyB;IACzB,yBAAyB;IACzB,wBAAwB;IACxB,+BAA+B;IAC/B,0BAA0B;IAC1B,oBAAoB;IACpB,+BAA+B;IAC/B,4BAA4B;IAC5B,mCAAmC;IACnC,uBAAuB;IACvB,8BAA8B;IAC9B,oCAAoC;IACpC,yBAAyB;IACzB,4BAA4B;IAC5B,uBAAuB;IACvB,wBAAwB;IACxB,wBAAwB;IACxB,0BAA0B;IAC1B,yBAAyB;IACzB,yBAAyB;IACzB,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,+BAA+B;IAC/B,gCAAgC;IAChC,mCAAmC;IACnC,2BAA2B;IAC3B,2BAA2B;IAC3B,uBAAuB;IACvB,6BAA6B;IAC7B,2BAA2B;IAC3B,4BAA4B;IAC5B,kCAAkC;IAClC,mCAAmC;IACnC,6BAA6B;IAC7B,4BAA4B;CAC7B,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAmC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;IACvF,4BAA4B,IAAI,EAAE;IAClC,GAAG,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,0BAA0B,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC;CAC/F,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `importing-metahumans` skill: an Epic MetaHuman glTF export (UE 5.7, the smorchj/metahuman-to-glb
|
|
3
|
+
* pipeline) brought in as the engine's high-res player — the GLB preparation, the retarget and
|
|
4
|
+
* helper-joint fixes, the material upgrades, lip-sync, and the numeric verification. Distilled from a
|
|
5
|
+
* lab game (Epic's "Bo" preset, September 2026) whose agent met every failure the skill now names by
|
|
6
|
+
* symptom: a model that loads as nothing (Draco), a face and body animating apart (three skeleton
|
|
7
|
+
* copies), arms crossed into the chest (A-pose bind vs Mixamo's T-pose), a shirt torn at the armpits
|
|
8
|
+
* (pose-driven helper joints), hair left behind by a head turn (unskinned cards), tinted skin (rig
|
|
9
|
+
* masks in COLOR_0) and black eyes (the eye shell's UVs).
|
|
10
|
+
*
|
|
11
|
+
* Same contract as `blender-level-skill-files.ts`: a pure function returning file contents,
|
|
12
|
+
* registered in `SHIPPED_SKILLS` (project.ts). The code the skill relies on — the runtime module
|
|
13
|
+
* (`src/work/metahuman/`), the GLB scripts, the lip-sync tool and the verification rig — ships in the
|
|
14
|
+
* package's `assets/metahuman/` and lands at the project root through `bitmagic tools install
|
|
15
|
+
* metahuman` (`tools/bundles.ts`), so the skill only ever names files the package holds
|
|
16
|
+
* (`__tests__/metahuman-assets.test.ts` checks that).
|
|
17
|
+
*
|
|
18
|
+
* Backticks and `${` are escaped for the template literal; `project-files.test.ts` checks the rendered
|
|
19
|
+
* frontmatter and that no escape leaks into the output.
|
|
20
|
+
*/
|
|
21
|
+
export declare function renderMetaHumanSkill(): string;
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `importing-metahumans` skill: an Epic MetaHuman glTF export (UE 5.7, the smorchj/metahuman-to-glb
|
|
3
|
+
* pipeline) brought in as the engine's high-res player — the GLB preparation, the retarget and
|
|
4
|
+
* helper-joint fixes, the material upgrades, lip-sync, and the numeric verification. Distilled from a
|
|
5
|
+
* lab game (Epic's "Bo" preset, September 2026) whose agent met every failure the skill now names by
|
|
6
|
+
* symptom: a model that loads as nothing (Draco), a face and body animating apart (three skeleton
|
|
7
|
+
* copies), arms crossed into the chest (A-pose bind vs Mixamo's T-pose), a shirt torn at the armpits
|
|
8
|
+
* (pose-driven helper joints), hair left behind by a head turn (unskinned cards), tinted skin (rig
|
|
9
|
+
* masks in COLOR_0) and black eyes (the eye shell's UVs).
|
|
10
|
+
*
|
|
11
|
+
* Same contract as `blender-level-skill-files.ts`: a pure function returning file contents,
|
|
12
|
+
* registered in `SHIPPED_SKILLS` (project.ts). The code the skill relies on — the runtime module
|
|
13
|
+
* (`src/work/metahuman/`), the GLB scripts, the lip-sync tool and the verification rig — ships in the
|
|
14
|
+
* package's `assets/metahuman/` and lands at the project root through `bitmagic tools install
|
|
15
|
+
* metahuman` (`tools/bundles.ts`), so the skill only ever names files the package holds
|
|
16
|
+
* (`__tests__/metahuman-assets.test.ts` checks that).
|
|
17
|
+
*
|
|
18
|
+
* Backticks and `${` are escaped for the template literal; `project-files.test.ts` checks the rendered
|
|
19
|
+
* frontmatter and that no escape leaks into the output.
|
|
20
|
+
*/
|
|
21
|
+
export function renderMetaHumanSkill() {
|
|
22
|
+
return `---
|
|
23
|
+
name: importing-metahumans
|
|
24
|
+
description: Bring an Epic MetaHuman (a UE 5.7 glTF export) into this game as the playable, animated, talking high-fidelity character without voxelizing it — prepare the GLB (Draco, one skeleton, body mesh first, garment weights), load it as the engine's high-res player, fix the A-pose retarget and the pose-driven helper joints, keep the hair on the head, upgrade skin / hair / eye materials, add life and lip-sync, and verify with numbers. Use it when a creator asks for a MetaHuman, an Unreal character, a "photoreal" or "highest fidelity" character — or when such a character shows floating hair, crossed arms, split legs, a torn shirt, tinted skin, black eyes, slumped shoulders or sliding feet.
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# Importing a MetaHuman
|
|
28
|
+
|
|
29
|
+
A MetaHuman export is a 40–80 MB skinned GLB with 51 ARKit blendshapes, hair as textured cards and a
|
|
30
|
+
UE5 skeleton with hundreds of pose-driven helper joints. The engine can load it as the player's
|
|
31
|
+
**high-res character** and drive it with its own Mixamo locomotion — but the raw export loads as
|
|
32
|
+
nothing (Draco), animates in pieces (three skeleton copies), stands with its arms crossed into its
|
|
33
|
+
chest (A-pose bind), tears its shirt at the armpits (helper joints), leaves its hair behind when it
|
|
34
|
+
turns its head (unskinned cards), and renders with tinted skin and black eyes (rig masks, eye shell).
|
|
35
|
+
Every one of those was met and fixed on Epic's "Bo" preset in a lab game (September 2026); this
|
|
36
|
+
skill is that path, in order, with the tools that do it. Everything it names ships with the CLI:
|
|
37
|
+
|
|
38
|
+
\`\`\`
|
|
39
|
+
bitmagic tools install metahuman
|
|
40
|
+
\`\`\`
|
|
41
|
+
|
|
42
|
+
lands, at the project root:
|
|
43
|
+
|
|
44
|
+
| Path | Does |
|
|
45
|
+
|---|---|
|
|
46
|
+
| \`src/work/metahuman/MetaHumanActor.ts\` | adopts the engine-loaded player model, re-parents the hair cards, fixes the arm retarget, applies the helper-joint policy, blinks / saccades / breathing / head look-at, morph access |
|
|
47
|
+
| \`src/work/metahuman/MetaHumanMaterials.ts\` | upgrades every material by name: skin SSS, hair/brow card atlas, lashes, eyes; hides the export's helper meshes |
|
|
48
|
+
| \`src/work/metahuman/MetaHumanSpeech.ts\` | plays a line and drives the ARKit mouth shapes from mouth cues (+ amplitude fallback); clock-driven mode for the frame recorder |
|
|
49
|
+
| \`src/work/metahuman/StudioEnvironment.ts\` | HDRI image-based lighting that survives the engine's ambient-lighting re-applies; optional separate sky map |
|
|
50
|
+
| \`src/work/metahuman/MetaHumanLabHooks.ts\` | installs \`window.__lab\`, the handle the rigs below drive |
|
|
51
|
+
| \`tools/metahuman/prepare.sh\` + five \`.mjs\` scripts | the GLB preparation, one command (needs Node ≥ 18; \`npm install\` runs on first use) |
|
|
52
|
+
| \`tools/metahuman/e2e/\` | \`shot.mjs\`, \`eval.mjs\`, \`walk-probe.mjs\` and \`probes/\` — headless Chrome stills and measurements |
|
|
53
|
+
| \`tools/lipsync/make_line.py\` | TTS audio → forced alignment → mouth cues (\`assets/speech/<id>.{m4a,json}\`) |
|
|
54
|
+
|
|
55
|
+
Nothing in them is character-specific: the scripts find meshes by the export's naming
|
|
56
|
+
(\`SKM_<name>_FaceMesh\`, \`SKM_<name>_BodyMesh\`, \`<name>_Outfits\`) and the actor classifies materials
|
|
57
|
+
by name. \`tools/metahuman/README.md\` is the index.
|
|
58
|
+
|
|
59
|
+
## 0. Before you start
|
|
60
|
+
|
|
61
|
+
- **WebGPU.** The skin, hair and eye upgrades are TSL node materials on three's WebGPU build (the
|
|
62
|
+
engine default). The WebGL fallback keeps plain glTF PBR with scalar tweaks — acceptable, not
|
|
63
|
+
photoreal. \`bitmagic verify\` prints which backend booted.
|
|
64
|
+
- **Licence.** Since June 2025 Epic allows MetaHumans in non-Unreal products; the export pipeline
|
|
65
|
+
below is MIT. Record both in an \`assets/LICENSES.md\` and check the current MetaHuman terms before
|
|
66
|
+
a commercial release.
|
|
67
|
+
- **Budget.** One character is ~45 MB of GLB plus two 4K atlases. Publish uploads it (step 8). The
|
|
68
|
+
whole cast goes highres with it — highres and block characters never coexist.
|
|
69
|
+
- **Nothing else changes.** \`artStyle\` in \`game.json\` stays whatever the game is; a MetaHuman is a
|
|
70
|
+
loaded file, not a generated asset, and costs no sparks.
|
|
71
|
+
|
|
72
|
+
## 1. Get an export
|
|
73
|
+
|
|
74
|
+
The exports come from **smorchj/metahuman-to-glb** (UE 5.7 MetaHuman → Blender → Draco GLB with the
|
|
75
|
+
51 ARKit blendshapes). Ready-made characters sit in that repo under \`docs/5.7/characters/<name>/\`
|
|
76
|
+
(bo 41 MB, bruce 79 MB; \`docs/characters/\` holds ada and taro from the older 5.6 pipeline). Fetch
|
|
77
|
+
through \`raw.githubusercontent.com\` — they are plain files, not LFS. An export folder holds:
|
|
78
|
+
|
|
79
|
+
- \`<name>.glb\` — Draco-compressed; meshes \`SKM_<name>_FaceMesh\` (face skin, teeth, eyes, eye shell,
|
|
80
|
+
lacrimal fluid, lashes, an \`M_Hide\` helper), \`<name>_Outfits\` (garments), \`SKM_<name>_BodyMesh\`
|
|
81
|
+
(body skin — **no torso or upper thighs under the clothing**, the export culls them), plus the
|
|
82
|
+
hair / eyebrow / beard \`*_CardsMesh_*\` card meshes;
|
|
83
|
+
- \`textures/<Hair|Eyebrows>_*_CardsAtlas_Attribute.png\` — 4K card atlases, R = coverage, G = root→tip,
|
|
84
|
+
B = per-strand seed; \`T_Eyelashes_*_Coverage.png\` — the lash mask;
|
|
85
|
+
- \`mh_materials.json\` — the pipeline's material sheet (base colours, alpha channels, roughness).
|
|
86
|
+
Reference only.
|
|
87
|
+
|
|
88
|
+
What is inside, and why every step below exists: **three copies of the skeleton** (the face skin's
|
|
89
|
+
875 joints incl. \`FACIAL_*\`, the outfit's 342, the body's 342 — same names, same rest pose), the
|
|
90
|
+
face skin **stops at the upper arms**, the cards are **unskinned meshes posed at the head's rest
|
|
91
|
+
pose**, \`COLOR_0\` on every mesh is a **rig mask** (not albedo), the bind pose is an **A-pose**, and
|
|
92
|
+
the corrective joints (\`*_correctiveRoot_*\`, \`*_twistCor_*\`, bicep/tricep, clavicle scap/out/pec,
|
|
93
|
+
latissimus, wrist, ankle, finger helpers) are **pose-driven** in Unreal by RBF drivers the export
|
|
94
|
+
cannot carry.
|
|
95
|
+
|
|
96
|
+
## 2. Prepare the GLB — one command
|
|
97
|
+
|
|
98
|
+
\`\`\`
|
|
99
|
+
tools/metahuman/prepare.sh <export>/<name>.glb assets/metahuman/<name>/<name>.glb
|
|
100
|
+
mkdir -p assets/metahuman/<name>/textures
|
|
101
|
+
cp <export>/textures/*CardsAtlas_Attribute.png <export>/textures/T_Eyelashes_*Coverage.png assets/metahuman/<name>/textures/
|
|
102
|
+
\`\`\`
|
|
103
|
+
|
|
104
|
+
| Step | Script | Why | Without it |
|
|
105
|
+
|---|---|---|---|
|
|
106
|
+
| 1 | \`tools/metahuman/strip-draco.mjs\` | \`engine.loader\` is a plain GLTFLoader — no Draco, no KTX2 | the model never appears |
|
|
107
|
+
| 2 | \`tools/metahuman/merge-skeletons.mjs\` | grafts the limb subtrees from the body hierarchy onto the face hierarchy (asserts identical rest transforms) and re-points every skin at the one skeleton | each mesh follows its own copy: the face and body animate apart |
|
|
108
|
+
| 3 | \`tools/metahuman/reorder-body-first.mjs\` | the engine's \`CharacterLoader\` captures a rig's bind pose from the **first** skinned mesh it traverses, and the face skin has no forearms or legs | split legs, twisted forearms and hands (10 bones corrected instead of 52) |
|
|
109
|
+
| 4 | \`tools/metahuman/smooth-outfit-weights.mjs\` (shorts 6 × λ 0.5, shirt 12 × λ 0.6) | Laplacian-smooths the garment weights so hard seams (torso latissimus helper beside arm twist correctives) become gradients | 26 cm shards at the armpits under every arm swing |
|
|
110
|
+
| 5 | \`tools/metahuman/transfer-skin-weights.mjs\` (full ≤ 2 cm, blend to 4.5 cm) | gives garment vertices the skin's weights wherever skin lies under them (adds the face's neck joints to the outfit skin) | skin pokes through the shirt |
|
|
111
|
+
|
|
112
|
+
\`SHORT_RE\` / \`SHIRT_RE\` override the garment material regexes (the export names them
|
|
113
|
+
\`MID_..._Short_NN\` / \`MID_..._Shirt_NN\`); \`KEEP_STEPS=1\` keeps the intermediates. The tuned numbers
|
|
114
|
+
came from a torn-edge metric on the CPU-skinned outfit at the Mixamo idle (8038 torn edges raw →
|
|
115
|
+
≈300 after steps 3–5 plus the helper policy). Check the result: the scripts print the scene order
|
|
116
|
+
(\`SKM_<name>_BodyMesh → <name>_Outfits → SKM_<name>_FaceMesh\`), the skins and their joint counts, and
|
|
117
|
+
throw if a joint is unreachable or a duplicate does not match its twin.
|
|
118
|
+
|
|
119
|
+
## 3. Load it as the player
|
|
120
|
+
|
|
121
|
+
\`src/work/world.json\`, in \`worldProfileData\`:
|
|
122
|
+
|
|
123
|
+
\`\`\`json
|
|
124
|
+
"characterUrl": "/assets/metahuman/bo/bo.glb",
|
|
125
|
+
"useHighResCharacter": true,
|
|
126
|
+
"characterConfig": { "height": 1.83, "walkSpeed": 1.4, "runSpeed": 2.4, "fastRunSpeed": 4 }
|
|
127
|
+
\`\`\`
|
|
128
|
+
|
|
129
|
+
and three animation assets in \`assets[]\` — the Mixamo viewer set — because the engine's \`generated\`
|
|
130
|
+
animation library plays the authored Idle but swaps Walk and Run for motion-captured clips whose
|
|
131
|
+
neutral shoulders sit ~20° lower (a visible slump on ANY character, only while walking):
|
|
132
|
+
|
|
133
|
+
\`\`\`json
|
|
134
|
+
{ "id": "mMixamoIdleViewer", "type": "animation", "locomotionState": "idle", "url": "https://mini.bitmagic.ai/worlds/v3/animations_brotli/NewIdle.glb" },
|
|
135
|
+
{ "id": "mMixamoWalkViewer", "type": "animation", "locomotionState": "walk", "url": "https://mini.bitmagic.ai/worlds/v3/animations_brotli/NewWalk.glb" },
|
|
136
|
+
{ "id": "mMixamoRunViewer", "type": "animation", "locomotionState": "run", "url": "https://mini.bitmagic.ai/worlds/v3/animations_brotli/NewRun.glb" }
|
|
137
|
+
\`\`\`
|
|
138
|
+
|
|
139
|
+
\`src/work/Game.ts\`: after \`setupPlayerController()\` and \`playerLoader.enablePlayerGravity()\`, adopt
|
|
140
|
+
the model the engine loaded (do NOT await slow downloads first — see fix 10), install the hooks, and
|
|
141
|
+
update the actor every frame:
|
|
142
|
+
|
|
143
|
+
\`\`\`ts
|
|
144
|
+
import { MetaHumanActor } from './metahuman/MetaHumanActor.js';
|
|
145
|
+
import { DEFAULT_HAIR, DEFAULT_BROWS } from './metahuman/MetaHumanMaterials.js';
|
|
146
|
+
import { installMetaHumanLabHooks } from './metahuman/MetaHumanLabHooks.js';
|
|
147
|
+
|
|
148
|
+
const bloomOn = this.worldProfileData.bloomConfig?.enabled ?? false;
|
|
149
|
+
const actor = new MetaHumanActor(this.engine, {
|
|
150
|
+
url: '/assets/metahuman/bo/bo.glb',
|
|
151
|
+
yawOffset: 0, // the export faces +Z = engine gameplay-forward
|
|
152
|
+
materials: {
|
|
153
|
+
hairAtlasUrl: '/assets/metahuman/bo/textures/Hair_S_SideSweptFringe_CardsAtlas_Attribute.png',
|
|
154
|
+
browAtlasUrl: '/assets/metahuman/bo/textures/Eyebrows_M_Wide_CardsAtlas_Attribute.png',
|
|
155
|
+
lashCoverageUrl: '/assets/metahuman/bo/textures/T_Eyelashes_S_Sparse_Coverage.png',
|
|
156
|
+
hair: { ...DEFAULT_HAIR }, brows: { ...DEFAULT_BROWS },
|
|
157
|
+
msaa: !bloomOn, // alpha-to-coverage only on the direct MSAA canvas
|
|
158
|
+
},
|
|
159
|
+
life: { blink: true, saccades: true, breathing: true, lookAtCamera: true, maxHeadTurn: 0.55 },
|
|
160
|
+
});
|
|
161
|
+
const root = this.playerLoader.getSkinnedSkeletonRoot();
|
|
162
|
+
if (root) actor.adopt(root, root, this.playerLoader); // engine-driven locomotion
|
|
163
|
+
else { this.engine.getPlayerVisibility().hide(); await actor.load(); actor.attachToPlayer(this.player, this.playerLoader.getFeetOffsetY()); }
|
|
164
|
+
this.metaHuman = actor;
|
|
165
|
+
installMetaHumanLabHooks({ engine: this.engine, actor, playerLoader: this.playerLoader, player: this.player, cameraController: this.cameraController, playerController: this.playerController });
|
|
166
|
+
// in update(deltaTime):
|
|
167
|
+
this.metaHuman?.update(deltaTime, this.engine.getDefaultCamera().position);
|
|
168
|
+
\`\`\`
|
|
169
|
+
|
|
170
|
+
Facts the wiring leans on: the engine faces the player toward −Z (camera behind) — use
|
|
171
|
+
\`actor.getFacing()\` for face cameras and turn \`ThirdPersonCamera.setAutoFollow(false)\` off while one
|
|
172
|
+
is on; the export faces +Z so \`yawOffset\` is 0; the engine picks walk or run by speed
|
|
173
|
+
(\`walkToRunThreshold\`) and never rescales a clip, so anything that drives the character by script
|
|
174
|
+
(cinematics, NPC copies) must move at the clip's stride speed — \`characterConfig.runSpeed\` 2.4 m/s
|
|
175
|
+
here — or the feet slide.
|
|
176
|
+
|
|
177
|
+
## 4. The fixes, by symptom
|
|
178
|
+
|
|
179
|
+
Each is a method of \`MetaHumanActor\` or a preparation step; know which one you are looking at.
|
|
180
|
+
|
|
181
|
+
1. **Hair, brows or beard stay behind when the head turns** → the cards are unskinned →
|
|
182
|
+
\`attachCardsToHead\` re-parents every non-skinned mesh onto the \`head\` bone with \`Object3D.attach\`
|
|
183
|
+
at load, while the skeleton is at rest. Any new load path must keep it.
|
|
184
|
+
2. **Split legs, twisted forearms and hands** → bind captured from the face skin → preparation step 3.
|
|
185
|
+
3. **Arms 45° too low, crossed into the torso** → the engine's per-bone correction \`inv(B_src)·B_rig\`
|
|
186
|
+
assumes the rig binds in the clip's rest pose; MetaHumans bind in an A-pose, Mixamo rests in a
|
|
187
|
+
T-pose → \`patchArmRetarget\` rewrites the loader's cached \`skinnedRetargetDeltas\` with a virtual
|
|
188
|
+
T-pose per arm segment (thumbs forward). Check: upper-arm and forearm world directions equal the
|
|
189
|
+
Mixamo rig's, hands at x ≈ ±0.30 m beside the thighs (\`tools/metahuman/e2e/probes/arm-pose-check.js\`).
|
|
190
|
+
4. **Shirt tears at the armpits and shoulders** → pose-driven helper joints swing rigidly with the
|
|
191
|
+
limb → \`applyHelperJointPolicy\`: each helper family follows only a fraction of its parent's
|
|
192
|
+
rotation delta from bind (\`helperFollow\`, families shoulder / thigh / elbow / knee / twistCor /
|
|
193
|
+
muscle / clavicle / lat / wrist / ankle / finger; tuned by coordinate descent on the torn-edge
|
|
194
|
+
metric, \`tools/metahuman/e2e/probes/helper-follow-descent.js\`) — plus preparation steps 4–5.
|
|
195
|
+
5. **Skin shows through the garment** → the outfit's weights differ from the skin's under it →
|
|
196
|
+
preparation step 5 (smoothing alone made this WORSE; transfer fixed it).
|
|
197
|
+
6. **Skin is tinted / blotchy** → \`COLOR_0\`/\`COLOR_1\` are rig masks → every material gets
|
|
198
|
+
\`vertexColors = false\` (\`MetaHumanMaterials\`).
|
|
199
|
+
7. **Eyes are black** → the export's eye shell has UVs that are not eye-centred, so any occlusion
|
|
200
|
+
gradient blacks the eye out → the shell, lacrimal fluid and \`M_Hide\` are hidden
|
|
201
|
+
(\`eyeShellOcclusion: 0\`).
|
|
202
|
+
8. **Far-side hair shows through the skin over the ear** → the hair depth bias was too strong →
|
|
203
|
+
polygon offset factor −0.5 / units −1, not −4 / −16.
|
|
204
|
+
9. **Hair edges alias or halo** → alpha-to-coverage needs the direct MSAA canvas, which only exists
|
|
205
|
+
while bloom / post-FX are off → \`msaa: !bloomOn\`; with post-FX on, the cards use the blended fringe.
|
|
206
|
+
10. **Hair or helpers detached, only on slow machines** → rest data was read from bones that were
|
|
207
|
+
already animating → capture every rest quantity from the skins' inverse bind matrices and adopt
|
|
208
|
+
BEFORE awaiting the HDRI or atlases.
|
|
209
|
+
11. **Shoulders slump only while walking** → the animation library, not the rig → section 3's
|
|
210
|
+
Mixamo assets. Compare raw clip tracks across states (\`tools/metahuman/e2e/probes/clip-shoulder.js\`)
|
|
211
|
+
before touching rig code.
|
|
212
|
+
12. **Feet slide** when moved by script → speed below the clip's stride → section 3.
|
|
213
|
+
|
|
214
|
+
## 5. What the materials do
|
|
215
|
+
|
|
216
|
+
\`upgradeMetaHumanMaterials(root, options)\` classifies each material by name (\`classifyMaterial\`)
|
|
217
|
+
and replaces it in place — geometry untouched:
|
|
218
|
+
|
|
219
|
+
- **skin** (\`MI_Face_Skin_*\`, \`MI_Body_*\`): roughness floor and a wrap-lighting subsurface term in a
|
|
220
|
+
\`PhysicalLightingModel\` subclass (light through ears, nose, lips);
|
|
221
|
+
- **hair / brow cards**: the 4K atlas drives coverage (alpha-to-coverage or blended fringe clone),
|
|
222
|
+
root darkening, per-strand tint and roughness variance, a normal-based self-occlusion;
|
|
223
|
+
\`DEFAULT_HAIR\` / \`DEFAULT_BROWS\` are the dials (colour, anisotropy, blend mode);
|
|
224
|
+
- **lashes**: the 2K coverage mask, alpha-blended;
|
|
225
|
+
- **eyes**: wet cornea (near-mirror roughness + clearcoat);
|
|
226
|
+
- **hidden**: \`M_Hide\`, lacrimal, eye edge, saliva, the eye shell.
|
|
227
|
+
|
|
228
|
+
Typing note for edits: \`@types/three\` types TSL nodes as \`Node<'vec3'>\` etc. while the engine's
|
|
229
|
+
lighting-model inputs are bare \`Node\` — cast; and \`three\` resolves to the WebGPU build.
|
|
230
|
+
|
|
231
|
+
## 6. Life and speech
|
|
232
|
+
|
|
233
|
+
- \`life\` options blink, saccade, breathe and turn the head toward the camera as deltas on top of the
|
|
234
|
+
animated pose (rest-frame world-axis rotations). \`setSpeechEnergy\` adds brow lift and nods.
|
|
235
|
+
- **Lip-sync**: \`MetaHumanSpeech\` maps Rhubarb-style mouth shapes (A closed, B teeth, C open, D wide,
|
|
236
|
+
E rounded, F puckered, G F/V, H L, X rest) to ARKit weights with 60 ms co-articulation, jaw scaled
|
|
237
|
+
by loudness, amplitude-driven jaw when a line has no cues. Lines live in \`assets/speech/lines.json\`
|
|
238
|
+
(\`MetaHumanSpeech.loadLines\`), \`speak(line)\` plays one, \`update(dt)\` every frame,
|
|
239
|
+
\`actor.setSpeechEnergy(speech.getEnergy())\` for the accents.
|
|
240
|
+
- **Making a line**: \`tools/lipsync/make_line.py <id> "<transcript>" --audio <tts.mp3>\` — PocketSphinx
|
|
241
|
+
forced alignment in a venv (\`python3 -m venv tools/lipsync/.venv && tools/lipsync/.venv/bin/pip
|
|
242
|
+
install pocketsphinx\`), unknown words via its \`EXTRA_WORDS\` table. Make the audio with
|
|
243
|
+
\`bitmagic generate speech --text "<the line>" --voice <voice> --out <line>.mp3 --no-world\` —
|
|
244
|
+
\`--no-world\` because a lip-sync line is an input to this tool, not a world.json asset the game
|
|
245
|
+
plays on its own, and \`--out\` writes the MP3 \`make_line.py --audio\` expects. Any provider's file
|
|
246
|
+
works too. macOS \`say\` is a placeholder the creator will hear immediately; never ship it. For an
|
|
247
|
+
exact pause between sentences generate them separately and join with silence.
|
|
248
|
+
- **Under the frame recorder** (\`bitmagic trailer record\`) the game runs slower than real time:
|
|
249
|
+
\`speech.setClockDriven(true)\` advances the cues on the engine delta, log a \`speech-start\` game
|
|
250
|
+
event when the cue clock starts, and mux the audio afterwards at that frame.
|
|
251
|
+
|
|
252
|
+
## 7. Verify with numbers, not thumbnails
|
|
253
|
+
|
|
254
|
+
Thumbnails hid crossed arms, detached hair and a "fix" whose before/after frames were identical.
|
|
255
|
+
Crop and zoom the contact region, and cross-check one measured quantity. The rigs drive the GAME
|
|
256
|
+
page (the game port in \`.bitmagic/dev.json\`, one below the dev shell's) through the system Chrome;
|
|
257
|
+
\`npm install\` in \`tools/metahuman/\` once:
|
|
258
|
+
|
|
259
|
+
- \`node tools/metahuman/e2e/shot.mjs <port>\` — stills: wide, front, face, three-quarter, profile,
|
|
260
|
+
hair, eye macro, life on, head-turn; asserts the hair↔head distance is unchanged across a turn and
|
|
261
|
+
that holding W moves the player;
|
|
262
|
+
- \`node tools/metahuman/e2e/eval.mjs tools/metahuman/e2e/probes/<probe>.js <port>\` with
|
|
263
|
+
\`arm-pose-check.js\`, \`bone-displacement.js\`, \`shirt-edge-stretch.js\`, \`shirt-long-edges.js\`,
|
|
264
|
+
\`outfit-bad-vertices.js\`, \`shirt-bone-ownership.js\`, \`helper-follow-sweep.js\`,
|
|
265
|
+
\`helper-follow-descent.js\`, \`helper-joints-inspect.js\`, \`clip-shoulder.js\`, \`grafted-bones.js\`,
|
|
266
|
+
\`outfit-own-skeleton.js\`, \`outfit-body-material.js\`;
|
|
267
|
+
- \`node tools/metahuman/e2e/walk-probe.mjs <port>\` — walks for a few seconds and prints idle-vs-walk
|
|
268
|
+
statistics (\`walk-sampler.js\`: bone heights, skin-under-shirt penetration, clip shoulders);
|
|
269
|
+
- in the page: \`__lab.retargetInfo()\` and \`__lab.boneMap()\` dump the engine's pose map, bind
|
|
270
|
+
corrections and name resolution (52 bones should be corrected);
|
|
271
|
+
- \`bitmagic verify\` last — it boots the real browser and reports the backend and fps.
|
|
272
|
+
|
|
273
|
+
## 8. Ship it
|
|
274
|
+
|
|
275
|
+
Every \`/assets/...\` URL the game fetches works only under \`bitmagic dev\` and 404s in a published
|
|
276
|
+
bundle: register the GLB with \`bitmagic assets add assets/metahuman/<name>/<name>.glb --keep-glb\`
|
|
277
|
+
and point \`characterUrl\` at the returned URL; do the same for the atlases, the lash mask, the HDRI
|
|
278
|
+
and the speech files, or inline them. This is the one step written from the CLI's rules rather
|
|
279
|
+
than from having done it — the lab game was never published.
|
|
280
|
+
|
|
281
|
+
## 9. Engine internals this depends on (re-check after \`bitmagic upgrade\`)
|
|
282
|
+
|
|
283
|
+
Written against engine 3.1173: \`PlayerLoader.getSkinnedSkeletonRoot()\`, \`CharacterLoader\`'s alias
|
|
284
|
+
map (resolves UE / Manny bone names) and its private \`skinnedRetargetDeltas\` / \`skinnedBind\` that
|
|
285
|
+
\`patchArmRetarget\` rewrites, \`engine.getPlayerVisibility()\`, the \`generated\` animation library. After
|
|
286
|
+
an upgrade run the probes in section 7 before trusting a screenshot.
|
|
287
|
+
|
|
288
|
+
## Known gaps
|
|
289
|
+
|
|
290
|
+
Shoulder / armpit fidelity (the RBF pose drivers are not in the export — real emulation or a
|
|
291
|
+
re-skin of the garment to the primary bones would fix it), scalp visible under thin hair cards, no
|
|
292
|
+
eye-socket occlusion, fingers keep the A-pose curl under Mixamo hand poses, the WebGL path is plain
|
|
293
|
+
PBR.
|
|
294
|
+
|
|
295
|
+
## Checklist
|
|
296
|
+
|
|
297
|
+
- [ ] export fetched, licence recorded in \`assets/LICENSES.md\`
|
|
298
|
+
- [ ] \`bitmagic tools install metahuman\`; \`tools/metahuman/prepare.sh\` ran clean: body mesh first, one skeleton, garment weights done
|
|
299
|
+
- [ ] atlases + lash mask copied; \`characterUrl\` + \`useHighResCharacter\` + Mixamo animation assets in world.json
|
|
300
|
+
- [ ] actor adopted BEFORE slow loads; hooks installed; \`actor.update\` every frame
|
|
301
|
+
- [ ] \`bitmagic check\`; shots + probes: hair follows the head, arms level with the Mixamo rig, ≈300 torn edges, no skin through the shirt
|
|
302
|
+
- [ ] \`bitmagic verify\` on WebGPU; speech line from a real TTS voice
|
|
303
|
+
- [ ] before publish: every \`/assets/...\` URL registered with \`bitmagic assets add\`
|
|
304
|
+
`;
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=metahuman-skill-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metahuman-skill-files.js","sourceRoot":"","sources":["../../src/scaffold/metahuman-skill-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,UAAU,oBAAoB;IAClC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0RR,CAAC;AACF,CAAC"}
|