code wiki / (root) / nx_xport_lib.nx

nx_xport_lib.nx

buildroot/runtime/nx_xport_lib.nx

39836 B906 linesdepth 4pulls 14 transitivereach 1 importersview sourcekind library
docsdependenciesstructsconstsfunctions

about

nx_xport_lib.nx -- DC12: ONE AUTHORED ASSET INTO FOUR CONSUMERS, MEASURED BY ONE RULER. WHY THIS EXISTS: the /compare/dcc board claims a single authored asset serves storefront, game, VR and clinical use. Today that is a PLAN. Nothing measures it, so a consumer could silently receive a decimated, re-scaled or re-wound mesh and no instrument in the estate would say so. This lib turns the claim into a number per consumer. THE RULER IS md_measure AND THERE IS NOT A SECOND ONE. nx_mmdev_lib already measures exact point-to-triangle deviation in tenths of a millimetre and is gate-proven to read a known 5.0 mm lift as 5.0 mm and a self-compare as zero. A new deviation metric on this board would be a duplicate ruler, i.e. a defect. Everything below COMPOSES it. The exporters are composed too -- write_glb and write_obj are called, never re-implemented -- so what is measured is the artifact the real storefront lane ships. WHAT IS MEASURED, PER CONSUMER: the artifact is written, then the geometry is RECOVERED BACK OUT OF THE ARTIFACT BYTES (not from an in-memory copy that never crossed the format) and measured against the source in BOTH directions. Deviation alone is not sufficient and this lib says so in code: a mesh mirrored about its own centre has ZERO point-to-triangle deviation and is still wrong, so orientation (the sign of the signed volume) and scale (per-axis AABB extent) are separate axes, not decoration. THE BOUND IS DERIVED, NEVER PICKED. Every consumer holds coordinates in its own integer unit. A round trip through a unit of U integer steps per metre, from the ruler's NM_UNIT_PER_M steps per metre, spends at most half a step in each direction, and NOTHING AT ALL when U is an integer multiple of the ruler's unit (the forward map is a multiplication and the inverse an exact division). The glTF path adds a second, computed term: write_glb encodes each integer coordinate with gl_i2f32, which TRUNCATES the mantissa, so the loss is the float32 ulp AT THIS ASSET'S OWN COORDINATE MAGNITUDE -- computed from the mesh, zero while the magnitude fits the 24-bit significand, and rising by itself if it ever does not. ABSTENTION IS NOT A SCORE OF ZERO. A consumer that cannot be measured reports UNREACHED with a named reason. A consumer that silently reads zero deviation is indistinguishable from one that was never measured, which is the whole failure this rung exists to prevent. DECLARED IMPRECISIONS, so no reader takes them as exact: (1) The volume-magnitude tolerance uses the AABB as a proxy for surface area. A convoluted mesh has more area per unit volume than its box, so on such a mesh that tolerance is OPTIMISTIC. It is a SUPPORTING axis only; the load-bearing orientation test is the volume SIGN, which needs no tolerance and cannot be optimistic. (2) The signed volume is the enclosed volume only for a CLOSED mesh. For an open mesh it is still a valid like-for-like shape statistic, because source and recovered are evaluated with the SAME origin (the source AABB minimum), but it is not a volume. (3) md_measure's own declared imprecisions carry through: its mean is valence-weighted and its p95 is

dependencies 8 imports · 1 importers

nx_syscalls.nx nx_vecmath.nx nx_nxmesh_lib.nx nx_mmdev_lib.nx nx_nxa.nx nx_gltf_export.nx nx_obj_export.nx nx_ge_str_lib.nx nx_xport_lib.nx nx_xport_gate.nx

imports: nx_syscalls.nxnx_vecmath.nxnx_nxmesh_lib.nxnx_mmdev_lib.nxnx_nxa.nxnx_gltf_export.nxnx_obj_export.nxnx_ge_str_lib.nx

