code wiki / _hdl_build / nx_char_gen.nx

nx_char_gen.nx source

↩ module page · 73 lines · 4676 B

1// nx_char_gen.nx -- a SOVEREIGN parametric CHARACTER generator (our analog to a DAZ Genesis figure: a character 2// from PARAMETERS, rendered to a 2D portrait by our OWN integer rasterizer -- no DAZ, no third-party, no float). 3// Top VNs (Being a DIK etc.) pose+render reusable 3D figures to 2D stills; this is the first rung of doing that 4// sovereignly: params (skin/hair/hairstyle/eyes/outfit) -> a stylized VN portrait PNG. HONEST: stylized 2D, not 5// photoreal 3D -- but it PROVES a reusable parametric pipeline (same code, different params -> different 6// characters). license_tier: ORIGINAL expect_exit: 0 7import "nx_syscalls.nx" 8import "nx_shade.nx" 9import "nx_png.nx" 10 11func aw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 12func frect(fb: *i64, w: i64, h: i64, x0: i64, y0: i64, x1: i64, y1: i64, c: i64) -> i64 { 13 var yy: i64 = y0; if yy < 0 { yy = 0 } var ye: i64 = y1; if ye > h { ye = h } 14 while yy < ye { var xx: i64 = x0; if xx < 0 { xx = 0 } var xe: i64 = x1; if xe > w { xe = w } while xx < xe { fb[yy*w + xx] = c; xx = xx + 1 } yy = yy + 1 } 15 return 0 16} 17// filled ellipse centered (cx,cy) radii (rx,ry), color c (integer; rx*rx*ry*ry can be large but fits i64). 18func efill(fb: *i64, w: i64, h: i64, cx: i64, cy: i64, rx: i64, ry: i64, c: i64) -> i64 { 19 var y: i64 = cy - ry 20 while y <= cy + ry { 21 var x: i64 = cx - rx 22 while x <= cx + rx { 23 let dx: i64 = x - cx; let dy: i64 = y - cy 24 if dx*dx*ry*ry + dy*dy*rx*rx <= rx*rx*ry*ry { if x >= 0 { if x < w { if y >= 0 { if y < h { fb[y*w + x] = c } } } } } 25 x = x + 1 26 } 27 y = y + 1 28 } 29 return 0 30} 31 32// render a stylized VN portrait into fb (W x H) from parameters. 33func portrait(fb: *i64, W: i64, H: i64, skin: i64, hair: i64, hstyle: i64, eyec: i64, outfit: i64) -> i64 { 34 let dark: i64 = sh_rgb(34, 30, 42) 35 sh_clear(fb, W, H, sh_rgb(48, 44, 62)) // soft studio bg 36 efill(fb, W, H, 120, 130, 24, 24, sh_rgb(60, 56, 78)) // subtle backdrop disc 37 efill(fb, W, H, 120, 350, 118, 95, outfit) // shoulders / clothing 38 frect(fb, W, H, 104, 178, 136, 246, skin) // neck 39 efill(fb, W, H, 120, 118, 70, 82, hair) // hair (back layer) 40 efill(fb, W, H, 64, 122, 9, 15, skin); efill(fb, W, H, 176, 122, 9, 15, skin) // ears 41 efill(fb, W, H, 120, 120, 56, 68, skin) // head/face 42 // hair front (bangs) -- style varies the silhouette 43 if hstyle == 0 { efill(fb, W, H, 120, 74, 58, 40, hair); frect(fb, W, H, 62, 60, 178, 96, hair) } // straight fringe 44 if hstyle == 1 { efill(fb, W, H, 120, 72, 58, 38, hair); frect(fb, W, H, 120, 60, 180, 104, hair) } // side-swept (covers right) 45 if hstyle == 2 { efill(fb, W, H, 120, 70, 56, 30, hair) } // short 46 // eyes: white, iris, pupil, highlight 47 efill(fb, W, H, 98, 134, 15, 18, sh_rgb(245, 245, 250)); efill(fb, W, H, 142, 134, 15, 18, sh_rgb(245, 245, 250)) 48 efill(fb, W, H, 98, 136, 10, 14, eyec); efill(fb, W, H, 142, 136, 10, 14, eyec) 49 efill(fb, W, H, 98, 138, 5, 8, dark); efill(fb, W, H, 142, 138, 5, 8, dark) 50 efill(fb, W, H, 95, 130, 3, 4, sh_rgb(255, 255, 255)); efill(fb, W, H, 139, 130, 3, 4, sh_rgb(255, 255, 255)) 51 // brows 52 frect(fb, W, H, 85, 112, 111, 116, dark); frect(fb, W, H, 129, 112, 155, 116, dark) 53 // nose hint + mouth 54 efill(fb, W, H, 120, 158, 3, 5, sh_rgb(sh_r(skin)*8/10, sh_g(skin)*8/10, sh_b(skin)*8/10)) 55 efill(fb, W, H, 120, 172, 11, 4, sh_rgb(176, 92, 96)) 56 // blush 57 efill(fb, W, H, 92, 158, 9, 5, sh_rgb(232, 150, 150)); efill(fb, W, H, 148, 158, 9, 5, sh_rgb(232, 150, 150)) 58 return 0 59} 60 61func main(argc: i64, argv: *i64) -> i64 { 62 let W: i64 = 240; let H: i64 = 320 63 let fb: *i64 = sys_mmap(8*W*H) as *i64 64 sys_mkdir("knowledge/staging/game" as *u8, 0x1ed) 65 // Char A -- "Mara" the keeper: auburn side-swept hair, green eyes, fair weathered skin, maroon coat 66 portrait(fb, W, H, sh_rgb(232, 200, 176), sh_rgb(124, 64, 42), 1, sh_rgb(72, 138, 92), sh_rgb(118, 52, 56)) 67 write_png(fb, W, H, "knowledge/staging/game/char_mara.png" as *u8) 68 // Char B -- a different person from the SAME code, different params (proves the parametric pipeline) 69 portrait(fb, W, H, sh_rgb(206, 162, 132), sh_rgb(222, 192, 110), 0, sh_rgb(70, 112, 184), sh_rgb(54, 64, 104)) 70 write_png(fb, W, H, "knowledge/staging/game/char_2.png" as *u8) 71 aw("nx_char_gen: 2 parametric portraits -> knowledge/staging/game/char_mara.png, char_2.png (integer raster, sovereign PNG)\n" as *u8) 72 sys_exit(0); return 0 73}