@genart-dev/components 0.1.0
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/dist/index.cjs +3985 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +60 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +3963 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3963 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/components/js/index.ts
|
|
8
|
+
var js_exports = {};
|
|
9
|
+
__export(js_exports, {
|
|
10
|
+
animation: () => animation_default,
|
|
11
|
+
boids: () => boids_default,
|
|
12
|
+
canvasUtils: () => canvas_utils_default,
|
|
13
|
+
color: () => color_default,
|
|
14
|
+
colorAdvanced: () => color_advanced_default,
|
|
15
|
+
curl: () => curl_default,
|
|
16
|
+
distribution: () => distribution_default,
|
|
17
|
+
distributionAdvanced: () => distribution_advanced_default,
|
|
18
|
+
dla: () => dla_default,
|
|
19
|
+
easing: () => easing_default,
|
|
20
|
+
flowField: () => flow_field_default,
|
|
21
|
+
grid: () => grid_default,
|
|
22
|
+
gridAdvanced: () => grid_advanced_default,
|
|
23
|
+
lSystem: () => l_system_default,
|
|
24
|
+
math: () => math_default,
|
|
25
|
+
mathAdvanced: () => math_advanced_default,
|
|
26
|
+
matrix: () => matrix_default,
|
|
27
|
+
noise2d: () => noise_2d_default,
|
|
28
|
+
noise3d: () => noise_3d_default,
|
|
29
|
+
noise4d: () => noise_4d_default,
|
|
30
|
+
particle: () => particle_default,
|
|
31
|
+
particleForces: () => particle_forces_default,
|
|
32
|
+
physicsRk4: () => physics_rk4_default,
|
|
33
|
+
physicsSpring: () => physics_spring_default,
|
|
34
|
+
physicsVerlet: () => physics_verlet_default,
|
|
35
|
+
prng: () => prng_default,
|
|
36
|
+
prngUtils: () => prng_utils_default,
|
|
37
|
+
quadtree: () => quadtree_default,
|
|
38
|
+
reactionDiffusion: () => reaction_diffusion_default,
|
|
39
|
+
shape: () => shape_default,
|
|
40
|
+
shapeAdvanced: () => shape_advanced_default,
|
|
41
|
+
spatialHash: () => spatial_hash_default,
|
|
42
|
+
svgPath: () => svg_path_default,
|
|
43
|
+
turtle: () => turtle_default,
|
|
44
|
+
vector: () => vector_default,
|
|
45
|
+
wave: () => wave_default,
|
|
46
|
+
worley: () => worley_default
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// src/components/js/prng.ts
|
|
50
|
+
var prng = {
|
|
51
|
+
name: "prng",
|
|
52
|
+
version: "1.0.0",
|
|
53
|
+
category: "randomness",
|
|
54
|
+
target: "js",
|
|
55
|
+
renderers: [],
|
|
56
|
+
code: `function mulberry32(a) {
|
|
57
|
+
return function() {
|
|
58
|
+
a |= 0; a = a + 0x6D2B79F5 | 0;
|
|
59
|
+
var t = Math.imul(a ^ a >>> 15, 1 | a);
|
|
60
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
61
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function sfc32(a, b, c, d) {
|
|
66
|
+
return function() {
|
|
67
|
+
a |= 0; b |= 0; c |= 0; d |= 0;
|
|
68
|
+
var t = (a + b | 0) + d | 0;
|
|
69
|
+
d = d + 1 | 0; a = b ^ (b >>> 9);
|
|
70
|
+
b = c + (c << 3) | 0; c = (c << 21 | c >>> 11);
|
|
71
|
+
c = c + t | 0;
|
|
72
|
+
return (t >>> 0) / 4294967296;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
`,
|
|
76
|
+
exports: ["mulberry32", "sfc32"],
|
|
77
|
+
dependencies: [],
|
|
78
|
+
description: "Seeded pseudo-random number generators (mulberry32, sfc32).",
|
|
79
|
+
usage: `### prng \u2014 Seeded PRNGs
|
|
80
|
+
|
|
81
|
+
\`\`\`js
|
|
82
|
+
const rng = mulberry32(state.SEED);
|
|
83
|
+
rng(); // \u2192 0.0\u20131.0
|
|
84
|
+
\`\`\`
|
|
85
|
+
|
|
86
|
+
- **mulberry32(seed)** \u2014 fast 32-bit PRNG, good for most use cases
|
|
87
|
+
- **sfc32(a, b, c, d)** \u2014 higher quality, 4 seeds, passes PractRand
|
|
88
|
+
`
|
|
89
|
+
};
|
|
90
|
+
var prng_default = prng;
|
|
91
|
+
|
|
92
|
+
// src/components/js/prng-utils.ts
|
|
93
|
+
var prngUtils = {
|
|
94
|
+
name: "prng-utils",
|
|
95
|
+
version: "1.0.0",
|
|
96
|
+
category: "randomness",
|
|
97
|
+
target: "js",
|
|
98
|
+
renderers: [],
|
|
99
|
+
code: `function randomInt(rng, min, max) {
|
|
100
|
+
return Math.floor(rng() * (max - min + 1)) + min;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function randomFloat(rng, min, max) {
|
|
104
|
+
return rng() * (max - min) + min;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function randomGaussian(rng) {
|
|
108
|
+
var u = 0, v = 0;
|
|
109
|
+
while (u === 0) u = rng();
|
|
110
|
+
while (v === 0) v = rng();
|
|
111
|
+
return Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function randomChoice(rng, arr) {
|
|
115
|
+
return arr[Math.floor(rng() * arr.length)];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function shuffle(rng, arr) {
|
|
119
|
+
var a = arr.slice();
|
|
120
|
+
for (var i = a.length - 1; i > 0; i--) {
|
|
121
|
+
var j = Math.floor(rng() * (i + 1));
|
|
122
|
+
var tmp = a[i]; a[i] = a[j]; a[j] = tmp;
|
|
123
|
+
}
|
|
124
|
+
return a;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function weightedChoice(rng, items, weights) {
|
|
128
|
+
var total = 0;
|
|
129
|
+
for (var i = 0; i < weights.length; i++) total += weights[i];
|
|
130
|
+
var r = rng() * total;
|
|
131
|
+
for (var i = 0; i < items.length; i++) {
|
|
132
|
+
r -= weights[i];
|
|
133
|
+
if (r <= 0) return items[i];
|
|
134
|
+
}
|
|
135
|
+
return items[items.length - 1];
|
|
136
|
+
}
|
|
137
|
+
`,
|
|
138
|
+
exports: ["randomInt", "randomFloat", "randomGaussian", "randomChoice", "shuffle", "weightedChoice"],
|
|
139
|
+
dependencies: ["prng"],
|
|
140
|
+
description: "RNG convenience wrappers (randomInt, randomFloat, shuffle, etc.).",
|
|
141
|
+
usage: `### prng-utils \u2014 RNG Convenience Wrappers
|
|
142
|
+
|
|
143
|
+
\`\`\`js
|
|
144
|
+
const rng = mulberry32(state.SEED);
|
|
145
|
+
randomInt(rng, 1, 10); // \u2192 integer in [1, 10]
|
|
146
|
+
randomFloat(rng, -1, 1); // \u2192 float in [-1, 1)
|
|
147
|
+
randomGaussian(rng); // \u2192 normally distributed float
|
|
148
|
+
randomChoice(rng, ['a','b']); // \u2192 random element
|
|
149
|
+
shuffle(rng, [1,2,3,4]); // \u2192 shuffled copy
|
|
150
|
+
\`\`\`
|
|
151
|
+
`
|
|
152
|
+
};
|
|
153
|
+
var prng_utils_default = prngUtils;
|
|
154
|
+
|
|
155
|
+
// src/components/js/noise-2d.ts
|
|
156
|
+
var noise2d = {
|
|
157
|
+
name: "noise-2d",
|
|
158
|
+
version: "1.0.0",
|
|
159
|
+
category: "noise",
|
|
160
|
+
target: "js",
|
|
161
|
+
renderers: [],
|
|
162
|
+
code: `function perlin2D(rng) {
|
|
163
|
+
var perm = new Uint8Array(512);
|
|
164
|
+
for (var i = 0; i < 256; i++) perm[i] = i;
|
|
165
|
+
for (var i = 255; i > 0; i--) {
|
|
166
|
+
var j = Math.floor(rng() * (i + 1));
|
|
167
|
+
var tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp;
|
|
168
|
+
}
|
|
169
|
+
for (var i = 0; i < 256; i++) perm[256 + i] = perm[i];
|
|
170
|
+
function fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); }
|
|
171
|
+
function grad(hash, x, y) {
|
|
172
|
+
var h = hash & 3;
|
|
173
|
+
return ((h & 1) ? -x : x) + ((h & 2) ? -y : y);
|
|
174
|
+
}
|
|
175
|
+
return function(x, y) {
|
|
176
|
+
var xi = Math.floor(x) & 255, yi = Math.floor(y) & 255;
|
|
177
|
+
var xf = x - Math.floor(x), yf = y - Math.floor(y);
|
|
178
|
+
var u = fade(xf), v = fade(yf);
|
|
179
|
+
var a0 = perm[xi] + yi, a1 = perm[xi + 1] + yi;
|
|
180
|
+
var aa = grad(perm[a0], xf, yf), ba = grad(perm[a1], xf - 1, yf);
|
|
181
|
+
var ab = grad(perm[a0 + 1], xf, yf - 1), bb = grad(perm[a1 + 1], xf - 1, yf - 1);
|
|
182
|
+
var x1 = aa + u * (ba - aa), x2 = ab + u * (bb - ab);
|
|
183
|
+
return (x1 + v * (x2 - x1) + 1) / 2;
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function simplex2D(rng) {
|
|
188
|
+
var perm = new Uint8Array(512);
|
|
189
|
+
for (var i = 0; i < 256; i++) perm[i] = i;
|
|
190
|
+
for (var i = 255; i > 0; i--) {
|
|
191
|
+
var j = Math.floor(rng() * (i + 1));
|
|
192
|
+
var tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp;
|
|
193
|
+
}
|
|
194
|
+
for (var i = 0; i < 256; i++) perm[256 + i] = perm[i];
|
|
195
|
+
var grad2 = [[1,1],[-1,1],[1,-1],[-1,-1],[1,0],[-1,0],[0,1],[0,-1]];
|
|
196
|
+
var F2 = 0.5 * (Math.sqrt(3) - 1), G2 = (3 - Math.sqrt(3)) / 6;
|
|
197
|
+
return function(x, y) {
|
|
198
|
+
var s = (x + y) * F2;
|
|
199
|
+
var i = Math.floor(x + s), j = Math.floor(y + s);
|
|
200
|
+
var t = (i + j) * G2;
|
|
201
|
+
var x0 = x - (i - t), y0 = y - (j - t);
|
|
202
|
+
var i1 = x0 > y0 ? 1 : 0, j1 = x0 > y0 ? 0 : 1;
|
|
203
|
+
var x1 = x0 - i1 + G2, y1 = y0 - j1 + G2;
|
|
204
|
+
var x2 = x0 - 1 + 2 * G2, y2 = y0 - 1 + 2 * G2;
|
|
205
|
+
var ii = i & 255, jj = j & 255;
|
|
206
|
+
function contrib(gx, gy, px, py) {
|
|
207
|
+
var t2 = 0.5 - px * px - py * py;
|
|
208
|
+
if (t2 < 0) return 0;
|
|
209
|
+
t2 *= t2;
|
|
210
|
+
return t2 * t2 * (gx * px + gy * py);
|
|
211
|
+
}
|
|
212
|
+
var g0 = grad2[perm[ii + perm[jj]] & 7];
|
|
213
|
+
var g1 = grad2[perm[ii + i1 + perm[jj + j1]] & 7];
|
|
214
|
+
var g2 = grad2[perm[ii + 1 + perm[jj + 1]] & 7];
|
|
215
|
+
return 0.5 + 35 * (contrib(g0[0], g0[1], x0, y0) + contrib(g1[0], g1[1], x1, y1) + contrib(g2[0], g2[1], x2, y2));
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function valueNoise2D(rng) {
|
|
220
|
+
var values = new Float64Array(256);
|
|
221
|
+
for (var i = 0; i < 256; i++) values[i] = rng();
|
|
222
|
+
function hash(x, y) {
|
|
223
|
+
return values[((x * 374761393 + y * 668265263) & 0x7fffffff) % 256];
|
|
224
|
+
}
|
|
225
|
+
return function(x, y) {
|
|
226
|
+
var ix = Math.floor(x), iy = Math.floor(y);
|
|
227
|
+
var fx = x - ix, fy = y - iy;
|
|
228
|
+
fx = fx * fx * (3 - 2 * fx);
|
|
229
|
+
fy = fy * fy * (3 - 2 * fy);
|
|
230
|
+
var a = hash(ix, iy), b = hash(ix + 1, iy);
|
|
231
|
+
var c = hash(ix, iy + 1), d = hash(ix + 1, iy + 1);
|
|
232
|
+
return a + fx * (b - a) + fy * (c - a) + fx * fy * (a - b - c + d);
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function fbm2D(noiseFn, octaves, lacunarity, gain) {
|
|
237
|
+
octaves = octaves || 6; lacunarity = lacunarity || 2; gain = gain || 0.5;
|
|
238
|
+
return function(x, y) {
|
|
239
|
+
var val = 0, amp = 1, freq = 1, mx = 0;
|
|
240
|
+
for (var o = 0; o < octaves; o++) {
|
|
241
|
+
val += amp * noiseFn(x * freq, y * freq);
|
|
242
|
+
mx += amp;
|
|
243
|
+
amp *= gain;
|
|
244
|
+
freq *= lacunarity;
|
|
245
|
+
}
|
|
246
|
+
return val / mx;
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
`,
|
|
250
|
+
exports: ["perlin2D", "simplex2D", "valueNoise2D", "fbm2D"],
|
|
251
|
+
dependencies: ["prng"],
|
|
252
|
+
description: "2D noise functions (Perlin, simplex, value) and fBm.",
|
|
253
|
+
usage: `### noise-2d \u2014 2D Noise Functions
|
|
254
|
+
|
|
255
|
+
\`\`\`js
|
|
256
|
+
var rng = mulberry32(state.SEED);
|
|
257
|
+
var noise = perlin2D(rng);
|
|
258
|
+
noise(x * 0.01, y * 0.01); // \u2192 0.0\u20131.0
|
|
259
|
+
|
|
260
|
+
var fbm = fbm2D(noise, 6, 2, 0.5);
|
|
261
|
+
fbm(x * 0.01, y * 0.01); // \u2192 fractal noise
|
|
262
|
+
\`\`\`
|
|
263
|
+
`
|
|
264
|
+
};
|
|
265
|
+
var noise_2d_default = noise2d;
|
|
266
|
+
|
|
267
|
+
// src/components/js/noise-3d.ts
|
|
268
|
+
var noise3d = {
|
|
269
|
+
name: "noise-3d",
|
|
270
|
+
version: "1.0.0",
|
|
271
|
+
category: "noise",
|
|
272
|
+
target: "js",
|
|
273
|
+
renderers: [],
|
|
274
|
+
code: `function perlin3D(rng) {
|
|
275
|
+
var perm = new Uint8Array(512);
|
|
276
|
+
for (var i = 0; i < 256; i++) perm[i] = i;
|
|
277
|
+
for (var i = 255; i > 0; i--) {
|
|
278
|
+
var j = Math.floor(rng() * (i + 1));
|
|
279
|
+
var tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp;
|
|
280
|
+
}
|
|
281
|
+
for (var i = 0; i < 256; i++) perm[256 + i] = perm[i];
|
|
282
|
+
function fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); }
|
|
283
|
+
function grad(hash, x, y, z) {
|
|
284
|
+
var h = hash & 15;
|
|
285
|
+
var u = h < 8 ? x : y;
|
|
286
|
+
var v = h < 4 ? y : (h === 12 || h === 14 ? x : z);
|
|
287
|
+
return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);
|
|
288
|
+
}
|
|
289
|
+
return function(x, y, z) {
|
|
290
|
+
var xi = Math.floor(x) & 255, yi = Math.floor(y) & 255, zi = Math.floor(z) & 255;
|
|
291
|
+
var xf = x - Math.floor(x), yf = y - Math.floor(y), zf = z - Math.floor(z);
|
|
292
|
+
var u = fade(xf), v = fade(yf), w = fade(zf);
|
|
293
|
+
var a = perm[xi]+yi, aa = perm[a]+zi, ab = perm[a+1]+zi;
|
|
294
|
+
var b = perm[xi+1]+yi, ba = perm[b]+zi, bb = perm[b+1]+zi;
|
|
295
|
+
return (
|
|
296
|
+
lerp(
|
|
297
|
+
lerp(lerp(grad(perm[aa],xf,yf,zf), grad(perm[ba],xf-1,yf,zf),u),
|
|
298
|
+
lerp(grad(perm[ab],xf,yf-1,zf), grad(perm[bb],xf-1,yf-1,zf),u),v),
|
|
299
|
+
lerp(lerp(grad(perm[aa+1],xf,yf,zf-1), grad(perm[ba+1],xf-1,yf,zf-1),u),
|
|
300
|
+
lerp(grad(perm[ab+1],xf,yf-1,zf-1), grad(perm[bb+1],xf-1,yf-1,zf-1),u),v),
|
|
301
|
+
w) + 1) / 2;
|
|
302
|
+
};
|
|
303
|
+
function lerp(a, b, t) { return a + t * (b - a); }
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function simplex3D(rng) {
|
|
307
|
+
var perm = new Uint8Array(512);
|
|
308
|
+
for (var i = 0; i < 256; i++) perm[i] = i;
|
|
309
|
+
for (var i = 255; i > 0; i--) {
|
|
310
|
+
var j = Math.floor(rng() * (i + 1));
|
|
311
|
+
var tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp;
|
|
312
|
+
}
|
|
313
|
+
for (var i = 0; i < 256; i++) perm[256 + i] = perm[i];
|
|
314
|
+
var grad3 = [[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]];
|
|
315
|
+
var F3 = 1/3, G3 = 1/6;
|
|
316
|
+
return function(x, y, z) {
|
|
317
|
+
var s = (x+y+z)*F3;
|
|
318
|
+
var i=Math.floor(x+s), j=Math.floor(y+s), k=Math.floor(z+s);
|
|
319
|
+
var t = (i+j+k)*G3;
|
|
320
|
+
var x0=x-(i-t), y0=y-(j-t), z0=z-(k-t);
|
|
321
|
+
var i1,j1,k1,i2,j2,k2;
|
|
322
|
+
if (x0>=y0) { if (y0>=z0) {i1=1;j1=0;k1=0;i2=1;j2=1;k2=0;} else if (x0>=z0) {i1=1;j1=0;k1=0;i2=1;j2=0;k2=1;} else {i1=0;j1=0;k1=1;i2=1;j2=0;k2=1;} }
|
|
323
|
+
else { if (y0<z0) {i1=0;j1=0;k1=1;i2=0;j2=1;k2=1;} else if (x0<z0) {i1=0;j1=1;k1=0;i2=0;j2=1;k2=1;} else {i1=0;j1=1;k1=0;i2=1;j2=1;k2=0;} }
|
|
324
|
+
var x1=x0-i1+G3, y1=y0-j1+G3, z1=z0-k1+G3;
|
|
325
|
+
var x2=x0-i2+2*G3, y2=y0-j2+2*G3, z2=z0-k2+2*G3;
|
|
326
|
+
var x3=x0-1+3*G3, y3=y0-1+3*G3, z3=z0-1+3*G3;
|
|
327
|
+
var ii=i&255, jj=j&255, kk=k&255;
|
|
328
|
+
function c(g, px, py, pz) { var t2=0.6-px*px-py*py-pz*pz; return t2<0?0:(t2*=t2, t2*t2*(g[0]*px+g[1]*py+g[2]*pz)); }
|
|
329
|
+
var n = c(grad3[perm[ii+perm[jj+perm[kk]]]%12], x0,y0,z0) + c(grad3[perm[ii+i1+perm[jj+j1+perm[kk+k1]]]%12], x1,y1,z1) + c(grad3[perm[ii+i2+perm[jj+j2+perm[kk+k2]]]%12], x2,y2,z2) + c(grad3[perm[ii+1+perm[jj+1+perm[kk+1]]]%12], x3,y3,z3);
|
|
330
|
+
return 0.5 + 16 * n;
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function fbm3D(noiseFn, octaves, lacunarity, gain) {
|
|
335
|
+
octaves = octaves || 6; lacunarity = lacunarity || 2; gain = gain || 0.5;
|
|
336
|
+
return function(x, y, z) {
|
|
337
|
+
var val = 0, amp = 1, freq = 1, mx = 0;
|
|
338
|
+
for (var o = 0; o < octaves; o++) {
|
|
339
|
+
val += amp * noiseFn(x * freq, y * freq, z * freq);
|
|
340
|
+
mx += amp; amp *= gain; freq *= lacunarity;
|
|
341
|
+
}
|
|
342
|
+
return val / mx;
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
`,
|
|
346
|
+
exports: ["perlin3D", "simplex3D", "fbm3D"],
|
|
347
|
+
dependencies: ["prng"],
|
|
348
|
+
description: "3D noise functions (Perlin, simplex) and fBm.",
|
|
349
|
+
usage: `### noise-3d \u2014 3D Noise Functions
|
|
350
|
+
|
|
351
|
+
\`\`\`js
|
|
352
|
+
var noise = perlin3D(rng);
|
|
353
|
+
noise(x, y, z); // \u2192 0.0\u20131.0
|
|
354
|
+
var fbm = fbm3D(noise, 6);
|
|
355
|
+
\`\`\`
|
|
356
|
+
`
|
|
357
|
+
};
|
|
358
|
+
var noise_3d_default = noise3d;
|
|
359
|
+
|
|
360
|
+
// src/components/js/noise-4d.ts
|
|
361
|
+
var noise4d = {
|
|
362
|
+
name: "noise-4d",
|
|
363
|
+
version: "1.0.0",
|
|
364
|
+
category: "noise",
|
|
365
|
+
target: "js",
|
|
366
|
+
renderers: [],
|
|
367
|
+
code: `function simplex4D(rng) {
|
|
368
|
+
var perm = new Uint8Array(512);
|
|
369
|
+
for (var i = 0; i < 256; i++) perm[i] = i;
|
|
370
|
+
for (var i = 255; i > 0; i--) {
|
|
371
|
+
var j = Math.floor(rng() * (i + 1));
|
|
372
|
+
var tmp = perm[i]; perm[i] = perm[j]; perm[j] = tmp;
|
|
373
|
+
}
|
|
374
|
+
for (var i = 0; i < 256; i++) perm[256 + i] = perm[i];
|
|
375
|
+
var grad4 = [[0,1,1,1],[0,1,1,-1],[0,1,-1,1],[0,1,-1,-1],[0,-1,1,1],[0,-1,1,-1],[0,-1,-1,1],[0,-1,-1,-1],
|
|
376
|
+
[1,0,1,1],[1,0,1,-1],[1,0,-1,1],[1,0,-1,-1],[-1,0,1,1],[-1,0,1,-1],[-1,0,-1,1],[-1,0,-1,-1],
|
|
377
|
+
[1,1,0,1],[1,1,0,-1],[1,-1,0,1],[1,-1,0,-1],[-1,1,0,1],[-1,1,0,-1],[-1,-1,0,1],[-1,-1,0,-1],
|
|
378
|
+
[1,1,1,0],[1,1,-1,0],[1,-1,1,0],[1,-1,-1,0],[-1,1,1,0],[-1,1,-1,0],[-1,-1,1,0],[-1,-1,-1,0]];
|
|
379
|
+
var F4 = (Math.sqrt(5) - 1) / 4, G4 = (5 - Math.sqrt(5)) / 20;
|
|
380
|
+
return function(x, y, z, w) {
|
|
381
|
+
var s = (x+y+z+w) * F4;
|
|
382
|
+
var i=Math.floor(x+s), j=Math.floor(y+s), k=Math.floor(z+s), l=Math.floor(w+s);
|
|
383
|
+
var t = (i+j+k+l) * G4;
|
|
384
|
+
var x0=x-(i-t), y0=y-(j-t), z0=z-(k-t), w0=w-(l-t);
|
|
385
|
+
var rankx=0,ranky=0,rankz=0,rankw=0;
|
|
386
|
+
if(x0>y0)rankx++;else ranky++;
|
|
387
|
+
if(x0>z0)rankx++;else rankz++;
|
|
388
|
+
if(x0>w0)rankx++;else rankw++;
|
|
389
|
+
if(y0>z0)ranky++;else rankz++;
|
|
390
|
+
if(y0>w0)ranky++;else rankw++;
|
|
391
|
+
if(z0>w0)rankz++;else rankw++;
|
|
392
|
+
var i1=rankx>=3?1:0,j1=ranky>=3?1:0,k1=rankz>=3?1:0,l1=rankw>=3?1:0;
|
|
393
|
+
var i2=rankx>=2?1:0,j2=ranky>=2?1:0,k2=rankz>=2?1:0,l2=rankw>=2?1:0;
|
|
394
|
+
var i3=rankx>=1?1:0,j3=ranky>=1?1:0,k3=rankz>=1?1:0,l3=rankw>=1?1:0;
|
|
395
|
+
var x1=x0-i1+G4,y1=y0-j1+G4,z1=z0-k1+G4,w1=w0-l1+G4;
|
|
396
|
+
var x2=x0-i2+2*G4,y2=y0-j2+2*G4,z2=z0-k2+2*G4,w2=w0-l2+2*G4;
|
|
397
|
+
var x3=x0-i3+3*G4,y3=y0-j3+3*G4,z3=z0-k3+3*G4,w3=w0-l3+3*G4;
|
|
398
|
+
var x4=x0-1+4*G4,y4=y0-1+4*G4,z4=z0-1+4*G4,w4=w0-1+4*G4;
|
|
399
|
+
var ii=i&255,jj=j&255,kk=k&255,ll=l&255;
|
|
400
|
+
function c(g,px,py,pz,pw){var t2=0.6-px*px-py*py-pz*pz-pw*pw;return t2<0?0:(t2*=t2,t2*t2*(g[0]*px+g[1]*py+g[2]*pz+g[3]*pw));}
|
|
401
|
+
var n = c(grad4[perm[ii+perm[jj+perm[kk+perm[ll]]]]&31],x0,y0,z0,w0)
|
|
402
|
+
+ c(grad4[perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]]&31],x1,y1,z1,w1)
|
|
403
|
+
+ c(grad4[perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]]&31],x2,y2,z2,w2)
|
|
404
|
+
+ c(grad4[perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]]&31],x3,y3,z3,w3)
|
|
405
|
+
+ c(grad4[perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]]&31],x4,y4,z4,w4);
|
|
406
|
+
return 0.5 + 13.5 * n;
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
`,
|
|
410
|
+
exports: ["simplex4D"],
|
|
411
|
+
dependencies: ["prng"],
|
|
412
|
+
description: "4D simplex noise for loopable animations.",
|
|
413
|
+
usage: `### noise-4d \u2014 4D Simplex Noise
|
|
414
|
+
|
|
415
|
+
\`\`\`js
|
|
416
|
+
var noise = simplex4D(rng);
|
|
417
|
+
// Loopable: map time to a circle in 4D
|
|
418
|
+
var nx = noise(x, y, Math.cos(t) * r, Math.sin(t) * r);
|
|
419
|
+
\`\`\`
|
|
420
|
+
`
|
|
421
|
+
};
|
|
422
|
+
var noise_4d_default = noise4d;
|
|
423
|
+
|
|
424
|
+
// src/components/js/worley.ts
|
|
425
|
+
var worley = {
|
|
426
|
+
name: "worley",
|
|
427
|
+
version: "1.0.0",
|
|
428
|
+
category: "noise",
|
|
429
|
+
target: "js",
|
|
430
|
+
renderers: [],
|
|
431
|
+
code: `function worley2D(rng) {
|
|
432
|
+
var cache = {};
|
|
433
|
+
function cellPoint(ix, iy) {
|
|
434
|
+
var key = ix + ',' + iy;
|
|
435
|
+
if (!cache[key]) {
|
|
436
|
+
var a = ix * 374761393 + iy * 668265263;
|
|
437
|
+
a = (a ^ (a >> 13)) * 1274126177;
|
|
438
|
+
var seed = ((a ^ (a >> 16)) >>> 0);
|
|
439
|
+
var r = mulberry32(seed ^ Math.floor(rng() * 0x7fffffff));
|
|
440
|
+
cache[key] = [ix + r(), iy + r()];
|
|
441
|
+
}
|
|
442
|
+
return cache[key];
|
|
443
|
+
}
|
|
444
|
+
return function(x, y) {
|
|
445
|
+
var ix = Math.floor(x), iy = Math.floor(y);
|
|
446
|
+
var minDist = 1e10;
|
|
447
|
+
for (var dx = -1; dx <= 1; dx++) {
|
|
448
|
+
for (var dy = -1; dy <= 1; dy++) {
|
|
449
|
+
var p = cellPoint(ix + dx, iy + dy);
|
|
450
|
+
var d = (x - p[0]) * (x - p[0]) + (y - p[1]) * (y - p[1]);
|
|
451
|
+
if (d < minDist) minDist = d;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return Math.sqrt(minDist);
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
function worley3D(rng) {
|
|
459
|
+
var cache = {};
|
|
460
|
+
function cellPoint(ix, iy, iz) {
|
|
461
|
+
var key = ix + ',' + iy + ',' + iz;
|
|
462
|
+
if (!cache[key]) {
|
|
463
|
+
var a = ix * 374761393 + iy * 668265263 + iz * 1274126177;
|
|
464
|
+
a = (a ^ (a >> 13)) * 1103515245;
|
|
465
|
+
var seed = ((a ^ (a >> 16)) >>> 0);
|
|
466
|
+
var r = mulberry32(seed ^ Math.floor(rng() * 0x7fffffff));
|
|
467
|
+
cache[key] = [ix + r(), iy + r(), iz + r()];
|
|
468
|
+
}
|
|
469
|
+
return cache[key];
|
|
470
|
+
}
|
|
471
|
+
return function(x, y, z) {
|
|
472
|
+
var ix = Math.floor(x), iy = Math.floor(y), iz = Math.floor(z);
|
|
473
|
+
var minDist = 1e10;
|
|
474
|
+
for (var dx = -1; dx <= 1; dx++)
|
|
475
|
+
for (var dy = -1; dy <= 1; dy++)
|
|
476
|
+
for (var dz = -1; dz <= 1; dz++) {
|
|
477
|
+
var p = cellPoint(ix + dx, iy + dy, iz + dz);
|
|
478
|
+
var d = (x-p[0])*(x-p[0]) + (y-p[1])*(y-p[1]) + (z-p[2])*(z-p[2]);
|
|
479
|
+
if (d < minDist) minDist = d;
|
|
480
|
+
}
|
|
481
|
+
return Math.sqrt(minDist);
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
`,
|
|
485
|
+
exports: ["worley2D", "worley3D"],
|
|
486
|
+
dependencies: ["prng"],
|
|
487
|
+
description: "Worley/cellular noise (2D and 3D).",
|
|
488
|
+
usage: `### worley \u2014 Cellular Noise
|
|
489
|
+
|
|
490
|
+
\`\`\`js
|
|
491
|
+
var w = worley2D(rng);
|
|
492
|
+
w(x * 5, y * 5); // \u2192 distance to nearest cell point
|
|
493
|
+
\`\`\`
|
|
494
|
+
`
|
|
495
|
+
};
|
|
496
|
+
var worley_default = worley;
|
|
497
|
+
|
|
498
|
+
// src/components/js/curl.ts
|
|
499
|
+
var curl = {
|
|
500
|
+
name: "curl",
|
|
501
|
+
version: "1.0.0",
|
|
502
|
+
category: "noise",
|
|
503
|
+
target: "js",
|
|
504
|
+
renderers: [],
|
|
505
|
+
code: `function curlNoise2D(noiseFn, eps) {
|
|
506
|
+
eps = eps || 0.001;
|
|
507
|
+
return function(x, y) {
|
|
508
|
+
var dndx = (noiseFn(x + eps, y) - noiseFn(x - eps, y)) / (2 * eps);
|
|
509
|
+
var dndy = (noiseFn(x, y + eps) - noiseFn(x, y - eps)) / (2 * eps);
|
|
510
|
+
return [dndy, -dndx];
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function curlNoise3D(noiseFnX, noiseFnY, noiseFnZ, eps) {
|
|
515
|
+
eps = eps || 0.001;
|
|
516
|
+
return function(x, y, z) {
|
|
517
|
+
var dzdy = (noiseFnZ(x, y + eps, z) - noiseFnZ(x, y - eps, z)) / (2 * eps);
|
|
518
|
+
var dydz = (noiseFnY(x, y, z + eps) - noiseFnY(x, y, z - eps)) / (2 * eps);
|
|
519
|
+
var dxdz = (noiseFnX(x, y, z + eps) - noiseFnX(x, y, z - eps)) / (2 * eps);
|
|
520
|
+
var dzdx = (noiseFnZ(x + eps, y, z) - noiseFnZ(x - eps, y, z)) / (2 * eps);
|
|
521
|
+
var dydx = (noiseFnY(x + eps, y, z) - noiseFnY(x - eps, y, z)) / (2 * eps);
|
|
522
|
+
var dxdy = (noiseFnX(x, y + eps, z) - noiseFnX(x, y - eps, z)) / (2 * eps);
|
|
523
|
+
return [dzdy - dydz, dxdz - dzdx, dydx - dxdy];
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
`,
|
|
527
|
+
exports: ["curlNoise2D", "curlNoise3D"],
|
|
528
|
+
dependencies: ["noise-2d", "noise-3d"],
|
|
529
|
+
description: "Curl noise for divergence-free flow fields.",
|
|
530
|
+
usage: `### curl \u2014 Curl Noise
|
|
531
|
+
|
|
532
|
+
\`\`\`js
|
|
533
|
+
var noise = perlin2D(rng);
|
|
534
|
+
var curl = curlNoise2D(noise);
|
|
535
|
+
var [vx, vy] = curl(x, y); // divergence-free velocity
|
|
536
|
+
\`\`\`
|
|
537
|
+
`
|
|
538
|
+
};
|
|
539
|
+
var curl_default = curl;
|
|
540
|
+
|
|
541
|
+
// src/components/js/math.ts
|
|
542
|
+
var math = {
|
|
543
|
+
name: "math",
|
|
544
|
+
version: "1.0.0",
|
|
545
|
+
category: "math",
|
|
546
|
+
target: "js",
|
|
547
|
+
renderers: [],
|
|
548
|
+
code: `function lerp(a, b, t) { return a + t * (b - a); }
|
|
549
|
+
function clamp(v, lo, hi) { return v < lo ? lo : v > hi ? hi : v; }
|
|
550
|
+
function clamp01(v) { return v < 0 ? 0 : v > 1 ? 1 : v; }
|
|
551
|
+
function remap(v, inLo, inHi, outLo, outHi) {
|
|
552
|
+
return outLo + (v - inLo) / (inHi - inLo) * (outHi - outLo);
|
|
553
|
+
}
|
|
554
|
+
function smoothstep(edge0, edge1, x) {
|
|
555
|
+
var t = clamp((x - edge0) / (edge1 - edge0), 0, 1);
|
|
556
|
+
return t * t * (3 - 2 * t);
|
|
557
|
+
}
|
|
558
|
+
function inverseLerp(a, b, v) { return (v - a) / (b - a); }
|
|
559
|
+
function mod(a, n) { return ((a % n) + n) % n; }
|
|
560
|
+
function fract(x) { return x - Math.floor(x); }
|
|
561
|
+
function sign0(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }
|
|
562
|
+
function step(edge, x) { return x < edge ? 0 : 1; }
|
|
563
|
+
`,
|
|
564
|
+
exports: ["lerp", "clamp", "clamp01", "remap", "smoothstep", "inverseLerp", "mod", "fract", "sign0", "step"],
|
|
565
|
+
dependencies: [],
|
|
566
|
+
description: "Core math utilities (lerp, clamp, smoothstep, remap, etc.).",
|
|
567
|
+
usage: `### math \u2014 Core Math Utilities
|
|
568
|
+
|
|
569
|
+
\`\`\`js
|
|
570
|
+
lerp(0, 100, 0.5); // \u2192 50
|
|
571
|
+
clamp(1.5, 0, 1); // \u2192 1
|
|
572
|
+
smoothstep(0, 1, 0.5); // \u2192 0.5 (S-curve)
|
|
573
|
+
remap(0.5, 0, 1, -10, 10); // \u2192 0
|
|
574
|
+
\`\`\`
|
|
575
|
+
`
|
|
576
|
+
};
|
|
577
|
+
var math_default = math;
|
|
578
|
+
|
|
579
|
+
// src/components/js/math-advanced.ts
|
|
580
|
+
var mathAdvanced = {
|
|
581
|
+
name: "math-advanced",
|
|
582
|
+
version: "1.0.0",
|
|
583
|
+
category: "math",
|
|
584
|
+
target: "js",
|
|
585
|
+
renderers: [],
|
|
586
|
+
code: `var PHI = (1 + Math.sqrt(5)) / 2;
|
|
587
|
+
var goldenRatio = PHI;
|
|
588
|
+
|
|
589
|
+
function bezierPoint(a, b, c, d, t) {
|
|
590
|
+
var t2 = t * t, t3 = t2 * t;
|
|
591
|
+
var mt = 1 - t, mt2 = mt * mt, mt3 = mt2 * mt;
|
|
592
|
+
return mt3 * a + 3 * mt2 * t * b + 3 * mt * t2 * c + t3 * d;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function catmullRom(p0, p1, p2, p3, t) {
|
|
596
|
+
var t2 = t * t, t3 = t2 * t;
|
|
597
|
+
return 0.5 * ((2 * p1) + (-p0 + p2) * t +
|
|
598
|
+
(2 * p0 - 5 * p1 + 4 * p2 - p3) * t2 +
|
|
599
|
+
(-p0 + 3 * p1 - 3 * p2 + p3) * t3);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function springDamper(current, target, velocity, stiffness, damping, dt) {
|
|
603
|
+
var force = -stiffness * (current - target) - damping * velocity;
|
|
604
|
+
velocity += force * dt;
|
|
605
|
+
current += velocity * dt;
|
|
606
|
+
return { value: current, velocity: velocity };
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
function exponentialDecay(value, target, rate, dt) {
|
|
610
|
+
return target + (value - target) * Math.exp(-rate * dt);
|
|
611
|
+
}
|
|
612
|
+
`,
|
|
613
|
+
exports: ["bezierPoint", "catmullRom", "springDamper", "exponentialDecay", "goldenRatio", "PHI"],
|
|
614
|
+
dependencies: ["math"],
|
|
615
|
+
description: "Advanced interpolation and constants (Bezier, Catmull-Rom, spring, PHI).",
|
|
616
|
+
usage: `### math-advanced \u2014 Advanced Interpolation
|
|
617
|
+
|
|
618
|
+
\`\`\`js
|
|
619
|
+
bezierPoint(0, 0.5, 0.5, 1, t); // cubic Bezier
|
|
620
|
+
catmullRom(p0, p1, p2, p3, t); // Catmull-Rom spline
|
|
621
|
+
springDamper(pos, target, vel, 100, 10, dt);
|
|
622
|
+
exponentialDecay(current, target, 5, dt);
|
|
623
|
+
PHI; // \u2192 1.618...
|
|
624
|
+
\`\`\`
|
|
625
|
+
`
|
|
626
|
+
};
|
|
627
|
+
var math_advanced_default = mathAdvanced;
|
|
628
|
+
|
|
629
|
+
// src/components/js/easing.ts
|
|
630
|
+
var easing = {
|
|
631
|
+
name: "easing",
|
|
632
|
+
version: "1.0.0",
|
|
633
|
+
category: "easing",
|
|
634
|
+
target: "js",
|
|
635
|
+
renderers: [],
|
|
636
|
+
code: `function easeInQuad(t) { return t * t; }
|
|
637
|
+
function easeOutQuad(t) { return t * (2 - t); }
|
|
638
|
+
function easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; }
|
|
639
|
+
function easeInCubic(t) { return t * t * t; }
|
|
640
|
+
function easeOutCubic(t) { var u = 1 - t; return 1 - u * u * u; }
|
|
641
|
+
function easeInOutCubic(t) {
|
|
642
|
+
return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
643
|
+
}
|
|
644
|
+
function easeInOutSine(t) { return -(Math.cos(Math.PI * t) - 1) / 2; }
|
|
645
|
+
function easeInExpo(t) { return t === 0 ? 0 : Math.pow(2, 10 * t - 10); }
|
|
646
|
+
function easeOutExpo(t) { return t === 1 ? 1 : 1 - Math.pow(2, -10 * t); }
|
|
647
|
+
function easeOutElastic(t) {
|
|
648
|
+
if (t === 0 || t === 1) return t;
|
|
649
|
+
return Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * (2 * Math.PI / 3)) + 1;
|
|
650
|
+
}
|
|
651
|
+
function easeOutBounce(t) {
|
|
652
|
+
if (t < 1 / 2.75) return 7.5625 * t * t;
|
|
653
|
+
if (t < 2 / 2.75) { t -= 1.5 / 2.75; return 7.5625 * t * t + 0.75; }
|
|
654
|
+
if (t < 2.5 / 2.75) { t -= 2.25 / 2.75; return 7.5625 * t * t + 0.9375; }
|
|
655
|
+
t -= 2.625 / 2.75; return 7.5625 * t * t + 0.984375;
|
|
656
|
+
}
|
|
657
|
+
function spring(t, freq, decay) {
|
|
658
|
+
freq = freq || 4; decay = decay || 4;
|
|
659
|
+
return 1 - Math.exp(-decay * t) * Math.cos(freq * Math.PI * t);
|
|
660
|
+
}
|
|
661
|
+
`,
|
|
662
|
+
exports: [
|
|
663
|
+
"easeInQuad",
|
|
664
|
+
"easeOutQuad",
|
|
665
|
+
"easeInOutQuad",
|
|
666
|
+
"easeInCubic",
|
|
667
|
+
"easeOutCubic",
|
|
668
|
+
"easeInOutCubic",
|
|
669
|
+
"easeInOutSine",
|
|
670
|
+
"easeInExpo",
|
|
671
|
+
"easeOutExpo",
|
|
672
|
+
"easeOutElastic",
|
|
673
|
+
"easeOutBounce",
|
|
674
|
+
"spring"
|
|
675
|
+
],
|
|
676
|
+
dependencies: [],
|
|
677
|
+
description: "Easing functions for smooth animations (0\u21921 domain).",
|
|
678
|
+
usage: `### easing \u2014 Easing Functions
|
|
679
|
+
|
|
680
|
+
\`\`\`js
|
|
681
|
+
easeInOutCubic(t); // smooth S-curve
|
|
682
|
+
easeOutElastic(t); // springy overshoot
|
|
683
|
+
easeOutBounce(t); // bouncing effect
|
|
684
|
+
spring(t, 4, 4); // damped spring
|
|
685
|
+
\`\`\`
|
|
686
|
+
`
|
|
687
|
+
};
|
|
688
|
+
var easing_default = easing;
|
|
689
|
+
|
|
690
|
+
// src/components/js/color.ts
|
|
691
|
+
var color = {
|
|
692
|
+
name: "color",
|
|
693
|
+
version: "1.0.0",
|
|
694
|
+
category: "color",
|
|
695
|
+
target: "js",
|
|
696
|
+
renderers: [],
|
|
697
|
+
code: `function hexToRgb(hex) {
|
|
698
|
+
var n = parseInt(hex.charAt(0) === '#' ? hex.slice(1) : hex, 16);
|
|
699
|
+
return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
function rgbToHex(r, g, b) {
|
|
703
|
+
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
function hslToRgb(h, s, l) {
|
|
707
|
+
h = h / 360; s = s / 100; l = l / 100;
|
|
708
|
+
if (s === 0) { var v = Math.round(l * 255); return [v, v, v]; }
|
|
709
|
+
function hue2rgb(p, q, t) {
|
|
710
|
+
if (t < 0) t += 1; if (t > 1) t -= 1;
|
|
711
|
+
if (t < 1/6) return p + (q - p) * 6 * t;
|
|
712
|
+
if (t < 1/2) return q;
|
|
713
|
+
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
|
714
|
+
return p;
|
|
715
|
+
}
|
|
716
|
+
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
717
|
+
var p = 2 * l - q;
|
|
718
|
+
return [
|
|
719
|
+
Math.round(hue2rgb(p, q, h + 1/3) * 255),
|
|
720
|
+
Math.round(hue2rgb(p, q, h) * 255),
|
|
721
|
+
Math.round(hue2rgb(p, q, h - 1/3) * 255)
|
|
722
|
+
];
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
function rgbToHsl(r, g, b) {
|
|
726
|
+
r /= 255; g /= 255; b /= 255;
|
|
727
|
+
var max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
728
|
+
var h = 0, s = 0, l = (max + min) / 2;
|
|
729
|
+
if (max !== min) {
|
|
730
|
+
var d = max - min;
|
|
731
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
732
|
+
if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
733
|
+
else if (max === g) h = ((b - r) / d + 2) / 6;
|
|
734
|
+
else h = ((r - g) / d + 4) / 6;
|
|
735
|
+
}
|
|
736
|
+
return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
function lerpColor(c1, c2, t) {
|
|
740
|
+
var a = hexToRgb(c1), b = hexToRgb(c2);
|
|
741
|
+
return rgbToHex(
|
|
742
|
+
Math.round(a[0] + (b[0] - a[0]) * t),
|
|
743
|
+
Math.round(a[1] + (b[1] - a[1]) * t),
|
|
744
|
+
Math.round(a[2] + (b[2] - a[2]) * t)
|
|
745
|
+
);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function contrastRatio(hex1, hex2) {
|
|
749
|
+
function luminance(hex) {
|
|
750
|
+
var rgb = hexToRgb(hex).map(function(c) {
|
|
751
|
+
c = c / 255;
|
|
752
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
753
|
+
});
|
|
754
|
+
return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
|
|
755
|
+
}
|
|
756
|
+
var l1 = luminance(hex1), l2 = luminance(hex2);
|
|
757
|
+
var lighter = Math.max(l1, l2), darker = Math.min(l1, l2);
|
|
758
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
759
|
+
}
|
|
760
|
+
`,
|
|
761
|
+
exports: ["hexToRgb", "rgbToHex", "hslToRgb", "rgbToHsl", "lerpColor", "contrastRatio"],
|
|
762
|
+
dependencies: [],
|
|
763
|
+
description: "Color space conversion (hex, RGB, HSL) and utilities.",
|
|
764
|
+
usage: `### color \u2014 Color Space Conversion
|
|
765
|
+
|
|
766
|
+
\`\`\`js
|
|
767
|
+
hexToRgb('#ff0000'); // \u2192 [255, 0, 0]
|
|
768
|
+
rgbToHex(255, 128, 0); // \u2192 '#ff8000'
|
|
769
|
+
hslToRgb(200, 80, 50); // \u2192 [r, g, b]
|
|
770
|
+
lerpColor('#000', '#fff', 0.5);
|
|
771
|
+
contrastRatio('#000', '#fff'); // \u2192 21
|
|
772
|
+
\`\`\`
|
|
773
|
+
`
|
|
774
|
+
};
|
|
775
|
+
var color_default = color;
|
|
776
|
+
|
|
777
|
+
// src/components/js/color-advanced.ts
|
|
778
|
+
var colorAdvanced = {
|
|
779
|
+
name: "color-advanced",
|
|
780
|
+
version: "1.0.0",
|
|
781
|
+
category: "color",
|
|
782
|
+
target: "js",
|
|
783
|
+
renderers: [],
|
|
784
|
+
code: `function rgbToOklab(r, g, b) {
|
|
785
|
+
r /= 255; g /= 255; b /= 255;
|
|
786
|
+
var lr = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
787
|
+
var lg = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
788
|
+
var lb = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
789
|
+
var l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);
|
|
790
|
+
var m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);
|
|
791
|
+
var s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);
|
|
792
|
+
return [
|
|
793
|
+
0.2104542553 * l + 0.7936177850 * m - 0.0040720468 * s,
|
|
794
|
+
1.9779984951 * l - 2.4285922050 * m + 0.4505937099 * s,
|
|
795
|
+
0.0259040371 * l + 0.7827717662 * m - 0.8086757660 * s
|
|
796
|
+
];
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
function oklabToRgb(L, a, b) {
|
|
800
|
+
var l = L + 0.3963377774 * a + 0.2158037573 * b;
|
|
801
|
+
var m = L - 0.1055613458 * a - 0.0638541728 * b;
|
|
802
|
+
var s = L - 0.0894841775 * a - 1.2914855480 * b;
|
|
803
|
+
l = l * l * l; m = m * m * m; s = s * s * s;
|
|
804
|
+
var r = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
|
|
805
|
+
var g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
|
|
806
|
+
var bl = -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s;
|
|
807
|
+
function toSrgb(c) {
|
|
808
|
+
c = c > 0.0031308 ? 1.055 * Math.pow(c, 1 / 2.4) - 0.055 : 12.92 * c;
|
|
809
|
+
return Math.max(0, Math.min(255, Math.round(c * 255)));
|
|
810
|
+
}
|
|
811
|
+
return [toSrgb(r), toSrgb(g), toSrgb(bl)];
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
function rgbToOklch(r, g, b) {
|
|
815
|
+
var lab = rgbToOklab(r, g, b);
|
|
816
|
+
var C = Math.sqrt(lab[1] * lab[1] + lab[2] * lab[2]);
|
|
817
|
+
var h = Math.atan2(lab[2], lab[1]) * 180 / Math.PI;
|
|
818
|
+
if (h < 0) h += 360;
|
|
819
|
+
return [lab[0], C, h];
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
function oklchToRgb(L, C, h) {
|
|
823
|
+
var rad = h * Math.PI / 180;
|
|
824
|
+
return oklabToRgb(L, C * Math.cos(rad), C * Math.sin(rad));
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
function lerpOklab(c1, c2, t) {
|
|
828
|
+
var a = rgbToOklab(c1[0], c1[1], c1[2]);
|
|
829
|
+
var b = rgbToOklab(c2[0], c2[1], c2[2]);
|
|
830
|
+
return oklabToRgb(
|
|
831
|
+
a[0] + (b[0] - a[0]) * t,
|
|
832
|
+
a[1] + (b[1] - a[1]) * t,
|
|
833
|
+
a[2] + (b[2] - a[2]) * t
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
function palette(colors, t) {
|
|
838
|
+
t = Math.max(0, Math.min(1, t)) * (colors.length - 1);
|
|
839
|
+
var i = Math.floor(t);
|
|
840
|
+
var f = t - i;
|
|
841
|
+
if (i >= colors.length - 1) return colors[colors.length - 1];
|
|
842
|
+
return lerpOklab(colors[i], colors[i + 1], f);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
function complementary(r, g, b) {
|
|
846
|
+
return [255 - r, 255 - g, 255 - b];
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
function triadic(h, s, l) {
|
|
850
|
+
return [
|
|
851
|
+
[h, s, l],
|
|
852
|
+
[(h + 120) % 360, s, l],
|
|
853
|
+
[(h + 240) % 360, s, l]
|
|
854
|
+
];
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
function analogous(h, s, l, angle) {
|
|
858
|
+
angle = angle || 30;
|
|
859
|
+
return [
|
|
860
|
+
[(h - angle + 360) % 360, s, l],
|
|
861
|
+
[h, s, l],
|
|
862
|
+
[(h + angle) % 360, s, l]
|
|
863
|
+
];
|
|
864
|
+
}
|
|
865
|
+
`,
|
|
866
|
+
exports: ["oklabToRgb", "rgbToOklab", "oklchToRgb", "rgbToOklch", "lerpOklab", "palette", "complementary", "triadic", "analogous"],
|
|
867
|
+
dependencies: ["color"],
|
|
868
|
+
description: "Perceptual color spaces (OKLab, OKLCh) and color harmony.",
|
|
869
|
+
usage: `### color-advanced \u2014 Perceptual Color & Harmony
|
|
870
|
+
|
|
871
|
+
\`\`\`js
|
|
872
|
+
var lab = rgbToOklab(255, 128, 0);
|
|
873
|
+
var rgb = oklabToRgb(lab[0], lab[1], lab[2]);
|
|
874
|
+
lerpOklab([255,0,0], [0,0,255], 0.5); // perceptually uniform blend
|
|
875
|
+
palette([[255,0,0],[0,255,0],[0,0,255]], 0.5); // palette sampling
|
|
876
|
+
triadic(200, 80, 50); // three equidistant hues
|
|
877
|
+
\`\`\`
|
|
878
|
+
`
|
|
879
|
+
};
|
|
880
|
+
var color_advanced_default = colorAdvanced;
|
|
881
|
+
|
|
882
|
+
// src/components/js/vector.ts
|
|
883
|
+
var vector = {
|
|
884
|
+
name: "vector",
|
|
885
|
+
version: "1.0.0",
|
|
886
|
+
category: "vector",
|
|
887
|
+
target: "js",
|
|
888
|
+
renderers: [],
|
|
889
|
+
code: `function vec2(x, y) { return [x, y]; }
|
|
890
|
+
function vec3(x, y, z) { return [x, y, z]; }
|
|
891
|
+
|
|
892
|
+
function add(a, b) {
|
|
893
|
+
var r = new Array(a.length);
|
|
894
|
+
for (var i = 0; i < a.length; i++) r[i] = a[i] + b[i];
|
|
895
|
+
return r;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
function sub(a, b) {
|
|
899
|
+
var r = new Array(a.length);
|
|
900
|
+
for (var i = 0; i < a.length; i++) r[i] = a[i] - b[i];
|
|
901
|
+
return r;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
function mul(a, s) {
|
|
905
|
+
var r = new Array(a.length);
|
|
906
|
+
for (var i = 0; i < a.length; i++) r[i] = a[i] * s;
|
|
907
|
+
return r;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
function div(a, s) {
|
|
911
|
+
var r = new Array(a.length);
|
|
912
|
+
for (var i = 0; i < a.length; i++) r[i] = a[i] / s;
|
|
913
|
+
return r;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
function dot(a, b) {
|
|
917
|
+
var s = 0;
|
|
918
|
+
for (var i = 0; i < a.length; i++) s += a[i] * b[i];
|
|
919
|
+
return s;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
function cross(a, b) {
|
|
923
|
+
return [
|
|
924
|
+
a[1] * b[2] - a[2] * b[1],
|
|
925
|
+
a[2] * b[0] - a[0] * b[2],
|
|
926
|
+
a[0] * b[1] - a[1] * b[0]
|
|
927
|
+
];
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
function length(a) {
|
|
931
|
+
var s = 0;
|
|
932
|
+
for (var i = 0; i < a.length; i++) s += a[i] * a[i];
|
|
933
|
+
return Math.sqrt(s);
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
function normalize(a) {
|
|
937
|
+
var len = length(a);
|
|
938
|
+
return len === 0 ? a : div(a, len);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
function distance(a, b) { return length(sub(a, b)); }
|
|
942
|
+
|
|
943
|
+
function reflect(v, n) {
|
|
944
|
+
var d = 2 * dot(v, n);
|
|
945
|
+
return sub(v, mul(n, d));
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
function rotate2D(v, angle) {
|
|
949
|
+
var c = Math.cos(angle), s = Math.sin(angle);
|
|
950
|
+
return [v[0] * c - v[1] * s, v[0] * s + v[1] * c];
|
|
951
|
+
}
|
|
952
|
+
`,
|
|
953
|
+
exports: ["vec2", "vec3", "add", "sub", "mul", "div", "dot", "cross", "normalize", "length", "distance", "reflect", "rotate2D"],
|
|
954
|
+
dependencies: [],
|
|
955
|
+
description: "Lightweight vector math using plain arrays.",
|
|
956
|
+
usage: `### vector \u2014 Vector Math
|
|
957
|
+
|
|
958
|
+
\`\`\`js
|
|
959
|
+
var a = vec2(1, 0), b = vec2(0, 1);
|
|
960
|
+
add(a, b); // \u2192 [1, 1]
|
|
961
|
+
normalize(a); // \u2192 [1, 0]
|
|
962
|
+
distance(a, b); // \u2192 1.414...
|
|
963
|
+
rotate2D(a, Math.PI / 2);
|
|
964
|
+
\`\`\`
|
|
965
|
+
`
|
|
966
|
+
};
|
|
967
|
+
var vector_default = vector;
|
|
968
|
+
|
|
969
|
+
// src/components/js/matrix.ts
|
|
970
|
+
var matrix = {
|
|
971
|
+
name: "matrix",
|
|
972
|
+
version: "1.0.0",
|
|
973
|
+
category: "vector",
|
|
974
|
+
target: "js",
|
|
975
|
+
renderers: [],
|
|
976
|
+
code: `function mat2(a, b, c, d) { return [a, b, c, d]; }
|
|
977
|
+
function mat3(m00, m01, m02, m10, m11, m12, m20, m21, m22) {
|
|
978
|
+
return [m00, m01, m02, m10, m11, m12, m20, m21, m22];
|
|
979
|
+
}
|
|
980
|
+
function mat4(m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33) {
|
|
981
|
+
return [m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33];
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
function multiply(a, b, n) {
|
|
985
|
+
var r = new Array(n * n);
|
|
986
|
+
for (var i = 0; i < n; i++)
|
|
987
|
+
for (var j = 0; j < n; j++) {
|
|
988
|
+
var s = 0;
|
|
989
|
+
for (var k = 0; k < n; k++) s += a[i * n + k] * b[k * n + j];
|
|
990
|
+
r[i * n + j] = s;
|
|
991
|
+
}
|
|
992
|
+
return r;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
function transpose(m, n) {
|
|
996
|
+
var r = new Array(n * n);
|
|
997
|
+
for (var i = 0; i < n; i++)
|
|
998
|
+
for (var j = 0; j < n; j++) r[j * n + i] = m[i * n + j];
|
|
999
|
+
return r;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
function inverse(m) {
|
|
1003
|
+
var a=m[0],b=m[1],c=m[2],d=m[3],e=m[4],f=m[5],g=m[6],h=m[7],i=m[8],j=m[9],k=m[10],l=m[11],n=m[12],o=m[13],p=m[14],q=m[15];
|
|
1004
|
+
var kpol=k*q-l*p, jpom=j*q-l*o, jpon=j*p-k*o, ipol=i*q-l*n, ipon=i*p-k*n, iomn=i*o-j*n;
|
|
1005
|
+
var det = a*(f*kpol-g*jpom+h*jpon) - b*(e*kpol-g*ipol+h*ipon) + c*(e*jpom-f*ipol+h*iomn) - d*(e*jpon-f*ipon+g*iomn);
|
|
1006
|
+
if (det === 0) return null;
|
|
1007
|
+
var id = 1/det;
|
|
1008
|
+
return [
|
|
1009
|
+
(f*kpol-g*jpom+h*jpon)*id, -(b*kpol-c*jpom+d*jpon)*id, (b*(g*q-h*p)-c*(f*q-h*o)+d*(f*p-g*o))*id, -(b*(g*l-h*k)-c*(f*l-h*j)+d*(f*k-g*j))*id,
|
|
1010
|
+
-(e*kpol-g*ipol+h*ipon)*id, (a*kpol-c*ipol+d*ipon)*id, -(a*(g*q-h*p)-c*(e*q-h*n)+d*(e*p-g*n))*id, (a*(g*l-h*k)-c*(e*l-h*i)+d*(e*k-g*i))*id,
|
|
1011
|
+
(e*jpom-f*ipol+h*iomn)*id, -(a*jpom-b*ipol+d*iomn)*id, (a*(f*q-h*o)-b*(e*q-h*n)+d*(e*o-f*n))*id, -(a*(f*l-h*j)-b*(e*l-h*i)+d*(e*j-f*i))*id,
|
|
1012
|
+
-(e*jpon-f*ipon+g*iomn)*id, (a*jpon-b*ipon+c*iomn)*id, -(a*(f*p-g*o)-b*(e*p-g*n)+c*(e*o-f*n))*id, (a*(f*k-g*j)-b*(e*k-g*i)+c*(e*j-f*i))*id
|
|
1013
|
+
];
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
function rotationMatrix(axis, angle) {
|
|
1017
|
+
var c = Math.cos(angle), s = Math.sin(angle), t = 1 - c;
|
|
1018
|
+
var x = axis[0], y = axis[1], z = axis[2];
|
|
1019
|
+
return [
|
|
1020
|
+
t*x*x+c, t*x*y-s*z, t*x*z+s*y, 0,
|
|
1021
|
+
t*x*y+s*z, t*y*y+c, t*y*z-s*x, 0,
|
|
1022
|
+
t*x*z-s*y, t*y*z+s*x, t*z*z+c, 0,
|
|
1023
|
+
0, 0, 0, 1
|
|
1024
|
+
];
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
function projectionMatrix(fov, aspect, near, far) {
|
|
1028
|
+
var f = 1 / Math.tan(fov / 2);
|
|
1029
|
+
var nf = 1 / (near - far);
|
|
1030
|
+
return [
|
|
1031
|
+
f/aspect, 0, 0, 0,
|
|
1032
|
+
0, f, 0, 0,
|
|
1033
|
+
0, 0, (far+near)*nf, -1,
|
|
1034
|
+
0, 0, 2*far*near*nf, 0
|
|
1035
|
+
];
|
|
1036
|
+
}
|
|
1037
|
+
`,
|
|
1038
|
+
exports: ["mat2", "mat3", "mat4", "multiply", "inverse", "transpose", "rotationMatrix", "projectionMatrix"],
|
|
1039
|
+
dependencies: ["vector"],
|
|
1040
|
+
description: "Matrix math for 2D/3D transforms and projections.",
|
|
1041
|
+
usage: `### matrix \u2014 Matrix Math
|
|
1042
|
+
|
|
1043
|
+
\`\`\`js
|
|
1044
|
+
var rot = rotationMatrix([0,1,0], Math.PI/4);
|
|
1045
|
+
var proj = projectionMatrix(Math.PI/3, 16/9, 0.1, 100);
|
|
1046
|
+
var result = multiply(proj, rot, 4);
|
|
1047
|
+
\`\`\`
|
|
1048
|
+
`
|
|
1049
|
+
};
|
|
1050
|
+
var matrix_default = matrix;
|
|
1051
|
+
|
|
1052
|
+
// src/components/js/grid.ts
|
|
1053
|
+
var grid = {
|
|
1054
|
+
name: "grid",
|
|
1055
|
+
version: "1.0.0",
|
|
1056
|
+
category: "grid",
|
|
1057
|
+
target: "js",
|
|
1058
|
+
renderers: [],
|
|
1059
|
+
code: `function marchingSquares(field, cols, rows, threshold) {
|
|
1060
|
+
var segments = [];
|
|
1061
|
+
function val(x, y) { return field[y * cols + x] >= threshold ? 1 : 0; }
|
|
1062
|
+
function interp(a, b, va, vb) {
|
|
1063
|
+
var dv = vb - va;
|
|
1064
|
+
return dv === 0 ? 0.5 : (threshold - va) / dv;
|
|
1065
|
+
}
|
|
1066
|
+
for (var y = 0; y < rows - 1; y++) {
|
|
1067
|
+
for (var x = 0; x < cols - 1; x++) {
|
|
1068
|
+
var v00 = field[y * cols + x], v10 = field[y * cols + x + 1];
|
|
1069
|
+
var v01 = field[(y+1) * cols + x], v11 = field[(y+1) * cols + x + 1];
|
|
1070
|
+
var code = val(x,y) | (val(x+1,y)<<1) | (val(x,y+1)<<2) | (val(x+1,y+1)<<3);
|
|
1071
|
+
if (code === 0 || code === 15) continue;
|
|
1072
|
+
var top = [x + interp(v00, v10, v00, v10), y];
|
|
1073
|
+
var bottom = [x + interp(v01, v11, v01, v11), y + 1];
|
|
1074
|
+
var left = [x, y + interp(v00, v01, v00, v01)];
|
|
1075
|
+
var right = [x + 1, y + interp(v10, v11, v10, v11)];
|
|
1076
|
+
if (code===1||code===14) segments.push([top, left]);
|
|
1077
|
+
else if (code===2||code===13) segments.push([top, right]);
|
|
1078
|
+
else if (code===3||code===12) segments.push([left, right]);
|
|
1079
|
+
else if (code===4||code===11) segments.push([left, bottom]);
|
|
1080
|
+
else if (code===6||code===9) segments.push([top, bottom]);
|
|
1081
|
+
else if (code===7||code===8) segments.push([right, bottom]);
|
|
1082
|
+
else if (code===5) { segments.push([top, left]); segments.push([right, bottom]); }
|
|
1083
|
+
else if (code===10) { segments.push([top, right]); segments.push([left, bottom]); }
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
return segments;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
function floodFill(grid, cols, rows, startX, startY, fillVal) {
|
|
1090
|
+
var target = grid[startY * cols + startX];
|
|
1091
|
+
if (target === fillVal) return grid;
|
|
1092
|
+
var result = grid.slice();
|
|
1093
|
+
var stack = [[startX, startY]];
|
|
1094
|
+
while (stack.length > 0) {
|
|
1095
|
+
var p = stack.pop();
|
|
1096
|
+
var px = p[0], py = p[1];
|
|
1097
|
+
if (px < 0 || px >= cols || py < 0 || py >= rows) continue;
|
|
1098
|
+
if (result[py * cols + px] !== target) continue;
|
|
1099
|
+
result[py * cols + px] = fillVal;
|
|
1100
|
+
stack.push([px+1,py],[px-1,py],[px,py+1],[px,py-1]);
|
|
1101
|
+
}
|
|
1102
|
+
return result;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
function bresenhamLine(x0, y0, x1, y1) {
|
|
1106
|
+
var points = [];
|
|
1107
|
+
var dx = Math.abs(x1 - x0), dy = Math.abs(y1 - y0);
|
|
1108
|
+
var sx = x0 < x1 ? 1 : -1, sy = y0 < y1 ? 1 : -1;
|
|
1109
|
+
var err = dx - dy;
|
|
1110
|
+
while (true) {
|
|
1111
|
+
points.push([x0, y0]);
|
|
1112
|
+
if (x0 === x1 && y0 === y1) break;
|
|
1113
|
+
var e2 = 2 * err;
|
|
1114
|
+
if (e2 > -dy) { err -= dy; x0 += sx; }
|
|
1115
|
+
if (e2 < dx) { err += dx; y0 += sy; }
|
|
1116
|
+
}
|
|
1117
|
+
return points;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
function cellularAutomaton(grid, cols, rows, ruleFn) {
|
|
1121
|
+
var next = new Array(cols * rows);
|
|
1122
|
+
for (var y = 0; y < rows; y++) {
|
|
1123
|
+
for (var x = 0; x < cols; x++) {
|
|
1124
|
+
var neighbors = 0;
|
|
1125
|
+
for (var dy = -1; dy <= 1; dy++)
|
|
1126
|
+
for (var dx = -1; dx <= 1; dx++) {
|
|
1127
|
+
if (dx === 0 && dy === 0) continue;
|
|
1128
|
+
var nx = (x + dx + cols) % cols, ny = (y + dy + rows) % rows;
|
|
1129
|
+
neighbors += grid[ny * cols + nx] ? 1 : 0;
|
|
1130
|
+
}
|
|
1131
|
+
next[y * cols + x] = ruleFn(grid[y * cols + x], neighbors);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
return next;
|
|
1135
|
+
}
|
|
1136
|
+
`,
|
|
1137
|
+
exports: ["marchingSquares", "floodFill", "bresenhamLine", "cellularAutomaton"],
|
|
1138
|
+
dependencies: [],
|
|
1139
|
+
description: "Grid/heightmap algorithms (marching squares, flood fill, Bresenham).",
|
|
1140
|
+
usage: `### grid \u2014 Grid Algorithms
|
|
1141
|
+
|
|
1142
|
+
\`\`\`js
|
|
1143
|
+
var segs = marchingSquares(heightmap, 100, 100, 0.5);
|
|
1144
|
+
var filled = floodFill(grid, w, h, 0, 0, 1);
|
|
1145
|
+
var line = bresenhamLine(0, 0, 10, 7);
|
|
1146
|
+
var next = cellularAutomaton(grid, w, h, function(cell, n) {
|
|
1147
|
+
return n === 3 || (cell && n === 2) ? 1 : 0; // Game of Life
|
|
1148
|
+
});
|
|
1149
|
+
\`\`\`
|
|
1150
|
+
`
|
|
1151
|
+
};
|
|
1152
|
+
var grid_default = grid;
|
|
1153
|
+
|
|
1154
|
+
// src/components/js/grid-advanced.ts
|
|
1155
|
+
var gridAdvanced = {
|
|
1156
|
+
name: "grid-advanced",
|
|
1157
|
+
version: "1.0.0",
|
|
1158
|
+
category: "grid",
|
|
1159
|
+
target: "js",
|
|
1160
|
+
renderers: [],
|
|
1161
|
+
code: `function marchingCubes(field, nx, ny, nz, threshold) {
|
|
1162
|
+
var vertices = [];
|
|
1163
|
+
function val(x, y, z) { return field[z * ny * nx + y * nx + x]; }
|
|
1164
|
+
function interp3(p1, p2, v1, v2) {
|
|
1165
|
+
if (Math.abs(v1 - v2) < 1e-6) return p1;
|
|
1166
|
+
var t = (threshold - v1) / (v2 - v1);
|
|
1167
|
+
return [p1[0]+(p2[0]-p1[0])*t, p1[1]+(p2[1]-p1[1])*t, p1[2]+(p2[2]-p1[2])*t];
|
|
1168
|
+
}
|
|
1169
|
+
for (var z = 0; z < nz-1; z++)
|
|
1170
|
+
for (var y = 0; y < ny-1; y++)
|
|
1171
|
+
for (var x = 0; x < nx-1; x++) {
|
|
1172
|
+
var v = [val(x,y,z),val(x+1,y,z),val(x+1,y+1,z),val(x,y+1,z),
|
|
1173
|
+
val(x,y,z+1),val(x+1,y,z+1),val(x+1,y+1,z+1),val(x,y+1,z+1)];
|
|
1174
|
+
var code = 0;
|
|
1175
|
+
for (var i = 0; i < 8; i++) if (v[i] >= threshold) code |= (1 << i);
|
|
1176
|
+
if (code === 0 || code === 255) continue;
|
|
1177
|
+
var corners = [[x,y,z],[x+1,y,z],[x+1,y+1,z],[x,y+1,z],[x,y,z+1],[x+1,y,z+1],[x+1,y+1,z+1],[x,y+1,z+1]];
|
|
1178
|
+
var edges = [[0,1],[1,2],[2,3],[3,0],[4,5],[5,6],[6,7],[7,4],[0,4],[1,5],[2,6],[3,7]];
|
|
1179
|
+
for (var i = 0; i < edges.length; i++) {
|
|
1180
|
+
var e = edges[i];
|
|
1181
|
+
if ((code & (1<<e[0])) !== (code & (1<<e[1])))
|
|
1182
|
+
vertices.push(interp3(corners[e[0]], corners[e[1]], v[e[0]], v[e[1]]));
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
return vertices;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
function diamondSquare(size, rng, roughness) {
|
|
1189
|
+
var n = size;
|
|
1190
|
+
var grid = new Float64Array(n * n);
|
|
1191
|
+
grid[0] = rng(); grid[n-1] = rng(); grid[(n-1)*n] = rng(); grid[(n-1)*n+n-1] = rng();
|
|
1192
|
+
var step = n - 1, scale = roughness;
|
|
1193
|
+
while (step > 1) {
|
|
1194
|
+
var half = step / 2;
|
|
1195
|
+
for (var y = 0; y < n-1; y += step)
|
|
1196
|
+
for (var x = 0; x < n-1; x += step) {
|
|
1197
|
+
var avg = (grid[y*n+x]+grid[y*n+x+step]+grid[(y+step)*n+x]+grid[(y+step)*n+x+step])/4;
|
|
1198
|
+
grid[(y+half)*n+x+half] = avg + (rng()-0.5)*scale;
|
|
1199
|
+
}
|
|
1200
|
+
for (var y = 0; y < n; y += half)
|
|
1201
|
+
for (var x = (y % step === 0 ? half : 0); x < n; x += step) {
|
|
1202
|
+
var sum = 0, cnt = 0;
|
|
1203
|
+
if (y-half>=0){sum+=grid[(y-half)*n+x];cnt++;}
|
|
1204
|
+
if (y+half<n){sum+=grid[(y+half)*n+x];cnt++;}
|
|
1205
|
+
if (x-half>=0){sum+=grid[y*n+x-half];cnt++;}
|
|
1206
|
+
if (x+half<n){sum+=grid[y*n+x+half];cnt++;}
|
|
1207
|
+
grid[y*n+x] = sum/cnt + (rng()-0.5)*scale;
|
|
1208
|
+
}
|
|
1209
|
+
step = half; scale *= 0.5;
|
|
1210
|
+
}
|
|
1211
|
+
return grid;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
function waveCollapse(tileCount, cols, rows, adjacency, rng) {
|
|
1215
|
+
var grid = new Array(cols * rows);
|
|
1216
|
+
for (var i = 0; i < grid.length; i++) {
|
|
1217
|
+
grid[i] = new Array(tileCount);
|
|
1218
|
+
for (var t = 0; t < tileCount; t++) grid[i][t] = true;
|
|
1219
|
+
}
|
|
1220
|
+
function entropy(cell) {
|
|
1221
|
+
var c = 0;
|
|
1222
|
+
for (var t = 0; t < tileCount; t++) if (cell[t]) c++;
|
|
1223
|
+
return c;
|
|
1224
|
+
}
|
|
1225
|
+
function collapse() {
|
|
1226
|
+
var minE = tileCount + 1, idx = -1;
|
|
1227
|
+
for (var i = 0; i < grid.length; i++) {
|
|
1228
|
+
var e = entropy(grid[i]);
|
|
1229
|
+
if (e > 1 && e < minE) { minE = e; idx = i; }
|
|
1230
|
+
}
|
|
1231
|
+
if (idx === -1) return false;
|
|
1232
|
+
var options = [];
|
|
1233
|
+
for (var t = 0; t < tileCount; t++) if (grid[idx][t]) options.push(t);
|
|
1234
|
+
var pick = options[Math.floor(rng() * options.length)];
|
|
1235
|
+
for (var t = 0; t < tileCount; t++) grid[idx][t] = (t === pick);
|
|
1236
|
+
propagate(idx);
|
|
1237
|
+
return true;
|
|
1238
|
+
}
|
|
1239
|
+
function propagate(idx) {
|
|
1240
|
+
var stack = [idx];
|
|
1241
|
+
while (stack.length > 0) {
|
|
1242
|
+
var ci = stack.pop();
|
|
1243
|
+
var cx = ci % cols, cy = Math.floor(ci / cols);
|
|
1244
|
+
var dirs = [[1,0],[-1,0],[0,1],[0,-1]];
|
|
1245
|
+
for (var d = 0; d < 4; d++) {
|
|
1246
|
+
var nx = cx+dirs[d][0], ny = cy+dirs[d][1];
|
|
1247
|
+
if (nx<0||nx>=cols||ny<0||ny>=rows) continue;
|
|
1248
|
+
var ni = ny*cols+nx;
|
|
1249
|
+
var changed = false;
|
|
1250
|
+
for (var t = 0; t < tileCount; t++) {
|
|
1251
|
+
if (!grid[ni][t]) continue;
|
|
1252
|
+
var valid = false;
|
|
1253
|
+
for (var s = 0; s < tileCount; s++) {
|
|
1254
|
+
if (grid[ci][s] && adjacency[s] && adjacency[s][d] && adjacency[s][d].indexOf(t) >= 0) { valid = true; break; }
|
|
1255
|
+
}
|
|
1256
|
+
if (!valid) { grid[ni][t] = false; changed = true; }
|
|
1257
|
+
}
|
|
1258
|
+
if (changed) stack.push(ni);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
while (collapse()) {}
|
|
1263
|
+
var result = new Array(cols * rows);
|
|
1264
|
+
for (var i = 0; i < grid.length; i++) {
|
|
1265
|
+
for (var t = 0; t < tileCount; t++) if (grid[i][t]) { result[i] = t; break; }
|
|
1266
|
+
}
|
|
1267
|
+
return result;
|
|
1268
|
+
}
|
|
1269
|
+
`,
|
|
1270
|
+
exports: ["marchingCubes", "diamondSquare", "waveCollapse"],
|
|
1271
|
+
dependencies: ["prng", "grid"],
|
|
1272
|
+
description: "Advanced grid generation (marching cubes, diamond-square, WFC).",
|
|
1273
|
+
usage: `### grid-advanced \u2014 Advanced Grid Generation
|
|
1274
|
+
|
|
1275
|
+
\`\`\`js
|
|
1276
|
+
var terrain = diamondSquare(129, rng, 1.0);
|
|
1277
|
+
var verts = marchingCubes(field, 32, 32, 32, 0.5);
|
|
1278
|
+
var tiles = waveCollapse(4, 20, 20, adjacencyRules, rng);
|
|
1279
|
+
\`\`\`
|
|
1280
|
+
`
|
|
1281
|
+
};
|
|
1282
|
+
var grid_advanced_default = gridAdvanced;
|
|
1283
|
+
|
|
1284
|
+
// src/components/js/particle.ts
|
|
1285
|
+
var particle = {
|
|
1286
|
+
name: "particle",
|
|
1287
|
+
version: "1.0.0",
|
|
1288
|
+
category: "particle",
|
|
1289
|
+
target: "js",
|
|
1290
|
+
renderers: [],
|
|
1291
|
+
code: `function createParticleSystem(maxParticles) {
|
|
1292
|
+
return {
|
|
1293
|
+
particles: [],
|
|
1294
|
+
maxParticles: maxParticles || 1000,
|
|
1295
|
+
time: 0
|
|
1296
|
+
};
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
function emitParticle(system, x, y, vx, vy, life) {
|
|
1300
|
+
if (system.particles.length >= system.maxParticles) return null;
|
|
1301
|
+
var p = { x: x, y: y, vx: vx || 0, vy: vy || 0, ax: 0, ay: 0, life: life || 1, maxLife: life || 1, age: 0 };
|
|
1302
|
+
system.particles.push(p);
|
|
1303
|
+
return p;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
function updateParticles(system, dt) {
|
|
1307
|
+
dt = dt || 1/60;
|
|
1308
|
+
system.time += dt;
|
|
1309
|
+
for (var i = system.particles.length - 1; i >= 0; i--) {
|
|
1310
|
+
var p = system.particles[i];
|
|
1311
|
+
p.vx += p.ax * dt; p.vy += p.ay * dt;
|
|
1312
|
+
p.x += p.vx * dt; p.y += p.vy * dt;
|
|
1313
|
+
p.ax = 0; p.ay = 0;
|
|
1314
|
+
p.age += dt; p.life -= dt;
|
|
1315
|
+
if (p.life <= 0) system.particles.splice(i, 1);
|
|
1316
|
+
}
|
|
1317
|
+
return system;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
function applyForce(particle, fx, fy) {
|
|
1321
|
+
particle.ax += fx;
|
|
1322
|
+
particle.ay += fy;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
function particleAge(particle) {
|
|
1326
|
+
return particle.age / particle.maxLife;
|
|
1327
|
+
}
|
|
1328
|
+
`,
|
|
1329
|
+
exports: ["createParticleSystem", "updateParticles", "emitParticle", "applyForce", "particleAge"],
|
|
1330
|
+
dependencies: ["vector"],
|
|
1331
|
+
description: "Renderer-agnostic particle system state management.",
|
|
1332
|
+
usage: `### particle \u2014 Particle System
|
|
1333
|
+
|
|
1334
|
+
\`\`\`js
|
|
1335
|
+
var sys = createParticleSystem(500);
|
|
1336
|
+
emitParticle(sys, x, y, vx, vy, 2.0);
|
|
1337
|
+
updateParticles(sys, dt);
|
|
1338
|
+
sys.particles.forEach(function(p) {
|
|
1339
|
+
applyForce(p, 0, 9.8); // gravity
|
|
1340
|
+
var t = particleAge(p); // 0\u21921 normalized age
|
|
1341
|
+
});
|
|
1342
|
+
\`\`\`
|
|
1343
|
+
`
|
|
1344
|
+
};
|
|
1345
|
+
var particle_default = particle;
|
|
1346
|
+
|
|
1347
|
+
// src/components/js/particle-forces.ts
|
|
1348
|
+
var particleForces = {
|
|
1349
|
+
name: "particle-forces",
|
|
1350
|
+
version: "1.0.0",
|
|
1351
|
+
category: "particle",
|
|
1352
|
+
target: "js",
|
|
1353
|
+
renderers: [],
|
|
1354
|
+
code: `function gravityForce(p, gx, gy) {
|
|
1355
|
+
p.ax += gx || 0;
|
|
1356
|
+
p.ay += gy || 9.8;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
function attractorForce(p, ax, ay, strength) {
|
|
1360
|
+
var dx = ax - p.x, dy = ay - p.y;
|
|
1361
|
+
var d = Math.sqrt(dx * dx + dy * dy) + 0.01;
|
|
1362
|
+
var f = strength / (d * d);
|
|
1363
|
+
p.ax += dx / d * f;
|
|
1364
|
+
p.ay += dy / d * f;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
function vortexForce(p, cx, cy, strength) {
|
|
1368
|
+
var dx = p.x - cx, dy = p.y - cy;
|
|
1369
|
+
var d = Math.sqrt(dx * dx + dy * dy) + 0.01;
|
|
1370
|
+
var f = strength / d;
|
|
1371
|
+
p.ax += -dy / d * f;
|
|
1372
|
+
p.ay += dx / d * f;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
function dragForce(p, coefficient) {
|
|
1376
|
+
coefficient = coefficient || 0.01;
|
|
1377
|
+
var speed = Math.sqrt(p.vx * p.vx + p.vy * p.vy);
|
|
1378
|
+
if (speed > 0) {
|
|
1379
|
+
var drag = coefficient * speed;
|
|
1380
|
+
p.ax -= p.vx / speed * drag;
|
|
1381
|
+
p.ay -= p.vy / speed * drag;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
function turbulenceForce(p, noiseFn, scale, strength) {
|
|
1386
|
+
var angle = noiseFn(p.x * scale, p.y * scale) * Math.PI * 4;
|
|
1387
|
+
p.ax += Math.cos(angle) * strength;
|
|
1388
|
+
p.ay += Math.sin(angle) * strength;
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
function boundaryForce(p, minX, minY, maxX, maxY, strength) {
|
|
1392
|
+
strength = strength || 10;
|
|
1393
|
+
var margin = 20;
|
|
1394
|
+
if (p.x < minX + margin) p.ax += strength * (1 - (p.x - minX) / margin);
|
|
1395
|
+
if (p.x > maxX - margin) p.ax -= strength * (1 - (maxX - p.x) / margin);
|
|
1396
|
+
if (p.y < minY + margin) p.ay += strength * (1 - (p.y - minY) / margin);
|
|
1397
|
+
if (p.y > maxY - margin) p.ay -= strength * (1 - (maxY - p.y) / margin);
|
|
1398
|
+
}
|
|
1399
|
+
`,
|
|
1400
|
+
exports: ["gravityForce", "attractorForce", "vortexForce", "dragForce", "turbulenceForce", "boundaryForce"],
|
|
1401
|
+
dependencies: ["particle", "vector"],
|
|
1402
|
+
description: "Common particle force functions (gravity, attractor, vortex, drag).",
|
|
1403
|
+
usage: `### particle-forces \u2014 Force Functions
|
|
1404
|
+
|
|
1405
|
+
\`\`\`js
|
|
1406
|
+
sys.particles.forEach(function(p) {
|
|
1407
|
+
gravityForce(p, 0, 9.8);
|
|
1408
|
+
attractorForce(p, cx, cy, 100);
|
|
1409
|
+
dragForce(p, 0.02);
|
|
1410
|
+
boundaryForce(p, 0, 0, width, height);
|
|
1411
|
+
});
|
|
1412
|
+
\`\`\`
|
|
1413
|
+
`
|
|
1414
|
+
};
|
|
1415
|
+
var particle_forces_default = particleForces;
|
|
1416
|
+
|
|
1417
|
+
// src/components/js/shape.ts
|
|
1418
|
+
var shape = {
|
|
1419
|
+
name: "shape",
|
|
1420
|
+
version: "1.0.0",
|
|
1421
|
+
category: "geometry",
|
|
1422
|
+
target: "js",
|
|
1423
|
+
renderers: [],
|
|
1424
|
+
code: `function regularPolygon(cx, cy, radius, sides) {
|
|
1425
|
+
var pts = [];
|
|
1426
|
+
for (var i = 0; i < sides; i++) {
|
|
1427
|
+
var a = (i / sides) * Math.PI * 2 - Math.PI / 2;
|
|
1428
|
+
pts.push([cx + Math.cos(a) * radius, cy + Math.sin(a) * radius]);
|
|
1429
|
+
}
|
|
1430
|
+
return pts;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
function star(cx, cy, outerR, innerR, points) {
|
|
1434
|
+
var pts = [];
|
|
1435
|
+
for (var i = 0; i < points * 2; i++) {
|
|
1436
|
+
var a = (i / (points * 2)) * Math.PI * 2 - Math.PI / 2;
|
|
1437
|
+
var r = i % 2 === 0 ? outerR : innerR;
|
|
1438
|
+
pts.push([cx + Math.cos(a) * r, cy + Math.sin(a) * r]);
|
|
1439
|
+
}
|
|
1440
|
+
return pts;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
function spiral(cx, cy, startR, endR, turns, segments) {
|
|
1444
|
+
var pts = [];
|
|
1445
|
+
for (var i = 0; i <= segments; i++) {
|
|
1446
|
+
var t = i / segments;
|
|
1447
|
+
var angle = t * turns * Math.PI * 2;
|
|
1448
|
+
var r = startR + (endR - startR) * t;
|
|
1449
|
+
pts.push([cx + Math.cos(angle) * r, cy + Math.sin(angle) * r]);
|
|
1450
|
+
}
|
|
1451
|
+
return pts;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
function lissajous(cx, cy, a, b, kx, ky, delta, segments) {
|
|
1455
|
+
var pts = [];
|
|
1456
|
+
for (var i = 0; i <= segments; i++) {
|
|
1457
|
+
var t = (i / segments) * Math.PI * 2;
|
|
1458
|
+
pts.push([cx + a * Math.sin(kx * t + delta), cy + b * Math.sin(ky * t)]);
|
|
1459
|
+
}
|
|
1460
|
+
return pts;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
function superellipse(cx, cy, rx, ry, n, segments) {
|
|
1464
|
+
var pts = [];
|
|
1465
|
+
for (var i = 0; i <= segments; i++) {
|
|
1466
|
+
var a = (i / segments) * Math.PI * 2;
|
|
1467
|
+
var ca = Math.cos(a), sa = Math.sin(a);
|
|
1468
|
+
var x = Math.pow(Math.abs(ca), 2/n) * rx * (ca >= 0 ? 1 : -1);
|
|
1469
|
+
var y = Math.pow(Math.abs(sa), 2/n) * ry * (sa >= 0 ? 1 : -1);
|
|
1470
|
+
pts.push([cx + x, cy + y]);
|
|
1471
|
+
}
|
|
1472
|
+
return pts;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
function heart(cx, cy, size, segments) {
|
|
1476
|
+
var pts = [];
|
|
1477
|
+
for (var i = 0; i <= segments; i++) {
|
|
1478
|
+
var t = (i / segments) * Math.PI * 2;
|
|
1479
|
+
var x = 16 * Math.pow(Math.sin(t), 3);
|
|
1480
|
+
var y = -(13 * Math.cos(t) - 5 * Math.cos(2*t) - 2 * Math.cos(3*t) - Math.cos(4*t));
|
|
1481
|
+
pts.push([cx + x * size / 16, cy + y * size / 16]);
|
|
1482
|
+
}
|
|
1483
|
+
return pts;
|
|
1484
|
+
}
|
|
1485
|
+
`,
|
|
1486
|
+
exports: ["regularPolygon", "star", "spiral", "lissajous", "superellipse", "heart"],
|
|
1487
|
+
dependencies: ["math"],
|
|
1488
|
+
description: "Parametric shape generators returning point arrays.",
|
|
1489
|
+
usage: `### shape \u2014 Parametric Shapes
|
|
1490
|
+
|
|
1491
|
+
\`\`\`js
|
|
1492
|
+
regularPolygon(cx, cy, 50, 6); // hexagon
|
|
1493
|
+
star(cx, cy, 50, 25, 5); // 5-point star
|
|
1494
|
+
spiral(cx, cy, 10, 100, 5, 200);
|
|
1495
|
+
heart(cx, cy, 40, 100);
|
|
1496
|
+
\`\`\`
|
|
1497
|
+
`
|
|
1498
|
+
};
|
|
1499
|
+
var shape_default = shape;
|
|
1500
|
+
|
|
1501
|
+
// src/components/js/shape-advanced.ts
|
|
1502
|
+
var shapeAdvanced = {
|
|
1503
|
+
name: "shape-advanced",
|
|
1504
|
+
version: "1.0.0",
|
|
1505
|
+
category: "geometry",
|
|
1506
|
+
target: "js",
|
|
1507
|
+
renderers: [],
|
|
1508
|
+
code: `function chaikinSmooth(points, iterations) {
|
|
1509
|
+
iterations = iterations || 3;
|
|
1510
|
+
var pts = points;
|
|
1511
|
+
for (var iter = 0; iter < iterations; iter++) {
|
|
1512
|
+
var next = [];
|
|
1513
|
+
for (var i = 0; i < pts.length - 1; i++) {
|
|
1514
|
+
var a = pts[i], b = pts[i+1];
|
|
1515
|
+
next.push([a[0]*0.75 + b[0]*0.25, a[1]*0.75 + b[1]*0.25]);
|
|
1516
|
+
next.push([a[0]*0.25 + b[0]*0.75, a[1]*0.25 + b[1]*0.75]);
|
|
1517
|
+
}
|
|
1518
|
+
pts = next;
|
|
1519
|
+
}
|
|
1520
|
+
return pts;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
function subdivideCurve(points, iterations) {
|
|
1524
|
+
iterations = iterations || 1;
|
|
1525
|
+
var pts = points;
|
|
1526
|
+
for (var iter = 0; iter < iterations; iter++) {
|
|
1527
|
+
var next = [pts[0]];
|
|
1528
|
+
for (var i = 0; i < pts.length - 1; i++) {
|
|
1529
|
+
var mid = [(pts[i][0]+pts[i+1][0])/2, (pts[i][1]+pts[i+1][1])/2];
|
|
1530
|
+
next.push(mid);
|
|
1531
|
+
next.push(pts[i+1]);
|
|
1532
|
+
}
|
|
1533
|
+
pts = next;
|
|
1534
|
+
}
|
|
1535
|
+
return pts;
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
function offsetPath(points, dist) {
|
|
1539
|
+
var result = [];
|
|
1540
|
+
for (var i = 0; i < points.length; i++) {
|
|
1541
|
+
var prev = points[(i-1+points.length)%points.length];
|
|
1542
|
+
var curr = points[i];
|
|
1543
|
+
var next = points[(i+1)%points.length];
|
|
1544
|
+
var dx1 = curr[0]-prev[0], dy1 = curr[1]-prev[1];
|
|
1545
|
+
var dx2 = next[0]-curr[0], dy2 = next[1]-curr[1];
|
|
1546
|
+
var len1 = Math.sqrt(dx1*dx1+dy1*dy1) || 1;
|
|
1547
|
+
var len2 = Math.sqrt(dx2*dx2+dy2*dy2) || 1;
|
|
1548
|
+
var nx = (-(dy1/len1 + dy2/len2))/2, ny = ((dx1/len1 + dx2/len2))/2;
|
|
1549
|
+
var nl = Math.sqrt(nx*nx+ny*ny) || 1;
|
|
1550
|
+
result.push([curr[0]+nx/nl*dist, curr[1]+ny/nl*dist]);
|
|
1551
|
+
}
|
|
1552
|
+
return result;
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
function convexHull(points) {
|
|
1556
|
+
var pts = points.slice().sort(function(a,b) { return a[0]-b[0] || a[1]-b[1]; });
|
|
1557
|
+
function cross(O,A,B) { return (A[0]-O[0])*(B[1]-O[1])-(A[1]-O[1])*(B[0]-O[0]); }
|
|
1558
|
+
var lower = [];
|
|
1559
|
+
for (var i = 0; i < pts.length; i++) {
|
|
1560
|
+
while (lower.length >= 2 && cross(lower[lower.length-2], lower[lower.length-1], pts[i]) <= 0) lower.pop();
|
|
1561
|
+
lower.push(pts[i]);
|
|
1562
|
+
}
|
|
1563
|
+
var upper = [];
|
|
1564
|
+
for (var i = pts.length - 1; i >= 0; i--) {
|
|
1565
|
+
while (upper.length >= 2 && cross(upper[upper.length-2], upper[upper.length-1], pts[i]) <= 0) upper.pop();
|
|
1566
|
+
upper.push(pts[i]);
|
|
1567
|
+
}
|
|
1568
|
+
return lower.slice(0, -1).concat(upper.slice(0, -1));
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
function delaunay(points) {
|
|
1572
|
+
var n = points.length;
|
|
1573
|
+
if (n < 3) return [];
|
|
1574
|
+
var ids = new Array(n);
|
|
1575
|
+
for (var i = 0; i < n; i++) ids[i] = i;
|
|
1576
|
+
ids.sort(function(a,b) { return points[a][0]-points[b][0] || points[a][1]-points[b][1]; });
|
|
1577
|
+
var triangles = [];
|
|
1578
|
+
function circumscribed(ax,ay,bx,by,cx,cy,px,py) {
|
|
1579
|
+
var dx=ax-px,dy=ay-py,ex=bx-px,ey=by-py,fx=cx-px,fy=cy-py;
|
|
1580
|
+
var ap=dx*dx+dy*dy,bp=ex*ex+ey*ey,cp=fx*fx+fy*fy;
|
|
1581
|
+
return dx*(ey*cp-bp*fy)-dy*(ex*cp-bp*fx)+ap*(ex*fy-ey*fx) > 0;
|
|
1582
|
+
}
|
|
1583
|
+
var st = [[-1e6,-1e6],[1e6,-1e6],[0,1e6]];
|
|
1584
|
+
triangles.push([n,n+1,n+2]);
|
|
1585
|
+
var all = points.concat(st);
|
|
1586
|
+
for (var i = 0; i < n; i++) {
|
|
1587
|
+
var pi = ids[i], px = all[pi][0], py = all[pi][1];
|
|
1588
|
+
var edges = [], bad = [];
|
|
1589
|
+
for (var j = 0; j < triangles.length; j++) {
|
|
1590
|
+
var t = triangles[j];
|
|
1591
|
+
if (circumscribed(all[t[0]][0],all[t[0]][1],all[t[1]][0],all[t[1]][1],all[t[2]][0],all[t[2]][1],px,py)) {
|
|
1592
|
+
bad.push(j);
|
|
1593
|
+
edges.push([t[0],t[1]],[t[1],t[2]],[t[2],t[0]]);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
for (var j = bad.length-1; j >= 0; j--) triangles.splice(bad[j],1);
|
|
1597
|
+
var unique = [];
|
|
1598
|
+
for (var j = 0; j < edges.length; j++) {
|
|
1599
|
+
var dup = false;
|
|
1600
|
+
for (var k = 0; k < edges.length; k++) {
|
|
1601
|
+
if (j !== k && edges[j][0]===edges[k][1] && edges[j][1]===edges[k][0]) { dup = true; break; }
|
|
1602
|
+
}
|
|
1603
|
+
if (!dup) unique.push(edges[j]);
|
|
1604
|
+
}
|
|
1605
|
+
for (var j = 0; j < unique.length; j++) triangles.push([unique[j][0], unique[j][1], pi]);
|
|
1606
|
+
}
|
|
1607
|
+
return triangles.filter(function(t) { return t[0] < n && t[1] < n && t[2] < n; });
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
function voronoi(points, width, height, resolution) {
|
|
1611
|
+
resolution = resolution || 1;
|
|
1612
|
+
var cols = Math.ceil(width/resolution), rows = Math.ceil(height/resolution);
|
|
1613
|
+
var cells = new Int32Array(cols * rows);
|
|
1614
|
+
for (var y = 0; y < rows; y++)
|
|
1615
|
+
for (var x = 0; x < cols; x++) {
|
|
1616
|
+
var px = x * resolution, py = y * resolution;
|
|
1617
|
+
var minD = Infinity, minI = 0;
|
|
1618
|
+
for (var i = 0; i < points.length; i++) {
|
|
1619
|
+
var dx = px - points[i][0], dy = py - points[i][1];
|
|
1620
|
+
var d = dx*dx + dy*dy;
|
|
1621
|
+
if (d < minD) { minD = d; minI = i; }
|
|
1622
|
+
}
|
|
1623
|
+
cells[y * cols + x] = minI;
|
|
1624
|
+
}
|
|
1625
|
+
return { cells: cells, cols: cols, rows: rows };
|
|
1626
|
+
}
|
|
1627
|
+
`,
|
|
1628
|
+
exports: ["chaikinSmooth", "subdivideCurve", "offsetPath", "convexHull", "delaunay", "voronoi"],
|
|
1629
|
+
dependencies: ["vector", "shape"],
|
|
1630
|
+
description: "Computational geometry (Chaikin, convex hull, Delaunay, Voronoi).",
|
|
1631
|
+
usage: `### shape-advanced \u2014 Computational Geometry
|
|
1632
|
+
|
|
1633
|
+
\`\`\`js
|
|
1634
|
+
var smooth = chaikinSmooth(points, 3);
|
|
1635
|
+
var hull = convexHull(points);
|
|
1636
|
+
var tris = delaunay(points);
|
|
1637
|
+
var v = voronoi(points, 800, 600);
|
|
1638
|
+
\`\`\`
|
|
1639
|
+
`
|
|
1640
|
+
};
|
|
1641
|
+
var shape_advanced_default = shapeAdvanced;
|
|
1642
|
+
|
|
1643
|
+
// src/components/js/distribution.ts
|
|
1644
|
+
var distribution = {
|
|
1645
|
+
name: "distribution",
|
|
1646
|
+
version: "1.0.0",
|
|
1647
|
+
category: "distribution",
|
|
1648
|
+
target: "js",
|
|
1649
|
+
renderers: [],
|
|
1650
|
+
code: `function poissonDisk(rng, width, height, minDist, maxAttempts) {
|
|
1651
|
+
maxAttempts = maxAttempts || 30;
|
|
1652
|
+
var cellSize = minDist / Math.SQRT2;
|
|
1653
|
+
var cols = Math.ceil(width / cellSize), rows = Math.ceil(height / cellSize);
|
|
1654
|
+
var grid = new Array(cols * rows).fill(-1);
|
|
1655
|
+
var points = [], active = [];
|
|
1656
|
+
function addPoint(x, y) {
|
|
1657
|
+
var i = points.length;
|
|
1658
|
+
points.push([x, y]);
|
|
1659
|
+
active.push(i);
|
|
1660
|
+
var gx = Math.floor(x / cellSize), gy = Math.floor(y / cellSize);
|
|
1661
|
+
grid[gy * cols + gx] = i;
|
|
1662
|
+
}
|
|
1663
|
+
addPoint(rng() * width, rng() * height);
|
|
1664
|
+
while (active.length > 0) {
|
|
1665
|
+
var ri = Math.floor(rng() * active.length);
|
|
1666
|
+
var pi = active[ri], p = points[pi];
|
|
1667
|
+
var found = false;
|
|
1668
|
+
for (var attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1669
|
+
var angle = rng() * Math.PI * 2;
|
|
1670
|
+
var dist = minDist + rng() * minDist;
|
|
1671
|
+
var nx = p[0] + Math.cos(angle) * dist, ny = p[1] + Math.sin(angle) * dist;
|
|
1672
|
+
if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;
|
|
1673
|
+
var gx = Math.floor(nx / cellSize), gy = Math.floor(ny / cellSize);
|
|
1674
|
+
var ok = true;
|
|
1675
|
+
for (var dy = -2; dy <= 2 && ok; dy++)
|
|
1676
|
+
for (var dx = -2; dx <= 2 && ok; dx++) {
|
|
1677
|
+
var cx = gx + dx, cy = gy + dy;
|
|
1678
|
+
if (cx < 0 || cx >= cols || cy < 0 || cy >= rows) continue;
|
|
1679
|
+
var ci = grid[cy * cols + cx];
|
|
1680
|
+
if (ci >= 0) {
|
|
1681
|
+
var cp = points[ci];
|
|
1682
|
+
var d2 = (nx-cp[0])*(nx-cp[0]) + (ny-cp[1])*(ny-cp[1]);
|
|
1683
|
+
if (d2 < minDist * minDist) ok = false;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
if (ok) { addPoint(nx, ny); found = true; break; }
|
|
1687
|
+
}
|
|
1688
|
+
if (!found) active.splice(ri, 1);
|
|
1689
|
+
}
|
|
1690
|
+
return points;
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
function jitteredGrid(rng, width, height, cellSize, jitter) {
|
|
1694
|
+
jitter = jitter || 0.5;
|
|
1695
|
+
var pts = [];
|
|
1696
|
+
for (var y = cellSize/2; y < height; y += cellSize)
|
|
1697
|
+
for (var x = cellSize/2; x < width; x += cellSize)
|
|
1698
|
+
pts.push([x + (rng()-0.5)*cellSize*jitter, y + (rng()-0.5)*cellSize*jitter]);
|
|
1699
|
+
return pts;
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
function haltonSequence(n, base1, base2) {
|
|
1703
|
+
base1 = base1 || 2; base2 = base2 || 3;
|
|
1704
|
+
function halton(i, base) {
|
|
1705
|
+
var f = 1, r = 0;
|
|
1706
|
+
while (i > 0) { f /= base; r += f * (i % base); i = Math.floor(i / base); }
|
|
1707
|
+
return r;
|
|
1708
|
+
}
|
|
1709
|
+
var pts = [];
|
|
1710
|
+
for (var i = 0; i < n; i++) pts.push([halton(i+1, base1), halton(i+1, base2)]);
|
|
1711
|
+
return pts;
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
function uniformOnSphere(rng) {
|
|
1715
|
+
var u = rng(), v = rng();
|
|
1716
|
+
var theta = 2 * Math.PI * u;
|
|
1717
|
+
var phi = Math.acos(2 * v - 1);
|
|
1718
|
+
return [Math.sin(phi)*Math.cos(theta), Math.sin(phi)*Math.sin(theta), Math.cos(phi)];
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
function gaussianCluster(rng, cx, cy, stddev, count) {
|
|
1722
|
+
var pts = [];
|
|
1723
|
+
for (var i = 0; i < count; i++) {
|
|
1724
|
+
var u1 = rng(), u2 = rng();
|
|
1725
|
+
var r = Math.sqrt(-2 * Math.log(u1 || 1e-10));
|
|
1726
|
+
var theta = 2 * Math.PI * u2;
|
|
1727
|
+
pts.push([cx + r * Math.cos(theta) * stddev, cy + r * Math.sin(theta) * stddev]);
|
|
1728
|
+
}
|
|
1729
|
+
return pts;
|
|
1730
|
+
}
|
|
1731
|
+
`,
|
|
1732
|
+
exports: ["poissonDisk", "jitteredGrid", "haltonSequence", "uniformOnSphere", "gaussianCluster"],
|
|
1733
|
+
dependencies: ["prng"],
|
|
1734
|
+
description: "Point distribution algorithms (Poisson disk, Halton, jittered grid).",
|
|
1735
|
+
usage: `### distribution \u2014 Point Distributions
|
|
1736
|
+
|
|
1737
|
+
\`\`\`js
|
|
1738
|
+
var pts = poissonDisk(rng, 800, 600, 20);
|
|
1739
|
+
var grid = jitteredGrid(rng, 800, 600, 40, 0.5);
|
|
1740
|
+
var halton = haltonSequence(100, 2, 3);
|
|
1741
|
+
var sphere = uniformOnSphere(rng);
|
|
1742
|
+
\`\`\`
|
|
1743
|
+
`
|
|
1744
|
+
};
|
|
1745
|
+
var distribution_default = distribution;
|
|
1746
|
+
|
|
1747
|
+
// src/components/js/distribution-advanced.ts
|
|
1748
|
+
var distributionAdvanced = {
|
|
1749
|
+
name: "distribution-advanced",
|
|
1750
|
+
version: "1.0.0",
|
|
1751
|
+
category: "distribution",
|
|
1752
|
+
target: "js",
|
|
1753
|
+
renderers: [],
|
|
1754
|
+
code: `function blueNoise(rng, width, height, count) {
|
|
1755
|
+
var pts = poissonDisk(rng, width, height, Math.sqrt(width * height / count));
|
|
1756
|
+
return pts.slice(0, count);
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
function lloydRelaxation(points, width, height, iterations) {
|
|
1760
|
+
var pts = points.map(function(p) { return [p[0], p[1]]; });
|
|
1761
|
+
for (var iter = 0; iter < iterations; iter++) {
|
|
1762
|
+
var v = voronoi(pts, width, height, 2);
|
|
1763
|
+
var sums = new Array(pts.length);
|
|
1764
|
+
var counts = new Array(pts.length);
|
|
1765
|
+
for (var i = 0; i < pts.length; i++) { sums[i] = [0, 0]; counts[i] = 0; }
|
|
1766
|
+
for (var y = 0; y < v.rows; y++)
|
|
1767
|
+
for (var x = 0; x < v.cols; x++) {
|
|
1768
|
+
var ci = v.cells[y * v.cols + x];
|
|
1769
|
+
sums[ci][0] += x * 2; sums[ci][1] += y * 2;
|
|
1770
|
+
counts[ci]++;
|
|
1771
|
+
}
|
|
1772
|
+
for (var i = 0; i < pts.length; i++) {
|
|
1773
|
+
if (counts[i] > 0) {
|
|
1774
|
+
pts[i] = [sums[i][0] / counts[i], sums[i][1] / counts[i]];
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
return pts;
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
function fibonacciSphere(n) {
|
|
1782
|
+
var pts = [];
|
|
1783
|
+
var goldenAngle = Math.PI * (3 - Math.sqrt(5));
|
|
1784
|
+
for (var i = 0; i < n; i++) {
|
|
1785
|
+
var y = 1 - (i / (n - 1)) * 2;
|
|
1786
|
+
var radius = Math.sqrt(1 - y * y);
|
|
1787
|
+
var theta = goldenAngle * i;
|
|
1788
|
+
pts.push([Math.cos(theta) * radius, y, Math.sin(theta) * radius]);
|
|
1789
|
+
}
|
|
1790
|
+
return pts;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
function uniformOnDisk(rng, count) {
|
|
1794
|
+
var pts = [];
|
|
1795
|
+
for (var i = 0; i < count; i++) {
|
|
1796
|
+
var r = Math.sqrt(rng());
|
|
1797
|
+
var theta = rng() * Math.PI * 2;
|
|
1798
|
+
pts.push([r * Math.cos(theta), r * Math.sin(theta)]);
|
|
1799
|
+
}
|
|
1800
|
+
return pts;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
function stratifiedSample(rng, width, height, nx, ny) {
|
|
1804
|
+
var pts = [];
|
|
1805
|
+
var cw = width / nx, ch = height / ny;
|
|
1806
|
+
for (var y = 0; y < ny; y++)
|
|
1807
|
+
for (var x = 0; x < nx; x++)
|
|
1808
|
+
pts.push([x * cw + rng() * cw, y * ch + rng() * ch]);
|
|
1809
|
+
return pts;
|
|
1810
|
+
}
|
|
1811
|
+
`,
|
|
1812
|
+
exports: ["blueNoise", "lloydRelaxation", "fibonacciSphere", "uniformOnDisk", "stratifiedSample"],
|
|
1813
|
+
dependencies: ["prng", "distribution"],
|
|
1814
|
+
description: "Advanced spatial sampling (blue noise, Lloyd, Fibonacci sphere).",
|
|
1815
|
+
usage: `### distribution-advanced \u2014 Advanced Sampling
|
|
1816
|
+
|
|
1817
|
+
\`\`\`js
|
|
1818
|
+
var pts = blueNoise(rng, 800, 600, 200);
|
|
1819
|
+
var relaxed = lloydRelaxation(pts, 800, 600, 5);
|
|
1820
|
+
var sphere = fibonacciSphere(100);
|
|
1821
|
+
var disk = uniformOnDisk(rng, 50);
|
|
1822
|
+
\`\`\`
|
|
1823
|
+
`
|
|
1824
|
+
};
|
|
1825
|
+
var distribution_advanced_default = distributionAdvanced;
|
|
1826
|
+
|
|
1827
|
+
// src/components/js/physics-spring.ts
|
|
1828
|
+
var physicsSpring = {
|
|
1829
|
+
name: "physics-spring",
|
|
1830
|
+
version: "1.0.0",
|
|
1831
|
+
category: "physics",
|
|
1832
|
+
target: "js",
|
|
1833
|
+
renderers: [],
|
|
1834
|
+
code: `function createSpring(restLength, stiffness, damping) {
|
|
1835
|
+
return { restLength: restLength, stiffness: stiffness || 100, damping: damping || 5 };
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
function springSystem(points, springs) {
|
|
1839
|
+
return { points: points, springs: springs };
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
function springStep(system, dt) {
|
|
1843
|
+
dt = dt || 1/60;
|
|
1844
|
+
for (var i = 0; i < system.springs.length; i++) {
|
|
1845
|
+
var s = system.springs[i];
|
|
1846
|
+
var a = system.points[s.a], b = system.points[s.b];
|
|
1847
|
+
var dx = b.x - a.x, dy = b.y - a.y;
|
|
1848
|
+
var dist = Math.sqrt(dx * dx + dy * dy) || 0.001;
|
|
1849
|
+
var force = s.stiffness * (dist - s.restLength);
|
|
1850
|
+
var dvx = b.vx - a.vx, dvy = b.vy - a.vy;
|
|
1851
|
+
var dampF = s.damping * (dvx * dx + dvy * dy) / dist;
|
|
1852
|
+
var fx = (force + dampF) * dx / dist;
|
|
1853
|
+
var fy = (force + dampF) * dy / dist;
|
|
1854
|
+
a.vx += fx * dt; a.vy += fy * dt;
|
|
1855
|
+
b.vx -= fx * dt; b.vy -= fy * dt;
|
|
1856
|
+
}
|
|
1857
|
+
for (var i = 0; i < system.points.length; i++) {
|
|
1858
|
+
var p = system.points[i];
|
|
1859
|
+
if (p.fixed) continue;
|
|
1860
|
+
p.x += p.vx * dt; p.y += p.vy * dt;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
function dampedHarmonic(x, v, target, stiffness, damping, dt) {
|
|
1865
|
+
var force = -stiffness * (x - target) - damping * v;
|
|
1866
|
+
v += force * dt;
|
|
1867
|
+
x += v * dt;
|
|
1868
|
+
return { x: x, v: v };
|
|
1869
|
+
}
|
|
1870
|
+
`,
|
|
1871
|
+
exports: ["springSystem", "springStep", "createSpring", "dampedHarmonic"],
|
|
1872
|
+
dependencies: ["vector"],
|
|
1873
|
+
description: "Spring-based physics simulation.",
|
|
1874
|
+
usage: `### physics-spring \u2014 Spring Physics
|
|
1875
|
+
|
|
1876
|
+
\`\`\`js
|
|
1877
|
+
var points = [{x:0,y:0,vx:0,vy:0,fixed:true}, {x:100,y:0,vx:0,vy:0}];
|
|
1878
|
+
var springs = [{a:0, b:1, restLength:50, stiffness:100, damping:5}];
|
|
1879
|
+
var sys = springSystem(points, springs);
|
|
1880
|
+
springStep(sys, 1/60);
|
|
1881
|
+
\`\`\`
|
|
1882
|
+
`
|
|
1883
|
+
};
|
|
1884
|
+
var physics_spring_default = physicsSpring;
|
|
1885
|
+
|
|
1886
|
+
// src/components/js/physics-verlet.ts
|
|
1887
|
+
var physicsVerlet = {
|
|
1888
|
+
name: "physics-verlet",
|
|
1889
|
+
version: "1.0.0",
|
|
1890
|
+
category: "physics",
|
|
1891
|
+
target: "js",
|
|
1892
|
+
renderers: [],
|
|
1893
|
+
code: `function verletSystem(points) {
|
|
1894
|
+
return {
|
|
1895
|
+
points: points.map(function(p) {
|
|
1896
|
+
return { x: p.x, y: p.y, px: p.x, py: p.y, ax: 0, ay: 0, fixed: p.fixed || false };
|
|
1897
|
+
}),
|
|
1898
|
+
constraints: []
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
function verletStep(system, dt) {
|
|
1903
|
+
dt = dt || 1/60;
|
|
1904
|
+
var dt2 = dt * dt;
|
|
1905
|
+
for (var i = 0; i < system.points.length; i++) {
|
|
1906
|
+
var p = system.points[i];
|
|
1907
|
+
if (p.fixed) continue;
|
|
1908
|
+
var nx = 2 * p.x - p.px + p.ax * dt2;
|
|
1909
|
+
var ny = 2 * p.y - p.py + p.ay * dt2;
|
|
1910
|
+
p.px = p.x; p.py = p.y;
|
|
1911
|
+
p.x = nx; p.y = ny;
|
|
1912
|
+
p.ax = 0; p.ay = 0;
|
|
1913
|
+
}
|
|
1914
|
+
solveConstraints(system, 3);
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
function addConstraint(system, a, b, restLength) {
|
|
1918
|
+
system.constraints.push({
|
|
1919
|
+
a: a, b: b,
|
|
1920
|
+
restLength: restLength !== undefined ? restLength :
|
|
1921
|
+
Math.sqrt(Math.pow(system.points[a].x - system.points[b].x, 2) + Math.pow(system.points[a].y - system.points[b].y, 2))
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
function solveConstraints(system, iterations) {
|
|
1926
|
+
iterations = iterations || 3;
|
|
1927
|
+
for (var iter = 0; iter < iterations; iter++) {
|
|
1928
|
+
for (var i = 0; i < system.constraints.length; i++) {
|
|
1929
|
+
var c = system.constraints[i];
|
|
1930
|
+
var a = system.points[c.a], b = system.points[c.b];
|
|
1931
|
+
var dx = b.x - a.x, dy = b.y - a.y;
|
|
1932
|
+
var dist = Math.sqrt(dx * dx + dy * dy) || 0.001;
|
|
1933
|
+
var diff = (c.restLength - dist) / dist * 0.5;
|
|
1934
|
+
var ox = dx * diff, oy = dy * diff;
|
|
1935
|
+
if (!a.fixed) { a.x -= ox; a.y -= oy; }
|
|
1936
|
+
if (!b.fixed) { b.x += ox; b.y += oy; }
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
`,
|
|
1941
|
+
exports: ["verletSystem", "verletStep", "addConstraint", "solveConstraints"],
|
|
1942
|
+
dependencies: ["vector"],
|
|
1943
|
+
description: "Verlet integration with distance constraints.",
|
|
1944
|
+
usage: `### physics-verlet \u2014 Verlet Integration
|
|
1945
|
+
|
|
1946
|
+
\`\`\`js
|
|
1947
|
+
var sys = verletSystem([{x:0,y:0,fixed:true},{x:50,y:0},{x:100,y:0}]);
|
|
1948
|
+
addConstraint(sys, 0, 1); addConstraint(sys, 1, 2);
|
|
1949
|
+
sys.points[2].ay = 98; // gravity
|
|
1950
|
+
verletStep(sys, 1/60);
|
|
1951
|
+
\`\`\`
|
|
1952
|
+
`
|
|
1953
|
+
};
|
|
1954
|
+
var physics_verlet_default = physicsVerlet;
|
|
1955
|
+
|
|
1956
|
+
// src/components/js/physics-rk4.ts
|
|
1957
|
+
var physicsRk4 = {
|
|
1958
|
+
name: "physics-rk4",
|
|
1959
|
+
version: "1.0.0",
|
|
1960
|
+
category: "physics",
|
|
1961
|
+
target: "js",
|
|
1962
|
+
renderers: [],
|
|
1963
|
+
code: `function rk4Step(state, derivsFn, dt) {
|
|
1964
|
+
var n = state.length;
|
|
1965
|
+
var k1 = derivsFn(state);
|
|
1966
|
+
var s2 = new Array(n);
|
|
1967
|
+
for (var i = 0; i < n; i++) s2[i] = state[i] + k1[i] * dt / 2;
|
|
1968
|
+
var k2 = derivsFn(s2);
|
|
1969
|
+
var s3 = new Array(n);
|
|
1970
|
+
for (var i = 0; i < n; i++) s3[i] = state[i] + k2[i] * dt / 2;
|
|
1971
|
+
var k3 = derivsFn(s3);
|
|
1972
|
+
var s4 = new Array(n);
|
|
1973
|
+
for (var i = 0; i < n; i++) s4[i] = state[i] + k3[i] * dt;
|
|
1974
|
+
var k4 = derivsFn(s4);
|
|
1975
|
+
var result = new Array(n);
|
|
1976
|
+
for (var i = 0; i < n; i++)
|
|
1977
|
+
result[i] = state[i] + (k1[i] + 2*k2[i] + 2*k3[i] + k4[i]) * dt / 6;
|
|
1978
|
+
return result;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
function rk4System(initialState, derivsFn, dt, steps) {
|
|
1982
|
+
var state = initialState.slice();
|
|
1983
|
+
var trajectory = [state.slice()];
|
|
1984
|
+
for (var s = 0; s < steps; s++) {
|
|
1985
|
+
state = rk4Step(state, derivsFn, dt);
|
|
1986
|
+
trajectory.push(state.slice());
|
|
1987
|
+
}
|
|
1988
|
+
return trajectory;
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1991
|
+
function lorenzAttractor(sigma, rho, beta) {
|
|
1992
|
+
sigma = sigma || 10; rho = rho || 28; beta = beta || 8/3;
|
|
1993
|
+
return function(state) {
|
|
1994
|
+
return [
|
|
1995
|
+
sigma * (state[1] - state[0]),
|
|
1996
|
+
state[0] * (rho - state[2]) - state[1],
|
|
1997
|
+
state[0] * state[1] - beta * state[2]
|
|
1998
|
+
];
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
function phasePortrait(derivsFn, xRange, yRange, gridSize) {
|
|
2003
|
+
var arrows = [];
|
|
2004
|
+
var dx = (xRange[1] - xRange[0]) / gridSize;
|
|
2005
|
+
var dy = (yRange[1] - yRange[0]) / gridSize;
|
|
2006
|
+
for (var i = 0; i <= gridSize; i++) {
|
|
2007
|
+
for (var j = 0; j <= gridSize; j++) {
|
|
2008
|
+
var x = xRange[0] + i * dx, y = yRange[0] + j * dy;
|
|
2009
|
+
var d = derivsFn([x, y]);
|
|
2010
|
+
arrows.push({ x: x, y: y, dx: d[0], dy: d[1] });
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
return arrows;
|
|
2014
|
+
}
|
|
2015
|
+
`,
|
|
2016
|
+
exports: ["rk4Step", "rk4System", "lorenzAttractor", "phasePortrait"],
|
|
2017
|
+
dependencies: ["vector"],
|
|
2018
|
+
description: "Runge-Kutta integration and common ODEs (Lorenz attractor).",
|
|
2019
|
+
usage: `### physics-rk4 \u2014 RK4 Integration
|
|
2020
|
+
|
|
2021
|
+
\`\`\`js
|
|
2022
|
+
var lorenz = lorenzAttractor(10, 28, 8/3);
|
|
2023
|
+
var traj = rk4System([1,1,1], lorenz, 0.01, 5000);
|
|
2024
|
+
\`\`\`
|
|
2025
|
+
`
|
|
2026
|
+
};
|
|
2027
|
+
var physics_rk4_default = physicsRk4;
|
|
2028
|
+
|
|
2029
|
+
// src/components/js/flow-field.ts
|
|
2030
|
+
var flowField = {
|
|
2031
|
+
name: "flow-field",
|
|
2032
|
+
version: "1.0.0",
|
|
2033
|
+
category: "pattern",
|
|
2034
|
+
target: "js",
|
|
2035
|
+
renderers: [],
|
|
2036
|
+
code: `function createFlowField(cols, rows, angleFn) {
|
|
2037
|
+
var field = new Float64Array(cols * rows);
|
|
2038
|
+
for (var y = 0; y < rows; y++)
|
|
2039
|
+
for (var x = 0; x < cols; x++)
|
|
2040
|
+
field[y * cols + x] = angleFn(x, y);
|
|
2041
|
+
return { field: field, cols: cols, rows: rows };
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
function flowFromNoise(noiseFn, cols, rows, scale) {
|
|
2045
|
+
return createFlowField(cols, rows, function(x, y) {
|
|
2046
|
+
return noiseFn(x * scale, y * scale) * Math.PI * 4;
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
function flowFromFunction(fn, cols, rows) {
|
|
2051
|
+
return createFlowField(cols, rows, fn);
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
function traceStreamline(field, startX, startY, cellSize, steps, stepSize) {
|
|
2055
|
+
stepSize = stepSize || 1;
|
|
2056
|
+
var pts = [[startX, startY]];
|
|
2057
|
+
var x = startX, y = startY;
|
|
2058
|
+
for (var i = 0; i < steps; i++) {
|
|
2059
|
+
var gx = Math.floor(x / cellSize), gy = Math.floor(y / cellSize);
|
|
2060
|
+
if (gx < 0 || gx >= field.cols || gy < 0 || gy >= field.rows) break;
|
|
2061
|
+
var angle = field.field[gy * field.cols + gx];
|
|
2062
|
+
x += Math.cos(angle) * stepSize;
|
|
2063
|
+
y += Math.sin(angle) * stepSize;
|
|
2064
|
+
pts.push([x, y]);
|
|
2065
|
+
}
|
|
2066
|
+
return pts;
|
|
2067
|
+
}
|
|
2068
|
+
`,
|
|
2069
|
+
exports: ["createFlowField", "traceStreamline", "flowFromNoise", "flowFromFunction"],
|
|
2070
|
+
dependencies: ["noise-2d", "vector"],
|
|
2071
|
+
description: "Flow field generation and streamline tracing.",
|
|
2072
|
+
usage: `### flow-field \u2014 Flow Fields
|
|
2073
|
+
|
|
2074
|
+
\`\`\`js
|
|
2075
|
+
var field = flowFromNoise(perlin2D(rng), 80, 60, 0.03);
|
|
2076
|
+
var line = traceStreamline(field, startX, startY, 10, 200, 1);
|
|
2077
|
+
\`\`\`
|
|
2078
|
+
`
|
|
2079
|
+
};
|
|
2080
|
+
var flow_field_default = flowField;
|
|
2081
|
+
|
|
2082
|
+
// src/components/js/l-system.ts
|
|
2083
|
+
var lSystem = {
|
|
2084
|
+
name: "l-system",
|
|
2085
|
+
version: "1.0.0",
|
|
2086
|
+
category: "pattern",
|
|
2087
|
+
target: "js",
|
|
2088
|
+
renderers: [],
|
|
2089
|
+
code: `function createLSystem(axiom, rules) {
|
|
2090
|
+
return { axiom: axiom, rules: rules, current: axiom };
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
function iterateLSystem(system, iterations) {
|
|
2094
|
+
var str = system.current;
|
|
2095
|
+
for (var iter = 0; iter < iterations; iter++) {
|
|
2096
|
+
var next = '';
|
|
2097
|
+
for (var i = 0; i < str.length; i++) {
|
|
2098
|
+
var ch = str[i];
|
|
2099
|
+
next += system.rules[ch] !== undefined ? system.rules[ch] : ch;
|
|
2100
|
+
}
|
|
2101
|
+
str = next;
|
|
2102
|
+
}
|
|
2103
|
+
system.current = str;
|
|
2104
|
+
return str;
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
function turtleInterpret(str, stepLength, angleDeg) {
|
|
2108
|
+
var x = 0, y = 0, angle = -90;
|
|
2109
|
+
var rad = angleDeg * Math.PI / 180;
|
|
2110
|
+
var path = [[x, y]];
|
|
2111
|
+
var stack = [];
|
|
2112
|
+
for (var i = 0; i < str.length; i++) {
|
|
2113
|
+
var ch = str[i];
|
|
2114
|
+
if (ch === 'F' || ch === 'G') {
|
|
2115
|
+
x += Math.cos(angle * Math.PI / 180) * stepLength;
|
|
2116
|
+
y += Math.sin(angle * Math.PI / 180) * stepLength;
|
|
2117
|
+
path.push([x, y]);
|
|
2118
|
+
} else if (ch === 'f') {
|
|
2119
|
+
x += Math.cos(angle * Math.PI / 180) * stepLength;
|
|
2120
|
+
y += Math.sin(angle * Math.PI / 180) * stepLength;
|
|
2121
|
+
path.push(null);
|
|
2122
|
+
path.push([x, y]);
|
|
2123
|
+
} else if (ch === '+') { angle += angleDeg; }
|
|
2124
|
+
else if (ch === '-') { angle -= angleDeg; }
|
|
2125
|
+
else if (ch === '[') { stack.push({ x: x, y: y, angle: angle }); }
|
|
2126
|
+
else if (ch === ']') {
|
|
2127
|
+
var s = stack.pop();
|
|
2128
|
+
x = s.x; y = s.y; angle = s.angle;
|
|
2129
|
+
path.push(null);
|
|
2130
|
+
path.push([x, y]);
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
return path;
|
|
2134
|
+
}
|
|
2135
|
+
`,
|
|
2136
|
+
exports: ["createLSystem", "iterateLSystem", "turtleInterpret"],
|
|
2137
|
+
dependencies: ["math"],
|
|
2138
|
+
description: "L-system grammar iteration and turtle graphics interpretation.",
|
|
2139
|
+
usage: `### l-system \u2014 L-Systems
|
|
2140
|
+
|
|
2141
|
+
\`\`\`js
|
|
2142
|
+
var sys = createLSystem('F', { 'F': 'F[+F]F[-F]F' });
|
|
2143
|
+
var str = iterateLSystem(sys, 4);
|
|
2144
|
+
var path = turtleInterpret(str, 5, 25.7);
|
|
2145
|
+
\`\`\`
|
|
2146
|
+
`
|
|
2147
|
+
};
|
|
2148
|
+
var l_system_default = lSystem;
|
|
2149
|
+
|
|
2150
|
+
// src/components/js/reaction-diffusion.ts
|
|
2151
|
+
var reactionDiffusion = {
|
|
2152
|
+
name: "reaction-diffusion",
|
|
2153
|
+
version: "1.0.0",
|
|
2154
|
+
category: "pattern",
|
|
2155
|
+
target: "js",
|
|
2156
|
+
renderers: [],
|
|
2157
|
+
code: `function createGrayScottGrid(cols, rows) {
|
|
2158
|
+
var a = new Float64Array(cols * rows).fill(1);
|
|
2159
|
+
var b = new Float64Array(cols * rows).fill(0);
|
|
2160
|
+
return { a: a, b: b, cols: cols, rows: rows };
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
function grayScottStep(grid, feed, kill, dA, dB, dt) {
|
|
2164
|
+
feed = feed || 0.037; kill = kill || 0.06;
|
|
2165
|
+
dA = dA || 1.0; dB = dB || 0.5; dt = dt || 1.0;
|
|
2166
|
+
var cols = grid.cols, rows = grid.rows;
|
|
2167
|
+
var a = grid.a, b = grid.b;
|
|
2168
|
+
var na = new Float64Array(cols * rows);
|
|
2169
|
+
var nb = new Float64Array(cols * rows);
|
|
2170
|
+
for (var y = 0; y < rows; y++) {
|
|
2171
|
+
for (var x = 0; x < cols; x++) {
|
|
2172
|
+
var i = y * cols + x;
|
|
2173
|
+
var up = ((y-1+rows)%rows)*cols+x, dn = ((y+1)%rows)*cols+x;
|
|
2174
|
+
var lt = y*cols+(x-1+cols)%cols, rt = y*cols+(x+1)%cols;
|
|
2175
|
+
var lapA = a[up]+a[dn]+a[lt]+a[rt]-4*a[i];
|
|
2176
|
+
var lapB = b[up]+b[dn]+b[lt]+b[rt]-4*b[i];
|
|
2177
|
+
var abb = a[i] * b[i] * b[i];
|
|
2178
|
+
na[i] = a[i] + (dA * lapA - abb + feed * (1 - a[i])) * dt;
|
|
2179
|
+
nb[i] = b[i] + (dB * lapB + abb - (kill + feed) * b[i]) * dt;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
grid.a = na; grid.b = nb;
|
|
2183
|
+
return grid;
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
function turingPattern(cols, rows, steps, feed, kill, rng) {
|
|
2187
|
+
var grid = createGrayScottGrid(cols, rows);
|
|
2188
|
+
var cx = cols/2, cy = rows/2, r = Math.min(cols, rows)/6;
|
|
2189
|
+
for (var y = Math.floor(cy-r); y <= Math.ceil(cy+r); y++)
|
|
2190
|
+
for (var x = Math.floor(cx-r); x <= Math.ceil(cx+r); x++)
|
|
2191
|
+
if ((x-cx)*(x-cx)+(y-cy)*(y-cy) < r*r) {
|
|
2192
|
+
var i = y * cols + x;
|
|
2193
|
+
grid.b[i] = 1;
|
|
2194
|
+
if (rng) { grid.a[i] += (rng()-0.5)*0.01; grid.b[i] += (rng()-0.5)*0.01; }
|
|
2195
|
+
}
|
|
2196
|
+
for (var s = 0; s < steps; s++) grayScottStep(grid, feed, kill);
|
|
2197
|
+
return grid;
|
|
2198
|
+
}
|
|
2199
|
+
`,
|
|
2200
|
+
exports: ["grayScottStep", "createGrayScottGrid", "turingPattern"],
|
|
2201
|
+
dependencies: [],
|
|
2202
|
+
description: "Reaction-diffusion simulation (Gray-Scott model).",
|
|
2203
|
+
usage: `### reaction-diffusion \u2014 Gray-Scott
|
|
2204
|
+
|
|
2205
|
+
\`\`\`js
|
|
2206
|
+
var grid = createGrayScottGrid(200, 200);
|
|
2207
|
+
// seed center region with chemical B
|
|
2208
|
+
for (var s = 0; s < 5000; s++) grayScottStep(grid, 0.037, 0.06);
|
|
2209
|
+
// grid.b contains the pattern
|
|
2210
|
+
\`\`\`
|
|
2211
|
+
`
|
|
2212
|
+
};
|
|
2213
|
+
var reaction_diffusion_default = reactionDiffusion;
|
|
2214
|
+
|
|
2215
|
+
// src/components/js/dla.ts
|
|
2216
|
+
var dla = {
|
|
2217
|
+
name: "dla",
|
|
2218
|
+
version: "1.0.0",
|
|
2219
|
+
category: "pattern",
|
|
2220
|
+
target: "js",
|
|
2221
|
+
renderers: [],
|
|
2222
|
+
code: `function diffusionLimitedAggregation(rng, width, height, seedCount, walkerCount, stickiness) {
|
|
2223
|
+
stickiness = stickiness || 1;
|
|
2224
|
+
var grid = new Uint8Array(width * height);
|
|
2225
|
+
for (var i = 0; i < seedCount; i++) {
|
|
2226
|
+
var sx = Math.floor(width / 2 + (rng() - 0.5) * 10);
|
|
2227
|
+
var sy = Math.floor(height / 2 + (rng() - 0.5) * 10);
|
|
2228
|
+
if (sx >= 0 && sx < width && sy >= 0 && sy < height) grid[sy * width + sx] = 1;
|
|
2229
|
+
}
|
|
2230
|
+
var attached = [];
|
|
2231
|
+
for (var y = 0; y < height; y++)
|
|
2232
|
+
for (var x = 0; x < width; x++)
|
|
2233
|
+
if (grid[y * width + x]) attached.push([x, y]);
|
|
2234
|
+
|
|
2235
|
+
for (var w = 0; w < walkerCount; w++) {
|
|
2236
|
+
var wx = Math.floor(rng() * width), wy = Math.floor(rng() * height);
|
|
2237
|
+
var stuck = false;
|
|
2238
|
+
for (var step = 0; step < 10000 && !stuck; step++) {
|
|
2239
|
+
wx += Math.round(rng() * 2 - 1);
|
|
2240
|
+
wy += Math.round(rng() * 2 - 1);
|
|
2241
|
+
if (wx < 0 || wx >= width || wy < 0 || wy >= height) {
|
|
2242
|
+
wx = Math.floor(rng() * width);
|
|
2243
|
+
wy = Math.floor(rng() * height);
|
|
2244
|
+
continue;
|
|
2245
|
+
}
|
|
2246
|
+
for (var dx = -1; dx <= 1 && !stuck; dx++)
|
|
2247
|
+
for (var dy = -1; dy <= 1 && !stuck; dy++) {
|
|
2248
|
+
var nx = wx + dx, ny = wy + dy;
|
|
2249
|
+
if (nx >= 0 && nx < width && ny >= 0 && ny < height && grid[ny * width + nx]) {
|
|
2250
|
+
if (rng() < stickiness) {
|
|
2251
|
+
grid[wy * width + wx] = 1;
|
|
2252
|
+
attached.push([wx, wy]);
|
|
2253
|
+
stuck = true;
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
return { grid: grid, points: attached, width: width, height: height };
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
function dlaStep(state, rng, walkers, stickiness) {
|
|
2263
|
+
walkers = walkers || 100;
|
|
2264
|
+
stickiness = stickiness || 1;
|
|
2265
|
+
var w = state.width, h = state.height, grid = state.grid;
|
|
2266
|
+
for (var i = 0; i < walkers; i++) {
|
|
2267
|
+
var wx = Math.floor(rng() * w), wy = Math.floor(rng() * h);
|
|
2268
|
+
for (var step = 0; step < 500; step++) {
|
|
2269
|
+
wx += Math.round(rng() * 2 - 1);
|
|
2270
|
+
wy += Math.round(rng() * 2 - 1);
|
|
2271
|
+
if (wx < 0 || wx >= w || wy < 0 || wy >= h) break;
|
|
2272
|
+
var hasN = false;
|
|
2273
|
+
for (var dx = -1; dx <= 1 && !hasN; dx++)
|
|
2274
|
+
for (var dy = -1; dy <= 1 && !hasN; dy++) {
|
|
2275
|
+
var nx = wx + dx, ny = wy + dy;
|
|
2276
|
+
if (nx >= 0 && nx < w && ny >= 0 && ny < h && grid[ny * w + nx]) hasN = true;
|
|
2277
|
+
}
|
|
2278
|
+
if (hasN && rng() < stickiness) {
|
|
2279
|
+
grid[wy * w + wx] = 1;
|
|
2280
|
+
state.points.push([wx, wy]);
|
|
2281
|
+
break;
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
return state;
|
|
2286
|
+
}
|
|
2287
|
+
`,
|
|
2288
|
+
exports: ["diffusionLimitedAggregation", "dlaStep"],
|
|
2289
|
+
dependencies: ["prng"],
|
|
2290
|
+
description: "Diffusion-limited aggregation (DLA) pattern generation.",
|
|
2291
|
+
usage: `### dla \u2014 Diffusion-Limited Aggregation
|
|
2292
|
+
|
|
2293
|
+
\`\`\`js
|
|
2294
|
+
var state = diffusionLimitedAggregation(rng, 400, 400, 1, 5000, 0.8);
|
|
2295
|
+
// state.grid \u2014 occupancy grid
|
|
2296
|
+
// state.points \u2014 attached point coordinates
|
|
2297
|
+
\`\`\`
|
|
2298
|
+
`
|
|
2299
|
+
};
|
|
2300
|
+
var dla_default = dla;
|
|
2301
|
+
|
|
2302
|
+
// src/components/js/boids.ts
|
|
2303
|
+
var boids = {
|
|
2304
|
+
name: "boids",
|
|
2305
|
+
version: "1.0.0",
|
|
2306
|
+
category: "particle",
|
|
2307
|
+
target: "js",
|
|
2308
|
+
renderers: [],
|
|
2309
|
+
code: `function createBoidSystem(count, rng, width, height) {
|
|
2310
|
+
var boids = [];
|
|
2311
|
+
for (var i = 0; i < count; i++) {
|
|
2312
|
+
var angle = rng() * Math.PI * 2;
|
|
2313
|
+
var speed = 1 + rng() * 2;
|
|
2314
|
+
boids.push({
|
|
2315
|
+
x: rng() * width, y: rng() * height,
|
|
2316
|
+
vx: Math.cos(angle) * speed, vy: Math.sin(angle) * speed
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
return { boids: boids, width: width, height: height };
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
function separationForce(boid, neighbors, sepDist) {
|
|
2323
|
+
var sx = 0, sy = 0;
|
|
2324
|
+
for (var i = 0; i < neighbors.length; i++) {
|
|
2325
|
+
var dx = boid.x - neighbors[i].x, dy = boid.y - neighbors[i].y;
|
|
2326
|
+
var d = Math.sqrt(dx*dx + dy*dy);
|
|
2327
|
+
if (d > 0 && d < sepDist) { sx += dx / d; sy += dy / d; }
|
|
2328
|
+
}
|
|
2329
|
+
return [sx, sy];
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
function alignmentForce(boid, neighbors) {
|
|
2333
|
+
if (neighbors.length === 0) return [0, 0];
|
|
2334
|
+
var ax = 0, ay = 0;
|
|
2335
|
+
for (var i = 0; i < neighbors.length; i++) {
|
|
2336
|
+
ax += neighbors[i].vx; ay += neighbors[i].vy;
|
|
2337
|
+
}
|
|
2338
|
+
return [(ax / neighbors.length - boid.vx) * 0.1, (ay / neighbors.length - boid.vy) * 0.1];
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
function cohesionForce(boid, neighbors) {
|
|
2342
|
+
if (neighbors.length === 0) return [0, 0];
|
|
2343
|
+
var cx = 0, cy = 0;
|
|
2344
|
+
for (var i = 0; i < neighbors.length; i++) {
|
|
2345
|
+
cx += neighbors[i].x; cy += neighbors[i].y;
|
|
2346
|
+
}
|
|
2347
|
+
return [(cx / neighbors.length - boid.x) * 0.005, (cy / neighbors.length - boid.y) * 0.005];
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
function updateBoids(system, perception, sepDist, maxSpeed) {
|
|
2351
|
+
perception = perception || 50; sepDist = sepDist || 25; maxSpeed = maxSpeed || 4;
|
|
2352
|
+
for (var i = 0; i < system.boids.length; i++) {
|
|
2353
|
+
var b = system.boids[i];
|
|
2354
|
+
var neighbors = [];
|
|
2355
|
+
for (var j = 0; j < system.boids.length; j++) {
|
|
2356
|
+
if (i === j) continue;
|
|
2357
|
+
var dx = system.boids[j].x - b.x, dy = system.boids[j].y - b.y;
|
|
2358
|
+
if (dx*dx + dy*dy < perception * perception) neighbors.push(system.boids[j]);
|
|
2359
|
+
}
|
|
2360
|
+
var sep = separationForce(b, neighbors, sepDist);
|
|
2361
|
+
var ali = alignmentForce(b, neighbors);
|
|
2362
|
+
var coh = cohesionForce(b, neighbors);
|
|
2363
|
+
b.vx += sep[0] * 0.15 + ali[0] + coh[0];
|
|
2364
|
+
b.vy += sep[1] * 0.15 + ali[1] + coh[1];
|
|
2365
|
+
var spd = Math.sqrt(b.vx*b.vx + b.vy*b.vy);
|
|
2366
|
+
if (spd > maxSpeed) { b.vx = b.vx/spd*maxSpeed; b.vy = b.vy/spd*maxSpeed; }
|
|
2367
|
+
b.x += b.vx; b.y += b.vy;
|
|
2368
|
+
if (b.x < 0) b.x += system.width;
|
|
2369
|
+
if (b.x > system.width) b.x -= system.width;
|
|
2370
|
+
if (b.y < 0) b.y += system.height;
|
|
2371
|
+
if (b.y > system.height) b.y -= system.height;
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
`,
|
|
2375
|
+
exports: ["createBoidSystem", "updateBoids", "separationForce", "alignmentForce", "cohesionForce"],
|
|
2376
|
+
dependencies: ["vector"],
|
|
2377
|
+
description: "Boid flocking algorithm (separation, alignment, cohesion).",
|
|
2378
|
+
usage: `### boids \u2014 Flocking Algorithm
|
|
2379
|
+
|
|
2380
|
+
\`\`\`js
|
|
2381
|
+
var sys = createBoidSystem(200, rng, width, height);
|
|
2382
|
+
updateBoids(sys, 50, 25, 4);
|
|
2383
|
+
sys.boids.forEach(function(b) { drawBoid(b); });
|
|
2384
|
+
\`\`\`
|
|
2385
|
+
`
|
|
2386
|
+
};
|
|
2387
|
+
var boids_default = boids;
|
|
2388
|
+
|
|
2389
|
+
// src/components/js/wave.ts
|
|
2390
|
+
var wave = {
|
|
2391
|
+
name: "wave",
|
|
2392
|
+
version: "1.0.0",
|
|
2393
|
+
category: "animation",
|
|
2394
|
+
target: "js",
|
|
2395
|
+
renderers: [],
|
|
2396
|
+
code: `function sineWave(t, freq, amp, phase) {
|
|
2397
|
+
return (amp || 1) * Math.sin(2 * Math.PI * (freq || 1) * t + (phase || 0));
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
function squareWave(t, freq) {
|
|
2401
|
+
return Math.sin(2 * Math.PI * (freq || 1) * t) >= 0 ? 1 : -1;
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
function sawtoothWave(t, freq) {
|
|
2405
|
+
var p = t * (freq || 1);
|
|
2406
|
+
return 2 * (p - Math.floor(p + 0.5));
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
function triangleWave(t, freq) {
|
|
2410
|
+
var p = t * (freq || 1);
|
|
2411
|
+
return 4 * Math.abs(p - Math.floor(p + 0.75) + 0.25) - 1;
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
function waveSum(waveFns, t) {
|
|
2415
|
+
var sum = 0;
|
|
2416
|
+
for (var i = 0; i < waveFns.length; i++) sum += waveFns[i](t);
|
|
2417
|
+
return sum;
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
function standingWave(x, t, freq, wavelength) {
|
|
2421
|
+
return Math.sin(2 * Math.PI * x / (wavelength || 1)) * Math.cos(2 * Math.PI * (freq || 1) * t);
|
|
2422
|
+
}
|
|
2423
|
+
`,
|
|
2424
|
+
exports: ["sineWave", "squareWave", "sawtoothWave", "triangleWave", "waveSum", "standingWave"],
|
|
2425
|
+
dependencies: ["math"],
|
|
2426
|
+
description: "Periodic wave functions (sine, square, sawtooth, triangle).",
|
|
2427
|
+
usage: `### wave \u2014 Wave Functions
|
|
2428
|
+
|
|
2429
|
+
\`\`\`js
|
|
2430
|
+
sineWave(t, 2, 1, 0); // 2 Hz sine
|
|
2431
|
+
squareWave(t, 1); // 1 Hz square
|
|
2432
|
+
triangleWave(t, 0.5); // 0.5 Hz triangle
|
|
2433
|
+
standingWave(x, t, 1, 100);
|
|
2434
|
+
\`\`\`
|
|
2435
|
+
`
|
|
2436
|
+
};
|
|
2437
|
+
var wave_default = wave;
|
|
2438
|
+
|
|
2439
|
+
// src/components/js/animation.ts
|
|
2440
|
+
var animation = {
|
|
2441
|
+
name: "animation",
|
|
2442
|
+
version: "1.0.0",
|
|
2443
|
+
category: "animation",
|
|
2444
|
+
target: "js",
|
|
2445
|
+
renderers: [],
|
|
2446
|
+
code: `function pingPong(t) {
|
|
2447
|
+
t = t % 2;
|
|
2448
|
+
return t <= 1 ? t : 2 - t;
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
function loop(t, duration) {
|
|
2452
|
+
return (t % duration) / duration;
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
function oscillate(t, min, max, freq) {
|
|
2456
|
+
return min + (max - min) * 0.5 * (1 + Math.sin(2 * Math.PI * (freq || 1) * t));
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
function stagger(index, total, duration, offset) {
|
|
2460
|
+
offset = offset || 0.1;
|
|
2461
|
+
return Math.max(0, Math.min(1, (duration - index * offset) / (duration - (total-1) * offset)));
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
function timeline(t, keyframes) {
|
|
2465
|
+
for (var i = 0; i < keyframes.length - 1; i++) {
|
|
2466
|
+
var a = keyframes[i], b = keyframes[i+1];
|
|
2467
|
+
if (t >= a.t && t <= b.t) {
|
|
2468
|
+
var p = (t - a.t) / (b.t - a.t);
|
|
2469
|
+
if (b.ease) p = b.ease(p);
|
|
2470
|
+
return a.value + (b.value - a.value) * p;
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
return keyframes[keyframes.length - 1].value;
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2476
|
+
function sequence(t, segments) {
|
|
2477
|
+
var totalDuration = 0;
|
|
2478
|
+
for (var i = 0; i < segments.length; i++) totalDuration += segments[i].duration;
|
|
2479
|
+
t = t % totalDuration;
|
|
2480
|
+
var elapsed = 0;
|
|
2481
|
+
for (var i = 0; i < segments.length; i++) {
|
|
2482
|
+
if (t < elapsed + segments[i].duration) {
|
|
2483
|
+
var local = (t - elapsed) / segments[i].duration;
|
|
2484
|
+
return segments[i].fn(local);
|
|
2485
|
+
}
|
|
2486
|
+
elapsed += segments[i].duration;
|
|
2487
|
+
}
|
|
2488
|
+
return segments[segments.length - 1].fn(1);
|
|
2489
|
+
}
|
|
2490
|
+
`,
|
|
2491
|
+
exports: ["pingPong", "loop", "oscillate", "stagger", "timeline", "sequence"],
|
|
2492
|
+
dependencies: ["math", "easing"],
|
|
2493
|
+
description: "Animation timing utilities (ping-pong, stagger, timeline, sequence).",
|
|
2494
|
+
usage: `### animation \u2014 Timing Utilities
|
|
2495
|
+
|
|
2496
|
+
\`\`\`js
|
|
2497
|
+
pingPong(t); // 0\u21921\u21920\u21921...
|
|
2498
|
+
loop(t, 5); // repeats every 5 seconds
|
|
2499
|
+
oscillate(t, 0, 100, 2); // bounces 0\u2194100 at 2 Hz
|
|
2500
|
+
timeline(t, [
|
|
2501
|
+
{ t: 0, value: 0 },
|
|
2502
|
+
{ t: 1, value: 100, ease: easeInOutCubic },
|
|
2503
|
+
{ t: 2, value: 50 }
|
|
2504
|
+
]);
|
|
2505
|
+
\`\`\`
|
|
2506
|
+
`
|
|
2507
|
+
};
|
|
2508
|
+
var animation_default = animation;
|
|
2509
|
+
|
|
2510
|
+
// src/components/js/quadtree.ts
|
|
2511
|
+
var quadtree = {
|
|
2512
|
+
name: "quadtree",
|
|
2513
|
+
version: "1.0.0",
|
|
2514
|
+
category: "data-structure",
|
|
2515
|
+
target: "js",
|
|
2516
|
+
renderers: [],
|
|
2517
|
+
code: `function createQuadTree(x, y, w, h, capacity) {
|
|
2518
|
+
return { x: x, y: y, w: w, h: h, capacity: capacity || 4, points: [], children: null };
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
function insertPoint(qt, px, py, data) {
|
|
2522
|
+
if (px < qt.x || px >= qt.x + qt.w || py < qt.y || py >= qt.y + qt.h) return false;
|
|
2523
|
+
if (qt.points.length < qt.capacity && !qt.children) {
|
|
2524
|
+
qt.points.push({ x: px, y: py, data: data });
|
|
2525
|
+
return true;
|
|
2526
|
+
}
|
|
2527
|
+
if (!qt.children) {
|
|
2528
|
+
var hw = qt.w/2, hh = qt.h/2;
|
|
2529
|
+
qt.children = [
|
|
2530
|
+
createQuadTree(qt.x, qt.y, hw, hh, qt.capacity),
|
|
2531
|
+
createQuadTree(qt.x+hw, qt.y, hw, hh, qt.capacity),
|
|
2532
|
+
createQuadTree(qt.x, qt.y+hh, hw, hh, qt.capacity),
|
|
2533
|
+
createQuadTree(qt.x+hw, qt.y+hh, hw, hh, qt.capacity)
|
|
2534
|
+
];
|
|
2535
|
+
for (var i = 0; i < qt.points.length; i++) {
|
|
2536
|
+
var p = qt.points[i];
|
|
2537
|
+
for (var c = 0; c < 4; c++) if (insertPoint(qt.children[c], p.x, p.y, p.data)) break;
|
|
2538
|
+
}
|
|
2539
|
+
qt.points = [];
|
|
2540
|
+
}
|
|
2541
|
+
for (var c = 0; c < 4; c++) if (insertPoint(qt.children[c], px, py, data)) return true;
|
|
2542
|
+
return false;
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
function queryRange(qt, rx, ry, rw, rh) {
|
|
2546
|
+
var found = [];
|
|
2547
|
+
if (qt.x + qt.w < rx || qt.x > rx + rw || qt.y + qt.h < ry || qt.y > ry + rh) return found;
|
|
2548
|
+
for (var i = 0; i < qt.points.length; i++) {
|
|
2549
|
+
var p = qt.points[i];
|
|
2550
|
+
if (p.x >= rx && p.x <= rx + rw && p.y >= ry && p.y <= ry + rh) found.push(p);
|
|
2551
|
+
}
|
|
2552
|
+
if (qt.children) {
|
|
2553
|
+
for (var c = 0; c < 4; c++) found = found.concat(queryRange(qt.children[c], rx, ry, rw, rh));
|
|
2554
|
+
}
|
|
2555
|
+
return found;
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
function queryRadius(qt, cx, cy, r) {
|
|
2559
|
+
var found = [];
|
|
2560
|
+
var r2 = r * r;
|
|
2561
|
+
function search(node) {
|
|
2562
|
+
if (cx - r > node.x + node.w || cx + r < node.x || cy - r > node.y + node.h || cy + r < node.y) return;
|
|
2563
|
+
for (var i = 0; i < node.points.length; i++) {
|
|
2564
|
+
var p = node.points[i];
|
|
2565
|
+
var dx = p.x - cx, dy = p.y - cy;
|
|
2566
|
+
if (dx*dx + dy*dy <= r2) found.push(p);
|
|
2567
|
+
}
|
|
2568
|
+
if (node.children) for (var c = 0; c < 4; c++) search(node.children[c]);
|
|
2569
|
+
}
|
|
2570
|
+
search(qt);
|
|
2571
|
+
return found;
|
|
2572
|
+
}
|
|
2573
|
+
`,
|
|
2574
|
+
exports: ["createQuadTree", "insertPoint", "queryRange", "queryRadius"],
|
|
2575
|
+
dependencies: [],
|
|
2576
|
+
description: "Quadtree spatial index for efficient neighbor queries.",
|
|
2577
|
+
usage: `### quadtree \u2014 Spatial Index
|
|
2578
|
+
|
|
2579
|
+
\`\`\`js
|
|
2580
|
+
var qt = createQuadTree(0, 0, 800, 600, 8);
|
|
2581
|
+
points.forEach(function(p) { insertPoint(qt, p.x, p.y, p); });
|
|
2582
|
+
var nearby = queryRadius(qt, mouseX, mouseY, 50);
|
|
2583
|
+
\`\`\`
|
|
2584
|
+
`
|
|
2585
|
+
};
|
|
2586
|
+
var quadtree_default = quadtree;
|
|
2587
|
+
|
|
2588
|
+
// src/components/js/spatial-hash.ts
|
|
2589
|
+
var spatialHash = {
|
|
2590
|
+
name: "spatial-hash",
|
|
2591
|
+
version: "1.0.0",
|
|
2592
|
+
category: "data-structure",
|
|
2593
|
+
target: "js",
|
|
2594
|
+
renderers: [],
|
|
2595
|
+
code: `function createSpatialHash(cellSize) {
|
|
2596
|
+
return { cellSize: cellSize, cells: {} };
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
function insertCell(hash, x, y, data) {
|
|
2600
|
+
var cx = Math.floor(x / hash.cellSize);
|
|
2601
|
+
var cy = Math.floor(y / hash.cellSize);
|
|
2602
|
+
var key = cx + ',' + cy;
|
|
2603
|
+
if (!hash.cells[key]) hash.cells[key] = [];
|
|
2604
|
+
hash.cells[key].push({ x: x, y: y, data: data });
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2607
|
+
function queryNearby(hash, x, y, radius) {
|
|
2608
|
+
var cs = hash.cellSize;
|
|
2609
|
+
var minCx = Math.floor((x - radius) / cs);
|
|
2610
|
+
var maxCx = Math.floor((x + radius) / cs);
|
|
2611
|
+
var minCy = Math.floor((y - radius) / cs);
|
|
2612
|
+
var maxCy = Math.floor((y + radius) / cs);
|
|
2613
|
+
var r2 = radius * radius;
|
|
2614
|
+
var results = [];
|
|
2615
|
+
for (var cy = minCy; cy <= maxCy; cy++) {
|
|
2616
|
+
for (var cx = minCx; cx <= maxCx; cx++) {
|
|
2617
|
+
var cell = hash.cells[cx + ',' + cy];
|
|
2618
|
+
if (!cell) continue;
|
|
2619
|
+
for (var i = 0; i < cell.length; i++) {
|
|
2620
|
+
var p = cell[i];
|
|
2621
|
+
var dx = p.x - x, dy = p.y - y;
|
|
2622
|
+
if (dx * dx + dy * dy <= r2) results.push(p);
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
return results;
|
|
2627
|
+
}
|
|
2628
|
+
`,
|
|
2629
|
+
exports: ["createSpatialHash", "insertCell", "queryNearby"],
|
|
2630
|
+
dependencies: [],
|
|
2631
|
+
description: "Grid-based spatial hashing for fast neighbor lookups.",
|
|
2632
|
+
usage: `### spatial-hash \u2014 Spatial Hashing
|
|
2633
|
+
|
|
2634
|
+
\`\`\`js
|
|
2635
|
+
var hash = createSpatialHash(50);
|
|
2636
|
+
points.forEach(function(p) { insertCell(hash, p.x, p.y, p); });
|
|
2637
|
+
var nearby = queryNearby(hash, x, y, 100);
|
|
2638
|
+
\`\`\`
|
|
2639
|
+
`
|
|
2640
|
+
};
|
|
2641
|
+
var spatial_hash_default = spatialHash;
|
|
2642
|
+
|
|
2643
|
+
// src/components/js/turtle.ts
|
|
2644
|
+
var turtle = {
|
|
2645
|
+
name: "turtle",
|
|
2646
|
+
version: "1.0.0",
|
|
2647
|
+
category: "geometry",
|
|
2648
|
+
target: "js",
|
|
2649
|
+
renderers: [],
|
|
2650
|
+
code: `function createTurtle(x, y, angle) {
|
|
2651
|
+
return { x: x || 0, y: y || 0, angle: angle || 0, pen: true, path: [[x || 0, y || 0]] };
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2654
|
+
function forward(t, dist) {
|
|
2655
|
+
var rad = t.angle * Math.PI / 180;
|
|
2656
|
+
t.x += Math.cos(rad) * dist;
|
|
2657
|
+
t.y += Math.sin(rad) * dist;
|
|
2658
|
+
if (t.pen) t.path.push([t.x, t.y]);
|
|
2659
|
+
return t;
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
function turn(t, degrees) {
|
|
2663
|
+
t.angle += degrees;
|
|
2664
|
+
return t;
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2667
|
+
function penUp(t) {
|
|
2668
|
+
t.pen = false;
|
|
2669
|
+
return t;
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
function penDown(t) {
|
|
2673
|
+
t.pen = true;
|
|
2674
|
+
t.path.push(null);
|
|
2675
|
+
t.path.push([t.x, t.y]);
|
|
2676
|
+
return t;
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
function getPath(t) {
|
|
2680
|
+
return t.path;
|
|
2681
|
+
}
|
|
2682
|
+
`,
|
|
2683
|
+
exports: ["createTurtle", "forward", "turn", "penUp", "penDown", "getPath"],
|
|
2684
|
+
dependencies: ["vector"],
|
|
2685
|
+
description: "Turtle graphics state machine for path generation.",
|
|
2686
|
+
usage: `### turtle \u2014 Turtle Graphics
|
|
2687
|
+
|
|
2688
|
+
\`\`\`js
|
|
2689
|
+
var t = createTurtle(400, 300, 0);
|
|
2690
|
+
for (var i = 0; i < 360; i++) { forward(t, 2); turn(t, 1); }
|
|
2691
|
+
var path = getPath(t); // circle-like path
|
|
2692
|
+
\`\`\`
|
|
2693
|
+
`
|
|
2694
|
+
};
|
|
2695
|
+
var turtle_default = turtle;
|
|
2696
|
+
|
|
2697
|
+
// src/components/js/svg-path.ts
|
|
2698
|
+
var svgPath = {
|
|
2699
|
+
name: "svg-path",
|
|
2700
|
+
version: "1.0.0",
|
|
2701
|
+
category: "geometry",
|
|
2702
|
+
target: "js",
|
|
2703
|
+
renderers: [],
|
|
2704
|
+
code: `function pathFromPoints(points, closed) {
|
|
2705
|
+
if (!points.length) return '';
|
|
2706
|
+
var d = 'M ' + points[0][0] + ' ' + points[0][1];
|
|
2707
|
+
for (var i = 1; i < points.length; i++) {
|
|
2708
|
+
if (points[i] === null) {
|
|
2709
|
+
if (i + 1 < points.length && points[i + 1]) {
|
|
2710
|
+
d += ' M ' + points[i + 1][0] + ' ' + points[i + 1][1];
|
|
2711
|
+
i++;
|
|
2712
|
+
}
|
|
2713
|
+
} else {
|
|
2714
|
+
d += ' L ' + points[i][0] + ' ' + points[i][1];
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
if (closed) d += ' Z';
|
|
2718
|
+
return d;
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
function arcPath(cx, cy, r, startAngle, endAngle) {
|
|
2722
|
+
var x1 = cx + r * Math.cos(startAngle), y1 = cy + r * Math.sin(startAngle);
|
|
2723
|
+
var x2 = cx + r * Math.cos(endAngle), y2 = cy + r * Math.sin(endAngle);
|
|
2724
|
+
var largeArc = Math.abs(endAngle - startAngle) > Math.PI ? 1 : 0;
|
|
2725
|
+
return 'M ' + x1 + ' ' + y1 + ' A ' + r + ' ' + r + ' 0 ' + largeArc + ' 1 ' + x2 + ' ' + y2;
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
function bezierPath(points) {
|
|
2729
|
+
if (points.length < 4) return pathFromPoints(points);
|
|
2730
|
+
var d = 'M ' + points[0][0] + ' ' + points[0][1];
|
|
2731
|
+
for (var i = 1; i + 2 < points.length; i += 3) {
|
|
2732
|
+
d += ' C ' + points[i][0] + ' ' + points[i][1] + ', ' +
|
|
2733
|
+
points[i+1][0] + ' ' + points[i+1][1] + ', ' +
|
|
2734
|
+
points[i+2][0] + ' ' + points[i+2][1];
|
|
2735
|
+
}
|
|
2736
|
+
return d;
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
function closePath(d) { return d + ' Z'; }
|
|
2740
|
+
|
|
2741
|
+
function pathToString(segments) {
|
|
2742
|
+
return segments.join(' ');
|
|
2743
|
+
}
|
|
2744
|
+
`,
|
|
2745
|
+
exports: ["pathFromPoints", "arcPath", "bezierPath", "closePath", "pathToString"],
|
|
2746
|
+
dependencies: [],
|
|
2747
|
+
description: "SVG path string builders (points to path, arcs, bezier curves).",
|
|
2748
|
+
usage: `### svg-path \u2014 SVG Path Builders
|
|
2749
|
+
|
|
2750
|
+
\`\`\`js
|
|
2751
|
+
var d = pathFromPoints(points, true); // closed polygon
|
|
2752
|
+
var arc = arcPath(100, 100, 50, 0, Math.PI);
|
|
2753
|
+
var curve = bezierPath(controlPoints);
|
|
2754
|
+
\`\`\`
|
|
2755
|
+
`
|
|
2756
|
+
};
|
|
2757
|
+
var svg_path_default = svgPath;
|
|
2758
|
+
|
|
2759
|
+
// src/components/js/canvas-utils.ts
|
|
2760
|
+
var canvasUtils = {
|
|
2761
|
+
name: "canvas-utils",
|
|
2762
|
+
version: "1.0.0",
|
|
2763
|
+
category: "imaging",
|
|
2764
|
+
target: "js",
|
|
2765
|
+
renderers: [],
|
|
2766
|
+
code: `function pixelAt(imageData, x, y) {
|
|
2767
|
+
var i = (y * imageData.width + x) * 4;
|
|
2768
|
+
return [imageData.data[i], imageData.data[i+1], imageData.data[i+2], imageData.data[i+3]];
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
function setPixelAt(imageData, x, y, r, g, b, a) {
|
|
2772
|
+
var i = (y * imageData.width + x) * 4;
|
|
2773
|
+
imageData.data[i] = r; imageData.data[i+1] = g;
|
|
2774
|
+
imageData.data[i+2] = b; imageData.data[i+3] = a !== undefined ? a : 255;
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
function forEachPixel(imageData, fn) {
|
|
2778
|
+
for (var y = 0; y < imageData.height; y++)
|
|
2779
|
+
for (var x = 0; x < imageData.width; x++) {
|
|
2780
|
+
var i = (y * imageData.width + x) * 4;
|
|
2781
|
+
fn(x, y, imageData.data[i], imageData.data[i+1], imageData.data[i+2], imageData.data[i+3], i);
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
|
|
2785
|
+
function convolve3x3(imageData, kernel) {
|
|
2786
|
+
var w = imageData.width, h = imageData.height;
|
|
2787
|
+
var src = new Uint8ClampedArray(imageData.data);
|
|
2788
|
+
for (var y = 1; y < h-1; y++)
|
|
2789
|
+
for (var x = 1; x < w-1; x++) {
|
|
2790
|
+
var r=0,g=0,b=0;
|
|
2791
|
+
for (var ky = -1; ky <= 1; ky++)
|
|
2792
|
+
for (var kx = -1; kx <= 1; kx++) {
|
|
2793
|
+
var i = ((y+ky)*w+(x+kx))*4;
|
|
2794
|
+
var k = kernel[(ky+1)*3+(kx+1)];
|
|
2795
|
+
r += src[i]*k; g += src[i+1]*k; b += src[i+2]*k;
|
|
2796
|
+
}
|
|
2797
|
+
var oi = (y*w+x)*4;
|
|
2798
|
+
imageData.data[oi] = Math.max(0,Math.min(255,r));
|
|
2799
|
+
imageData.data[oi+1] = Math.max(0,Math.min(255,g));
|
|
2800
|
+
imageData.data[oi+2] = Math.max(0,Math.min(255,b));
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
|
|
2804
|
+
function threshold(imageData, level) {
|
|
2805
|
+
for (var i = 0; i < imageData.data.length; i += 4) {
|
|
2806
|
+
var v = (imageData.data[i]*0.299 + imageData.data[i+1]*0.587 + imageData.data[i+2]*0.114) >= level ? 255 : 0;
|
|
2807
|
+
imageData.data[i] = imageData.data[i+1] = imageData.data[i+2] = v;
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
function dither(imageData) {
|
|
2812
|
+
var w = imageData.width, h = imageData.height;
|
|
2813
|
+
var buf = new Float64Array(w * h);
|
|
2814
|
+
for (var i = 0; i < buf.length; i++)
|
|
2815
|
+
buf[i] = imageData.data[i*4]*0.299 + imageData.data[i*4+1]*0.587 + imageData.data[i*4+2]*0.114;
|
|
2816
|
+
for (var y = 0; y < h; y++)
|
|
2817
|
+
for (var x = 0; x < w; x++) {
|
|
2818
|
+
var old = buf[y*w+x];
|
|
2819
|
+
var nw = old < 128 ? 0 : 255;
|
|
2820
|
+
buf[y*w+x] = nw;
|
|
2821
|
+
var err = old - nw;
|
|
2822
|
+
if (x+1<w) buf[y*w+x+1] += err*7/16;
|
|
2823
|
+
if (y+1<h) {
|
|
2824
|
+
if (x>0) buf[(y+1)*w+x-1] += err*3/16;
|
|
2825
|
+
buf[(y+1)*w+x] += err*5/16;
|
|
2826
|
+
if (x+1<w) buf[(y+1)*w+x+1] += err/16;
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
for (var i = 0; i < buf.length; i++) {
|
|
2830
|
+
var v = Math.max(0, Math.min(255, Math.round(buf[i])));
|
|
2831
|
+
imageData.data[i*4] = imageData.data[i*4+1] = imageData.data[i*4+2] = v;
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
`,
|
|
2835
|
+
exports: ["pixelAt", "setPixelAt", "forEachPixel", "convolve3x3", "threshold", "dither"],
|
|
2836
|
+
dependencies: [],
|
|
2837
|
+
description: "ImageData pixel manipulation (read, write, convolve, dither).",
|
|
2838
|
+
usage: `### canvas-utils \u2014 Pixel Manipulation
|
|
2839
|
+
|
|
2840
|
+
\`\`\`js
|
|
2841
|
+
var px = pixelAt(imageData, x, y); // [r, g, b, a]
|
|
2842
|
+
setPixelAt(imageData, x, y, 255, 0, 0);
|
|
2843
|
+
convolve3x3(imageData, [0,-1,0,-1,5,-1,0,-1,0]); // sharpen
|
|
2844
|
+
threshold(imageData, 128);
|
|
2845
|
+
dither(imageData); // Floyd-Steinberg
|
|
2846
|
+
\`\`\`
|
|
2847
|
+
`
|
|
2848
|
+
};
|
|
2849
|
+
var canvas_utils_default = canvasUtils;
|
|
2850
|
+
|
|
2851
|
+
// src/components/glsl/index.ts
|
|
2852
|
+
var glsl_exports = {};
|
|
2853
|
+
__export(glsl_exports, {
|
|
2854
|
+
glslBlend: () => blend_default,
|
|
2855
|
+
glslColor: () => color_default2,
|
|
2856
|
+
glslCurl: () => curl_default2,
|
|
2857
|
+
glslDomain: () => domain_default,
|
|
2858
|
+
glslEasing: () => easing_default2,
|
|
2859
|
+
glslGradient: () => gradient_default,
|
|
2860
|
+
glslLighting: () => lighting_default,
|
|
2861
|
+
glslMath: () => math_default2,
|
|
2862
|
+
glslNoise: () => noise_default,
|
|
2863
|
+
glslNoise3d: () => noise_3d_default2,
|
|
2864
|
+
glslNoise4d: () => noise_4d_default2,
|
|
2865
|
+
glslPattern: () => pattern_default,
|
|
2866
|
+
glslPost: () => post_default,
|
|
2867
|
+
glslRay: () => ray_default,
|
|
2868
|
+
glslSdf: () => sdf_default,
|
|
2869
|
+
glslSdf3d: () => sdf_3d_default,
|
|
2870
|
+
glslShape: () => shape_default2,
|
|
2871
|
+
glslTransform: () => transform_default
|
|
2872
|
+
});
|
|
2873
|
+
|
|
2874
|
+
// src/components/glsl/noise.ts
|
|
2875
|
+
var glslNoise = {
|
|
2876
|
+
name: "glsl-noise",
|
|
2877
|
+
version: "1.0.0",
|
|
2878
|
+
category: "noise",
|
|
2879
|
+
target: "glsl",
|
|
2880
|
+
renderers: [],
|
|
2881
|
+
code: `float hash(vec2 p) {
|
|
2882
|
+
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
float noise(vec2 p) {
|
|
2886
|
+
vec2 i = floor(p);
|
|
2887
|
+
vec2 f = fract(p);
|
|
2888
|
+
f = f * f * (3.0 - 2.0 * f);
|
|
2889
|
+
float a = hash(i);
|
|
2890
|
+
float b = hash(i + vec2(1.0, 0.0));
|
|
2891
|
+
float c = hash(i + vec2(0.0, 1.0));
|
|
2892
|
+
float d = hash(i + vec2(1.0, 1.0));
|
|
2893
|
+
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2896
|
+
float fbm(vec2 p, int octaves) {
|
|
2897
|
+
float val = 0.0, amp = 0.5;
|
|
2898
|
+
for (int i = 0; i < 8; i++) {
|
|
2899
|
+
if (i >= octaves) break;
|
|
2900
|
+
val += amp * noise(p);
|
|
2901
|
+
p *= 2.0;
|
|
2902
|
+
amp *= 0.5;
|
|
2903
|
+
}
|
|
2904
|
+
return val;
|
|
2905
|
+
}
|
|
2906
|
+
|
|
2907
|
+
float voronoi(vec2 p) {
|
|
2908
|
+
vec2 n = floor(p);
|
|
2909
|
+
vec2 f = fract(p);
|
|
2910
|
+
float minDist = 1.0;
|
|
2911
|
+
for (int j = -1; j <= 1; j++) {
|
|
2912
|
+
for (int i = -1; i <= 1; i++) {
|
|
2913
|
+
vec2 g = vec2(float(i), float(j));
|
|
2914
|
+
vec2 o = vec2(hash(n + g), hash(n + g + vec2(37.0, 17.0)));
|
|
2915
|
+
vec2 diff = g + o - f;
|
|
2916
|
+
minDist = min(minDist, dot(diff, diff));
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
return sqrt(minDist);
|
|
2920
|
+
}
|
|
2921
|
+
`,
|
|
2922
|
+
exports: ["hash", "noise", "fbm", "voronoi"],
|
|
2923
|
+
dependencies: [],
|
|
2924
|
+
description: "Standard GLSL noise stack (hash, value noise, fBm, Voronoi).",
|
|
2925
|
+
usage: `### glsl-noise \u2014 GLSL Noise
|
|
2926
|
+
|
|
2927
|
+
\`\`\`glsl
|
|
2928
|
+
float n = noise(uv * 10.0);
|
|
2929
|
+
float f = fbm(uv * 5.0, 6);
|
|
2930
|
+
float v = voronoi(uv * 8.0);
|
|
2931
|
+
\`\`\`
|
|
2932
|
+
`
|
|
2933
|
+
};
|
|
2934
|
+
var noise_default = glslNoise;
|
|
2935
|
+
|
|
2936
|
+
// src/components/glsl/noise-3d.ts
|
|
2937
|
+
var glslNoise3d = {
|
|
2938
|
+
name: "glsl-noise-3d",
|
|
2939
|
+
version: "1.0.0",
|
|
2940
|
+
category: "noise",
|
|
2941
|
+
target: "glsl",
|
|
2942
|
+
renderers: [],
|
|
2943
|
+
code: `float hash3(vec3 p) {
|
|
2944
|
+
p = fract(p * vec3(443.897, 441.423, 437.195));
|
|
2945
|
+
p += dot(p, p.yzx + 19.19);
|
|
2946
|
+
return fract((p.x + p.y) * p.z);
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2949
|
+
float noise3(vec3 p) {
|
|
2950
|
+
vec3 i = floor(p);
|
|
2951
|
+
vec3 f = fract(p);
|
|
2952
|
+
f = f * f * (3.0 - 2.0 * f);
|
|
2953
|
+
float a = hash3(i);
|
|
2954
|
+
float b = hash3(i + vec3(1.0, 0.0, 0.0));
|
|
2955
|
+
float c = hash3(i + vec3(0.0, 1.0, 0.0));
|
|
2956
|
+
float d = hash3(i + vec3(1.0, 1.0, 0.0));
|
|
2957
|
+
float e = hash3(i + vec3(0.0, 0.0, 1.0));
|
|
2958
|
+
float f2 = hash3(i + vec3(1.0, 0.0, 1.0));
|
|
2959
|
+
float g = hash3(i + vec3(0.0, 1.0, 1.0));
|
|
2960
|
+
float h = hash3(i + vec3(1.0, 1.0, 1.0));
|
|
2961
|
+
float x1 = mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
|
2962
|
+
float x2 = mix(mix(e, f2, f.x), mix(g, h, f.x), f.y);
|
|
2963
|
+
return mix(x1, x2, f.z);
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2966
|
+
float fbm3(vec3 p, int octaves) {
|
|
2967
|
+
float val = 0.0, amp = 0.5;
|
|
2968
|
+
for (int i = 0; i < 8; i++) {
|
|
2969
|
+
if (i >= octaves) break;
|
|
2970
|
+
val += amp * noise3(p);
|
|
2971
|
+
p *= 2.0;
|
|
2972
|
+
amp *= 0.5;
|
|
2973
|
+
}
|
|
2974
|
+
return val;
|
|
2975
|
+
}
|
|
2976
|
+
`,
|
|
2977
|
+
exports: ["hash3", "noise3", "fbm3"],
|
|
2978
|
+
dependencies: [],
|
|
2979
|
+
description: "3D GLSL noise (hash, value noise, fBm).",
|
|
2980
|
+
usage: `### glsl-noise-3d \u2014 3D Noise
|
|
2981
|
+
|
|
2982
|
+
\`\`\`glsl
|
|
2983
|
+
float n = noise3(vec3(uv * 5.0, u_time));
|
|
2984
|
+
float f = fbm3(vec3(uv * 3.0, u_time * 0.5), 6);
|
|
2985
|
+
\`\`\`
|
|
2986
|
+
`
|
|
2987
|
+
};
|
|
2988
|
+
var noise_3d_default2 = glslNoise3d;
|
|
2989
|
+
|
|
2990
|
+
// src/components/glsl/noise-4d.ts
|
|
2991
|
+
var glslNoise4d = {
|
|
2992
|
+
name: "glsl-noise-4d",
|
|
2993
|
+
version: "1.0.0",
|
|
2994
|
+
category: "noise",
|
|
2995
|
+
target: "glsl",
|
|
2996
|
+
renderers: [],
|
|
2997
|
+
code: `float noise4(vec4 p) {
|
|
2998
|
+
vec4 i = floor(p);
|
|
2999
|
+
vec4 f = fract(p);
|
|
3000
|
+
f = f * f * (3.0 - 2.0 * f);
|
|
3001
|
+
float h1 = fract(sin(dot(i, vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3002
|
+
float h2 = fract(sin(dot(i + vec4(1,0,0,0), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3003
|
+
float h3 = fract(sin(dot(i + vec4(0,1,0,0), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3004
|
+
float h4 = fract(sin(dot(i + vec4(1,1,0,0), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3005
|
+
float h5 = fract(sin(dot(i + vec4(0,0,1,0), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3006
|
+
float h6 = fract(sin(dot(i + vec4(1,0,1,0), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3007
|
+
float h7 = fract(sin(dot(i + vec4(0,1,1,0), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3008
|
+
float h8 = fract(sin(dot(i + vec4(1,1,1,0), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3009
|
+
float h9 = fract(sin(dot(i + vec4(0,0,0,1), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3010
|
+
float h10 = fract(sin(dot(i + vec4(1,0,0,1), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3011
|
+
float h11 = fract(sin(dot(i + vec4(0,1,0,1), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3012
|
+
float h12 = fract(sin(dot(i + vec4(1,1,0,1), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3013
|
+
float h13 = fract(sin(dot(i + vec4(0,0,1,1), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3014
|
+
float h14 = fract(sin(dot(i + vec4(1,0,1,1), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3015
|
+
float h15 = fract(sin(dot(i + vec4(0,1,1,1), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3016
|
+
float h16 = fract(sin(dot(i + vec4(1,1,1,1), vec4(127.1,311.7,269.5,183.3))) * 43758.5453);
|
|
3017
|
+
float x1 = mix(mix(h1,h2,f.x), mix(h3,h4,f.x), f.y);
|
|
3018
|
+
float x2 = mix(mix(h5,h6,f.x), mix(h7,h8,f.x), f.y);
|
|
3019
|
+
float x3 = mix(mix(h9,h10,f.x), mix(h11,h12,f.x), f.y);
|
|
3020
|
+
float x4 = mix(mix(h13,h14,f.x), mix(h15,h16,f.x), f.y);
|
|
3021
|
+
return mix(mix(x1,x2,f.z), mix(x3,x4,f.z), f.w);
|
|
3022
|
+
}
|
|
3023
|
+
|
|
3024
|
+
float fbm4(vec4 p, int octaves) {
|
|
3025
|
+
float val = 0.0, amp = 0.5;
|
|
3026
|
+
for (int i = 0; i < 8; i++) {
|
|
3027
|
+
if (i >= octaves) break;
|
|
3028
|
+
val += amp * noise4(p);
|
|
3029
|
+
p *= 2.0;
|
|
3030
|
+
amp *= 0.5;
|
|
3031
|
+
}
|
|
3032
|
+
return val;
|
|
3033
|
+
}
|
|
3034
|
+
`,
|
|
3035
|
+
exports: ["noise4", "fbm4"],
|
|
3036
|
+
dependencies: [],
|
|
3037
|
+
description: "4D GLSL noise for loopable animations.",
|
|
3038
|
+
usage: `### glsl-noise-4d \u2014 4D Noise
|
|
3039
|
+
|
|
3040
|
+
\`\`\`glsl
|
|
3041
|
+
float n = noise4(vec4(uv * 5.0, cos(t) * r, sin(t) * r));
|
|
3042
|
+
\`\`\`
|
|
3043
|
+
`
|
|
3044
|
+
};
|
|
3045
|
+
var noise_4d_default2 = glslNoise4d;
|
|
3046
|
+
|
|
3047
|
+
// src/components/glsl/curl.ts
|
|
3048
|
+
var glslCurl = {
|
|
3049
|
+
name: "glsl-curl",
|
|
3050
|
+
version: "1.0.0",
|
|
3051
|
+
category: "noise",
|
|
3052
|
+
target: "glsl",
|
|
3053
|
+
renderers: [],
|
|
3054
|
+
code: `vec2 curlNoise(vec2 p) {
|
|
3055
|
+
float eps = 0.001;
|
|
3056
|
+
float n1 = noise(p + vec2(eps, 0.0));
|
|
3057
|
+
float n2 = noise(p - vec2(eps, 0.0));
|
|
3058
|
+
float n3 = noise(p + vec2(0.0, eps));
|
|
3059
|
+
float n4 = noise(p - vec2(0.0, eps));
|
|
3060
|
+
float dndx = (n1 - n2) / (2.0 * eps);
|
|
3061
|
+
float dndy = (n3 - n4) / (2.0 * eps);
|
|
3062
|
+
return vec2(dndy, -dndx);
|
|
3063
|
+
}
|
|
3064
|
+
`,
|
|
3065
|
+
exports: ["curlNoise"],
|
|
3066
|
+
dependencies: ["glsl-noise"],
|
|
3067
|
+
description: "GLSL curl noise for divergence-free flow.",
|
|
3068
|
+
usage: `### glsl-curl \u2014 Curl Noise
|
|
3069
|
+
|
|
3070
|
+
\`\`\`glsl
|
|
3071
|
+
vec2 flow = curlNoise(uv * 5.0);
|
|
3072
|
+
\`\`\`
|
|
3073
|
+
`
|
|
3074
|
+
};
|
|
3075
|
+
var curl_default2 = glslCurl;
|
|
3076
|
+
|
|
3077
|
+
// src/components/glsl/sdf.ts
|
|
3078
|
+
var glslSdf = {
|
|
3079
|
+
name: "glsl-sdf",
|
|
3080
|
+
version: "1.0.0",
|
|
3081
|
+
category: "sdf",
|
|
3082
|
+
target: "glsl",
|
|
3083
|
+
renderers: [],
|
|
3084
|
+
code: `float sdCircle(vec2 p, float r) {
|
|
3085
|
+
return length(p) - r;
|
|
3086
|
+
}
|
|
3087
|
+
|
|
3088
|
+
float sdBox(vec2 p, vec2 b) {
|
|
3089
|
+
vec2 d = abs(p) - b;
|
|
3090
|
+
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
float sdLine(vec2 p, vec2 a, vec2 b) {
|
|
3094
|
+
vec2 pa = p - a, ba = b - a;
|
|
3095
|
+
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
|
3096
|
+
return length(pa - ba * h);
|
|
3097
|
+
}
|
|
3098
|
+
|
|
3099
|
+
float sdPolygon(vec2 p, vec2 v[8], int n) {
|
|
3100
|
+
float d = dot(p - v[0], p - v[0]);
|
|
3101
|
+
float s = 1.0;
|
|
3102
|
+
for (int i = 0, j = n - 1; i < 8; j = i, i++) {
|
|
3103
|
+
if (i >= n) break;
|
|
3104
|
+
vec2 e = v[j] - v[i];
|
|
3105
|
+
vec2 w = p - v[i];
|
|
3106
|
+
vec2 b = w - e * clamp(dot(w, e) / dot(e, e), 0.0, 1.0);
|
|
3107
|
+
d = min(d, dot(b, b));
|
|
3108
|
+
bvec3 cond = bvec3(p.y >= v[i].y, p.y < v[j].y, e.x * w.y > e.y * w.x);
|
|
3109
|
+
if (all(cond) || all(not(cond))) s *= -1.0;
|
|
3110
|
+
}
|
|
3111
|
+
return s * sqrt(d);
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
float sdRing(vec2 p, float r, float thickness) {
|
|
3115
|
+
return abs(length(p) - r) - thickness;
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3118
|
+
float opUnion(float d1, float d2) { return min(d1, d2); }
|
|
3119
|
+
float opSubtract(float d1, float d2) { return max(-d1, d2); }
|
|
3120
|
+
float opIntersect(float d1, float d2) { return max(d1, d2); }
|
|
3121
|
+
float opSmooth(float d1, float d2, float k) {
|
|
3122
|
+
float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
|
|
3123
|
+
return mix(d2, d1, h) - k * h * (1.0 - h);
|
|
3124
|
+
}
|
|
3125
|
+
`,
|
|
3126
|
+
exports: ["sdCircle", "sdBox", "sdLine", "sdPolygon", "sdRing", "opUnion", "opSubtract", "opIntersect", "opSmooth"],
|
|
3127
|
+
dependencies: [],
|
|
3128
|
+
description: "2D signed distance functions and CSG operations.",
|
|
3129
|
+
usage: `### glsl-sdf \u2014 2D SDF
|
|
3130
|
+
|
|
3131
|
+
\`\`\`glsl
|
|
3132
|
+
float d = sdCircle(uv - 0.5, 0.2);
|
|
3133
|
+
d = opSmooth(d, sdBox(uv - vec2(0.7), vec2(0.1)), 0.05);
|
|
3134
|
+
vec3 col = mix(vec3(1), vec3(0), smoothstep(0.0, 0.01, d));
|
|
3135
|
+
\`\`\`
|
|
3136
|
+
`
|
|
3137
|
+
};
|
|
3138
|
+
var sdf_default = glslSdf;
|
|
3139
|
+
|
|
3140
|
+
// src/components/glsl/sdf-3d.ts
|
|
3141
|
+
var glslSdf3d = {
|
|
3142
|
+
name: "glsl-sdf-3d",
|
|
3143
|
+
version: "1.0.0",
|
|
3144
|
+
category: "sdf",
|
|
3145
|
+
target: "glsl",
|
|
3146
|
+
renderers: [],
|
|
3147
|
+
code: `float sdSphere(vec3 p, float r) { return length(p) - r; }
|
|
3148
|
+
|
|
3149
|
+
float sdBox3(vec3 p, vec3 b) {
|
|
3150
|
+
vec3 d = abs(p) - b;
|
|
3151
|
+
return length(max(d, 0.0)) + min(max(d.x, max(d.y, d.z)), 0.0);
|
|
3152
|
+
}
|
|
3153
|
+
|
|
3154
|
+
float sdCylinder(vec3 p, float h, float r) {
|
|
3155
|
+
vec2 d = abs(vec2(length(p.xz), p.y)) - vec2(r, h);
|
|
3156
|
+
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
|
|
3157
|
+
}
|
|
3158
|
+
|
|
3159
|
+
float sdTorus(vec3 p, vec2 t) {
|
|
3160
|
+
vec2 q = vec2(length(p.xz) - t.x, p.y);
|
|
3161
|
+
return length(q) - t.y;
|
|
3162
|
+
}
|
|
3163
|
+
|
|
3164
|
+
float opUnion3(float d1, float d2) { return min(d1, d2); }
|
|
3165
|
+
float opSmooth3(float d1, float d2, float k) {
|
|
3166
|
+
float h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
|
|
3167
|
+
return mix(d2, d1, h) - k * h * (1.0 - h);
|
|
3168
|
+
}
|
|
3169
|
+
|
|
3170
|
+
vec3 opRepeat(vec3 p, vec3 c) {
|
|
3171
|
+
return mod(p + 0.5 * c, c) - 0.5 * c;
|
|
3172
|
+
}
|
|
3173
|
+
`,
|
|
3174
|
+
exports: ["sdSphere", "sdBox3", "sdCylinder", "sdTorus", "opUnion3", "opSmooth3", "opRepeat"],
|
|
3175
|
+
dependencies: [],
|
|
3176
|
+
description: "3D SDF primitives (sphere, box, cylinder, torus) and operations.",
|
|
3177
|
+
usage: `### glsl-sdf-3d \u2014 3D SDF
|
|
3178
|
+
|
|
3179
|
+
\`\`\`glsl
|
|
3180
|
+
float d = sdSphere(p, 1.0);
|
|
3181
|
+
d = opSmooth3(d, sdBox3(p - vec3(1.5, 0, 0), vec3(0.5)), 0.2);
|
|
3182
|
+
\`\`\`
|
|
3183
|
+
`
|
|
3184
|
+
};
|
|
3185
|
+
var sdf_3d_default = glslSdf3d;
|
|
3186
|
+
|
|
3187
|
+
// src/components/glsl/color.ts
|
|
3188
|
+
var glslColor = {
|
|
3189
|
+
name: "glsl-color",
|
|
3190
|
+
version: "1.0.0",
|
|
3191
|
+
category: "color",
|
|
3192
|
+
target: "glsl",
|
|
3193
|
+
renderers: [],
|
|
3194
|
+
code: `vec3 rgb2hsv(vec3 c) {
|
|
3195
|
+
vec4 K = vec4(0.0, -1.0/3.0, 2.0/3.0, -1.0);
|
|
3196
|
+
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
|
3197
|
+
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
|
3198
|
+
float d = q.x - min(q.w, q.y);
|
|
3199
|
+
float e = 1.0e-10;
|
|
3200
|
+
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
|
3201
|
+
}
|
|
3202
|
+
|
|
3203
|
+
vec3 hsv2rgb(vec3 c) {
|
|
3204
|
+
vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);
|
|
3205
|
+
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
|
3206
|
+
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
vec3 rgb2hsl(vec3 c) {
|
|
3210
|
+
float maxC = max(c.r, max(c.g, c.b));
|
|
3211
|
+
float minC = min(c.r, min(c.g, c.b));
|
|
3212
|
+
float l = (maxC + minC) * 0.5;
|
|
3213
|
+
if (maxC == minC) return vec3(0.0, 0.0, l);
|
|
3214
|
+
float d = maxC - minC;
|
|
3215
|
+
float s = l > 0.5 ? d / (2.0 - maxC - minC) : d / (maxC + minC);
|
|
3216
|
+
float h;
|
|
3217
|
+
if (maxC == c.r) h = (c.g - c.b) / d + (c.g < c.b ? 6.0 : 0.0);
|
|
3218
|
+
else if (maxC == c.g) h = (c.b - c.r) / d + 2.0;
|
|
3219
|
+
else h = (c.r - c.g) / d + 4.0;
|
|
3220
|
+
h /= 6.0;
|
|
3221
|
+
return vec3(h, s, l);
|
|
3222
|
+
}
|
|
3223
|
+
|
|
3224
|
+
vec3 hsl2rgb(vec3 c) {
|
|
3225
|
+
if (c.y == 0.0) return vec3(c.z);
|
|
3226
|
+
float q = c.z < 0.5 ? c.z * (1.0 + c.y) : c.z + c.y - c.z * c.y;
|
|
3227
|
+
float p = 2.0 * c.z - q;
|
|
3228
|
+
vec3 t = vec3(c.x + 1.0/3.0, c.x, c.x - 1.0/3.0);
|
|
3229
|
+
t = fract(t);
|
|
3230
|
+
vec3 r;
|
|
3231
|
+
for (int i = 0; i < 3; i++) {
|
|
3232
|
+
float ti = i == 0 ? t.x : (i == 1 ? t.y : t.z);
|
|
3233
|
+
float v;
|
|
3234
|
+
if (ti < 1.0/6.0) v = p + (q - p) * 6.0 * ti;
|
|
3235
|
+
else if (ti < 0.5) v = q;
|
|
3236
|
+
else if (ti < 2.0/3.0) v = p + (q - p) * (2.0/3.0 - ti) * 6.0;
|
|
3237
|
+
else v = p;
|
|
3238
|
+
if (i == 0) r.x = v;
|
|
3239
|
+
else if (i == 1) r.y = v;
|
|
3240
|
+
else r.z = v;
|
|
3241
|
+
}
|
|
3242
|
+
return r;
|
|
3243
|
+
}
|
|
3244
|
+
|
|
3245
|
+
vec3 rgb2oklab(vec3 c) {
|
|
3246
|
+
float l = 0.4122214708 * c.r + 0.5363325363 * c.g + 0.0514459929 * c.b;
|
|
3247
|
+
float m = 0.2119034982 * c.r + 0.6806995451 * c.g + 0.1073969566 * c.b;
|
|
3248
|
+
float s = 0.0883024619 * c.r + 0.2817188376 * c.g + 0.6299787005 * c.b;
|
|
3249
|
+
l = pow(l, 1.0/3.0); m = pow(m, 1.0/3.0); s = pow(s, 1.0/3.0);
|
|
3250
|
+
return vec3(
|
|
3251
|
+
0.2104542553*l + 0.7936177850*m - 0.0040720468*s,
|
|
3252
|
+
1.9779984951*l - 2.4285922050*m + 0.4505937099*s,
|
|
3253
|
+
0.0259040371*l + 0.7827717662*m - 0.8086757660*s
|
|
3254
|
+
);
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
vec3 oklab2rgb(vec3 lab) {
|
|
3258
|
+
float l = lab.x + 0.3963377774*lab.y + 0.2158037573*lab.z;
|
|
3259
|
+
float m = lab.x - 0.1055613458*lab.y - 0.0638541728*lab.z;
|
|
3260
|
+
float s = lab.x - 0.0894841775*lab.y - 1.2914855480*lab.z;
|
|
3261
|
+
l=l*l*l; m=m*m*m; s=s*s*s;
|
|
3262
|
+
return vec3(
|
|
3263
|
+
4.0767416621*l - 3.3077115913*m + 0.2309699292*s,
|
|
3264
|
+
-1.2684380046*l + 2.6097574011*m - 0.3413193965*s,
|
|
3265
|
+
-0.0041960863*l - 0.7034186147*m + 1.7076147010*s
|
|
3266
|
+
);
|
|
3267
|
+
}
|
|
3268
|
+
|
|
3269
|
+
vec3 posterize(vec3 c, float levels) {
|
|
3270
|
+
return floor(c * levels + 0.5) / levels;
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3273
|
+
vec3 quantize(vec3 c, float steps) {
|
|
3274
|
+
return floor(c * steps) / steps;
|
|
3275
|
+
}
|
|
3276
|
+
`,
|
|
3277
|
+
exports: ["rgb2hsv", "hsv2rgb", "rgb2hsl", "hsl2rgb", "rgb2oklab", "oklab2rgb", "posterize", "quantize"],
|
|
3278
|
+
dependencies: [],
|
|
3279
|
+
description: "GLSL color space conversions (HSV, HSL, OKLab) and quantization.",
|
|
3280
|
+
usage: `### glsl-color \u2014 Color Spaces
|
|
3281
|
+
|
|
3282
|
+
\`\`\`glsl
|
|
3283
|
+
vec3 hsv = rgb2hsv(color);
|
|
3284
|
+
hsv.x += 0.1; // hue shift
|
|
3285
|
+
color = hsv2rgb(hsv);
|
|
3286
|
+
color = posterize(color, 4.0);
|
|
3287
|
+
\`\`\`
|
|
3288
|
+
`
|
|
3289
|
+
};
|
|
3290
|
+
var color_default2 = glslColor;
|
|
3291
|
+
|
|
3292
|
+
// src/components/glsl/pattern.ts
|
|
3293
|
+
var glslPattern = {
|
|
3294
|
+
name: "glsl-pattern",
|
|
3295
|
+
version: "1.0.0",
|
|
3296
|
+
category: "pattern",
|
|
3297
|
+
target: "glsl",
|
|
3298
|
+
renderers: [],
|
|
3299
|
+
code: `float truchet(vec2 uv, float scale) {
|
|
3300
|
+
vec2 id = floor(uv * scale);
|
|
3301
|
+
vec2 f = fract(uv * scale);
|
|
3302
|
+
float r = hash(id);
|
|
3303
|
+
if (r > 0.5) f.x = 1.0 - f.x;
|
|
3304
|
+
float d1 = length(f) - 0.5;
|
|
3305
|
+
float d2 = length(f - 1.0) - 0.5;
|
|
3306
|
+
return min(abs(d1), abs(d2));
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3309
|
+
float checkerboard(vec2 uv, float scale) {
|
|
3310
|
+
vec2 c = floor(uv * scale);
|
|
3311
|
+
return mod(c.x + c.y, 2.0);
|
|
3312
|
+
}
|
|
3313
|
+
|
|
3314
|
+
vec2 hexGrid(vec2 uv) {
|
|
3315
|
+
vec2 s = vec2(1.0, 1.7320508);
|
|
3316
|
+
vec2 a = mod(uv, s) - s * 0.5;
|
|
3317
|
+
vec2 b = mod(uv - s * 0.5, s) - s * 0.5;
|
|
3318
|
+
return dot(a, a) < dot(b, b) ? a : b;
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
float voronoiEdges(vec2 uv, float scale) {
|
|
3322
|
+
vec2 p = uv * scale;
|
|
3323
|
+
vec2 n = floor(p);
|
|
3324
|
+
vec2 f = fract(p);
|
|
3325
|
+
float md = 8.0;
|
|
3326
|
+
for (int j = -1; j <= 1; j++)
|
|
3327
|
+
for (int i = -1; i <= 1; i++) {
|
|
3328
|
+
vec2 g = vec2(float(i), float(j));
|
|
3329
|
+
vec2 o = vec2(hash(n + g), hash(n + g + vec2(37.0)));
|
|
3330
|
+
vec2 r = g + o - f;
|
|
3331
|
+
md = min(md, dot(r, r));
|
|
3332
|
+
}
|
|
3333
|
+
return sqrt(md);
|
|
3334
|
+
}
|
|
3335
|
+
|
|
3336
|
+
float stripes(vec2 uv, float freq, float angle) {
|
|
3337
|
+
float c = cos(angle), s = sin(angle);
|
|
3338
|
+
float t = uv.x * c + uv.y * s;
|
|
3339
|
+
return 0.5 + 0.5 * sin(t * freq * 6.28318);
|
|
3340
|
+
}
|
|
3341
|
+
|
|
3342
|
+
float dots(vec2 uv, float scale, float radius) {
|
|
3343
|
+
vec2 f = fract(uv * scale) - 0.5;
|
|
3344
|
+
return smoothstep(radius, radius - 0.01, length(f));
|
|
3345
|
+
}
|
|
3346
|
+
`,
|
|
3347
|
+
exports: ["truchet", "checkerboard", "hexGrid", "voronoiEdges", "stripes", "dots"],
|
|
3348
|
+
dependencies: ["glsl-noise"],
|
|
3349
|
+
description: "Tiling and pattern functions (truchet, hex grid, stripes, dots).",
|
|
3350
|
+
usage: `### glsl-pattern \u2014 Patterns
|
|
3351
|
+
|
|
3352
|
+
\`\`\`glsl
|
|
3353
|
+
float t = truchet(uv, 10.0);
|
|
3354
|
+
float c = checkerboard(uv, 8.0);
|
|
3355
|
+
float s = stripes(uv, 20.0, 0.785);
|
|
3356
|
+
\`\`\`
|
|
3357
|
+
`
|
|
3358
|
+
};
|
|
3359
|
+
var pattern_default = glslPattern;
|
|
3360
|
+
|
|
3361
|
+
// src/components/glsl/transform.ts
|
|
3362
|
+
var glslTransform = {
|
|
3363
|
+
name: "glsl-transform",
|
|
3364
|
+
version: "1.0.0",
|
|
3365
|
+
category: "transform",
|
|
3366
|
+
target: "glsl",
|
|
3367
|
+
renderers: [],
|
|
3368
|
+
code: `vec2 rotate2D(vec2 p, float angle) {
|
|
3369
|
+
float c = cos(angle), s = sin(angle);
|
|
3370
|
+
return vec2(p.x * c - p.y * s, p.x * s + p.y * c);
|
|
3371
|
+
}
|
|
3372
|
+
|
|
3373
|
+
vec2 scale2D(vec2 p, vec2 s) { return p / s; }
|
|
3374
|
+
vec2 translate2D(vec2 p, vec2 t) { return p - t; }
|
|
3375
|
+
|
|
3376
|
+
vec2 kaleidoscope(vec2 p, float segments) {
|
|
3377
|
+
float angle = atan(p.y, p.x);
|
|
3378
|
+
float r = length(p);
|
|
3379
|
+
float seg = 6.28318 / segments;
|
|
3380
|
+
angle = mod(angle, seg);
|
|
3381
|
+
if (angle > seg * 0.5) angle = seg - angle;
|
|
3382
|
+
return vec2(cos(angle), sin(angle)) * r;
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3385
|
+
vec2 polarCoords(vec2 p) {
|
|
3386
|
+
return vec2(length(p), atan(p.y, p.x));
|
|
3387
|
+
}
|
|
3388
|
+
|
|
3389
|
+
vec2 fishEye(vec2 uv, float strength) {
|
|
3390
|
+
vec2 c = uv - 0.5;
|
|
3391
|
+
float r = length(c);
|
|
3392
|
+
float bind = sqrt(dot(vec2(0.5), vec2(0.5)));
|
|
3393
|
+
vec2 nuv = c / bind;
|
|
3394
|
+
nuv *= 1.0 - strength + strength * r;
|
|
3395
|
+
return nuv * bind + 0.5;
|
|
3396
|
+
}
|
|
3397
|
+
|
|
3398
|
+
vec2 ripple(vec2 uv, vec2 center, float freq, float amp, float time) {
|
|
3399
|
+
vec2 d = uv - center;
|
|
3400
|
+
float r = length(d);
|
|
3401
|
+
float offset = sin(r * freq - time) * amp;
|
|
3402
|
+
return uv + normalize(d) * offset;
|
|
3403
|
+
}
|
|
3404
|
+
`,
|
|
3405
|
+
exports: ["rotate2D", "scale2D", "translate2D", "kaleidoscope", "polarCoords", "fishEye", "ripple"],
|
|
3406
|
+
dependencies: [],
|
|
3407
|
+
description: "UV coordinate transformations (rotate, kaleidoscope, fisheye, ripple).",
|
|
3408
|
+
usage: `### glsl-transform \u2014 UV Transforms
|
|
3409
|
+
|
|
3410
|
+
\`\`\`glsl
|
|
3411
|
+
vec2 p = rotate2D(uv - 0.5, u_time) + 0.5;
|
|
3412
|
+
p = kaleidoscope(p - 0.5, 6.0);
|
|
3413
|
+
p = fishEye(uv, 0.5);
|
|
3414
|
+
\`\`\`
|
|
3415
|
+
`
|
|
3416
|
+
};
|
|
3417
|
+
var transform_default = glslTransform;
|
|
3418
|
+
|
|
3419
|
+
// src/components/glsl/math.ts
|
|
3420
|
+
var glslMath = {
|
|
3421
|
+
name: "glsl-math",
|
|
3422
|
+
version: "1.0.0",
|
|
3423
|
+
category: "math",
|
|
3424
|
+
target: "glsl",
|
|
3425
|
+
renderers: [],
|
|
3426
|
+
code: `float remap(float value, float inMin, float inMax, float outMin, float outMax) {
|
|
3427
|
+
return outMin + (value - inMin) / (inMax - inMin) * (outMax - outMin);
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3430
|
+
float mod289(float x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
|
3431
|
+
|
|
3432
|
+
float inverseLerp(float a, float b, float v) { return (v - a) / (b - a); }
|
|
3433
|
+
|
|
3434
|
+
float smoothmin(float a, float b, float k) {
|
|
3435
|
+
float h = max(k - abs(a - b), 0.0) / k;
|
|
3436
|
+
return min(a, b) - h * h * h * k * (1.0 / 6.0);
|
|
3437
|
+
}
|
|
3438
|
+
|
|
3439
|
+
float bias(float x, float b) {
|
|
3440
|
+
return x / ((1.0 / b - 2.0) * (1.0 - x) + 1.0);
|
|
3441
|
+
}
|
|
3442
|
+
|
|
3443
|
+
float gain(float x, float g) {
|
|
3444
|
+
if (x < 0.5) return bias(x * 2.0, g) * 0.5;
|
|
3445
|
+
return bias(x * 2.0 - 1.0, 1.0 - g) * 0.5 + 0.5;
|
|
3446
|
+
}
|
|
3447
|
+
`,
|
|
3448
|
+
exports: ["remap", "mod289", "inverseLerp", "smoothmin", "bias", "gain"],
|
|
3449
|
+
dependencies: [],
|
|
3450
|
+
description: "GLSL math utilities (remap, smoothmin, bias, gain).",
|
|
3451
|
+
usage: `### glsl-math \u2014 GLSL Math
|
|
3452
|
+
|
|
3453
|
+
\`\`\`glsl
|
|
3454
|
+
float v = remap(x, 0.0, 1.0, -1.0, 1.0);
|
|
3455
|
+
float s = smoothmin(d1, d2, 0.1);
|
|
3456
|
+
float b = bias(x, 0.3);
|
|
3457
|
+
\`\`\`
|
|
3458
|
+
`
|
|
3459
|
+
};
|
|
3460
|
+
var math_default2 = glslMath;
|
|
3461
|
+
|
|
3462
|
+
// src/components/glsl/easing.ts
|
|
3463
|
+
var glslEasing = {
|
|
3464
|
+
name: "glsl-easing",
|
|
3465
|
+
version: "1.0.0",
|
|
3466
|
+
category: "easing",
|
|
3467
|
+
target: "glsl",
|
|
3468
|
+
renderers: [],
|
|
3469
|
+
code: `float easeInQuad(float t) { return t * t; }
|
|
3470
|
+
float easeOutQuad(float t) { return t * (2.0 - t); }
|
|
3471
|
+
float easeInOutCubic(float t) {
|
|
3472
|
+
return t < 0.5 ? 4.0 * t * t * t : 1.0 - pow(-2.0 * t + 2.0, 3.0) / 2.0;
|
|
3473
|
+
}
|
|
3474
|
+
float easeOutElastic(float t) {
|
|
3475
|
+
if (t == 0.0 || t == 1.0) return t;
|
|
3476
|
+
return pow(2.0, -10.0 * t) * sin((t * 10.0 - 0.75) * (6.28318 / 3.0)) + 1.0;
|
|
3477
|
+
}
|
|
3478
|
+
float easeOutBounce(float t) {
|
|
3479
|
+
if (t < 1.0 / 2.75) return 7.5625 * t * t;
|
|
3480
|
+
if (t < 2.0 / 2.75) { t -= 1.5 / 2.75; return 7.5625 * t * t + 0.75; }
|
|
3481
|
+
if (t < 2.5 / 2.75) { t -= 2.25 / 2.75; return 7.5625 * t * t + 0.9375; }
|
|
3482
|
+
t -= 2.625 / 2.75; return 7.5625 * t * t + 0.984375;
|
|
3483
|
+
}
|
|
3484
|
+
`,
|
|
3485
|
+
exports: ["easeInQuad", "easeOutQuad", "easeInOutCubic", "easeOutElastic", "easeOutBounce"],
|
|
3486
|
+
dependencies: [],
|
|
3487
|
+
description: "Easing functions in GLSL.",
|
|
3488
|
+
usage: `### glsl-easing \u2014 GLSL Easing
|
|
3489
|
+
|
|
3490
|
+
\`\`\`glsl
|
|
3491
|
+
float t = easeInOutCubic(progress);
|
|
3492
|
+
float e = easeOutElastic(progress);
|
|
3493
|
+
\`\`\`
|
|
3494
|
+
`
|
|
3495
|
+
};
|
|
3496
|
+
var easing_default2 = glslEasing;
|
|
3497
|
+
|
|
3498
|
+
// src/components/glsl/blend.ts
|
|
3499
|
+
var glslBlend = {
|
|
3500
|
+
name: "glsl-blend",
|
|
3501
|
+
version: "1.0.0",
|
|
3502
|
+
category: "color",
|
|
3503
|
+
target: "glsl",
|
|
3504
|
+
renderers: [],
|
|
3505
|
+
code: `vec3 blendMultiply(vec3 base, vec3 blend) { return base * blend; }
|
|
3506
|
+
vec3 blendScreen(vec3 base, vec3 blend) { return 1.0 - (1.0 - base) * (1.0 - blend); }
|
|
3507
|
+
vec3 blendOverlay(vec3 base, vec3 blend) {
|
|
3508
|
+
return vec3(
|
|
3509
|
+
base.r < 0.5 ? 2.0 * base.r * blend.r : 1.0 - 2.0 * (1.0 - base.r) * (1.0 - blend.r),
|
|
3510
|
+
base.g < 0.5 ? 2.0 * base.g * blend.g : 1.0 - 2.0 * (1.0 - base.g) * (1.0 - blend.g),
|
|
3511
|
+
base.b < 0.5 ? 2.0 * base.b * blend.b : 1.0 - 2.0 * (1.0 - base.b) * (1.0 - blend.b)
|
|
3512
|
+
);
|
|
3513
|
+
}
|
|
3514
|
+
vec3 blendSoftLight(vec3 base, vec3 blend) {
|
|
3515
|
+
return mix(
|
|
3516
|
+
sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend),
|
|
3517
|
+
2.0 * base * blend + base * base * (1.0 - 2.0 * blend),
|
|
3518
|
+
step(vec3(0.5), blend)
|
|
3519
|
+
);
|
|
3520
|
+
}
|
|
3521
|
+
vec3 blendAdd(vec3 base, vec3 blend) { return min(base + blend, vec3(1.0)); }
|
|
3522
|
+
`,
|
|
3523
|
+
exports: ["blendMultiply", "blendScreen", "blendOverlay", "blendSoftLight", "blendAdd"],
|
|
3524
|
+
dependencies: [],
|
|
3525
|
+
description: "Photoshop-style blend modes in GLSL.",
|
|
3526
|
+
usage: `### glsl-blend \u2014 Blend Modes
|
|
3527
|
+
|
|
3528
|
+
\`\`\`glsl
|
|
3529
|
+
vec3 result = blendOverlay(base, overlay);
|
|
3530
|
+
result = blendScreen(result, glow);
|
|
3531
|
+
\`\`\`
|
|
3532
|
+
`
|
|
3533
|
+
};
|
|
3534
|
+
var blend_default = glslBlend;
|
|
3535
|
+
|
|
3536
|
+
// src/components/glsl/lighting.ts
|
|
3537
|
+
var glslLighting = {
|
|
3538
|
+
name: "glsl-lighting",
|
|
3539
|
+
version: "1.0.0",
|
|
3540
|
+
category: "pattern",
|
|
3541
|
+
target: "glsl",
|
|
3542
|
+
renderers: [],
|
|
3543
|
+
code: `float lambertian(vec3 normal, vec3 lightDir) {
|
|
3544
|
+
return max(dot(normalize(normal), normalize(lightDir)), 0.0);
|
|
3545
|
+
}
|
|
3546
|
+
|
|
3547
|
+
float phong(vec3 normal, vec3 lightDir, vec3 viewDir, float shininess) {
|
|
3548
|
+
vec3 n = normalize(normal);
|
|
3549
|
+
vec3 l = normalize(lightDir);
|
|
3550
|
+
vec3 r = reflect(-l, n);
|
|
3551
|
+
float diff = max(dot(n, l), 0.0);
|
|
3552
|
+
float spec = pow(max(dot(normalize(viewDir), r), 0.0), shininess);
|
|
3553
|
+
return diff + spec;
|
|
3554
|
+
}
|
|
3555
|
+
|
|
3556
|
+
vec3 normalFromHeight(sampler2D tex, vec2 uv, float strength) {
|
|
3557
|
+
float eps = 1.0 / 512.0;
|
|
3558
|
+
float h = texture2D(tex, uv).r;
|
|
3559
|
+
float hx = texture2D(tex, uv + vec2(eps, 0.0)).r;
|
|
3560
|
+
float hy = texture2D(tex, uv + vec2(0.0, eps)).r;
|
|
3561
|
+
return normalize(vec3((h - hx) * strength, (h - hy) * strength, 1.0));
|
|
3562
|
+
}
|
|
3563
|
+
|
|
3564
|
+
float ambientOcclusion(vec2 uv, float radius, float intensity) {
|
|
3565
|
+
float ao = 0.0;
|
|
3566
|
+
for (int i = 0; i < 4; i++) {
|
|
3567
|
+
float angle = float(i) * 1.5708;
|
|
3568
|
+
vec2 offset = vec2(cos(angle), sin(angle)) * radius;
|
|
3569
|
+
ao += smoothstep(0.0, 1.0, length(offset));
|
|
3570
|
+
}
|
|
3571
|
+
return 1.0 - (ao / 4.0) * intensity;
|
|
3572
|
+
}
|
|
3573
|
+
`,
|
|
3574
|
+
exports: ["phong", "lambertian", "normalFromHeight", "ambientOcclusion"],
|
|
3575
|
+
dependencies: [],
|
|
3576
|
+
description: "Basic GLSL lighting models (Phong, Lambertian, normal mapping).",
|
|
3577
|
+
usage: `### glsl-lighting \u2014 Lighting
|
|
3578
|
+
|
|
3579
|
+
\`\`\`glsl
|
|
3580
|
+
float diff = lambertian(normal, lightPos - fragPos);
|
|
3581
|
+
float lit = phong(normal, lightDir, viewDir, 32.0);
|
|
3582
|
+
vec3 n = normalFromHeight(heightMap, uv, 2.0);
|
|
3583
|
+
\`\`\`
|
|
3584
|
+
`
|
|
3585
|
+
};
|
|
3586
|
+
var lighting_default = glslLighting;
|
|
3587
|
+
|
|
3588
|
+
// src/components/glsl/ray.ts
|
|
3589
|
+
var glslRay = {
|
|
3590
|
+
name: "glsl-ray",
|
|
3591
|
+
version: "1.0.0",
|
|
3592
|
+
category: "sdf",
|
|
3593
|
+
target: "glsl",
|
|
3594
|
+
renderers: [],
|
|
3595
|
+
code: `float rayMarch(vec3 ro, vec3 rd, float maxDist, int maxSteps) {
|
|
3596
|
+
float t = 0.0;
|
|
3597
|
+
for (int i = 0; i < 256; i++) {
|
|
3598
|
+
if (i >= maxSteps) break;
|
|
3599
|
+
vec3 p = ro + rd * t;
|
|
3600
|
+
float d = sdSphere(p, 1.0);
|
|
3601
|
+
if (d < 0.001 || t > maxDist) break;
|
|
3602
|
+
t += d;
|
|
3603
|
+
}
|
|
3604
|
+
return t;
|
|
3605
|
+
}
|
|
3606
|
+
|
|
3607
|
+
vec3 estimateNormal(vec3 p) {
|
|
3608
|
+
float eps = 0.001;
|
|
3609
|
+
return normalize(vec3(
|
|
3610
|
+
sdSphere(p + vec3(eps,0,0), 1.0) - sdSphere(p - vec3(eps,0,0), 1.0),
|
|
3611
|
+
sdSphere(p + vec3(0,eps,0), 1.0) - sdSphere(p - vec3(0,eps,0), 1.0),
|
|
3612
|
+
sdSphere(p + vec3(0,0,eps), 1.0) - sdSphere(p - vec3(0,0,eps), 1.0)
|
|
3613
|
+
));
|
|
3614
|
+
}
|
|
3615
|
+
|
|
3616
|
+
float softShadow(vec3 ro, vec3 rd, float mint, float maxt, float k) {
|
|
3617
|
+
float res = 1.0;
|
|
3618
|
+
float t = mint;
|
|
3619
|
+
for (int i = 0; i < 64; i++) {
|
|
3620
|
+
float h = sdSphere(ro + rd * t, 1.0);
|
|
3621
|
+
res = min(res, k * h / t);
|
|
3622
|
+
t += clamp(h, 0.02, 0.1);
|
|
3623
|
+
if (h < 0.001 || t > maxt) break;
|
|
3624
|
+
}
|
|
3625
|
+
return clamp(res, 0.0, 1.0);
|
|
3626
|
+
}
|
|
3627
|
+
|
|
3628
|
+
float ambientOcclusion3D(vec3 p, vec3 n) {
|
|
3629
|
+
float occ = 0.0;
|
|
3630
|
+
float sca = 1.0;
|
|
3631
|
+
for (int i = 0; i < 5; i++) {
|
|
3632
|
+
float h = 0.01 + 0.12 * float(i);
|
|
3633
|
+
float d = sdSphere(p + n * h, 1.0);
|
|
3634
|
+
occ += (h - d) * sca;
|
|
3635
|
+
sca *= 0.95;
|
|
3636
|
+
}
|
|
3637
|
+
return clamp(1.0 - 3.0 * occ, 0.0, 1.0);
|
|
3638
|
+
}
|
|
3639
|
+
`,
|
|
3640
|
+
exports: ["rayMarch", "estimateNormal", "softShadow", "ambientOcclusion3D"],
|
|
3641
|
+
dependencies: ["glsl-sdf-3d"],
|
|
3642
|
+
description: "Raymarching utilities (march, normals, soft shadows, AO).",
|
|
3643
|
+
usage: `### glsl-ray \u2014 Raymarching
|
|
3644
|
+
|
|
3645
|
+
\`\`\`glsl
|
|
3646
|
+
float t = rayMarch(ro, rd, 100.0, 128);
|
|
3647
|
+
if (t < 100.0) {
|
|
3648
|
+
vec3 p = ro + rd * t;
|
|
3649
|
+
vec3 n = estimateNormal(p);
|
|
3650
|
+
float shadow = softShadow(p, lightDir, 0.02, 10.0, 8.0);
|
|
3651
|
+
}
|
|
3652
|
+
\`\`\`
|
|
3653
|
+
`
|
|
3654
|
+
};
|
|
3655
|
+
var ray_default = glslRay;
|
|
3656
|
+
|
|
3657
|
+
// src/components/glsl/post.ts
|
|
3658
|
+
var glslPost = {
|
|
3659
|
+
name: "glsl-post",
|
|
3660
|
+
version: "1.0.0",
|
|
3661
|
+
category: "imaging",
|
|
3662
|
+
target: "glsl",
|
|
3663
|
+
renderers: [],
|
|
3664
|
+
code: `float vignette(vec2 uv, float intensity) {
|
|
3665
|
+
vec2 d = uv - 0.5;
|
|
3666
|
+
return 1.0 - dot(d, d) * intensity;
|
|
3667
|
+
}
|
|
3668
|
+
|
|
3669
|
+
vec3 chromaticAberration(sampler2D tex, vec2 uv, float offset) {
|
|
3670
|
+
float r = texture2D(tex, uv + vec2(offset, 0.0)).r;
|
|
3671
|
+
float g = texture2D(tex, uv).g;
|
|
3672
|
+
float b = texture2D(tex, uv - vec2(offset, 0.0)).b;
|
|
3673
|
+
return vec3(r, g, b);
|
|
3674
|
+
}
|
|
3675
|
+
|
|
3676
|
+
float filmGrain(vec2 uv, float time, float intensity) {
|
|
3677
|
+
return (hash(uv * 1000.0 + time) - 0.5) * intensity;
|
|
3678
|
+
}
|
|
3679
|
+
|
|
3680
|
+
vec3 bloom(sampler2D tex, vec2 uv, float threshold, float intensity) {
|
|
3681
|
+
vec3 col = texture2D(tex, uv).rgb;
|
|
3682
|
+
vec3 bright = max(col - vec3(threshold), vec3(0.0));
|
|
3683
|
+
vec3 blur = vec3(0.0);
|
|
3684
|
+
for (int i = -2; i <= 2; i++)
|
|
3685
|
+
for (int j = -2; j <= 2; j++)
|
|
3686
|
+
blur += max(texture2D(tex, uv + vec2(float(i), float(j)) * 0.003).rgb - vec3(threshold), vec3(0.0));
|
|
3687
|
+
blur /= 25.0;
|
|
3688
|
+
return col + blur * intensity;
|
|
3689
|
+
}
|
|
3690
|
+
|
|
3691
|
+
vec3 sharpen(sampler2D tex, vec2 uv, float strength) {
|
|
3692
|
+
vec2 px = vec2(1.0) / vec2(textureSize(tex, 0));
|
|
3693
|
+
vec3 col = texture2D(tex, uv).rgb * (1.0 + 4.0 * strength);
|
|
3694
|
+
col -= texture2D(tex, uv + vec2(px.x, 0.0)).rgb * strength;
|
|
3695
|
+
col -= texture2D(tex, uv - vec2(px.x, 0.0)).rgb * strength;
|
|
3696
|
+
col -= texture2D(tex, uv + vec2(0.0, px.y)).rgb * strength;
|
|
3697
|
+
col -= texture2D(tex, uv - vec2(0.0, px.y)).rgb * strength;
|
|
3698
|
+
return col;
|
|
3699
|
+
}
|
|
3700
|
+
`,
|
|
3701
|
+
exports: ["vignette", "chromaticAberration", "filmGrain", "bloom", "sharpen"],
|
|
3702
|
+
dependencies: ["glsl-noise"],
|
|
3703
|
+
description: "Post-processing effects (vignette, chromatic aberration, grain, bloom).",
|
|
3704
|
+
usage: `### glsl-post \u2014 Post Processing
|
|
3705
|
+
|
|
3706
|
+
\`\`\`glsl
|
|
3707
|
+
color *= vignette(uv, 2.0);
|
|
3708
|
+
color += filmGrain(uv, u_time, 0.05);
|
|
3709
|
+
color = bloom(tex, uv, 0.8, 1.5);
|
|
3710
|
+
\`\`\`
|
|
3711
|
+
`
|
|
3712
|
+
};
|
|
3713
|
+
var post_default = glslPost;
|
|
3714
|
+
|
|
3715
|
+
// src/components/glsl/shape.ts
|
|
3716
|
+
var glslShape = {
|
|
3717
|
+
name: "glsl-shape",
|
|
3718
|
+
version: "1.0.0",
|
|
3719
|
+
category: "geometry",
|
|
3720
|
+
target: "glsl",
|
|
3721
|
+
renderers: [],
|
|
3722
|
+
code: `float polygon(vec2 p, int sides, float radius) {
|
|
3723
|
+
float a = atan(p.y, p.x);
|
|
3724
|
+
float seg = 6.28318 / float(sides);
|
|
3725
|
+
float d = cos(floor(0.5 + a / seg) * seg - a) * length(p);
|
|
3726
|
+
return d - radius;
|
|
3727
|
+
}
|
|
3728
|
+
|
|
3729
|
+
float star(vec2 p, int points, float outer, float inner) {
|
|
3730
|
+
float a = atan(p.y, p.x);
|
|
3731
|
+
float seg = 3.14159 / float(points);
|
|
3732
|
+
a = mod(a, 2.0 * seg) - seg;
|
|
3733
|
+
float r = length(p);
|
|
3734
|
+
float d1 = r * cos(a) - outer;
|
|
3735
|
+
float d2 = r * cos(a - seg) - inner;
|
|
3736
|
+
return max(d1, d2);
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3739
|
+
float roundedRect(vec2 p, vec2 size, float radius) {
|
|
3740
|
+
vec2 d = abs(p) - size + radius;
|
|
3741
|
+
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) - radius;
|
|
3742
|
+
}
|
|
3743
|
+
|
|
3744
|
+
float ring(vec2 p, float radius, float thickness) {
|
|
3745
|
+
return abs(length(p) - radius) - thickness;
|
|
3746
|
+
}
|
|
3747
|
+
|
|
3748
|
+
float arc(vec2 p, float radius, float angle, float thickness) {
|
|
3749
|
+
float a = atan(p.y, p.x);
|
|
3750
|
+
float ha = angle * 0.5;
|
|
3751
|
+
float d = abs(length(p) - radius) - thickness;
|
|
3752
|
+
float angDist = abs(mod(a + 3.14159, 6.28318) - 3.14159);
|
|
3753
|
+
return max(d, angDist - ha);
|
|
3754
|
+
}
|
|
3755
|
+
|
|
3756
|
+
float line(vec2 p, vec2 a, vec2 b, float thickness) {
|
|
3757
|
+
vec2 pa = p - a, ba = b - a;
|
|
3758
|
+
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
|
3759
|
+
return length(pa - ba * h) - thickness;
|
|
3760
|
+
}
|
|
3761
|
+
`,
|
|
3762
|
+
exports: ["polygon", "star", "roundedRect", "ring", "arc", "line"],
|
|
3763
|
+
dependencies: ["glsl-sdf"],
|
|
3764
|
+
description: "2D shape rendering via SDF (polygon, star, rounded rect, ring).",
|
|
3765
|
+
usage: `### glsl-shape \u2014 2D Shapes
|
|
3766
|
+
|
|
3767
|
+
\`\`\`glsl
|
|
3768
|
+
float d = polygon(uv - 0.5, 6, 0.3);
|
|
3769
|
+
d = min(d, star(uv - vec2(0.7, 0.5), 5, 0.2, 0.1));
|
|
3770
|
+
d = min(d, roundedRect(uv - vec2(0.3, 0.7), vec2(0.1), 0.02));
|
|
3771
|
+
vec3 col = mix(vec3(1), vec3(0), smoothstep(0.0, 0.01, d));
|
|
3772
|
+
\`\`\`
|
|
3773
|
+
`
|
|
3774
|
+
};
|
|
3775
|
+
var shape_default2 = glslShape;
|
|
3776
|
+
|
|
3777
|
+
// src/components/glsl/domain.ts
|
|
3778
|
+
var glslDomain = {
|
|
3779
|
+
name: "glsl-domain",
|
|
3780
|
+
version: "1.0.0",
|
|
3781
|
+
category: "transform",
|
|
3782
|
+
target: "glsl",
|
|
3783
|
+
renderers: [],
|
|
3784
|
+
code: `vec2 domainWarp(vec2 p, float strength) {
|
|
3785
|
+
float n1 = noise(p);
|
|
3786
|
+
float n2 = noise(p + vec2(5.2, 1.3));
|
|
3787
|
+
return p + vec2(n1, n2) * strength;
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
vec2 domainRepeat(vec2 p, vec2 period) {
|
|
3791
|
+
return mod(p + period * 0.5, period) - period * 0.5;
|
|
3792
|
+
}
|
|
3793
|
+
|
|
3794
|
+
vec2 domainTwist(vec2 p, float amount) {
|
|
3795
|
+
float angle = p.y * amount;
|
|
3796
|
+
float c = cos(angle), s = sin(angle);
|
|
3797
|
+
return vec2(p.x * c - p.y * s, p.x * s + p.y * c);
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3800
|
+
vec2 domainFold(vec2 p, vec2 axis) {
|
|
3801
|
+
float d = dot(p, normalize(axis));
|
|
3802
|
+
if (d < 0.0) p -= 2.0 * d * normalize(axis);
|
|
3803
|
+
return p;
|
|
3804
|
+
}
|
|
3805
|
+
`,
|
|
3806
|
+
exports: ["domainWarp", "domainRepeat", "domainTwist", "domainFold"],
|
|
3807
|
+
dependencies: ["glsl-noise"],
|
|
3808
|
+
description: "Domain manipulation (warp, repeat, twist, fold).",
|
|
3809
|
+
usage: `### glsl-domain \u2014 Domain Manipulation
|
|
3810
|
+
|
|
3811
|
+
\`\`\`glsl
|
|
3812
|
+
vec2 p = domainWarp(uv * 5.0, 0.3);
|
|
3813
|
+
p = domainRepeat(p, vec2(2.0));
|
|
3814
|
+
p = domainTwist(p, 1.5);
|
|
3815
|
+
\`\`\`
|
|
3816
|
+
`
|
|
3817
|
+
};
|
|
3818
|
+
var domain_default = glslDomain;
|
|
3819
|
+
|
|
3820
|
+
// src/components/glsl/gradient.ts
|
|
3821
|
+
var glslGradient = {
|
|
3822
|
+
name: "glsl-gradient",
|
|
3823
|
+
version: "1.0.0",
|
|
3824
|
+
category: "color",
|
|
3825
|
+
target: "glsl",
|
|
3826
|
+
renderers: [],
|
|
3827
|
+
code: `vec3 linearGradient(vec2 uv, vec3 c1, vec3 c2, float angle) {
|
|
3828
|
+
float c = cos(angle), s = sin(angle);
|
|
3829
|
+
float t = clamp(uv.x * c + uv.y * s, 0.0, 1.0);
|
|
3830
|
+
return mix(c1, c2, t);
|
|
3831
|
+
}
|
|
3832
|
+
|
|
3833
|
+
vec3 radialGradient(vec2 uv, vec3 c1, vec3 c2, vec2 center, float radius) {
|
|
3834
|
+
float t = clamp(length(uv - center) / radius, 0.0, 1.0);
|
|
3835
|
+
return mix(c1, c2, t);
|
|
3836
|
+
}
|
|
3837
|
+
|
|
3838
|
+
vec3 angularGradient(vec2 uv, vec3 c1, vec3 c2, vec2 center) {
|
|
3839
|
+
float angle = atan(uv.y - center.y, uv.x - center.x);
|
|
3840
|
+
float t = (angle + 3.14159) / 6.28318;
|
|
3841
|
+
return mix(c1, c2, t);
|
|
3842
|
+
}
|
|
3843
|
+
|
|
3844
|
+
vec3 conicGradient(vec2 uv, vec3 colors[4], vec2 center) {
|
|
3845
|
+
float angle = atan(uv.y - center.y, uv.x - center.x);
|
|
3846
|
+
float t = (angle + 3.14159) / 6.28318;
|
|
3847
|
+
float segment = t * 4.0;
|
|
3848
|
+
int i = int(floor(segment));
|
|
3849
|
+
float f = fract(segment);
|
|
3850
|
+
if (i >= 3) return mix(colors[3], colors[0], f);
|
|
3851
|
+
return mix(colors[i], colors[i + 1], f);
|
|
3852
|
+
}
|
|
3853
|
+
|
|
3854
|
+
vec3 paletteGradient(float t, vec3 a, vec3 b, vec3 c, vec3 d) {
|
|
3855
|
+
return a + b * cos(6.28318 * (c * t + d));
|
|
3856
|
+
}
|
|
3857
|
+
`,
|
|
3858
|
+
exports: ["linearGradient", "radialGradient", "angularGradient", "conicGradient", "paletteGradient"],
|
|
3859
|
+
dependencies: [],
|
|
3860
|
+
description: "Gradient generation (linear, radial, angular, palette).",
|
|
3861
|
+
usage: `### glsl-gradient \u2014 Gradients
|
|
3862
|
+
|
|
3863
|
+
\`\`\`glsl
|
|
3864
|
+
vec3 g = linearGradient(uv, vec3(1,0,0), vec3(0,0,1), 0.0);
|
|
3865
|
+
vec3 r = radialGradient(uv, vec3(1), vec3(0), vec2(0.5), 0.5);
|
|
3866
|
+
// Iq-style cosine palette
|
|
3867
|
+
vec3 p = paletteGradient(t, vec3(0.5), vec3(0.5), vec3(1), vec3(0,0.33,0.67));
|
|
3868
|
+
\`\`\`
|
|
3869
|
+
`
|
|
3870
|
+
};
|
|
3871
|
+
var gradient_default = glslGradient;
|
|
3872
|
+
|
|
3873
|
+
// src/registry.ts
|
|
3874
|
+
var COMPONENT_REGISTRY = Object.fromEntries(
|
|
3875
|
+
[...Object.values(js_exports), ...Object.values(glsl_exports)].map((c) => [c.name, c])
|
|
3876
|
+
);
|
|
3877
|
+
|
|
3878
|
+
// src/resolver.ts
|
|
3879
|
+
var RENDERER_TARGET = {
|
|
3880
|
+
p5: "js",
|
|
3881
|
+
three: "js",
|
|
3882
|
+
canvas2d: "js",
|
|
3883
|
+
svg: "js",
|
|
3884
|
+
glsl: "glsl"
|
|
3885
|
+
};
|
|
3886
|
+
function resolveComponents(components, renderer) {
|
|
3887
|
+
const target = RENDERER_TARGET[renderer];
|
|
3888
|
+
const allNames = /* @__PURE__ */ new Set();
|
|
3889
|
+
const stack = Object.keys(components);
|
|
3890
|
+
while (stack.length > 0) {
|
|
3891
|
+
const name = stack.pop();
|
|
3892
|
+
if (allNames.has(name)) continue;
|
|
3893
|
+
const entry = COMPONENT_REGISTRY[name];
|
|
3894
|
+
if (!entry) {
|
|
3895
|
+
throw new Error(`Unknown component: "${name}"`);
|
|
3896
|
+
}
|
|
3897
|
+
if (entry.target !== target) {
|
|
3898
|
+
throw new Error(
|
|
3899
|
+
`Component "${name}" has target "${entry.target}" but renderer "${renderer}" requires target "${target}"`
|
|
3900
|
+
);
|
|
3901
|
+
}
|
|
3902
|
+
if (entry.renderers.length > 0 && !entry.renderers.includes(renderer)) {
|
|
3903
|
+
throw new Error(
|
|
3904
|
+
`Component "${name}" is not compatible with renderer "${renderer}". Compatible: ${entry.renderers.join(", ")}`
|
|
3905
|
+
);
|
|
3906
|
+
}
|
|
3907
|
+
allNames.add(name);
|
|
3908
|
+
for (const dep of entry.dependencies) {
|
|
3909
|
+
if (!allNames.has(dep)) {
|
|
3910
|
+
stack.push(dep);
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
const sorted = [];
|
|
3915
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3916
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
3917
|
+
function visit(name) {
|
|
3918
|
+
if (visited.has(name)) return;
|
|
3919
|
+
if (visiting.has(name)) {
|
|
3920
|
+
throw new Error(`Circular dependency detected involving component "${name}"`);
|
|
3921
|
+
}
|
|
3922
|
+
visiting.add(name);
|
|
3923
|
+
const entry = COMPONENT_REGISTRY[name];
|
|
3924
|
+
for (const dep of entry.dependencies) {
|
|
3925
|
+
if (allNames.has(dep)) {
|
|
3926
|
+
visit(dep);
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3929
|
+
visiting.delete(name);
|
|
3930
|
+
visited.add(name);
|
|
3931
|
+
sorted.push(name);
|
|
3932
|
+
}
|
|
3933
|
+
for (const name of allNames) {
|
|
3934
|
+
visit(name);
|
|
3935
|
+
}
|
|
3936
|
+
const exportNames = /* @__PURE__ */ new Map();
|
|
3937
|
+
for (const name of sorted) {
|
|
3938
|
+
const entry = COMPONENT_REGISTRY[name];
|
|
3939
|
+
for (const exp of entry.exports) {
|
|
3940
|
+
const existing = exportNames.get(exp);
|
|
3941
|
+
if (existing) {
|
|
3942
|
+
throw new Error(
|
|
3943
|
+
`Export collision: "${exp}" is exported by both "${existing}" and "${name}"`
|
|
3944
|
+
);
|
|
3945
|
+
}
|
|
3946
|
+
exportNames.set(exp, name);
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3949
|
+
return sorted.map((name) => {
|
|
3950
|
+
const entry = COMPONENT_REGISTRY[name];
|
|
3951
|
+
return {
|
|
3952
|
+
name: entry.name,
|
|
3953
|
+
version: entry.version,
|
|
3954
|
+
code: entry.code,
|
|
3955
|
+
exports: entry.exports
|
|
3956
|
+
};
|
|
3957
|
+
});
|
|
3958
|
+
}
|
|
3959
|
+
export {
|
|
3960
|
+
COMPONENT_REGISTRY,
|
|
3961
|
+
resolveComponents
|
|
3962
|
+
};
|
|
3963
|
+
//# sourceMappingURL=index.js.map
|