code wiki / (root) / nx_nxa_garment.nx

nx_nxa_garment.nx source

↩ module page · 220 lines · 8220 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" 13const K_MAGIC_4611686018427387903: i64 = 4611686018427387903 14const K_MAGIC_4096: i64 = 4096 15const K_MAGIC_100000000: i64 = 100000000 16const K_MAGIC_65536: i64 = 65536 17 18const GU: i64 = 36 // columns around the body 19const GV: i64 = 18 // rows above-bust..hem (one-layer strapless dress) 20 21func gw9(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 22func gn9(v: i64) -> i64 { 23 let t: *u8 = sys_mmap(32) as *u8 24 var m: i64 = v; var w: i64 = 0 25 if m<0 { t[w]=45 as u8; w=w+1; m=0-m } 26 if m==0 { t[0]=48 as u8; sys_write(1,t,1); return 0 } 27 let d: *u8 = sys_mmap(32) as *u8 28 var k: i64=0 29 while m>0 { d[k]=(48+(m%10)) as u8; m=m/10; k=k+1 } 30 var j: i64=0 31 while j<k { t[w]=d[k-1-j]; w=w+1; j=j+1 } 32 sys_write(1,t,w); return 0 33} 34func main(argc: i64, argv: *i64) -> i64 { 35 if argc < 3 { gw9("usage: nx_nxa_garment <in.nxa> <out.nxa>\n" as *u8); return 2 } 36 let lp: *i64 = sys_mmap(16) as *i64 37 let b: *u8 = sys_map_file(argv[1] as *u8, lp) 38 let flen: i64 = lp[0] 39 let vwo: i64 = nxa_find(b, flen, nxa_tag4("VERT" as *u8)) 40 if vwo < 0 { gw9("bad nxa\n" as *u8); return 5 } 41 let h: *i64 = b as *i64 42 let nv: i64 = h[vwo] 43 let vx: *i64 = ((b as i64) + vwo*8 + 8) as *i64 44 // measure: z-up models; body extents 45 var mn2: i64 = K_MAGIC_4611686018427387903 46 var mx2: i64 = 0 - K_MAGIC_4611686018427387903 47 var mnx: i64 = K_MAGIC_4611686018427387903 48 var mxx: i64 = 0 - K_MAGIC_4611686018427387903 49 var mny: i64 = K_MAGIC_4611686018427387903 50 var mxy: i64 = 0 - K_MAGIC_4611686018427387903 51 var i0: i64 = 0 52 while i0 < nv { 53 if vx[i0*3] < mnx { mnx = vx[i0*3] } 54 if vx[i0*3] > mxx { mxx = vx[i0*3] } 55 if vx[i0*3+1] < mny { mny = vx[i0*3+1] } 56 if vx[i0*3+1] > mxy { mxy = vx[i0*3+1] } 57 if vx[i0*3+2] < mn2 { mn2 = vx[i0*3+2] } 58 if vx[i0*3+2] > mx2 { mx2 = vx[i0*3+2] } 59 i0 = i0 + 1 60 } 61 let H: i64 = mx2 - mn2 62 let cx: i64 = (mnx + mxx)/2 63 let cy: i64 = (mny + mxy)/2 64 // rows: y01 from 775 (above bust, armpit line -- strapless top edge) down to 370 65 // (mid-thigh); per row measure the body's MAX radius from the axis within the band 66 // (torso only: |x-cx| < .16H so T-pose arms never inflate the top rows) + ease 67 let rowz: *i64 = sys_mmap(GV*8 + 64) as *i64 68 let rowr: *i64 = sys_mmap(GV*8 + 64) as *i64 69 var r0: i64 = 0 70 while r0 < GV { 71 let y01: i64 = 758 - r0*388/(GV-1) 72 rowz[r0] = mn2 + H*y01/1000 73 var best: i64 = 0 74 var i1: i64 = 0 75 while i1 < nv { 76 let dz9: i64 = vx[i1*3+2] - rowz[r0] 77 var az9: i64 = dz9 78 if az9 < 0 { az9 = 0 - az9 } 79 if az9 < H*12/1000 { 80 let dx9: i64 = vx[i1*3] - cx 81 let dy9: i64 = vx[i1*3+1] - cy 82 var ax9: i64 = dx9 83 if ax9 < 0 { ax9 = 0 - ax9 } 84 if ax9 < H*115/1000 { 85 let rr9: i64 = dx9*dx9 + dy9*dy9 86 if rr9 > best { best = rr9 } 87 } 88 } 89 i1 = i1 + 1 90 } 91 // isqrt via itrig-free Newton (small local) 92 var xq: i64 = K_MAGIC_4096 93 if best > K_MAGIC_100000000 { xq = K_MAGIC_65536 } 94 var itn: i64 = 0 95 while itn < 30 { 96 if xq > 0 { let yq: i64 = (xq + best/xq)/2; if yq > 0 { xq = yq } } 97 itn = itn + 1 98 } 99 // ease (pattern-making literature): a fitted woven skirt carries 5-10cm of hip ease 100 // -- on this figure's ~105cm hip that is 5-9pct. Surplus fabric is what BUCKLES into 101 // folds; a zero-ease shrink-wrap can only cone. Flare grows over the last 7 rows. 102 var ease: i64 = 62 103 if r0 > GV-8 { ease = 62 + (r0-(GV-8))*48 } 104 rowr[r0] = xq + xq*ease/1000 105 r0 = r0 + 1 106 } 107 gw9("rows=" as *u8); gn9(GV) 108 gw9(" r_top=" as *u8); gn9(rowr[0]) 109 gw9(" r_hip=" as *u8); gn9(rowr[12]) 110 gw9(" r_hem=" as *u8); gn9(rowr[GV-1]); gw9("\n" as *u8) 111 // build ring-grid mesh: GU columns x GV rows; slight ellipse (y depth 82pct of x width) 112 let gnv: i64 = GU*GV 113 let gvp: *i64 = sys_mmap((1 + gnv*3)*8 + 64) as *i64 114 gvp[0] = gnv 115 var rr0: i64 = 0 116 while rr0 < GV { 117 var u0: i64 = 0 118 while u0 < GU { 119 let ang: i64 = u0*2*IT_PI/GU 120 let cs9: i64 = it_cos4096(ang) 121 let sn9b: i64 = it_sin4096(ang) 122 let idx: i64 = (rr0*GU + u0)*3 123 gvp[1 + idx] = cx + rowr[rr0]*cs9/K_MAGIC_4096 124 gvp[1 + idx + 1] = cy + rowr[rr0]*82/100*sn9b/K_MAGIC_4096 125 gvp[1 + idx + 2] = rowz[rr0] 126 u0 = u0 + 1 127 } 128 rr0 = rr0 + 1 129 } 130 // tris: two per quad, wrapping in u 131 let gnt: i64 = GU*(GV-1)*2 132 let gtp: *i64 = sys_mmap((1 + gnt*3)*8 + 64) as *i64 133 gtp[0] = gnt 134 var tw9: i64 = 0 135 var rr1: i64 = 0 136 while rr1 < GV-1 { 137 var u1: i64 = 0 138 while u1 < GU { 139 let a9: i64 = rr1*GU + u1 140 var u2: i64 = u1 + 1 141 if u2 >= GU { u2 = 0 } 142 let b9: i64 = rr1*GU + u2 143 let c9: i64 = (rr1+1)*GU + u1 144 let d9: i64 = (rr1+1)*GU + u2 145 gtp[1 + tw9*3] = a9 146 gtp[1 + tw9*3 + 1] = c9 147 gtp[1 + tw9*3 + 2] = b9 148 tw9 = tw9 + 1 149 gtp[1 + tw9*3] = b9 150 gtp[1 + tw9*3 + 1] = c9 151 gtp[1 + tw9*3 + 2] = d9 152 tw9 = tw9 + 1 153 u1 = u1 + 1 154 } 155 rr1 = rr1 + 1 156 } 157 // pins: the whole top row 158 let gnp: i64 = GU 159 let gpp: *i64 = sys_mmap((1 + gnp)*8 + 64) as *i64 160 gpp[0] = gnp 161 var p0: i64 = 0 162 while p0 < gnp { gpp[1 + p0] = p0; p0 = p0 + 1 } 163 gw9("garment verts=" as *u8); gn9(gnv) 164 gw9(" tris=" as *u8); gn9(gnt) 165 gw9(" pins=" as *u8); gn9(gnp); gw9("\n" as *u8) 166 // append GVRT/GTRI/GPIN 167 let ons: i64 = h[2] 168 let otoc: *i64 = ((b as i64) + 32) as *i64 169 let ns2: i64 = ons + 3 170 let hdr: *i64 = sys_mmap(64) as *i64 171 let toc: *i64 = sys_mmap(ns2*32 + 64) as *i64 172 var o: i64 = 32 + ns2*32 173 var ti: i64 = 0 174 while ti < ons { 175 toc[ti*4] = otoc[ti*4] 176 toc[ti*4+1] = o 177 toc[ti*4+2] = otoc[ti*4+2] 178 toc[ti*4+3] = otoc[ti*4+3] 179 o = o + otoc[ti*4+2]*8 180 ti = ti + 1 181 } 182 let gvl: i64 = 1 + gnv*3 183 let gtl: i64 = 1 + gnt*3 184 let gpl: i64 = 1 + gnp 185 toc[ti*4] = nxa_tag4("GVRT" as *u8) 186 toc[ti*4+1] = o 187 toc[ti*4+2] = gvl 188 toc[ti*4+3] = nxa_check2(1, gvp, gvl) 189 o = o + gvl*8 190 ti = ti + 1 191 toc[ti*4] = nxa_tag4("GTRI" as *u8) 192 toc[ti*4+1] = o 193 toc[ti*4+2] = gtl 194 toc[ti*4+3] = nxa_check2(1, gtp, gtl) 195 o = o + gtl*8 196 ti = ti + 1 197 toc[ti*4] = nxa_tag4("GPIN" as *u8) 198 toc[ti*4+1] = o 199 toc[ti*4+2] = gpl 200 toc[ti*4+3] = nxa_check2(1, gpp, gpl) 201 hdr[0] = nxa_magic() 202 hdr[1] = NXA_VER 203 hdr[2] = ns2 204 hdr[3] = nxa_check2(1, toc, ns2*4) 205 let fd: i64 = sys_openat_wr(argv[2] as *u8, 0x1a4) 206 if fd < 0 { gw9("open out failed\n" as *u8); return 9 } 207 sys_write(fd, hdr as *u8, 32) 208 sys_write(fd, toc as *u8, ns2*32) 209 var ci: i64 = 0 210 while ci < ons { 211 sys_write(fd, ((b as i64) + otoc[ci*4+1]) as *u8, otoc[ci*4+2]*8) 212 ci = ci + 1 213 } 214 sys_write(fd, gvp as *u8, gvl*8) 215 sys_write(fd, gtp as *u8, gtl*8) 216 sys_write(fd, gpp as *u8, gpl*8) 217 sys_close(fd) 218 gw9("NXA+GARMENT written sections=" as *u8); gn9(ns2); gw9("\n" as *u8) 219 return 0 220}