nx_vnormals_gate.nx
buildroot/runtime/nx_vnormals_gate.nx
about
nx_vnormals_gate.nx -- proves the vertex-normal consolidation, and proves the NON-consolidation.
TWO SEPARATE CLAIMS, EACH MEASURED:
(1) THE RETIREMENT LOST NOTHING. gl_vnormals (nx_gltf_export) and the block that was INLINE inside
write_obj (nx_obj_export) both now call vn_smooth_area (nx_vnormals_lib). This gate carries a
VERBATIM TRANSCRIPTION OF EACH ORIGINAL BODY as a reference oracle and asserts the owner reproduces
both, word for word over every output word, on every fixture. That is the same differential-probe
discipline nx_retire_onto applies before it writes; it is done by hand here because that organ
retires a named private FUNCTION onto an owner and the obj copy was not a function at all.
(2) THE THIRD COPY IS NOT THE SAME COMPUTATION AND WAS CORRECTLY LEFT ALONE. sc_vertex_normals
(nx_shellclose) normalises each face normal BEFORE accumulating it, so faces contribute EQUALLY
regardless of area. This gate runs the REAL shipped sc_vertex_normals -- not a paraphrase of it --
on the same geometry and shows the two answers are not even PARALLEL.
AND THE TOOTH THAT MAKES (2) MEAN SOMETHING IS T12, NOT T10. "These two functions disagree" is a weak
claim: two functions can disagree because one of them is simply broken. T12 runs both on a fixture whose
two incident triangles have EQUAL area and shows they then agree exactly in direction. So the divergence
in T10 is caused BY THE AREA RATIO and by nothing else, which is the actual mechanism, and it is the
reason merging them would have silently changed shipped geometry rather than merely changed code.
THE REFERENCE ORACLES BELOW CONTAIN BARE 3s AND 1000s ON PURPOSE. They are transcriptions of code that
has been deleted, and their whole value is being INDEPENDENT of the owner. Rewriting them in terms of
the owner's VN_V3 and VN_SCALE would make them agree with it by construction and they would stop being
able to detect a change in those constants -- an oracle that imports its subject's constants is not an
oracle. Named here so the next reader sees a decision rather than an oversight.
100 percent sovereign. No hardware writes (Rule 26). expect_exit: 0
dependencies 7 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict.nxnx_vecmath.nxnx_vnormals_lib.nxnx_gltf_export.nxnx_obj_export.nxnx_shellclose.nx
imported by: nobody (leaf or entry point)
structs
| none |
consts
| 40 | const VNG_DIR_MODE: i64 = 493 // 0755, spelled in decimal because this dialect has no octal |
| 41 | const VNG_V3: i64 = 3 |
| 45 | const VNG_A_NV: i64 = 6 |
| 46 | const VNG_A_NF: i64 = 2 |
| 51 | const VNG_A_KAT_X: i64 = 0 |
| 52 | const VNG_A_KAT_Y: i64 = 9 |
| 53 | const VNG_A_KAT_Z: i64 = 999 |
| 57 | const VNG_B_NV: i64 = 5 |
| 58 | const VNG_B_NF: i64 = 2 |
functions
| 60 | func vng_eq(a: i64, b: i64) -> i64 { if a == b { return 1 } return 0 } |
| 61 | func vng_ne(a: i64, b: i64) -> i64 { if a != b { return 1 } return 0 } |
| 62 | func vng_pv(label: *u8, v: i64) -> i64 { gv_puts(label); gv_num(v); gv_puts("\n" as *u8); return 0 } |
| 64 | func vng_p3(label: *u8, a: *i64, vi: i64) -> i64 |
| 70 | func vng_same(a: *i64, b: *i64, n: i64) -> i64 |
| 81 | func vng_cross_yz(a: *i64, b: *i64, vi: i64) -> i64 |
| 85 | func vng_find(hay: *u8, hlen: i64, needle: *u8) -> i64 |
| 103 | func vng_m3_build(base: i64, verts: *i64, nv: i64, tris: *i64, nf: i64) -> i64 |
| 113 | func vnref_gl_original(vbuf: *i64, fbuf: *i64, nv: i64, nf: i64, nrm: *i64) -> i64 |
| 141 | func vnref_obj_original(vbuf: *i64, fbuf: *i64, nv: i64, nf: i64, nrm: *i64) -> i64 |
| 169 | func vng_streq(a: *u8, b: *u8) -> i64 |
| 176 | func vng_set3(a: *i64, i: i64, x: i64, y: i64, z: i64) -> i64 { a[i*3+0]=x; a[i*3+1]=y; a[i*3+2]=z; return 0 } |
| 178 | func main() -> i64 |