code wiki / _hdl_build / nx_gltf_export_gate.nx

nx_gltf_export_gate.nx

buildroot/runtime/_hdl_build/nx_gltf_export_gate.nx

9619 B185 linesdepth 5pulls 14 transitivereach 0 importersview sourcekind gate/prooftopic gltf
docsdependenciesstructsconstsfunctions

about

nx_gltf_export_gate.nx -- prove the glTF/.glb export (roadmap R7, VRM foundation): mesh the bestiary, write a binary glTF per variant, and validate the container: magic "glTF" + version 2 + total-length == filesize + a JSON chunk (POSITION/NORMAL accessors) + a BIN chunk big enough for the geometry the JSON declares. This is a REAL interchange format (three.js/Unity/Godot/Blender import it), the step up from STL/OBJ toward riggable VRM avatars. MIGRATED OFF D001 2026-08-26. This gate used to hand-roll a `fails` tally and print its own "GLTF-EXPORT-GATE 4/4 verdict=GREEN" line, so /api/promote refused it: nothing outside could read its outcome, nx_gate_green could not judge it, and it recorded no harness.jrnl frame, leaving flake and erosion invisible for it. It now inherits nx_gate_verdict -- per-tooth gv_check, so declared == executed by construction, and the verdict is carried in the EXIT CODE where /api/gate_run reads it. The migration surfaced two vacuity defects, fixed here rather than carried across: - the BIN-size check compared got_bin >= nv*24 + nf*12, which PASSES when the mesher returns nv=0 and nf=0. A tooth that passes on the empty set is not a tooth. The vertex and triangle counts are now declared SUBJECTS, so an empty mesh ends SKIP (no evidence) instead of scoring a silent GREEN. - the six-variant export loop printed a line per file and asserted NOTHING about any of them, so a write_glb returning 0 for every variant was invisible. It is a tooth now. Two neg-controls drive the header detector and the JSON scanner with crafted inputs, because a checker that answers the same way for everything scores 100% and proves nothing. license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0

dependencies 6 imports · 0 importers

nx_syscalls.nx nx_sdfrender.nx nx_meshgen.nx nx_assetvariant.nx nx_gltf_export.nx nx_gate_verdict.nx nx_gltf_export_gate.nx

imports: nx_syscalls.nxnx_sdfrender.nxnx_meshgen.nxnx_assetvariant.nxnx_gltf_export.nxnx_gate_verdict.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main gv_ctr sys_mmap nxa_die sys_write sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ gv_head gv_puts sys_write ↻ sys_mmap ↻ sdf_bytes av_build sys_mmap ↻ av_base_human av_p av_base_wolf av_p ↻ av_base_goblin av_p ↻ av_slot_head av_p ↻ av_slot_ears av_p ↻ av_slot_tail av_p ↻ sdf_clear_ops mg_build mg_sample_sdf mg_fi

structs

none

consts

30const GX_MAGIC_GLTF: i64 = 0x46546C67 // "glTF", little-endian
31const GX_CHUNK_JSON: i64 = 0x4E4F534A // "JSON"
32const GX_CHUNK_BIN: i64 = 0x004E4942 // "BIN\0"
33const GX_VERSION: i64 = 2 // glTF 2.0
34const GX_HDR_BYTES: i64 = 12 // magic + version + total length
35const GX_CHUNKHDR: i64 = 8 // chunk length + chunk type
36const GX_VEC3_F32: i64 = 12 // three float32 per vertex attribute
37const GX_ATTRS: i64 = 2 // POSITION and NORMAL, both vec3
38const GX_IDX_BYTES: i64 = 4 // uint32 index
39const GX_TRI_IDX: i64 = 3 // indices per triangle
43const GX_NVARIANT: i64 = 6
44const GX_VT_FIELDS: i64 = 5
45const GX_SCRATCH: i64 = 16

functions

47func rd32(b: *u8, o: i64) -> i64 { return (b[o]&0xff) | ((b[o+1]&0xff)<<8) | ((b[o+2]&0xff)<<16) | ((b[o+3]&0xff)<<24) }
49func has_str(b: *u8, n: i64, s: *u8) -> i64
called by 1: main
67func glb_magic_rejects(b: *u8) -> i64
called by 1: main calls 1: rd32
72func main() -> i64