tela.js 1.2.8 → 1.2.10
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/package.json +1 -1
- package/src/Geometry/Line.js +5 -1
- package/src/Geometry/Triangle.js +77 -32
- package/src/Scene/KScene.js +2 -2
- package/src/Tela/telaWorker.js +3 -1
package/package.json
CHANGED
package/src/Geometry/Line.js
CHANGED
|
@@ -5,6 +5,8 @@ import { clamp } from "../Utils/Math.js";
|
|
|
5
5
|
import Vec, { Vec2, Vec3 } from "../Vector/Vector.js";
|
|
6
6
|
import { generateUniqueID } from "../Utils/Utils.js";
|
|
7
7
|
|
|
8
|
+
const clamp01 = clamp();
|
|
9
|
+
|
|
8
10
|
export default class Line {
|
|
9
11
|
constructor({ name, positions, colors, texCoords, normals, texture, radius, emissive, material }) {
|
|
10
12
|
this.name = name;
|
|
@@ -32,7 +34,9 @@ export default class Line {
|
|
|
32
34
|
distanceToPoint(p) {
|
|
33
35
|
const l = this.edge;
|
|
34
36
|
const v = p.sub(this.positions[0]);
|
|
35
|
-
const
|
|
37
|
+
const sqLength = l.dot(l);
|
|
38
|
+
if(sqLength < 1e-6) return Number.MAX_VALUE
|
|
39
|
+
const h = clamp01(l.dot(v) / sqLength);
|
|
36
40
|
return p.sub(this.positions[0].add(l.scale(h))).length() - this.radius;
|
|
37
41
|
}
|
|
38
42
|
|
package/src/Geometry/Triangle.js
CHANGED
|
@@ -38,54 +38,99 @@ export default class Triangle {
|
|
|
38
38
|
this.invU2 = Vec2(-c, a).scale(detInv);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
getBarycentricCoords(p) {
|
|
42
|
+
const r = p.sub(this.positions[0]);
|
|
43
|
+
const x = Vec2(this.tangents[0].dot(r), this.tangents[1].dot(r));
|
|
44
|
+
let alpha = Vec2(this.invU1.dot(x), this.invU2.dot(x));
|
|
45
|
+
const sum = alpha.fold((e, x) => e + x, 0)
|
|
46
|
+
return Vec3(alpha.x, alpha.y, 1 - sum);
|
|
47
|
+
}
|
|
48
|
+
|
|
41
49
|
getBoundingBox() {
|
|
50
|
+
const n = this.positions[0].dim;
|
|
42
51
|
if (this.boundingBox) return this.boundingBox;
|
|
43
|
-
|
|
52
|
+
const r = Vec.ONES(n).scale(this.radius)
|
|
53
|
+
this.boundingBox = this.positions.reduce((box, x) => box.add(new Box(x.sub(r), x.add(r))), Box.EMPTY);
|
|
44
54
|
return this.boundingBox;
|
|
45
55
|
}
|
|
46
56
|
|
|
47
57
|
distanceToPoint(p) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
let alpha = this.getBarycentricCoords(p).map(x => Math.max(0, x));
|
|
59
|
+
const sum = alpha.fold((e, x) => e + x, 0);
|
|
60
|
+
|
|
61
|
+
// if (sum === 1) {
|
|
62
|
+
// const r0 = p.sub(this.positions[0]);
|
|
63
|
+
// const r1 = p.sub(this.positions[1]);
|
|
64
|
+
// const r2 = p.sub(this.positions[2]);
|
|
65
|
+
// return -Math.min(
|
|
66
|
+
// r0.sub(this.edges[0].scale(this.edges[0].dot(r0) / this.edges[0].dot(this.edges[0]))).length(),
|
|
67
|
+
// r1.sub(this.edges[1].scale(this.edges[1].dot(r1) / this.edges[1].dot(this.edges[1]))).length(),
|
|
68
|
+
// r2.sub(this.edges[2].scale(this.edges[2].dot(r2) / this.edges[2].dot(this.edges[2]))).length()
|
|
69
|
+
// )
|
|
70
|
+
// }
|
|
71
|
+
|
|
72
|
+
alpha = alpha.scale(1 / sum);
|
|
56
73
|
const pointOnTriangle = this.positions[0]
|
|
57
74
|
.add(
|
|
58
75
|
this.tangents[0].scale(alpha.x)
|
|
59
|
-
.add(
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
-
)
|
|
76
|
+
.add(this.tangents[1].scale(alpha.y))
|
|
77
|
+
);
|
|
63
78
|
return p.sub(pointOnTriangle).length() - this.radius;
|
|
64
79
|
}
|
|
65
80
|
|
|
66
81
|
normalToPoint(p) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
82
|
+
if (this.radius === 0) {
|
|
83
|
+
const r = p.sub(this.positions[0]);
|
|
84
|
+
const dot = this.faceNormal.dot(r);
|
|
85
|
+
return dot < 1e-3 ? this.faceNormal : this.faceNormal.scale(-1);
|
|
86
|
+
}
|
|
87
|
+
const epsilon = 1e-6;
|
|
88
|
+
const f = this.distanceToPoint(p);
|
|
89
|
+
const sign = Math.sign(f);
|
|
90
|
+
const grad = Vec3(
|
|
91
|
+
this.distanceToPoint(p.add(Vec3(epsilon, 0, 0))) - f,
|
|
92
|
+
this.distanceToPoint(p.add(Vec3(0, epsilon, 0))) - f,
|
|
93
|
+
this.distanceToPoint(p.add(Vec3(0, 0, epsilon))) - f,
|
|
94
|
+
).normalize();
|
|
95
|
+
return grad.scale(sign);
|
|
71
96
|
}
|
|
72
97
|
|
|
73
98
|
interceptWithRay(ray) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
99
|
+
if(this.radius === 0) {
|
|
100
|
+
const epsilon = 1e-9
|
|
101
|
+
const v = ray.dir;
|
|
102
|
+
const p = ray.init.sub(this.positions[0]);
|
|
103
|
+
const n = this.faceNormal;
|
|
104
|
+
const t = - n.dot(p) / n.dot(v);
|
|
105
|
+
if (t <= epsilon) return;
|
|
106
|
+
const x = ray.trace(t);
|
|
107
|
+
for (let i = 0; i < this.positions.length; i++) {
|
|
108
|
+
const xi = this.positions[i];
|
|
109
|
+
const u = x.sub(xi);
|
|
110
|
+
const ni = n.cross(this.edges[i]);
|
|
111
|
+
const dot = ni.dot(u);
|
|
112
|
+
if (dot <= epsilon) return;
|
|
113
|
+
}
|
|
114
|
+
return [t - epsilon, x, this];
|
|
115
|
+
}
|
|
116
|
+
const maxIte = 20;
|
|
117
|
+
const epsilon = 1e-3;
|
|
118
|
+
let p = ray.init;
|
|
119
|
+
let t = this.distanceToPoint(p);
|
|
120
|
+
let minT = t;
|
|
121
|
+
for (let i = 0; i < maxIte; i++) {
|
|
122
|
+
p = ray.trace(t);
|
|
123
|
+
const d = this.distanceToPoint(p);
|
|
124
|
+
t += d;
|
|
125
|
+
if (d < epsilon) {
|
|
126
|
+
return [t, p, this];
|
|
127
|
+
}
|
|
128
|
+
if (d > minT) {
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
minT = d;
|
|
87
132
|
}
|
|
88
|
-
return
|
|
133
|
+
return;
|
|
89
134
|
}
|
|
90
135
|
|
|
91
136
|
sample() {
|
|
@@ -138,7 +183,7 @@ class TriangleBuilder {
|
|
|
138
183
|
this._colors = indx.map(() => Color.BLACK);
|
|
139
184
|
this._positions = indx.map(() => Vec3());
|
|
140
185
|
this._texCoords = [Vec2(), Vec2(1, 0), Vec2(0, 1)];
|
|
141
|
-
this._radius =
|
|
186
|
+
this._radius = 0.0;
|
|
142
187
|
this._emissive = false;
|
|
143
188
|
this._material = Diffuse();
|
|
144
189
|
}
|
package/src/Scene/KScene.js
CHANGED
|
@@ -139,7 +139,7 @@ export default class KScene extends NaiveScene {
|
|
|
139
139
|
debugScene = debugScene || new NaiveScene();
|
|
140
140
|
if (level === 0) {
|
|
141
141
|
let maxLevels = Math.round(Math.log2(node.numberOfLeafs / this.k)) + 1;
|
|
142
|
-
maxLevels = maxLevels
|
|
142
|
+
maxLevels = maxLevels <= 0 ? 1 : maxLevels;
|
|
143
143
|
for (let i = 0; i <= maxLevels; i++)
|
|
144
144
|
level2colors.push(
|
|
145
145
|
Color.RED.scale(1 - i / maxLevels).add(Color.BLUE.scale(i / maxLevels))
|
|
@@ -220,7 +220,7 @@ class Node {
|
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
distanceToPoint(p) {
|
|
223
|
-
if(!this.left && !this.right) return Number.MAX_VALUE;
|
|
223
|
+
if (!this.left && !this.right) return Number.MAX_VALUE;
|
|
224
224
|
return this.getElementNear(p).distanceToPoint(p);
|
|
225
225
|
}
|
|
226
226
|
|
package/src/Tela/telaWorker.js
CHANGED
|
@@ -3,6 +3,8 @@ import { memoize } from "../Utils/Utils.js";
|
|
|
3
3
|
// necessary to load this even though is not used in the code, it might be used in the eval.
|
|
4
4
|
import Color from "../Color/Color.js";
|
|
5
5
|
import Box from "../Geometry/Box.js";
|
|
6
|
+
import Triangle from "../Geometry/Triangle.js";
|
|
7
|
+
import Line from "../Geometry/Line.js";
|
|
6
8
|
import Vec, { Vec2, Vec3 } from "../Vector/Vector.js";
|
|
7
9
|
import Camera from "../Camera/Camera.js";
|
|
8
10
|
import Ray from "../Ray/Ray.js";
|
|
@@ -27,7 +29,7 @@ async function main(inputs) {
|
|
|
27
29
|
for (let i = __startRow; i < __endRow; i++) {
|
|
28
30
|
for (let x = 0; x < __width; x++) {
|
|
29
31
|
const y = __height - 1 - i;
|
|
30
|
-
const color = func(x, y, __vars);
|
|
32
|
+
const color = await func(x, y, __vars);
|
|
31
33
|
if (!color) continue;
|
|
32
34
|
image[index++] = color.red;
|
|
33
35
|
image[index++] = color.green;
|