code wiki / (root) / nx_skinneural.nx

nx_skinneural.nx source

↩ module page · 156 lines · 6651 B

1// nx_skinneural.nx -- ★P4-R3: DEPLOY the trained skin-family model onto generated people. Loads the R2 artifact 2// (knowledge/skinfam_w.bin: coordinate-MLP weights + the 6 learned patch latents), derives a NOVEL in-family 3// latent from a person seed, and BAKES a seamless albedo RATIO tile (texel 128 = x1.0) for the anatstack 4// as_set_skintex hook -- so a seed-grown person gets seed-grown NEURAL skin that modulates (never replaces) 5// their seeded tone. Integer inference only; consts MUST match nx_skinfam_train_gate. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7import "nx_itrig.nx" 8const SKN_MAGIC_6364136223846793005: i64 = 6364136223846793005 9const SKN_MAGIC_1442695040888963407: i64 = 1442695040888963407 10const SKN_MAGIC_2147483647: i64 = 2147483647 11const SKN_MAGIC_2654435761: i64 = 2654435761 12const SKN_MAGIC_1024: i64 = 1024 13const SKN_MAGIC_888888877: i64 = 888888877 14const SKN_MAGIC_12289: i64 = 12289 15const SKN_MAGIC_25736: i64 = 25736 16const SKN_MAGIC_4096: i64 = 4096 17const SKN_MAGIC_16384: i64 = 16384 18const SKN_MAGIC_65536: i64 = 65536 19 20const SKN_PS: i64 = 32 21const SKN_NFR: i64 = 5 22const SKN_NFF: i64 = 20 23const SKN_NL: i64 = 8 24const SKN_NIN: i64 = 28 25const SKN_NH: i64 = 56 26const SKN_NO: i64 = 3 27const SKN_NPAT: i64 = 6 28const SKN_BYTES: i64 = 14744 // (56*28 + 56 + 3*56 + 3 + 6*8) i64s * 8 29 30func skn_lcg(st: *i64) -> i64 { var h: i64=st[0]; h=h*SKN_MAGIC_6364136223846793005+SKN_MAGIC_1442695040888963407; st[0]=h; return (h>>33)&SKN_MAGIC_2147483647 } 31 32// load the trained model blob; returns 0 if missing/size-mismatch (caller must handle LOUDLY, no fallback) 33func skn_load() -> i64 { 34 let lsz: *i64 = sys_mmap(16) as *i64 35 let blob: *u8 = sys_read_file("knowledge/skinfam_w.bin" as *u8, lsz) 36 if (blob as i64) == 0 { return 0 } 37 if lsz[0] != SKN_BYTES { return 0 } 38 return blob as i64 39} 40 41// derive a NOVEL in-family latent from a person seed: a seeded 2-anchor blend of the learned latents + jitter 42func skn_latent(blob: i64, seed: i64, zout: *i64) -> i64 { 43 let Z: *i64 = (blob + (SKN_NH*SKN_NIN + SKN_NH + SKN_NO*SKN_NH + SKN_NO)*8) as *i64 44 let st: *i64 = sys_mmap(16) as *i64 45 st[0] = seed*SKN_MAGIC_2654435761 + 977 46 skn_lcg(st); skn_lcg(st) 47 let a: i64 = skn_lcg(st) % SKN_NPAT 48 var b: i64 = skn_lcg(st) % SKN_NPAT 49 if b == a { b = (b + 1) % SKN_NPAT } 50 let w: i64 = 200 + skn_lcg(st) % 625 // blend weight in [200,824]/SKN_MAGIC_1024 51 var l: i64 = 0 52 while l < SKN_NL { 53 let za: i64 = Z[a*SKN_NL+l] 54 let zb: i64 = Z[b*SKN_NL+l] 55 zout[l] = za + (zb - za)*w/SKN_MAGIC_1024 + (skn_lcg(st) % 100 - 50) 56 l = l + 1 57 } 58 return 0 59} 60 61// bake a tw x tw seamless RATIO tile (texel = r + g*256 + b*65536, 128 = x1.0) from the net at latent z. 62// ★R3 FINDING (measured): at R2 scale (~1.8k params) the latent's effect is almost purely TONAL -- and tone is 63// deliberately STRIPPED by the ratio normalization (persongen owns tone). So per-person SPATIAL variety comes 64// from a seeded PHASE ROLL + DIHEDRAL orientation of the (genuinely neural) pattern; the latent plumbing stays 65// for R5-scale models where capacity lets z drive the pattern itself. 66func skn_bake(blob: i64, z: *i64, tile: *i64, tw: i64, seed: i64) -> i64 { 67 let ost: *i64 = sys_mmap(16) as *i64 68 ost[0] = seed*SKN_MAGIC_888888877 + SKN_MAGIC_12289 69 skn_lcg(ost); skn_lcg(ost) 70 let phx: i64 = skn_lcg(ost) % tw 71 let phy: i64 = skn_lcg(ost) % tw 72 let orient: i64 = skn_lcg(ost) % 8 73 let W1: *i64 = blob as *i64 74 let B1: *i64 = (blob + SKN_NH*SKN_NIN*8) as *i64 75 let W2: *i64 = (blob + (SKN_NH*SKN_NIN + SKN_NH)*8) as *i64 76 let B2: *i64 = (blob + (SKN_NH*SKN_NIN + SKN_NH + SKN_NO*SKN_NH)*8) as *i64 77 let fr: *i64 = sys_mmap(8*8) as *i64 78 fr[0]=1; fr[1]=2; fr[2]=4; fr[3]=8; fr[4]=16 79 let fin: *i64 = sys_mmap(SKN_NIN*8) as *i64 80 let h: *i64 = sys_mmap(SKN_NH*8) as *i64 81 let raw: *i64 = sys_mmap(tw*tw*3*8) as *i64 82 var mr: i64 = 0 83 var mg: i64 = 0 84 var mb: i64 = 0 85 var ty: i64 = 0 86 while ty < tw { 87 var tx: i64 = 0 88 while tx < tw { 89 // seeded torus roll + dihedral orientation (seamless: the basis is periodic) 90 var sxc: i64 = (tx + phx) % tw 91 var syc: i64 = (ty + phy) % tw 92 if (orient & 1) != 0 { sxc = tw - 1 - sxc } 93 if (orient & 2) != 0 { syc = tw - 1 - syc } 94 if (orient & 4) != 0 { let tmp: i64 = sxc; sxc = syc; syc = tmp } 95 var k: i64 = 0 96 while k < SKN_NFR { 97 let ax: i64 = sxc * SKN_MAGIC_25736 * fr[k] / tw 98 let ay: i64 = syc * SKN_MAGIC_25736 * fr[k] / tw 99 fin[k*4] = it_sin4096(ax) 100 fin[k*4+1] = it_cos4096(ax) 101 fin[k*4+2] = it_sin4096(ay) 102 fin[k*4+3] = it_cos4096(ay) 103 k = k + 1 104 } 105 var l: i64 = 0 106 while l < SKN_NL { fin[SKN_NFF+l] = z[l]; l = l + 1 } 107 var j: i64 = 0 108 while j < SKN_NH { 109 var acc: i64 = B1[j] 110 var i2: i64 = 0 111 while i2 < SKN_NIN { acc = acc + W1[j*SKN_NIN+i2]*fin[i2]/SKN_MAGIC_4096; i2 = i2 + 1 } 112 if acc < 0 { acc = 0 } 113 if acc > SKN_MAGIC_16384 { acc = SKN_MAGIC_16384 } 114 h[j] = acc 115 j = j + 1 116 } 117 let ti: i64 = (ty*tw+tx)*3 118 var c: i64 = 0 119 while c < SKN_NO { 120 var acc: i64 = B2[c] 121 j = 0 122 while j < SKN_NH { acc = acc + W2[c*SKN_NH+j]*h[j]/SKN_MAGIC_4096; j = j + 1 } 123 var v: i64 = acc*255/SKN_MAGIC_4096 124 if v < 1 { v = 1 } 125 if v > 255 { v = 255 } 126 raw[ti+c] = v 127 if c == 0 { mr = mr + v } 128 if c == 1 { mg = mg + v } 129 if c == 2 { mb = mb + v } 130 c = c + 1 131 } 132 tx = tx + 1 133 } 134 ty = ty + 1 135 } 136 mr = mr/(tw*tw); mg = mg/(tw*tw); mb = mb/(tw*tw) 137 if mr < 1 { mr = 1 } 138 if mg < 1 { mg = 1 } 139 if mb < 1 { mb = 1 } 140 // ratio-to-mean, clamped gently: texture variation without tone shift 141 var i3: i64 = 0 142 while i3 < tw*tw { 143 var rr: i64 = raw[i3*3]*128/mr 144 var rg: i64 = raw[i3*3+1]*128/mg 145 var rb: i64 = raw[i3*3+2]*128/mb 146 if rr < 84 { rr = 84 } 147 if rr > 176 { rr = 176 } 148 if rg < 84 { rg = 84 } 149 if rg > 176 { rg = 176 } 150 if rb < 84 { rb = 84 } 151 if rb > 176 { rb = 176 } 152 tile[i3] = rr + rg*256 + rb*SKN_MAGIC_65536 153 i3 = i3 + 1 154 } 155 return 0 156}