tela.js 1.0.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/.eslintrc.yml +8 -0
- package/LICENSE +201 -0
- package/README.md +54 -0
- package/assets/bunny.obj +7474 -0
- package/assets/expand.svg +1 -0
- package/assets/great.jpg +0 -0
- package/assets/kakashi.jpg +0 -0
- package/assets/spot.obj +11999 -0
- package/assets/spot.png +0 -0
- package/assets/torus.obj +3137 -0
- package/assets/x.svg +1 -0
- package/bun.lockb +0 -0
- package/bundle.js +39 -0
- package/dist/node/index.js +37048 -0
- package/dist/web/index.js +1511 -0
- package/index.css +129 -0
- package/index.html +19 -0
- package/index.js +534 -0
- package/package.json +40 -0
- package/src/Animation/Animation.js +61 -0
- package/src/Box/Box.js +105 -0
- package/src/Camera/Camera.js +133 -0
- package/src/Canvas/Canvas.js +203 -0
- package/src/Canvas/README.md +83 -0
- package/src/Color/Color.js +77 -0
- package/src/DomBuilder/DomBuilder.js +126 -0
- package/src/IO/IO.js +120 -0
- package/src/Image/Image.js +138 -0
- package/src/Image/README.md +33 -0
- package/src/Monads/Monads.js +28 -0
- package/src/Ray/Ray.js +7 -0
- package/src/Scene/Mesh.js +103 -0
- package/src/Scene/NaiveScene.js +77 -0
- package/src/Scene/Point.js +109 -0
- package/src/Scene/PointCloud.js +51 -0
- package/src/Scene/Scene.js +200 -0
- package/src/Stream/Stream.js +10 -0
- package/src/Utils/Constants.js +1 -0
- package/src/Utils/Math.js +65 -0
- package/src/Utils/Utils.js +39 -0
- package/src/Vector/Vector.js +495 -0
- package/src/index.js +32 -0
- package/src/index.node.js +5 -0
- package/test/node/amazing_shader.js +56 -0
- package/test/node/bunny.js +55 -0
- package/test/node/bunny_parallel.js +102 -0
- package/test/node/image2rgb.js +57 -0
- package/test/node/image_test.js +38 -0
- package/test/node/lorentz.js +0 -0
- package/test/web/amazing_shader.js +60 -0
- package/test/web/amazing_shader_2.js +54 -0
- package/test/web/bunny.js +72 -0
- package/test/web/image2rgb.js +77 -0
- package/test/web/interactive_wave.js +108 -0
- package/test/web/lorenz.js +60 -0
- package/test/web/mandelbrot.js +59 -0
- package/test/web/rotating_grid.js +62 -0
- package/test/web/signed_bunny.js +139 -0
- package/test/web/signed_distance.js +95 -0
- package/test/web/simple_animation.js +39 -0
- package/test/web/simple_shader.js +14 -0
- package/test/web/six_spheres.js +102 -0
- package/test/web/wave_equation.js +93 -0
- package/vs-monaco/package/LICENSE +21 -0
- package/vs-monaco/package/ThirdPartyNotices.txt +448 -0
- package/vs-monaco/package/min/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.de.js +8 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.es.js +8 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.fr.js +8 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.it.js +8 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.ja.js +8 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.js +8 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.ko.js +8 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.ru.js +8 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.zh-cn.js +8 -0
- package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.zh-tw.js +8 -0
- package/vs-monaco/package/min/vs/base/worker/workerMain.js +27 -0
- package/vs-monaco/package/min/vs/basic-languages/abap/abap.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/apex/apex.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/azcli/azcli.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/bat/bat.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/bicep/bicep.js +11 -0
- package/vs-monaco/package/min/vs/basic-languages/cameligo/cameligo.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/clojure/clojure.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/coffee/coffee.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/cpp/cpp.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/csharp/csharp.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/csp/csp.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/css/css.js +12 -0
- package/vs-monaco/package/min/vs/basic-languages/cypher/cypher.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/dart/dart.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/dockerfile/dockerfile.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/ecl/ecl.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/elixir/elixir.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/flow9/flow9.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/freemarker2/freemarker2.js +12 -0
- package/vs-monaco/package/min/vs/basic-languages/fsharp/fsharp.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/go/go.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/graphql/graphql.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/handlebars/handlebars.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/hcl/hcl.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/html/html.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/ini/ini.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/java/java.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/javascript/javascript.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/julia/julia.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/kotlin/kotlin.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/less/less.js +11 -0
- package/vs-monaco/package/min/vs/basic-languages/lexon/lexon.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/liquid/liquid.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/lua/lua.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/m3/m3.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/markdown/markdown.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/mdx/mdx.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/mips/mips.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/msdax/msdax.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/mysql/mysql.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/objective-c/objective-c.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/pascal/pascal.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/pascaligo/pascaligo.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/perl/perl.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/pgsql/pgsql.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/php/php.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/pla/pla.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/postiats/postiats.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/powerquery/powerquery.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/powershell/powershell.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/protobuf/protobuf.js +11 -0
- package/vs-monaco/package/min/vs/basic-languages/pug/pug.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/python/python.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/qsharp/qsharp.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/r/r.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/razor/razor.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/redis/redis.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/redshift/redshift.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/restructuredtext/restructuredtext.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/ruby/ruby.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/rust/rust.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/sb/sb.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/scala/scala.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/scheme/scheme.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/scss/scss.js +12 -0
- package/vs-monaco/package/min/vs/basic-languages/shell/shell.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/solidity/solidity.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/sophia/sophia.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/sparql/sparql.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/sql/sql.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/st/st.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/swift/swift.js +13 -0
- package/vs-monaco/package/min/vs/basic-languages/systemverilog/systemverilog.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/tcl/tcl.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/twig/twig.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/typescript/typescript.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/vb/vb.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/wgsl/wgsl.js +307 -0
- package/vs-monaco/package/min/vs/basic-languages/xml/xml.js +10 -0
- package/vs-monaco/package/min/vs/basic-languages/yaml/yaml.js +10 -0
- package/vs-monaco/package/min/vs/editor/editor.main.css +6 -0
- package/vs-monaco/package/min/vs/editor/editor.main.js +745 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.de.js +31 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.es.js +31 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.fr.js +29 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.it.js +29 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.ja.js +31 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.js +29 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.ko.js +29 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.ru.js +31 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.zh-cn.js +31 -0
- package/vs-monaco/package/min/vs/editor/editor.main.nls.zh-tw.js +29 -0
- package/vs-monaco/package/min/vs/language/css/cssMode.js +13 -0
- package/vs-monaco/package/min/vs/language/css/cssWorker.js +81 -0
- package/vs-monaco/package/min/vs/language/html/htmlMode.js +13 -0
- package/vs-monaco/package/min/vs/language/html/htmlWorker.js +453 -0
- package/vs-monaco/package/min/vs/language/json/jsonMode.js +15 -0
- package/vs-monaco/package/min/vs/language/json/jsonWorker.js +36 -0
- package/vs-monaco/package/min/vs/language/typescript/tsMode.js +20 -0
- package/vs-monaco/package/min/vs/language/typescript/tsWorker.js +37016 -0
- package/vs-monaco/package/min/vs/loader.js +11 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { writeFileSync, unlinkSync } from "fs";
|
|
2
|
+
import { IO } from "../../dist/node/index.js";
|
|
3
|
+
import { exec, execSync, spawn } from "child_process";
|
|
4
|
+
import path from "path";
|
|
5
|
+
const { createPPMFromFromImage } = IO;
|
|
6
|
+
|
|
7
|
+
export async function measureTime(lambda) {
|
|
8
|
+
const t = performance.now();
|
|
9
|
+
await lambda()
|
|
10
|
+
return 1e-3 * (performance.now() - t);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
const fileName = "bunny_parallel";
|
|
15
|
+
const deltaT = 0.04; //seconds per frame
|
|
16
|
+
const maxT = 10; // seconds
|
|
17
|
+
const numOfFrames = Math.floor(maxT / deltaT);
|
|
18
|
+
const FPS = Math.floor(1 / deltaT);
|
|
19
|
+
const parallelStreams = 20;
|
|
20
|
+
const partitions = [...Array(numOfFrames)].map((_,i) => i).reduce((e,x) => {
|
|
21
|
+
const index = x % parallelStreams;
|
|
22
|
+
if(!e[index]) e[index] = [];
|
|
23
|
+
e[index].push(x);
|
|
24
|
+
return e;
|
|
25
|
+
}, {})
|
|
26
|
+
const imageProducers = Object.values(partitions).map(partition => {
|
|
27
|
+
return (
|
|
28
|
+
`
|
|
29
|
+
import { Color, Image, Stream, IO, Utils, Mesh, Vec3, Scene, Camera } from "./dist/node/index.js";
|
|
30
|
+
import { readFileSync, writeFileSync } from "fs"
|
|
31
|
+
|
|
32
|
+
${createPPMFromFromImage.toString().replaceAll("function", "function createPPMFromFromImage")}
|
|
33
|
+
|
|
34
|
+
(() => {
|
|
35
|
+
const width = 640;
|
|
36
|
+
const height = 480;
|
|
37
|
+
|
|
38
|
+
const scene = new Scene()
|
|
39
|
+
const camera = new Camera({ sphericalCoords: Vec3(5, 0, 0) });
|
|
40
|
+
const stanfordBunnyObj = readFileSync("./assets/bunny.obj", { encoding: "utf-8" });
|
|
41
|
+
let bunnyMesh = Mesh.readObj(stanfordBunnyObj);
|
|
42
|
+
const bunnyBox = bunnyMesh.getBoundingBox();
|
|
43
|
+
bunnyMesh = bunnyMesh
|
|
44
|
+
.mapVertices(v => v.sub(bunnyBox.min).div(bunnyBox.diagonal).scale(2).sub(Vec3(1, 1, 1)))
|
|
45
|
+
.mapVertices(v => Vec3(-v.y, v.x, v.z))
|
|
46
|
+
.mapVertices(v => Vec3(v.z, v.y, -v.x))
|
|
47
|
+
.mapColors(v => Color.ofRGB(...v.map(x => Math.max(0, Math.min(1, 0.5 * (x + 1)))).toArray()));
|
|
48
|
+
scene.add(...bunnyMesh.asPoints("bunny", 0.05));
|
|
49
|
+
const deltaT = ${deltaT};
|
|
50
|
+
const partitionIndices = [${partition.toString()}];
|
|
51
|
+
for(let i = 0; i < partitionIndices.length; i++) {
|
|
52
|
+
const j = partitionIndices[i];
|
|
53
|
+
const time = deltaT * j;
|
|
54
|
+
const theta = Math.PI / 4 * time;
|
|
55
|
+
camera.sphericalCoords = Vec3(camera.sphericalCoords.get(0), theta, 0);
|
|
56
|
+
camera.orbit();
|
|
57
|
+
const image = camera.sceneShot(scene).to(Image.ofSize(width, height));
|
|
58
|
+
writeFileSync(\`${fileName}_\${j}.ppm\`, createPPMFromFromImage(image));
|
|
59
|
+
console.log("Image created", j);
|
|
60
|
+
}
|
|
61
|
+
return 0;
|
|
62
|
+
})();
|
|
63
|
+
`
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
(async () => {
|
|
68
|
+
const time = await measureTime(
|
|
69
|
+
() => {
|
|
70
|
+
const promises = [...Array(parallelStreams)].map((_, i) => {
|
|
71
|
+
const spawnFile = "ParallelRender_" + i + ".js";
|
|
72
|
+
const spawnFilePath = path.join("./", spawnFile);
|
|
73
|
+
writeFileSync(spawnFilePath, imageProducers[i]);
|
|
74
|
+
return new Promise(resolve => {
|
|
75
|
+
exec(`bun ${spawnFilePath.toString()}`, () => {
|
|
76
|
+
resolve();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
return Promise
|
|
81
|
+
.all(promises)
|
|
82
|
+
.then(() => {
|
|
83
|
+
return new Promise(resolve => exec(
|
|
84
|
+
`ffmpeg -framerate ${FPS} -i ${fileName}_%d.ppm ${fileName}.mp4`,
|
|
85
|
+
() => resolve()
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
})
|
|
89
|
+
.then(() => {
|
|
90
|
+
for (let i = 0; i < numOfFrames; i++) {
|
|
91
|
+
unlinkSync(`${fileName}_${i}.ppm`);
|
|
92
|
+
}
|
|
93
|
+
for (let i = 0; i < parallelStreams; i++) {
|
|
94
|
+
unlinkSync(`ParallelRender_${i}.js`);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
console.log(
|
|
99
|
+
"Video created in: ",
|
|
100
|
+
time
|
|
101
|
+
)
|
|
102
|
+
})()
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Color, Image, Stream, IO, Utils, Mesh, Vec3, Scene, NaiveScene, Camera, Point } from "../../dist/node/index.js";
|
|
2
|
+
const { saveStreamToFile } = IO;
|
|
3
|
+
const { measureTimeWithResult, measureTime } = Utils;
|
|
4
|
+
|
|
5
|
+
(async () => {
|
|
6
|
+
const width = 640;
|
|
7
|
+
const height = 480;
|
|
8
|
+
|
|
9
|
+
// scene
|
|
10
|
+
const scene = new NaiveScene();
|
|
11
|
+
const camera = new Camera({ sphericalCoords: Vec3(4, 0, 0) });
|
|
12
|
+
const img = await Image.ofUrl("./assets/kakashi.jpg");
|
|
13
|
+
const grid = [...Array(img.width * img.height)]
|
|
14
|
+
.map((_, k) => {
|
|
15
|
+
const i = Math.floor(k / img.width);
|
|
16
|
+
const j = k % img.width;
|
|
17
|
+
const x = j;
|
|
18
|
+
const y = i;
|
|
19
|
+
return Point
|
|
20
|
+
.builder()
|
|
21
|
+
.name(`pxl_${k}`)
|
|
22
|
+
.radius(0.01)
|
|
23
|
+
.position(
|
|
24
|
+
Vec3(0, x / img.width, y / img.height)
|
|
25
|
+
)
|
|
26
|
+
.color(img.getPxl(x, y))
|
|
27
|
+
.build();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
console.log("Add objects to scene", measureTime(() => scene.addList(grid)));
|
|
31
|
+
const imageStream = new Stream(
|
|
32
|
+
{ time: 0, image: camera.reverseShot(scene).to(Image.ofSize(width, height)) },
|
|
33
|
+
({ time, image }) => {
|
|
34
|
+
const dt = 0.04; // 25 FPS
|
|
35
|
+
const theta = Math.PI / 4 * time;
|
|
36
|
+
camera.sphericalCoords = Vec3(camera.sphericalCoords.get(0), theta, Math.PI / 4);
|
|
37
|
+
camera.orbit();
|
|
38
|
+
const { result: newImage, time: t } = measureTimeWithResult(() => camera.reverseShot(scene).to(image));
|
|
39
|
+
console.log(`Image took ${t}s`);
|
|
40
|
+
return {
|
|
41
|
+
time: time + dt,
|
|
42
|
+
image: newImage
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
console.log(
|
|
48
|
+
"Video created in: ",
|
|
49
|
+
measureTime(() => {
|
|
50
|
+
saveStreamToFile(
|
|
51
|
+
"./kakashi.mp4",
|
|
52
|
+
imageStream,
|
|
53
|
+
{ fps: 25 }
|
|
54
|
+
).until(({ time }) => time < 10);
|
|
55
|
+
})
|
|
56
|
+
)
|
|
57
|
+
})()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Color, Image, Stream, IO, Utils } from "../../dist/node/index.js";
|
|
2
|
+
|
|
3
|
+
const { measureTime } = Utils;
|
|
4
|
+
const { saveImageToFile, saveStreamToFile } = IO;
|
|
5
|
+
|
|
6
|
+
const width = 640;
|
|
7
|
+
const height = 480;
|
|
8
|
+
const step = (threshold) => (x) => x < threshold ? 0 : 1;
|
|
9
|
+
const mod = (x) => (n) => ((x % n) + n) % n;
|
|
10
|
+
|
|
11
|
+
saveImageToFile(
|
|
12
|
+
"./test0.png",
|
|
13
|
+
Image.ofSize(width, height)
|
|
14
|
+
.map((x, y) => {
|
|
15
|
+
let u = x / width;
|
|
16
|
+
let v = y / height;
|
|
17
|
+
return Color.ofRGB((2 * u) % 1, (2 * v) % 1, 0);
|
|
18
|
+
})
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
saveImageToFile(
|
|
22
|
+
"./test1.jpeg",
|
|
23
|
+
Image.ofSize(width, height)
|
|
24
|
+
.map((x, y) => {
|
|
25
|
+
let u = x / (width - 1);
|
|
26
|
+
let v = y / (height - 1);
|
|
27
|
+
const grid = 10;
|
|
28
|
+
u *= grid;
|
|
29
|
+
v *= grid;
|
|
30
|
+
const t = 1;
|
|
31
|
+
const u_t = Math.cos(t) * u + Math.sin(t) * v;
|
|
32
|
+
const v_t = -Math.sin(t) * u + Math.cos(t) * v;
|
|
33
|
+
const color =
|
|
34
|
+
(1 - step(0.95)(mod(u_t)(1))) * (1 - step(0.95)(mod(v_t)(1)));
|
|
35
|
+
return Color.ofRGB(color, color, color);
|
|
36
|
+
})
|
|
37
|
+
)
|
|
38
|
+
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Port from https://www.shadertoy.com/view/mtyGWy
|
|
2
|
+
(canvas, fps) => {
|
|
3
|
+
// resize incoming canvas:Canvas object.
|
|
4
|
+
const width = 640 / 2;
|
|
5
|
+
const height = 480 / 2;
|
|
6
|
+
canvas.resize(width, height);
|
|
7
|
+
// utils
|
|
8
|
+
const T = 20;
|
|
9
|
+
function palette(t) {
|
|
10
|
+
let a = [0.5, 0.5, 0.5];
|
|
11
|
+
let b = [0.5, 0.5, 0.5];
|
|
12
|
+
let c = [1.0, 1.0, 1.0];
|
|
13
|
+
let d = [0.263, 0.416, 0.557];
|
|
14
|
+
return [a[0] + b[0] * Math.cos(6.28318 * (c[0] * t + d[0])), a[1] + b[1] * Math.cos(6.28318 * (c[1] * t + d[1])), a[2] + b[2] * Math.cos(6.28318 * (c[2] * t + d[2]))];
|
|
15
|
+
}
|
|
16
|
+
Animation
|
|
17
|
+
.builder()
|
|
18
|
+
.initialState({
|
|
19
|
+
it: 1,
|
|
20
|
+
time: 0,
|
|
21
|
+
oldT: new Date().getTime(),
|
|
22
|
+
})
|
|
23
|
+
.nextState(({
|
|
24
|
+
it,
|
|
25
|
+
time,
|
|
26
|
+
oldT,
|
|
27
|
+
}) => {
|
|
28
|
+
const newT = new Date().getTime();
|
|
29
|
+
const dt = (newT - oldT) * 1e-3;
|
|
30
|
+
fps(dt, it);
|
|
31
|
+
canvas.map((x, y) => {
|
|
32
|
+
let u = (2 * x - width) / height
|
|
33
|
+
let v = (2 * y - height) / height;
|
|
34
|
+
const u0 = u;
|
|
35
|
+
const v0 = v;
|
|
36
|
+
let finalColor = [0, 0, 0]
|
|
37
|
+
for (let i = 0; i < 4; i++) {
|
|
38
|
+
u = (u * 1.5 - Math.floor(u * 1.5)) - 0.5;
|
|
39
|
+
v = (v * 1.5 - Math.floor(v * 1.5)) - 0.5;
|
|
40
|
+
const d0 = -Math.sqrt(u0 * u0 + v0 * v0);
|
|
41
|
+
let d = Math.sqrt(u * u + v * v) * Math.exp(d0);
|
|
42
|
+
const col = palette(d0 + i * 0.4 + time * 0.4);
|
|
43
|
+
d = Math.sin(d * 8 + time) / 8;
|
|
44
|
+
d = Math.abs(d);
|
|
45
|
+
d = Math.pow(0.01 / d, 1.2);
|
|
46
|
+
|
|
47
|
+
finalColor = [finalColor[0] + col[0] * d, finalColor[1] + col[1] * d, finalColor[2] + col[2] * d]
|
|
48
|
+
}
|
|
49
|
+
return Color.ofRGB(finalColor[0], finalColor[1], finalColor[2]);
|
|
50
|
+
})
|
|
51
|
+
return {
|
|
52
|
+
it: it + 1,
|
|
53
|
+
oldT: newT,
|
|
54
|
+
time: time + dt,
|
|
55
|
+
};
|
|
56
|
+
})
|
|
57
|
+
.while(({ time }) => time <= T)
|
|
58
|
+
.build()
|
|
59
|
+
.play();
|
|
60
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Port from https://www.shadertoy.com/view/XsXXDn
|
|
2
|
+
(canvas, fps) => {
|
|
3
|
+
// resize incoming canvas:Canvas object.
|
|
4
|
+
const width = 640 / 2;
|
|
5
|
+
const height = 480 / 2;
|
|
6
|
+
canvas.resize(width, height);
|
|
7
|
+
|
|
8
|
+
// util variables
|
|
9
|
+
const T = Number.MAX_VALUE;
|
|
10
|
+
const r = Vec2(width, height);
|
|
11
|
+
const mod = (x) => (n) => ((x % n) + n) % n;
|
|
12
|
+
// Using Animation from tela.js
|
|
13
|
+
Animation
|
|
14
|
+
.builder()
|
|
15
|
+
.initialState({
|
|
16
|
+
it: 1,
|
|
17
|
+
time: 0,
|
|
18
|
+
oldT: new Date().getTime(),
|
|
19
|
+
})
|
|
20
|
+
.nextState(({
|
|
21
|
+
it,
|
|
22
|
+
time,
|
|
23
|
+
oldT,
|
|
24
|
+
}) => {
|
|
25
|
+
const newT = new Date().getTime();
|
|
26
|
+
const dt = (newT - oldT) * 1e-3;
|
|
27
|
+
fps(dt, it);
|
|
28
|
+
canvas
|
|
29
|
+
.map((x, y) => {
|
|
30
|
+
let z = time;
|
|
31
|
+
const c = [];
|
|
32
|
+
let l;
|
|
33
|
+
for (let i = 0; i < 3; i++) {
|
|
34
|
+
let p = Vec2(x, y).div(r);
|
|
35
|
+
let uv = p.clone();
|
|
36
|
+
p = p.map(x => x - 0.5);
|
|
37
|
+
p = Vec2(p.x * (r.x / r.y), p.y);
|
|
38
|
+
z += 0.07;
|
|
39
|
+
l = p.length();
|
|
40
|
+
uv = uv.add(p.scale(((Math.sin(z) + 1) * Math.abs(Math.sin(l * 9 - z - z)))).scale(1 / l))
|
|
41
|
+
c[i] = 0.01 / uv.map(x => mod(x)(1) - 0.5).length();
|
|
42
|
+
}
|
|
43
|
+
return Color.ofRGB(...c).scale(1 / l);
|
|
44
|
+
})
|
|
45
|
+
return {
|
|
46
|
+
it: it + 1,
|
|
47
|
+
oldT: newT,
|
|
48
|
+
time: time + dt,
|
|
49
|
+
};
|
|
50
|
+
})
|
|
51
|
+
.while(({ time }) => time <= T)
|
|
52
|
+
.build()
|
|
53
|
+
.play();
|
|
54
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* eslint-disable no-undef */
|
|
2
|
+
async (canvas, fps, logger) => {
|
|
3
|
+
// resize incoming canvas:Canvas object.
|
|
4
|
+
const width = 640;
|
|
5
|
+
const height = 480;
|
|
6
|
+
canvas.resize(width, height);
|
|
7
|
+
// scene
|
|
8
|
+
const scene = new Scene()
|
|
9
|
+
const camera = new Camera({ sphericalCoords: Vec3(5, 0, 0) });
|
|
10
|
+
// mouse handling
|
|
11
|
+
let mousedown = false;
|
|
12
|
+
let mouse = Vec2();
|
|
13
|
+
canvas.onMouseDown((x, y) => {
|
|
14
|
+
mousedown = true;
|
|
15
|
+
mouse = Vec2(x, y);
|
|
16
|
+
})
|
|
17
|
+
canvas.onMouseUp(() => {
|
|
18
|
+
mousedown = false;
|
|
19
|
+
mouse = Vec2();
|
|
20
|
+
})
|
|
21
|
+
canvas.onMouseMove((x, y) => {
|
|
22
|
+
const newMouse = Vec2(x, y);
|
|
23
|
+
if (!mousedown || newMouse.equals(mouse)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const [dx, dy] = newMouse.sub(mouse).toArray();
|
|
27
|
+
camera.sphericalCoords = camera.sphericalCoords.add(
|
|
28
|
+
Vec3(
|
|
29
|
+
0,
|
|
30
|
+
-2 * Math.PI * (dx / canvas.width),
|
|
31
|
+
-2 * Math.PI * (dy / canvas.height)
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
mouse = newMouse;
|
|
35
|
+
camera.orbit();
|
|
36
|
+
})
|
|
37
|
+
canvas.onMouseWheel(({ deltaY }) => {
|
|
38
|
+
camera.sphericalCoords = camera.sphericalCoords.add(Vec3(deltaY * 0.001, 0, 0));
|
|
39
|
+
camera.orbit();
|
|
40
|
+
})
|
|
41
|
+
// scene
|
|
42
|
+
const stanfordBunnyObj = await fetch("/assets/bunny.obj").then(x => x.text());
|
|
43
|
+
let bunnyMesh = Mesh.readObj(stanfordBunnyObj);
|
|
44
|
+
const bunnyBox = bunnyMesh.getBoundingBox();
|
|
45
|
+
bunnyMesh = bunnyMesh
|
|
46
|
+
.mapVertices(v =>
|
|
47
|
+
v.sub(bunnyBox.min).div(bunnyBox.diagonal).scale(2).sub(Vec3(1, 1, 1))
|
|
48
|
+
)
|
|
49
|
+
.mapVertices(v => Vec3(-v.y, v.x, v.z))
|
|
50
|
+
.mapVertices(v => Vec3(v.z, v.y, -v.x))
|
|
51
|
+
.mapColors(v =>
|
|
52
|
+
Color.ofRGB(...v.map(x => Math.max(0, Math.min(1, 0.5 * (x + 1)))).toArray())
|
|
53
|
+
)
|
|
54
|
+
scene.add(...bunnyMesh.asPoints("bunny", 0.05));
|
|
55
|
+
|
|
56
|
+
// boilerplate for fps
|
|
57
|
+
Animation
|
|
58
|
+
.builder()
|
|
59
|
+
.initialState({ it: 1, oldTime: new Date().getTime() })
|
|
60
|
+
.nextState(({ it, oldTime }) => {
|
|
61
|
+
camera.reverseShot(scene).to(canvas);
|
|
62
|
+
const dt = (new Date().getTime() - oldTime) * 1e-3;
|
|
63
|
+
logger.print(Math.floor(1 / dt));
|
|
64
|
+
return {
|
|
65
|
+
it: it + 1,
|
|
66
|
+
oldTime: new Date().getTime()
|
|
67
|
+
};
|
|
68
|
+
})
|
|
69
|
+
.while(() => true)
|
|
70
|
+
.build()
|
|
71
|
+
.play();
|
|
72
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/* eslint-disable no-undef */
|
|
2
|
+
async (canvas, fps, logger) => {
|
|
3
|
+
// resize incoming canvas:Canvas object.
|
|
4
|
+
const width = 640;
|
|
5
|
+
const height = 480;
|
|
6
|
+
canvas.resize(width, height);
|
|
7
|
+
// scene
|
|
8
|
+
const scene = new NaiveScene();
|
|
9
|
+
const camera = new Camera({ sphericalCoords: Vec3(5, 0, 0) });
|
|
10
|
+
// mouse handling
|
|
11
|
+
let mousedown = false;
|
|
12
|
+
let mouse = Vec2();
|
|
13
|
+
canvas.onMouseDown((x, y) => {
|
|
14
|
+
mousedown = true;
|
|
15
|
+
mouse = Vec2(x, y);
|
|
16
|
+
})
|
|
17
|
+
canvas.onMouseUp(() => {
|
|
18
|
+
mousedown = false;
|
|
19
|
+
mouse = Vec2();
|
|
20
|
+
})
|
|
21
|
+
canvas.onMouseMove((x, y) => {
|
|
22
|
+
const newMouse = Vec2(x, y);
|
|
23
|
+
if (!mousedown || newMouse.equals(mouse)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const [dx, dy] = newMouse.sub(mouse).toArray();
|
|
27
|
+
camera.sphericalCoords = camera.sphericalCoords.add(
|
|
28
|
+
Vec3(
|
|
29
|
+
0,
|
|
30
|
+
-2 * Math.PI * (dx / canvas.width),
|
|
31
|
+
-2 * Math.PI * (dy / canvas.height)
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
mouse = newMouse;
|
|
35
|
+
camera.orbit();
|
|
36
|
+
})
|
|
37
|
+
canvas.onMouseWheel(({ deltaY }) => {
|
|
38
|
+
camera.sphericalCoords = camera.sphericalCoords.add(Vec3(deltaY * 0.001, 0, 0));
|
|
39
|
+
camera.orbit();
|
|
40
|
+
})
|
|
41
|
+
// scene
|
|
42
|
+
const img = await Canvas.ofUrl("./assets/kakashi.jpg");
|
|
43
|
+
const grid = [...Array(img.width * img.height)]
|
|
44
|
+
.map((_, k) => {
|
|
45
|
+
const i = Math.floor(k / img.width);
|
|
46
|
+
const j = k % img.width;
|
|
47
|
+
const x = j;
|
|
48
|
+
const y = i;
|
|
49
|
+
return Point
|
|
50
|
+
.builder()
|
|
51
|
+
.name(`pxl_${k}`)
|
|
52
|
+
.radius(0.01)
|
|
53
|
+
.position(
|
|
54
|
+
Vec3(0, x / img.width, y / img.height)
|
|
55
|
+
)
|
|
56
|
+
.color(img.getPxl(x, y))
|
|
57
|
+
.build();
|
|
58
|
+
});
|
|
59
|
+
scene.addList(grid);
|
|
60
|
+
|
|
61
|
+
// boilerplate for fps
|
|
62
|
+
Animation
|
|
63
|
+
.builder()
|
|
64
|
+
.initialState({ it: 1, oldTime: new Date().getTime() })
|
|
65
|
+
.nextState(({ it, oldTime }) => {
|
|
66
|
+
camera.reverseShot(scene).to(canvas);
|
|
67
|
+
const dt = (new Date().getTime() - oldTime) * 1e-3;
|
|
68
|
+
logger.print(Math.floor(1 / dt));
|
|
69
|
+
return {
|
|
70
|
+
it: it + 1,
|
|
71
|
+
oldTime: new Date().getTime()
|
|
72
|
+
};
|
|
73
|
+
})
|
|
74
|
+
.while(() => true)
|
|
75
|
+
.build()
|
|
76
|
+
.play();
|
|
77
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
(canvas, fps) => {
|
|
2
|
+
// resize incoming canvas:Canvas object.
|
|
3
|
+
const width = 100;
|
|
4
|
+
const height = 100;
|
|
5
|
+
canvas.resize(width, height);
|
|
6
|
+
|
|
7
|
+
// utils
|
|
8
|
+
const T = 100;
|
|
9
|
+
const amp = 10;
|
|
10
|
+
const friction = 1;
|
|
11
|
+
const waveScalarSpeed = 50;
|
|
12
|
+
const mod = (n, m) => ((n % m) + m) % m;
|
|
13
|
+
const wave = [...new Array(height)].map(
|
|
14
|
+
() => new Float64Array(width)
|
|
15
|
+
);
|
|
16
|
+
const waveSpeed = [...new Array(height)].map(
|
|
17
|
+
() => new Float64Array(width)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
let mousedown = false;
|
|
21
|
+
canvas.onMouseDown(() => {
|
|
22
|
+
mousedown = true;
|
|
23
|
+
})
|
|
24
|
+
canvas.onMouseUp(() => {
|
|
25
|
+
mousedown = false;
|
|
26
|
+
})
|
|
27
|
+
canvas.onMouseMove((x, y) => {
|
|
28
|
+
if (!mousedown) return;
|
|
29
|
+
const i = mod(y - height + 1, height);
|
|
30
|
+
const j = mod(x, width);
|
|
31
|
+
let steps = [-1, 0, 1];
|
|
32
|
+
//steps = [-2,-1,0,1,2]; // uncomment this line for bigger paint brush
|
|
33
|
+
const n = steps.length;
|
|
34
|
+
const nn = n * n;
|
|
35
|
+
for (let k = 0; k < nn; k++) {
|
|
36
|
+
const u = Math.floor(k / n)
|
|
37
|
+
const v = k % n
|
|
38
|
+
wave[mod(i + steps[u], height)][mod(j + steps[v], width)] = amp;
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// start animation
|
|
43
|
+
Animation
|
|
44
|
+
.builder()
|
|
45
|
+
.initialState({
|
|
46
|
+
it: 1,
|
|
47
|
+
time: 0,
|
|
48
|
+
oldT: new Date().getTime(),
|
|
49
|
+
})
|
|
50
|
+
.nextState(({
|
|
51
|
+
it,
|
|
52
|
+
time,
|
|
53
|
+
oldT,
|
|
54
|
+
}) => {
|
|
55
|
+
const newT = new Date().getTime();
|
|
56
|
+
const dt = (newT - oldT) * 1e-3;
|
|
57
|
+
fps(dt, it)
|
|
58
|
+
|
|
59
|
+
let maxWave = Number.MIN_VALUE;
|
|
60
|
+
let minWave = Number.MAX_VALUE;
|
|
61
|
+
let maxAbsSpeed = Number.MIN_VALUE;
|
|
62
|
+
// update wave
|
|
63
|
+
for (let i = 0; i < height; i++) {
|
|
64
|
+
for (let j = 0; j < width; j++) {
|
|
65
|
+
/**
|
|
66
|
+
* Sympletic integration
|
|
67
|
+
*/
|
|
68
|
+
// compute acceleration
|
|
69
|
+
const laplacian =
|
|
70
|
+
wave[i][mod(j + 1, width)] +
|
|
71
|
+
wave[i][mod(j - 1, width)] +
|
|
72
|
+
wave[mod(i + 1, height)][j] +
|
|
73
|
+
wave[mod(i - 1, height)][j] -
|
|
74
|
+
4 * wave[i][j];
|
|
75
|
+
const acceleration = waveScalarSpeed * laplacian - friction * waveSpeed[i][j];
|
|
76
|
+
|
|
77
|
+
//update speed
|
|
78
|
+
waveSpeed[i][j] = waveSpeed[i][j] + dt * acceleration;
|
|
79
|
+
|
|
80
|
+
// update position
|
|
81
|
+
wave[i][j] = wave[i][j] + dt * waveSpeed[i][j];
|
|
82
|
+
|
|
83
|
+
// get max min values of wave
|
|
84
|
+
maxWave = maxWave <= wave[i][j] ? wave[i][j] : maxWave;
|
|
85
|
+
minWave = minWave > wave[i][j] ? wave[i][j] : minWave;
|
|
86
|
+
const absSpeed = Math.abs(waveSpeed[i][j]);
|
|
87
|
+
maxAbsSpeed = maxAbsSpeed <= absSpeed ? absSpeed : maxAbsSpeed;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
canvas.map((x, y) => {
|
|
92
|
+
let xi = x;
|
|
93
|
+
let yi = y;
|
|
94
|
+
const redColor = (wave[yi][xi] - minWave) / (maxWave - minWave);
|
|
95
|
+
const blueColor = 1 - (wave[yi][xi] - minWave) / (maxWave - minWave);
|
|
96
|
+
const greenColor = Math.abs(waveSpeed[yi][xi]) / maxAbsSpeed;
|
|
97
|
+
return Color.ofRGB(redColor, greenColor, blueColor);
|
|
98
|
+
})
|
|
99
|
+
return {
|
|
100
|
+
it: it + 1,
|
|
101
|
+
oldT: newT,
|
|
102
|
+
time: time + dt,
|
|
103
|
+
};
|
|
104
|
+
})
|
|
105
|
+
.while(() => true)
|
|
106
|
+
.build()
|
|
107
|
+
.play();
|
|
108
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* eslint-disable no-undef */
|
|
2
|
+
async (canvas, fps, logger) => {
|
|
3
|
+
// resize incoming canvas:Canvas object.
|
|
4
|
+
const width = 640 / 2;
|
|
5
|
+
const height = 480 / 2;
|
|
6
|
+
canvas.resize(width, height);
|
|
7
|
+
// scene
|
|
8
|
+
const scene = new Scene();
|
|
9
|
+
const camera = new Camera({ sphericalCoords: Vec3(20, 0, 0) });
|
|
10
|
+
// mouse handling
|
|
11
|
+
let mousedown = false;
|
|
12
|
+
let mouse = Vec2();
|
|
13
|
+
canvas.onMouseDown((x, y) => {
|
|
14
|
+
mousedown = true;
|
|
15
|
+
mouse = Vec2(x, y);
|
|
16
|
+
})
|
|
17
|
+
canvas.onMouseUp(() => {
|
|
18
|
+
mousedown = false;
|
|
19
|
+
mouse = Vec2();
|
|
20
|
+
})
|
|
21
|
+
canvas.onMouseMove((x, y) => {
|
|
22
|
+
const newMouse = Vec2(x, y);
|
|
23
|
+
if (!mousedown || newMouse.equals(mouse)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const [dx, dy] = newMouse.sub(mouse).toArray();
|
|
27
|
+
camera.sphericalCoords = camera.sphericalCoords.add(
|
|
28
|
+
Vec3(
|
|
29
|
+
0,
|
|
30
|
+
-2 * Math.PI * (dx / canvas.width),
|
|
31
|
+
-2 * Math.PI * (dy / canvas.height)
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
mouse = newMouse;
|
|
35
|
+
camera.orbit();
|
|
36
|
+
})
|
|
37
|
+
canvas.onMouseWheel(({ deltaY }) => {
|
|
38
|
+
camera.sphericalCoords = camera.sphericalCoords.add(Vec3(deltaY * 0.001, 0, 0));
|
|
39
|
+
camera.orbit();
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
Animation
|
|
43
|
+
.builder()
|
|
44
|
+
.initialState({ it: 1, time: 0, oldTime: new Date().getTime() })
|
|
45
|
+
.nextState(({ it, time, oldTime }) => {
|
|
46
|
+
const dt = (new Date().getTime() - oldTime) * 1e-3;
|
|
47
|
+
oldTime = new Date().getTime()
|
|
48
|
+
const t = time;
|
|
49
|
+
camera.sceneShot(rayScene).to(canvas);
|
|
50
|
+
logger.print(`FPS: ${Math.floor(1 / dt)}`);
|
|
51
|
+
return {
|
|
52
|
+
it: it + 1,
|
|
53
|
+
time: time + dt,
|
|
54
|
+
oldTime
|
|
55
|
+
};
|
|
56
|
+
})
|
|
57
|
+
.while(() => true)
|
|
58
|
+
.build()
|
|
59
|
+
.play();
|
|
60
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
(canvas, fps, logger) => {
|
|
2
|
+
// resize incoming canvas:Canvas object.
|
|
3
|
+
const width = 640/2;
|
|
4
|
+
const height = 480/2;
|
|
5
|
+
canvas.resize(width, height);
|
|
6
|
+
// utils
|
|
7
|
+
const size = Vec2(width, height);
|
|
8
|
+
const complexMul = (z, w) => Vec2(z.x * w.x - z.y * w.y, z.x * w.y + z.y * w.x);
|
|
9
|
+
let box = new Box(Vec2(-1, -1), Vec2(1, 1));
|
|
10
|
+
// mouse handling
|
|
11
|
+
let mousedown = false;
|
|
12
|
+
let mouse = Vec2();
|
|
13
|
+
canvas.onMouseDown((x, y) => {
|
|
14
|
+
mousedown = true;
|
|
15
|
+
mouse = Vec2(x, y);
|
|
16
|
+
})
|
|
17
|
+
canvas.onMouseUp(() => {
|
|
18
|
+
mousedown = false;
|
|
19
|
+
mouse = Vec2();
|
|
20
|
+
})
|
|
21
|
+
canvas.onMouseMove((x, y) => {
|
|
22
|
+
const newMouse = Vec2(x, y);
|
|
23
|
+
if (!mousedown || newMouse.equals(mouse)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const [dx, dy] = newMouse.sub(mouse).toArray();
|
|
27
|
+
const v = Vec2(dx, dy).scale(-1).div(size).mul(box.diagonal);
|
|
28
|
+
box = box.move(v);
|
|
29
|
+
mouse = newMouse;
|
|
30
|
+
update();
|
|
31
|
+
})
|
|
32
|
+
canvas.onMouseWheel(({ deltaY }) => {
|
|
33
|
+
const scale = Math.sign(deltaY) * 1e-1;
|
|
34
|
+
box = box.scale(1+scale);
|
|
35
|
+
update();
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
function update() {
|
|
39
|
+
const ite = 100;
|
|
40
|
+
canvas.map((x, y) => {
|
|
41
|
+
let p = Vec2(x, y).div(size);
|
|
42
|
+
p = p.map(z => 2 * z - 1);
|
|
43
|
+
p = Vec2(p.x * (size.x / size.y) - 0.5, p.y);
|
|
44
|
+
p = box.min.add(
|
|
45
|
+
box.diagonal.mul(
|
|
46
|
+
p.add(Vec2(1, 1)).scale(1 / 2)
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
let z = Vec2();
|
|
50
|
+
for (let i = 0; i < ite; i++) {
|
|
51
|
+
z = complexMul(z, z).add(p);
|
|
52
|
+
}
|
|
53
|
+
const l = z.length();
|
|
54
|
+
const ll = Math.min(1, Math.max(0, l));
|
|
55
|
+
return Color.ofRGB(1 - ll, ll, 0);
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
update();
|
|
59
|
+
}
|