File size: 4,624 Bytes
8a259ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# End-to-End-Sim: App-Layouts (wie OsState.defaultLayout) -> App-Hint-Logik
# -> ONNX -> Glass-Frame. Verifiziert, was die App auf dem Handy zeigen wird.
import sys
import numpy as np
import onnxruntime as ort
from PIL import Image

W, H = 512.0, 1088.0
T = {"panel": 0.15, "card": 0.25, "circle": 0.35, "button": 0.45, "pill": 0.60, "dot": 0.85}


def app_layout(screen):
    els = []
    def el(kind, x0, y0, x1, y1, r):
        els.append(dict(kind=kind, x0=x0, y0=y0, x1=x1, y1=y1, r=r, t=T[kind]))
    el("dot", 28, 20, 52, 44, 10); el("pill", 240, 18, 336, 46, 12); el("dot", 448, 20, 472, 44, 10)
    el("pill", 124, 1012, 236, 1068, 26); el("pill", 196, 1024, 316, 1056, 14); el("pill", 352, 1012, 464, 1068, 26)
    if screen == "home":
        el("panel", 28, 68, 484, 240, 36)
        el("card", 28, 264, 300, 436, 28); el("card", 320, 264, 484, 436, 28)
        el("panel", 28, 456, 484, 576, 28)
        for i in range(4):
            x = 52 + i * 112
            el("pill", x, 880, x + 88, 968, 24)
    elif screen == "lock":
        el("circle", 116, 140, 396, 420, 140)
        el("panel", 96, 600, 416, 712, 40)
        el("button", 156, 780, 356, 868, 32)
    else:  # settings
        for i in range(4):
            el("card", 28, 72 + i * 124, 484, 72 + i * 124 + 100, 24)
        el("panel", 28, 584, 484, 712, 28)
    return els


def sdf_rr(fx, fy, e):
    cx, cy = (e["x0"] + e["x1"]) / 2, (e["y0"] + e["y1"]) / 2
    hx = (e["x1"] - e["x0"]) / 2 - e["r"]; hy = (e["y1"] - e["y0"]) / 2 - e["r"]
    qx = abs(fx - cx) - hx; qy = abs(fy - cy) - hy
    ax = np.maximum(qx, 0); ay = np.maximum(qy, 0)
    return np.sqrt(ax * ax + ay * ay) + np.minimum(np.maximum(qx, qy), 0) - e["r"]


def app_hint(els, ripples, hw=256, hh=544):
    hint = np.zeros((hh, hw, 3), np.float32)
    Y, X = np.mgrid[0:hh, 0:hw].astype(np.float32)
    fx = X * (W / hw) + 1.0; fy = Y * (H / hh) + 1.0   # Pixelzentren ~ Modellkoords
    for (rx, ry, age, s) in ripples:
        cx, cy = rx * W, ry * H
        dist = np.sqrt((X * (W / hw) - cx) ** 2 + (Y * (H / hh) - cy) ** 2)
        r0 = age * 300.0
        fade = (1.0 - age) * s
        ring = np.exp(-((dist - r0) ** 2) / 128.0) * fade
        glow = np.exp(-(dist ** 2) / 4608.0) * fade * 0.8
        hint[..., 1] += np.clip(ring + glow, 0, 1)
    for e in els:
        if e["kind"] == "circle":
            cx, cy = (e["x0"] + e["x1"]) / 2, (e["y0"] + e["y1"]) / 2
            sdf = np.sqrt((fx - cx) ** 2 + (fy - cy) ** 2) - (e["x1"] - e["x0"]) / 2
        else:
            sdf = sdf_rr(fx, fy, e)
        m_in = sdf <= 0
        border = np.abs(sdf) < 2.2
        t = e["t"]
        hint[..., 0] = np.where(border, np.maximum(hint[..., 0], 0.95), hint[..., 0])
        hint[..., 1] = np.where(border, np.maximum(hint[..., 1], 0.5), hint[..., 1])
        fill = max(0.28, t) if t < 0.45 else t
        hint[..., 1] = np.where(m_in, np.maximum(hint[..., 1], fill), hint[..., 1])
        hint[..., 2] = np.where(m_in, np.maximum(hint[..., 2], t), hint[..., 2])
    return hint


def stvec(screen_idx, ripples, phase=0.3, hue=210):
    v = np.zeros(32, np.float32)
    v[screen_idx] = 1.0
    for k, (rx, ry, rr_, s_) in enumerate(ripples[:2]):
        v[10 + k * 4] = rx; v[11 + k * 4] = ry; v[12 + k * 4] = rr_; v[13 + k * 4] = s_
    v[18] = np.sin(2 * np.pi * phase); v[19] = np.cos(2 * np.pi * phase)
    v[20] = 0.5; v[21] = np.sin(2 * np.pi * hue / 360); v[22] = np.cos(2 * np.pi * hue / 360)
    v[23] = 0.8; v[24] = 0.6; v[25] = 1.0; v[29] = 1.0; v[31] = 0.2
    return v


sess = ort.InferenceSession("/home/z/my-project/eos-v5/models/os_glass_v5.onnx",
                            providers=["CPUExecutionProvider"])
rows = []
for si, (name, idx) in enumerate([("lock", 0), ("home", 1), ("settings", 6)]):
    ripples = [(0.5, 0.45, 0.45, 1.0)] if name != "settings" else [(0.3, 0.75, 0.25, 0.9)]
    els = app_layout(name)
    hint = app_hint(els, ripples)                    # 544x256x3 (App-Res)
    vec = stvec(idx, ripples)
    out = sess.run(None, {"hint": np.transpose(hint, (2, 0, 1))[None],
                          "state": vec[None]})[0][0]
    frame = np.transpose(out, (1, 2, 0))
    hint_up = np.repeat(np.repeat(hint, 2, 0), 2, 1)
    row = np.concatenate([hint_up, frame], axis=1)
    rows.append(row)
    Image.fromarray((np.clip(frame, 0, 1) * 255).astype(np.uint8)).save(
        "/home/z/my-project/eos-v5/previews/app_%s.png" % name)
grid = (np.clip(np.concatenate(rows, 0), 0, 1) * 255).astype(np.uint8)
Image.fromarray(grid).save("/home/z/my-project/eos-v5/previews/app_sim_grid.png")
print("app sim ok -> previews/app_sim_grid.png")