imported by: nx_xport_gate.nx

structs

none

consts

69const XP_GL_UNIT_PER_M: i64 = 1024
72const XP_NXA_UNIT_PER_M: i64 = 100000
74const XP_MODE_0644: i64 = 420
75const XP_PATH_CAP: i64 = 512
76const XP_PERMIL: i64 = 1000
79const XP_I64_SAFE: i64 = 4611686018427387904
82const XP_GLB_MAGIC: i64 = 1179937895 // "glTF" little-endian
83const XP_GLB_VER: i64 = 2
84const XP_GLB_JSONLEN_OFF: i64 = 12
85const XP_GLB_JSON_OFF: i64 = 20 // 12 byte header + 8 byte chunk header
86const XP_GLB_CHUNKHDR: i64 = 8
87const XP_GLB_VEC3_BYTES: i64 = 12
88const XP_GLB_U32_BYTES: i64 = 4
90const XP_GLB_IDX_START_MUL: i64 = 24
94const XP_GLB_SCALE_LIT: *u8 = "\"scale\":[0.0009765625,0.0009765625,0.0009765625]"
95const XP_GLB_COUNT_KEY: *u8 = "\"count\":"
98const XP_NXA_SECTIONS: i64 = 2 // VERT + TRIS
99const XP_NXA_TOC_BYTE: i64 = 32
100const XP_NXA_TOC_ROW_WORDS: i64 = 4 // tag, byte offset, word length, payload check
105const XP_HASH_A: i64 = 73856093
106const XP_HASH_B: i64 = 19349663
107const XP_HASH_C: i64 = 83492791
109const XP_HASH_LOAD_INV: i64 = 2
112const XP_VOL_PERMIL_FLOOR: i64 = 1
115const XP_C_STORE_GLB: i64 = 0
116const XP_C_STORE_OBJ: i64 = 1
117const XP_C_GAME_NXA: i64 = 2
118const XP_C_VR_FRAME: i64 = 3
119const XP_C_CLINICAL: i64 = 4
120const XP_C_N: i64 = 5
123const XP_R_REACHED: i64 = 0 // 1 iff an artifact was produced for this consumer
124const XP_R_WHY: i64 = 1 // 0 when the verdict is measured, else the reason it is not
125const XP_R_BYTES: i64 = 2
126const XP_R_TRIS_SRC: i64 = 3
127const XP_R_TRIS_REC: i64 = 4
128const XP_R_MEAN_AB: i64 = 5 // source vertices -> recovered surface
129const XP_R_P95_AB: i64 = 6
130const XP_R_MAX_AB: i64 = 7
131const XP_R_MEAN_BA: i64 = 8 // recovered vertices -> source surface
132const XP_R_P95_BA: i64 = 9
133const XP_R_MAX_BA: i64 = 10
134const XP_R_VOLSIGN_OK: i64 = 11
135const XP_R_VOL_PERMIL: i64 = 12
136const XP_R_VOL_PERMIL_BOUND: i64 = 13 // -1 = UNMEASURED (degenerate AABB), never a silent zero
137const XP_R_EXT_DELTA: i64 = 14
138const XP_R_EXT_BOUND: i64 = 15
139const XP_R_BOUND: i64 = 16 // the derived 3D deviation bound, in tenths of a millimetre
140const XP_R_AXIS: i64 = 17 // per-axis bound = quantisation term + float32 term
141const XP_R_AXISQ: i64 = 18
142const XP_R_AXISF: i64 = 19
143const XP_R_VERTS: i64 = 20
144const XP_R_PASS: i64 = 21
145const XP_R_N: i64 = 22
148const XP_WHY_OK: i64 = 0
149const XP_WHY_NO_MESH_PARAM: i64 = 1 // the consumer's entry point takes no mesh at all
150const XP_WHY_RASTER_ONLY: i64 = 2 // the consumer's artifact is an image: geometry is not in it
151const XP_WHY_ARTIFACT_MISSING: i64 = 3
152const XP_WHY_ARTIFACT_MALFORMED: i64 = 4
153const XP_WHY_SCALE_UNDECLARED: i64 = 5 // refused rather than mis-scaled
154const XP_WHY_RULER_REFUSED: i64 = 6 // md_measure itself declined; its code is in the ruler's res
155const XP_WHY_COUNT_MISMATCH: i64 = 7
157const XP_F_GLB: *u8 = "xport.glb"
158const XP_F_OBJ: *u8 = "xport.obj"
159const XP_F_NXA: *u8 = "xport.nxa"
160const XP_F_MSH: *u8 = "xport.nxmsh2"
169const XP_VR_SRC: *u8 = "buildroot/runtime/_hdl_build/nx_vrframe.nx"
170const XP_VR_SIG: *u8 = "func vf_build(distort: i64, outpath: *u8) -> i64"
171const XP_VR_RASTER: *u8 = "write_png(combo"

