nx_mannequin_index_test.nx source
↩ module page · 153 lines · 6047 B
1// Smoke for nx_mannequin_index composite scorer + the two leaf detectors
2// (nx_subsurface_warmth, nx_specular_falloff). Synthetic skin patches
3// representing (a) mannequin-feel render and (b) natural-feel render.
4
5import "nx_syscalls.nx"
6import "nx_image.nx"
7import "nx_subsurface_warmth.nx"
8import "nx_specular_falloff.nx"
9import "nx_mannequin_index.nx"
10
11// Paint a 40x40 RGB skin patch with adjustable shadow R/G boost and
12// adjustable highlight blob size.
13// mode=0: MANNEQUIN — flat RGB ratio in shadow, sharp narrow highlight
14// mode=1: NATURAL — elevated R in shadow (SSS), broad soft highlight
15func paint_skin_patch(rgb: *Image, mask: *Image, mode: i64) -> i64 {
16 let w: i64 = rgb.width
17 let h: i64 = rgb.height
18 var y: i64 = 0
19 while y < h {
20 var x: i64 = 0
21 while x < w {
22 nx_image_set(mask, x, y, 0, 255)
23 // Build a vertical gradient: top half = shadow, bottom = lit.
24 let in_shadow: i64 = y - h / 2
25 if in_shadow < 0 {
26 // SHADOW region.
27 if mode == 0 {
28 // Mannequin: flat tone, R=G=B=120.
29 nx_image_set(rgb, x, y, 0, 120)
30 nx_image_set(rgb, x, y, 1, 120)
31 nx_image_set(rgb, x, y, 2, 120)
32 } else {
33 // Natural: R elevated, G/B suppressed (SSS).
34 nx_image_set(rgb, x, y, 0, 145)
35 nx_image_set(rgb, x, y, 1, 110)
36 nx_image_set(rgb, x, y, 2, 100)
37 }
38 } else {
39 // LIT region: midtone skin.
40 nx_image_set(rgb, x, y, 0, 200)
41 nx_image_set(rgb, x, y, 1, 175)
42 nx_image_set(rgb, x, y, 2, 160)
43 }
44 x = x + 1
45 }
46 y = y + 1
47 }
48 // Highlight: bright blob centered at (w/2, h/2 + 5).
49 // Mannequin: sharp 3x3 blob. Natural: soft 10x10 blob with falloff.
50 let cx: i64 = w / 2
51 let cy: i64 = h / 2 + 5
52 if mode == 0 {
53 var dy: i64 = -1
54 while dy <= 1 {
55 var dx: i64 = -1
56 while dx <= 1 {
57 let xx: i64 = cx + dx
58 let yy: i64 = cy + dy
59 if xx >= 0 { if xx < w { if yy >= 0 { if yy < h {
60 nx_image_set(rgb, xx, yy, 0, 255)
61 nx_image_set(rgb, xx, yy, 1, 250)
62 nx_image_set(rgb, xx, yy, 2, 240)
63 } } } }
64 dx = dx + 1
65 }
66 dy = dy + 1
67 }
68 } else {
69 var dy: i64 = -5
70 while dy <= 5 {
71 var dx: i64 = -5
72 while dx <= 5 {
73 let xx: i64 = cx + dx
74 let yy: i64 = cy + dy
75 if xx >= 0 { if xx < w { if yy >= 0 { if yy < h {
76 // Falloff softer toward edges of 10x10 blob.
77 var ad: i64 = dx
78 if ad < 0 { ad = -ad }
79 var ady: i64 = dy
80 if ady < 0 { ady = -ady }
81 let r_falloff: i64 = 230 - ad * 5 - ady * 5
82 if r_falloff > 200 {
83 nx_image_set(rgb, xx, yy, 0, r_falloff)
84 nx_image_set(rgb, xx, yy, 1, r_falloff - 25)
85 nx_image_set(rgb, xx, yy, 2, r_falloff - 40)
86 }
87 } } } }
88 dx = dx + 1
89 }
90 dy = dy + 1
91 }
92 }
93 return 0
94}
95
96func main() -> i64 {
97 let w: i64 = 40
98 let h: i64 = 40
99
100 // T1: MANNEQUIN patch
101 let rgb_m: *Image = nx_image_alloc(w, h, 3)
102 let mask_m: *Image = nx_image_alloc(w, h, 1)
103 paint_skin_patch(rgb_m, mask_m, 0)
104
105 let sss_res: *i64 = (sys_mmap(NX_SSS_RES_FIELDS * 8 + 16)) as *i64
106 nx_subsurface_warmth(rgb_m, mask_m, sss_res)
107 let sss_verdict_m: i64 = sss_res[NX_SSS_RES_VERDICT]
108 if sss_verdict_m != NX_SSS_VERDICT_MANNEQUIN { return 1 }
109 let sss_score_m: i64 = sss_res[NX_SSS_RES_SCORE]
110 if sss_score_m > 256 { return 2 }
111
112 let spec_res: *i64 = (sys_mmap(NX_SPEC_RES_FIELDS * 8 + 16)) as *i64
113 nx_specular_falloff(rgb_m, mask_m, spec_res)
114 let spec_verdict_m: i64 = spec_res[NX_SPEC_RES_VERDICT]
115 if spec_verdict_m == NX_SPEC_VERDICT_NATURAL { return 10 }
116 let spec_score_m: i64 = spec_res[NX_SPEC_RES_SCORE]
117
118 let mann_res_m: *i64 = (sys_mmap(NX_MANN_RES_FIELDS * 8 + 16)) as *i64
119 nx_mannequin_score(sss_score_m, spec_score_m, -1, mann_res_m)
120 let mann_verdict_m: i64 = mann_res_m[NX_MANN_RES_VERDICT]
121 if mann_verdict_m == NX_MANN_LIVING_PERSON { return 20 }
122
123 // T2: NATURAL patch
124 let rgb_n: *Image = nx_image_alloc(w, h, 3)
125 let mask_n: *Image = nx_image_alloc(w, h, 1)
126 paint_skin_patch(rgb_n, mask_n, 1)
127
128 let sss_res2: *i64 = (sys_mmap(NX_SSS_RES_FIELDS * 8 + 16)) as *i64
129 nx_subsurface_warmth(rgb_n, mask_n, sss_res2)
130 let sss_verdict_n: i64 = sss_res2[NX_SSS_RES_VERDICT]
131 if sss_verdict_n != NX_SSS_VERDICT_NATURAL { return 30 }
132 let sss_score_n: i64 = sss_res2[NX_SSS_RES_SCORE]
133 if sss_score_n < 512 { return 31 }
134
135 let spec_res2: *i64 = (sys_mmap(NX_SPEC_RES_FIELDS * 8 + 16)) as *i64
136 nx_specular_falloff(rgb_n, mask_n, spec_res2)
137 let spec_score_n: i64 = spec_res2[NX_SPEC_RES_SCORE]
138 if spec_score_n <= spec_score_m { return 40 } // natural must beat mannequin
139
140 let mann_res_n: *i64 = (sys_mmap(NX_MANN_RES_FIELDS * 8 + 16)) as *i64
141 nx_mannequin_score(sss_score_n, spec_score_n, -1, mann_res_n)
142 let mann_verdict_n: i64 = mann_res_n[NX_MANN_RES_VERDICT]
143 if mann_verdict_n == NX_MANN_OBVIOUS_PLASTIC { return 50 }
144
145 // T3: corrective phrases — mannequin verdict must emit some.
146 let phrases: *i64 = (sys_mmap(16 * 8 + 16)) as *i64
147 let n_phrases: i64 = nx_mannequin_corrective_phrases(mann_verdict_m,
148 sss_score_m, spec_score_m,
149 -1, phrases)
150 if n_phrases == 0 { return 60 }
151
152 return 0
153}