@limrun/ui 0.16.0 → 0.17.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -0
- package/dist/GLTFLoader-Cami_vza.mjs +1679 -0
- package/dist/GLTFLoader-DeCLxW_q.js +1 -0
- package/dist/components/duo-button-hinge.d.ts +16 -0
- package/dist/components/duo-controls.d.ts +21 -0
- package/dist/components/duo-flat-frame.d.ts +7 -0
- package/dist/components/duo-flat-geometry.d.ts +52 -0
- package/dist/components/duo-fold-motion.d.ts +27 -0
- package/dist/components/duo-fold-renderer.d.ts +19 -0
- package/dist/components/duo-fold-timing.d.ts +1 -0
- package/dist/components/duo-frame.d.ts +16 -0
- package/dist/components/duo-hardware.d.ts +20 -0
- package/dist/components/duo-loading.d.ts +8 -0
- package/dist/components/duo-model.d.ts +19 -0
- package/dist/components/duo-screen-handoff.d.ts +4 -0
- package/dist/components/duo-view.d.ts +9 -0
- package/dist/components/remote-control.d.ts +5 -1
- package/dist/core/duo.d.ts +63 -0
- package/dist/duo-fold-renderer-BXejNHcY.mjs +257 -0
- package/dist/duo-fold-renderer-DdltAnF7.js +53 -0
- package/dist/duo-frame-Cmw4p2uN.mjs +26767 -0
- package/dist/duo-frame-iMtrvx_a.js +4059 -0
- package/dist/duo-view-BAh-w2Kz.js +1 -0
- package/dist/duo-view-D9Ae00rj.mjs +512 -0
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +2 -2
- package/dist/lite.cjs +1 -1
- package/dist/lite.js +1 -1
- package/dist/remote-control-B2jZpf3c.js +1 -0
- package/dist/remote-control-DiddxS8l.mjs +2883 -0
- package/package.json +8 -2
- package/dist/demo.d.ts +0 -1
- package/dist/remote-control-BRgbD7yo.mjs +0 -2516
- package/dist/remote-control-VISrP1zI.js +0 -1
- package/index.html +0 -199
- package/src/assets/Apple_logo_white.svg +0 -4
- package/src/assets/android_boot.gif +0 -0
- package/src/assets/android_boot.webp +0 -0
- package/src/assets/iphone16pro_black.webp +0 -0
- package/src/assets/iphone16pro_black_bg.webp +0 -0
- package/src/assets/iphone16pro_black_landscape.webp +0 -0
- package/src/assets/iphone16pro_black_landscape_bg.webp +0 -0
- package/src/assets/pixel9_black.webp +0 -0
- package/src/assets/pixel9_black_landscape.webp +0 -0
- package/src/assets/pixel_tablet_landscape.webp +0 -0
- package/src/assets/pixel_tablet_portrait.webp +0 -0
- package/src/components/device-install/index.ts +0 -1
- package/src/components/inspect-overlay.css +0 -223
- package/src/components/inspect-overlay.tsx +0 -437
- package/src/components/remote-control-framed.tsx +0 -14
- package/src/components/remote-control.css +0 -131
- package/src/components/remote-control.test.ts +0 -34
- package/src/components/remote-control.tsx +0 -3853
- package/src/core/ax-fetcher.test.ts +0 -418
- package/src/core/ax-fetcher.ts +0 -387
- package/src/core/ax-tree.test.ts +0 -491
- package/src/core/ax-tree.ts +0 -416
- package/src/core/camera.test.ts +0 -155
- package/src/core/camera.ts +0 -133
- package/src/core/constants.ts +0 -344
- package/src/core/webrtc-messages.ts +0 -148
- package/src/demo.tsx +0 -269
- package/src/frame-assets.ts +0 -22
- package/src/hooks/index.ts +0 -1
- package/src/index.ts +0 -29
- package/src/lite.test.ts +0 -30
- package/src/lite.ts +0 -30
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.json +0 -26
- package/tsconfig.node.json +0 -26
- package/vite.config.ts +0 -35
- package/vitest.config.ts +0 -24
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
const C = 1200;
|
|
2
|
+
function U(p, l, T, e, t = 0) {
|
|
3
|
+
const o = [];
|
|
4
|
+
for (const [u, r, c, h] of [
|
|
5
|
+
[p / 2 - e, l / 2 - e, e, 0],
|
|
6
|
+
[-p / 2 + T, l / 2 - T, T, Math.PI / 2],
|
|
7
|
+
[-p / 2 + T, -l / 2 + T, T, Math.PI],
|
|
8
|
+
[p / 2 - e, -l / 2 + e, e, Math.PI * 1.5]
|
|
9
|
+
])
|
|
10
|
+
for (let n = 0; n <= 8; n++) {
|
|
11
|
+
const i = h + n * Math.PI / 16, a = Math.cos(i), s = Math.sin(i);
|
|
12
|
+
o.push({ x: u + (c - t) * a, y: r + (c - t) * s, nx: a, ny: s });
|
|
13
|
+
}
|
|
14
|
+
return o;
|
|
15
|
+
}
|
|
16
|
+
function B() {
|
|
17
|
+
const p = [], l = (t, o, u) => p.push({ side: t, kind: o, vertices: new Float32Array(u) }), T = (t, o, u, r, c, h, n, i, a, s) => {
|
|
18
|
+
const x = [], d = (m, g, v, _) => x.push(m.x + u, m.y + r, g, m.nx * _, m.ny * _, v, 0, 0), E = Math.min(0.32, i / 3, a / 2, s / 2), I = [
|
|
19
|
+
[E, n, 0.707, 0.707],
|
|
20
|
+
[0, n - E, 0, 1],
|
|
21
|
+
[0, n - i + E, 0, 1],
|
|
22
|
+
[E, n - i, -0.707, 0.707]
|
|
23
|
+
];
|
|
24
|
+
for (let m = 0; m < I.length - 1; m++) {
|
|
25
|
+
const g = I[m], v = I[m + 1], _ = U(c, h, a, s, g[0]), H = U(c, h, a, s, v[0]);
|
|
26
|
+
for (let F = 0; F < _.length; F++) {
|
|
27
|
+
const L = (F + 1) % _.length;
|
|
28
|
+
for (const [D, M] of [
|
|
29
|
+
[_[F], g],
|
|
30
|
+
[H[F], v],
|
|
31
|
+
[_[L], g],
|
|
32
|
+
[_[L], g],
|
|
33
|
+
[H[F], v],
|
|
34
|
+
[H[L], v]
|
|
35
|
+
])
|
|
36
|
+
d(D, M[1], M[2], M[3]);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const A = U(c, h, a, s, E);
|
|
40
|
+
for (const [m, g] of [
|
|
41
|
+
[n, 1],
|
|
42
|
+
[n - i, -1]
|
|
43
|
+
])
|
|
44
|
+
for (let v = 0; v < A.length; v++)
|
|
45
|
+
x.push(u, r, m, 0, 0, g, 0, 0), d(A[v], m, g, 0), d(A[(v + 1) % A.length], m, g, 0);
|
|
46
|
+
l(t, o, x);
|
|
47
|
+
}, e = (t, o, u, r, c, h, n, i) => {
|
|
48
|
+
const a = [], s = U(r, c, n, i), x = (d, E) => {
|
|
49
|
+
const I = d + u;
|
|
50
|
+
let A = 0, m = 0;
|
|
51
|
+
o === "inner" && (A = 0.5 - E / 110.8, m = 0.5 + I / 157.5), o === "outer" && (A = 0.5 - d / r, m = 0.5 + E / c), a.push(I, E, h, 0, 0, o === "outer" || o === "back" ? -1 : 1, A, m);
|
|
52
|
+
};
|
|
53
|
+
for (let d = 0; d < s.length; d++)
|
|
54
|
+
x(0, 0), x(s[d].x, s[d].y), x(s[(d + 1) % s.length].x, s[(d + 1) % s.length].y);
|
|
55
|
+
l(t, o, a);
|
|
56
|
+
};
|
|
57
|
+
for (const t of [-1, 1]) {
|
|
58
|
+
const o = t === -1 ? 8.4 : 1.25, u = t === 1 ? 8.4 : 1.25;
|
|
59
|
+
T(t, "metal", t * 82.3 / 2, 0, 82.3, 117.8, 0, 5.2, o, u), e(
|
|
60
|
+
t,
|
|
61
|
+
"seal",
|
|
62
|
+
t * 82.3 / 2,
|
|
63
|
+
82.3 - 2.24,
|
|
64
|
+
117.8 - 2.24,
|
|
65
|
+
0.12,
|
|
66
|
+
t === -1 ? 7.15 : 0.2,
|
|
67
|
+
t === 1 ? 7.15 : 0.2
|
|
68
|
+
), e(
|
|
69
|
+
t,
|
|
70
|
+
"inner",
|
|
71
|
+
t * (157.5 / 4 + 0.55),
|
|
72
|
+
157.5 / 2 - 1.1,
|
|
73
|
+
110.8,
|
|
74
|
+
0.24,
|
|
75
|
+
t === -1 ? 5.3 : 0,
|
|
76
|
+
t === 1 ? 5.3 : 0
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
for (const [t, o, u] of [
|
|
80
|
+
["metal", 117.8, -0.12],
|
|
81
|
+
["seal", 117.8 - 2.24, 0.12],
|
|
82
|
+
["inner", 110.8, 0.24]
|
|
83
|
+
]) {
|
|
84
|
+
const r = [], c = (h, n) => r.push(h, n, u, 0, 0, 1, 0.5 - n / 110.8, 0.5 + h / 157.5);
|
|
85
|
+
for (let h = 0; h < 6; h++) {
|
|
86
|
+
const n = -1.1 + h * 2.2 / 6, i = n + 2.2 / 6;
|
|
87
|
+
for (const [a, s] of [
|
|
88
|
+
[n, -o / 2],
|
|
89
|
+
[i, -o / 2],
|
|
90
|
+
[n, o / 2],
|
|
91
|
+
[n, o / 2],
|
|
92
|
+
[i, -o / 2],
|
|
93
|
+
[i, o / 2]
|
|
94
|
+
])
|
|
95
|
+
c(a, s);
|
|
96
|
+
}
|
|
97
|
+
l(0, t, r);
|
|
98
|
+
}
|
|
99
|
+
e(-1, "seal", -82.3 / 2, 82.3 - 2.24, 117.8 - 2.24, -5.2 - 0.12, 7.15, 0.65), e(-1, "outer", -82.3 / 2, 77.1, 112.2, -5.2 - 0.24, 6.6, 0.8), e(1, "back", 82.3 / 2, 82.3 - 1, 117.8 - 1, -5.2 - 0.12, 0.8, 8);
|
|
100
|
+
for (const t of [82.3 - 37, 82.3 - 25])
|
|
101
|
+
T(1, "metal", t, 117.8 / 2 + 0.4, 9.5, 0.8, -1.4, 2, 0.35, 0.35);
|
|
102
|
+
return T(1, "metal", 82.3 + 0.4, 21, 0.8, 13, -1.4, 2, 0.35, 0.35), p;
|
|
103
|
+
}
|
|
104
|
+
function N(p) {
|
|
105
|
+
const l = [
|
|
106
|
+
[0, 180, 0, -0.5],
|
|
107
|
+
[0.12, 176, -4, -0.46],
|
|
108
|
+
[0.24, 150, -8, -0.4],
|
|
109
|
+
[0.35, 90, -12, -0.32],
|
|
110
|
+
[0.48, 48, -22, -0.14],
|
|
111
|
+
[0.62, 30, -20, -0.04],
|
|
112
|
+
[0.8, 14, -10, 0],
|
|
113
|
+
[1, 0, 0, 0]
|
|
114
|
+
], T = Math.max(0, Math.min(1, p)), e = Math.max(0, l.findIndex((c) => c[0] >= T) - 1), t = l[e], o = l[e + 1], u = Math.max(0, Math.min(1, (T - t[0]) / (o[0] - t[0]))), r = (c) => t[c] + (o[c] - t[c]) * u;
|
|
115
|
+
return { left: r(1) * Math.PI / 180, right: r(2) * Math.PI / 180, shift: r(3) * 82.3 };
|
|
116
|
+
}
|
|
117
|
+
const k = `
|
|
118
|
+
attribute vec3 position;
|
|
119
|
+
attribute vec3 normal;
|
|
120
|
+
attribute vec2 uv;
|
|
121
|
+
uniform vec2 viewport;
|
|
122
|
+
uniform float scale;
|
|
123
|
+
uniform vec2 leaf;
|
|
124
|
+
uniform vec2 roll;
|
|
125
|
+
uniform vec4 hinge;
|
|
126
|
+
uniform int bend;
|
|
127
|
+
uniform float shift;
|
|
128
|
+
uniform float level;
|
|
129
|
+
varying vec3 worldPosition;
|
|
130
|
+
varying vec3 worldNormal;
|
|
131
|
+
varying vec2 texcoord;
|
|
132
|
+
void main() {
|
|
133
|
+
vec3 p = position - vec3(0.,0.,${0.6});
|
|
134
|
+
p = vec3(leaf.x*p.x + leaf.y*p.z, p.y, -leaf.y*p.x + leaf.x*p.z);
|
|
135
|
+
if (bend==1) {
|
|
136
|
+
vec2 a=vec2(-1.1*hinge.x+(position.z-${0.6})*hinge.y,1.1*hinge.y+(position.z-${0.6})*hinge.x);
|
|
137
|
+
vec2 b=vec2(1.1*hinge.z+(position.z-${0.6})*hinge.w,-1.1*hinge.w+(position.z-${0.6})*hinge.z);
|
|
138
|
+
p.xz=mix(a,b,(position.x+1.1)/2.2);
|
|
139
|
+
}
|
|
140
|
+
p += vec3(shift,0.,${0.6});
|
|
141
|
+
vec3 n = vec3(leaf.x*normal.x + leaf.y*normal.z, normal.y, -leaf.y*normal.x + leaf.x*normal.z);
|
|
142
|
+
p.xy = vec2(roll.x*p.x-roll.y*p.y, roll.y*p.x+roll.x*p.y);
|
|
143
|
+
n.xy = vec2(roll.x*n.x-roll.y*n.y, roll.y*n.x+roll.x*n.y);
|
|
144
|
+
p.z -= level;
|
|
145
|
+
worldPosition=p; worldNormal=n; texcoord=uv;
|
|
146
|
+
float w = 1. - p.z/600.;
|
|
147
|
+
gl_Position=vec4(p.xy*scale*2./viewport, -p.z/180., w);
|
|
148
|
+
}`, X = `
|
|
149
|
+
precision highp float;
|
|
150
|
+
uniform int kind;
|
|
151
|
+
uniform sampler2D screen;
|
|
152
|
+
varying vec3 worldPosition;
|
|
153
|
+
varying vec3 worldNormal;
|
|
154
|
+
varying vec2 texcoord;
|
|
155
|
+
void main() {
|
|
156
|
+
if (kind==2) { gl_FragColor=texture2D(screen,texcoord); return; }
|
|
157
|
+
vec3 n=normalize(worldNormal);
|
|
158
|
+
vec3 eye=normalize(vec3(0.,0.,600.)-worldPosition);
|
|
159
|
+
vec3 r=normalize(reflect(-eye,n)+worldPosition/190.);
|
|
160
|
+
float longitude=atan(r.z,r.x);
|
|
161
|
+
float latitude=asin(clamp(r.y,-1.,1.));
|
|
162
|
+
float strip=pow(.5+.5*sin(4.*longitude+1.8*sin(latitude)),12.);
|
|
163
|
+
float fill=pow(.5+.5*cos(2.*longitude-3.*latitude),5.);
|
|
164
|
+
float highlight=pow(max(0.,dot(n,normalize(vec3(-.4,.65,1.)))),90.);
|
|
165
|
+
vec3 silver=vec3(.30,.32,.34)+vec3(.85,.86,.87)*strip+vec3(.48)*fill+vec3(.7)*highlight;
|
|
166
|
+
if(kind==1) silver=vec3(.022,.026,.030)+silver*.035;
|
|
167
|
+
if(kind==3) silver=vec3(.93,.93,.91)*(0.88+.12*max(n.z,0.));
|
|
168
|
+
gl_FragColor=vec4(clamp(silver,0.,1.),1.);
|
|
169
|
+
}`;
|
|
170
|
+
function V(p, l, T) {
|
|
171
|
+
const e = p.getContext("webgl", { alpha: !0, antialias: !0, powerPreference: "low-power" });
|
|
172
|
+
if (!e) throw new Error("Fold animation WebGL unavailable");
|
|
173
|
+
const t = [], o = [], u = [];
|
|
174
|
+
let r = null, c = 0, h = !1;
|
|
175
|
+
const n = () => {
|
|
176
|
+
if (!h) {
|
|
177
|
+
h = !0, cancelAnimationFrame(c);
|
|
178
|
+
for (const i of o) e.deleteBuffer(i);
|
|
179
|
+
for (const i of u) e.deleteTexture(i);
|
|
180
|
+
for (const i of t) e.deleteShader(i);
|
|
181
|
+
r && e.deleteProgram(r), e.getExtension("WEBGL_lose_context")?.loseContext();
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
try {
|
|
185
|
+
for (const [f, P] of [
|
|
186
|
+
[e.VERTEX_SHADER, k],
|
|
187
|
+
[e.FRAGMENT_SHADER, X]
|
|
188
|
+
]) {
|
|
189
|
+
const R = e.createShader(f);
|
|
190
|
+
if (t.push(R), e.shaderSource(R, P), e.compileShader(R), !e.getShaderParameter(R, e.COMPILE_STATUS))
|
|
191
|
+
throw new Error("Fold shader compilation failed");
|
|
192
|
+
}
|
|
193
|
+
r = e.createProgram();
|
|
194
|
+
for (const f of t) e.attachShader(r, f);
|
|
195
|
+
if (e.linkProgram(r), !e.getProgramParameter(r, e.LINK_STATUS)) throw new Error("Fold shader link failed");
|
|
196
|
+
e.useProgram(r);
|
|
197
|
+
const i = (f) => e.getUniformLocation(r, f), a = Object.fromEntries(
|
|
198
|
+
["viewport", "scale", "leaf", "roll", "shift", "level", "kind", "screen", "hinge", "bend"].map((f) => [
|
|
199
|
+
f,
|
|
200
|
+
i(f)
|
|
201
|
+
])
|
|
202
|
+
), s = l.to.inner, x = s ? l.to : l.from, d = s ? l.from : l.to, E = x.frame.rect.min.x + x.frame.rect.max.x, I = x.frame.rect.min.y + x.frame.rect.max.y, A = Math.min(window.devicePixelRatio || 1, 1.5, 1280 / Math.max(E, I));
|
|
203
|
+
p.width = Math.round(E * A), p.height = Math.round(I * A), e.viewport(0, 0, p.width, p.height), e.uniform2f(a.viewport, E, I), e.uniform1i(a.screen, 0), e.enable(e.DEPTH_TEST), e.clearColor(0, 0, 0, 0);
|
|
204
|
+
const m = {
|
|
205
|
+
inner: s ? l.after : l.before,
|
|
206
|
+
outer: s ? l.before : l.after
|
|
207
|
+
}, g = {};
|
|
208
|
+
for (const f of ["inner", "outer"]) {
|
|
209
|
+
const P = e.createTexture();
|
|
210
|
+
u.push(P), g[f] = P, e.bindTexture(e.TEXTURE_2D, P), e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL, 1), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, e.RGBA, e.UNSIGNED_BYTE, m[f]), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE);
|
|
211
|
+
}
|
|
212
|
+
const v = ["position", "normal", "uv"].map((f) => e.getAttribLocation(r, f)), _ = B().map((f) => {
|
|
213
|
+
const P = e.createBuffer();
|
|
214
|
+
return o.push(P), e.bindBuffer(e.ARRAY_BUFFER, P), e.bufferData(e.ARRAY_BUFFER, f.vertices, e.STATIC_DRAW), { ...f, buffer: P };
|
|
215
|
+
}), H = performance.now(), F = d.frame.turns * -Math.PI / 2, L = (x.frame.turns * -Math.PI / 2 - F + Math.PI * 3) % (Math.PI * 2) - Math.PI;
|
|
216
|
+
let D = -1 / 0;
|
|
217
|
+
const M = (f) => {
|
|
218
|
+
if (h) return;
|
|
219
|
+
if (f - D < 1e3 / 60 - 0.5 && f - H < 1200) {
|
|
220
|
+
c = requestAnimationFrame(M);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
D = f;
|
|
224
|
+
const P = Math.min(1, (f - H) / 1200), R = s ? P : 1 - P, b = N(R), z = R * R * (3 - 2 * R), O = F + L * z;
|
|
225
|
+
e.clear(e.COLOR_BUFFER_BIT | e.DEPTH_BUFFER_BIT), e.uniform1f(a.scale, d.frame.scale + (x.frame.scale - d.frame.scale) * z), e.uniform2f(a.roll, Math.cos(O), Math.sin(O)), e.uniform1f(a.shift, b.shift), e.uniform1f(a.level, (5.2 + 0.6 * 2 + 0.24) * (1 - z)), e.uniform4f(
|
|
226
|
+
a.hinge,
|
|
227
|
+
Math.cos(b.left),
|
|
228
|
+
Math.sin(b.left),
|
|
229
|
+
Math.cos(b.right),
|
|
230
|
+
Math.sin(b.right)
|
|
231
|
+
);
|
|
232
|
+
for (const y of _) {
|
|
233
|
+
e.uniform1i(a.bend, y.side === 0 ? 1 : 0);
|
|
234
|
+
const S = y.side === -1 ? b.left : b.right;
|
|
235
|
+
e.uniform2f(a.leaf, Math.cos(S), Math.sin(S));
|
|
236
|
+
const G = y.kind === "inner" || y.kind === "outer";
|
|
237
|
+
e.uniform1i(
|
|
238
|
+
a.kind,
|
|
239
|
+
G ? 2 : y.kind === "metal" ? 0 : y.kind === "seal" ? 1 : 3
|
|
240
|
+
), G && e.bindTexture(e.TEXTURE_2D, g[y.kind]), e.bindBuffer(e.ARRAY_BUFFER, y.buffer);
|
|
241
|
+
for (let w = 0; w < v.length; w++)
|
|
242
|
+
e.enableVertexAttribArray(v[w]), e.vertexAttribPointer(v[w], w === 2 ? 2 : 3, e.FLOAT, !1, 32, w === 2 ? 24 : w * 12);
|
|
243
|
+
e.drawArrays(e.TRIANGLES, 0, y.vertices.length / 8);
|
|
244
|
+
}
|
|
245
|
+
P < 1 ? c = requestAnimationFrame(M) : (n(), T());
|
|
246
|
+
};
|
|
247
|
+
return M(H), n;
|
|
248
|
+
} catch (i) {
|
|
249
|
+
throw n(), i;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
export {
|
|
253
|
+
C as FOLD_DURATION,
|
|
254
|
+
B as foldMeshes,
|
|
255
|
+
N as foldPose,
|
|
256
|
+
V as renderFold
|
|
257
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const G=1200,y=82.3,U=117.8,B=5.2,S=.6;function N(p,l,v,e,t=0){const o=[];for(const[u,r,c,h]of[[p/2-e,l/2-e,e,0],[-p/2+v,l/2-v,v,Math.PI/2],[-p/2+v,-l/2+v,v,Math.PI],[p/2-e,-l/2+e,e,Math.PI*1.5]])for(let n=0;n<=8;n++){const i=h+n*Math.PI/16,a=Math.cos(i),s=Math.sin(i);o.push({x:u+(c-t)*a,y:r+(c-t)*s,nx:a,ny:s})}return o}function W(){const p=[],l=(t,o,u)=>p.push({side:t,kind:o,vertices:new Float32Array(u)}),v=(t,o,u,r,c,h,n,i,a,s)=>{const g=[],d=(m,T,x,R)=>g.push(m.x+u,m.y+r,T,m.nx*R,m.ny*R,x,0,0),E=Math.min(.32,i/3,a/2,s/2),M=[[E,n,.707,.707],[0,n-E,0,1],[0,n-i+E,0,1],[E,n-i,-.707,.707]];for(let m=0;m<M.length-1;m++){const T=M[m],x=M[m+1],R=N(c,h,a,s,T[0]),I=N(c,h,a,s,x[0]);for(let b=0;b<R.length;b++){const L=(b+1)%R.length;for(const[k,F]of[[R[b],T],[I[b],x],[R[L],T],[R[L],T],[I[b],x],[I[L],x]])d(k,F[1],F[2],F[3])}}const _=N(c,h,a,s,E);for(const[m,T]of[[n,1],[n-i,-1]])for(let x=0;x<_.length;x++)g.push(u,r,m,0,0,T,0,0),d(_[x],m,T,0),d(_[(x+1)%_.length],m,T,0);l(t,o,g)},e=(t,o,u,r,c,h,n,i)=>{const a=[],s=N(r,c,n,i),g=(d,E)=>{const M=d+u;let _=0,m=0;o==="inner"&&(_=.5-E/110.8,m=.5+M/157.5),o==="outer"&&(_=.5-d/r,m=.5+E/c),a.push(M,E,h,0,0,o==="outer"||o==="back"?-1:1,_,m)};for(let d=0;d<s.length;d++)g(0,0),g(s[d].x,s[d].y),g(s[(d+1)%s.length].x,s[(d+1)%s.length].y);l(t,o,a)};for(const t of[-1,1]){const o=t===-1?8.4:1.25,u=t===1?8.4:1.25;v(t,"metal",t*y/2,0,y,U,0,B,o,u),e(t,"seal",t*y/2,y-2.24,U-2.24,.12,t===-1?7.15:.2,t===1?7.15:.2),e(t,"inner",t*(157.5/4+.55),157.5/2-1.1,110.8,.24,t===-1?5.3:0,t===1?5.3:0)}for(const[t,o,u]of[["metal",U,-.12],["seal",U-2.24,.12],["inner",110.8,.24]]){const r=[],c=(h,n)=>r.push(h,n,u,0,0,1,.5-n/110.8,.5+h/157.5);for(let h=0;h<6;h++){const n=-1.1+h*2.2/6,i=n+2.2/6;for(const[a,s]of[[n,-o/2],[i,-o/2],[n,o/2],[n,o/2],[i,-o/2],[i,o/2]])c(a,s)}l(0,t,r)}e(-1,"seal",-y/2,y-2.24,U-2.24,-B-.12,7.15,.65),e(-1,"outer",-y/2,77.1,112.2,-B-.24,6.6,.8),e(1,"back",y/2,y-1,U-1,-B-.12,.8,8);for(const t of[y-37,y-25])v(1,"metal",t,U/2+.4,9.5,.8,-1.4,2,.35,.35);return v(1,"metal",y+.4,21,.8,13,-1.4,2,.35,.35),p}function $(p){const l=[[0,180,0,-.5],[.12,176,-4,-.46],[.24,150,-8,-.4],[.35,90,-12,-.32],[.48,48,-22,-.14],[.62,30,-20,-.04],[.8,14,-10,0],[1,0,0,0]],v=Math.max(0,Math.min(1,p)),e=Math.max(0,l.findIndex(c=>c[0]>=v)-1),t=l[e],o=l[e+1],u=Math.max(0,Math.min(1,(v-t[0])/(o[0]-t[0]))),r=c=>t[c]+(o[c]-t[c])*u;return{left:r(1)*Math.PI/180,right:r(2)*Math.PI/180,shift:r(3)*y}}const Y=`
|
|
2
|
+
attribute vec3 position;
|
|
3
|
+
attribute vec3 normal;
|
|
4
|
+
attribute vec2 uv;
|
|
5
|
+
uniform vec2 viewport;
|
|
6
|
+
uniform float scale;
|
|
7
|
+
uniform vec2 leaf;
|
|
8
|
+
uniform vec2 roll;
|
|
9
|
+
uniform vec4 hinge;
|
|
10
|
+
uniform int bend;
|
|
11
|
+
uniform float shift;
|
|
12
|
+
uniform float level;
|
|
13
|
+
varying vec3 worldPosition;
|
|
14
|
+
varying vec3 worldNormal;
|
|
15
|
+
varying vec2 texcoord;
|
|
16
|
+
void main() {
|
|
17
|
+
vec3 p = position - vec3(0.,0.,${S});
|
|
18
|
+
p = vec3(leaf.x*p.x + leaf.y*p.z, p.y, -leaf.y*p.x + leaf.x*p.z);
|
|
19
|
+
if (bend==1) {
|
|
20
|
+
vec2 a=vec2(-1.1*hinge.x+(position.z-${S})*hinge.y,1.1*hinge.y+(position.z-${S})*hinge.x);
|
|
21
|
+
vec2 b=vec2(1.1*hinge.z+(position.z-${S})*hinge.w,-1.1*hinge.w+(position.z-${S})*hinge.z);
|
|
22
|
+
p.xz=mix(a,b,(position.x+1.1)/2.2);
|
|
23
|
+
}
|
|
24
|
+
p += vec3(shift,0.,${S});
|
|
25
|
+
vec3 n = vec3(leaf.x*normal.x + leaf.y*normal.z, normal.y, -leaf.y*normal.x + leaf.x*normal.z);
|
|
26
|
+
p.xy = vec2(roll.x*p.x-roll.y*p.y, roll.y*p.x+roll.x*p.y);
|
|
27
|
+
n.xy = vec2(roll.x*n.x-roll.y*n.y, roll.y*n.x+roll.x*n.y);
|
|
28
|
+
p.z -= level;
|
|
29
|
+
worldPosition=p; worldNormal=n; texcoord=uv;
|
|
30
|
+
float w = 1. - p.z/600.;
|
|
31
|
+
gl_Position=vec4(p.xy*scale*2./viewport, -p.z/180., w);
|
|
32
|
+
}`,j=`
|
|
33
|
+
precision highp float;
|
|
34
|
+
uniform int kind;
|
|
35
|
+
uniform sampler2D screen;
|
|
36
|
+
varying vec3 worldPosition;
|
|
37
|
+
varying vec3 worldNormal;
|
|
38
|
+
varying vec2 texcoord;
|
|
39
|
+
void main() {
|
|
40
|
+
if (kind==2) { gl_FragColor=texture2D(screen,texcoord); return; }
|
|
41
|
+
vec3 n=normalize(worldNormal);
|
|
42
|
+
vec3 eye=normalize(vec3(0.,0.,600.)-worldPosition);
|
|
43
|
+
vec3 r=normalize(reflect(-eye,n)+worldPosition/190.);
|
|
44
|
+
float longitude=atan(r.z,r.x);
|
|
45
|
+
float latitude=asin(clamp(r.y,-1.,1.));
|
|
46
|
+
float strip=pow(.5+.5*sin(4.*longitude+1.8*sin(latitude)),12.);
|
|
47
|
+
float fill=pow(.5+.5*cos(2.*longitude-3.*latitude),5.);
|
|
48
|
+
float highlight=pow(max(0.,dot(n,normalize(vec3(-.4,.65,1.)))),90.);
|
|
49
|
+
vec3 silver=vec3(.30,.32,.34)+vec3(.85,.86,.87)*strip+vec3(.48)*fill+vec3(.7)*highlight;
|
|
50
|
+
if(kind==1) silver=vec3(.022,.026,.030)+silver*.035;
|
|
51
|
+
if(kind==3) silver=vec3(.93,.93,.91)*(0.88+.12*max(n.z,0.));
|
|
52
|
+
gl_FragColor=vec4(clamp(silver,0.,1.),1.);
|
|
53
|
+
}`;function V(p,l,v){const e=p.getContext("webgl",{alpha:!0,antialias:!0,powerPreference:"low-power"});if(!e)throw new Error("Fold animation WebGL unavailable");const t=[],o=[],u=[];let r=null,c=0,h=!1;const n=()=>{if(!h){h=!0,cancelAnimationFrame(c);for(const i of o)e.deleteBuffer(i);for(const i of u)e.deleteTexture(i);for(const i of t)e.deleteShader(i);r&&e.deleteProgram(r),e.getExtension("WEBGL_lose_context")?.loseContext()}};try{for(const[f,P]of[[e.VERTEX_SHADER,Y],[e.FRAGMENT_SHADER,j]]){const A=e.createShader(f);if(t.push(A),e.shaderSource(A,P),e.compileShader(A),!e.getShaderParameter(A,e.COMPILE_STATUS))throw new Error("Fold shader compilation failed")}r=e.createProgram();for(const f of t)e.attachShader(r,f);if(e.linkProgram(r),!e.getProgramParameter(r,e.LINK_STATUS))throw new Error("Fold shader link failed");e.useProgram(r);const i=f=>e.getUniformLocation(r,f),a=Object.fromEntries(["viewport","scale","leaf","roll","shift","level","kind","screen","hinge","bend"].map(f=>[f,i(f)])),s=l.to.inner,g=s?l.to:l.from,d=s?l.from:l.to,E=g.frame.rect.min.x+g.frame.rect.max.x,M=g.frame.rect.min.y+g.frame.rect.max.y,_=Math.min(window.devicePixelRatio||1,1.5,1280/Math.max(E,M));p.width=Math.round(E*_),p.height=Math.round(M*_),e.viewport(0,0,p.width,p.height),e.uniform2f(a.viewport,E,M),e.uniform1i(a.screen,0),e.enable(e.DEPTH_TEST),e.clearColor(0,0,0,0);const m={inner:s?l.after:l.before,outer:s?l.before:l.after},T={};for(const f of["inner","outer"]){const P=e.createTexture();u.push(P),T[f]=P,e.bindTexture(e.TEXTURE_2D,P),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,1),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,m[f]),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE)}const x=["position","normal","uv"].map(f=>e.getAttribLocation(r,f)),R=W().map(f=>{const P=e.createBuffer();return o.push(P),e.bindBuffer(e.ARRAY_BUFFER,P),e.bufferData(e.ARRAY_BUFFER,f.vertices,e.STATIC_DRAW),{...f,buffer:P}}),I=performance.now(),b=d.frame.turns*-Math.PI/2,L=(g.frame.turns*-Math.PI/2-b+Math.PI*3)%(Math.PI*2)-Math.PI;let k=-1/0;const F=f=>{if(h)return;if(f-k<1e3/60-.5&&f-I<G){c=requestAnimationFrame(F);return}k=f;const P=Math.min(1,(f-I)/G),A=s?P:1-P,D=$(A),O=A*A*(3-2*A),X=b+L*O;e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT),e.uniform1f(a.scale,d.frame.scale+(g.frame.scale-d.frame.scale)*O),e.uniform2f(a.roll,Math.cos(X),Math.sin(X)),e.uniform1f(a.shift,D.shift),e.uniform1f(a.level,(B+S*2+.24)*(1-O)),e.uniform4f(a.hinge,Math.cos(D.left),Math.sin(D.left),Math.cos(D.right),Math.sin(D.right));for(const w of R){e.uniform1i(a.bend,w.side===0?1:0);const C=w.side===-1?D.left:D.right;e.uniform2f(a.leaf,Math.cos(C),Math.sin(C));const H=w.kind==="inner"||w.kind==="outer";e.uniform1i(a.kind,H?2:w.kind==="metal"?0:w.kind==="seal"?1:3),H&&e.bindTexture(e.TEXTURE_2D,T[w.kind]),e.bindBuffer(e.ARRAY_BUFFER,w.buffer);for(let z=0;z<x.length;z++)e.enableVertexAttribArray(x[z]),e.vertexAttribPointer(x[z],z===2?2:3,e.FLOAT,!1,32,z===2?24:z*12);e.drawArrays(e.TRIANGLES,0,w.vertices.length/8)}P<1?c=requestAnimationFrame(F):(n(),v())};return F(I),n}catch(i){throw n(),i}}exports.FOLD_DURATION=G;exports.foldMeshes=W;exports.foldPose=$;exports.renderFold=V;
|