simulationjsv2 0.2.4 → 0.2.5
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/constants.d.ts +3 -0
- package/dist/constants.js +3 -0
- package/dist/geometry.d.ts +103 -0
- package/dist/geometry.js +407 -0
- package/dist/graphics.d.ts +53 -47
- package/dist/graphics.js +239 -457
- package/dist/simulation.d.ts +8 -3
- package/dist/simulation.js +50 -176
- package/dist/types.d.ts +57 -2
- package/dist/utils.d.ts +10 -5
- package/dist/utils.js +92 -7
- package/package.json +1 -1
package/dist/graphics.js
CHANGED
|
@@ -1,32 +1,37 @@
|
|
|
1
|
-
import { vec3,
|
|
2
|
-
import { Vertex, VertexCache, cloneBuf, color, colorFromVector4,
|
|
1
|
+
import { vec3, mat4, vec2, vec4 } from 'wgpu-matrix';
|
|
2
|
+
import { Vertex, VertexCache, cloneBuf, color, colorFromVector4, vector3ToPixelRatio, vector2, vector3, vertex, Color, transitionValues, logger, vector2FromVector3, matrix4, rotateMat4, vector3FromVector2 } from './utils.js';
|
|
3
|
+
import { CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, SplineGeometry, SquareGeometry } from './geometry.js';
|
|
3
4
|
export class SimulationElement {
|
|
4
|
-
pos;
|
|
5
5
|
color;
|
|
6
|
-
|
|
6
|
+
wireframe;
|
|
7
7
|
vertexCache;
|
|
8
|
+
rotation;
|
|
8
9
|
is3d;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
for (let i = 0; i < this.pos.length; i++) {
|
|
14
|
-
this.pos[i] = temp[i];
|
|
15
|
-
}
|
|
10
|
+
/**
|
|
11
|
+
* @param pos - Expected to be adjusted to devicePixelRatio before reaching constructor
|
|
12
|
+
*/
|
|
13
|
+
constructor(color = new Color(), rotation, is3d = true) {
|
|
16
14
|
this.color = color;
|
|
17
15
|
this.vertexCache = new VertexCache();
|
|
18
|
-
this.camera = null;
|
|
19
16
|
this.is3d = is3d;
|
|
17
|
+
this.wireframe = false;
|
|
18
|
+
this.rotation = rotation;
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
this.
|
|
20
|
+
getGeometryType() {
|
|
21
|
+
return this.geometry.getType();
|
|
22
|
+
}
|
|
23
|
+
setWireframe(wireframe) {
|
|
24
|
+
this.wireframe = wireframe;
|
|
25
|
+
}
|
|
26
|
+
isWireframe() {
|
|
27
|
+
return this.wireframe;
|
|
28
|
+
}
|
|
29
|
+
getColor() {
|
|
30
|
+
return this.color;
|
|
23
31
|
}
|
|
24
32
|
getPos() {
|
|
25
33
|
return this.pos;
|
|
26
34
|
}
|
|
27
|
-
setCamera(camera) {
|
|
28
|
-
this.camera = camera;
|
|
29
|
-
}
|
|
30
35
|
fill(newColor, t = 0, f) {
|
|
31
36
|
const diff = newColor.diff(this.color);
|
|
32
37
|
const finalColor = newColor.clone();
|
|
@@ -41,52 +46,45 @@ export class SimulationElement {
|
|
|
41
46
|
this.vertexCache.updated();
|
|
42
47
|
}, t, f);
|
|
43
48
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
this.vertexCache.updated();
|
|
58
|
-
}, t, f);
|
|
49
|
+
defaultUpdateMatrix(camera) {
|
|
50
|
+
const matrix = matrix4();
|
|
51
|
+
if (typeof this.rotation === 'number') {
|
|
52
|
+
const pos = vector3FromVector2(this.pos);
|
|
53
|
+
pos[1] = camera.getScreenSize()[1] - pos[1];
|
|
54
|
+
mat4.translate(matrix, pos, matrix);
|
|
55
|
+
mat4.rotateZ(matrix, this.rotation, matrix);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
mat4.translate(matrix, this.pos, matrix);
|
|
59
|
+
rotateMat4(matrix, this.rotation);
|
|
60
|
+
}
|
|
61
|
+
this.geometry.updateMatrix(matrix);
|
|
59
62
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
getBuffer(camera) {
|
|
64
|
+
if (this.vertexCache.shouldUpdate() || camera.hasUpdated()) {
|
|
65
|
+
this.updateMatrix(camera);
|
|
66
|
+
this.geometry.recompute();
|
|
67
|
+
let resBuffer = [];
|
|
68
|
+
if (this.isWireframe()) {
|
|
69
|
+
resBuffer = this.geometry.getWireframeBuffer(this.color);
|
|
66
70
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
for (let i = 0; i < this.pos.length; i++) {
|
|
70
|
-
this.pos[i] = pos[i];
|
|
71
|
+
else {
|
|
72
|
+
resBuffer = this.geometry.getTriangleBuffer(this.color);
|
|
71
73
|
}
|
|
72
|
-
this.vertexCache.
|
|
73
|
-
|
|
74
|
+
this.vertexCache.setCache(resBuffer);
|
|
75
|
+
return resBuffer;
|
|
76
|
+
}
|
|
77
|
+
return this.vertexCache.getCache();
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
export class SimulationElement3d extends SimulationElement {
|
|
81
|
+
pos;
|
|
77
82
|
rotation;
|
|
78
|
-
wireframe = false;
|
|
79
|
-
wireframeCache;
|
|
80
83
|
constructor(pos, rotation = vector3(), color) {
|
|
81
|
-
super(
|
|
84
|
+
super(color, rotation);
|
|
85
|
+
this.pos = pos;
|
|
86
|
+
vector3ToPixelRatio(this.pos);
|
|
82
87
|
this.rotation = rotation;
|
|
83
|
-
this.wireframeCache = new VertexCache();
|
|
84
|
-
}
|
|
85
|
-
setWireframe(wireframe) {
|
|
86
|
-
this.wireframe = wireframe;
|
|
87
|
-
}
|
|
88
|
-
isWireframe() {
|
|
89
|
-
return this.wireframe;
|
|
90
88
|
}
|
|
91
89
|
rotate(amount, t = 0, f) {
|
|
92
90
|
const finalRotation = cloneBuf(this.rotation);
|
|
@@ -101,7 +99,7 @@ export class SimulationElement3d extends SimulationElement {
|
|
|
101
99
|
this.vertexCache.updated();
|
|
102
100
|
}, t, f);
|
|
103
101
|
}
|
|
104
|
-
|
|
102
|
+
rotateTo(rot, t = 0, f) {
|
|
105
103
|
const diff = vector3();
|
|
106
104
|
vec3.sub(rot, this.rotation, diff);
|
|
107
105
|
return transitionValues((p) => {
|
|
@@ -114,30 +112,39 @@ export class SimulationElement3d extends SimulationElement {
|
|
|
114
112
|
this.vertexCache.updated();
|
|
115
113
|
}, t, f);
|
|
116
114
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
115
|
+
move(amount, t = 0, f) {
|
|
116
|
+
const finalPos = cloneBuf(this.pos);
|
|
117
|
+
vec3.add(finalPos, amount, finalPos);
|
|
118
|
+
return transitionValues((p) => {
|
|
119
|
+
this.pos[0] += amount[0] * p;
|
|
120
|
+
this.pos[1] += amount[1] * p;
|
|
121
|
+
this.pos[2] += amount[2] * p;
|
|
122
|
+
this.vertexCache.updated();
|
|
123
|
+
}, () => {
|
|
124
|
+
this.pos = finalPos;
|
|
125
|
+
this.vertexCache.updated();
|
|
126
|
+
}, t, f);
|
|
127
|
+
}
|
|
128
|
+
moveTo(pos, t = 0, f) {
|
|
129
|
+
const diff = vector3();
|
|
130
|
+
vec3.sub(pos, this.pos, diff);
|
|
131
|
+
return transitionValues((p) => {
|
|
132
|
+
this.pos[0] += diff[0] * p;
|
|
133
|
+
this.pos[1] += diff[1] * p;
|
|
134
|
+
this.pos[2] += diff[2] * p;
|
|
135
|
+
this.vertexCache.updated();
|
|
136
|
+
}, () => {
|
|
137
|
+
this.pos = pos;
|
|
138
|
+
this.vertexCache.updated();
|
|
139
|
+
}, t, f);
|
|
135
140
|
}
|
|
136
141
|
}
|
|
137
142
|
export class SimulationElement2d extends SimulationElement {
|
|
143
|
+
pos;
|
|
138
144
|
rotation;
|
|
139
145
|
constructor(pos, rotation = 0, color) {
|
|
140
|
-
super(
|
|
146
|
+
super(color, rotation, false);
|
|
147
|
+
this.pos = pos;
|
|
141
148
|
this.rotation = rotation;
|
|
142
149
|
}
|
|
143
150
|
rotate(rotation, t = 0, f) {
|
|
@@ -150,7 +157,7 @@ export class SimulationElement2d extends SimulationElement {
|
|
|
150
157
|
this.vertexCache.updated();
|
|
151
158
|
}, t, f);
|
|
152
159
|
}
|
|
153
|
-
|
|
160
|
+
rotateTo(newRotation, t = 0, f) {
|
|
154
161
|
const diff = newRotation - this.rotation;
|
|
155
162
|
return transitionValues((p) => {
|
|
156
163
|
this.rotation += diff * p;
|
|
@@ -160,61 +167,53 @@ export class SimulationElement2d extends SimulationElement {
|
|
|
160
167
|
this.vertexCache.updated();
|
|
161
168
|
}, t, f);
|
|
162
169
|
}
|
|
170
|
+
move(amount, t = 0, f) {
|
|
171
|
+
const finalPos = vector2();
|
|
172
|
+
vec3.add(amount, this.pos, finalPos);
|
|
173
|
+
return transitionValues((p) => {
|
|
174
|
+
this.pos[0] += amount[0] * p;
|
|
175
|
+
this.pos[1] += amount[1] * p;
|
|
176
|
+
this.vertexCache.updated();
|
|
177
|
+
}, () => {
|
|
178
|
+
this.pos = finalPos;
|
|
179
|
+
this.vertexCache.updated();
|
|
180
|
+
}, t, f);
|
|
181
|
+
}
|
|
182
|
+
moveTo(pos, t = 0, f) {
|
|
183
|
+
const diff = vector2();
|
|
184
|
+
vec2.sub(pos, this.pos, diff);
|
|
185
|
+
return transitionValues((p) => {
|
|
186
|
+
this.pos[0] += diff[0] * p;
|
|
187
|
+
this.pos[1] += diff[1] * p;
|
|
188
|
+
this.vertexCache.updated();
|
|
189
|
+
}, () => {
|
|
190
|
+
this.pos = pos;
|
|
191
|
+
this.vertexCache.updated();
|
|
192
|
+
}, t, f);
|
|
193
|
+
}
|
|
163
194
|
}
|
|
164
195
|
export class Plane extends SimulationElement3d {
|
|
196
|
+
geometry;
|
|
165
197
|
points;
|
|
166
198
|
constructor(pos, points, color, rotation = vector3()) {
|
|
167
199
|
super(pos, rotation, color);
|
|
168
|
-
this.points = points;
|
|
169
200
|
this.rotation = rotation;
|
|
201
|
+
this.points = points;
|
|
202
|
+
this.geometry = new PlaneGeometry(points);
|
|
170
203
|
}
|
|
171
204
|
setPoints(newPoints) {
|
|
172
205
|
this.points = newPoints;
|
|
206
|
+
this.vertexCache.updated();
|
|
173
207
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const order = Array(this.points.length)
|
|
177
|
-
.fill(0)
|
|
178
|
-
.map((_, index) => index);
|
|
179
|
-
let front = 0;
|
|
180
|
-
let back = this.points.length - 1;
|
|
181
|
-
while (front < back) {
|
|
182
|
-
order.push(front, back);
|
|
183
|
-
front++;
|
|
184
|
-
back--;
|
|
185
|
-
}
|
|
186
|
-
const vertices = this.points.map((p) => p.getPos());
|
|
187
|
-
return this.wireframeFromVertexOrder(vertices, order);
|
|
188
|
-
}
|
|
189
|
-
return this.wireframeCache.getCache();
|
|
190
|
-
}
|
|
191
|
-
getTriangles(_, force) {
|
|
192
|
-
if (this.vertexCache.shouldUpdate() || force) {
|
|
193
|
-
let resBuffer = [];
|
|
194
|
-
const triangles = lossyTriangulate(this.points).flat();
|
|
195
|
-
triangles.forEach((verticy) => {
|
|
196
|
-
const rot = quat.create();
|
|
197
|
-
quat.fromEuler(...this.rotation, 'xyz', rot);
|
|
198
|
-
const mat = mat4.create();
|
|
199
|
-
mat4.fromQuat(rot, mat);
|
|
200
|
-
const out = vector3();
|
|
201
|
-
vec3.transformMat4(verticy.getPos(), mat, out);
|
|
202
|
-
vec3.add(out, this.getPos(), out);
|
|
203
|
-
let vertexColor = verticy.getColor();
|
|
204
|
-
vertexColor = vertexColor ? vertexColor : this.getColor();
|
|
205
|
-
resBuffer = resBuffer.concat(vertexBuffer(out[0], out[1], out[2], vertexColor));
|
|
206
|
-
});
|
|
207
|
-
this.vertexCache.setCache(resBuffer);
|
|
208
|
-
return resBuffer;
|
|
209
|
-
}
|
|
210
|
-
return this.vertexCache.getCache();
|
|
208
|
+
updateMatrix(camera) {
|
|
209
|
+
this.defaultUpdateMatrix(camera);
|
|
211
210
|
}
|
|
212
211
|
}
|
|
213
212
|
export class Square extends SimulationElement2d {
|
|
213
|
+
geometry;
|
|
214
214
|
width;
|
|
215
215
|
height;
|
|
216
216
|
vertexColors;
|
|
217
|
-
points;
|
|
218
217
|
/**
|
|
219
218
|
* @param vertexColors{Record<number, Color>} - 0 is top left vertex, numbers increase clockwise
|
|
220
219
|
*/
|
|
@@ -222,22 +221,62 @@ export class Square extends SimulationElement2d {
|
|
|
222
221
|
super(pos, rotation, color);
|
|
223
222
|
this.width = width * devicePixelRatio;
|
|
224
223
|
this.height = height * devicePixelRatio;
|
|
225
|
-
this.vertexColors = vertexColors || {};
|
|
226
|
-
this.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
]
|
|
224
|
+
this.vertexColors = this.cloneColorMap(vertexColors || {});
|
|
225
|
+
this.geometry = new SquareGeometry(this.width, this.height);
|
|
226
|
+
this.geometry.setVertexColorMap(this.vertexColors);
|
|
227
|
+
}
|
|
228
|
+
cloneColorMap(colorMap) {
|
|
229
|
+
const newColorMap = {};
|
|
230
|
+
Object.entries(colorMap).forEach(([key, value]) => {
|
|
231
|
+
newColorMap[+key] = value.clone();
|
|
232
|
+
});
|
|
233
|
+
return newColorMap;
|
|
234
|
+
}
|
|
235
|
+
setVertexColors(newColorMap, t = 0, f) {
|
|
236
|
+
const colorMap = this.cloneColorMap(newColorMap);
|
|
237
|
+
const diffMap = {};
|
|
238
|
+
Object.entries(colorMap).forEach(([key, value]) => {
|
|
239
|
+
if (!this.vertexColors[+key]) {
|
|
240
|
+
this.vertexColors[+key] = color();
|
|
241
|
+
}
|
|
242
|
+
diffMap[+key] = value.diff(this.vertexColors[+key] || color());
|
|
243
|
+
});
|
|
244
|
+
Object.entries(this.vertexColors).forEach(([key, value]) => {
|
|
245
|
+
if (!diffMap[+key]) {
|
|
246
|
+
const clone = value.clone();
|
|
247
|
+
clone.r *= -1;
|
|
248
|
+
clone.g *= -1;
|
|
249
|
+
clone.b *= -1;
|
|
250
|
+
diffMap[+key] = clone;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
return transitionValues((p) => {
|
|
254
|
+
Object.entries(diffMap).forEach(([key, value]) => {
|
|
255
|
+
const color = this.vertexColors[+key];
|
|
256
|
+
color.r += value.r * p;
|
|
257
|
+
color.g += value.g * p;
|
|
258
|
+
color.b += value.b * p;
|
|
259
|
+
color.a += value.a * p;
|
|
260
|
+
this.vertexColors[+key] = color;
|
|
261
|
+
});
|
|
262
|
+
this.geometry.setVertexColorMap(this.vertexColors);
|
|
263
|
+
this.vertexCache.updated();
|
|
264
|
+
}, () => {
|
|
265
|
+
this.vertexColors = colorMap;
|
|
266
|
+
this.geometry.setVertexColorMap(this.vertexColors);
|
|
267
|
+
this.vertexCache.updated();
|
|
268
|
+
}, t, f);
|
|
232
269
|
}
|
|
233
270
|
scaleWidth(amount, t = 0, f) {
|
|
234
271
|
const finalWidth = this.width * amount;
|
|
235
272
|
const diffWidth = finalWidth - this.width;
|
|
236
273
|
return transitionValues((p) => {
|
|
237
274
|
this.width += diffWidth * p;
|
|
275
|
+
this.geometry.setWidth(this.width);
|
|
238
276
|
this.vertexCache.updated();
|
|
239
277
|
}, () => {
|
|
240
278
|
this.width = finalWidth;
|
|
279
|
+
this.geometry.setWidth(this.width);
|
|
241
280
|
this.vertexCache.updated();
|
|
242
281
|
}, t, f);
|
|
243
282
|
}
|
|
@@ -246,9 +285,11 @@ export class Square extends SimulationElement2d {
|
|
|
246
285
|
const diffHeight = finalHeight - this.height;
|
|
247
286
|
return transitionValues((p) => {
|
|
248
287
|
this.height += diffHeight * p;
|
|
288
|
+
this.geometry.setHeight(this.height);
|
|
249
289
|
this.vertexCache.updated();
|
|
250
290
|
}, () => {
|
|
251
291
|
this.height = finalHeight;
|
|
292
|
+
this.geometry.setHeight(this.height);
|
|
252
293
|
this.vertexCache.updated();
|
|
253
294
|
}, t, f);
|
|
254
295
|
}
|
|
@@ -260,10 +301,14 @@ export class Square extends SimulationElement2d {
|
|
|
260
301
|
return transitionValues((p) => {
|
|
261
302
|
this.width += diffWidth * p;
|
|
262
303
|
this.height += diffHeight * p;
|
|
304
|
+
this.geometry.setWidth(this.width);
|
|
305
|
+
this.geometry.setHeight(this.height);
|
|
263
306
|
this.vertexCache.updated();
|
|
264
307
|
}, () => {
|
|
265
308
|
this.width = finalWidth;
|
|
266
309
|
this.height = finalHeight;
|
|
310
|
+
this.geometry.setWidth(this.width);
|
|
311
|
+
this.geometry.setHeight(this.height);
|
|
267
312
|
this.vertexCache.updated();
|
|
268
313
|
}, t, f);
|
|
269
314
|
}
|
|
@@ -272,9 +317,11 @@ export class Square extends SimulationElement2d {
|
|
|
272
317
|
const diffWidth = num - this.width;
|
|
273
318
|
return transitionValues((p) => {
|
|
274
319
|
this.width += diffWidth * p;
|
|
320
|
+
this.geometry.setWidth(this.width);
|
|
275
321
|
this.vertexCache.updated();
|
|
276
322
|
}, () => {
|
|
277
323
|
this.width = num;
|
|
324
|
+
this.geometry.setWidth(this.width);
|
|
278
325
|
this.vertexCache.updated();
|
|
279
326
|
}, t, f);
|
|
280
327
|
}
|
|
@@ -283,56 +330,45 @@ export class Square extends SimulationElement2d {
|
|
|
283
330
|
const diffHeight = num - this.height;
|
|
284
331
|
return transitionValues((p) => {
|
|
285
332
|
this.height += diffHeight * p;
|
|
333
|
+
this.geometry.setHeight(this.height);
|
|
286
334
|
this.vertexCache.updated();
|
|
287
335
|
}, () => {
|
|
288
336
|
this.height = num;
|
|
337
|
+
this.geometry.setHeight(this.height);
|
|
289
338
|
this.vertexCache.updated();
|
|
290
339
|
}, t, f);
|
|
291
340
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
vec2.add(vec, this.getPos(), pos);
|
|
302
|
-
pos[1] = camera.getScreenSize()[1] - pos[1];
|
|
303
|
-
pos[0] += this.width / 2;
|
|
304
|
-
pos[1] -= this.height / 2;
|
|
305
|
-
return pos;
|
|
306
|
-
});
|
|
307
|
-
let resBuffer = vertexOrder
|
|
308
|
-
.map((vertex) => {
|
|
309
|
-
let vertexColor = this.vertexColors[vertex];
|
|
310
|
-
vertexColor = vertexColor ? vertexColor : this.getColor();
|
|
311
|
-
return vertexBuffer(points[vertex][0], points[vertex][1], 0, vertexColor);
|
|
312
|
-
})
|
|
313
|
-
.flat();
|
|
314
|
-
this.vertexCache.setCache(resBuffer);
|
|
315
|
-
return resBuffer;
|
|
316
|
-
}
|
|
317
|
-
return this.vertexCache.getCache();
|
|
341
|
+
updateMatrix(camera) {
|
|
342
|
+
const pos = cloneBuf(this.pos);
|
|
343
|
+
pos[1] = camera.getScreenSize()[1] - pos[1];
|
|
344
|
+
pos[0] += this.width / 2;
|
|
345
|
+
pos[1] -= this.height / 2;
|
|
346
|
+
const matrix = matrix4();
|
|
347
|
+
mat4.translate(matrix, vector3FromVector2(pos), matrix);
|
|
348
|
+
mat4.rotateZ(matrix, this.rotation, matrix);
|
|
349
|
+
this.geometry.updateMatrix(matrix);
|
|
318
350
|
}
|
|
319
351
|
}
|
|
320
352
|
export class Circle extends SimulationElement2d {
|
|
353
|
+
geometry;
|
|
321
354
|
radius;
|
|
322
355
|
detail;
|
|
323
356
|
constructor(pos, radius, color, detail = 50) {
|
|
324
357
|
super(pos, 0, color);
|
|
325
|
-
this.radius = radius
|
|
358
|
+
this.radius = radius;
|
|
326
359
|
this.detail = detail;
|
|
360
|
+
this.geometry = new CircleGeometry(this.radius, this.detail);
|
|
327
361
|
}
|
|
328
362
|
setRadius(num, t = 0, f) {
|
|
329
363
|
num *= devicePixelRatio;
|
|
330
364
|
const diff = num - this.radius;
|
|
331
365
|
return transitionValues((p) => {
|
|
332
366
|
this.radius += diff * p;
|
|
367
|
+
this.geometry.setRadius(this.radius);
|
|
333
368
|
this.vertexCache.updated();
|
|
334
369
|
}, () => {
|
|
335
370
|
this.radius = num;
|
|
371
|
+
this.geometry.setRadius(this.radius);
|
|
336
372
|
this.vertexCache.updated();
|
|
337
373
|
}, t, f);
|
|
338
374
|
}
|
|
@@ -341,45 +377,26 @@ export class Circle extends SimulationElement2d {
|
|
|
341
377
|
const diff = finalRadius - this.radius;
|
|
342
378
|
return transitionValues((p) => {
|
|
343
379
|
this.radius += diff * p;
|
|
380
|
+
this.geometry.setRadius(this.radius);
|
|
344
381
|
this.vertexCache.updated();
|
|
345
382
|
}, () => {
|
|
346
383
|
this.radius = finalRadius;
|
|
384
|
+
this.geometry.setRadius(this.radius);
|
|
347
385
|
this.vertexCache.updated();
|
|
348
386
|
}, t, f);
|
|
349
387
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const points = [];
|
|
353
|
-
const rotationInc = (Math.PI * 2) / this.detail;
|
|
354
|
-
for (let i = 0; i < this.detail; i++) {
|
|
355
|
-
const mat = mat4.identity();
|
|
356
|
-
mat4.rotateZ(mat, rotationInc * i, mat);
|
|
357
|
-
const vec = vector3(this.radius);
|
|
358
|
-
vec3.transformMat4(vec, mat, vec);
|
|
359
|
-
vec3.add(vec, this.getPos(), vec);
|
|
360
|
-
const screenSize = camera.getScreenSize();
|
|
361
|
-
points.push(new Vertex(vec[0], screenSize[1] - vec[1], vec[2], this.getColor(), false));
|
|
362
|
-
}
|
|
363
|
-
const vertices = lossyTriangulate(points).reduce((acc, curr) => {
|
|
364
|
-
curr.forEach((vertex) => acc.push(...vertex.toBuffer(this.getColor())));
|
|
365
|
-
return acc;
|
|
366
|
-
}, []);
|
|
367
|
-
this.vertexCache.setCache(vertices);
|
|
368
|
-
return vertices;
|
|
369
|
-
}
|
|
370
|
-
return this.vertexCache.getCache();
|
|
388
|
+
updateMatrix(camera) {
|
|
389
|
+
this.defaultUpdateMatrix(camera);
|
|
371
390
|
}
|
|
372
391
|
}
|
|
392
|
+
// TODO: litterally this whole thing
|
|
373
393
|
export class Polygon extends SimulationElement2d {
|
|
394
|
+
geometry;
|
|
374
395
|
vertices;
|
|
375
|
-
constructor(pos,
|
|
396
|
+
constructor(pos, points, color, rotation) {
|
|
376
397
|
super(pos, rotation, color);
|
|
377
|
-
this.vertices =
|
|
378
|
-
|
|
379
|
-
newVertex.setZ(0);
|
|
380
|
-
newVertex.setIs3d(false);
|
|
381
|
-
return vertex;
|
|
382
|
-
});
|
|
398
|
+
this.vertices = points;
|
|
399
|
+
this.geometry = new PolygonGeometry(this.vertices);
|
|
383
400
|
}
|
|
384
401
|
getVertices() {
|
|
385
402
|
return this.vertices;
|
|
@@ -395,7 +412,7 @@ export class Polygon extends SimulationElement2d {
|
|
|
395
412
|
if (vertices.length > this.vertices.length) {
|
|
396
413
|
while (vertices.length > this.vertices.length) {
|
|
397
414
|
const lastPos = lastVert.getPos();
|
|
398
|
-
this.vertices.push(new Vertex(lastPos[0], lastPos[1], 0, lastVert.getColor() || this.
|
|
415
|
+
this.vertices.push(new Vertex(lastPos[0], lastPos[1], 0, lastVert.getColor() || this.color, false));
|
|
399
416
|
}
|
|
400
417
|
}
|
|
401
418
|
const initialPositions = this.vertices.map((p) => cloneBuf(p.getPos()));
|
|
@@ -413,16 +430,16 @@ export class Polygon extends SimulationElement2d {
|
|
|
413
430
|
})
|
|
414
431
|
: [])
|
|
415
432
|
];
|
|
416
|
-
const initialColors = this.vertices.map((vert) => (vert.getColor() || this.
|
|
433
|
+
const initialColors = this.vertices.map((vert) => (vert.getColor() || this.color).toVec4());
|
|
417
434
|
const colorChanges = [
|
|
418
435
|
...vertices.map((vert, i) => {
|
|
419
|
-
const diff = (vert.getColor() || this.
|
|
436
|
+
const diff = (vert.getColor() || this.color).diff(this.vertices[i].getColor() || this.color);
|
|
420
437
|
return diff.toVec4();
|
|
421
438
|
}),
|
|
422
439
|
...(this.vertices.length > vertices.length
|
|
423
440
|
? this.vertices.slice(vertices.length, this.vertices.length).map((vert) => {
|
|
424
441
|
const toColor = vertices[vertices.length - 1].getColor();
|
|
425
|
-
return (toColor || this.
|
|
442
|
+
return (toColor || this.color).diff(vert.getColor() || this.color).toVec4();
|
|
426
443
|
})
|
|
427
444
|
: [])
|
|
428
445
|
];
|
|
@@ -433,7 +450,7 @@ export class Polygon extends SimulationElement2d {
|
|
|
433
450
|
vec3.scale(posChange, p, posChange);
|
|
434
451
|
vec3.add(vert.getPos(), posChange, posChange);
|
|
435
452
|
vec4.scale(colorChange, p, colorChange);
|
|
436
|
-
vec4.add((vert.getColor() || this.
|
|
453
|
+
vec4.add((vert.getColor() || this.color).toVec4(), colorChange, colorChange);
|
|
437
454
|
vert.setPos(posChange);
|
|
438
455
|
vert.setColor(colorFromVector4(colorChange));
|
|
439
456
|
});
|
|
@@ -451,38 +468,21 @@ export class Polygon extends SimulationElement2d {
|
|
|
451
468
|
this.vertexCache.updated();
|
|
452
469
|
}, t, f);
|
|
453
470
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
let resBuffer = [];
|
|
457
|
-
const rotationMat = mat4.identity();
|
|
458
|
-
mat4.rotateZ(rotationMat, this.rotation, rotationMat);
|
|
459
|
-
lossyTriangulate(this.vertices)
|
|
460
|
-
.flat()
|
|
461
|
-
.forEach((vert) => {
|
|
462
|
-
const pos = vector3();
|
|
463
|
-
vec3.add(vert.getPos(), pos, pos);
|
|
464
|
-
vec3.transformMat4(pos, rotationMat, pos);
|
|
465
|
-
vec3.add(this.getPos(), pos, pos);
|
|
466
|
-
pos[1] = camera.getScreenSize()[1] - pos[1];
|
|
467
|
-
resBuffer = resBuffer.concat(vertexBuffer(pos[0], pos[1], 0, vert.getColor() || this.getColor()));
|
|
468
|
-
});
|
|
469
|
-
this.vertexCache.setCache(resBuffer);
|
|
470
|
-
return resBuffer;
|
|
471
|
-
}
|
|
472
|
-
return this.vertexCache.getCache();
|
|
471
|
+
updateMatrix(camera) {
|
|
472
|
+
this.defaultUpdateMatrix(camera);
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
export class Line3d extends SimulationElement3d {
|
|
476
|
+
geometry;
|
|
476
477
|
to;
|
|
477
|
-
toColor;
|
|
478
478
|
thickness;
|
|
479
479
|
constructor(pos, to, thickness) {
|
|
480
480
|
super(pos.getPos(), vector3(), to.getColor() || undefined);
|
|
481
481
|
this.thickness = thickness;
|
|
482
|
-
this.toColor = to.getColor() || this.getColor();
|
|
483
482
|
this.to = to.getPos();
|
|
484
483
|
vec3.scale(this.to, devicePixelRatio, this.to);
|
|
485
|
-
vec3.sub(this.to, this.
|
|
484
|
+
vec3.sub(this.to, this.pos, this.to);
|
|
485
|
+
this.geometry = new Line3dGeometry(this.pos, this.to, this.thickness);
|
|
486
486
|
}
|
|
487
487
|
setStart(pos, t = 0, f) {
|
|
488
488
|
return this.moveTo(pos, t, f);
|
|
@@ -502,72 +502,24 @@ export class Line3d extends SimulationElement3d {
|
|
|
502
502
|
this.vertexCache.updated();
|
|
503
503
|
}, t, f);
|
|
504
504
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
const normal = vector2(-this.to[1], this.to[0]);
|
|
508
|
-
vec2.normalize(normal, normal);
|
|
509
|
-
vec2.scale(normal, this.thickness / 2, normal);
|
|
510
|
-
const vertices = [
|
|
511
|
-
vector3(normal[0], normal[1]),
|
|
512
|
-
vector3(-normal[0], -normal[1]),
|
|
513
|
-
vector3(this.to[0] + normal[0], this.to[1] + normal[1], this.to[2]),
|
|
514
|
-
vector3(this.to[0] - normal[0], this.to[1] - normal[1], this.to[2])
|
|
515
|
-
];
|
|
516
|
-
const order = [0, 1, 3, 2, 0, 3];
|
|
517
|
-
return this.wireframeFromVertexOrder(vertices, order);
|
|
518
|
-
}
|
|
519
|
-
return this.wireframeCache.getCache();
|
|
520
|
-
}
|
|
521
|
-
getTriangles(_, force) {
|
|
522
|
-
if (this.vertexCache.shouldUpdate() || force) {
|
|
523
|
-
const normal = vector2(-this.to[1], this.to[0]);
|
|
524
|
-
vec2.normalize(normal, normal);
|
|
525
|
-
vec2.scale(normal, this.thickness / 2, normal);
|
|
526
|
-
const pos = this.getPos();
|
|
527
|
-
const resBuffer = [
|
|
528
|
-
...vertexBuffer(pos[0] + normal[0], pos[1] + normal[1], pos[2], this.getColor()),
|
|
529
|
-
...vertexBuffer(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
|
|
530
|
-
...vertexBuffer(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
|
|
531
|
-
...vertexBuffer(pos[0] - normal[0], pos[1] - normal[1], pos[2], this.getColor()),
|
|
532
|
-
...vertexBuffer(pos[0] + this.to[0] + normal[0], pos[1] + this.to[1] + normal[1], pos[2] + this.to[2], this.toColor || this.getColor()),
|
|
533
|
-
...vertexBuffer(pos[0] + this.to[0] - normal[0], pos[1] + this.to[1] - normal[1], pos[2] + this.to[2], this.toColor || this.getColor())
|
|
534
|
-
];
|
|
535
|
-
this.vertexCache.setCache(resBuffer);
|
|
536
|
-
return resBuffer;
|
|
537
|
-
}
|
|
538
|
-
return this.vertexCache.getCache();
|
|
505
|
+
updateMatrix(camera) {
|
|
506
|
+
return this.defaultUpdateMatrix(camera);
|
|
539
507
|
}
|
|
540
508
|
}
|
|
541
|
-
export class Line2d extends
|
|
509
|
+
export class Line2d extends SimulationElement2d {
|
|
510
|
+
geometry;
|
|
542
511
|
to;
|
|
543
|
-
toColor;
|
|
544
512
|
thickness;
|
|
545
513
|
constructor(from, to, thickness = 1) {
|
|
546
|
-
super(from.getPos(), from.getColor() || undefined);
|
|
514
|
+
super(vector2FromVector3(from.getPos()), 0, from.getColor() || undefined);
|
|
547
515
|
this.thickness = thickness * devicePixelRatio;
|
|
548
|
-
this.toColor = to.getColor();
|
|
549
516
|
this.to = vector2FromVector3(to.getPos());
|
|
550
517
|
vec2.scale(this.to, devicePixelRatio, this.to);
|
|
551
|
-
vec2.sub(this.to, this.
|
|
552
|
-
|
|
553
|
-
setEndColor(newColor, t = 0, f) {
|
|
554
|
-
if (!this.toColor)
|
|
555
|
-
this.toColor = this.getColor();
|
|
556
|
-
const diff = newColor.diff(this.toColor);
|
|
557
|
-
const finalColor = newColor.clone();
|
|
558
|
-
return transitionValues((p) => {
|
|
559
|
-
this.toColor.r += diff.r * p;
|
|
560
|
-
this.toColor.g += diff.g * p;
|
|
561
|
-
this.toColor.b += diff.b * p;
|
|
562
|
-
this.toColor.a += diff.a * p;
|
|
563
|
-
this.vertexCache.updated();
|
|
564
|
-
}, () => {
|
|
565
|
-
this.toColor = finalColor;
|
|
566
|
-
this.vertexCache.updated();
|
|
567
|
-
}, t, f);
|
|
518
|
+
vec2.sub(this.to, this.pos, this.to);
|
|
519
|
+
this.geometry = new Line2dGeometry(this.pos, this.to, this.thickness);
|
|
568
520
|
}
|
|
569
521
|
setStart(pos, t = 0, f) {
|
|
570
|
-
return this.moveTo(
|
|
522
|
+
return this.moveTo(pos, t, f);
|
|
571
523
|
}
|
|
572
524
|
setEnd(pos, t = 0, f) {
|
|
573
525
|
const diff = vector3();
|
|
@@ -582,103 +534,33 @@ export class Line2d extends SimulationElement {
|
|
|
582
534
|
this.vertexCache.updated();
|
|
583
535
|
}, t, f);
|
|
584
536
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
const normal = vector2(-this.to[1], this.to[0]);
|
|
588
|
-
vec2.normalize(normal, normal);
|
|
589
|
-
vec2.scale(normal, this.thickness / 2, normal);
|
|
590
|
-
const screenSize = camera.getScreenSize();
|
|
591
|
-
const pos = this.getPos();
|
|
592
|
-
const resBuffer = [
|
|
593
|
-
...vertexBuffer(pos[0] + normal[0], screenSize[1] - pos[1] + normal[1], 0, this.getColor()),
|
|
594
|
-
...vertexBuffer(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], 0, this.getColor()),
|
|
595
|
-
...vertexBuffer(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], 0, this.toColor || this.getColor()),
|
|
596
|
-
...vertexBuffer(pos[0] - normal[0], screenSize[1] - pos[1] - normal[1], 0, this.getColor()),
|
|
597
|
-
...vertexBuffer(pos[0] + this.to[0] + normal[0], screenSize[1] - pos[1] + this.to[1] + normal[1], 0, this.toColor || this.getColor()),
|
|
598
|
-
...vertexBuffer(pos[0] + this.to[0] - normal[0], screenSize[1] - pos[1] + this.to[1] - normal[1], 0, this.toColor || this.getColor())
|
|
599
|
-
];
|
|
600
|
-
this.vertexCache.setCache(resBuffer);
|
|
601
|
-
return resBuffer;
|
|
602
|
-
}
|
|
603
|
-
return this.vertexCache.getCache();
|
|
537
|
+
updateMatrix(camera) {
|
|
538
|
+
return this.defaultUpdateMatrix(camera);
|
|
604
539
|
}
|
|
605
540
|
}
|
|
606
541
|
export class Cube extends SimulationElement3d {
|
|
607
|
-
|
|
542
|
+
geometry;
|
|
608
543
|
width;
|
|
609
544
|
height;
|
|
610
545
|
depth;
|
|
611
|
-
wireframeLines;
|
|
612
|
-
static wireframeOrder = [
|
|
613
|
-
[0, 1],
|
|
614
|
-
[1, 2],
|
|
615
|
-
[2, 3],
|
|
616
|
-
[3, 0],
|
|
617
|
-
[4, 5],
|
|
618
|
-
[5, 6],
|
|
619
|
-
[6, 7],
|
|
620
|
-
[7, 4],
|
|
621
|
-
[0, 4],
|
|
622
|
-
[3, 7],
|
|
623
|
-
[1, 5],
|
|
624
|
-
[2, 6]
|
|
625
|
-
];
|
|
626
546
|
constructor(pos, width, height, depth, color, rotation) {
|
|
627
547
|
super(pos, rotation, color);
|
|
628
548
|
this.width = width * devicePixelRatio;
|
|
629
549
|
this.height = height * devicePixelRatio;
|
|
630
550
|
this.depth = depth * devicePixelRatio;
|
|
631
551
|
this.rotation = rotation || vector3();
|
|
632
|
-
this.
|
|
633
|
-
const numWireframeLines = 12;
|
|
634
|
-
const lineThickness = 0.025;
|
|
635
|
-
for (let i = 0; i < numWireframeLines; i++) {
|
|
636
|
-
this.wireframeLines.push(new Line3d(vertex(), vertex(), lineThickness));
|
|
637
|
-
}
|
|
638
|
-
this.vertices = [];
|
|
639
|
-
this.computeVertices();
|
|
640
|
-
this.shiftWireframeLines();
|
|
641
|
-
}
|
|
642
|
-
computeVertices() {
|
|
643
|
-
this.vertices = [
|
|
644
|
-
// front face
|
|
645
|
-
vector3(-this.width / 2, -this.height / 2, this.depth / 2),
|
|
646
|
-
vector3(this.width / 2, -this.height / 2, this.depth / 2),
|
|
647
|
-
vector3(this.width / 2, this.height / 2, this.depth / 2),
|
|
648
|
-
vector3(-this.width / 2, this.height / 2, this.depth / 2),
|
|
649
|
-
// back face
|
|
650
|
-
vector3(-this.width / 2, -this.height / 2, -this.depth / 2),
|
|
651
|
-
vector3(this.width / 2, -this.height / 2, -this.depth / 2),
|
|
652
|
-
vector3(this.width / 2, this.height / 2, -this.depth / 2),
|
|
653
|
-
vector3(-this.width / 2, this.height / 2, -this.depth / 2)
|
|
654
|
-
];
|
|
655
|
-
}
|
|
656
|
-
shiftWireframeLines() {
|
|
657
|
-
let rotMatrix = mat4.identity();
|
|
658
|
-
mat4.rotateZ(rotMatrix, this.rotation[2], rotMatrix);
|
|
659
|
-
mat4.rotateY(rotMatrix, this.rotation[1], rotMatrix);
|
|
660
|
-
mat4.rotateX(rotMatrix, this.rotation[0], rotMatrix);
|
|
661
|
-
const pos = this.getPos();
|
|
662
|
-
Cube.wireframeOrder.forEach((lineVertices, index) => {
|
|
663
|
-
const line = this.wireframeLines[index];
|
|
664
|
-
const start = cloneBuf(this.vertices[lineVertices[0]]);
|
|
665
|
-
const endPoint = cloneBuf(this.vertices[lineVertices[1]]);
|
|
666
|
-
vec3.sub(endPoint, start, endPoint);
|
|
667
|
-
vec3.transformMat4(endPoint, rotMatrix, endPoint);
|
|
668
|
-
vec3.transformMat4(start, rotMatrix, start);
|
|
669
|
-
vec3.add(start, pos, start);
|
|
670
|
-
line.setStart(start);
|
|
671
|
-
line.setEnd(endPoint);
|
|
672
|
-
});
|
|
552
|
+
this.geometry = new CubeGeometry(this.width, this.height, this.depth);
|
|
673
553
|
}
|
|
674
554
|
setWidth(width, t = 0, f) {
|
|
675
555
|
width *= devicePixelRatio;
|
|
676
556
|
const diff = width - this.width;
|
|
677
557
|
return transitionValues((p) => {
|
|
678
558
|
this.width += diff * p;
|
|
559
|
+
this.geometry.setWidth(this.width);
|
|
679
560
|
this.vertexCache.updated();
|
|
680
561
|
}, () => {
|
|
681
562
|
this.width = width;
|
|
563
|
+
this.geometry.setWidth(this.width);
|
|
682
564
|
this.vertexCache.updated();
|
|
683
565
|
}, t, f);
|
|
684
566
|
}
|
|
@@ -687,9 +569,11 @@ export class Cube extends SimulationElement3d {
|
|
|
687
569
|
const diff = height - this.width;
|
|
688
570
|
return transitionValues((p) => {
|
|
689
571
|
this.height += diff * p;
|
|
572
|
+
this.geometry.setHeight(this.height);
|
|
690
573
|
this.vertexCache.updated();
|
|
691
574
|
}, () => {
|
|
692
575
|
this.height = height;
|
|
576
|
+
this.geometry.setHeight(this.height);
|
|
693
577
|
this.vertexCache.updated();
|
|
694
578
|
}, t, f);
|
|
695
579
|
}
|
|
@@ -698,9 +582,11 @@ export class Cube extends SimulationElement3d {
|
|
|
698
582
|
const diff = depth - this.width;
|
|
699
583
|
return transitionValues((p) => {
|
|
700
584
|
this.depth += diff * p;
|
|
585
|
+
this.geometry.setDepth(this.depth);
|
|
701
586
|
this.vertexCache.updated();
|
|
702
587
|
}, () => {
|
|
703
588
|
this.depth = depth;
|
|
589
|
+
this.geometry.setDepth(this.depth);
|
|
704
590
|
this.vertexCache.updated();
|
|
705
591
|
}, t, f);
|
|
706
592
|
}
|
|
@@ -715,55 +601,22 @@ export class Cube extends SimulationElement3d {
|
|
|
715
601
|
this.width += widthDiff * p;
|
|
716
602
|
this.height += heightDiff * p;
|
|
717
603
|
this.depth += depthDiff * p;
|
|
604
|
+
this.geometry.setWidth(this.width);
|
|
605
|
+
this.geometry.setHeight(this.height);
|
|
606
|
+
this.geometry.setDepth(this.depth);
|
|
718
607
|
this.vertexCache.updated();
|
|
719
608
|
}, () => {
|
|
720
609
|
this.width = finalWidth;
|
|
721
610
|
this.height = finalHeight;
|
|
722
611
|
this.depth = finalDepth;
|
|
612
|
+
this.geometry.setWidth(this.width);
|
|
613
|
+
this.geometry.setHeight(this.height);
|
|
614
|
+
this.geometry.setDepth(this.depth);
|
|
723
615
|
this.vertexCache.updated();
|
|
724
616
|
}, t, f);
|
|
725
617
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
// prettier-ignore
|
|
729
|
-
const lineOrder = [
|
|
730
|
-
0, 1, 2, 3, 0, 2,
|
|
731
|
-
6, 5, 1, 6,
|
|
732
|
-
7, 4, 5, 7,
|
|
733
|
-
3, 4, 0,
|
|
734
|
-
5, 6, 3
|
|
735
|
-
];
|
|
736
|
-
return this.wireframeFromVertexOrder(this.vertices, lineOrder);
|
|
737
|
-
}
|
|
738
|
-
return this.wireframeCache.getCache();
|
|
739
|
-
}
|
|
740
|
-
getTriangles(_, force) {
|
|
741
|
-
if (this.vertexCache.shouldUpdate() || force) {
|
|
742
|
-
this.computeVertices();
|
|
743
|
-
this.shiftWireframeLines();
|
|
744
|
-
const triangleOrder = [
|
|
745
|
-
0, 1, 2, 0, 2, 3,
|
|
746
|
-
4, 5, 6, 4, 6, 7,
|
|
747
|
-
0, 3, 7, 0, 7, 4,
|
|
748
|
-
0, 4, 5, 0, 5, 1,
|
|
749
|
-
1, 2, 6, 1, 5, 6,
|
|
750
|
-
2, 3, 7, 2, 6, 7
|
|
751
|
-
];
|
|
752
|
-
let rotMatrix = mat4.identity();
|
|
753
|
-
mat4.rotateZ(rotMatrix, this.rotation[2], rotMatrix);
|
|
754
|
-
mat4.rotateY(rotMatrix, this.rotation[1], rotMatrix);
|
|
755
|
-
mat4.rotateX(rotMatrix, this.rotation[0], rotMatrix);
|
|
756
|
-
const pos = this.getPos();
|
|
757
|
-
let resBuffer = [];
|
|
758
|
-
triangleOrder.forEach((index) => {
|
|
759
|
-
const vertex = cloneBuf(this.vertices[index]);
|
|
760
|
-
vec3.transformMat4(vertex, rotMatrix, vertex);
|
|
761
|
-
resBuffer = resBuffer.concat(vertexBuffer(vertex[0] + pos[0], vertex[1] + pos[1], vertex[2] + pos[2], this.getColor()));
|
|
762
|
-
});
|
|
763
|
-
this.vertexCache.setCache(resBuffer);
|
|
764
|
-
return resBuffer;
|
|
765
|
-
}
|
|
766
|
-
return this.vertexCache.getCache();
|
|
618
|
+
updateMatrix(camera) {
|
|
619
|
+
this.defaultUpdateMatrix(camera);
|
|
767
620
|
}
|
|
768
621
|
}
|
|
769
622
|
export class BezierCurve2d {
|
|
@@ -891,45 +744,31 @@ export class SplinePoint2d {
|
|
|
891
744
|
];
|
|
892
745
|
}
|
|
893
746
|
}
|
|
894
|
-
export class Spline2d extends
|
|
747
|
+
export class Spline2d extends SimulationElement2d {
|
|
748
|
+
geometry;
|
|
895
749
|
curves;
|
|
896
750
|
thickness;
|
|
897
751
|
detail;
|
|
898
752
|
interpolateStart;
|
|
899
753
|
interpolateLimit;
|
|
900
|
-
distance;
|
|
901
754
|
constructor(pos, points, thickness = devicePixelRatio, detail = 40) {
|
|
902
|
-
super(pos.getPos(), pos.getColor() || undefined);
|
|
755
|
+
super(vector2FromVector3(pos.getPos()), 0, pos.getColor() || undefined);
|
|
903
756
|
this.curves = [];
|
|
904
757
|
this.thickness = thickness * devicePixelRatio;
|
|
905
758
|
this.detail = detail;
|
|
906
759
|
this.interpolateStart = 0;
|
|
907
760
|
this.interpolateLimit = 1;
|
|
908
|
-
this.
|
|
909
|
-
for (let i = 0; i < points.length; i++) {
|
|
910
|
-
let prevControl = null;
|
|
911
|
-
let prevColor = null;
|
|
912
|
-
if (i > 0) {
|
|
913
|
-
prevControl = cloneBuf(points[i - 1].getRawControls()[1]);
|
|
914
|
-
vec2.negate(prevControl, prevControl);
|
|
915
|
-
const prevColors = points[i - 1].getColors();
|
|
916
|
-
if (prevColors.at(-1)) {
|
|
917
|
-
prevColor = prevColors.at(-1) || null;
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
const bezierPoints = points[i].getVectorArray(i > 0 ? vector2FromVector3(points[i - 1].getEnd().getPos()) : null, prevControl);
|
|
921
|
-
const curve = new CubicBezierCurve2d(bezierPoints, points[i].getDetail(), points[i].getColors(prevColor));
|
|
922
|
-
this.distance += curve.getLength();
|
|
923
|
-
this.curves.push(curve);
|
|
924
|
-
}
|
|
761
|
+
this.geometry = new SplineGeometry(points, this.getColor(), this.thickness, this.detail);
|
|
925
762
|
}
|
|
926
763
|
setInterpolateStart(start, t = 0, f) {
|
|
927
764
|
const diff = start - this.interpolateStart;
|
|
928
765
|
return transitionValues((p) => {
|
|
929
766
|
this.interpolateStart += diff * p;
|
|
767
|
+
this.geometry.updateInterpolationStart(this.interpolateStart);
|
|
930
768
|
this.vertexCache.updated();
|
|
931
769
|
}, () => {
|
|
932
770
|
this.interpolateStart = start;
|
|
771
|
+
this.geometry.updateInterpolationStart(this.interpolateStart);
|
|
933
772
|
this.vertexCache.updated();
|
|
934
773
|
}, t, f);
|
|
935
774
|
}
|
|
@@ -937,9 +776,11 @@ export class Spline2d extends SimulationElement {
|
|
|
937
776
|
const diff = limit - this.interpolateLimit;
|
|
938
777
|
return transitionValues((p) => {
|
|
939
778
|
this.interpolateLimit += diff * p;
|
|
779
|
+
this.geometry.updateInterpolationLimit(this.interpolateLimit);
|
|
940
780
|
this.vertexCache.updated();
|
|
941
781
|
}, () => {
|
|
942
782
|
this.interpolateLimit = limit;
|
|
783
|
+
this.geometry.updateInterpolationLimit(this.interpolateLimit);
|
|
943
784
|
this.vertexCache.updated();
|
|
944
785
|
}, t, f);
|
|
945
786
|
}
|
|
@@ -955,66 +796,7 @@ export class Spline2d extends SimulationElement {
|
|
|
955
796
|
const [vec] = this.interpolateSlope(t);
|
|
956
797
|
return vec;
|
|
957
798
|
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
const screenSize = camera.getScreenSize();
|
|
961
|
-
let verticesTop = [];
|
|
962
|
-
const verticesBottom = [];
|
|
963
|
-
let currentDistance = 0;
|
|
964
|
-
let interpolationStarted = false;
|
|
965
|
-
outer: for (let i = 0; i < this.curves.length; i++) {
|
|
966
|
-
const detail = this.curves[i].getDetail() || this.detail;
|
|
967
|
-
const step = 1 / detail;
|
|
968
|
-
const distanceRatio = currentDistance / this.distance;
|
|
969
|
-
if (distanceRatio > this.interpolateLimit)
|
|
970
|
-
break;
|
|
971
|
-
const curveLength = this.curves[i].getLength();
|
|
972
|
-
currentDistance += curveLength;
|
|
973
|
-
const sectionRatio = curveLength / this.distance;
|
|
974
|
-
for (let j = 0; j < detail + 1; j++) {
|
|
975
|
-
let currentInterpolation = step * j;
|
|
976
|
-
let atLimit = false;
|
|
977
|
-
if (step * j * sectionRatio + distanceRatio > this.interpolateLimit) {
|
|
978
|
-
atLimit = true;
|
|
979
|
-
currentInterpolation = (this.interpolateLimit - distanceRatio) / sectionRatio;
|
|
980
|
-
}
|
|
981
|
-
if (distanceRatio + currentInterpolation / this.curves.length < this.interpolateStart) {
|
|
982
|
-
continue;
|
|
983
|
-
}
|
|
984
|
-
if (!interpolationStarted) {
|
|
985
|
-
interpolationStarted = true;
|
|
986
|
-
currentInterpolation = (this.interpolateStart - distanceRatio) / sectionRatio;
|
|
987
|
-
j--;
|
|
988
|
-
}
|
|
989
|
-
const [point, slope] = this.curves[i].interpolateSlope(currentInterpolation);
|
|
990
|
-
const pos = this.getPos();
|
|
991
|
-
point[0] += pos[0];
|
|
992
|
-
point[1] += screenSize[1] - pos[1];
|
|
993
|
-
const normal = vector2(-slope[1], slope[0]);
|
|
994
|
-
vec2.normalize(normal, normal);
|
|
995
|
-
vec2.scale(normal, this.thickness / 2, normal);
|
|
996
|
-
const colors = this.curves[i].getColors().map((c) => (c ? c : this.getColor()));
|
|
997
|
-
const vertexColor = interpolateColors(colors, currentInterpolation);
|
|
998
|
-
const vertTop = vertex(point[0] + normal[0], point[1] + normal[1], 0, vertexColor);
|
|
999
|
-
verticesTop.push(vertTop);
|
|
1000
|
-
const vertBottom = vertex(point[0] - normal[0], point[1] - normal[1], 0, vertexColor);
|
|
1001
|
-
verticesBottom.unshift(vertBottom);
|
|
1002
|
-
if (atLimit) {
|
|
1003
|
-
break outer;
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
verticesTop = verticesTop.concat(verticesBottom);
|
|
1008
|
-
let resBuffer = [];
|
|
1009
|
-
lossyTriangulate(verticesTop)
|
|
1010
|
-
.flat()
|
|
1011
|
-
.forEach((vert) => {
|
|
1012
|
-
const pos = vert.getPos();
|
|
1013
|
-
resBuffer = resBuffer.concat(vertexBuffer(pos[0], pos[1], 0, vert.getColor() || this.getColor()));
|
|
1014
|
-
});
|
|
1015
|
-
this.vertexCache.setCache(resBuffer);
|
|
1016
|
-
return resBuffer;
|
|
1017
|
-
}
|
|
1018
|
-
return this.vertexCache.getCache();
|
|
799
|
+
updateMatrix(camera) {
|
|
800
|
+
this.defaultUpdateMatrix(camera);
|
|
1019
801
|
}
|
|
1020
802
|
}
|