code wiki / (root) / nx_partloft_lib.nx

nx_partloft_lib.nx

buildroot/runtime/nx_partloft_lib.nx

47789 B1025 linesdepth 3pulls 6 transitivereach 2 importersview sourcekind library
docsdependenciesstructsconstsfunctions

about

nx_partloft_lib.nx -- THE LOFTED PART: Infinigen's NurbsPart, replicated in NishiLang from the first byte up (procgen PG59 / anatomy AN19, 2026-09-19). Operator standing order the same day: the estate uses the best-in-class published method as its BASELINE and improves it piece by piece; the ellipsoid-union skull is retired. This file is the first piece. ONE part = a skeleton polyline with a normalised profile at every station, DECOMPOSED into the genes the Infinigen creature system mutates, RECOMPOSED into a grid of NURBS control handles, EVALUATED as a cubic B-spline surface, and WRITTEN as NXMSH2 through the estate's one mesh layout (nx_nxmesh_lib). Read from the primary source, mirrored under knowledge/fetched/ and pinned on procgen.refs: infinigen/assets/creatures/parts/generic_nurbs.py decompose_nurbs_handles / recompose_nurbs_handles / NurbsPart.sample_params (the gene noise STRUCTURE) infinigen/assets/creatures/util/geometry/lofting.py factorize_nurbs_handles, skeleton_to_tangents, compute_profile_verts (frames by rotate_match_directions) infinigen/assets/creatures/util/geometry/nurbs.py geomdl_nurbs: degree (3,3), clamped uniform u knots, cyclic v wrapping three control points, sample_size from face_size infinigen/assets/creatures/util/part_util.py nurbs_to_part: the attachment skeleton is the INTERIOR rows infinigen/assets/creatures/util/creature.py apply_attach_transform: (u, v, rad) surface coordinates CONVENTIONS, THEIRS: a part runs along +x (profiles face +x), y is lateral, z is up; skeleton_yoffs is the lateral drift per segment and thetas the pitch in the xz plane (degrees there, VM_ONE radians here). UNITS, OURS, and there are exactly three: POSITIONS in tenths of a millimetre (u10, NM_UNIT_PER_M, the NXMSH2 ruler's unit); FRACTIONS in PL_FQ = 65536 (Q16) -- gene proportions, lateral drifts, station parameters, normalised profiles, surface parameters, the attachment coordinates, the gene variance, and the B-spline knots and basis; and ANGLES in VM_ONE radians (Q12), the estate's one trigonometric unit, for the pitch genes and the yaw. A radius is a position with sixteen fractional bits (Q16 u10), because a profile normalised by a radius rounded to 0.1 mm was measured 0.25 percent off at 20 mm and would be 2.5 percent off on a finger: MEASURED on the first run of the gate, where Q12 proportions truncated to whole u10 per segment lost 0.5 percent of a part's length (995 for 1000). Every division that lands on a stored value rounds to nearest (pl_rdiv); truncation is how that half-percent was lost. No float anywhere: the file's float32 is encoded once, at the door, by nx_nxmesh_lib / nx_vecmath. DECLARED DEVIATIONS (each a rung on procgen, never a silent difference): 1. np.random.normal is Irwin-Hall (twelve uniforms of a 31-bit LCG): same mean and variance, tails end at six sigma. The STRUCTURE of the noise is the source's exactly: one size draw, one length draw, one shared radius draw plus one per station, one per proportion, zero-meaned pitch noise, per-column times per-cell profile noise mirrored across the profile. 2. The attachment ray-cast against a BVH is a parametric search: around the requested station the closed profile is searched for the point nearest the ray (least perpendicular distance, in front of the origin), coarse then bisected, over a one-segment window of u. 3. The attachment skeleton is the clamped cubic B-spline of the interior rows, where the source runs two Catmull-Clark levels over the interior polyline (the limit of that subdivision IS the cubic B-spline). 4. The emitted mesh carries two fan caps so the part is a closed solid for the lattice fusion; the source leaves the tube open and lets remesh close it. Winding is made outward per triangle here; the source runs normals_make_consistent. LIB, no main. license_tier: ORIGINAL (a re-implementation from a read of BSD-3 source; no source bytes copied; the

dependencies 4 imports · 2 importers

nx_syscalls.nx nx_vecmath.nx nx_nxmesh_lib.nx nx_itoa_lib.nx nx_partloft_lib.nx nx_partloft_capture_t319.nx nx_partloft_gate.nx

imports: nx_syscalls.nxnx_vecmath.nxnx_nxmesh_lib.nxnx_itoa_lib.nx

imported by: nx_partloft_capture_t319.nxnx_partloft_gate.nx

structs

106struct PlPart { nu: i64, nv: i64, root: *i64, length: i64, prop: *i64, theta: *i64, yoff: *i64, rad: *i64, ts: *i64, prof: *i64, skel: *i64, tang: *i64, hnd: *i64, ku: *i64, kv: *i64, ka: *i64, bu: *i64, bv: *i64, bl: *i64, br: *i64 }

consts

47const PL_ONE: i64 = 4096 // VM_ONE spelled once here, the ANGLE and unit-vector unit; the gate asserts the two agree
48const PL_FQ: i64 = 65536 // the FRACTION unit (Q16): genes, parameters, knots, basis
49const PL_FQ2: i64 = 4294967296 // PL_FQ squared: the divisor that takes a Q16 profile times a Q16 radius back to u10
50const PL_FQ_SHIFT: i64 = 16
51const PL_FQ_HALF_SHIFT: i64 = 8 // sqrt(x << 16) << 8 = sqrt(x) << 16: a length with sixteen fractional bits
52const PL_DEG: i64 = 3 // degree_u, degree_v = (3, 3): nurbs.py geomdl_nurbs
53const PL_ORD: i64 = 4 // PL_DEG + 1 nonzero basis functions on any span
54const PL_I64: i64 = 8
55const PL_V3: i64 = 3
56const PL_Q4: i64 = 4
57const PL_PART_BYTES: i64 = 256 // PlPart: 21 words, one page-rounded map
58const PL_MIN_RAD: i64 = 65536 // rads clipped to at least one u10 (Q16): np.clip(rads, 1e-3 m, 1e5 m)
59const PL_MIN_NU: i64 = 4 // a clamped cubic needs four control rows
60const PL_MIN_NV: i64 = 3 // and a periodic cubic three columns
61const PL_GAUSS_N: i64 = 12 // Irwin-Hall count: the variance of a sum of n uniforms is n/12, one at twelve
62const PL_LCG_MUL: i64 = 1103515245 // the ANSI C rand() recurrence, a published constant
63const PL_LCG_ADD: i64 = 12345
64const PL_LCG_MOD: i64 = 2147483648 // 2^31: state times multiplier stays under 2^62
65const PL_LCG_SHIFT: i64 = 16 // the low bits of an LCG are its weakest, discarded
66const PL_LCG_BITS: i64 = 32768 // 2^15 output range after the shift
70const PL_SD_SIZE: i64 = 6554 // sz = N(1, 0.1)
71const PL_SD_LENGTH: i64 = 6554 // length *= sz * N(1, 0.1)
72const PL_SD_RADS: i64 = 6554 // rads *= sz * N(1, 0.1) ...
73const PL_SD_RAD_STATION: i64 = 9830 // ... * N(1, 0.15) per station
74const PL_SD_PROP: i64 = 9830 // proportions *= N(1, 0.15) per segment
75const PL_SD_THETA: i64 = 500 // thetas += N(0, 7 deg) per segment, zero-meaned (VM_ONE radians)
76const PL_SD_PROF_COL: i64 = 4587 // profile noise N(1, 0.07) per column ...
77const PL_SD_PROF_CELL: i64 = 9830 // ... times N(1, 0.15) per cell
78const PL_SEARCH_COARSE: i64 = 64 // attachment search: samples around the ring before the bisection
79const PL_SEARCH_REFINE: i64 = 12 // bisection steps after the coarse pass
80const PL_SEARCH_UHALF: i64 = 2 // u window: this many quarter-segments either side of the station
81const PL_SEARCH_UQUART: i64 = 4 // a segment is split in this many steps for the window
82const PL_FD_STEP: i64 = 256 // finite-difference step for tangents and normals, Q16 (1/256 of the domain)
83const PL_MAGIC_0: i64 = 78 // N
84const PL_MAGIC_1: i64 = 88 // X
85const PL_MAGIC_2: i64 = 77 // M
86const PL_MAGIC_3: i64 = 83 // S
87const PL_MAGIC_4: i64 = 72 // H
88const PL_MAGIC_5: i64 = 50 // 2
89const PL_LAYER_START_OFF: i64 = 16 // within a 24-byte layer record: 16 name bytes, then start u32, then count u32
90const PL_LAYER_COUNT_OFF: i64 = 20
91const PL_OFF_NORMALS: i64 = 36 // byte offset of the three per-vertex normals within a triangle record
92const PL_COL_BONE_R: i64 = 900 // the part's default colour, per-mille: a bone tint a viewer renders as bone
93const PL_COL_BONE_G: i64 = 880
94const PL_COL_BONE_B: i64 = 840
95const PL_MIN_RING: i64 = 3 // a cap fan needs three ring points
96const PL_SAVE_DIGITS: i64 = 16 // bytes reserved per integer on save: sign, 14 digits, separator
97const PL_SAVE_HEADER: i64 = 64
98const PL_MODE644: i64 = 420
99const PL_LOAD_HDR: i64 = 16 // the two-word length record sys_read_file fills
100const PL_FMT_VERSION: i64 = 2 // version 2: Q16 fractions and Q16 radii (version 1 was Q12, never shipped)
101const PL_HEADER_INTS: i64 = 7 // version nu nv root(3) length
102const PL_ASKEL_SPLINE: i64 = 1 // pl_askel took the cubic path (four or more interior rows)
103const PL_ASKEL_LINEAR: i64 = 2 // pl_askel took the linear path (fewer)
104const PL_POS_HUGE: i64 = 1000000000000000000

functions

108func pl_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
110func pl_rdiv(a: i64, b: i64) -> i64 { if a >= 0 { return (a + b/2) / b } return (a - b/2) / b }
111func pl_len3(x: i64, y: i64, z: i64) -> i64 { return vm_isqrt(x*x + y*y + z*z) }
113func pl_len3_fx(x: i64, y: i64, z: i64) -> i64 { return vm_isqrt((x*x + y*y + z*z) << PL_FQ_SHIFT) << PL_FQ_HALF_SHIFT }
called by 1: pl_decompose calls 1: vm_isqrt
115func pl_unit(o: *i64, a: *i64) -> i64
122func pl_rad_u10(p: *PlPart, i: i64) -> i64 { return pl_rdiv(p.rad[i], PL_FQ) }
called by 2: mainmain calls 1: pl_rdiv
129func pl_knots(p: *PlPart) -> i64
165func pl_new(nu: i64, nv: i64) -> *PlPart
called by 3: mainmainpl_load calls 2: sys_mmappl_knots
190func pl_copy(dst: *PlPart, src: *PlPart) -> i64
called by 2: mainmain calls 1: pl_knots
211func pl_rot_match(q: *i64, a: *i64, b: *i64) -> i64
224func pl_tangents(skel: *i64, n: i64, tang: *i64, edge: *i64) -> i64
258func pl_decompose(hnd: *i64, nu: i64, nv: i64, p: *PlPart) -> i64
332func pl_recompose(p: *PlPart) -> i64
401func pl_lcg(st: *i64) -> i64
called by 1: pl_urand
406func pl_urand(st: *i64) -> i64 { return pl_lcg(st) * PL_FQ / PL_LCG_BITS }
called by 1: pl_nrand calls 1: pl_lcg
408func pl_nrand(st: *i64) -> i64
called by 1: pl_normal calls 1: pl_urand
416func pl_normal(st: *i64, mean: i64, sd: i64, var_: i64) -> i64
called by 1: pl_mutate calls 2: pl_rdivpl_nrand
423func pl_mutate(p: *PlPart, seed: i64, var_: i64) -> i64
485func pl_span(U: *i64, ncp: i64, x: i64) -> i64
494func pl_basis(U: *i64, k: i64, x: i64, N: *i64, left: *i64, right: *i64) -> i64
516func pl_surface(p: *PlPart, u: i64, v: i64, out: *i64) -> i64
554func pl_askel_point(p: *PlPart, t: i64, out: *i64) -> i64
called by 1: pl_askel calls 3: pl_spanpl_basispl_rdiv
591func pl_askel(p: *PlPart, t: i64, out: *i64, tan: *i64) -> i64
611func pl_ray_perp2(p: *PlPart, u: i64, v: i64, o: *i64, dw: *i64, s: *i64) -> i64
called by 1: pl_surface_at calls 1: pl_surface
625func pl_surface_at(p: *PlPart, t: i64, yaw: i64, rad: i64, out: *i64, nrm: *i64, tan: *i64, info: *i64) -> i64
727func pl_mesh_counts(p: *PlPart, face: i64, out: *i64) -> i64
called by 3: mainmainpl_mesh_write calls 1: pl_len3
771func pl_put_tri(B: *u8, tb: i64, t: i64, V: *i64, ia: i64, ib: i64, ic: i64, ox: i64, oy: i64, oz: i64, xyz9: *i64) -> i64
806func pl_mesh_write(p: *PlPart, face: i64, path: *u8, rep: *i64) -> i64
908func pl_save_ints(fb: *u8, fo: i64, A: *i64, n: i64) -> i64
called by 1: pl_save calls 1: nxi_buf
920func pl_save(path: *u8, p: *PlPart) -> i64
952func pl_tok(buf: *u8, n: i64, pos: *i64, out: *i64) -> i64
called by 2: pl_load_intspl_load
985func pl_load_ints(buf: *u8, n: i64, pos: *i64, A: *i64, cnt: i64, tok: *i64) -> i64
called by 1: pl_load calls 1: pl_tok
996func pl_load(path: *u8) -> *PlPart