functions

173func xp_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
174func xp_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
176func xp_res() -> *i64
182func xp_rs(res: *i64, c: i64, slot: i64, v: i64) -> i64 { res[c*XP_R_N + slot] = v; return 0 }
183func xp_rg(res: *i64, c: i64, slot: i64) -> i64 { return res[c*XP_R_N + slot] }
185func xp_name(c: i64) -> *u8
193func xp_file_of(c: i64) -> *u8
201func xp_unit_of(c: i64) -> i64
211func xp_uses_f32(c: i64) -> i64
218func xp_q(v: i64, num: i64, den: i64) -> i64
235func xp_axis_bound(dst_per_m: i64) -> i64
246func xp_f32_axis_term(maxabs_dst: i64, dst_per_m: i64) -> i64
262func xp_bound3d(axis_nm: i64) -> i64
269func xp_aabb(m: *u8, out6: *i64) -> i64
293func xp_extent(bb: *i64) -> i64
300func xp_maxabs(m: *u8) -> i64
316func xp_ext_delta(a: *u8, b: *u8) -> i64
334func xp_vol_div(m: *u8, bb: *i64) -> i64
348func xp_vol6(m: *u8, org: *i64, div: i64) -> i64
378func xp_vol_permil_bound(bb: *i64, bound3d: i64) -> i64
395func xp_weld(m: *u8, dst_per_m: i64, vbuf: *i64, fbuf: *i64) -> i64
446func xp_soup_from_indexed(vbuf: *i64, fbuf: *i64, nv: i64, nf: i64, src_per_m: i64, out: *u8) -> i64
472func xp_path(dir: *u8, name: *u8, out: *u8) -> i64
483func xp_write_bytes(b: *u8, n: i64, path: *u8) -> i64
493func xp_nxa_write(vbuf: *i64, fbuf: *i64, nv: i64, nf: i64, path: *u8) -> i64
523func xp_atoi(b: *u8, o: i64, n: i64) -> i64
541func xp_rec_glb(b: *u8, n: i64, out: *i64) -> *u8
588func xp_line_end(b: *u8, ls: i64, n: i64) -> i64
600func xp_next_int(b: *u8, cur: *i64, end: i64, ok: *i64) -> i64
630func xp_skip_tok(b: *u8, cur: *i64, end: i64) -> i64
642func xp_rec_obj(b: *u8, n: i64, out: *i64) -> *u8
705func xp_rec_nxa(b: *u8, n: i64, out: *i64) -> *u8
728func xp_rec_msh(b: *u8, n: i64, out: *i64) -> *u8
740func xp_recover(c: i64, b: *u8, n: i64, out: *i64) -> *u8
755func xp_vr_still_unreached(out2: *i64) -> i64
772func xp_emit_all(m: *u8, dir: *u8, res: *i64) -> i64
826func xp_consumers(m: *u8, dir: *u8, res: *i64) -> i64