code wiki / (root) / nx_nxa_garment.nx

nx_nxa_garment.nx source

↩ module page · 252 lines · 9686 B

1// nx_nxa_garment.nx -- FITTED GARMENT GENERATOR (SOTA garment rung): builds a dress mesh 2// fitted to the character BY MEASUREMENT (per-row body cross-section radii sampled from 3// VERT + ease margin -- tooling, per-character, no hand constants beyond the ease profile), 4// from underbust to mid-thigh with hem flare. Appends GVRT (rest verts, mesh space), GTRI, 5// GPIN (top-ring verts pinned; viewer binds pins to the chest frame). The viewer sims it 6// with general edge-list XPBD -- the same machinery future GarmentCode ingests will use. 7// usage: nx_nxa_garment <in.nxa> <out.nxa> 8// rc: 0 ok, 2 usage, 5 bad nxa, 9 io 9// license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_nxa.nx" 12import "nx_itrig.nx" 13import "nx_gm_cloth_lib.nx" 14const K_MAGIC_4611686018427387903: i64 = 4611686018427387903 15const K_MAGIC_4096: i64 = 4096 16const K_MAGIC_100000000: i64 = 100000000 17const K_MAGIC_65536: i64 = 65536 18 19const GU: i64 = 36 // columns around the body 20const GV: i64 = 18 // rows above-bust..hem (one-layer strapless dress) 21 22func gw9(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 23func gn9(v: i64) -> i64 { 24 let t: *u8 = sys_mmap(32) as *u8 25 var m: i64 = v; var w: i64 = 0 26 if m<0 { t[w]=45 as u8; w=w+1; m=0-m } 27 if m==0 { t[0]=48 as u8; sys_write(1,t,1); return 0 } 28 let d: *u8 = sys_mmap(32) as *u8 29 var k: i64=0 30 while m>0 { d[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 31 var j: i64=0 32 while j<k { t[w]=d[k-1-j]; w=w+1; j=j+1 } 33 sys_write(1,t,w); return 0 34} 35func gs_eq(a: *u8, b: *u8) -> i64 { 36 var i: i64 = 0 37 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } 38 if b[i] != (0 as u8) { return 0 } 39 return 1 40} 41 42func main(argc: i64, argv: *i64) -> i64 { 43 // PG29 wiring: `nx_nxa_garment xpbdcheck` exercises gm_xpbd_step on a two-vert edge -- a real 44 // in-organ call of the solver this organ's watch row names, so the /compare flip is backed by 45 // wiring. The full physics proof is nx_gm_xpbd_gate; this verb only proves reachability. 46 if argc >= 2 { if gs_eq(argv[1] as *u8, "xpbdcheck" as *u8) == 1 { 47 let v2: *i64 = sys_mmap(6*8) as *i64 48 let ve: *i64 = sys_mmap(6*8) as *i64 49 let ed: *i64 = sys_mmap(GM_EROW*8) as *i64 50 let bk: *i64 = sys_mmap(6*8) as *i64 51 v2[0]=0; v2[1]=0; v2[2]=0; v2[3]=200; v2[4]=0; v2[5]=0 52 var z9: i64 = 0 53 while z9 < 6 { ve[z9]=0; z9=z9+1 } 54 ed[0]=0; ed[1]=1; ed[2]=100; ed[3]=GM_C_STRUCT // rest 100, stretched to 200 55 let d0: i64 = gm_dist(v2, 0, 1) 56 gm_xpbd_step_banked(v2, ve, 2, ed, 1, 0 as *i64, 0, 0, 16666, 8, 0, 0, bk) 57 let d1: i64 = gm_dist(v2, 0, 1) 58 gw9("GM-XPBD-CHECK before=" as *u8); gn9(d0) 59 gw9(" after=" as *u8); gn9(d1) 60 gw9(" rest=100 converged=" as *u8) 61 var ok9: i64 = 0 62 if d1 < d0 { if d1 >= 95 { if d1 <= 105 { ok9 = 1 } } } 63 gn9(ok9); gw9("\n" as *u8) 64 if ok9 == 1 { return 0 } 65 return 1 66 } } 67 if argc < 3 { gw9("usage: nx_nxa_garment <in.nxa> <out.nxa> | xpbdcheck\n" as *u8); return 2 } 68 let lp: *i64 = sys_mmap(16) as *i64 69 let b: *u8 = sys_map_file(argv[1] as *u8, lp) 70 let flen: i64 = lp[0] 71 let vwo: i64 = nxa_find(b, flen, nxa_tag4("VERT" as *u8)) 72 if vwo < 0 { gw9("bad nxa\n" as *u8); return 5 } 73 let h: *i64 = b as *i64 74 let nv: i64 = h[vwo] 75 let vx: *i64 = ((b as i64) + vwo*8 + 8) as *i64 76 // measure: z-up models; body extents 77 var mn2: i64 = K_MAGIC_4611686018427387903 78 var mx2: i64 = 0 - K_MAGIC_4611686018427387903 79 var mnx: i64 = K_MAGIC_4611686018427387903 80 var mxx: i64 = 0 - K_MAGIC_4611686018427387903 81 var mny: i64 = K_MAGIC_4611686018427387903 82 var mxy: i64 = 0 - K_MAGIC_4611686018427387903 83 var i0: i64 = 0 84 while i0 < nv { 85 if vx[i0*3] < mnx { mnx = vx[i0*3] } 86 if vx[i0*3] > mxx { mxx = vx[i0*3] } 87 if vx[i0*3+1] < mny { mny = vx[i0*3+1] } 88 if vx[i0*3+1] > mxy { mxy = vx[i0*3+1] } 89 if vx[i0*3+2] < mn2 { mn2 = vx[i0*3+2] } 90 if vx[i0*3+2] > mx2 { mx2 = vx[i0*3+2] } 91 i0 = i0 + 1 92 } 93 let H: i64 = mx2 - mn2 94 let cx: i64 = (mnx + mxx)/2 95 let cy: i64 = (mny + mxy)/2 96 // rows: y01 from 775 (above bust, armpit line -- strapless top edge) down to 370 97 // (mid-thigh); per row measure the body's MAX radius from the axis within the band 98 // (torso only: |x-cx| < .16H so T-pose arms never inflate the top rows) + ease 99 let rowz: *i64 = sys_mmap(GV*8 + 64) as *i64 100 let rowr: *i64 = sys_mmap(GV*8 + 64) as *i64 101 var r0: i64 = 0 102 while r0 < GV { 103 let y01: i64 = 758 - r0*388/(GV-1) 104 rowz[r0] = mn2 + H*y01/1000 105 var best: i64 = 0 106 var i1: i64 = 0 107 while i1 < nv { 108 let dz9: i64 = vx[i1*3+2] - rowz[r0] 109 var az9: i64 = dz9 110 if az9 < 0 { az9 = 0 - az9 } 111 if az9 < H*12/1000 { 112 let dx9: i64 = vx[i1*3] - cx 113 let dy9: i64 = vx[i1*3+1] - cy 114 var ax9: i64 = dx9 115 if ax9 < 0 { ax9 = 0 - ax9 } 116 if ax9 < H*115/1000 { 117 let rr9: i64 = dx9*dx9 + dy9*dy9 118 if rr9 > best { best = rr9 } 119 } 120 } 121 i1 = i1 + 1 122 } 123 // isqrt via itrig-free Newton (small local) 124 var xq: i64 = K_MAGIC_4096 125 if best > K_MAGIC_100000000 { xq = K_MAGIC_65536 } 126 var itn: i64 = 0 127 while itn < 30 { 128 if xq > 0 { let yq: i64 = (xq + best/xq)/2; if yq > 0 { xq = yq } } 129 itn = itn + 1 130 } 131 // ease (pattern-making literature): a fitted woven skirt carries 5-10cm of hip ease 132 // -- on this figure's ~105cm hip that is 5-9pct. Surplus fabric is what BUCKLES into 133 // folds; a zero-ease shrink-wrap can only cone. Flare grows over the last 7 rows. 134 var ease: i64 = 62 135 if r0 > GV-8 { ease = 62 + (r0-(GV-8))*48 } 136 rowr[r0] = xq + xq*ease/1000 137 r0 = r0 + 1 138 } 139 gw9("rows=" as *u8); gn9(GV) 140 gw9(" r_top=" as *u8); gn9(rowr[0]) 141 gw9(" r_hip=" as *u8); gn9(rowr[12]) 142 gw9(" r_hem=" as *u8); gn9(rowr[GV-1]); gw9("\n" as *u8) 143 // build ring-grid mesh: GU columns x GV rows; slight ellipse (y depth 82pct of x width) 144 let gnv: i64 = GU*GV 145 let gvp: *i64 = sys_mmap((1 + gnv*3)*8 + 64) as *i64 146 gvp[0] = gnv 147 var rr0: i64 = 0 148 while rr0 < GV { 149 var u0: i64 = 0 150 while u0 < GU { 151 let ang: i64 = u0*2*IT_PI/GU 152 let cs9: i64 = it_cos4096(ang) 153 let sn9b: i64 = it_sin4096(ang) 154 let idx: i64 = (rr0*GU + u0)*3 155 gvp[1 + idx] = cx + rowr[rr0]*cs9/K_MAGIC_4096 156 gvp[1 + idx + 1] = cy + rowr[rr0]*82/100*sn9b/K_MAGIC_4096 157 gvp[1 + idx + 2] = rowz[rr0] 158 u0 = u0 + 1 159 } 160 rr0 = rr0 + 1 161 } 162 // tris: two per quad, wrapping in u 163 let gnt: i64 = GU*(GV-1)*2 164 let gtp: *i64 = sys_mmap((1 + gnt*3)*8 + 64) as *i64 165 gtp[0] = gnt 166 var tw9: i64 = 0 167 var rr1: i64 = 0 168 while rr1 < GV-1 { 169 var u1: i64 = 0 170 while u1 < GU { 171 let a9: i64 = rr1*GU + u1 172 var u2: i64 = u1 + 1 173 if u2 >= GU { u2 = 0 } 174 let b9: i64 = rr1*GU + u2 175 let c9: i64 = (rr1+1)*GU + u1 176 let d9: i64 = (rr1+1)*GU + u2 177 gtp[1 + tw9*3] = a9 178 gtp[1 + tw9*3 + 1] = c9 179 gtp[1 + tw9*3 + 2] = b9 180 tw9 = tw9 + 1 181 gtp[1 + tw9*3] = b9 182 gtp[1 + tw9*3 + 1] = c9 183 gtp[1 + tw9*3 + 2] = d9 184 tw9 = tw9 + 1 185 u1 = u1 + 1 186 } 187 rr1 = rr1 + 1 188 } 189 // pins: the whole top row 190 let gnp: i64 = GU 191 let gpp: *i64 = sys_mmap((1 + gnp)*8 + 64) as *i64 192 gpp[0] = gnp 193 var p0: i64 = 0 194 while p0 < gnp { gpp[1 + p0] = p0; p0 = p0 + 1 } 195 gw9("garment verts=" as *u8); gn9(gnv) 196 gw9(" tris=" as *u8); gn9(gnt) 197 gw9(" pins=" as *u8); gn9(gnp); gw9("\n" as *u8) 198 // append GVRT/GTRI/GPIN 199 let ons: i64 = h[2] 200 let otoc: *i64 = ((b as i64) + 32) as *i64 201 let ns2: i64 = ons + 3 202 let hdr: *i64 = sys_mmap(64) as *i64 203 let toc: *i64 = sys_mmap(ns2*32 + 64) as *i64 204 var o: i64 = 32 + ns2*32 205 var ti: i64 = 0 206 while ti < ons { 207 toc[ti*4] = otoc[ti*4] 208 toc[ti*4+1] = o 209 toc[ti*4+2] = otoc[ti*4+2] 210 toc[ti*4+3] = otoc[ti*4+3] 211 o = o + otoc[ti*4+2]*8 212 ti = ti + 1 213 } 214 let gvl: i64 = 1 + gnv*3 215 let gtl: i64 = 1 + gnt*3 216 let gpl: i64 = 1 + gnp 217 toc[ti*4] = nxa_tag4("GVRT" as *u8) 218 toc[ti*4+1] = o 219 toc[ti*4+2] = gvl 220 toc[ti*4+3] = nxa_check2(1, gvp, gvl) 221 o = o + gvl*8 222 ti = ti + 1 223 toc[ti*4] = nxa_tag4("GTRI" as *u8) 224 toc[ti*4+1] = o 225 toc[ti*4+2] = gtl 226 toc[ti*4+3] = nxa_check2(1, gtp, gtl) 227 o = o + gtl*8 228 ti = ti + 1 229 toc[ti*4] = nxa_tag4("GPIN" as *u8) 230 toc[ti*4+1] = o 231 toc[ti*4+2] = gpl 232 toc[ti*4+3] = nxa_check2(1, gpp, gpl) 233 hdr[0] = nxa_magic() 234 hdr[1] = NXA_VER 235 hdr[2] = ns2 236 hdr[3] = nxa_check2(1, toc, ns2*4) 237 let fd: i64 = sys_openat_wr(argv[2] as *u8, 0x1a4) 238 if fd < 0 { gw9("open out failed\n" as *u8); return 9 } 239 sys_write(fd, hdr as *u8, 32) 240 sys_write(fd, toc as *u8, ns2*32) 241 var ci: i64 = 0 242 while ci < ons { 243 sys_write(fd, ((b as i64) + otoc[ci*4+1]) as *u8, otoc[ci*4+2]*8) 244 ci = ci + 1 245 } 246 sys_write(fd, gvp as *u8, gvl*8) 247 sys_write(fd, gtp as *u8, gtl*8) 248 sys_write(fd, gpp as *u8, gpl*8) 249 sys_close(fd) 250 gw9("NXA+GARMENT written sections=" as *u8); gn9(ns2); gw9("\n" as *u8) 251 return 0 252}