nx_makeup.nx source
↩ module page · 83 lines · 4629 B
1// nx_makeup.nx -- MAKEUP layer (the LT_MAKEUP layer type from nx_char_layers, operator "add layers of ... makeup").
2// Unlike clothing (worn geometry), makeup is a COSMETIC recolor/overlay of face REGIONS painted by the photoreal
3// shader (nx_sdfrender mats 12/13/16). v0 recolored lip parts only; ★v2 (2026-07-07, the crash-session follow-ons):
4// EYESHADOW = appended thin LID parts (mat 16, between lash line and brow) + BLUSH = appended cheek-APPLE parts
5// (mat 13, low + frontal -- the old cheek-6/7 recolor sat in the shadowed under-eye zone and read as a dark patch,
6// exactly why it was deferred). Applies to the DETAILED sdf_face; call AFTER sdf_face (+ hairstyle) so appends
7// stack correctly. license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_sdfrender.nx"
10
11// cosmetic materials (nx_sdfrender albedo)
12const MK_LIPSTICK: i64 = 12
13const MK_BLUSH: i64 = 13
14const MK_EYESHADOW: i64 = 16
15// sdf_face part indices (see sdf_face part list): 6/7 cheeks, 10/11 lips
16const FACE_CHEEK_L: i64 = 6
17const FACE_CHEEK_R: i64 = 7
18const FACE_LIP_UP: i64 = 10
19const FACE_LIP_LO: i64 = 11
20// makeup presets
21const MKUP_NONE: i64 = 0
22const MKUP_NATURAL: i64 = 1 // blush + soft lip
23const MKUP_GLAM: i64 = 2 // bold lip + blush
24
25// apply cosmetic materials onto an sdf_face base (call after sdf_face). Flags select the zones.
26func makeup_apply(base: i64, lips_on: i64, blush_on: i64) -> i64 {
27 if lips_on == 1 { sdf_set_mat(base, FACE_LIP_UP, MK_LIPSTICK); sdf_set_mat(base, FACE_LIP_LO, MK_LIPSTICK) }
28 if blush_on == 1 { sdf_set_mat(base, FACE_CHEEK_L, MK_BLUSH); sdf_set_mat(base, FACE_CHEEK_R, MK_BLUSH) }
29 return 0
30}
31// ★v2 apply (2026-07-07): lips recolor (as v0) + APPENDED cosmetic geometry -- eyeshadow LID parts (thin, just
32// above the lash line at (+-258,290,-632), below the brows at (+-250,322,-565); slightly proud in -z so the
33// material query picks them) + blush cheek-APPLE parts (low + frontal on the apples, clear of the under-eye
34// shadow zone that killed the v0 recolor). n0 = current part count (27 straight after sdf_face; pass the
35// hairstyle's return if one was applied). Returns the new part count.
36func makeup_apply2(base: i64, n0: i64, lips_on: i64, blush_on: i64, shadow_on: i64) -> i64 {
37 var n: i64 = n0
38 let p: *i64 = (base + O_PARTS) as *i64
39 if lips_on == 1 { sdf_set_mat(base, FACE_LIP_UP, MK_LIPSTICK); sdf_set_mat(base, FACE_LIP_LO, MK_LIPSTICK) }
40 if shadow_on == 1 {
41 // the lid band is CROWDED: lash (front z~-724) below y~307, brow field reaching z~-651 across y 280..364.
42 // The lid part must be PROUD of the brow field (front ~-680) so the material query picks it on the
43 // between-lash-and-brow skin, while the lash stays in front in its own band = the real makeup layering.
44 p[n*6]=0-255; p[n*6+1]=315; p[n*6+2]=0-640; p[n*6+3]=148; p[n*6+4]=30; p[n*6+5]=40
45 sdf_set_mat(base, n, MK_EYESHADOW)
46 n = n + 1
47 p[n*6]=255; p[n*6+1]=315; p[n*6+2]=0-640; p[n*6+3]=148; p[n*6+4]=30; p[n*6+5]=40
48 sdf_set_mat(base, n, MK_EYESHADOW)
49 n = n + 1
50 }
51 if blush_on == 1 {
52 // on the MALAR prominence (below the outer eye, out on the cheek mass) -- placement lessons: (+-285,-130,
53 // -480) sat inboard by the nose = gaunt-hollow read; (+-310,-70,-470) was BURIED inside the cheek volume
54 // (surface there ~z-580 -> diff 0). The apple must ride the malar SURFACE ~10-15 units proud: front
55 // reach z ~-595 vs the cheek ellipsoid's ~-580 at (x310,y-70).
56 p[n*6]=0-310; p[n*6+1]=0-70; p[n*6+2]=0-540; p[n*6+3]=100; p[n*6+4]=80; p[n*6+5]=55
57 sdf_set_mat(base, n, MK_BLUSH)
58 n = n + 1
59 p[n*6]=310; p[n*6+1]=0-70; p[n*6+2]=0-540; p[n*6+3]=100; p[n*6+4]=80; p[n*6+5]=55
60 sdf_set_mat(base, n, MK_BLUSH)
61 n = n + 1
62 }
63 let np: *i64 = (base + O_NPART) as *i64
64 np[0] = n
65 return n
66}
67// presets (v2): NATURAL = soft lip + blush apples; GLAM = lip + blush + eyeshadow. Returns the new part count.
68// (v0 makeup_style kept below for old callers -- lipstick-only, no appends.)
69func makeup_style2(base: i64, n0: i64, style: i64) -> i64 {
70 if style == MKUP_NATURAL { return makeup_apply2(base, n0, 1, 1, 0) }
71 if style == MKUP_GLAM { return makeup_apply2(base, n0, 1, 1, 1) }
72 return n0
73}
74func makeup_style(base: i64, style: i64) -> i64 {
75 if style == MKUP_NATURAL { makeup_apply(base, 1, 0) }
76 if style == MKUP_GLAM { makeup_apply(base, 1, 0) }
77 return 0
78}
79func makeup_name(s: i64) -> *u8 {
80 if s == 1 { return "natural" as *u8 }
81 if s == 2 { return "glam" as *u8 }
82 return "bare" as *u8
83}