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,109 @@
|
|
|
1
|
+
import Box from "../Box/Box.js";
|
|
2
|
+
import Color from "../Color/Color.js";
|
|
3
|
+
import { none, some } from "../Monads/Monads.js";
|
|
4
|
+
import Vec, { Vec3 } from "../Vector/Vector.js";
|
|
5
|
+
|
|
6
|
+
class Point {
|
|
7
|
+
constructor({ name, position, normal, color, radius }) {
|
|
8
|
+
this.name = name;
|
|
9
|
+
this.color = color;
|
|
10
|
+
this.normal = normal;
|
|
11
|
+
this.radius = radius;
|
|
12
|
+
this.position = position;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
distanceToPoint(p) {
|
|
16
|
+
return this.position.sub(p).length() - this.radius;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interceptWith(ray) {
|
|
20
|
+
return sphereInterception(this, ray)
|
|
21
|
+
.map(t => {
|
|
22
|
+
const pointOnSphere = ray.trace(t);
|
|
23
|
+
const normal = pointOnSphere.sub(this.position).normalize();
|
|
24
|
+
return [pointOnSphere, normal];
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getBoundingBox() {
|
|
29
|
+
if (this.boundingBox) return this.boundingBox;
|
|
30
|
+
const n = this.position.dim;
|
|
31
|
+
this.boundingBox = new Box(
|
|
32
|
+
this.position.add(Vec.ONES(n).scale(-this.radius)),
|
|
33
|
+
this.position.add(Vec.ONES(n).scale(this.radius))
|
|
34
|
+
);
|
|
35
|
+
return this.boundingBox;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static builder() {
|
|
39
|
+
return new PointBuilder();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class PointBuilder {
|
|
46
|
+
constructor() {
|
|
47
|
+
this._name;
|
|
48
|
+
this._color = Color.WHITE;
|
|
49
|
+
this._radius = 1;
|
|
50
|
+
this._normal = Vec3(1, 0, 0);
|
|
51
|
+
this._position = Vec3(0, 0, 0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
name(name) {
|
|
55
|
+
this._name = name;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
color(color) {
|
|
60
|
+
this._color = color;
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
radius(radius) {
|
|
66
|
+
this._radius = radius;
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
normal(normal) {
|
|
71
|
+
this._normal = normal;
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
position(posVec3) {
|
|
76
|
+
this._position = posVec3;
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
build() {
|
|
81
|
+
const attrs = {
|
|
82
|
+
name: this._name,
|
|
83
|
+
color: this._color,
|
|
84
|
+
radius: this._radius,
|
|
85
|
+
normal: this._normal,
|
|
86
|
+
position: this._position,
|
|
87
|
+
}
|
|
88
|
+
if (Object.values(attrs).some((x) => x === undefined)) {
|
|
89
|
+
throw new Error("Point is incomplete");
|
|
90
|
+
}
|
|
91
|
+
return new Point(attrs);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function sphereInterception(point, ray) {
|
|
96
|
+
const { init, dir } = ray;
|
|
97
|
+
const diff = init.sub(point.position);
|
|
98
|
+
const b = 2 * dir.dot(diff);
|
|
99
|
+
const c = diff.squareLength() - point.radius * point.radius;
|
|
100
|
+
const discriminant = b * b - 4 * c; // a = 1
|
|
101
|
+
if (discriminant < 0) return none();
|
|
102
|
+
const sqrt = Math.sqrt(discriminant);
|
|
103
|
+
const [t1, t2] = [(-b - sqrt) / 2, (-b + sqrt) / 2];
|
|
104
|
+
const t = Math.min(t1, t2);
|
|
105
|
+
if (t1 * t2 < 0) return some(t);
|
|
106
|
+
return t1 >= 0 && t2 >= 0 ? some(t) : none();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default Point;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
class PointCloud {
|
|
2
|
+
constructor({ name, pointCloud }) {
|
|
3
|
+
this.name = name;
|
|
4
|
+
this.pointCloud = pointCloud
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interceptWith(ray) {
|
|
8
|
+
// TODO;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
getBoundingBox() {
|
|
12
|
+
if (this.boundingBox) return this.boundingBox;
|
|
13
|
+
// TODO
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static builder() {
|
|
17
|
+
return new PointCloudBuilder();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class PointCloudBuilder {
|
|
24
|
+
constructor() {
|
|
25
|
+
this._name;
|
|
26
|
+
this._pointCloud = [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
name(name) {
|
|
30
|
+
this._name = name;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
objFile(objString) {
|
|
35
|
+
//TODO
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
build() {
|
|
40
|
+
const attrs = {
|
|
41
|
+
name: this._name,
|
|
42
|
+
pointCloud: this._pointCloud
|
|
43
|
+
}
|
|
44
|
+
if (Object.values(attrs).some((x) => x === undefined)) {
|
|
45
|
+
throw new Error("Point is incomplete");
|
|
46
|
+
}
|
|
47
|
+
return new PointCloud(attrs);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default PointCloud;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
|
|
2
|
+
import Box from "../Box/Box.js";
|
|
3
|
+
import { none, some } from "../Monads/Monads.js";
|
|
4
|
+
import { argmin } from "../Utils/Utils.js";
|
|
5
|
+
import Point from "./Point.js";
|
|
6
|
+
import Ray from "../Ray/Ray.js";
|
|
7
|
+
import Vec from "../Vector/Vector.js";
|
|
8
|
+
import { smin } from "../Utils/Math.js";
|
|
9
|
+
|
|
10
|
+
export default class Scene {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.id2ElemMap = {};
|
|
13
|
+
this.sceneElements = [];
|
|
14
|
+
this.boundingBoxScene = new Node();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
add(...elements) {
|
|
18
|
+
return this.addList(elements);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
addList(elements) {
|
|
22
|
+
for (let i = 0; i < elements.length; i++) {
|
|
23
|
+
const elem = elements[i];
|
|
24
|
+
const classes = [Point];
|
|
25
|
+
if (!classes.some((c) => elem instanceof c)) return this;
|
|
26
|
+
const { name } = elem;
|
|
27
|
+
this.id2ElemMap[name] = elem;
|
|
28
|
+
this.sceneElements.push(elem);
|
|
29
|
+
this.boundingBoxScene.add(elem);
|
|
30
|
+
}
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
clear() {
|
|
35
|
+
this.id2ElemMap = {};
|
|
36
|
+
this.sceneElements = [];
|
|
37
|
+
this.boundingBoxScene = new Node();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getElements() {
|
|
41
|
+
return this.sceneElements;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interceptWith(ray, level) {
|
|
45
|
+
return this.boundingBoxScene.interceptWith(ray, level);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
distanceToPoint(p) {
|
|
49
|
+
return this.boundingBoxScene.distanceToPoint(p)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
estimateNormal(p) {
|
|
53
|
+
const epsilon = 1e-3;
|
|
54
|
+
const n = p.dim;
|
|
55
|
+
const grad = [];
|
|
56
|
+
const d = this.distanceToPoint(p);
|
|
57
|
+
for (let i = 0; i < n; i++) {
|
|
58
|
+
grad.push(this.distanceToPoint(p.add(Vec.e(n)(i).scale(epsilon))) - d);
|
|
59
|
+
}
|
|
60
|
+
return Vec.fromArray(grad).scale(Math.sign(d)).normalize();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
class Node {
|
|
65
|
+
isLeaf = false;
|
|
66
|
+
numberOfLeafs = 0;
|
|
67
|
+
leafs = [];
|
|
68
|
+
constructor() {
|
|
69
|
+
this.box = Box.EMPTY;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
add(element) {
|
|
73
|
+
this.numberOfLeafs += 1;
|
|
74
|
+
this.leafs.push(element);
|
|
75
|
+
const elemBox = element.getBoundingBox();
|
|
76
|
+
this.box = this.box.add(elemBox);
|
|
77
|
+
if (!this.left) {
|
|
78
|
+
this.left = new Leaf(element);
|
|
79
|
+
} else if (!this.right) {
|
|
80
|
+
this.right = new Leaf(element);
|
|
81
|
+
} else {
|
|
82
|
+
this._addElementWhenTreeIsFull(element, elemBox);
|
|
83
|
+
}
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
distanceToPoint(p) {
|
|
88
|
+
if (this.numberOfLeafs <= 2) {
|
|
89
|
+
return this.getElements().reduce((e, leaf) => smin(e, leaf.distanceToPoint(p)), 1000);
|
|
90
|
+
}
|
|
91
|
+
const children = [this.left, this.right];
|
|
92
|
+
const index = argmin(children, c => c.box.distanceToPoint(p));
|
|
93
|
+
return children[index].distanceToPoint(p);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getElements() {
|
|
97
|
+
return this.leafs;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
getRandomLeaf() {
|
|
101
|
+
return Math.random() < 0.5 ? this.left.getRandomLeaf() : this.right.getRandomLeaf();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
interceptWith(ray, depth = 1) {
|
|
105
|
+
if (this.numberOfLeafs === 5) {
|
|
106
|
+
// return this.getRandomLeaf().interceptWith(ray, 10);
|
|
107
|
+
return this.box.interceptWith(ray).map(p => [p, this.box.estimateNormal(p)]);
|
|
108
|
+
}
|
|
109
|
+
return this.box.interceptWith(ray).flatMap((p) => {
|
|
110
|
+
const children = [this.left, this.right].filter(x => x);
|
|
111
|
+
const hits = [];
|
|
112
|
+
for (let i = 0; i < children.length; i++) {
|
|
113
|
+
const maybeHit = children[i].interceptWith(ray, depth + 1);
|
|
114
|
+
if (maybeHit.isSome()) hits.push(maybeHit.orElse());
|
|
115
|
+
}
|
|
116
|
+
const minIndex = argmin(hits, ([point]) => point.sub(ray.init).length());
|
|
117
|
+
if (minIndex === -1) return none();
|
|
118
|
+
return some(hits[minIndex]);
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
_addElementWhenTreeIsFull(element, elemBox) {
|
|
123
|
+
if (this.left.isLeaf && this.right.isLeaf) {
|
|
124
|
+
this._addWithLeafs(element);
|
|
125
|
+
} else {
|
|
126
|
+
// at least one children is not a leaf
|
|
127
|
+
const minIndex = argmin([
|
|
128
|
+
this.left.box.distanceToBox(elemBox),
|
|
129
|
+
this.right.box.distanceToBox(elemBox)
|
|
130
|
+
]);
|
|
131
|
+
this._updateChildren(minIndex, element);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
_updateChildren(minIndex, element) {
|
|
136
|
+
let child = [this.left, this.right][minIndex];
|
|
137
|
+
if (!child.isLeaf) {
|
|
138
|
+
child.add(element);
|
|
139
|
+
} else {
|
|
140
|
+
const aux = child.element;
|
|
141
|
+
if (minIndex === 0) this.left = new Node().add(aux).add(element);
|
|
142
|
+
if (minIndex === 1) this.right = new Node().add(aux).add(element);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
_addWithLeafs(element) {
|
|
147
|
+
const elemBox = element.getBoundingBox();
|
|
148
|
+
const distances = [
|
|
149
|
+
elemBox.distanceToBox(this.left.box),
|
|
150
|
+
elemBox.distanceToBox(this.right.box),
|
|
151
|
+
this.left.box.distanceToBox(this.right.box)
|
|
152
|
+
]
|
|
153
|
+
const index = argmin(distances);
|
|
154
|
+
const index2Action = {
|
|
155
|
+
0: () => {
|
|
156
|
+
const aux = this.left;
|
|
157
|
+
this.left = new Node();
|
|
158
|
+
this.left.add(aux.element).add(element);
|
|
159
|
+
},
|
|
160
|
+
1: () => {
|
|
161
|
+
const aux = this.right;
|
|
162
|
+
this.right = new Node();
|
|
163
|
+
this.right.add(aux.element).add(element);
|
|
164
|
+
},
|
|
165
|
+
2: () => {
|
|
166
|
+
const aux = this.left;
|
|
167
|
+
this.left = new Node();
|
|
168
|
+
this.left.add(aux.element).add(this.right.element);
|
|
169
|
+
this.right = new Leaf(element);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
index2Action[index]();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
class Leaf {
|
|
177
|
+
isLeaf = true;
|
|
178
|
+
constructor(element) {
|
|
179
|
+
this.element = element;
|
|
180
|
+
this.box = element.getBoundingBox();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
distanceToPoint(x) {
|
|
184
|
+
// return this.box.distanceToPoint(x);
|
|
185
|
+
return this.element.distanceToPoint(x);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
getLeafs() {
|
|
189
|
+
return [this];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
getRandomLeaf() {
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
interceptWith(ray, depth) {
|
|
197
|
+
// return this.box.interceptWith(ray).map(pos => [pos, this.box.estimateNormal(pos)]);
|
|
198
|
+
return this.element.interceptWith(ray);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default class Stream {
|
|
2
|
+
constructor(initialState, updateStateFunction) {
|
|
3
|
+
this._head = initialState;
|
|
4
|
+
this._tail = updateStateFunction;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
get head() { return this._head; }
|
|
8
|
+
|
|
9
|
+
get tail() { return new Stream(this._tail(this._head), this._tail); }
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MAX_8BIT = 255;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export function smin(a, b, k = 32) {
|
|
2
|
+
const res = Math.exp(-k * a) + Math.exp(-k * b);
|
|
3
|
+
return -Math.log(res) / k;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function clipLine(p0, p1, box) {
|
|
7
|
+
const pointStack = [p0, p1];
|
|
8
|
+
const inStack = [];
|
|
9
|
+
const outStack = [];
|
|
10
|
+
for (let i = 0; i < pointStack.length; i++) {
|
|
11
|
+
const p = pointStack[i];
|
|
12
|
+
if (box.collidesWith(p)) {
|
|
13
|
+
inStack.push(p);
|
|
14
|
+
} else {
|
|
15
|
+
outStack.push(p);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// both points are inside
|
|
19
|
+
if (inStack.length >= 2) {
|
|
20
|
+
return inStack;
|
|
21
|
+
}
|
|
22
|
+
// one of them is inside
|
|
23
|
+
if (inStack.length === 1) {
|
|
24
|
+
const [inPoint] = inStack;
|
|
25
|
+
const [outPoint] = outStack;
|
|
26
|
+
return [inPoint, ...lineBoxIntersection(inPoint, outPoint)];
|
|
27
|
+
}
|
|
28
|
+
// both points are outside,need to intersect the boundary
|
|
29
|
+
return lineBoxIntersection(...outStack, box);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function lineBoxIntersection(start, end, box) {
|
|
33
|
+
const width = box.max.get(0) - box.min.get(0);
|
|
34
|
+
const height = box.max.get(1) - box.min.get(1);
|
|
35
|
+
const v = end.sub(start);
|
|
36
|
+
// point and direction of boundary
|
|
37
|
+
const boundary = [
|
|
38
|
+
[vec2.ZERO, vec2.of(height, 0)],
|
|
39
|
+
[vec2.of(height, 0), vec2.of(0, width)],
|
|
40
|
+
[vec2.of(height, width), vec2.of(-height, 0)],
|
|
41
|
+
[vec2.of(0, width), vec2.of(0, -width)],
|
|
42
|
+
];
|
|
43
|
+
const intersectionSolutions = [];
|
|
44
|
+
boundary.forEach(([s, d]) => {
|
|
45
|
+
if (d.get(0) === 0) {
|
|
46
|
+
const solution = this._solveLowTriMatrix(v, -d.get(1), s.sub(start));
|
|
47
|
+
solution !== undefined && intersectionSolutions.push(solution);
|
|
48
|
+
} else {
|
|
49
|
+
const solution = this._solveUpTriMatrix(v, -d.get(0), s.sub(start));
|
|
50
|
+
solution !== undefined && intersectionSolutions.push(solution);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const validIntersections = [];
|
|
54
|
+
intersectionSolutions.forEach((solution) => {
|
|
55
|
+
const [x, y] = [solution.get(0), solution.get(1)];
|
|
56
|
+
if (0 <= x && x <= 1 && 0 <= y && y <= 1) {
|
|
57
|
+
validIntersections.push(solution);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
if (validIntersections.length === 0) return [];
|
|
61
|
+
return validIntersections.map((solution) => {
|
|
62
|
+
const t = solution.get(0);
|
|
63
|
+
return start.add(v.scale(t));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function measureTime(lambda) {
|
|
2
|
+
const t = performance.now();
|
|
3
|
+
lambda()
|
|
4
|
+
return 1e-3 * (performance.now() - t);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function measureTimeWithResult(lambda) {
|
|
8
|
+
const t = performance.now();
|
|
9
|
+
const result = lambda();
|
|
10
|
+
return { result, time: 1e-3 * (performance.now() - t) };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function compose(f, g) {
|
|
14
|
+
return x => f(g(x));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function or(...lambdas) {
|
|
18
|
+
for (let i = 0; i < lambdas.length; i++) {
|
|
19
|
+
try {
|
|
20
|
+
return lambdas[i]();
|
|
21
|
+
} catch (err) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function argmin(array, costFunction = x => x) {
|
|
28
|
+
let argminIndex = -1;
|
|
29
|
+
let cost = Number.MAX_VALUE;
|
|
30
|
+
// faster than forEach
|
|
31
|
+
for (let i = 0; i < array.length; i++) {
|
|
32
|
+
const newCost = costFunction(array[i]);
|
|
33
|
+
if (newCost < cost) {
|
|
34
|
+
cost = newCost;
|
|
35
|
+
argminIndex = i;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return argminIndex;
|
|
39
|
+
}
|