Invocation

legaia-engine export-glb --scene town01 --out glb-export       # one scene
legaia-engine export-glb --all-scenes --out glb-export         # everything
legaia-engine export-glb --items --out glb-export              # every equipment item
legaia-engine export-glb --party --out glb-export              # Vahn, Noa, Gala field forms

It reads extracted/ or --disc <image.bin>. --scale sets glTF metres per PSX unit (default 1/128: one 128-unit walk tile is one metre, which reads right against a headset's real player scale). --include-sky keeps the sky shells the site viewers hide; --no-npcs and --no-props drop those families. --all-scenes skips cutscene labels, reports each scene's yield and continues past failures.

What one scene exports

glb-export/town01/
├── town01.glb        the assembled world (+ baked morph animation)
├── npcs/*.glb        one animated glb per catalogued placement
├── props/*.glb       animated placed props (windmills, doors)
├── music/bgm_*.wav   the scene's entry BGM as a seamless loop
└── manifest.json     transforms, labels and conventions

Everything is composed by the same kernels the browser viewers render with, so the export matches the on-screen pages.

  • World - the field-scene page's assembly: the ground heightfield, terrain tiles and placed objects at their resolved .MAP transforms, clip-bound placements posed at frame 0. One VRAM-derived texture atlas with nearest sampling, the packet colours on COLOR_0 (linearised so a linear-colour-space importer reproduces retail's texel × colour / 128), PSX transparency as a cutout mask. Semi-transparent primitives split into one blend material per PSX blend rate, named legaia_semi_abr<N>: core glTF has only alpha blending, so the name is the contract an importer restores the real blend from, and the Unity kit maps the additive rates to an additive shader.
  • NPCs - each catalogued placement's mesh with its spawn clip first and every matching scene clip as a named animation; spawn transforms live in the manifest.
  • Animated props - each distinct (mesh, clip) pair whose clip has more than one frame, object-local, with every placement in the manifest. The world keeps their frame-0 twins, so these are opt-in upgrades.
  • Ambient vertex morphs - in the scenes where the engine's scene-entry pulse runs (the jou family and Rim Elm's shoreline), one morph target per envelope lane and a looping weights animation of exactly one period: the wave sheet washes in and out in any glTF player.
  • Music - the scene's first BGM rendered through the engine's SPU and sequencer, only the detected loop region, so a looping audio source repeats it seamlessly.

Equipment items and the party

  • --items exports every equippable record of the four player battle files - weapons, Ra-Seru, armour, headgear, footwear - two files each: *_alone.glb, the item cut out with its grip repaired (a grabbable pickup, a Blender prop), and *_with_limb.glb, the exact cut with its host limb. Both carry the character's battle action clips and the weapon's swings. It is the same kernel as the characters page's equipment viewer, and the manifest repeats each record's honesty tags so a heuristic cut is told apart from a curated one. Item files are in raw PSX units.
  • --party exports Vahn, Noa and Gala as they walk the towns: each field mesh textured from its field pages, with the 7-clip locomotion bank as named takes (Idle first, Walk second). The files and the manifest's roster have the same shape as a scene's villagers, so a builder places a party member the way it places any NPC.

The manifest and its frame

manifest.json carries the scale and axis conventions, a suggested spawn (the median of the placed objects - the village centre, not the map's), and the placement arrays:

ArrayHolds
npcs[]file, kind (talk / door / prop), the dialog's first line, position on the retail floor sampler, clips. The position is where retail's spawn prologue actually puts the actor under fresh-game flags, not the raw placement tile.
doors[]portal placements with their target map
animated_props[]file, frame count, whether retail leaves the clip free-running (the windmill) or holds it for a script (a door), each instance's position and rotation, and door tags
teleports[]retail's intra-scene doorways, both families, as trigger boxes with a floor-sampled destination and arrival facing: a house interior is an unused corner of the same map
scene_portals[]town exits and overworld entrances: trigger box, target scene, arrival point in the target's frame
music, world_animthe BGM loop and the baked morph clip
PSX world X right Y down Z into the screen (x, y, z) → (x, −y, −z) Rx(180), determinant +1 Export (glTF) X right Y up Z toward the viewer a rotation, not a mirror: winding is reversed so retail's front faces stay front-facing
Both frames are right-handed, so one rotation is the whole conversion: stand at the eye retail's camera uses, look where it looks, and a glTF viewer draws what retail draws. The world glb, the NPC and prop files and every number in the manifest share this frame (conventions.world_frame: "psx_rx180"), and placement rotations carry all three authored angles, so a leaning plank keeps its tilt.
  • Winding. Retail's field front face runs clockwise on its Y-down screen; glTF's runs counter-clockwise, so the bake reverses every triangle and a viewer that culls by winding keeps what retail's cull keeps. Materials stay double-sided anyway: retail's camera never walks round a building, and a VR player does.
  • The landmark test. Handedness is settled by looking, not by counting reflections: render the raw glb from a retail state's own camera, and the picture must match retail's frame better than its left-right flip.

Verification, and what is approximated

Disc-free tests pin the handedness on a synthetic pitched, rolled and yawed record; a disc-gated test assembles town01, validates every glb container, and checks the sky filter, the prop split, both doorway families and the world-map gate portal, the door tags, the shoreline morphs, the ground's up-facing winding and every animated prop instance against its world twin.

Geometry, textures, packet-colour shading, placements, floor heights, the walk surface, the doorway data, the shoreline morphs and the BGM render are retail-parity kernels. A static export approximates the rest by design: NPCs loop a clip instead of running their scripts, non-door props free-run, a door swing becomes open-on-approach, and script doors are frozen at the cold-entry story state. The Unity kit layers optional realism passes (lighting, day and night, fog, grass, interiors, ambience) and furniture (a mirror, a video screen, a card table) on top, each generated from scratch; switching them all off restores the faithful build.

The playable slot machine

The kit also builds the casino slot machine as an in-world cabinet from a separate feed: asset slot-art decodes the slot overlay and its art pack into images and a manifest with the payout table, the scene-geometry tables and the retail projection constants. An editor menu composes the whole retail screen onto a cabinet's screen face through the retail software projection, and an UdonSharp port of the engine's slot rules drives it, checked against a committed rules-parity fixture. The cabinet model is the one thing you bring.

See also