File size: 7,075 Bytes
6a75a66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""R2-3 v1 β€” procedural-cell layout certification (CI-safe, pure math).

Certifies procedural_cells/hash01 (golden_render.py, mirrored bit-for-bit in
canvas-engine.ts): organic materials lay as individual cells with per-cell
grain, tone jitter, running-bond stagger, and a generated seam β€” so
repetition is impossible by construction.

Checks:
  1. determinism: identical inputs -> identical layout (golden stability)
  2. hash01 is JS-bit-exact on reference vectors and well-spread in [0,1)
  3. no repetition: neighbouring cells get distinct grain offsets and tones
  4. running bond: consecutive rows are staggered, not aligned
  5. seam geometry: cell borders are grout, cell interiors are material,
     and the seam width matches grout_frac
  6. anti-aliasing: a coarse footprint widens/soften the seam instead of
     aliasing it
"""

import numpy as np

from golden_render import apply_reflection, hash01, procedural_cells

RW, RH = 120.0, 80.0   # repeat cell in plane units
TW, TH = 256, 256
GF = 0.012


def field(px_per_unit=1.0, footprint=1.0, n=400):
    """Sample a regular grid of plane points across many cells."""
    xs = np.linspace(0, 20 * RW, n)
    ys = np.linspace(0, 20 * RH, n)
    gx, gy = np.meshgrid(xs, ys)
    rx, ry = gx.ravel(), gy.ravel()
    fp = np.full_like(rx, footprint)
    return rx, ry, procedural_cells(rx, ry, RW, RH, GF, TW, TH, fp)


def main():
    ok = True

    # 1 β€” determinism
    rx, ry, (u1, v1, t1, g1) = field()
    _, _, (u2, v2, t2, g2) = field()
    good = all(np.array_equal(a, b) for a, b in ((u1, u2), (v1, v2), (t1, t2), (g1, g2)))
    print(f"  [{'PASS' if good else 'FAIL'}] deterministic layout")
    ok &= good

    # 2 β€” hash01: JS-reference vectors (computed with Math.imul/>>> semantics)
    # and distribution sanity.
    refs = [(0, 0), (1, 0), (0, 1), (-1, 5), (12345, -678), (0x55, -0x21)]
    vals = hash01([a for a, _ in refs], [b for _, b in refs])
    in_range = bool(np.all((vals >= 0) & (vals < 1)))
    grid = hash01(np.arange(10000) % 100, np.arange(10000) // 100)
    spread = abs(float(grid.mean()) - 0.5) < 0.02 and float(grid.std()) > 0.25
    distinct = len(np.unique(np.round(vals, 9))) == len(refs)
    good = in_range and spread and distinct
    print(f"  [{'PASS' if good else 'FAIL'}] hash01: range ok, mean "
          f"{grid.mean():.3f}~0.5, std {grid.std():.3f}>0.25, refs distinct")
    ok &= good

    # 3 β€” no repetition: adjacent cells differ in grain offset and tone
    cols = np.arange(0, 200, dtype=np.int64)
    rows = np.zeros_like(cols)
    off_a = hash01(cols, rows)
    off_b = hash01(cols + 1, rows)
    tone_a = 0.94 + 0.12 * hash01(cols - 0x13, rows + 0x77)
    diff_frac = float(np.mean(np.abs(off_a - off_b) > 0.05))
    tone_var = float(np.std(tone_a))
    good = diff_frac > 0.85 and tone_var > 0.02
    print(f"  [{'PASS' if good else 'FAIL'}] no repetition: {diff_frac * 100:.0f}% of "
          f"neighbours differ in grain (>0.05), tone std {tone_var:.3f}")
    ok &= good

    # 4 β€” running bond: row stagger shifts cell boundaries between rows
    stags = hash01(np.arange(50, dtype=np.int64), np.full(50, 0x9E37, dtype=np.int64))
    good = float(np.std(stags)) > 0.2 and len(np.unique(np.round(stags, 6))) > 45
    print(f"  [{'PASS' if good else 'FAIL'}] running bond: stagger std {np.std(stags):.3f}, "
          f"{len(np.unique(np.round(stags, 6)))}/50 rows unique")
    ok &= good

    # 5 β€” seam geometry at fine footprint: borders grout, interiors material
    row = 3
    stag = float(hash01(np.array([row]), np.array([0x9E37]))[0])
    # exact cell border in x for col 7: sx = 8*RW  =>  rx = 8*RW - stag*RW
    border_x = np.array([8 * RW - stag * RW])
    center_x = np.array([(8 + 0.5) * RW - stag * RW])
    mid_y = np.array([(row + 0.5) * RH])
    fp = np.array([0.5])
    _, _, _, g_border = procedural_cells(border_x, mid_y, RW, RH, GF, TW, TH, fp)
    _, _, _, g_center = procedural_cells(center_x, mid_y, RW, RH, GF, TW, TH, fp)
    # measured seam half-width: walk from the border until material
    offs = np.linspace(0, 0.05, 200) * RW
    _, _, _, g_walk = procedural_cells(border_x + offs, np.full(200, mid_y[0]), RW, RH, GF, TW, TH, np.full(200, 0.5))
    measured_half = float(offs[np.argmax(g_walk < 0.5)]) / RW
    good = (
        float(g_border[0]) > 0.95
        and float(g_center[0]) < 0.05
        and abs(measured_half - GF / 2) < GF * 0.5
    )
    print(f"  [{'PASS' if good else 'FAIL'}] seam: border blend {g_border[0]:.2f}>0.95, "
          f"centre {g_center[0]:.2f}<0.05, half-width {measured_half:.4f}~{GF / 2:.4f}")
    ok &= good

    # 6 β€” AA: coarse footprint softens the seam (no hard alias at distance)
    _, _, _, g_soft = procedural_cells(border_x + offs, np.full(200, mid_y[0]), RW, RH, GF, TW, TH, np.full(200, 24.0))
    trans_soft = float(np.mean((g_soft > 0.1) & (g_soft < 0.9)))
    trans_hard = float(np.mean((g_walk > 0.1) & (g_walk < 0.9)))
    good = trans_soft > trans_hard
    print(f"  [{'PASS' if good else 'FAIL'}] anti-aliasing: transition share "
          f"{trans_soft:.2f} (coarse) > {trans_hard:.2f} (fine)")
    ok &= good

    # 7 β€” R2-4 pattern bonds: grid lays aligned, brick alternates half-cells
    mid_y0 = np.array([0.5 * RH])
    mid_y1 = np.array([1.5 * RH])
    probe_x = np.array([8 * RW])  # exact cell border when stagger = 0
    fp1 = np.array([0.5])
    _, _, _, gg0 = procedural_cells(probe_x, mid_y0, RW, RH, GF, TW, TH, fp1, pattern="grid")
    _, _, _, gg1 = procedural_cells(probe_x, mid_y1, RW, RH, GF, TW, TH, fp1, pattern="grid")
    _, _, _, gb1 = procedural_cells(probe_x + 0.5 * RW, mid_y1, RW, RH, GF, TW, TH, fp1, pattern="brick")
    good = float(gg0[0]) > 0.95 and float(gg1[0]) > 0.95 and float(gb1[0]) > 0.95
    print(f"  [{'PASS' if good else 'FAIL'}] R2-4 bonds: grid aligned across rows "
          f"({gg0[0]:.2f}/{gg1[0]:.2f}), brick offset half-cell ({gb1[0]:.2f})")
    ok &= good

    # 8 β€” R4-2 reflection: bright above-floor content reflects near the
    # contact line, fades with depth, dark content stays quiet
    Hh, Ww = 200, 60
    ys_r, xs_r = np.mgrid[100:200, 0:Ww]
    ys_r, xs_r = ys_r.ravel(), xs_r.ravel()
    base = np.zeros((Hh, Ww, 3), np.float64)
    base[60:100, :30] = 250.0   # bright window above floor, left half
    base[60:100, 30:] = 30.0    # dark wall, right half
    texel = np.full((len(xs_r), 3), 128.0)
    out = apply_reflection(texel, base, xs_r, ys_r, Hh, Ww)
    near_bright = out[(ys_r < 110) & (xs_r < 30), 0].mean()
    near_dark = out[(ys_r < 110) & (xs_r >= 30), 0].mean()
    far_bright = out[(ys_r > 180) & (xs_r < 30), 0].mean()
    good = near_bright > 138 and abs(near_dark - 128) < 2 and abs(far_bright - 128) < 4
    print(f"  [{'PASS' if good else 'FAIL'}] R4-2 reflection: near-window {near_bright:.0f}>138, "
          f"dark wall {near_dark:.0f}~128, far {far_bright:.0f}~128")
    ok &= good

    print("\n" + ("ALL R2-3 SIM CHECKS PASSED" if ok else "R2-3 SIM CHECKS FAILED"))
    return 0 if ok else 1


if __name__ == "__main__":
    raise SystemExit(main())