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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tela.js",
3
- "version": "1.2.8",
3
+ "version": "1.2.10",
4
4
  "author": "Pedroth",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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 h = clamp()(l.dot(v) / l.dot(l))
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
 
@@ -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
- this.boundingBox = this.positions.reduce((box, x) => box.add(new Box(x, x)), Box.EMPTY);
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
- const r = p.sub(this.positions[0]);
49
- if (this.isDegenerate) return r.length() - this.radius;
50
- const x = Vec2(this.tangents[0].dot(r), this.tangents[1].dot(r));
51
- let alpha = Vec2(this.invU1.dot(x), this.invU2.dot(x)).map(x => x < 0 ? 0 : x);
52
- const sum = alpha.fold((e, x) => e + x, 0)
53
- if (sum > 1) {
54
- alpha = alpha.scale(1 / sum);
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
- this.tangents[1].scale(alpha.y)
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
- // fixes problem in ray tracing
68
- const r = p.sub(this.positions[0]);
69
- const dot = this.faceNormal.dot(r);
70
- return dot < 1e-3 ? this.faceNormal : this.faceNormal.scale(-1);
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
- const epsilon = 1e-9
75
- const v = ray.dir;
76
- const p = ray.init.sub(this.positions[0]);
77
- const n = this.faceNormal;
78
- const t = - n.dot(p) / n.dot(v);
79
- if (t <= epsilon) return;
80
- const x = ray.trace(t);
81
- for (let i = 0; i < this.positions.length; i++) {
82
- const xi = this.positions[i];
83
- const u = x.sub(xi);
84
- const ni = n.cross(this.edges[i]);
85
- const dot = ni.dot(u);
86
- if (dot <= epsilon) return;
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 [t - epsilon, x, this];
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 = 1;
186
+ this._radius = 0.0;
142
187
  this._emissive = false;
143
188
  this._material = Diffuse();
144
189
  }
@@ -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 === 0 ? 1 : 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
 
@@ -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;