simulationjsv2 0.6.0 → 0.7.2

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/graphics.js CHANGED
@@ -1,35 +1,85 @@
1
1
  import { vec3, mat4, vec2, vec4 } from 'wgpu-matrix';
2
- import { Vertex, cloneBuf, color, colorFromVector4, vector2, vector3, vertex, Color, transitionValues, vector2FromVector3, matrix4, vector3FromVector2, distance2d } from './utils.js';
3
- import { BlankGeometry, CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry } from './geometry.js';
4
- import { VertexCache, bufferGenerator, logger, rotateMat4, vector3ToPixelRatio } from './internalUtils.js';
5
- import { modelProjMatOffset } from './constants.js';
6
- export class SimulationElement {
2
+ import { Vertex, cloneBuf, color, colorFromVector4, vector2, vector3, vertex, Color, vector2FromVector3, matrix4, vector3FromVector2, distance2d } from './utils.js';
3
+ import { BlankGeometry, CircleGeometry, CubeGeometry, Line2dGeometry, Line3dGeometry, PlaneGeometry, PolygonGeometry, Spline2dGeometry, SquareGeometry, TraceLines2dGeometry as TraceLinesGeometry } from './geometry.js';
4
+ import { SimSceneObjInfo, VertexCache, bufferGenerator, globalInfo, internalTransitionValues, logger, posTo2dScreen, vector3ToPixelRatio } from './internalUtils.js';
5
+ import { mat4ByteLength, modelProjMatOffset } from './constants.js';
6
+ export class SimulationElement3d {
7
+ children;
8
+ uniformBuffer;
9
+ parent;
10
+ centerOffset;
11
+ rotationOffset;
7
12
  pos;
8
13
  color;
9
14
  wireframe;
10
15
  vertexCache;
11
16
  rotation;
12
17
  modelMatrix;
13
- uniformBuffer;
14
- isInstanced;
18
+ isInstance = false;
19
+ isInstanced = false;
20
+ is3d = true;
21
+ isEmpty = false;
15
22
  /**
16
23
  * @param pos - Expected to be adjusted to devicePixelRatio before reaching constructor
17
24
  */
18
25
  constructor(pos, rotation, color = new Color()) {
19
26
  this.pos = pos;
27
+ this.centerOffset = vector3();
28
+ // TODO test this
29
+ this.rotationOffset = vector3();
20
30
  this.color = color;
21
31
  this.vertexCache = new VertexCache();
22
32
  this.wireframe = false;
23
- this.isInstanced = false;
24
- this.rotation = rotation;
33
+ this.rotation = cloneBuf(rotation);
25
34
  this.uniformBuffer = null;
35
+ this.children = [];
26
36
  this.modelMatrix = matrix4();
37
+ this.parent = null;
38
+ }
39
+ add(el, id) {
40
+ el.setParent(this);
41
+ const info = new SimSceneObjInfo(el, id);
42
+ this.children.push(info);
43
+ }
44
+ remove(el) {
45
+ for (let i = 0; i < this.children.length; i++) {
46
+ if (this.children[i].getObj() === el) {
47
+ this.children.splice(i, 1);
48
+ }
49
+ }
50
+ }
51
+ getChildren() {
52
+ return this.children.map((child) => child.getObj());
53
+ }
54
+ getChildrenInfos() {
55
+ return this.children;
56
+ }
57
+ hasChildren() {
58
+ return this.children.length > 0;
27
59
  }
28
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
29
- getModelMatrix(_) {
60
+ setParent(parent) {
61
+ this.parent = parent;
62
+ }
63
+ getParent() {
64
+ return this.parent;
65
+ }
66
+ setCenterOffset(offset) {
67
+ this.centerOffset = offset;
68
+ }
69
+ setRotationOffset(offset) {
70
+ this.rotationOffset = offset;
71
+ }
72
+ resetCenterOffset() {
73
+ this.centerOffset[0] = 0;
74
+ this.centerOffset[1] = 0;
75
+ this.centerOffset[2] = 0;
76
+ }
77
+ getModelMatrix() {
78
+ this.updateModelMatrix3d();
30
79
  return this.modelMatrix;
31
80
  }
32
- getUniformBuffer(device, mat) {
81
+ getUniformBuffer(mat) {
82
+ const device = globalInfo.errorGetDevice();
33
83
  if (!this.uniformBuffer) {
34
84
  const uniformBufferSize = 4 * 16 + 4 * 16 + 4 * 2 + 8; // 4x4 matrix + 4x4 matrix + vec2<f32> + 8 bc 144 is cool
35
85
  this.uniformBuffer = device.createBuffer({
@@ -40,12 +90,53 @@ export class SimulationElement {
40
90
  device.queue.writeBuffer(this.uniformBuffer, modelProjMatOffset, mat);
41
91
  return this.uniformBuffer;
42
92
  }
93
+ mirrorParentTransforms3d(mat) {
94
+ if (!this.parent)
95
+ return;
96
+ this.parent.mirrorParentTransforms3d(mat);
97
+ mat4.translate(mat, this.parent.getPos(), mat);
98
+ const parentRot = this.parent.getRotation();
99
+ mat4.rotateZ(mat, parentRot[2], mat);
100
+ mat4.rotateY(mat, parentRot[1], mat);
101
+ mat4.rotateX(mat, parentRot[0], mat);
102
+ }
43
103
  updateModelMatrix3d() {
44
104
  mat4.identity(this.modelMatrix);
105
+ if (this.parent) {
106
+ this.mirrorParentTransforms3d(this.modelMatrix);
107
+ }
45
108
  mat4.translate(this.modelMatrix, this.pos, this.modelMatrix);
109
+ // vec3.negate(this.rotationOffset, cachedVec1);
110
+ // mat4.translate(this.modelMatrix, cachedVec1, this.modelMatrix);
46
111
  mat4.rotateZ(this.modelMatrix, this.rotation[2], this.modelMatrix);
47
112
  mat4.rotateY(this.modelMatrix, this.rotation[1], this.modelMatrix);
48
113
  mat4.rotateX(this.modelMatrix, this.rotation[0], this.modelMatrix);
114
+ // mat4.translate(this.modelMatrix, this.rotationOffset, this.modelMatrix);
115
+ mat4.translate(this.modelMatrix, this.centerOffset, this.modelMatrix);
116
+ }
117
+ mirrorParentTransforms2d(mat) {
118
+ if (!this.parent) {
119
+ const parentPos = posTo2dScreen(this.pos);
120
+ mat4.translate(mat, parentPos, mat);
121
+ return;
122
+ }
123
+ this.parent.mirrorParentTransforms2d(mat);
124
+ const parentRot = this.parent.getRotation();
125
+ mat4.rotateZ(mat, parentRot[2], mat);
126
+ mat4.translate(mat, this.pos, mat);
127
+ }
128
+ updateModelMatrix2d() {
129
+ mat4.identity(this.modelMatrix);
130
+ const pos = posTo2dScreen(this.pos);
131
+ vec3.add(pos, this.centerOffset, pos);
132
+ if (this.parent) {
133
+ this.mirrorParentTransforms2d(this.modelMatrix);
134
+ }
135
+ else {
136
+ mat4.translate(this.modelMatrix, pos, this.modelMatrix);
137
+ }
138
+ mat4.rotateZ(this.modelMatrix, this.rotation[2], this.modelMatrix);
139
+ mat4.translate(this.modelMatrix, this.centerOffset, this.modelMatrix);
49
140
  }
50
141
  getGeometryType() {
51
142
  return this.geometry.getType();
@@ -62,13 +153,22 @@ export class SimulationElement {
62
153
  getPos() {
63
154
  return this.pos;
64
155
  }
156
+ getAbsolutePos() {
157
+ const vec = vector3();
158
+ this.updateModelMatrix3d();
159
+ mat4.getTranslation(this.modelMatrix, vec);
160
+ return vec;
161
+ }
65
162
  getRotation() {
66
163
  return this.rotation;
67
164
  }
165
+ getCenterOffset() {
166
+ return this.centerOffset;
167
+ }
68
168
  fill(newColor, t = 0, f) {
69
169
  const diff = newColor.diff(this.color);
70
170
  const finalColor = newColor.clone();
71
- return transitionValues((p) => {
171
+ return internalTransitionValues((p) => {
72
172
  this.color.r += diff.r * p;
73
173
  this.color.g += diff.g * p;
74
174
  this.color.b += diff.b * p;
@@ -79,76 +179,92 @@ export class SimulationElement {
79
179
  this.vertexCache.updated();
80
180
  }, t, f);
81
181
  }
82
- move(amount, t = 0, f) {
182
+ moveChildren(amount, t = 0, f) {
183
+ for (let i = 0; i < this.children.length; i++) {
184
+ this.children[i].getObj().move(amount, t, f, true);
185
+ }
186
+ }
187
+ move(amount, t = 0, f, fromDevicePixelRatio = false) {
83
188
  const tempAmount = cloneBuf(amount);
84
- vector3ToPixelRatio(tempAmount);
189
+ if (!fromDevicePixelRatio)
190
+ vector3ToPixelRatio(tempAmount);
85
191
  const finalPos = cloneBuf(this.pos);
86
192
  vec3.add(finalPos, tempAmount, finalPos);
87
- return transitionValues((p) => {
193
+ this.moveChildren(amount, t, f);
194
+ return internalTransitionValues((p) => {
88
195
  this.pos[0] += tempAmount[0] * p;
89
196
  this.pos[1] += tempAmount[1] * p;
90
197
  this.pos[2] += tempAmount[2] * p;
91
- this.updateModelMatrix3d();
92
198
  }, () => {
93
199
  this.pos = finalPos;
94
- this.updateModelMatrix3d();
95
200
  }, t, f);
96
201
  }
97
- moveTo(pos, t = 0, f) {
202
+ moveTo(pos, t = 0, f, fromDevicePixelRatio = false) {
98
203
  const tempPos = cloneBuf(pos);
99
- vector3ToPixelRatio(tempPos);
204
+ if (!fromDevicePixelRatio)
205
+ vector3ToPixelRatio(tempPos);
100
206
  const diff = vector3();
101
207
  vec3.sub(tempPos, this.pos, diff);
102
- return transitionValues((p) => {
208
+ this.moveChildren(diff, t, f);
209
+ return internalTransitionValues((p) => {
103
210
  this.pos[0] += diff[0] * p;
104
211
  this.pos[1] += diff[1] * p;
105
212
  this.pos[2] += diff[2] * p;
106
- this.updateModelMatrix3d();
107
213
  }, () => {
108
214
  this.pos = tempPos;
109
- this.updateModelMatrix3d();
110
215
  }, t, f);
111
216
  }
217
+ rotateChildrenTo(angle) {
218
+ for (let i = 0; i < this.children.length; i++) {
219
+ this.children[i].getObj().rotateTo(angle);
220
+ }
221
+ }
222
+ rotateChildren(angle) {
223
+ for (let i = 0; i < this.children.length; i++) {
224
+ this.children[i].getObj().rotate(angle);
225
+ }
226
+ }
112
227
  rotate(amount, t = 0, f) {
113
- const tempAmount = cloneBuf(amount);
114
228
  const finalRotation = cloneBuf(amount);
115
229
  vec3.add(finalRotation, this.rotation, finalRotation);
116
- return transitionValues((p) => {
117
- this.rotation[0] += tempAmount[0] * p;
118
- this.rotation[1] += tempAmount[1] * p;
119
- this.rotation[2] += tempAmount[2] * p;
120
- this.updateModelMatrix3d();
230
+ const tempDiff = vector3();
231
+ return internalTransitionValues((p) => {
232
+ vec3.scale(amount, p, tempDiff);
233
+ this.rotation[0] += tempDiff[0];
234
+ this.rotation[1] += tempDiff[1];
235
+ this.rotation[2] += tempDiff[2];
121
236
  }, () => {
122
237
  this.rotation = finalRotation;
123
- this.updateModelMatrix3d();
124
238
  }, t, f);
125
239
  }
126
240
  rotateTo(rot, t = 0, f) {
127
241
  const diff = vec3.sub(rot, this.rotation);
128
- return transitionValues((p) => {
129
- this.rotation[0] += diff[0] * p;
130
- this.rotation[1] += diff[1] * p;
131
- this.rotation[2] += diff[2] * p;
132
- this.updateModelMatrix3d();
242
+ const tempDiff = vector3();
243
+ return internalTransitionValues((p) => {
244
+ vec3.scale(diff, p, tempDiff);
245
+ this.rotation[0] += tempDiff[0];
246
+ this.rotation[1] += tempDiff[1];
247
+ this.rotation[2] += tempDiff[2];
133
248
  }, () => {
134
249
  this.rotation = cloneBuf(rot);
135
- this.updateModelMatrix3d();
136
250
  }, t, f);
137
251
  }
138
252
  getVertexCount() {
139
253
  if (this.vertexCache.shouldUpdate()) {
140
254
  this.geometry.recompute();
141
255
  }
256
+ let childrenVertices = 0;
257
+ for (let i = 0; i < this.children.length; i++) {
258
+ childrenVertices += this.children[i].getObj().getVertexCount();
259
+ }
260
+ let currentVertices = 0;
142
261
  if (this.isWireframe()) {
143
- return this.geometry.getWireframeVertexCount();
262
+ currentVertices = this.geometry.getWireframeVertexCount();
144
263
  }
145
- return this.geometry.getTriangleVertexCount();
146
- }
147
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
148
- defaultUpdateMatrix(_) {
149
- const matrix = matrix4();
150
- mat4.translate(matrix, this.pos, matrix);
151
- rotateMat4(matrix, this.rotation);
264
+ else {
265
+ currentVertices = this.geometry.getTriangleVertexCount();
266
+ }
267
+ return currentVertices + childrenVertices;
152
268
  }
153
269
  getBuffer(vertexParamGenerator) {
154
270
  if (this.vertexCache.shouldUpdate()) {
@@ -170,18 +286,20 @@ export class SimulationElement {
170
286
  return this.vertexCache.getCache();
171
287
  }
172
288
  }
173
- export class SimulationElement3d extends SimulationElement {
174
- pos;
175
- rotation;
176
- is3d = true;
177
- constructor(pos, rotation = vector3(), color) {
178
- super(pos, rotation, color);
179
- this.pos = pos;
180
- vector3ToPixelRatio(this.pos);
181
- this.rotation = rotation;
289
+ export class EmptyElement extends SimulationElement3d {
290
+ geometry = new BlankGeometry();
291
+ label;
292
+ isEmpty = true;
293
+ constructor(label) {
294
+ super(vector3(), vector3());
295
+ this.label = label || null;
296
+ }
297
+ getLabel() {
298
+ return this.label;
182
299
  }
183
300
  }
184
- export class SimulationElement2d extends SimulationElement {
301
+ export class SimulationElement2d extends SimulationElement3d {
302
+ is3d = false;
185
303
  constructor(pos, rotation = vector3(), color) {
186
304
  super(vector3FromVector2(pos), rotation, color);
187
305
  vector3ToPixelRatio(this.pos);
@@ -192,15 +310,8 @@ export class SimulationElement2d extends SimulationElement {
192
310
  rotateTo2d(rot, t = 0, f) {
193
311
  return super.rotateTo(vector3(0, 0, rot), t, f);
194
312
  }
195
- updateModelMatrix2d(camera) {
196
- mat4.identity(this.modelMatrix);
197
- const pos = cloneBuf(this.pos);
198
- pos[1] = camera.getScreenSize()[1] + pos[1];
199
- mat4.translate(this.modelMatrix, pos, this.modelMatrix);
200
- mat4.rotateZ(this.modelMatrix, this.rotation[2], this.modelMatrix);
201
- }
202
- getModelMatrix(camera) {
203
- this.updateModelMatrix2d(camera);
313
+ getModelMatrix() {
314
+ super.updateModelMatrix2d();
204
315
  return this.modelMatrix;
205
316
  }
206
317
  }
@@ -270,7 +381,7 @@ export class Square extends SimulationElement2d {
270
381
  diffMap[+key] = clone;
271
382
  }
272
383
  });
273
- return transitionValues((p) => {
384
+ return internalTransitionValues((p) => {
274
385
  Object.entries(diffMap).forEach(([key, value]) => {
275
386
  const color = this.vertexColors[+key];
276
387
  color.r += value.r * p;
@@ -290,7 +401,7 @@ export class Square extends SimulationElement2d {
290
401
  scaleWidth(amount, t = 0, f) {
291
402
  const finalWidth = this.width * amount;
292
403
  const diffWidth = finalWidth - this.width;
293
- return transitionValues((p) => {
404
+ return internalTransitionValues((p) => {
294
405
  this.width += diffWidth * p;
295
406
  this.geometry.setWidth(this.width);
296
407
  this.vertexCache.updated();
@@ -303,7 +414,7 @@ export class Square extends SimulationElement2d {
303
414
  scaleHeight(amount, t = 0, f) {
304
415
  const finalHeight = this.height * amount;
305
416
  const diffHeight = finalHeight - this.height;
306
- return transitionValues((p) => {
417
+ return internalTransitionValues((p) => {
307
418
  this.height += diffHeight * p;
308
419
  this.geometry.setHeight(this.height);
309
420
  this.vertexCache.updated();
@@ -318,7 +429,7 @@ export class Square extends SimulationElement2d {
318
429
  const finalHeight = this.height * amount;
319
430
  const diffWidth = finalWidth - this.width;
320
431
  const diffHeight = finalHeight - this.height;
321
- return transitionValues((p) => {
432
+ return internalTransitionValues((p) => {
322
433
  this.width += diffWidth * p;
323
434
  this.height += diffHeight * p;
324
435
  this.geometry.setWidth(this.width);
@@ -335,7 +446,7 @@ export class Square extends SimulationElement2d {
335
446
  setWidth(num, t = 0, f) {
336
447
  num *= devicePixelRatio;
337
448
  const diffWidth = num - this.width;
338
- return transitionValues((p) => {
449
+ return internalTransitionValues((p) => {
339
450
  this.width += diffWidth * p;
340
451
  this.geometry.setWidth(this.width);
341
452
  this.vertexCache.updated();
@@ -348,7 +459,7 @@ export class Square extends SimulationElement2d {
348
459
  setHeight(num, t = 0, f) {
349
460
  num *= devicePixelRatio;
350
461
  const diffHeight = num - this.height;
351
- return transitionValues((p) => {
462
+ return internalTransitionValues((p) => {
352
463
  this.height += diffHeight * p;
353
464
  this.geometry.setHeight(this.height);
354
465
  this.vertexCache.updated();
@@ -372,7 +483,7 @@ export class Circle extends SimulationElement2d {
372
483
  setRadius(num, t = 0, f) {
373
484
  num *= devicePixelRatio;
374
485
  const diff = num - this.radius;
375
- return transitionValues((p) => {
486
+ return internalTransitionValues((p) => {
376
487
  this.radius += diff * p;
377
488
  this.geometry.setRadius(this.radius);
378
489
  this.vertexCache.updated();
@@ -385,7 +496,7 @@ export class Circle extends SimulationElement2d {
385
496
  scale(amount, t = 0, f) {
386
497
  const finalRadius = this.radius * amount;
387
498
  const diff = finalRadius - this.radius;
388
- return transitionValues((p) => {
499
+ return internalTransitionValues((p) => {
389
500
  this.radius += diff * p;
390
501
  this.geometry.setRadius(this.radius);
391
502
  this.vertexCache.updated();
@@ -411,14 +522,13 @@ export class Polygon extends SimulationElement2d {
411
522
  const vertices = newVertices.map((vert) => {
412
523
  const newVertex = vert.clone();
413
524
  newVertex.setZ(0);
414
- newVertex.setIs3d(false);
415
525
  return newVertex;
416
526
  });
417
- const lastVert = this.vertices.length > 0 ? this.vertices[this.vertices.length - 1] : vertex(0, 0, 0, color(), false);
527
+ const lastVert = this.vertices.length > 0 ? this.vertices[this.vertices.length - 1] : vertex(0, 0, 0, color());
418
528
  if (vertices.length > this.vertices.length) {
419
529
  while (vertices.length > this.vertices.length) {
420
530
  const lastPos = lastVert.getPos();
421
- this.vertices.push(new Vertex(lastPos[0], lastPos[1], 0, lastVert.getColor() || this.color, false));
531
+ this.vertices.push(new Vertex(lastPos[0], lastPos[1], 0, lastVert.getColor() || this.color));
422
532
  }
423
533
  }
424
534
  const initialPositions = this.vertices.map((p) => cloneBuf(p.getPos()));
@@ -449,7 +559,7 @@ export class Polygon extends SimulationElement2d {
449
559
  })
450
560
  : [])
451
561
  ];
452
- return transitionValues((p) => {
562
+ return internalTransitionValues((p) => {
453
563
  this.vertices.forEach((vert, i) => {
454
564
  const posChange = cloneBuf(posChanges[i]);
455
565
  const colorChange = cloneBuf(colorChanges[i]);
@@ -493,7 +603,7 @@ export class Line3d extends SimulationElement3d {
493
603
  setEnd(pos, t = 0, f) {
494
604
  const diff = vector3();
495
605
  vec3.sub(pos, this.to, diff);
496
- return transitionValues((p) => {
606
+ return internalTransitionValues((p) => {
497
607
  this.to[0] += diff[0] * p;
498
608
  this.to[1] += diff[1] * p;
499
609
  this.to[2] += diff[2] * p;
@@ -526,7 +636,7 @@ export class Line2d extends SimulationElement2d {
526
636
  // vec2.sub(tempPos, this.getPos(), tempPos);
527
637
  const diff = vector3();
528
638
  vec2.sub(tempPos, this.to, diff);
529
- return transitionValues((p) => {
639
+ return internalTransitionValues((p) => {
530
640
  this.to[0] += diff[0] * p;
531
641
  this.to[1] += diff[1] * p;
532
642
  this.vertexCache.updated();
@@ -542,18 +652,18 @@ export class Cube extends SimulationElement3d {
542
652
  width;
543
653
  height;
544
654
  depth;
545
- constructor(pos, width, height, depth, color, rotation) {
655
+ constructor(pos, width, height, depth, color, rotation = vector3()) {
546
656
  super(pos, rotation, color);
547
- this.width = width * devicePixelRatio;
548
- this.height = height * devicePixelRatio;
549
- this.depth = depth * devicePixelRatio;
657
+ this.width = width;
658
+ this.height = height;
659
+ this.depth = depth;
550
660
  this.rotation = rotation || vector3();
551
661
  this.geometry = new CubeGeometry(this.width, this.height, this.depth);
552
662
  }
553
663
  setWidth(width, t = 0, f) {
554
664
  width *= devicePixelRatio;
555
665
  const diff = width - this.width;
556
- return transitionValues((p) => {
666
+ return internalTransitionValues((p) => {
557
667
  this.width += diff * p;
558
668
  this.geometry.setWidth(this.width);
559
669
  this.vertexCache.updated();
@@ -566,7 +676,7 @@ export class Cube extends SimulationElement3d {
566
676
  setHeight(height, t = 0, f) {
567
677
  height *= devicePixelRatio;
568
678
  const diff = height - this.width;
569
- return transitionValues((p) => {
679
+ return internalTransitionValues((p) => {
570
680
  this.height += diff * p;
571
681
  this.geometry.setHeight(this.height);
572
682
  this.vertexCache.updated();
@@ -579,7 +689,7 @@ export class Cube extends SimulationElement3d {
579
689
  setDepth(depth, t = 0, f) {
580
690
  depth *= devicePixelRatio;
581
691
  const diff = depth - this.width;
582
- return transitionValues((p) => {
692
+ return internalTransitionValues((p) => {
583
693
  this.depth += diff * p;
584
694
  this.geometry.setDepth(this.depth);
585
695
  this.vertexCache.updated();
@@ -596,7 +706,7 @@ export class Cube extends SimulationElement3d {
596
706
  const widthDiff = finalWidth - this.width;
597
707
  const heightDiff = finalHeight - this.height;
598
708
  const depthDiff = finalDepth - this.depth;
599
- return transitionValues((p) => {
709
+ return internalTransitionValues((p) => {
600
710
  this.width += widthDiff * p;
601
711
  this.height += heightDiff * p;
602
712
  this.depth += depthDiff * p;
@@ -786,7 +896,7 @@ export class Spline2d extends SimulationElement2d {
786
896
  }
787
897
  setInterpolateStart(start, t = 0, f) {
788
898
  const diff = start - this.interpolateStart;
789
- return transitionValues((p) => {
899
+ return internalTransitionValues((p) => {
790
900
  this.interpolateStart += diff * p;
791
901
  this.geometry.updateInterpolationStart(this.interpolateStart);
792
902
  this.vertexCache.updated();
@@ -798,7 +908,7 @@ export class Spline2d extends SimulationElement2d {
798
908
  }
799
909
  setInterpolateLimit(limit, t = 0, f) {
800
910
  const diff = limit - this.interpolateLimit;
801
- return transitionValues((p) => {
911
+ return internalTransitionValues((p) => {
802
912
  this.interpolateLimit += diff * p;
803
913
  this.geometry.updateInterpolationLimit(this.interpolateLimit);
804
914
  this.vertexCache.updated();
@@ -827,7 +937,7 @@ export class Spline2d extends SimulationElement2d {
827
937
  setThickness(thickness, t = 0, f) {
828
938
  thickness *= devicePixelRatio;
829
939
  const diff = thickness - this.thickness;
830
- return transitionValues((p) => {
940
+ return internalTransitionValues((p) => {
831
941
  this.thickness += diff * p;
832
942
  this.geometry.updateThickness(this.thickness);
833
943
  this.vertexCache.updated();
@@ -867,24 +977,20 @@ export class Instance extends SimulationElement3d {
867
977
  obj;
868
978
  instanceMatrix;
869
979
  matrixBuffer;
870
- device;
871
980
  baseMat;
981
+ maxInstances;
982
+ isInstance = true;
872
983
  constructor(obj, numInstances) {
873
- super(vector3());
874
- this.device = null;
984
+ super(vector3(), vector3());
985
+ // 32 matrices
986
+ this.maxInstances = 32;
875
987
  this.matrixBuffer = null;
876
988
  obj.isInstanced = true;
877
989
  this.obj = obj;
878
990
  this.instanceMatrix = [];
879
- this.is3d = Boolean(obj.is3d);
991
+ this.is3d = obj.is3d;
880
992
  this.geometry = new BlankGeometry();
881
993
  this.baseMat = matrix4();
882
- if (typeof obj.getRotation() === 'number') {
883
- mat4.rotateZ(this.baseMat, obj.getRotation(), this.baseMat);
884
- }
885
- else {
886
- rotateMat4(this.baseMat, obj.getRotation());
887
- }
888
994
  for (let i = 0; i < numInstances; i++) {
889
995
  const clone = cloneBuf(this.baseMat);
890
996
  this.instanceMatrix.push(clone);
@@ -893,6 +999,10 @@ export class Instance extends SimulationElement3d {
893
999
  setNumInstances(numInstances) {
894
1000
  if (numInstances < 0)
895
1001
  throw logger.error('Num instances is less than 0');
1002
+ if (numInstances > this.maxInstances) {
1003
+ this.maxInstances = numInstances;
1004
+ this.allocBuffer(numInstances);
1005
+ }
896
1006
  const oldLen = this.instanceMatrix.length;
897
1007
  if (numInstances < oldLen) {
898
1008
  const diff = oldLen - numInstances;
@@ -915,11 +1025,27 @@ export class Instance extends SimulationElement3d {
915
1025
  return;
916
1026
  this.instanceMatrix[instance] = transformation;
917
1027
  }
1028
+ allocBuffer(size) {
1029
+ const device = globalInfo.getDevice();
1030
+ if (!device)
1031
+ return;
1032
+ const byteSize = size * mat4ByteLength;
1033
+ this.matrixBuffer = device.createBuffer({
1034
+ size: byteSize,
1035
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
1036
+ });
1037
+ }
918
1038
  mapBuffer() {
919
- if (!this.device || this.matrixBuffer === null)
1039
+ const device = globalInfo.getDevice();
1040
+ if (!device)
920
1041
  return;
1042
+ if (!this.matrixBuffer) {
1043
+ const minSize = this.maxInstances * mat4ByteLength;
1044
+ const size = Math.max(minSize, this.instanceMatrix.length);
1045
+ this.allocBuffer(size);
1046
+ }
921
1047
  const buf = new Float32Array(this.instanceMatrix.map((mat) => [...mat]).flat());
922
- this.device.queue.writeBuffer(this.matrixBuffer, 0, buf.buffer, buf.byteOffset, buf.byteLength);
1048
+ device.queue.writeBuffer(this.matrixBuffer, 0, buf.buffer, buf.byteOffset, buf.byteLength);
923
1049
  this.matrixBuffer.unmap();
924
1050
  }
925
1051
  getInstances() {
@@ -928,15 +1054,7 @@ export class Instance extends SimulationElement3d {
928
1054
  getNumInstances() {
929
1055
  return this.instanceMatrix.length;
930
1056
  }
931
- getMatrixBuffer(device) {
932
- if (!this.matrixBuffer) {
933
- const minSize = 640;
934
- const size = Math.max(minSize, this.instanceMatrix[0].byteLength * this.instanceMatrix.length);
935
- this.matrixBuffer = device.createBuffer({
936
- size,
937
- usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
938
- });
939
- }
1057
+ getMatrixBuffer() {
940
1058
  this.mapBuffer();
941
1059
  return this.matrixBuffer;
942
1060
  }
@@ -949,4 +1067,43 @@ export class Instance extends SimulationElement3d {
949
1067
  getBuffer() {
950
1068
  return this.obj.getBuffer();
951
1069
  }
1070
+ getModelMatrix() {
1071
+ return this.obj.getModelMatrix();
1072
+ }
1073
+ }
1074
+ export class TraceLines2d extends SimulationElement2d {
1075
+ geometry;
1076
+ constructor(color, maxLen) {
1077
+ super(vector2(), vector3(), color);
1078
+ this.geometry = new TraceLinesGeometry(maxLen);
1079
+ }
1080
+ addPoint(point, color) {
1081
+ const vert = vertex(point[0], point[1], point?.[2] || 0, color);
1082
+ this.geometry.addVertex(vert);
1083
+ this.vertexCache.updated();
1084
+ }
1085
+ // always being wireframe means that triangleOrder
1086
+ // in in the geometry does not need to be a duplicate
1087
+ // of wireframeOrder
1088
+ isWireframe() {
1089
+ return true;
1090
+ }
1091
+ }
1092
+ export class TraceLines3d extends SimulationElement3d {
1093
+ geometry;
1094
+ constructor(color, maxLen) {
1095
+ super(vector3(), vector3(), color);
1096
+ this.geometry = new TraceLinesGeometry(maxLen);
1097
+ }
1098
+ addPoint(point, color) {
1099
+ const vert = vertex(point[0], point[1], point?.[2] || 0, color);
1100
+ this.geometry.addVertex(vert);
1101
+ this.vertexCache.updated();
1102
+ }
1103
+ // always being wireframe means that triangleOrder
1104
+ // in in the geometry does not need to be a duplicate
1105
+ // of wireframeOrder
1106
+ isWireframe() {
1107
+ return true;
1108
+ }
952
1109
  }